diff --git a/cmd/maestro/server/grpc_server.go b/cmd/maestro/server/grpc_server.go index da1f3df3..6c09f0d5 100644 --- a/cmd/maestro/server/grpc_server.go +++ b/cmd/maestro/server/grpc_server.go @@ -226,11 +226,11 @@ func decode(eventDataType types.CloudEventsDataType, evt *ce.Event) (*api.Resour resource.Meta.DeletedAt.Time = deletionTimestamp } - manifest, err := api.CloudEventToJSONMap(evt) + payload, err := api.CloudEventToJSONMap(evt) if err != nil { - return nil, fmt.Errorf("failed to convert cloudevent to resource manifest: %v", err) + return nil, fmt.Errorf("failed to convert cloudevent to resource payload: %v", err) } - resource.Manifest = manifest + resource.Payload = payload switch eventDataType { case workpayload.ManifestEventDataType: diff --git a/data/generated/openapi/openapi.go b/data/generated/openapi/openapi.go index ce159dfb..56afae67 100755 --- a/data/generated/openapi/openapi.go +++ b/data/generated/openapi/openapi.go @@ -92,7 +92,7 @@ func openapiYaml() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "openapi.yaml", size: 22337, mode: os.FileMode(493), modTime: time.Unix(1717126081, 0)} + info := bindataFileInfo{name: "openapi.yaml", size: 22337, mode: os.FileMode(493), modTime: time.Unix(1717473157, 0)} a := &asset{bytes: bytes, info: info} return a, nil } diff --git a/pkg/api/presenters/resource.go b/pkg/api/presenters/resource.go index b3e18093..f0292e8b 100755 --- a/pkg/api/presenters/resource.go +++ b/pkg/api/presenters/resource.go @@ -14,7 +14,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, resource.DeleteOption, resource.UpdateStrategy) + payload, err := ConvertResourceManifest(resource.Manifest, resource.DeleteOption, resource.UpdateStrategy) if err != nil { return nil, err } @@ -26,9 +26,9 @@ func ConvertResource(resource openapi.Resource) (*api.Resource, error) { ConsumerName: util.NilToEmptyString(resource.ConsumerName), Version: util.NilToEmptyInt32(resource.Version), // Set the default source ID for RESTful API calls and do not allow modification - Source: constants.DefaultSourceID, - Type: api.ResourceTypeSingle, - Manifest: manifest, + Source: constants.DefaultSourceID, + Type: api.ResourceTypeSingle, + Payload: payload, }, nil } @@ -39,7 +39,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, deleteOption, updateStrategy, err := api.DecodeManifest(resource.Manifest) + manifest, deleteOption, updateStrategy, err := api.DecodeManifest(resource.Payload) if err != nil { return nil, err } @@ -66,7 +66,7 @@ func PresentResource(resource *api.Resource) (*openapi.Resource, error) { // PresentResourceBundle converts a resource from the API to the openapi representation. func PresentResourceBundle(resource *api.Resource) (*openapi.ResourceBundle, error) { - manifestBundle, err := api.DecodeManifestBundle(resource.Manifest) + manifestBundle, err := api.DecodeManifestBundle(resource.Payload) if err != nil { return nil, err } diff --git a/pkg/api/resource_types.go b/pkg/api/resource_types.go index 292e70a6..165cba0f 100755 --- a/pkg/api/resource_types.go +++ b/pkg/api/resource_types.go @@ -31,7 +31,7 @@ type Resource struct { Source string ConsumerName string Type ResourceType - Manifest datatypes.JSONMap + Payload datatypes.JSONMap Status datatypes.JSONMap // Name must be unique and not null, it can be treated as the resource external ID. // The format of the name should be follow the RFC 1123 (same as the k8s namespace). diff --git a/pkg/client/cloudevents/bundle_codec.go b/pkg/client/cloudevents/bundle_codec.go index e0e23194..4dddabc8 100644 --- a/pkg/client/cloudevents/bundle_codec.go +++ b/pkg/client/cloudevents/bundle_codec.go @@ -23,9 +23,9 @@ func (codec *BundleCodec) EventDataType() cetypes.CloudEventsDataType { } func (codec *BundleCodec) Encode(source string, eventType cetypes.CloudEventsType, res *api.Resource) (*cloudevents.Event, error) { - evt, err := api.JSONMAPToCloudEvent(res.Manifest) + evt, err := api.JSONMAPToCloudEvent(res.Payload) if err != nil { - return nil, fmt.Errorf("failed to convert resource manifest to cloudevent: %v", err) + return nil, fmt.Errorf("failed to convert resource payload to cloudevent: %v", err) } evt.SetSource(source) diff --git a/pkg/client/cloudevents/codec.go b/pkg/client/cloudevents/codec.go index 397999df..bb3ad50a 100644 --- a/pkg/client/cloudevents/codec.go +++ b/pkg/client/cloudevents/codec.go @@ -23,9 +23,9 @@ func (codec *Codec) EventDataType() cetypes.CloudEventsDataType { } func (codec *Codec) Encode(source string, eventType cetypes.CloudEventsType, res *api.Resource) (*cloudevents.Event, error) { - evt, err := api.JSONMAPToCloudEvent(res.Manifest) + evt, err := api.JSONMAPToCloudEvent(res.Payload) if err != nil { - return nil, fmt.Errorf("failed to convert resource manifest to cloudevent: %v", err) + return nil, fmt.Errorf("failed to convert resource payload to cloudevent: %v", err) } evt.SetSource(source) diff --git a/pkg/db/migrations/202311151850_add_resources.go b/pkg/db/migrations/202311151850_add_resources.go index c91ce206..807bbebe 100755 --- a/pkg/db/migrations/202311151850_add_resources.go +++ b/pkg/db/migrations/202311151850_add_resources.go @@ -18,8 +18,8 @@ func addResources() *gormigrate.Migration { // "Single" resource type for RESTful API calls, // "Bundle" resource type mainly for gRPC calls. Type string `gorm:"index"` - // Manifest holds the resource manifest in CloudEvent format (JSON representation). - Manifest datatypes.JSON `gorm:"type:json"` + // Payload is CloudEvent payload with CloudEvent format (JSON representation). + Payload datatypes.JSON `gorm:"type:json"` // Status represents the resource status in CloudEvent format (JSON representation). Status datatypes.JSON `gorm:"type:json"` } diff --git a/pkg/handlers/resource.go b/pkg/handlers/resource.go index 8056a72c..d225e148 100755 --- a/pkg/handlers/resource.go +++ b/pkg/handlers/resource.go @@ -70,15 +70,15 @@ 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, patch.DeleteOption, patch.UpdateStrategy) + payload, err := presenters.ConvertResourceManifest(patch.Manifest, patch.DeleteOption, patch.UpdateStrategy) if err != nil { return nil, errors.GeneralError("failed to convert resource manifest: %s", err) } resource, serviceErr := h.resource.Update(ctx, &api.Resource{ - Meta: api.Meta{ID: id}, - Version: *patch.Version, - Type: api.ResourceTypeSingle, - Manifest: manifest, + Meta: api.Meta{ID: id}, + Version: *patch.Version, + Type: api.ResourceTypeSingle, + Payload: payload, }) if serviceErr != nil { return nil, serviceErr diff --git a/pkg/services/resource.go b/pkg/services/resource.go index a87c7492..f7cb7c52 100755 --- a/pkg/services/resource.go +++ b/pkg/services/resource.go @@ -70,7 +70,7 @@ func (s *sqlResourceService) Create(ctx context.Context, resource *api.Resource) return nil, errors.Validation("the name in the resource is invalid, %v", err) } } - if err := ValidateManifest(resource.Type, resource.Manifest); err != nil { + if err := ValidateManifest(resource.Type, resource.Payload); err != nil { return nil, errors.Validation("the manifest in the resource is invalid, %v", err) } @@ -113,17 +113,17 @@ func (s *sqlResourceService) Update(ctx context.Context, resource *api.Resource) } // New manifest is not changed, the update action is not needed. - if reflect.DeepEqual(resource.Manifest, found.Manifest) { + if reflect.DeepEqual(resource.Payload, found.Payload) { return found, nil } - if err := ValidateManifestUpdate(resource.Type, resource.Manifest, found.Manifest); err != nil { + if err := ValidateManifestUpdate(resource.Type, resource.Payload, found.Payload); err != nil { return nil, errors.Validation("the new manifest in the resource is invalid, %v", err) } // Increase the current resource version and update its manifest. found.Version = found.Version + 1 - found.Manifest = resource.Manifest + found.Payload = resource.Payload updated, err := s.resourceDao.Update(ctx, found) if err != nil { diff --git a/pkg/services/resource_test.go b/pkg/services/resource_test.go index 718e7c44..07e7ee3f 100755 --- a/pkg/services/resource_test.go +++ b/pkg/services/resource_test.go @@ -23,13 +23,13 @@ func TestResourceFindByConsumerID(t *testing.T) { const Breviceratops = "c4df9ff0-bfeb-5bc6-a0ab-4c9128d698b4" resources := api.ResourceList{ - &api.Resource{ConsumerName: Fukuisaurus, Type: api.ResourceTypeSingle, Manifest: newManifest(t, "{\"id\":\"75479c10-b537-4261-8058-ca2e36bac384\",\"time\":\"2024-03-07T03:29:03.194843266Z\",\"type\":\"io.open-cluster-management.works.v1alpha1.manifests.spec.create_request\",\"source\":\"maestro\",\"specversion\":\"1.0\",\"datacontenttype\":\"application/json\",\"data\":{\"manifest\":{\"apiVersion\":\"v1\",\"kind\":\"ConfigMap\",\"metadata\":{\"name\":\"test\",\"namespace\":\"test\"}}}}")}, - &api.Resource{ConsumerName: Fukuisaurus, Type: api.ResourceTypeBundle, Manifest: newManifest(t, "{\"id\":\"266a8cd2-2fab-4e89-9bf0-a56425ebcdf8\",\"time\":\"2024-02-05T17:31:05Z\",\"type\":\"io.open-cluster-management.works.v1alpha1.manifestbundles.spec.create_request\",\"source\":\"grpc\",\"specversion\":\"1.0\",\"datacontenttype\":\"application/json\",\"resourceid\":\"c4df9ff0-bfeb-5bc6-a0ab-4c9128d698b4\",\"clustername\":\"b288a9da-8bfe-4c82-94cc-2b48e773fc46\",\"resourceversion\":1,\"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\"}}]}}")}, - &api.Resource{ConsumerName: Fukuisaurus, Type: api.ResourceTypeSingle, Manifest: newManifest(t, "{\"id\":\"75479c10-b537-4261-8058-ca2e36bac384\",\"time\":\"2024-03-07T03:29:03.194843266Z\",\"type\":\"io.open-cluster-management.works.v1alpha1.manifests.spec.create_request\",\"source\":\"maestro\",\"specversion\":\"1.0\",\"datacontenttype\":\"application/json\",\"data\":{\"manifest\":{\"apiVersion\":\"v1\",\"kind\":\"ConfigMap\",\"metadata\":{\"name\":\"test\",\"namespace\":\"test\"}}}}")}, - &api.Resource{ConsumerName: Seismosaurus, Type: api.ResourceTypeSingle, Manifest: newManifest(t, "{\"id\":\"75479c10-b537-4261-8058-ca2e36bac384\",\"time\":\"2024-03-07T03:29:03.194843266Z\",\"type\":\"io.open-cluster-management.works.v1alpha1.manifests.spec.create_request\",\"source\":\"maestro\",\"specversion\":\"1.0\",\"datacontenttype\":\"application/json\",\"data\":{\"manifest\":{\"apiVersion\":\"v1\",\"kind\":\"ConfigMap\",\"metadata\":{\"name\":\"test\",\"namespace\":\"test\"}}}}")}, - &api.Resource{ConsumerName: Seismosaurus, Type: api.ResourceTypeBundle, Manifest: newManifest(t, "{\"id\":\"266a8cd2-2fab-4e89-9bf0-a56425ebcdf8\",\"time\":\"2024-02-05T17:31:05Z\",\"type\":\"io.open-cluster-management.works.v1alpha1.manifestbundles.spec.create_request\",\"source\":\"grpc\",\"specversion\":\"1.0\",\"datacontenttype\":\"application/json\",\"resourceid\":\"c4df9ff0-bfeb-5bc6-a0ab-4c9128d698b4\",\"clustername\":\"e3eb7db1-b124-4a4d-8bb6-cc779c01b402\",\"resourceversion\":1,\"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\"}}]}}")}, - &api.Resource{ConsumerName: Breviceratops, Type: api.ResourceTypeSingle, Manifest: newManifest(t, "{\"id\":\"75479c10-b537-4261-8058-ca2e36bac384\",\"time\":\"2024-03-07T03:29:03.194843266Z\",\"type\":\"io.open-cluster-management.works.v1alpha1.manifests.spec.create_request\",\"source\":\"maestro\",\"specversion\":\"1.0\",\"datacontenttype\":\"application/json\",\"data\":{\"manifest\":{\"apiVersion\":\"v1\",\"kind\":\"ConfigMap\",\"metadata\":{\"name\":\"test\",\"namespace\":\"test\"}}}}")}, - &api.Resource{ConsumerName: Breviceratops, Type: api.ResourceTypeBundle, Manifest: newManifest(t, "{\"id\":\"266a8cd2-2fab-4e89-9bf0-a56425ebcdf8\",\"time\":\"2024-02-05T17:31:05Z\",\"type\":\"io.open-cluster-management.works.v1alpha1.manifestbundles.spec.create_request\",\"source\":\"grpc\",\"specversion\":\"1.0\",\"datacontenttype\":\"application/json\",\"resourceid\":\"c4df9ff0-bfeb-5bc6-a0ab-4c9128d698b4\",\"clustername\":\"c4df9ff0-bfeb-5bc6-a0ab-4c9128d698b4\",\"resourceversion\":1,\"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\"}}]}}")}, + &api.Resource{ConsumerName: Fukuisaurus, Type: api.ResourceTypeSingle, Payload: newPayload(t, "{\"id\":\"75479c10-b537-4261-8058-ca2e36bac384\",\"time\":\"2024-03-07T03:29:03.194843266Z\",\"type\":\"io.open-cluster-management.works.v1alpha1.manifests.spec.create_request\",\"source\":\"maestro\",\"specversion\":\"1.0\",\"datacontenttype\":\"application/json\",\"data\":{\"manifest\":{\"apiVersion\":\"v1\",\"kind\":\"ConfigMap\",\"metadata\":{\"name\":\"test\",\"namespace\":\"test\"}}}}")}, + &api.Resource{ConsumerName: Fukuisaurus, Type: api.ResourceTypeBundle, Payload: newPayload(t, "{\"id\":\"266a8cd2-2fab-4e89-9bf0-a56425ebcdf8\",\"time\":\"2024-02-05T17:31:05Z\",\"type\":\"io.open-cluster-management.works.v1alpha1.manifestbundles.spec.create_request\",\"source\":\"grpc\",\"specversion\":\"1.0\",\"datacontenttype\":\"application/json\",\"resourceid\":\"c4df9ff0-bfeb-5bc6-a0ab-4c9128d698b4\",\"clustername\":\"b288a9da-8bfe-4c82-94cc-2b48e773fc46\",\"resourceversion\":1,\"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\"}}]}}")}, + &api.Resource{ConsumerName: Fukuisaurus, Type: api.ResourceTypeSingle, Payload: newPayload(t, "{\"id\":\"75479c10-b537-4261-8058-ca2e36bac384\",\"time\":\"2024-03-07T03:29:03.194843266Z\",\"type\":\"io.open-cluster-management.works.v1alpha1.manifests.spec.create_request\",\"source\":\"maestro\",\"specversion\":\"1.0\",\"datacontenttype\":\"application/json\",\"data\":{\"manifest\":{\"apiVersion\":\"v1\",\"kind\":\"ConfigMap\",\"metadata\":{\"name\":\"test\",\"namespace\":\"test\"}}}}")}, + &api.Resource{ConsumerName: Seismosaurus, Type: api.ResourceTypeSingle, Payload: newPayload(t, "{\"id\":\"75479c10-b537-4261-8058-ca2e36bac384\",\"time\":\"2024-03-07T03:29:03.194843266Z\",\"type\":\"io.open-cluster-management.works.v1alpha1.manifests.spec.create_request\",\"source\":\"maestro\",\"specversion\":\"1.0\",\"datacontenttype\":\"application/json\",\"data\":{\"manifest\":{\"apiVersion\":\"v1\",\"kind\":\"ConfigMap\",\"metadata\":{\"name\":\"test\",\"namespace\":\"test\"}}}}")}, + &api.Resource{ConsumerName: Seismosaurus, Type: api.ResourceTypeBundle, Payload: newPayload(t, "{\"id\":\"266a8cd2-2fab-4e89-9bf0-a56425ebcdf8\",\"time\":\"2024-02-05T17:31:05Z\",\"type\":\"io.open-cluster-management.works.v1alpha1.manifestbundles.spec.create_request\",\"source\":\"grpc\",\"specversion\":\"1.0\",\"datacontenttype\":\"application/json\",\"resourceid\":\"c4df9ff0-bfeb-5bc6-a0ab-4c9128d698b4\",\"clustername\":\"e3eb7db1-b124-4a4d-8bb6-cc779c01b402\",\"resourceversion\":1,\"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\"}}]}}")}, + &api.Resource{ConsumerName: Breviceratops, Type: api.ResourceTypeSingle, Payload: newPayload(t, "{\"id\":\"75479c10-b537-4261-8058-ca2e36bac384\",\"time\":\"2024-03-07T03:29:03.194843266Z\",\"type\":\"io.open-cluster-management.works.v1alpha1.manifests.spec.create_request\",\"source\":\"maestro\",\"specversion\":\"1.0\",\"datacontenttype\":\"application/json\",\"data\":{\"manifest\":{\"apiVersion\":\"v1\",\"kind\":\"ConfigMap\",\"metadata\":{\"name\":\"test\",\"namespace\":\"test\"}}}}")}, + &api.Resource{ConsumerName: Breviceratops, Type: api.ResourceTypeBundle, Payload: newPayload(t, "{\"id\":\"266a8cd2-2fab-4e89-9bf0-a56425ebcdf8\",\"time\":\"2024-02-05T17:31:05Z\",\"type\":\"io.open-cluster-management.works.v1alpha1.manifestbundles.spec.create_request\",\"source\":\"grpc\",\"specversion\":\"1.0\",\"datacontenttype\":\"application/json\",\"resourceid\":\"c4df9ff0-bfeb-5bc6-a0ab-4c9128d698b4\",\"clustername\":\"c4df9ff0-bfeb-5bc6-a0ab-4c9128d698b4\",\"resourceversion\":1,\"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\"}}]}}")}, } for _, resource := range resources { _, err := resourceService.Create(context.Background(), resource) @@ -55,7 +55,7 @@ func TestCreateInvalidResource(t *testing.T) { events := NewEventService(mocks.NewEventDao()) resourceService := NewResourceService(dbmocks.NewMockAdvisoryLockFactory(), resourceDAO, events) - resource := &api.Resource{ConsumerName: "invalidation", Manifest: newManifest(t, "{}")} + resource := &api.Resource{ConsumerName: "invalidation", Payload: newPayload(t, "{}")} _, svcErr := resourceService.Create(context.Background(), resource) gm.Expect(svcErr).ShouldNot(gm.BeNil()) diff --git a/pkg/services/validation_test.go b/pkg/services/validation_test.go index a727241c..58167773 100644 --- a/pkg/services/validation_test.go +++ b/pkg/services/validation_test.go @@ -96,29 +96,29 @@ func TestValidateNewManifest(t *testing.T) { { name: "validated single manifest", resType: api.ResourceTypeSingle, - manifest: newManifest(t, "{\"id\":\"75479c10-b537-4261-8058-ca2e36bac384\",\"time\":\"2024-03-07T03:29:03.194843266Z\",\"type\":\"io.open-cluster-management.works.v1alpha1.manifests.spec.create_request\",\"source\":\"maestro\",\"specversion\":\"1.0\",\"datacontenttype\":\"application/json\",\"data\":{\"manifest\":{\"apiVersion\":\"v1\",\"kind\":\"ConfigMap\",\"metadata\":{\"name\":\"test\",\"namespace\":\"test\"}}}}"), + manifest: newPayload(t, "{\"id\":\"75479c10-b537-4261-8058-ca2e36bac384\",\"time\":\"2024-03-07T03:29:03.194843266Z\",\"type\":\"io.open-cluster-management.works.v1alpha1.manifests.spec.create_request\",\"source\":\"maestro\",\"specversion\":\"1.0\",\"datacontenttype\":\"application/json\",\"data\":{\"manifest\":{\"apiVersion\":\"v1\",\"kind\":\"ConfigMap\",\"metadata\":{\"name\":\"test\",\"namespace\":\"test\"}}}}"), }, { name: "validated bundle manifest", resType: api.ResourceTypeBundle, - manifest: newManifest(t, "{\"id\":\"266a8cd2-2fab-4e89-9bf0-a56425ebcdf8\",\"time\":\"2024-02-05T17:31:05Z\",\"type\":\"io.open-cluster-management.works.v1alpha1.manifestbundles.spec.create_request\",\"source\":\"grpc\",\"specversion\":\"1.0\",\"datacontenttype\":\"application/json\",\"resourceid\":\"c4df9ff0-bfeb-5bc6-a0ab-4c9128d698b4\",\"clustername\":\"b288a9da-8bfe-4c82-94cc-2b48e773fc46\",\"resourceversion\":1,\"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\"}}]}}"), + manifest: newPayload(t, "{\"id\":\"266a8cd2-2fab-4e89-9bf0-a56425ebcdf8\",\"time\":\"2024-02-05T17:31:05Z\",\"type\":\"io.open-cluster-management.works.v1alpha1.manifestbundles.spec.create_request\",\"source\":\"grpc\",\"specversion\":\"1.0\",\"datacontenttype\":\"application/json\",\"resourceid\":\"c4df9ff0-bfeb-5bc6-a0ab-4c9128d698b4\",\"clustername\":\"b288a9da-8bfe-4c82-94cc-2b48e773fc46\",\"resourceversion\":1,\"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\"}}]}}"), }, { name: "invalidated single manifest", resType: api.ResourceTypeSingle, - manifest: newManifest(t, "{\"id\":\"266a8cd2-2fab-4e89-9bf0-a56425ebcdf8\",\"time\":\"2024-02-05T17:31:05Z\",\"type\":\"io.open-cluster-management.works.v1alpha1.manifestbundles.spec.create_request\",\"source\":\"grpc\",\"specversion\":\"1.0\",\"datacontenttype\":\"application/json\",\"resourceid\":\"c4df9ff0-bfeb-5bc6-a0ab-4c9128d698b4\",\"clustername\":\"b288a9da-8bfe-4c82-94cc-2b48e773fc46\",\"resourceversion\":1,\"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\"}}]}}"), + manifest: newPayload(t, "{\"id\":\"266a8cd2-2fab-4e89-9bf0-a56425ebcdf8\",\"time\":\"2024-02-05T17:31:05Z\",\"type\":\"io.open-cluster-management.works.v1alpha1.manifestbundles.spec.create_request\",\"source\":\"grpc\",\"specversion\":\"1.0\",\"datacontenttype\":\"application/json\",\"resourceid\":\"c4df9ff0-bfeb-5bc6-a0ab-4c9128d698b4\",\"clustername\":\"b288a9da-8bfe-4c82-94cc-2b48e773fc46\",\"resourceversion\":1,\"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\"}}]}}"), expectedErrorMsg: "manifest is empty", }, { name: "invalidated bundle manifest", resType: api.ResourceTypeBundle, - manifest: newManifest(t, "{\"id\":\"75479c10-b537-4261-8058-ca2e36bac384\",\"time\":\"2024-03-07T03:29:03.194843266Z\",\"type\":\"io.open-cluster-management.works.v1alpha1.manifests.spec.create_request\",\"source\":\"maestro\",\"specversion\":\"1.0\",\"datacontenttype\":\"application/json\",\"data\":{\"manifest\":{\"apiVersion\":\"v1\",\"kind\":\"ConfigMap\",\"metadata\":{\"name\":\"test\",\"namespace\":\"test\"}}}}"), + manifest: newPayload(t, "{\"id\":\"75479c10-b537-4261-8058-ca2e36bac384\",\"time\":\"2024-03-07T03:29:03.194843266Z\",\"type\":\"io.open-cluster-management.works.v1alpha1.manifests.spec.create_request\",\"source\":\"maestro\",\"specversion\":\"1.0\",\"datacontenttype\":\"application/json\",\"data\":{\"manifest\":{\"apiVersion\":\"v1\",\"kind\":\"ConfigMap\",\"metadata\":{\"name\":\"test\",\"namespace\":\"test\"}}}}"), expectedErrorMsg: "manifest bundle is empty", }, { name: "invalidated resource type", resType: "invalid", - manifest: newManifest(t, "{\"id\":\"75479c10-b537-4261-8058-ca2e36bac384\",\"time\":\"2024-03-07T03:29:03.194843266Z\",\"type\":\"io.open-cluster-management.works.v1alpha1.manifests.spec.create_request\",\"source\":\"maestro\",\"specversion\":\"1.0\",\"datacontenttype\":\"application/json\",\"data\":{\"manifest\":{\"apiVersion\":\"v1\",\"kind\":\"ConfigMap\",\"metadata\":{\"name\":\"test\",\"namespace\":\"test\"}}}}"), + manifest: newPayload(t, "{\"id\":\"75479c10-b537-4261-8058-ca2e36bac384\",\"time\":\"2024-03-07T03:29:03.194843266Z\",\"type\":\"io.open-cluster-management.works.v1alpha1.manifests.spec.create_request\",\"source\":\"maestro\",\"specversion\":\"1.0\",\"datacontenttype\":\"application/json\",\"data\":{\"manifest\":{\"apiVersion\":\"v1\",\"kind\":\"ConfigMap\",\"metadata\":{\"name\":\"test\",\"namespace\":\"test\"}}}}"), expectedErrorMsg: "unknown resource type: invalid", }, } @@ -141,56 +141,56 @@ func TestValidateNewObject(t *testing.T) { }{ { name: "validated", - manifest: newManifest(t, "{\"apiVersion\":\"v1\",\"kind\":\"ConfigMap\",\"metadata\":{\"name\":\"test\",\"namespace\":\"test\"}}"), + manifest: newPayload(t, "{\"apiVersion\":\"v1\",\"kind\":\"ConfigMap\",\"metadata\":{\"name\":\"test\",\"namespace\":\"test\"}}"), }, { name: "no apiVersion", - manifest: newManifest(t, "{\"kind\":\"ConfigMap\",\"metadata\":{\"name\":\"test\",\"namespace\":\"test\"}}"), + manifest: newPayload(t, "{\"kind\":\"ConfigMap\",\"metadata\":{\"name\":\"test\",\"namespace\":\"test\"}}"), expectedErrorMsg: "apiVersion: Required value: field not set", }, { name: "no kind", - manifest: newManifest(t, "{\"apiVersion\":\"v1\",\"metadata\":{\"name\":\"test\",\"namespace\":\"test\"}}"), + manifest: newPayload(t, "{\"apiVersion\":\"v1\",\"metadata\":{\"name\":\"test\",\"namespace\":\"test\"}}"), expectedErrorMsg: "kind: Required value: field not set", }, { name: "no name", - manifest: newManifest(t, "{\"apiVersion\":\"v1\",\"kind\":\"ConfigMap\",\"metadata\":{\"namespace\":\"test\"}}"), + manifest: newPayload(t, "{\"apiVersion\":\"v1\",\"kind\":\"ConfigMap\",\"metadata\":{\"namespace\":\"test\"}}"), expectedErrorMsg: "metadata.name: Required value: field not set", }, { name: "has generate name", - manifest: newManifest(t, "{\"apiVersion\":\"v1\",\"kind\":\"ConfigMap\",\"metadata\":{\"name\":\"test\",\"generateName\":\"test\",\"namespace\":\"test\"}}"), + manifest: newPayload(t, "{\"apiVersion\":\"v1\",\"kind\":\"ConfigMap\",\"metadata\":{\"name\":\"test\",\"generateName\":\"test\",\"namespace\":\"test\"}}"), expectedErrorMsg: "metadata.generateName: Forbidden: field cannot be set", }, { name: "has resource version", - manifest: newManifest(t, "{\"apiVersion\":\"v1\",\"kind\":\"ConfigMap\",\"metadata\":{\"name\":\"test\",\"resourceVersion\":\"123\",\"namespace\":\"test\"}}"), + manifest: newPayload(t, "{\"apiVersion\":\"v1\",\"kind\":\"ConfigMap\",\"metadata\":{\"name\":\"test\",\"resourceVersion\":\"123\",\"namespace\":\"test\"}}"), expectedErrorMsg: "metadata.resourceVersion: Forbidden: field cannot be set", }, { name: "has deletion grace period seconds", - manifest: newManifest(t, "{\"apiVersion\":\"v1\",\"kind\":\"ConfigMap\",\"metadata\":{\"name\":\"test\",\"deletionGracePeriodSeconds\":10,\"namespace\":\"test\"}}"), + manifest: newPayload(t, "{\"apiVersion\":\"v1\",\"kind\":\"ConfigMap\",\"metadata\":{\"name\":\"test\",\"deletionGracePeriodSeconds\":10,\"namespace\":\"test\"}}"), expectedErrorMsg: "metadata.deletionGracePeriodSeconds: Forbidden: field cannot be set", }, { name: "wrong namespace", - manifest: newManifest(t, "{\"apiVersion\":\"v1\",\"kind\":\"ConfigMap\",\"metadata\":{\"name\":\"test\",\"namespace\":\"_\"}}"), + manifest: newPayload(t, "{\"apiVersion\":\"v1\",\"kind\":\"ConfigMap\",\"metadata\":{\"name\":\"test\",\"namespace\":\"_\"}}"), expectedErrorMsg: "metadata.namespace: Invalid value: \"_\": a lowercase RFC 1123 label must consist of lower case alphanumeric characters or '-', and must start and end with an alphanumeric character (e.g. 'my-name', or '123-abc', regex used for validation is '[a-z0-9]([-a-z0-9]*[a-z0-9])?')", }, { name: "wrong api version (no version)", - manifest: newManifest(t, "{\"apiVersion\":\"apps/\",\"kind\":\"ConfigMap\",\"metadata\":{\"name\":\"test\",\"namespace\":\"test\"}}"), + manifest: newPayload(t, "{\"apiVersion\":\"apps/\",\"kind\":\"ConfigMap\",\"metadata\":{\"name\":\"test\",\"namespace\":\"test\"}}"), expectedErrorMsg: "apiVersion: Invalid value: \"apps/\": version not set", }, { name: "wrong api version (no version)", - manifest: newManifest(t, "{\"apiVersion\":\"/v1\",\"kind\":\"ConfigMap\",\"metadata\":{\"name\":\"test\",\"namespace\":\"test\"}}"), + manifest: newPayload(t, "{\"apiVersion\":\"/v1\",\"kind\":\"ConfigMap\",\"metadata\":{\"name\":\"test\",\"namespace\":\"test\"}}"), expectedErrorMsg: "apiVersion: Invalid value: \"/v1\": group not set", }, { name: "wrong api version", - manifest: newManifest(t, "{\"apiVersion\":\"apps/v1/test\",\"kind\":\"ConfigMap\",\"metadata\":{\"name\":\"test\",\"namespace\":\"test\"}}"), + manifest: newPayload(t, "{\"apiVersion\":\"apps/v1/test\",\"kind\":\"ConfigMap\",\"metadata\":{\"name\":\"test\",\"namespace\":\"test\"}}"), expectedErrorMsg: "apiVersion: Invalid value: \"apps/v1/test\": bad format", }, } @@ -209,48 +209,48 @@ func TestValidateUpdateManifest(t *testing.T) { cases := []struct { name string resType api.ResourceType - newManifest datatypes.JSONMap + newPayload datatypes.JSONMap oldManifest datatypes.JSONMap expectedErrorMsg string }{ { name: "validated single manifest", resType: api.ResourceTypeSingle, - newManifest: newManifest(t, "{\"id\":\"75479c10-b537-4261-8058-ca2e36bac384\",\"time\":\"2024-03-07T03:29:03.194843266Z\",\"type\":\"io.open-cluster-management.works.v1alpha1.manifests.spec.create_request\",\"source\":\"maestro\",\"specversion\":\"1.0\",\"datacontenttype\":\"application/json\",\"data\":{\"manifest\":{\"apiVersion\":\"v1\",\"kind\":\"ConfigMap\",\"metadata\":{\"name\":\"test\",\"namespace\":\"test\"}}}}"), - oldManifest: newManifest(t, "{\"id\":\"75479c10-b537-4261-8058-ca2e36bac384\",\"time\":\"2024-03-07T03:29:03.194843266Z\",\"type\":\"io.open-cluster-management.works.v1alpha1.manifests.spec.create_request\",\"source\":\"maestro\",\"specversion\":\"1.0\",\"datacontenttype\":\"application/json\",\"data\":{\"manifest\":{\"apiVersion\":\"v1\",\"kind\":\"ConfigMap\",\"metadata\":{\"name\":\"test\",\"namespace\":\"test\"}}}}"), + newPayload: newPayload(t, "{\"id\":\"75479c10-b537-4261-8058-ca2e36bac384\",\"time\":\"2024-03-07T03:29:03.194843266Z\",\"type\":\"io.open-cluster-management.works.v1alpha1.manifests.spec.create_request\",\"source\":\"maestro\",\"specversion\":\"1.0\",\"datacontenttype\":\"application/json\",\"data\":{\"manifest\":{\"apiVersion\":\"v1\",\"kind\":\"ConfigMap\",\"metadata\":{\"name\":\"test\",\"namespace\":\"test\"}}}}"), + oldManifest: newPayload(t, "{\"id\":\"75479c10-b537-4261-8058-ca2e36bac384\",\"time\":\"2024-03-07T03:29:03.194843266Z\",\"type\":\"io.open-cluster-management.works.v1alpha1.manifests.spec.create_request\",\"source\":\"maestro\",\"specversion\":\"1.0\",\"datacontenttype\":\"application/json\",\"data\":{\"manifest\":{\"apiVersion\":\"v1\",\"kind\":\"ConfigMap\",\"metadata\":{\"name\":\"test\",\"namespace\":\"test\"}}}}"), }, { name: "validated bundle manifest", resType: api.ResourceTypeBundle, - newManifest: newManifest(t, "{\"id\":\"266a8cd2-2fab-4e89-9bf0-a56425ebcdf8\",\"time\":\"2024-02-05T17:31:05Z\",\"type\":\"io.open-cluster-management.works.v1alpha1.manifestbundles.spec.create_request\",\"source\":\"grpc\",\"specversion\":\"1.0\",\"datacontenttype\":\"application/json\",\"resourceid\":\"c4df9ff0-bfeb-5bc6-a0ab-4c9128d698b4\",\"clustername\":\"b288a9da-8bfe-4c82-94cc-2b48e773fc46\",\"resourceversion\":1,\"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\"}}]}}"), - oldManifest: newManifest(t, "{\"id\":\"266a8cd2-2fab-4e89-9bf0-a56425ebcdf8\",\"time\":\"2024-02-05T17:31:05Z\",\"type\":\"io.open-cluster-management.works.v1alpha1.manifestbundles.spec.create_request\",\"source\":\"grpc\",\"specversion\":\"1.0\",\"datacontenttype\":\"application/json\",\"resourceid\":\"c4df9ff0-bfeb-5bc6-a0ab-4c9128d698b4\",\"clustername\":\"b288a9da-8bfe-4c82-94cc-2b48e773fc46\",\"resourceversion\":1,\"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\"}}]}}"), + newPayload: newPayload(t, "{\"id\":\"266a8cd2-2fab-4e89-9bf0-a56425ebcdf8\",\"time\":\"2024-02-05T17:31:05Z\",\"type\":\"io.open-cluster-management.works.v1alpha1.manifestbundles.spec.create_request\",\"source\":\"grpc\",\"specversion\":\"1.0\",\"datacontenttype\":\"application/json\",\"resourceid\":\"c4df9ff0-bfeb-5bc6-a0ab-4c9128d698b4\",\"clustername\":\"b288a9da-8bfe-4c82-94cc-2b48e773fc46\",\"resourceversion\":1,\"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\"}}]}}"), + oldManifest: newPayload(t, "{\"id\":\"266a8cd2-2fab-4e89-9bf0-a56425ebcdf8\",\"time\":\"2024-02-05T17:31:05Z\",\"type\":\"io.open-cluster-management.works.v1alpha1.manifestbundles.spec.create_request\",\"source\":\"grpc\",\"specversion\":\"1.0\",\"datacontenttype\":\"application/json\",\"resourceid\":\"c4df9ff0-bfeb-5bc6-a0ab-4c9128d698b4\",\"clustername\":\"b288a9da-8bfe-4c82-94cc-2b48e773fc46\",\"resourceversion\":1,\"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\"}}]}}"), }, { name: "invalidated single manifest", resType: api.ResourceTypeSingle, - newManifest: newManifest(t, "{\"id\":\"266a8cd2-2fab-4e89-9bf0-a56425ebcdf8\",\"time\":\"2024-02-05T17:31:05Z\",\"type\":\"io.open-cluster-management.works.v1alpha1.manifestbundles.spec.create_request\",\"source\":\"grpc\",\"specversion\":\"1.0\",\"datacontenttype\":\"application/json\",\"resourceid\":\"c4df9ff0-bfeb-5bc6-a0ab-4c9128d698b4\",\"clustername\":\"b288a9da-8bfe-4c82-94cc-2b48e773fc46\",\"resourceversion\":1,\"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\"}}]}}"), - oldManifest: newManifest(t, "{\"id\":\"75479c10-b537-4261-8058-ca2e36bac384\",\"time\":\"2024-03-07T03:29:03.194843266Z\",\"type\":\"io.open-cluster-management.works.v1alpha1.manifests.spec.create_request\",\"source\":\"maestro\",\"specversion\":\"1.0\",\"datacontenttype\":\"application/json\",\"data\":{\"manifest\":{\"apiVersion\":\"v1\",\"kind\":\"ConfigMap\",\"metadata\":{\"name\":\"test\",\"namespace\":\"test\"}}}}"), + newPayload: newPayload(t, "{\"id\":\"266a8cd2-2fab-4e89-9bf0-a56425ebcdf8\",\"time\":\"2024-02-05T17:31:05Z\",\"type\":\"io.open-cluster-management.works.v1alpha1.manifestbundles.spec.create_request\",\"source\":\"grpc\",\"specversion\":\"1.0\",\"datacontenttype\":\"application/json\",\"resourceid\":\"c4df9ff0-bfeb-5bc6-a0ab-4c9128d698b4\",\"clustername\":\"b288a9da-8bfe-4c82-94cc-2b48e773fc46\",\"resourceversion\":1,\"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\"}}]}}"), + oldManifest: newPayload(t, "{\"id\":\"75479c10-b537-4261-8058-ca2e36bac384\",\"time\":\"2024-03-07T03:29:03.194843266Z\",\"type\":\"io.open-cluster-management.works.v1alpha1.manifests.spec.create_request\",\"source\":\"maestro\",\"specversion\":\"1.0\",\"datacontenttype\":\"application/json\",\"data\":{\"manifest\":{\"apiVersion\":\"v1\",\"kind\":\"ConfigMap\",\"metadata\":{\"name\":\"test\",\"namespace\":\"test\"}}}}"), expectedErrorMsg: "new or old manifest is empty", }, { name: "invalidated bundle manifest", resType: api.ResourceTypeBundle, - newManifest: newManifest(t, "{\"id\":\"75479c10-b537-4261-8058-ca2e36bac384\",\"time\":\"2024-03-07T03:29:03.194843266Z\",\"type\":\"io.open-cluster-management.works.v1alpha1.manifests.spec.create_request\",\"source\":\"maestro\",\"specversion\":\"1.0\",\"datacontenttype\":\"application/json\",\"data\":{\"manifest\":{\"apiVersion\":\"v1\",\"kind\":\"ConfigMap\",\"metadata\":{\"name\":\"test\",\"namespace\":\"test\"}}}}"), - oldManifest: newManifest(t, "{\"id\":\"75479c10-b537-4261-8058-ca2e36bac384\",\"time\":\"2024-03-07T03:29:03.194843266Z\",\"type\":\"io.open-cluster-management.works.v1alpha1.manifests.spec.create_request\",\"source\":\"maestro\",\"specversion\":\"1.0\",\"datacontenttype\":\"application/json\",\"data\":{\"manifest\":{\"apiVersion\":\"v1\",\"kind\":\"ConfigMap\",\"metadata\":{\"name\":\"test\",\"namespace\":\"test\"}}}}"), + newPayload: newPayload(t, "{\"id\":\"75479c10-b537-4261-8058-ca2e36bac384\",\"time\":\"2024-03-07T03:29:03.194843266Z\",\"type\":\"io.open-cluster-management.works.v1alpha1.manifests.spec.create_request\",\"source\":\"maestro\",\"specversion\":\"1.0\",\"datacontenttype\":\"application/json\",\"data\":{\"manifest\":{\"apiVersion\":\"v1\",\"kind\":\"ConfigMap\",\"metadata\":{\"name\":\"test\",\"namespace\":\"test\"}}}}"), + oldManifest: newPayload(t, "{\"id\":\"75479c10-b537-4261-8058-ca2e36bac384\",\"time\":\"2024-03-07T03:29:03.194843266Z\",\"type\":\"io.open-cluster-management.works.v1alpha1.manifests.spec.create_request\",\"source\":\"maestro\",\"specversion\":\"1.0\",\"datacontenttype\":\"application/json\",\"data\":{\"manifest\":{\"apiVersion\":\"v1\",\"kind\":\"ConfigMap\",\"metadata\":{\"name\":\"test\",\"namespace\":\"test\"}}}}"), expectedErrorMsg: "new or old manifest bundle is empty", }, { name: "invalidated resource type", resType: "invalid", - newManifest: newManifest(t, "{\"id\":\"75479c10-b537-4261-8058-ca2e36bac384\",\"time\":\"2024-03-07T03:29:03.194843266Z\",\"type\":\"io.open-cluster-management.works.v1alpha1.manifests.spec.create_request\",\"source\":\"maestro\",\"specversion\":\"1.0\",\"datacontenttype\":\"application/json\",\"data\":{\"manifest\":{\"apiVersion\":\"v1\",\"kind\":\"ConfigMap\",\"metadata\":{\"name\":\"test\",\"namespace\":\"test\"}}}}"), - oldManifest: newManifest(t, "{\"id\":\"75479c10-b537-4261-8058-ca2e36bac384\",\"time\":\"2024-03-07T03:29:03.194843266Z\",\"type\":\"io.open-cluster-management.works.v1alpha1.manifests.spec.create_request\",\"source\":\"maestro\",\"specversion\":\"1.0\",\"datacontenttype\":\"application/json\",\"data\":{\"manifest\":{\"apiVersion\":\"v1\",\"kind\":\"ConfigMap\",\"metadata\":{\"name\":\"test\",\"namespace\":\"test\"}}}}"), + newPayload: newPayload(t, "{\"id\":\"75479c10-b537-4261-8058-ca2e36bac384\",\"time\":\"2024-03-07T03:29:03.194843266Z\",\"type\":\"io.open-cluster-management.works.v1alpha1.manifests.spec.create_request\",\"source\":\"maestro\",\"specversion\":\"1.0\",\"datacontenttype\":\"application/json\",\"data\":{\"manifest\":{\"apiVersion\":\"v1\",\"kind\":\"ConfigMap\",\"metadata\":{\"name\":\"test\",\"namespace\":\"test\"}}}}"), + oldManifest: newPayload(t, "{\"id\":\"75479c10-b537-4261-8058-ca2e36bac384\",\"time\":\"2024-03-07T03:29:03.194843266Z\",\"type\":\"io.open-cluster-management.works.v1alpha1.manifests.spec.create_request\",\"source\":\"maestro\",\"specversion\":\"1.0\",\"datacontenttype\":\"application/json\",\"data\":{\"manifest\":{\"apiVersion\":\"v1\",\"kind\":\"ConfigMap\",\"metadata\":{\"name\":\"test\",\"namespace\":\"test\"}}}}"), expectedErrorMsg: "unknown resource type: invalid", }, } for _, c := range cases { t.Run(c.name, func(t *testing.T) { - err := ValidateManifestUpdate(c.resType, c.newManifest, c.oldManifest) + err := ValidateManifestUpdate(c.resType, c.newPayload, c.oldManifest) if err != nil && err.Error() != c.expectedErrorMsg { t.Errorf("expected %#v but got: %#v", c.expectedErrorMsg, err) } @@ -261,44 +261,44 @@ func TestValidateUpdateManifest(t *testing.T) { func TestValidateUpdateObject(t *testing.T) { cases := []struct { name string - newManifest datatypes.JSONMap + newPayload datatypes.JSONMap oldManifest datatypes.JSONMap expectedErrorMsg string }{ { name: "validated", - newManifest: newManifest(t, "{\"apiVersion\":\"v1\",\"kind\":\"ConfigMap\",\"metadata\":{\"name\":\"test\",\"namespace\":\"test\"}}"), - oldManifest: newManifest(t, "{\"apiVersion\":\"v1\",\"kind\":\"ConfigMap\",\"metadata\":{\"name\":\"test\",\"namespace\":\"test\"}}"), + newPayload: newPayload(t, "{\"apiVersion\":\"v1\",\"kind\":\"ConfigMap\",\"metadata\":{\"name\":\"test\",\"namespace\":\"test\"}}"), + oldManifest: newPayload(t, "{\"apiVersion\":\"v1\",\"kind\":\"ConfigMap\",\"metadata\":{\"name\":\"test\",\"namespace\":\"test\"}}"), }, { name: "apiVersion mismatch", - newManifest: newManifest(t, "{\"apiVersion\":\"v2\",\"kind\":\"ConfigMap\",\"metadata\":{\"name\":\"test\",\"namespace\":\"test\"}}"), - oldManifest: newManifest(t, "{\"apiVersion\":\"v1\",\"kind\":\"ConfigMap\",\"metadata\":{\"name\":\"test\",\"namespace\":\"test\"}}"), + newPayload: newPayload(t, "{\"apiVersion\":\"v2\",\"kind\":\"ConfigMap\",\"metadata\":{\"name\":\"test\",\"namespace\":\"test\"}}"), + oldManifest: newPayload(t, "{\"apiVersion\":\"v1\",\"kind\":\"ConfigMap\",\"metadata\":{\"name\":\"test\",\"namespace\":\"test\"}}"), expectedErrorMsg: "apiVersion: Invalid value: \"v2\": field is immutable", }, { name: "kind mismatch", - newManifest: newManifest(t, "{\"apiVersion\":\"v1\",\"kind\":\"Test\",\"metadata\":{\"name\":\"test\",\"namespace\":\"test\"}}"), - oldManifest: newManifest(t, "{\"apiVersion\":\"v1\",\"kind\":\"ConfigMap\",\"metadata\":{\"name\":\"test\",\"namespace\":\"test\"}}"), + newPayload: newPayload(t, "{\"apiVersion\":\"v1\",\"kind\":\"Test\",\"metadata\":{\"name\":\"test\",\"namespace\":\"test\"}}"), + oldManifest: newPayload(t, "{\"apiVersion\":\"v1\",\"kind\":\"ConfigMap\",\"metadata\":{\"name\":\"test\",\"namespace\":\"test\"}}"), expectedErrorMsg: "kind: Invalid value: \"Test\": field is immutable", }, { name: "name mismatch", - newManifest: newManifest(t, "{\"apiVersion\":\"v1\",\"kind\":\"ConfigMap\",\"metadata\":{\"name\":\"test2\",\"namespace\":\"test\"}}"), - oldManifest: newManifest(t, "{\"apiVersion\":\"v1\",\"kind\":\"ConfigMap\",\"metadata\":{\"name\":\"test1\",\"namespace\":\"test\"}}"), + newPayload: newPayload(t, "{\"apiVersion\":\"v1\",\"kind\":\"ConfigMap\",\"metadata\":{\"name\":\"test2\",\"namespace\":\"test\"}}"), + oldManifest: newPayload(t, "{\"apiVersion\":\"v1\",\"kind\":\"ConfigMap\",\"metadata\":{\"name\":\"test1\",\"namespace\":\"test\"}}"), expectedErrorMsg: "metadata.name: Invalid value: \"test2\": field is immutable", }, { name: "namespace mismatch", - newManifest: newManifest(t, "{\"apiVersion\":\"v1\",\"kind\":\"ConfigMap\",\"metadata\":{\"name\":\"test\",\"namespace\":\"test2\"}}"), - oldManifest: newManifest(t, "{\"apiVersion\":\"v1\",\"kind\":\"ConfigMap\",\"metadata\":{\"name\":\"test\",\"namespace\":\"test1\"}}"), + newPayload: newPayload(t, "{\"apiVersion\":\"v1\",\"kind\":\"ConfigMap\",\"metadata\":{\"name\":\"test\",\"namespace\":\"test2\"}}"), + oldManifest: newPayload(t, "{\"apiVersion\":\"v1\",\"kind\":\"ConfigMap\",\"metadata\":{\"name\":\"test\",\"namespace\":\"test1\"}}"), expectedErrorMsg: "metadata.namespace: Invalid value: \"test2\": field is immutable", }, } for _, c := range cases { t.Run(c.name, func(t *testing.T) { - err := ValidateObjectUpdate(c.newManifest, c.oldManifest) + err := ValidateObjectUpdate(c.newPayload, c.oldManifest) if err != nil && err.Error() != c.expectedErrorMsg { t.Errorf("expected %#v but got: %#v", c.expectedErrorMsg, err) } @@ -306,13 +306,13 @@ func TestValidateUpdateObject(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 newPayload(t *testing.T, data string) datatypes.JSONMap { + payload := map[string]interface{}{} + if err := json.Unmarshal([]byte(data), &payload); err != nil { t.Fatal(err) } - return manifest + return payload } func maxName() string { diff --git a/test/factories.go b/test/factories.go index f1952cf3..84699059 100755 --- a/test/factories.go +++ b/test/factories.go @@ -66,7 +66,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, testResource.DeleteOption, testResource.UpdateStrategy) + testPayload, err := api.EncodeManifest(testResource.Manifest, testResource.DeleteOption, testResource.UpdateStrategy) if err != nil { helper.T.Errorf("error encoding manifest: %q", err) } @@ -74,7 +74,7 @@ func (helper *Helper) NewResource(consumerName string, replicas int) *api.Resour resource := &api.Resource{ ConsumerName: consumerName, Type: api.ResourceTypeSingle, - Manifest: testManifest, + Payload: testPayload, Version: 1, } @@ -164,7 +164,7 @@ func (helper *Helper) EncodeManifestBundle(manifest map[string]interface{}) (dat func (helper *Helper) NewResourceBundle(name, consumerName string, replicas int) *api.Resource { testResource := helper.NewAPIResource(consumerName, replicas) - testManifest, err := helper.EncodeManifestBundle(testResource.Manifest) + testPayload, err := helper.EncodeManifestBundle(testResource.Manifest) if err != nil { helper.T.Errorf("error encoding manifest bundle: %q", err) } @@ -173,7 +173,7 @@ func (helper *Helper) NewResourceBundle(name, consumerName string, replicas int) Name: name, ConsumerName: consumerName, Type: api.ResourceTypeBundle, - Manifest: testManifest, + Payload: testPayload, Version: 1, } diff --git a/test/grpc_codec.go b/test/grpc_codec.go index fd9292b4..fbd93727 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.Payload) 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.Payload) if err != nil { return nil, fmt.Errorf("failed to decode manifest: %v", err) }