diff --git a/cmd/maestro/server/grpc_broker.go b/cmd/maestro/server/grpc_broker.go index 3b9b232e..3707e087 100644 --- a/cmd/maestro/server/grpc_broker.go +++ b/cmd/maestro/server/grpc_broker.go @@ -336,7 +336,7 @@ func (bkr *GRPCBroker) respondResyncSpecRequest(ctx context.Context, eventDataTy } clusterName := fmt.Sprintf("%s", clusterNameValue) - objs, err := bkr.resourceService.List(types.ListOptions{ClusterName: clusterName}) + objs, err := bkr.resourceService.List(types.ListOptions{ClusterName: clusterName, CloudEventsDataType: eventDataType}) if err != nil { return err } diff --git a/pkg/dao/mocks/resource.go b/pkg/dao/mocks/resource.go index f75bd07d..d6d998e0 100755 --- a/pkg/dao/mocks/resource.go +++ b/pkg/dao/mocks/resource.go @@ -57,6 +57,20 @@ func (d *resourceDaoMock) FindByConsumerName(ctx context.Context, consumerID str return resources, nil } +func (d *resourceDaoMock) FindByConsumerNameAndResourceType(ctx context.Context, consumerName string, resourceType api.ResourceType) (api.ResourceList, error) { + var resources api.ResourceList + for _, resource := range d.resources { + if resource.ConsumerName != consumerName { + continue + } + if resource.Type != resourceType { + continue + } + resources = append(resources, resource) + } + return resources, nil +} + func (d *resourceDaoMock) FindBySource(ctx context.Context, source string) (api.ResourceList, error) { var resources api.ResourceList for _, resource := range d.resources { diff --git a/pkg/dao/resource.go b/pkg/dao/resource.go index 2ef1333e..0dd3dc21 100755 --- a/pkg/dao/resource.go +++ b/pkg/dao/resource.go @@ -17,6 +17,7 @@ type ResourceDao interface { FindByIDs(ctx context.Context, ids []string) (api.ResourceList, error) FindBySource(ctx context.Context, source string) (api.ResourceList, error) FindByConsumerName(ctx context.Context, consumerName string) (api.ResourceList, error) + FindByConsumerNameAndResourceType(ctx context.Context, consumerName string, resourceType api.ResourceType) (api.ResourceList, error) All(ctx context.Context) (api.ResourceList, error) FirstByConsumerName(ctx context.Context, name string, unscoped bool) (api.Resource, error) } @@ -98,6 +99,15 @@ func (d *sqlResourceDao) FindByConsumerName(ctx context.Context, consumerName st return resources, nil } +func (d *sqlResourceDao) FindByConsumerNameAndResourceType(ctx context.Context, consumerName string, resourceType api.ResourceType) (api.ResourceList, error) { + g2 := (*d.sessionFactory).New(ctx) + resources := api.ResourceList{} + if err := g2.Unscoped().Where("consumer_name = ? and type = ?", consumerName, resourceType).Find(&resources).Error; err != nil { + return nil, err + } + return resources, nil +} + func (d *sqlResourceDao) All(ctx context.Context) (api.ResourceList, error) { g2 := (*d.sessionFactory).New(ctx) resources := api.ResourceList{} diff --git a/pkg/services/resource.go b/pkg/services/resource.go index 63295c35..68d3d6dc 100755 --- a/pkg/services/resource.go +++ b/pkg/services/resource.go @@ -13,6 +13,7 @@ import ( cegeneric "open-cluster-management.io/sdk-go/pkg/cloudevents/generic" cetypes "open-cluster-management.io/sdk-go/pkg/cloudevents/generic/types" + "open-cluster-management.io/sdk-go/pkg/cloudevents/work/payload" "github.com/openshift-online/maestro/pkg/api" "github.com/openshift-online/maestro/pkg/errors" @@ -287,7 +288,17 @@ var _ cegeneric.Lister[*api.Resource] = &sqlResourceService{} // For more details, refer to the cegeneric.Lister interface: // https://github.com/open-cluster-management-io/sdk-go/blob/d3c47c228d7905ebb20f331f9b72bc5ff6a84789/pkg/cloudevents/generic/interface.go#L36-L39 func (s *sqlResourceService) List(listOpts cetypes.ListOptions) ([]*api.Resource, error) { - resourceList, err := s.resourceDao.FindByConsumerName(context.TODO(), listOpts.ClusterName) + var resourceType api.ResourceType + resourceEventDataType := listOpts.CloudEventsDataType + switch resourceEventDataType { + case payload.ManifestEventDataType: + resourceType = api.ResourceTypeSingle + case payload.ManifestBundleEventDataType: + resourceType = api.ResourceTypeBundle + default: + return nil, fmt.Errorf("unsupported resource event data type %v", resourceEventDataType) + } + resourceList, err := s.resourceDao.FindByConsumerNameAndResourceType(context.TODO(), listOpts.ClusterName, resourceType) if err != nil { return nil, err } diff --git a/pkg/services/resource_test.go b/pkg/services/resource_test.go index 69cca6b4..8d82b20f 100755 --- a/pkg/services/resource_test.go +++ b/pkg/services/resource_test.go @@ -5,12 +5,20 @@ import ( "testing" gm "github.com/onsi/gomega" + "open-cluster-management.io/sdk-go/pkg/cloudevents/generic/types" + "open-cluster-management.io/sdk-go/pkg/cloudevents/work/payload" "github.com/openshift-online/maestro/pkg/api" "github.com/openshift-online/maestro/pkg/dao/mocks" dbmocks "github.com/openshift-online/maestro/pkg/db/mocks" ) +const ( + Fukuisaurus = "b288a9da-8bfe-4c82-94cc-2b48e773fc46" + Seismosaurus = "e3eb7db1-b124-4a4d-8bb6-cc779c01b402" + Breviceratops = "c4df9ff0-bfeb-5bc6-a0ab-4c9128d698b4" +) + func TestResourceFindByConsumerID(t *testing.T) { gm.RegisterTestingT(t) @@ -19,10 +27,6 @@ func TestResourceFindByConsumerID(t *testing.T) { resourceService := NewResourceService(dbmocks.NewMockAdvisoryLockFactory(), resourceDAO, events, nil) - const Fukuisaurus = "b288a9da-8bfe-4c82-94cc-2b48e773fc46" - const Seismosaurus = "e3eb7db1-b124-4a4d-8bb6-cc779c01b402" - const Breviceratops = "c4df9ff0-bfeb-5bc6-a0ab-4c9128d698b4" - resources := api.ResourceList{ &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\"}}]}}")}, @@ -65,3 +69,43 @@ func TestCreateInvalidResource(t *testing.T) { gm.Expect(err).To(gm.BeNil()) gm.Expect(len(invalidations)).To(gm.Equal(0)) } + +func TestList(t *testing.T) { + gm.RegisterTestingT(t) + + resourceDAO := mocks.NewResourceDao() + events := NewEventService(mocks.NewEventDao()) + + resourceService := NewResourceService(dbmocks.NewMockAdvisoryLockFactory(), resourceDAO, events, nil) + resources := api.ResourceList{ + &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.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: 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\"}}}}")}, + } + for _, resource := range resources { + _, err := resourceService.Create(context.Background(), resource) + gm.Expect(err).To(gm.BeNil()) + } + + resoruces, err := resourceService.List(types.ListOptions{ + ClusterName: Fukuisaurus, + CloudEventsDataType: payload.ManifestEventDataType, + }) + gm.Expect(err).To(gm.BeNil()) + gm.Expect(len(resoruces)).To(gm.Equal(2)) + + resoruces, err = resourceService.List(types.ListOptions{ + ClusterName: Fukuisaurus, + CloudEventsDataType: payload.ManifestBundleEventDataType, + }) + gm.Expect(err).To(gm.BeNil()) + gm.Expect(len(resoruces)).To(gm.Equal(1)) + + resoruces, err = resourceService.List(types.ListOptions{ + ClusterName: Seismosaurus, + CloudEventsDataType: payload.ManifestEventDataType, + }) + gm.Expect(err).To(gm.BeNil()) + gm.Expect(len(resoruces)).To(gm.Equal(1)) +}