From a3c8bcdca7fe35a075798bd555dbcbd8698439fb Mon Sep 17 00:00:00 2001 From: clyang82 Date: Thu, 23 May 2024 23:30:23 +0800 Subject: [PATCH 1/3] Support UpdateStrategy and DeleteOption Signed-off-by: clyang82 --- README.md | 6 ++ data/generated/openapi/openapi.go | 4 +- openapi/openapi.yaml | 8 ++ pkg/api/openapi/api/openapi.yaml | 10 ++ pkg/api/openapi/docs/Resource.md | 52 +++++++++++ pkg/api/openapi/docs/ResourceAllOf.md | 52 +++++++++++ pkg/api/openapi/docs/ResourcePatchRequest.md | 52 +++++++++++ pkg/api/openapi/model_resource.go | 92 +++++++++++++++++-- pkg/api/openapi/model_resource_all_of.go | 86 +++++++++++++++-- .../openapi/model_resource_patch_request.go | 76 ++++++++++++++- pkg/api/presenters/resource.go | 6 +- pkg/api/resource_types.go | 44 +++++++-- pkg/api/resource_types_test.go | 37 +++++--- pkg/handlers/resource.go | 2 +- test/factories.go | 2 +- 15 files changed, 480 insertions(+), 49 deletions(-) diff --git a/README.md b/README.md index 5518043c..5660f9b9 100755 --- a/README.md +++ b/README.md @@ -173,6 +173,12 @@ ocm post /api/maestro/v1/resources << EOF } } } + }, + "update_strategy": { + "type": "Orphan" + }, + "delete_option": { + "propagationPolicy": "CreateOnly" } } EOF diff --git a/data/generated/openapi/openapi.go b/data/generated/openapi/openapi.go index 4aec3434..97c79a55 100755 --- a/data/generated/openapi/openapi.go +++ b/data/generated/openapi/openapi.go @@ -77,7 +77,7 @@ func (fi bindataFileInfo) Sys() interface{} { return nil } -var _openapiYaml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\x5c\x5f\x8f\xdb\xb8\x11\x7f\xf7\xa7\x18\xa0\x2d\x7c\x39\x78\x6d\xa7\x77\x05\x5a\x23\x39\x20\xb9\x5e\x8a\x3b\xe4\x92\x34\x9b\xb4\x0f\x45\xb1\x4b\x93\x23\x8b\xb7\x12\xa9\x90\xd4\xee\x3a\x6d\xbf\x7b\x41\x52\xff\x2d\x69\x65\x63\x37\x56\x16\xbe\x97\x5b\x51\xc3\xe1\x0c\xf9\x9b\x9f\x86\x1c\x3a\x32\x41\x41\x12\xbe\x82\xef\xe6\xcb\xf9\x72\xc2\x45\x20\x57\x13\x00\xc3\x4d\x84\x2b\x88\x09\x6a\xa3\x24\x9c\xa3\xba\xe6\x14\xe1\xc5\xbb\x9f\x27\x00\x0c\x35\x55\x3c\x31\x5c\x8a\x2e\x91\x6b\x54\xda\xbd\x5e\xce\x97\xf3\xa7\x13\x8d\xca\xb6\x58\xcd\x67\x90\xaa\x68\x05\xa1\x31\xc9\x6a\xb1\x88\x24\x25\x51\x28\xb5\x59\xfd\x79\xb9\x5c\x4e\x00\x1a\xda\x69\xaa\x14\x0a\x03\x4c\xc6\x84\x8b\x7a\x77\xbd\x5a\x2c\x48\xc2\xe7\xd6\x05\x1d\xf2\xc0\xcc\xa9\x8c\x77\x55\xfc\x4a\xb8\x80\x6f\x12\x25\x59\x4a\x6d\xcb\x13\xf0\xd6\xb4\x2b\xd3\x86\x6c\xf0\x2e\x95\xe7\x86\x6c\xb8\xd8\xe4\x8a\x12\x62\x42\xe7\x9b\xd5\xb0\xc8\x26\x64\x71\xfd\x74\xa1\x50\xcb\x54\x51\x74\x2f\x01\x36\x68\xfc\x1f\x00\x3a\x8d\x63\xa2\xb6\x2b\x78\x8f\x26\x55\x42\x03\x81\x88\x6b\x03\x32\x80\xa2\x53\x2e\x8a\x34\x55\xdc\x6c\xf3\xae\xd6\xec\x97\x48\x14\xaa\x15\xfc\xeb\xdf\x59\xa3\x42\x9d\x48\xa1\xf3\x91\xec\x7f\xd3\x3f\x2e\x97\xd3\xf2\xb1\xe1\xc2\x0b\xf8\xe5\xfc\xed\x1b\x20\x4a\x91\x6d\x75\x54\x90\xeb\xdf\x90\x1a\x5d\xe9\x47\xa5\x30\x28\x4c\x55\x15\x00\x49\x92\x88\x53\x62\x95\x2d\x7e\xd3\x52\xd4\xdf\x02\x68\x1a\x62\x4c\x9a\xad\x00\xbf\x57\x18\xac\x60\xfa\xbb\x05\x95\x71\x22\x05\x0a\xa3\x17\x5e\x56\x2f\xde\x67\x36\xbc\xe6\xda\x4c\x4b\x3f\xbe\x5f\x3e\xed\xf1\x23\x35\x21\x18\x79\x85\x02\xb8\x06\x2e\xae\x49\xc4\xd9\x31\x8c\xff\x49\x29\xa9\x6a\x56\x7f\xd7\x6d\xf5\x47\x41\x52\x13\x4a\xc5\x3f\x23\x03\x23\x21\x41\x15\x48\x15\x83\x4c\x50\x39\xb3\xc6\xe0\xc1\x9f\xfa\xf0\xf3\x51\xe0\x6d\x82\xd4\x20\x03\xb4\xfd\x40\x52\x17\xab\xc7\x9f\xfb\x84\x28\x12\xa3\xc9\xe8\x06\x5c\xbc\xb4\x75\x2e\xe5\x16\x09\xd9\xe0\x74\xa8\xb0\xe6\x9f\xf7\x10\x46\xa2\x68\x38\x58\x5c\x2a\x86\xea\xe5\x76\xb0\x7c\xc0\x31\x62\xda\x8b\x27\x96\x45\x9b\xf4\xf2\xa3\x42\x62\x10\x08\x08\xbc\x29\x62\x7c\x3f\x62\xf9\x94\xa2\x36\x2f\x25\xab\xc8\xd5\x90\x90\x47\x2d\x30\x62\x48\x21\x62\xfb\x71\x85\x6c\x05\x46\xa5\x38\xe9\x81\x44\x3f\x20\xda\xe1\x30\x84\x45\xa6\xbd\xd4\xd8\x43\x29\x7e\xce\x8e\x02\xe4\xa6\xed\x8e\x47\x7a\xa2\xf0\x1f\x96\xed\x9c\x09\x3e\x0a\xf5\x78\xc2\xf0\x44\xdc\x47\xf4\xe0\x2f\xdd\x1e\x14\xe1\x4a\x22\x85\x84\x6d\x01\x6f\xb9\x3e\xce\xf7\x7e\xaf\x0f\xce\x0b\x01\x69\xd7\x37\x07\xa8\x0d\x59\x9b\x91\x99\x10\x9b\x34\x77\x1c\x97\x3a\x53\xc1\xc5\x7f\x38\xfb\x5f\x77\x3e\xf8\x37\x34\x40\x44\x99\x8e\xad\xb7\x50\x84\xc5\xc3\x64\x82\x05\x20\x02\x99\x0a\x56\x1b\xf0\x8b\x4e\x5d\x2b\xf7\x9d\x08\xe4\x38\x1e\x7c\xdf\xed\xc1\x1b\x59\xa2\xf3\x86\x9b\x10\x74\x82\x94\x07\x1c\x19\x70\xf6\xb5\xb0\xc9\x58\xd3\xd7\x84\x18\x1a\xee\x90\xc2\xc7\x84\xb9\x2c\x4e\x3c\x50\x0a\xe7\xf5\xb3\x72\x5d\x47\x96\xca\xbd\xb3\xb3\xf2\xde\xbb\xd1\x9f\xd6\x0d\xe1\xb9\x34\xf3\x56\xa7\x94\xa2\xd6\x41\x1a\x45\xdb\xd1\x10\xde\x29\xd9\xfb\xc2\x56\x9f\xb8\x7a\x14\x4e\x3c\xc2\x8c\x75\xe7\x1b\xe3\x88\xc7\x66\xa9\xa3\xc8\x50\xad\xb5\x11\x1a\xdc\xf9\xda\xfc\xd5\x35\x03\x39\xf0\x63\xd3\x46\xcb\x3d\x10\x2d\x8f\x0f\xdc\xb0\x1d\xb4\x7c\x62\xc6\x2f\x6f\xf5\x89\x19\x47\xe0\xc4\x7e\x0c\xe3\x62\x68\x44\x0c\xd3\x3c\x8b\xbd\xf3\x40\x93\xb3\xb6\xcd\x33\x95\x42\xa7\x71\xa1\x65\x58\x1d\xa5\xe8\xf4\xa0\xbb\xe7\x66\x1d\x25\x1f\xf5\x98\x75\x94\x1f\x33\x1b\x4e\x75\x94\x51\xf0\xd0\x57\xb9\x11\x6d\xab\xa3\xec\x59\x49\xd9\xb3\x96\xb2\x77\x35\x65\xff\x7a\xca\xbd\x57\x54\xf2\x68\xbf\xdf\xed\x78\x1e\xbf\x63\xd9\x86\xe7\xf6\x7c\x8d\x15\x95\xa6\xed\xa7\x54\xf2\x44\xe1\x87\x78\xd0\xb3\x3f\x2d\xc2\xf5\x2b\xdb\x9f\x0e\xaf\xa8\x34\x68\xee\x38\x2e\x75\x26\x85\xc3\x2a\x2a\x45\x62\xf6\xf0\x15\x95\x02\x10\x47\xae\xa8\xb4\x72\xdf\x89\x40\xc6\xb8\x17\x2d\xd0\xf9\x78\xf6\xa2\x23\xf9\x6e\xde\x55\x51\x79\x98\x14\x2e\xaf\xa8\xd0\x91\xa6\x72\xf7\x52\x51\x29\x78\x6e\x2c\x15\x95\x53\xb2\x37\x06\xab\x4f\x5c\x3d\x0a\x27\x1e\x61\xc6\xda\x5d\x51\x19\x45\x86\x7a\x77\x45\xe5\xb0\x8f\xcd\x9e\x15\x95\xf2\xf8\xe0\x54\x51\x39\x31\xe3\xfd\x7a\xf0\x08\x98\xf1\xc0\x8a\xca\x48\x18\xe6\x80\xdb\xed\x9c\x4d\x27\xe5\x1b\xdb\x2d\xe7\x9d\x73\xab\x3f\x27\x96\x8c\x78\x32\xad\x66\x9b\xa0\xff\x65\xcc\xa4\x62\x37\xae\x60\xed\xc4\xb2\x46\xff\xf0\x4a\xaa\x98\x98\x15\xfc\xf2\xcf\x0f\x93\xdc\xc1\x4c\xe9\x5b\x57\x05\x79\x8f\x01\x2a\x14\x14\xeb\xda\x7d\x89\x24\x6b\x4a\x94\x85\xba\xe1\x55\x9e\xe3\xac\x3a\x4f\xbe\x93\x36\x8a\x8b\x4d\xd1\x7c\xc5\xc5\xdd\x42\xa1\x9d\xa0\x3e\xa1\xd7\xbc\x3c\xe9\x1d\x68\xdb\xa0\x81\x13\xb2\xc1\x5d\x21\x2e\x0c\x6e\x2a\x48\xd2\xfc\xf3\x00\x29\x23\x0d\x89\xee\x12\x2b\x76\x16\x95\x2f\x8a\xb5\xb4\xf2\x68\x6d\xaa\x3c\xda\xc1\x2b\x8f\x6e\x94\xca\x33\x37\x18\xfb\xb0\x75\x20\xcc\xf5\x92\x28\x7a\x1b\xf4\x23\x30\x07\x6f\x03\x02\xe5\x6f\x1b\x5a\x26\xba\x7d\xaa\x6d\xa4\x31\xac\x87\x4c\xeb\x74\x5b\xff\xc9\x4e\xcc\x75\x88\x16\xcc\x7a\x51\x87\x59\x4b\x07\xe7\x7a\x15\x23\x7b\xb8\x5f\x2d\xc2\xed\xe5\xb3\x9b\xf9\x36\xc3\x5c\xad\xb1\xd6\xde\x22\x3a\x98\x50\xf2\xfb\x17\x47\x5a\x59\x41\xe2\x61\x2b\x9b\xf3\xef\xc5\xe0\x1e\xf9\x6f\x10\x5b\x64\x9b\xb1\x05\xfe\xbc\x13\xd9\x05\x31\x83\x74\x03\x04\x19\xe9\xd9\x9d\xef\x99\xe1\x71\xb5\xd4\x9e\xed\x87\xef\x47\x59\x4c\x04\x0f\x50\xb7\xaa\x6a\x4c\x31\x80\x36\xc4\xa4\xad\xa8\xa9\x88\x56\x7f\x67\xf7\x58\x10\x5d\xbf\x4c\xd9\x76\x71\x74\x4f\x7e\x6f\x41\x4f\x3b\x76\xda\xd6\x67\x67\x8c\x3c\x27\x6f\x9d\xee\x03\xe3\xac\x73\xf6\xbb\xe6\xbf\x2d\xda\x7a\x40\x19\x91\x35\x46\x3b\x8b\xd0\x31\xa2\x73\x8a\x31\x6e\x09\x95\x44\xef\x3a\xc6\xef\x1d\xaf\x2b\x04\x7b\xba\xf4\x47\x4e\x77\x20\x1e\xa0\xb2\x7a\xa9\xe2\xa0\x55\xac\xdf\xc6\xd8\x7b\xe9\x5a\x23\xa2\x2b\x7c\x3a\xc4\xf7\x39\x3d\x6b\x3b\x29\xdc\x33\x84\x76\x01\xd4\xe1\xf3\xdd\xc0\x69\x2c\x57\x33\x0b\x2e\xbf\xe0\x0e\xe1\x65\xbd\x85\x8b\x15\x24\xc4\x84\xd9\x63\x2d\xd7\xff\x10\xa2\xdd\x99\xb8\x1f\x3f\x53\xa9\x58\x33\x85\xaa\x1e\xce\x36\xb3\xf6\x1d\xf8\x54\x33\x3d\x6f\x43\x25\xcf\xb2\x56\x7c\x4a\x51\x6d\xdb\xcc\x78\x47\x36\x08\x22\x8d\xd7\xa8\x4a\x5b\xfc\x2d\xa6\x9b\x10\x45\xad\x01\x6f\x29\x22\xd3\x95\xad\x95\x1d\xa5\x9a\xc3\xb5\x1b\xda\xe4\x2c\x86\x01\x49\x23\xb3\x82\xa7\x25\x8d\x71\xc1\xe3\x34\x2e\x9b\xca\x79\x08\x48\xa4\xbd\xfe\x6a\xa6\xea\xbd\xac\x0c\xdd\xeb\xe5\xaf\xe4\xd6\xaa\xdf\x71\x54\xdb\xcd\xae\x72\x97\xb7\x0e\xf4\x20\xfb\x67\x03\x6a\x3e\x2c\xfb\x7c\x70\x97\x48\x1a\x5e\xb8\xb6\x0e\x3f\xda\x94\x34\xbc\xfb\xef\x59\x61\xc3\x79\xb6\x34\xda\x55\x4e\xbd\x62\xa0\x8a\x1b\x54\x9c\xcc\x1d\xe8\xf4\x56\x18\x72\x6b\xe7\xc0\x84\x5c\x97\x60\x06\x5e\x6e\x90\x35\x8f\x79\x44\x94\x9d\x1d\xd3\xe8\x82\x70\x71\x13\xa2\xc2\x0b\xa0\x11\x49\x35\xda\x56\x22\xe0\xfc\xef\xaf\xdd\xe7\x1f\x63\x14\x66\x56\x28\x4a\x75\x5e\xc5\xb5\xae\xea\x5c\x85\xdd\x9a\x02\x31\x46\xf1\x75\x6a\x50\xc3\x02\xa8\x8c\xd2\x58\xd4\xa5\x08\xa5\x32\x15\x66\x0e\x85\xba\x57\x52\x01\xde\x92\x38\x89\x70\x06\x5c\x80\xbb\x61\x93\xad\xa1\xe2\x78\x8d\x96\x14\xab\x7d\xb5\x3f\x0c\x20\x90\x6a\x54\x56\x79\xe9\xa2\x21\xca\x6d\xad\x9d\xc0\x65\xbc\xbd\x5c\x4d\x8a\x97\x97\x97\x97\xfa\x53\x54\xf1\xc2\x77\x86\x88\x5f\x21\x4c\xe3\xed\x1f\xa6\x55\xd1\xb2\xdf\x87\xdd\x49\x07\x4a\x04\x90\x48\x4b\x58\xa3\xdf\x9e\x23\x03\x69\x03\x2b\xaa\xfd\xea\x65\x7e\x80\x93\x3a\x5d\x17\x30\xd0\x9e\xf0\xd0\x55\x7c\x2f\x03\x29\x9f\xaf\x89\xba\x9c\x75\xfa\x54\xed\x7b\xe1\xb9\x72\x7e\x85\x5b\x78\x0e\xd3\x40\xca\x29\x10\xc1\x5a\x65\xae\x49\x94\xa2\x95\x5a\x13\xd5\x31\x0b\x3f\xfb\xe5\xab\x22\x4b\x4c\x8d\x25\xe9\x6b\xce\x90\xcd\x40\x2a\xe0\x5e\xc6\x6b\xe3\x1a\x30\x4e\xcc\x76\x66\xdb\xca\xb3\xa6\x9d\xb5\x34\x21\x31\xae\xc5\x2e\x08\x84\x44\x43\x82\x2a\xe6\xda\xa6\x4a\x76\x82\x34\x22\xdc\xf0\x28\x82\x75\xb9\xce\x3e\xba\x91\xcd\x87\x72\x69\x76\x6b\xab\x1e\xa2\x59\xe3\x03\xc4\xa8\x5f\xdd\xf5\xf6\xde\xa3\x34\x57\x3c\x2c\x50\xd7\xa9\xd9\x3b\x58\x1b\x61\xba\x27\x80\x8b\x55\x75\xaf\x3d\x6e\xf3\x40\x1b\x10\x8a\x44\xd3\x76\xf4\xbd\x55\x87\x8d\x09\x17\x44\xb0\x0b\x08\xb8\xd2\x06\x86\x1b\x31\xf3\x3d\xde\xf4\xda\x74\x5f\x11\x21\x24\xe0\x6d\x12\x71\xca\x8d\x77\xc1\x13\x98\x43\x7c\x4e\x2e\x83\x81\xee\x2f\x1b\xd6\x71\xee\xdb\xee\x07\xe6\xa9\xb3\x47\xbb\xc2\x43\x1c\x93\x33\x8d\xd6\x7f\xcb\x79\xf9\x25\x69\x3f\x9a\x5d\xa5\x35\xee\x04\x2a\xc0\x2b\xff\x5a\x06\x96\x88\xce\xb4\x51\x29\x35\xa9\xb2\x1a\x85\x4b\x9c\x5c\xe6\xa9\xed\x6a\xc0\xb3\xe2\xed\x0f\xf3\x67\x4e\xed\x0f\x20\xa4\x71\x27\x2c\xa5\xc2\x67\xda\xe4\x42\xdf\x42\x8c\x44\x68\x87\x0a\x27\xef\x14\x42\xa1\xa6\xe8\xf3\x93\x07\xf2\xca\xa3\x9a\xd0\x10\xce\x2b\xac\x68\x6d\xdf\xa0\x01\xce\x66\xee\x9c\x6f\x06\x49\x44\xc4\x37\x9c\x39\x1b\xaf\xb8\x60\x4f\xdc\x5f\x9e\x3c\xe1\x9b\x62\x38\xfd\xa4\x86\xae\xe2\x6f\x49\x63\xa7\xb0\x4e\xed\x67\x67\x25\x74\x7c\xf7\xe7\x9c\xcd\xdc\x80\x76\xbc\x39\x67\xfe\xff\x76\xc0\x59\x46\xd4\xdf\xd6\x7b\xa1\xa1\xe1\x6b\xf7\xe6\x79\xad\xec\x5f\x0e\xde\x0b\x98\xff\x07\x00\x00\xff\xff\x08\x8d\x91\xbe\xaa\x49\x00\x00") +var _openapiYaml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\x5c\x5f\x8f\xdb\xb8\x11\x7f\xf7\xa7\x18\xa0\x2d\x7c\x39\x78\x6d\xa7\x77\x05\x5a\x23\x39\x20\xb9\x5e\x8a\x3b\xe4\x92\x34\x9b\xb4\x0f\x45\xe1\xa5\xc9\x91\xc5\x8b\x44\x2a\x24\xb5\x59\xa7\xed\x77\x2f\x48\xea\xbf\x25\xad\x6c\xec\xc6\xca\xc2\x79\x89\x45\xcd\x0c\x67\xc8\x99\x1f\x87\x1c\x6a\x65\x82\x82\x24\x7c\x05\xdf\xcd\x97\xf3\xe5\x84\x8b\x40\xae\x26\x00\x86\x9b\x08\x57\x10\x13\xd4\x46\x49\xb8\x44\x75\xcd\x29\xc2\xb3\x37\x3f\x4f\x00\x18\x6a\xaa\x78\x62\xb8\x14\x5d\x24\xd7\xa8\xb4\x7b\xbd\x9c\x2f\xe7\x8f\x27\x1a\x95\x6d\xb1\x92\x2f\x20\x55\xd1\x0a\x42\x63\x92\xd5\x62\x11\x49\x4a\xa2\x50\x6a\xb3\xfa\xf3\x72\xb9\x9c\x00\x34\xa4\xd3\x54\x29\x14\x06\x98\x8c\x09\x17\x75\x76\xbd\x5a\x2c\x48\xc2\xe7\xd6\x04\x1d\xf2\xc0\xcc\xa9\x8c\xf7\x45\xfc\x4a\xb8\x80\x6f\x12\x25\x59\x4a\x6d\xcb\x23\xf0\xda\xb4\x0b\xd3\x86\x6c\xf1\x36\x91\x97\x86\x6c\xb9\xd8\xe6\x82\x12\x62\x42\x67\x9b\x95\xb0\xc8\x06\x64\x71\xfd\x78\xa1\x50\xcb\x54\x51\x74\x2f\x01\xb6\x68\xfc\x0f\x00\x9d\xc6\x31\x51\xbb\x15\xbc\x45\x93\x2a\xa1\x81\x40\xc4\xb5\x01\x19\x40\xc1\x94\x93\x22\x4d\x15\x37\xbb\x9c\xd5\xaa\xfd\x1c\x89\x42\xb5\x82\x7f\xfd\x3b\x6b\x54\xa8\x13\x29\x74\xde\x93\xfd\x37\xfd\xe3\x72\x39\x2d\x1f\x1b\x26\x3c\x83\x5f\x2e\x5f\xbf\x02\xa2\x14\xd9\x55\x7b\x05\xb9\xf9\x0d\xa9\xd1\x15\x3e\x2a\x85\x41\x61\xaa\xa2\x00\x48\x92\x44\x9c\x12\x2b\x6c\xf1\x9b\x96\xa2\xfe\x16\x40\xd3\x10\x63\xd2\x6c\x05\xf8\xbd\xc2\x60\x05\xd3\xdf\x2d\xa8\x8c\x13\x29\x50\x18\xbd\xf0\xb4\x7a\xf1\x36\xd3\xe1\x25\xd7\x66\x5a\xda\xf1\xfd\xf2\x71\x8f\x1d\xa9\x09\xc1\xc8\x0f\x28\x80\x6b\xe0\xe2\x9a\x44\x9c\x9d\x42\xf9\x9f\x94\x92\xaa\xa6\xf5\x77\xdd\x5a\xbf\x17\x24\x35\xa1\x54\xfc\x33\x32\x30\x12\x12\x54\x81\x54\x31\xc8\x04\x95\x53\x6b\x0c\x16\xfc\xa9\xcf\x7f\xde\x0b\xbc\x49\x90\x1a\x64\x80\x96\x0f\x24\x75\xb1\x7a\xfa\xb1\x4f\x88\x22\x31\x9a\x0c\x6e\xc0\xc5\x4b\x1b\x73\x49\xb7\x48\xc8\x16\xa7\x43\x89\x35\xff\x7c\x00\x31\x12\x45\xc3\xc1\xe4\x52\x31\x54\xcf\x77\x83\xe9\x03\x8e\x11\xd3\x9e\x3c\xb1\x28\xda\x84\x97\x1f\x15\x12\x83\x40\x40\xe0\xa7\x22\xc6\x0f\x03\x96\x8f\x29\x6a\xf3\x5c\xb2\x0a\x5d\xcd\x13\xf2\xa8\x05\x46\x0c\x29\x48\x2c\x1f\x57\xc8\x56\x60\x54\x8a\x93\x1e\x97\xe8\x77\x88\x76\x77\x18\x82\x22\xd3\x5e\x68\xec\x81\x14\x3f\x66\x27\x71\xe4\xa6\xee\x0e\x47\x7a\xa2\xf0\x1f\x16\xed\x9c\x0a\x3e\x0a\xf5\x78\xc2\xf0\x0c\xdc\x27\xb4\xe0\x2f\xdd\x16\x14\xe1\x4a\x22\x85\x84\xed\x00\x6f\xb8\x3e\xcd\x7a\x7f\xd0\x82\xf3\x4c\x40\xda\xb5\xe6\x00\xb5\x21\x6b\x33\x32\x13\x62\x13\xe6\x4e\x63\x52\x67\x2a\xb8\xf8\x0f\x67\xff\xeb\xce\x07\xff\x86\x06\x88\x28\xd3\xb1\xcd\x0e\x8a\xb0\xb8\x9f\x4c\xb0\x70\x88\x40\xa6\x82\xd5\x3a\xfc\xa2\x43\xd7\x8a\x7d\x67\x00\x39\x8d\x05\xdf\x77\x5b\xf0\x4a\x96\xde\xf9\x89\x9b\x10\x74\x82\x94\x07\x1c\x19\x70\xf6\xb5\xa0\xc9\x58\xd3\xd7\x84\x18\x1a\xee\x81\xc2\xfb\x84\xb9\x2c\x4e\xdc\x53\x0a\xe7\xe5\xb3\x72\x5e\x47\x96\xca\xbd\xb1\xa3\xf2\xd6\x9b\xd1\x9f\xd6\x0d\xc1\xb9\x34\xb3\x56\xa7\x94\xa2\xd6\x41\x1a\x45\xbb\xd1\x00\xde\x39\xd9\xfb\xc2\x5a\x9f\xb1\x7a\x14\x46\x3c\xc0\x8c\x75\x6f\x8d\x71\xc0\x63\xb3\xd4\x51\x64\xa8\x56\xdb\x08\x0d\xee\xad\x36\x7f\x75\xcd\x40\x8e\x5c\x6c\xda\x60\xb9\xc7\x45\xcb\xe3\x03\xd7\x6d\x07\x2c\x9f\x91\xf1\xcb\x6b\x7d\x46\xc6\x11\x18\x71\x18\xc2\xb8\x18\x1a\x11\xc2\x34\xcf\x62\x6f\x3d\xd0\xe4\xac\x6d\xf3\x4c\xa5\xd0\x69\x5c\x48\x19\x56\x47\x29\x98\xee\x75\xf7\xdc\xac\xa3\xe4\xbd\x9e\xb2\x8e\xf2\x63\xa6\xc3\xb9\x8e\x32\x0a\x1c\xfa\x2a\x37\xa2\x6d\x75\x94\x03\x2b\x29\x07\xd6\x52\x0e\xae\xa6\x1c\x5e\x4f\xb9\xf3\x8a\x4a\x1e\xed\x77\xbb\x1d\xcf\xe3\x77\x2c\xdb\xf0\x5c\x9f\xaf\xb1\xa2\xd2\xd4\xfd\x9c\x4a\x9e\x21\xfc\x18\x0b\x7a\xf6\xa7\x45\xb8\x7e\x65\xfb\xd3\xe1\x15\x95\x06\xcc\x9d\xc6\xa4\xce\xa4\x70\x58\x45\xa5\x48\xcc\xee\xbf\xa2\x52\x38\xc4\x89\x2b\x2a\xad\xd8\x77\x06\x90\x31\xee\x45\x0b\xef\x7c\x38\x7b\xd1\x91\xac\x9b\xb7\x55\x54\xee\x27\x85\xcb\x2b\x2a\x74\xa4\xa9\xdc\x9d\x54\x54\x0a\x9c\x1b\x4b\x45\xe5\x9c\xec\x8d\x41\xeb\x33\x56\x8f\xc2\x88\x07\x98\xb1\x76\x57\x54\x46\x91\xa1\xde\x5e\x51\x39\x6e\xb1\x39\xb0\xa2\x52\x1e\x1f\x9c\x2b\x2a\x67\x64\xbc\x5b\x0b\x1e\x00\x32\x1e\x59\x51\x19\x09\xc2\x1c\x71\xbb\x9d\xb3\xe9\xa4\x7c\x63\xd9\x72\xdc\xb9\xb4\xf2\x73\x60\xc9\x80\x27\x93\x6a\x76\x09\xfa\x2f\x63\x26\x15\xbd\x71\x05\x1b\x47\x96\x35\xfa\x87\x17\x52\xc5\xc4\xac\xe0\x97\x7f\xbe\x9b\xe4\x06\x66\x42\x5f\xbb\x2a\xc8\x5b\x0c\x50\xa1\xa0\x58\x97\xee\x4b\x24\x59\x53\xa2\xac\xab\x1b\x5e\xc5\x39\xce\xaa\xe3\xe4\x99\xb4\x51\x5c\x6c\x8b\xe6\x0f\x5c\xdc\x4e\x14\xda\x01\xea\x23\x7a\xc9\xcb\x93\xde\x81\xba\x0d\xea\x38\x21\x5b\xdc\x27\xe2\xc2\xe0\xb6\xe2\x49\x9a\x7f\x1e\x40\x65\xa4\x21\xd1\x6d\x64\xc5\xce\xa2\xb2\xa2\x58\x4d\x2b\x8f\x56\xa7\xca\xa3\xed\xbc\xf2\xe8\x7a\xa9\x3c\x73\x83\xb1\x0f\x5b\xe7\x84\xb9\x5c\x12\x45\xaf\x83\x7e\x0f\xcc\x9d\xb7\xe1\x02\xe5\xb7\x0d\x2d\x03\xdd\x3e\xd4\x36\xd2\x18\xd6\x43\xa6\x75\xb8\xad\xfd\x64\x2f\xe6\x3a\x48\x0b\x64\x5d\xd7\xdd\xac\x85\xc1\x99\x5e\xf5\x91\x03\xcc\xaf\x16\xe1\x0e\xb2\xd9\x8d\x7c\x9b\x62\xae\xd6\x58\x6b\x6f\x21\x1d\x0c\x28\xf9\xfd\x8b\x13\xcd\xac\x20\xf1\xb0\x99\xcd\xf1\x77\x3d\x98\x23\xff\x06\xb1\x85\xb6\x19\x5b\xe0\xcf\x3b\x91\xad\x89\x19\x24\x1b\x20\xc8\x40\xcf\xee\x7c\x2f\x0c\x8f\xab\xa5\xf6\x6c\x3f\x7c\x37\xc2\x62\x22\x78\x80\xba\x55\x54\x63\x88\xf3\x04\x74\x2d\xfd\x72\x36\x84\xc3\xeb\xba\xd6\x46\x11\x83\xdb\xdd\x20\x1e\x6d\x88\x49\x5b\x7d\xb3\x42\x5a\xfd\x9a\xef\xa1\xc4\x4d\xfd\xca\x66\xdb\xf5\xd4\x03\x57\x91\x16\x1f\x6d\xf7\xd0\x36\x2f\x68\x1d\x94\x4e\x0f\x68\xa5\xee\x99\xfd\x3d\xfa\x7c\x5f\xd1\x3a\x99\x47\x62\x45\xe7\xdc\x76\xcd\x6e\x1b\x62\xf4\x04\x56\x44\x36\x18\xed\x4d\x71\x47\x8f\xce\x28\xc6\xb8\x1d\x39\x12\xbd\xe9\xe8\xbf\xb7\xbf\x2e\x18\xe9\x61\xe9\x8f\xfe\x6e\x30\x39\x42\x64\xf5\x62\xc8\x51\xb3\x58\xbf\x51\x72\xf0\xd4\xb5\xc6\x5b\x57\x70\x76\x90\x1f\x72\x02\xd8\x76\xda\x79\x60\x80\xee\x3b\x50\x87\xcd\xb7\x3b\x4e\x63\xba\x9a\x99\x7c\x99\x85\x38\x0f\x2f\x6b\x46\x5c\xac\x20\x21\x26\xcc\x1e\x6b\xfb\x95\x77\x21\xda\xdd\x95\xfb\x80\x9b\x4a\xc5\x9a\x69\x60\xf5\x80\xb9\xb9\xf3\xd8\x73\x9f\x6a\xb6\xea\x75\xa8\xe4\x8a\x56\x8b\x8f\x29\xaa\x5d\x9b\x1a\x6f\xc8\x16\x41\xa4\xf1\x06\x55\xa9\x8b\xbf\x89\xf5\x29\x44\x51\x6b\xc0\x1b\x8a\xc8\x74\x65\x7b\x68\x7b\xa9\xe6\xa1\xed\x8a\x36\x11\x91\x61\x40\xd2\xc8\xac\xe0\x71\x09\x92\x5c\xf0\x38\x8d\xcb\xa6\x72\x1c\x02\x12\x69\x2f\xbf\x9a\x6d\x7b\x2b\x2b\x5d\xf7\x5a\xf9\x2b\xb9\xb1\xe2\xf7\x0c\xd5\x76\xc3\xae\xdc\x05\xb4\x23\x2d\xc8\xfe\xf4\x41\xcd\x86\x65\x9f\x0d\xee\x22\x4c\xc3\x0a\xd7\xd6\x61\x47\x9b\x90\x86\x75\xff\xbd\x28\x74\xb8\xcc\xa6\x46\xbb\xea\xaf\x17\x0c\x54\x71\x83\x8a\x93\xb9\x73\x3a\xbd\x13\x86\xdc\xd8\x31\x30\x21\xd7\xa5\x33\x03\x2f\x37\xf9\x9a\xc7\x3c\x22\xca\x8e\x8e\x69\xb0\x20\xac\x3f\x85\xa8\x70\x0d\x34\x22\xa9\x46\xdb\x4a\x04\x5c\xfe\xfd\xa5\x4b\x2e\x30\x46\x61\x66\xe5\x2a\xa5\xf3\x4a\xb4\x35\x55\xe7\x22\xec\xf6\x1a\x88\x31\x8a\x6f\x52\x83\x1a\x16\x40\x65\x94\xc6\xa2\x4e\x45\x28\x95\xa9\x30\x73\x28\xc4\xbd\x90\x0a\xf0\x86\xc4\x49\x84\x33\xe0\x02\xdc\x2d\xa1\x6c\x0e\x15\xc7\x6b\xb4\xa0\x58\xe5\xd5\xfe\x40\x83\x40\xaa\x51\x59\xe1\xa5\x89\x86\x28\x77\x3c\xe0\x08\xae\xe2\xdd\xd5\x6a\x52\xbc\xbc\xba\xba\xd2\x1f\xa3\x8a\x15\x9e\x19\x22\xfe\x01\x61\x1a\xef\xfe\x30\xad\x92\x96\x7c\xef\xf6\x07\x1d\x28\x11\x40\x22\x2d\x61\x83\xfe\x88\x01\x19\x48\x1b\x58\x51\xed\xcb\x9d\xf9\x11\x46\xea\x74\x53\xb8\x81\xf6\x80\x87\xae\x6a\x7d\x15\x48\xf9\x74\x43\xd4\xd5\xac\xd3\xa6\x2a\xef\xda\x63\xe5\xfc\x03\xee\xe0\x29\x4c\x03\x29\xa7\x40\x04\x6b\xa5\xb9\x26\x51\x8a\x96\x6a\x43\x54\xc7\x28\xfc\xec\xa7\xaf\xea\x59\x62\x6a\x2c\x48\x5f\x73\x86\x6c\x06\x52\x01\xf7\x34\x5e\x1a\xd7\x80\x71\x62\x76\x33\xdb\x56\x9e\x97\xed\xcd\xa5\x09\x89\x71\x2d\x76\x42\x20\x24\x1a\x12\x54\x31\xd7\x36\x11\xb3\x03\xa4\x11\xe1\x13\x8f\x22\xd8\x94\xf3\xec\xa3\x1b\xd9\x7c\x28\x96\x66\x37\xcf\xea\x21\x9a\x35\xde\x43\x8c\xfa\xd9\xdd\xec\xee\x3c\x4a\x73\xc1\xc3\x02\x75\x93\x9a\x83\x83\xb5\x11\xa6\x07\x3a\x70\x31\xab\xee\xb5\xf7\xdb\x3c\xd0\x06\x84\x22\xd1\xb4\xdd\xfb\x5e\xab\xe3\xfa\x84\x35\x11\x6c\x0d\x01\x57\xda\xc0\x70\x25\x66\x9e\xe3\x55\xaf\x4e\x77\x15\x11\x42\x02\xde\x24\x11\xa7\xdc\x78\x13\x3c\x80\x39\x8f\xcf\xc1\x65\xb0\xa3\xfb\x0b\x93\x75\x3f\xf7\x6d\x77\xe3\xe6\xa9\xd3\x47\xbb\xe2\x49\x1c\x93\x0b\x8d\xd6\x7e\x8b\x79\xf9\x45\x6f\xdf\x9b\x9d\xa5\x0d\xee\x05\x2a\xc0\x0b\xff\x5a\x06\x16\x88\x2e\xb4\x51\x29\x35\xa9\xb2\x12\x85\x4b\x9c\x5c\xe6\xa9\xed\x6c\xc0\x93\xe2\xed\x0f\xf3\x27\x4e\xec\x0f\x20\xa4\x71\xa7\x44\xa5\xc0\x27\xda\xe4\x44\xdf\x42\x8c\x44\x68\xe7\x15\x8e\xde\x09\x84\x42\x4c\xc1\xf3\x93\x77\xe4\x95\xf7\x6a\x42\x43\xb8\xac\xa0\xa2\xd5\x7d\x8b\x06\x38\x9b\xb9\xb3\xca\x19\x24\x11\x11\xdf\x70\xe6\x74\xfc\xc0\x05\x7b\xe4\x7e\x79\xf0\x84\x6f\x8a\xee\xf4\xa3\x9a\x77\x15\xbf\x25\x8d\x9d\xc0\x3a\xb4\x5f\x5c\x94\xae\xe3\xd9\x9f\x72\x36\x73\x1d\xda\xfe\xe6\x9c\xf9\xff\x6d\x87\xb3\x0c\xa8\xbf\xad\x73\xa1\xa1\xe1\x4b\xf7\xe6\x69\xed\xea\x42\xd9\x79\xaf\xc3\xfc\x3f\x00\x00\xff\xff\xe3\xa8\xf9\x43\x6e\x4a\x00\x00") func openapiYamlBytes() ([]byte, error) { return bindataRead( @@ -92,7 +92,7 @@ func openapiYaml() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "openapi.yaml", size: 18858, mode: os.FileMode(493), modTime: time.Unix(1713249971, 0)} + info := bindataFileInfo{name: "openapi.yaml", size: 19054, mode: os.FileMode(493), modTime: time.Unix(1716477375, 0)} a := &asset{bytes: bytes, info: info} return a, nil } diff --git a/openapi/openapi.yaml b/openapi/openapi.yaml index ac1fca7f..68509b21 100755 --- a/openapi/openapi.yaml +++ b/openapi/openapi.yaml @@ -509,6 +509,10 @@ components: format: date-time manifest: type: object + delete_option: + type: object + update_strategy: + type: object status: type: object ResourceList: @@ -527,6 +531,10 @@ components: type: integer manifest: type: object + delete_option: + type: object + update_strategy: + type: object Consumer: allOf: - $ref: '#/components/schemas/ObjectReference' diff --git a/pkg/api/openapi/api/openapi.yaml b/pkg/api/openapi/api/openapi.yaml index 1cd83608..903bc260 100644 --- a/pkg/api/openapi/api/openapi.yaml +++ b/pkg/api/openapi/api/openapi.yaml @@ -774,6 +774,8 @@ components: - $ref: '#/components/schemas/ResourceList_allOf' ResourcePatchRequest: example: + delete_option: "{}" + update_strategy: "{}" manifest: "{}" version: 0 properties: @@ -781,6 +783,10 @@ components: type: integer manifest: type: object + delete_option: + type: object + update_strategy: + type: object type: object Consumer: allOf: @@ -834,6 +840,10 @@ components: type: string manifest: type: object + delete_option: + type: object + update_strategy: + type: object status: type: object type: object diff --git a/pkg/api/openapi/docs/Resource.md b/pkg/api/openapi/docs/Resource.md index 86c3aa1f..0736ecc4 100644 --- a/pkg/api/openapi/docs/Resource.md +++ b/pkg/api/openapi/docs/Resource.md @@ -13,6 +13,8 @@ Name | Type | Description | Notes **CreatedAt** | Pointer to **time.Time** | | [optional] **UpdatedAt** | Pointer to **time.Time** | | [optional] **Manifest** | Pointer to **map[string]interface{}** | | [optional] +**DeleteOption** | Pointer to **map[string]interface{}** | | [optional] +**UpdateStrategy** | Pointer to **map[string]interface{}** | | [optional] **Status** | Pointer to **map[string]interface{}** | | [optional] ## Methods @@ -259,6 +261,56 @@ SetManifest sets Manifest field to given value. HasManifest returns a boolean if a field has been set. +### GetDeleteOption + +`func (o *Resource) GetDeleteOption() map[string]interface{}` + +GetDeleteOption returns the DeleteOption field if non-nil, zero value otherwise. + +### GetDeleteOptionOk + +`func (o *Resource) GetDeleteOptionOk() (*map[string]interface{}, bool)` + +GetDeleteOptionOk returns a tuple with the DeleteOption field if it's non-nil, zero value otherwise +and a boolean to check if the value has been set. + +### SetDeleteOption + +`func (o *Resource) SetDeleteOption(v map[string]interface{})` + +SetDeleteOption sets DeleteOption field to given value. + +### HasDeleteOption + +`func (o *Resource) HasDeleteOption() bool` + +HasDeleteOption returns a boolean if a field has been set. + +### GetUpdateStrategy + +`func (o *Resource) GetUpdateStrategy() map[string]interface{}` + +GetUpdateStrategy returns the UpdateStrategy field if non-nil, zero value otherwise. + +### GetUpdateStrategyOk + +`func (o *Resource) GetUpdateStrategyOk() (*map[string]interface{}, bool)` + +GetUpdateStrategyOk returns a tuple with the UpdateStrategy field if it's non-nil, zero value otherwise +and a boolean to check if the value has been set. + +### SetUpdateStrategy + +`func (o *Resource) SetUpdateStrategy(v map[string]interface{})` + +SetUpdateStrategy sets UpdateStrategy field to given value. + +### HasUpdateStrategy + +`func (o *Resource) HasUpdateStrategy() bool` + +HasUpdateStrategy returns a boolean if a field has been set. + ### GetStatus `func (o *Resource) GetStatus() map[string]interface{}` diff --git a/pkg/api/openapi/docs/ResourceAllOf.md b/pkg/api/openapi/docs/ResourceAllOf.md index ab434420..7a0f972c 100644 --- a/pkg/api/openapi/docs/ResourceAllOf.md +++ b/pkg/api/openapi/docs/ResourceAllOf.md @@ -10,6 +10,8 @@ Name | Type | Description | Notes **CreatedAt** | Pointer to **time.Time** | | [optional] **UpdatedAt** | Pointer to **time.Time** | | [optional] **Manifest** | Pointer to **map[string]interface{}** | | [optional] +**DeleteOption** | Pointer to **map[string]interface{}** | | [optional] +**UpdateStrategy** | Pointer to **map[string]interface{}** | | [optional] **Status** | Pointer to **map[string]interface{}** | | [optional] ## Methods @@ -181,6 +183,56 @@ SetManifest sets Manifest field to given value. HasManifest returns a boolean if a field has been set. +### GetDeleteOption + +`func (o *ResourceAllOf) GetDeleteOption() map[string]interface{}` + +GetDeleteOption returns the DeleteOption field if non-nil, zero value otherwise. + +### GetDeleteOptionOk + +`func (o *ResourceAllOf) GetDeleteOptionOk() (*map[string]interface{}, bool)` + +GetDeleteOptionOk returns a tuple with the DeleteOption field if it's non-nil, zero value otherwise +and a boolean to check if the value has been set. + +### SetDeleteOption + +`func (o *ResourceAllOf) SetDeleteOption(v map[string]interface{})` + +SetDeleteOption sets DeleteOption field to given value. + +### HasDeleteOption + +`func (o *ResourceAllOf) HasDeleteOption() bool` + +HasDeleteOption returns a boolean if a field has been set. + +### GetUpdateStrategy + +`func (o *ResourceAllOf) GetUpdateStrategy() map[string]interface{}` + +GetUpdateStrategy returns the UpdateStrategy field if non-nil, zero value otherwise. + +### GetUpdateStrategyOk + +`func (o *ResourceAllOf) GetUpdateStrategyOk() (*map[string]interface{}, bool)` + +GetUpdateStrategyOk returns a tuple with the UpdateStrategy field if it's non-nil, zero value otherwise +and a boolean to check if the value has been set. + +### SetUpdateStrategy + +`func (o *ResourceAllOf) SetUpdateStrategy(v map[string]interface{})` + +SetUpdateStrategy sets UpdateStrategy field to given value. + +### HasUpdateStrategy + +`func (o *ResourceAllOf) HasUpdateStrategy() bool` + +HasUpdateStrategy returns a boolean if a field has been set. + ### GetStatus `func (o *ResourceAllOf) GetStatus() map[string]interface{}` diff --git a/pkg/api/openapi/docs/ResourcePatchRequest.md b/pkg/api/openapi/docs/ResourcePatchRequest.md index 6b01c129..eebeba0d 100644 --- a/pkg/api/openapi/docs/ResourcePatchRequest.md +++ b/pkg/api/openapi/docs/ResourcePatchRequest.md @@ -6,6 +6,8 @@ Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- **Version** | Pointer to **int32** | | [optional] **Manifest** | Pointer to **map[string]interface{}** | | [optional] +**DeleteOption** | Pointer to **map[string]interface{}** | | [optional] +**UpdateStrategy** | Pointer to **map[string]interface{}** | | [optional] ## Methods @@ -76,6 +78,56 @@ SetManifest sets Manifest field to given value. HasManifest returns a boolean if a field has been set. +### GetDeleteOption + +`func (o *ResourcePatchRequest) GetDeleteOption() map[string]interface{}` + +GetDeleteOption returns the DeleteOption field if non-nil, zero value otherwise. + +### GetDeleteOptionOk + +`func (o *ResourcePatchRequest) GetDeleteOptionOk() (*map[string]interface{}, bool)` + +GetDeleteOptionOk returns a tuple with the DeleteOption field if it's non-nil, zero value otherwise +and a boolean to check if the value has been set. + +### SetDeleteOption + +`func (o *ResourcePatchRequest) SetDeleteOption(v map[string]interface{})` + +SetDeleteOption sets DeleteOption field to given value. + +### HasDeleteOption + +`func (o *ResourcePatchRequest) HasDeleteOption() bool` + +HasDeleteOption returns a boolean if a field has been set. + +### GetUpdateStrategy + +`func (o *ResourcePatchRequest) GetUpdateStrategy() map[string]interface{}` + +GetUpdateStrategy returns the UpdateStrategy field if non-nil, zero value otherwise. + +### GetUpdateStrategyOk + +`func (o *ResourcePatchRequest) GetUpdateStrategyOk() (*map[string]interface{}, bool)` + +GetUpdateStrategyOk returns a tuple with the UpdateStrategy field if it's non-nil, zero value otherwise +and a boolean to check if the value has been set. + +### SetUpdateStrategy + +`func (o *ResourcePatchRequest) SetUpdateStrategy(v map[string]interface{})` + +SetUpdateStrategy sets UpdateStrategy field to given value. + +### HasUpdateStrategy + +`func (o *ResourcePatchRequest) HasUpdateStrategy() bool` + +HasUpdateStrategy returns a boolean if a field has been set. + [[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) diff --git a/pkg/api/openapi/model_resource.go b/pkg/api/openapi/model_resource.go index 2529fe94..8dbc705d 100644 --- a/pkg/api/openapi/model_resource.go +++ b/pkg/api/openapi/model_resource.go @@ -20,16 +20,18 @@ var _ MappedNullable = &Resource{} // Resource struct for Resource type Resource struct { - Id *string `json:"id,omitempty"` - Kind *string `json:"kind,omitempty"` - Href *string `json:"href,omitempty"` - Name *string `json:"name,omitempty"` - ConsumerName *string `json:"consumer_name,omitempty"` - Version *int32 `json:"version,omitempty"` - CreatedAt *time.Time `json:"created_at,omitempty"` - UpdatedAt *time.Time `json:"updated_at,omitempty"` - Manifest map[string]interface{} `json:"manifest,omitempty"` - Status map[string]interface{} `json:"status,omitempty"` + Id *string `json:"id,omitempty"` + Kind *string `json:"kind,omitempty"` + Href *string `json:"href,omitempty"` + Name *string `json:"name,omitempty"` + ConsumerName *string `json:"consumer_name,omitempty"` + Version *int32 `json:"version,omitempty"` + CreatedAt *time.Time `json:"created_at,omitempty"` + UpdatedAt *time.Time `json:"updated_at,omitempty"` + Manifest map[string]interface{} `json:"manifest,omitempty"` + DeleteOption map[string]interface{} `json:"delete_option,omitempty"` + UpdateStrategy map[string]interface{} `json:"update_strategy,omitempty"` + Status map[string]interface{} `json:"status,omitempty"` } // NewResource instantiates a new Resource object @@ -337,6 +339,70 @@ func (o *Resource) SetManifest(v map[string]interface{}) { o.Manifest = v } +// GetDeleteOption returns the DeleteOption field value if set, zero value otherwise. +func (o *Resource) GetDeleteOption() map[string]interface{} { + if o == nil || IsNil(o.DeleteOption) { + var ret map[string]interface{} + return ret + } + return o.DeleteOption +} + +// GetDeleteOptionOk returns a tuple with the DeleteOption field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Resource) GetDeleteOptionOk() (map[string]interface{}, bool) { + if o == nil || IsNil(o.DeleteOption) { + return map[string]interface{}{}, false + } + return o.DeleteOption, true +} + +// HasDeleteOption returns a boolean if a field has been set. +func (o *Resource) HasDeleteOption() bool { + if o != nil && !IsNil(o.DeleteOption) { + return true + } + + return false +} + +// SetDeleteOption gets a reference to the given map[string]interface{} and assigns it to the DeleteOption field. +func (o *Resource) SetDeleteOption(v map[string]interface{}) { + o.DeleteOption = v +} + +// GetUpdateStrategy returns the UpdateStrategy field value if set, zero value otherwise. +func (o *Resource) GetUpdateStrategy() map[string]interface{} { + if o == nil || IsNil(o.UpdateStrategy) { + var ret map[string]interface{} + return ret + } + return o.UpdateStrategy +} + +// GetUpdateStrategyOk returns a tuple with the UpdateStrategy field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Resource) GetUpdateStrategyOk() (map[string]interface{}, bool) { + if o == nil || IsNil(o.UpdateStrategy) { + return map[string]interface{}{}, false + } + return o.UpdateStrategy, true +} + +// HasUpdateStrategy returns a boolean if a field has been set. +func (o *Resource) HasUpdateStrategy() bool { + if o != nil && !IsNil(o.UpdateStrategy) { + return true + } + + return false +} + +// SetUpdateStrategy gets a reference to the given map[string]interface{} and assigns it to the UpdateStrategy field. +func (o *Resource) SetUpdateStrategy(v map[string]interface{}) { + o.UpdateStrategy = v +} + // GetStatus returns the Status field value if set, zero value otherwise. func (o *Resource) GetStatus() map[string]interface{} { if o == nil || IsNil(o.Status) { @@ -406,6 +472,12 @@ func (o Resource) ToMap() (map[string]interface{}, error) { if !IsNil(o.Manifest) { toSerialize["manifest"] = o.Manifest } + if !IsNil(o.DeleteOption) { + toSerialize["delete_option"] = o.DeleteOption + } + if !IsNil(o.UpdateStrategy) { + toSerialize["update_strategy"] = o.UpdateStrategy + } if !IsNil(o.Status) { toSerialize["status"] = o.Status } diff --git a/pkg/api/openapi/model_resource_all_of.go b/pkg/api/openapi/model_resource_all_of.go index d94f6097..79d99f8d 100644 --- a/pkg/api/openapi/model_resource_all_of.go +++ b/pkg/api/openapi/model_resource_all_of.go @@ -20,13 +20,15 @@ var _ MappedNullable = &ResourceAllOf{} // ResourceAllOf struct for ResourceAllOf type ResourceAllOf struct { - Name *string `json:"name,omitempty"` - ConsumerName *string `json:"consumer_name,omitempty"` - Version *int32 `json:"version,omitempty"` - CreatedAt *time.Time `json:"created_at,omitempty"` - UpdatedAt *time.Time `json:"updated_at,omitempty"` - Manifest map[string]interface{} `json:"manifest,omitempty"` - Status map[string]interface{} `json:"status,omitempty"` + Name *string `json:"name,omitempty"` + ConsumerName *string `json:"consumer_name,omitempty"` + Version *int32 `json:"version,omitempty"` + CreatedAt *time.Time `json:"created_at,omitempty"` + UpdatedAt *time.Time `json:"updated_at,omitempty"` + Manifest map[string]interface{} `json:"manifest,omitempty"` + DeleteOption map[string]interface{} `json:"delete_option,omitempty"` + UpdateStrategy map[string]interface{} `json:"update_strategy,omitempty"` + Status map[string]interface{} `json:"status,omitempty"` } // NewResourceAllOf instantiates a new ResourceAllOf object @@ -238,6 +240,70 @@ func (o *ResourceAllOf) SetManifest(v map[string]interface{}) { o.Manifest = v } +// GetDeleteOption returns the DeleteOption field value if set, zero value otherwise. +func (o *ResourceAllOf) GetDeleteOption() map[string]interface{} { + if o == nil || IsNil(o.DeleteOption) { + var ret map[string]interface{} + return ret + } + return o.DeleteOption +} + +// GetDeleteOptionOk returns a tuple with the DeleteOption field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ResourceAllOf) GetDeleteOptionOk() (map[string]interface{}, bool) { + if o == nil || IsNil(o.DeleteOption) { + return map[string]interface{}{}, false + } + return o.DeleteOption, true +} + +// HasDeleteOption returns a boolean if a field has been set. +func (o *ResourceAllOf) HasDeleteOption() bool { + if o != nil && !IsNil(o.DeleteOption) { + return true + } + + return false +} + +// SetDeleteOption gets a reference to the given map[string]interface{} and assigns it to the DeleteOption field. +func (o *ResourceAllOf) SetDeleteOption(v map[string]interface{}) { + o.DeleteOption = v +} + +// GetUpdateStrategy returns the UpdateStrategy field value if set, zero value otherwise. +func (o *ResourceAllOf) GetUpdateStrategy() map[string]interface{} { + if o == nil || IsNil(o.UpdateStrategy) { + var ret map[string]interface{} + return ret + } + return o.UpdateStrategy +} + +// GetUpdateStrategyOk returns a tuple with the UpdateStrategy field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ResourceAllOf) GetUpdateStrategyOk() (map[string]interface{}, bool) { + if o == nil || IsNil(o.UpdateStrategy) { + return map[string]interface{}{}, false + } + return o.UpdateStrategy, true +} + +// HasUpdateStrategy returns a boolean if a field has been set. +func (o *ResourceAllOf) HasUpdateStrategy() bool { + if o != nil && !IsNil(o.UpdateStrategy) { + return true + } + + return false +} + +// SetUpdateStrategy gets a reference to the given map[string]interface{} and assigns it to the UpdateStrategy field. +func (o *ResourceAllOf) SetUpdateStrategy(v map[string]interface{}) { + o.UpdateStrategy = v +} + // GetStatus returns the Status field value if set, zero value otherwise. func (o *ResourceAllOf) GetStatus() map[string]interface{} { if o == nil || IsNil(o.Status) { @@ -298,6 +364,12 @@ func (o ResourceAllOf) ToMap() (map[string]interface{}, error) { if !IsNil(o.Manifest) { toSerialize["manifest"] = o.Manifest } + if !IsNil(o.DeleteOption) { + toSerialize["delete_option"] = o.DeleteOption + } + if !IsNil(o.UpdateStrategy) { + toSerialize["update_strategy"] = o.UpdateStrategy + } if !IsNil(o.Status) { toSerialize["status"] = o.Status } diff --git a/pkg/api/openapi/model_resource_patch_request.go b/pkg/api/openapi/model_resource_patch_request.go index f59bd335..a72ea467 100644 --- a/pkg/api/openapi/model_resource_patch_request.go +++ b/pkg/api/openapi/model_resource_patch_request.go @@ -19,8 +19,10 @@ var _ MappedNullable = &ResourcePatchRequest{} // ResourcePatchRequest struct for ResourcePatchRequest type ResourcePatchRequest struct { - Version *int32 `json:"version,omitempty"` - Manifest map[string]interface{} `json:"manifest,omitempty"` + Version *int32 `json:"version,omitempty"` + Manifest map[string]interface{} `json:"manifest,omitempty"` + DeleteOption map[string]interface{} `json:"delete_option,omitempty"` + UpdateStrategy map[string]interface{} `json:"update_strategy,omitempty"` } // NewResourcePatchRequest instantiates a new ResourcePatchRequest object @@ -104,6 +106,70 @@ func (o *ResourcePatchRequest) SetManifest(v map[string]interface{}) { o.Manifest = v } +// GetDeleteOption returns the DeleteOption field value if set, zero value otherwise. +func (o *ResourcePatchRequest) GetDeleteOption() map[string]interface{} { + if o == nil || IsNil(o.DeleteOption) { + var ret map[string]interface{} + return ret + } + return o.DeleteOption +} + +// GetDeleteOptionOk returns a tuple with the DeleteOption field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ResourcePatchRequest) GetDeleteOptionOk() (map[string]interface{}, bool) { + if o == nil || IsNil(o.DeleteOption) { + return map[string]interface{}{}, false + } + return o.DeleteOption, true +} + +// HasDeleteOption returns a boolean if a field has been set. +func (o *ResourcePatchRequest) HasDeleteOption() bool { + if o != nil && !IsNil(o.DeleteOption) { + return true + } + + return false +} + +// SetDeleteOption gets a reference to the given map[string]interface{} and assigns it to the DeleteOption field. +func (o *ResourcePatchRequest) SetDeleteOption(v map[string]interface{}) { + o.DeleteOption = v +} + +// GetUpdateStrategy returns the UpdateStrategy field value if set, zero value otherwise. +func (o *ResourcePatchRequest) GetUpdateStrategy() map[string]interface{} { + if o == nil || IsNil(o.UpdateStrategy) { + var ret map[string]interface{} + return ret + } + return o.UpdateStrategy +} + +// GetUpdateStrategyOk returns a tuple with the UpdateStrategy field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ResourcePatchRequest) GetUpdateStrategyOk() (map[string]interface{}, bool) { + if o == nil || IsNil(o.UpdateStrategy) { + return map[string]interface{}{}, false + } + return o.UpdateStrategy, true +} + +// HasUpdateStrategy returns a boolean if a field has been set. +func (o *ResourcePatchRequest) HasUpdateStrategy() bool { + if o != nil && !IsNil(o.UpdateStrategy) { + return true + } + + return false +} + +// SetUpdateStrategy gets a reference to the given map[string]interface{} and assigns it to the UpdateStrategy field. +func (o *ResourcePatchRequest) SetUpdateStrategy(v map[string]interface{}) { + o.UpdateStrategy = v +} + func (o ResourcePatchRequest) MarshalJSON() ([]byte, error) { toSerialize, err := o.ToMap() if err != nil { @@ -120,6 +186,12 @@ func (o ResourcePatchRequest) ToMap() (map[string]interface{}, error) { if !IsNil(o.Manifest) { toSerialize["manifest"] = o.Manifest } + if !IsNil(o.DeleteOption) { + toSerialize["delete_option"] = o.DeleteOption + } + if !IsNil(o.UpdateStrategy) { + toSerialize["update_strategy"] = o.UpdateStrategy + } return toSerialize, nil } diff --git a/pkg/api/presenters/resource.go b/pkg/api/presenters/resource.go index 929efec5..105513c1 100755 --- a/pkg/api/presenters/resource.go +++ b/pkg/api/presenters/resource.go @@ -9,7 +9,7 @@ import ( // ConvertResource converts a resource from the API to the openapi representation. func ConvertResource(resource openapi.Resource) (*api.Resource, error) { - manifest, err := ConvertResourceManifest(resource.Manifest) + manifest, err := ConvertResourceManifest(resource.Manifest, resource.DeleteOption, resource.UpdateStrategy) if err != nil { return nil, err } @@ -26,8 +26,8 @@ func ConvertResource(resource openapi.Resource) (*api.Resource, error) { } // ConvertResourceManifest converts a resource manifest from the openapi representation to the API. -func ConvertResourceManifest(manifest map[string]interface{}) (datatypes.JSONMap, error) { - return api.EncodeManifest(manifest) +func ConvertResourceManifest(manifest, deleteOption, updateStrategy map[string]interface{}) (datatypes.JSONMap, error) { + return api.EncodeManifest(manifest, deleteOption, updateStrategy) } // PresentResource converts a resource from the API to the openapi representation. diff --git a/pkg/api/resource_types.go b/pkg/api/resource_types.go index 409c51e0..224ec756 100755 --- a/pkg/api/resource_types.go +++ b/pkg/api/resource_types.go @@ -122,18 +122,47 @@ func CloudEventToJSONMap(evt *cloudevents.Event) (datatypes.JSONMap, error) { } // EncodeManifest converts a resource manifest (map[string]interface{}) into a CloudEvent JSONMap representation. -func EncodeManifest(manifest map[string]interface{}) (datatypes.JSONMap, error) { +func EncodeManifest(manifest, deleteOption, updateStrategy map[string]interface{}) (datatypes.JSONMap, error) { if len(manifest) == 0 { return nil, nil } + delOption := &workv1.DeleteOption{ + PropagationPolicy: workv1.DeletePropagationPolicyTypeForeground, + } + if len(deleteOption) != 0 { + delOption = &workv1.DeleteOption{} + deleteOptionBytes, err := json.Marshal(deleteOption) + if err != nil { + return nil, fmt.Errorf("failed to marshal deleteOption to json: %v", err) + } + err = json.Unmarshal(deleteOptionBytes, delOption) + if err != nil { + return nil, fmt.Errorf("failed to unmarshal json to deleteOption: %v", err) + } + } + + upStrategy := &workv1.UpdateStrategy{ + Type: workv1.UpdateStrategyTypeServerSideApply, + } + if len(updateStrategy) != 0 { + upStrategy = &workv1.UpdateStrategy{} + updateStrategyBytes, err := json.Marshal(updateStrategy) + if err != nil { + return nil, fmt.Errorf("failed to marshal updateStrategy to json: %v", err) + } + err = json.Unmarshal(updateStrategyBytes, upStrategy) + if err != nil { + return nil, fmt.Errorf("failed to unmarshal json to updateStrategy: %v", err) + } + fmt.Println("upStrategy", upStrategy) + } + // create a cloud event with the manifest as the data evt := cetypes.NewEventBuilder("maestro", cetypes.CloudEventsType{}).NewEvent() eventPayload := &workpayload.Manifest{ - Manifest: unstructured.Unstructured{Object: manifest}, - DeleteOption: &workv1.DeleteOption{ - PropagationPolicy: workv1.DeletePropagationPolicyTypeForeground, - }, + Manifest: unstructured.Unstructured{Object: manifest}, + DeleteOption: delOption, ConfigOption: &workpayload.ManifestConfigOption{ FeedbackRules: []workv1.FeedbackRule{ { @@ -146,10 +175,7 @@ func EncodeManifest(manifest map[string]interface{}) (datatypes.JSONMap, error) }, }, }, - UpdateStrategy: &workv1.UpdateStrategy{ - // TODO support external configuration, e.g. configure this through manifest annotations - Type: workv1.UpdateStrategyTypeServerSideApply, - }, + UpdateStrategy: upStrategy, }, } diff --git a/pkg/api/resource_types_test.go b/pkg/api/resource_types_test.go index 9f3f63c1..4f9e8b4e 100644 --- a/pkg/api/resource_types_test.go +++ b/pkg/api/resource_types_test.go @@ -12,6 +12,8 @@ func TestEncodeManifest(t *testing.T) { cases := []struct { name string input map[string]interface{} + deleteOption map[string]interface{} + updateStrategy map[string]interface{} expected datatypes.JSONMap expectedErrorMsg string }{ @@ -22,13 +24,20 @@ func TestEncodeManifest(t *testing.T) { }, { name: "valid", - input: newManifest(t, "{\"apiVersion\":\"v1\",\"kind\":\"ConfigMap\",\"metadata\":{\"name\":\"test\",\"namespace\":\"test\"}}"), - expected: newManifest(t, "{\"specversion\":\"1.0\",\"datacontenttype\":\"application/json\",\"data\":{\"manifest\":{\"apiVersion\":\"v1\",\"kind\":\"ConfigMap\",\"metadata\":{\"name\":\"test\",\"namespace\":\"test\"}}}}"), + input: newJSONMap(t, "{\"apiVersion\":\"v1\",\"kind\":\"ConfigMap\",\"metadata\":{\"name\":\"test\",\"namespace\":\"test\"}}"), + expected: newJSONMap(t, "{\"specversion\":\"1.0\",\"datacontenttype\":\"application/json\",\"data\":{\"manifest\":{\"apiVersion\":\"v1\",\"kind\":\"ConfigMap\",\"metadata\":{\"name\":\"test\",\"namespace\":\"test\"}}}}"), + }, + { + name: "valid", + deleteOption: newJSONMap(t, "{\"propagationPolicy\": \"Orphan\"}"), + updateStrategy: newJSONMap(t, "{\"type\": \"CreateOnly\"}"), + input: newJSONMap(t, "{\"apiVersion\":\"v1\",\"kind\":\"ConfigMap\",\"metadata\":{\"name\":\"test\",\"namespace\":\"test\"}}"), + expected: newJSONMap(t, "{\"specversion\":\"1.0\",\"datacontenttype\":\"application/json\",\"data\":{\"configOption\":{\"updateStrategy\": {\"type\": \"CreateOnly\"}},\"deleteOption\": {\"propagationPolicy\": \"Orphan\"},\"manifest\":{\"apiVersion\":\"v1\",\"kind\":\"ConfigMap\",\"metadata\":{\"name\":\"test\",\"namespace\":\"test\"}}}}"), }, } for _, c := range cases { t.Run(c.name, func(t *testing.T) { - gotManifest, err := EncodeManifest(c.input) + gotManifest, err := EncodeManifest(c.input, c.deleteOption, c.updateStrategy) if err != nil { if err.Error() != c.expectedErrorMsg { t.Errorf("expected %#v but got: %#v", c.expectedErrorMsg, err) @@ -57,8 +66,8 @@ func TestDecodeManifest(t *testing.T) { }, { name: "valid", - input: newManifest(t, "{\"specversion\":\"1.0\",\"datacontenttype\":\"application/json\",\"data\":{\"manifest\":{\"apiVersion\":\"v1\",\"kind\":\"ConfigMap\",\"metadata\":{\"name\":\"test\",\"namespace\":\"test\"}}}}"), - expected: newManifest(t, "{\"apiVersion\":\"v1\",\"kind\":\"ConfigMap\",\"metadata\":{\"name\":\"test\",\"namespace\":\"test\"}}"), + input: newJSONMap(t, "{\"specversion\":\"1.0\",\"datacontenttype\":\"application/json\",\"data\":{\"manifest\":{\"apiVersion\":\"v1\",\"kind\":\"ConfigMap\",\"metadata\":{\"name\":\"test\",\"namespace\":\"test\"}}}}"), + expected: newJSONMap(t, "{\"apiVersion\":\"v1\",\"kind\":\"ConfigMap\",\"metadata\":{\"name\":\"test\",\"namespace\":\"test\"}}"), }, } for _, c := range cases { @@ -92,10 +101,10 @@ func TestDecodeManifestBundle(t *testing.T) { }, { name: "valid", - input: newManifest(t, "{\"specversion\":\"1.0\",\"datacontenttype\":\"application/json\",\"data\":{\"manifests\":[{\"apiVersion\":\"v1\",\"kind\":\"ConfigMap\",\"metadata\":{\"name\":\"nginx\",\"namespace\":\"default\"}},{\"apiVersion\":\"apps/v1\",\"kind\":\"Deployment\",\"metadata\":{\"name\":\"nginx\",\"namespace\":\"default\"},\"spec\":{\"replicas\":1,\"selector\":{\"matchLabels\":{\"app\":\"nginx\"}},\"template\":{\"spec\":{\"containers\":[{\"name\":\"nginx\",\"image\":\"nginxinc/nginx-unprivileged\"}]},\"metadata\":{\"labels\":{\"app\":\"nginx\"}}}}}],\"deleteOption\":{\"propagationPolicy\":\"Foreground\"},\"manifestConfigs\":[{\"updateStrategy\":{\"type\":\"ServerSideApply\"},\"resourceIdentifier\":{\"name\":\"nginx\",\"group\":\"apps\",\"resource\":\"deployments\",\"namespace\":\"default\"}}]}}"), + input: newJSONMap(t, "{\"specversion\":\"1.0\",\"datacontenttype\":\"application/json\",\"data\":{\"manifests\":[{\"apiVersion\":\"v1\",\"kind\":\"ConfigMap\",\"metadata\":{\"name\":\"nginx\",\"namespace\":\"default\"}},{\"apiVersion\":\"apps/v1\",\"kind\":\"Deployment\",\"metadata\":{\"name\":\"nginx\",\"namespace\":\"default\"},\"spec\":{\"replicas\":1,\"selector\":{\"matchLabels\":{\"app\":\"nginx\"}},\"template\":{\"spec\":{\"containers\":[{\"name\":\"nginx\",\"image\":\"nginxinc/nginx-unprivileged\"}]},\"metadata\":{\"labels\":{\"app\":\"nginx\"}}}}}],\"deleteOption\":{\"propagationPolicy\":\"Foreground\"},\"manifestConfigs\":[{\"updateStrategy\":{\"type\":\"ServerSideApply\"},\"resourceIdentifier\":{\"name\":\"nginx\",\"group\":\"apps\",\"resource\":\"deployments\",\"namespace\":\"default\"}}]}}"), expected: []map[string]interface{}{ - newManifest(t, "{\"apiVersion\":\"v1\",\"kind\":\"ConfigMap\",\"metadata\":{\"name\":\"nginx\",\"namespace\":\"default\"}}"), - newManifest(t, "{\"apiVersion\":\"apps/v1\",\"kind\":\"Deployment\",\"metadata\":{\"name\":\"nginx\",\"namespace\":\"default\"},\"spec\":{\"replicas\":1,\"selector\":{\"matchLabels\":{\"app\":\"nginx\"}},\"template\":{\"spec\":{\"containers\":[{\"name\":\"nginx\",\"image\":\"nginxinc/nginx-unprivileged\"}]},\"metadata\":{\"labels\":{\"app\":\"nginx\"}}}}}"), + newJSONMap(t, "{\"apiVersion\":\"v1\",\"kind\":\"ConfigMap\",\"metadata\":{\"name\":\"nginx\",\"namespace\":\"default\"}}"), + newJSONMap(t, "{\"apiVersion\":\"apps/v1\",\"kind\":\"Deployment\",\"metadata\":{\"name\":\"nginx\",\"namespace\":\"default\"},\"spec\":{\"replicas\":1,\"selector\":{\"matchLabels\":{\"app\":\"nginx\"}},\"template\":{\"spec\":{\"containers\":[{\"name\":\"nginx\",\"image\":\"nginxinc/nginx-unprivileged\"}]},\"metadata\":{\"labels\":{\"app\":\"nginx\"}}}}}"), }, }, } @@ -136,8 +145,8 @@ func TestDecodeStatus(t *testing.T) { }, { name: "valid", - input: newManifest(t, "{\"id\":\"1f21fcbe-3e41-4639-ab8d-1713c578e4cd\",\"time\":\"2024-03-07T03:29:12.094854533Z\",\"type\":\"io.open-cluster-management.works.v1alpha1.manifests.status.update_request\",\"source\":\"maestro-agent-59d9c485d9-7bvwb\",\"specversion\":\"1.0\",\"datacontenttype\":\"application/json\",\"resourceid\":\"b9368296-3200-42ec-bfbb-f7d44a06c4e0\",\"sequenceid\":\"1765580430112722944\",\"clustername\":\"b288a9da-8bfe-4c82-94cc-2b48e773fc46\",\"originalsource\":\"maestro\",\"resourceversion\":\"1\",\"data\":{\"status\":{\"conditions\":[{\"type\":\"Applied\",\"reason\":\"AppliedManifestComplete\",\"status\":\"True\",\"message\":\"Apply manifest complete\",\"lastTransitionTime\":\"2024-03-07T03:29:03Z\"},{\"type\":\"Available\",\"reason\":\"ResourceAvailable\",\"status\":\"True\",\"message\":\"Resource is available\",\"lastTransitionTime\":\"2024-03-07T03:29:03Z\"},{\"type\":\"StatusFeedbackSynced\",\"reason\":\"StatusFeedbackSynced\",\"status\":\"True\",\"message\":\"\",\"lastTransitionTime\":\"2024-03-07T03:29:03Z\"}],\"resourceMeta\":{\"kind\":\"Deployment\",\"name\":\"nginx1\",\"group\":\"apps\",\"ordinal\":0,\"version\":\"v1\",\"resource\":\"deployments\",\"namespace\":\"default\"},\"statusFeedback\":{\"values\":[{\"name\":\"status\",\"fieldValue\":{\"type\":\"JsonRaw\",\"jsonRaw\":\"{\\\"availableReplicas\\\":1,\\\"conditions\\\":[{\\\"lastTransitionTime\\\":\\\"2024-03-07T03:29:06Z\\\",\\\"lastUpdateTime\\\":\\\"2024-03-07T03:29:06Z\\\",\\\"message\\\":\\\"Deployment has minimum availability.\\\",\\\"reason\\\":\\\"MinimumReplicasAvailable\\\",\\\"status\\\":\\\"True\\\",\\\"type\\\":\\\"Available\\\"},{\\\"lastTransitionTime\\\":\\\"2024-03-07T03:29:03Z\\\",\\\"lastUpdateTime\\\":\\\"2024-03-07T03:29:06Z\\\",\\\"message\\\":\\\"ReplicaSet \\\\\\\"nginx1-5d6b548959\\\\\\\" has successfully progressed.\\\",\\\"reason\\\":\\\"NewReplicaSetAvailable\\\",\\\"status\\\":\\\"True\\\",\\\"type\\\":\\\"Progressing\\\"}],\\\"observedGeneration\\\":1,\\\"readyReplicas\\\":1,\\\"replicas\\\":1,\\\"updatedReplicas\\\":1}\"}}]}},\"conditions\":[{\"type\":\"Applied\",\"reason\":\"AppliedManifestWorkComplete\",\"status\":\"True\",\"message\":\"Apply manifest work complete\",\"lastTransitionTime\":\"2024-03-07T03:29:03Z\"},{\"type\":\"Available\",\"reason\":\"ResourcesAvailable\",\"status\":\"True\",\"message\":\"All resources are available\",\"lastTransitionTime\":\"2024-03-07T03:29:03Z\"}]}}"), - expected: newManifest(t, "{\"ContentStatus\":{\"availableReplicas\":1,\"observedGeneration\":1,\"readyReplicas\":1,\"replicas\":1,\"updatedReplicas\":1,\"conditions\":[{\"lastTransitionTime\":\"2024-03-07T03:29:06Z\",\"lastUpdateTime\":\"2024-03-07T03:29:06Z\",\"message\":\"Deployment has minimum availability.\",\"reason\":\"MinimumReplicasAvailable\",\"status\":\"True\",\"type\":\"Available\"},{\"lastTransitionTime\":\"2024-03-07T03:29:03Z\",\"lastUpdateTime\":\"2024-03-07T03:29:06Z\",\"message\":\"ReplicaSet \\\"nginx1-5d6b548959\\\" has successfully progressed.\",\"reason\":\"NewReplicaSetAvailable\",\"status\":\"True\",\"type\":\"Progressing\"}]},\"ReconcileStatus\":{\"Conditions\":[{\"lastTransitionTime\":\"2024-03-07T03:29:03Z\",\"message\":\"Apply manifest complete\",\"reason\":\"AppliedManifestComplete\",\"status\":\"True\",\"type\":\"Applied\"},{\"lastTransitionTime\":\"2024-03-07T03:29:03Z\",\"message\":\"Resource is available\",\"reason\":\"ResourceAvailable\",\"status\":\"True\",\"type\":\"Available\"},{\"lastTransitionTime\":\"2024-03-07T03:29:03Z\",\"message\":\"\",\"reason\":\"StatusFeedbackSynced\",\"status\":\"True\",\"type\":\"StatusFeedbackSynced\"}],\"ObservedVersion\":1,\"SequenceID\":\"1765580430112722944\"}}"), + input: newJSONMap(t, "{\"id\":\"1f21fcbe-3e41-4639-ab8d-1713c578e4cd\",\"time\":\"2024-03-07T03:29:12.094854533Z\",\"type\":\"io.open-cluster-management.works.v1alpha1.manifests.status.update_request\",\"source\":\"maestro-agent-59d9c485d9-7bvwb\",\"specversion\":\"1.0\",\"datacontenttype\":\"application/json\",\"resourceid\":\"b9368296-3200-42ec-bfbb-f7d44a06c4e0\",\"sequenceid\":\"1765580430112722944\",\"clustername\":\"b288a9da-8bfe-4c82-94cc-2b48e773fc46\",\"originalsource\":\"maestro\",\"resourceversion\":\"1\",\"data\":{\"status\":{\"conditions\":[{\"type\":\"Applied\",\"reason\":\"AppliedManifestComplete\",\"status\":\"True\",\"message\":\"Apply manifest complete\",\"lastTransitionTime\":\"2024-03-07T03:29:03Z\"},{\"type\":\"Available\",\"reason\":\"ResourceAvailable\",\"status\":\"True\",\"message\":\"Resource is available\",\"lastTransitionTime\":\"2024-03-07T03:29:03Z\"},{\"type\":\"StatusFeedbackSynced\",\"reason\":\"StatusFeedbackSynced\",\"status\":\"True\",\"message\":\"\",\"lastTransitionTime\":\"2024-03-07T03:29:03Z\"}],\"resourceMeta\":{\"kind\":\"Deployment\",\"name\":\"nginx1\",\"group\":\"apps\",\"ordinal\":0,\"version\":\"v1\",\"resource\":\"deployments\",\"namespace\":\"default\"},\"statusFeedback\":{\"values\":[{\"name\":\"status\",\"fieldValue\":{\"type\":\"JsonRaw\",\"jsonRaw\":\"{\\\"availableReplicas\\\":1,\\\"conditions\\\":[{\\\"lastTransitionTime\\\":\\\"2024-03-07T03:29:06Z\\\",\\\"lastUpdateTime\\\":\\\"2024-03-07T03:29:06Z\\\",\\\"message\\\":\\\"Deployment has minimum availability.\\\",\\\"reason\\\":\\\"MinimumReplicasAvailable\\\",\\\"status\\\":\\\"True\\\",\\\"type\\\":\\\"Available\\\"},{\\\"lastTransitionTime\\\":\\\"2024-03-07T03:29:03Z\\\",\\\"lastUpdateTime\\\":\\\"2024-03-07T03:29:06Z\\\",\\\"message\\\":\\\"ReplicaSet \\\\\\\"nginx1-5d6b548959\\\\\\\" has successfully progressed.\\\",\\\"reason\\\":\\\"NewReplicaSetAvailable\\\",\\\"status\\\":\\\"True\\\",\\\"type\\\":\\\"Progressing\\\"}],\\\"observedGeneration\\\":1,\\\"readyReplicas\\\":1,\\\"replicas\\\":1,\\\"updatedReplicas\\\":1}\"}}]}},\"conditions\":[{\"type\":\"Applied\",\"reason\":\"AppliedManifestWorkComplete\",\"status\":\"True\",\"message\":\"Apply manifest work complete\",\"lastTransitionTime\":\"2024-03-07T03:29:03Z\"},{\"type\":\"Available\",\"reason\":\"ResourcesAvailable\",\"status\":\"True\",\"message\":\"All resources are available\",\"lastTransitionTime\":\"2024-03-07T03:29:03Z\"}]}}"), + expected: newJSONMap(t, "{\"ContentStatus\":{\"availableReplicas\":1,\"observedGeneration\":1,\"readyReplicas\":1,\"replicas\":1,\"updatedReplicas\":1,\"conditions\":[{\"lastTransitionTime\":\"2024-03-07T03:29:06Z\",\"lastUpdateTime\":\"2024-03-07T03:29:06Z\",\"message\":\"Deployment has minimum availability.\",\"reason\":\"MinimumReplicasAvailable\",\"status\":\"True\",\"type\":\"Available\"},{\"lastTransitionTime\":\"2024-03-07T03:29:03Z\",\"lastUpdateTime\":\"2024-03-07T03:29:06Z\",\"message\":\"ReplicaSet \\\"nginx1-5d6b548959\\\" has successfully progressed.\",\"reason\":\"NewReplicaSetAvailable\",\"status\":\"True\",\"type\":\"Progressing\"}]},\"ReconcileStatus\":{\"Conditions\":[{\"lastTransitionTime\":\"2024-03-07T03:29:03Z\",\"message\":\"Apply manifest complete\",\"reason\":\"AppliedManifestComplete\",\"status\":\"True\",\"type\":\"Applied\"},{\"lastTransitionTime\":\"2024-03-07T03:29:03Z\",\"message\":\"Resource is available\",\"reason\":\"ResourceAvailable\",\"status\":\"True\",\"type\":\"Available\"},{\"lastTransitionTime\":\"2024-03-07T03:29:03Z\",\"message\":\"\",\"reason\":\"StatusFeedbackSynced\",\"status\":\"True\",\"type\":\"StatusFeedbackSynced\"}],\"ObservedVersion\":1,\"SequenceID\":\"1765580430112722944\"}}"), }, } for _, c := range cases { @@ -156,11 +165,11 @@ func TestDecodeStatus(t *testing.T) { } } -func newManifest(t *testing.T, data string) datatypes.JSONMap { - manifest := map[string]interface{}{} - if err := json.Unmarshal([]byte(data), &manifest); err != nil { +func newJSONMap(t *testing.T, data string) datatypes.JSONMap { + jsonmap := map[string]interface{}{} + if err := json.Unmarshal([]byte(data), &jsonmap); err != nil { t.Fatal(err) } - return manifest + return jsonmap } diff --git a/pkg/handlers/resource.go b/pkg/handlers/resource.go index b40c1752..fd18e05d 100755 --- a/pkg/handlers/resource.go +++ b/pkg/handlers/resource.go @@ -70,7 +70,7 @@ func (h resourceHandler) Patch(w http.ResponseWriter, r *http.Request) { func() (interface{}, *errors.ServiceError) { ctx := r.Context() id := mux.Vars(r)["id"] - manifest, err := presenters.ConvertResourceManifest(patch.Manifest) + manifest, err := presenters.ConvertResourceManifest(patch.Manifest, patch.DeleteOption, patch.UpdateStrategy) if err != nil { return nil, errors.GeneralError("failed to convert resource manifest: %s", err) } diff --git a/test/factories.go b/test/factories.go index 9711efa5..971846b6 100755 --- a/test/factories.go +++ b/test/factories.go @@ -58,7 +58,7 @@ func (helper *Helper) NewAPIResource(consumerName string, replicas int) openapi. func (helper *Helper) NewResource(consumerName string, replicas int) *api.Resource { testResource := helper.NewAPIResource(consumerName, replicas) - testManifest, err := api.EncodeManifest(testResource.Manifest) + testManifest, err := api.EncodeManifest(testResource.Manifest, testResource.DeleteOption, testResource.UpdateStrategy) if err != nil { helper.T.Errorf("error encoding manifest: %q", err) } From 2c0d4b599cdabcf18ba741825eb2d5808532c8f0 Mon Sep 17 00:00:00 2001 From: clyang82 Date: Mon, 27 May 2024 20:38:47 +0800 Subject: [PATCH 2/3] Return delete_option and update_strategy Signed-off-by: clyang82 --- README.md | 19 ++++++++++-- pkg/api/presenters/resource.go | 24 ++++++++------- pkg/api/resource_types.go | 56 +++++++++++++++++++++++++++++----- pkg/api/resource_types_test.go | 40 +++++++++++++++--------- pkg/services/validation.go | 7 +++-- test/grpc_codec.go | 4 +-- 6 files changed, 111 insertions(+), 39 deletions(-) diff --git a/README.md b/README.md index 5660f9b9..2855d23b 100755 --- a/README.md +++ b/README.md @@ -175,15 +175,24 @@ ocm post /api/maestro/v1/resources << EOF } }, "update_strategy": { - "type": "Orphan" + "type": "ServerSideApply" }, "delete_option": { - "propagationPolicy": "CreateOnly" + "propagationPolicy": "Foreground" } } EOF ``` +delete_option defines the option to delete the resource. It is optional when creating a resource. The propagationPolicy of `delete_option` can be: +- `Foreground` represents that the resource should be fourground deleted. This is a default value. +- `Orphan` represents that the resource is orphaned when deleting the resource. + +update_strategy defines the strategy to update the resource. It is optional when creating a resource. The type of `update_strategy` can be: +- `ServerSideApply` means to update resource using server side apply with work-controller as the field manager. This is a default value. +- `Update` means to update resource by an update call. +- `CreateOnly` means do not update resource based on current manifest. +- `ReadOnly` means only check the existence of the resource based on the resource's metadata. #### Get your Resource @@ -194,6 +203,9 @@ ocm get /api/maestro/v1/resources { "consumer_name": "cluster1", "created_at": "2023-11-23T09:26:13.43061Z", + "delete_option": { + "propagationPolicy":"Foreground" + }, "href": "/api/maestro/v1/resources/f428e21d-71cb-47a4-8d7f-82a65d9a4048", "id": "f428e21d-71cb-47a4-8d7f-82a65d9a4048", "kind": "Resource", @@ -282,6 +294,9 @@ ocm get /api/maestro/v1/resources "SequenceID": "1744926882802962432" } }, + "update_strategy": { + "type":"ServerSideApply" + }, "updated_at": "2023-11-23T09:26:13.457419Z", "version": 1 } diff --git a/pkg/api/presenters/resource.go b/pkg/api/presenters/resource.go index 105513c1..5b27062b 100755 --- a/pkg/api/presenters/resource.go +++ b/pkg/api/presenters/resource.go @@ -32,7 +32,7 @@ func ConvertResourceManifest(manifest, deleteOption, updateStrategy map[string]i // PresentResource converts a resource from the API to the openapi representation. func PresentResource(resource *api.Resource) (*openapi.Resource, error) { - manifest, err := api.DecodeManifest(resource.Manifest) + manifest, deleteOption, updateStrategy, err := api.DecodeManifest(resource.Manifest) if err != nil { return nil, err } @@ -42,15 +42,17 @@ func PresentResource(resource *api.Resource) (*openapi.Resource, error) { } reference := PresentReference(resource.ID, resource) return &openapi.Resource{ - Id: reference.Id, - Kind: reference.Kind, - Href: reference.Href, - Name: openapi.PtrString(resource.Name), - ConsumerName: openapi.PtrString(resource.ConsumerName), - Version: openapi.PtrInt32(resource.Version), - CreatedAt: openapi.PtrTime(resource.CreatedAt), - UpdatedAt: openapi.PtrTime(resource.UpdatedAt), - Manifest: manifest, - Status: status, + Id: reference.Id, + Kind: reference.Kind, + Href: reference.Href, + Name: openapi.PtrString(resource.Name), + ConsumerName: openapi.PtrString(resource.ConsumerName), + Version: openapi.PtrInt32(resource.Version), + CreatedAt: openapi.PtrTime(resource.CreatedAt), + UpdatedAt: openapi.PtrTime(resource.UpdatedAt), + Manifest: manifest, + DeleteOption: deleteOption, + UpdateStrategy: updateStrategy, + Status: status, }, nil } diff --git a/pkg/api/resource_types.go b/pkg/api/resource_types.go index 224ec756..52c67d5d 100755 --- a/pkg/api/resource_types.go +++ b/pkg/api/resource_types.go @@ -121,7 +121,7 @@ func CloudEventToJSONMap(evt *cloudevents.Event) (datatypes.JSONMap, error) { return res, nil } -// EncodeManifest converts a resource manifest (map[string]interface{}) into a CloudEvent JSONMap representation. +// EncodeManifest converts resource manifest, deleteOption and updateStrategy (map[string]interface{}) into a CloudEvent JSONMap representation. func EncodeManifest(manifest, deleteOption, updateStrategy map[string]interface{}) (datatypes.JSONMap, error) { if len(manifest) == 0 { return nil, nil @@ -193,23 +193,65 @@ func EncodeManifest(manifest, deleteOption, updateStrategy map[string]interface{ } // DecodeManifest converts a CloudEvent JSONMap representation of a resource manifest -// into resource manifest (map[string]interface{}). -func DecodeManifest(manifest datatypes.JSONMap) (map[string]interface{}, error) { +// into resource manifest, deleteOption and updateStrategy (map[string]interface{}). +func DecodeManifest(manifest datatypes.JSONMap) (map[string]interface{}, map[string]interface{}, map[string]interface{}, error) { if len(manifest) == 0 { - return nil, nil + return nil, nil, nil, nil } evt, err := JSONMAPToCloudEvent(manifest) if err != nil { - return nil, fmt.Errorf("failed to convert resource manifest to cloudevent: %v", err) + return nil, nil, nil, fmt.Errorf("failed to convert resource manifest to cloudevent: %v", err) } eventPayload := &workpayload.Manifest{} if err := evt.DataAs(eventPayload); err != nil { - return nil, fmt.Errorf("failed to decode cloudevent payload as resource manifest: %v", err) + return nil, nil, nil, fmt.Errorf("failed to decode cloudevent payload as resource manifest: %v", err) + } + + deleteOptionObj := &map[string]interface{}{} + if eventPayload.DeleteOption != nil { + deleteOptionJsonData, err := json.Marshal(eventPayload.DeleteOption) + if err != nil { + return nil, nil, nil, fmt.Errorf("failed to marshal deleteOption to json: %v", err) + } + if err := json.Unmarshal(deleteOptionJsonData, deleteOptionObj); err != nil { + return nil, nil, nil, fmt.Errorf("failed to unmarshal deleteOption to cloudevent: %v", err) + } + } + + updateStrategyObj := &map[string]interface{}{} + if eventPayload.ConfigOption != nil && eventPayload.ConfigOption.UpdateStrategy != nil { + updateStrategyJsonData, err := json.Marshal(eventPayload.ConfigOption.UpdateStrategy) + if err != nil { + return nil, nil, nil, fmt.Errorf("failed to marshal updateStrategy to json: %v", err) + } + if err := json.Unmarshal(updateStrategyJsonData, updateStrategyObj); err != nil { + return nil, nil, nil, fmt.Errorf("failed to unmarshal updateStrategy to cloudevent: %v", err) + } + } + + return eventPayload.Manifest.Object, *deleteOptionObj, *updateStrategyObj, nil +} + +// DecodeDeleteOption converts a CloudEvent JSONMap representation of a resoure deleteOption +// into resource deleteOption (map[string]interface{}). +func DecodeDeleteOption(deleteOption datatypes.JSONMap) (map[string]interface{}, error) { + if len(deleteOption) == 0 { + return nil, nil + } + + jsonData, err := deleteOption.MarshalJSON() + if err != nil { + return nil, fmt.Errorf("failed to marshal deleteOption to json: %v", err) + } + + obj := &map[string]interface{}{} + if err := json.Unmarshal(jsonData, obj); err != nil { + return nil, fmt.Errorf("failed to unmarshal deleteOption to cloudevent: %v", err) } - return eventPayload.Manifest.Object, nil + return *obj, nil } // DecodeManifestBundle converts a CloudEvent JSONMap representation of a list of resource manifest diff --git a/pkg/api/resource_types_test.go b/pkg/api/resource_types_test.go index 4f9e8b4e..a667ad93 100644 --- a/pkg/api/resource_types_test.go +++ b/pkg/api/resource_types_test.go @@ -53,34 +53,46 @@ func TestEncodeManifest(t *testing.T) { func TestDecodeManifest(t *testing.T) { cases := []struct { - name string - input datatypes.JSONMap - expected map[string]interface{} - expectedErrorMsg string + name string + input datatypes.JSONMap + expectedManifest map[string]interface{} + expectedDeleteOption map[string]interface{} + expectedUpdateStrategy map[string]interface{} + expectedErrorMsg string }{ { - name: "empty", - input: datatypes.JSONMap{}, - expected: nil, - expectedErrorMsg: "", + name: "empty", + input: datatypes.JSONMap{}, + expectedManifest: nil, + expectedDeleteOption: nil, + expectedUpdateStrategy: nil, + expectedErrorMsg: "", }, { - name: "valid", - input: newJSONMap(t, "{\"specversion\":\"1.0\",\"datacontenttype\":\"application/json\",\"data\":{\"manifest\":{\"apiVersion\":\"v1\",\"kind\":\"ConfigMap\",\"metadata\":{\"name\":\"test\",\"namespace\":\"test\"}}}}"), - expected: newJSONMap(t, "{\"apiVersion\":\"v1\",\"kind\":\"ConfigMap\",\"metadata\":{\"name\":\"test\",\"namespace\":\"test\"}}"), + name: "valid", + input: newJSONMap(t, "{\"specversion\":\"1.0\",\"datacontenttype\":\"application/json\",\"data\":{\"configOption\":{\"updateStrategy\": {\"type\": \"CreateOnly\"}},\"deleteOption\": {\"propagationPolicy\": \"Orphan\"},\"manifest\":{\"apiVersion\":\"v1\",\"kind\":\"ConfigMap\",\"metadata\":{\"name\":\"test\",\"namespace\":\"test\"}}}}"), + expectedManifest: newJSONMap(t, "{\"apiVersion\":\"v1\",\"kind\":\"ConfigMap\",\"metadata\":{\"name\":\"test\",\"namespace\":\"test\"}}"), + expectedDeleteOption: newJSONMap(t, "{\"propagationPolicy\": \"Orphan\"}"), + expectedUpdateStrategy: newJSONMap(t, "{\"type\": \"CreateOnly\"}"), }, } for _, c := range cases { t.Run(c.name, func(t *testing.T) { - gotManifest, err := DecodeManifest(c.input) + gotManifest, gotDeleteOption, gotUpdateStrategy, err := DecodeManifest(c.input) if err != nil { if err.Error() != c.expectedErrorMsg { t.Errorf("expected %#v but got: %#v", c.expectedErrorMsg, err) } return } - if !equality.Semantic.DeepDerivative(c.expected, gotManifest) { - t.Errorf("expected %#v but got: %#v", c.expected, gotManifest) + if !equality.Semantic.DeepDerivative(c.expectedManifest, gotManifest) { + t.Errorf("expected %#v but got: %#v", c.expectedManifest, gotManifest) + } + if !equality.Semantic.DeepDerivative(c.expectedDeleteOption, gotDeleteOption) { + t.Errorf("expected %#v but got: %#v", c.expectedDeleteOption, gotDeleteOption) + } + if !equality.Semantic.DeepDerivative(c.expectedUpdateStrategy, gotUpdateStrategy) { + t.Errorf("expected %#v but got: %#v", c.expectedUpdateStrategy, gotUpdateStrategy) } }) } diff --git a/pkg/services/validation.go b/pkg/services/validation.go index 88e9c457..3ee6bba2 100644 --- a/pkg/services/validation.go +++ b/pkg/services/validation.go @@ -43,7 +43,8 @@ func ValidateConsumer(consumer *api.Consumer) error { func ValidateManifest(resType api.ResourceType, manifest datatypes.JSONMap) error { switch resType { case api.ResourceTypeSingle: - obj, err := api.DecodeManifest(manifest) + // TODO: validate the deleteOption and updateStrategy + obj, _, _, err := api.DecodeManifest(manifest) if err != nil { return fmt.Errorf("failed to decode manifest: %v", err) } @@ -104,11 +105,11 @@ func ValidateObject(obj datatypes.JSONMap) error { func ValidateManifestUpdate(resType api.ResourceType, new, old datatypes.JSONMap) error { switch resType { case api.ResourceTypeSingle: - newObj, err := api.DecodeManifest(new) + newObj, _, _, err := api.DecodeManifest(new) if err != nil { return fmt.Errorf("failed to decode new manifest: %v", err) } - oldObj, err := api.DecodeManifest(old) + oldObj, _, _, err := api.DecodeManifest(old) if err != nil { return fmt.Errorf("failed to decode old manifest: %v", err) } diff --git a/test/grpc_codec.go b/test/grpc_codec.go index 1a2e7a30..fd9292b4 100644 --- a/test/grpc_codec.go +++ b/test/grpc_codec.go @@ -41,7 +41,7 @@ func (c *ResourceCodec) Encode(source string, eventType types.CloudEventsType, r return &evt, nil } - manifest, err := api.DecodeManifest(resource.Manifest) + manifest, _, _, err := api.DecodeManifest(resource.Manifest) if err != nil { return nil, fmt.Errorf("failed to decode manifest: %v", err) } @@ -153,7 +153,7 @@ func (c *ResourceBundleCodec) Encode(source string, eventType types.CloudEventsT return &evt, nil } - manifest, err := api.DecodeManifest(resource.Manifest) + manifest, _, _, err := api.DecodeManifest(resource.Manifest) if err != nil { return nil, fmt.Errorf("failed to decode manifest: %v", err) } From a27f7d4d1699b01f376b54dfbbf1c0b8ef452af8 Mon Sep 17 00:00:00 2001 From: clyang82 Date: Tue, 28 May 2024 14:22:44 +0800 Subject: [PATCH 3/3] Add e2e tests Signed-off-by: clyang82 --- test/e2e/pkg/resources_test.go | 145 ++++++++++++++++++++++++++++++-- test/e2e/pkg/serverside_test.go | 6 ++ 2 files changed, 143 insertions(+), 8 deletions(-) diff --git a/test/e2e/pkg/resources_test.go b/test/e2e/pkg/resources_test.go index 84ab71c0..7e400d6b 100644 --- a/test/e2e/pkg/resources_test.go +++ b/test/e2e/pkg/resources_test.go @@ -15,12 +15,9 @@ import ( var _ = Describe("Resources", Ordered, Label("e2e-tests-resources"), func() { - It("is CRUD tests", func() { - }) - var resource *openapi.Resource - Context("Create Resource", func() { + Context("Resource CRUD Tests", func() { It("post the nginx resource to the maestro api", func() { res := helper.NewAPIResource(consumer_name, 1) @@ -39,9 +36,6 @@ var _ = Describe("Resources", Ordered, Label("e2e-tests-resources"), func() { return nil }, 1*time.Minute, 1*time.Second).ShouldNot(HaveOccurred()) }) - }) - - Context("Patch Resource", func() { It("patch the nginx resource", func() { @@ -63,9 +57,144 @@ var _ = Describe("Resources", Ordered, Label("e2e-tests-resources"), func() { return fmt.Errorf("replicas is not 2") }, 1*time.Minute, 1*time.Second).ShouldNot(HaveOccurred()) }) + + It("delete the nginx resource", func() { + + resp, err := apiClient.DefaultApi.ApiMaestroV1ResourcesIdDelete(context.Background(), *resource.Id).Execute() + Expect(err).ShouldNot(HaveOccurred()) + Expect(resp.StatusCode).To(Equal(http.StatusNoContent)) + + Eventually(func() error { + _, err := kubeClient.AppsV1().Deployments("default").Get(context.Background(), "nginx", metav1.GetOptions{}) + if err != nil { + if errors.IsNotFound(err) { + return nil + } + return err + } + return fmt.Errorf("nginx deployment still exists") + }, 1*time.Minute, 1*time.Second).ShouldNot(HaveOccurred()) + }) + }) + + Context("Resource Delete Option Tests", func() { + res := helper.NewAPIResource(consumer_name, 1) + It("post the nginx resource to the maestro api", func() { + var resp *http.Response + var err error + resource, resp, err = apiClient.DefaultApi.ApiMaestroV1ResourcesPost(context.Background()).Resource(res).Execute() + Expect(err).ShouldNot(HaveOccurred()) + Expect(resp.StatusCode).To(Equal(http.StatusCreated)) + Expect(*resource.Id).ShouldNot(BeEmpty()) + + Eventually(func() error { + _, err := kubeClient.AppsV1().Deployments("default").Get(context.Background(), "nginx", metav1.GetOptions{}) + if err != nil { + return err + } + return nil + }, 1*time.Minute, 1*time.Second).ShouldNot(HaveOccurred()) + }) + + It("patch the nginx resource with orphan delete option", func() { + + patchedResource, resp, err := apiClient.DefaultApi.ApiMaestroV1ResourcesIdPatch(context.Background(), *resource.Id). + ResourcePatchRequest(openapi.ResourcePatchRequest{Version: resource.Version, Manifest: res.Manifest, DeleteOption: map[string]interface{}{"propagationPolicy": "Orphan"}}).Execute() + Expect(err).ShouldNot(HaveOccurred()) + Expect(resp.StatusCode).To(Equal(http.StatusOK)) + Expect(*patchedResource.Version).To(Equal(*resource.Version + 1)) + + }) + + It("delete the nginx resource from the maestro api", func() { + + resp, err := apiClient.DefaultApi.ApiMaestroV1ResourcesIdDelete(context.Background(), *resource.Id).Execute() + Expect(err).ShouldNot(HaveOccurred()) + Expect(resp.StatusCode).To(Equal(http.StatusNoContent)) + + retry := 0 + Eventually(func() error { + // Attempt to retrieve the "nginx" deployment in the "default" namespace + _, err := kubeClient.AppsV1().Deployments("default").Get(context.Background(), "nginx", metav1.GetOptions{}) + + // If an error occurs + if err != nil { + // Return any other errors directly + return err + } + + // Increment the retry counter + retry++ + + // If the retry count reaches 30, consider it successful + if retry == 30 { + return nil + } + + // Otherwise, indicate that another retry is needed + return fmt.Errorf("need to retry again") + }, 1*time.Minute, 1*time.Second).ShouldNot(HaveOccurred()) + }) + + It("delete the nginx deployment", func() { + err := kubeClient.AppsV1().Deployments("default").Delete(context.Background(), "nginx", metav1.DeleteOptions{}) + Expect(err).ShouldNot(HaveOccurred()) + + Eventually(func() error { + _, err := kubeClient.AppsV1().Deployments("default").Get(context.Background(), "nginx", metav1.GetOptions{}) + if err != nil { + if errors.IsNotFound(err) { + return nil + } + return err + } + return fmt.Errorf("nginx deployment still exists") + }, 1*time.Minute, 1*time.Second).ShouldNot(HaveOccurred()) + }) + }) - Context("Delete Resource", func() { + Context("Resource Update Strategy Tests", func() { + + It("post the nginx resource to the maestro api with createOnly updateStrategy", func() { + res := helper.NewAPIResource(consumer_name, 1) + var resp *http.Response + var err error + res.UpdateStrategy = map[string]interface{}{"type": "CreateOnly"} + resource, resp, err = apiClient.DefaultApi.ApiMaestroV1ResourcesPost(context.Background()).Resource(res).Execute() + Expect(err).ShouldNot(HaveOccurred()) + Expect(resp.StatusCode).To(Equal(http.StatusCreated)) + Expect(*resource.Id).ShouldNot(BeEmpty()) + + Eventually(func() error { + _, err := kubeClient.AppsV1().Deployments("default").Get(context.Background(), "nginx", metav1.GetOptions{}) + if err != nil { + return err + } + return nil + }, 1*time.Minute, 1*time.Second).ShouldNot(HaveOccurred()) + }) + + It("patch the nginx resource", func() { + + newRes := helper.NewAPIResource(consumer_name, 2) + patchedResource, resp, err := apiClient.DefaultApi.ApiMaestroV1ResourcesIdPatch(context.Background(), *resource.Id). + ResourcePatchRequest(openapi.ResourcePatchRequest{Version: resource.Version, Manifest: newRes.Manifest}).Execute() + Expect(err).ShouldNot(HaveOccurred()) + Expect(resp.StatusCode).To(Equal(http.StatusOK)) + Expect(*patchedResource.Version).To(Equal(*resource.Version + 1)) + + Eventually(func() error { + deploy, err := kubeClient.AppsV1().Deployments("default").Get(context.Background(), "nginx", metav1.GetOptions{}) + if err != nil { + return err + } + if *deploy.Spec.Replicas == 1 { + return nil + } + return fmt.Errorf("replicas is not 1") + }, 1*time.Minute, 1*time.Second).ShouldNot(HaveOccurred()) + }) It("delete the nginx resource", func() { diff --git a/test/e2e/pkg/serverside_test.go b/test/e2e/pkg/serverside_test.go index b164992b..61675c22 100644 --- a/test/e2e/pkg/serverside_test.go +++ b/test/e2e/pkg/serverside_test.go @@ -103,5 +103,11 @@ var _ = Describe("Server Side Apply", func() { return nil }, 1*time.Minute, 1*time.Second).ShouldNot(HaveOccurred()) + + // cleanup the job + resp, err = apiClient.DefaultApi.ApiMaestroV1ResourcesIdDelete(context.Background(), resourceID).Execute() + Expect(err).ShouldNot(HaveOccurred()) + Expect(resp.StatusCode).To(Equal(http.StatusNoContent)) + }) })