From 8c767848b71fa895f8ce64f8651c1f375f23ff50 Mon Sep 17 00:00:00 2001 From: Hukumraj Singh Deora Date: Mon, 21 Oct 2024 01:05:10 +0200 Subject: [PATCH 01/12] feat: Add support for spec.associatedResources --- internal/common/validation/validation.go | 19 +++++++- internal/common/validation/validation_test.go | 33 ++++++++++++++ .../service/contentprovider/moduleconfig.go | 29 ++++++------ .../generator/moduleconfig_generator_test.go | 7 +++ .../reader/moduleconfig_reader.go | 26 ++++++----- .../reader/moduleconfig_reader_test.go | 3 ++ .../templategenerator/templategenerator.go | 45 ++++++++++++------- .../templategenerator_test.go | 37 +++++++++++++++ tests/e2e/create/create_suite_test.go | 17 +++---- tests/e2e/create/create_test.go | 39 ++++++++++++++++ .../valid/with-associated-resources.yaml | 8 ++++ 11 files changed, 212 insertions(+), 51 deletions(-) create mode 100644 tests/e2e/create/testdata/moduleconfig/valid/with-associated-resources.yaml diff --git a/internal/common/validation/validation.go b/internal/common/validation/validation.go index 8befb3f4..67db4c35 100644 --- a/internal/common/validation/validation.go +++ b/internal/common/validation/validation.go @@ -2,11 +2,10 @@ package validation import ( "fmt" + "github.com/Masterminds/semver/v3" "regexp" "strings" - "github.com/Masterminds/semver/v3" - commonerrors "github.com/kyma-project/modulectl/internal/common/errors" ) @@ -116,3 +115,19 @@ func validateSemanticVersion(version string) error { return nil } + +func ValidateGvk(group, version, kind string) error { + if kind == "" { + return fmt.Errorf("kind must not be empty: %w", commonerrors.ErrInvalidOption) + } + + if group == "" { + return fmt.Errorf("group must not be empty: %w", commonerrors.ErrInvalidOption) + } + + if version == "" { + return fmt.Errorf("version must not be empty: %w", commonerrors.ErrInvalidOption) + } + + return nil +} diff --git a/internal/common/validation/validation_test.go b/internal/common/validation/validation_test.go index 2029cb2a..fe7dc64e 100644 --- a/internal/common/validation/validation_test.go +++ b/internal/common/validation/validation_test.go @@ -225,3 +225,36 @@ func TestValidateNamespace(t *testing.T) { }) } } + +func TestValidateGvk(t *testing.T) { + type args struct { + group string + version string + kind string + } + tests := []struct { + name string + args args + wantErr bool + }{ + {name: "valid GVK", + args: args{group: "kyma-project.io", version: "v1alpha1", kind: "Module"}, + wantErr: false}, + {name: "invalid GVK when group empty", + args: args{version: "v1alpha1", kind: "Module"}, + wantErr: true}, + {name: "invalid GVK when version empty", + args: args{group: "kyma-project.io", kind: "Module"}, + wantErr: true}, + {name: "invalid GVK when kind empty", + args: args{group: "kyma-project.io", version: "v1alpha1"}, + wantErr: true}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := validation.ValidateGvk(tt.args.group, tt.args.version, tt.args.kind); (err != nil) != tt.wantErr { + t.Errorf("ValidateGvk() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/service/contentprovider/moduleconfig.go b/internal/service/contentprovider/moduleconfig.go index 4207eb2a..088dfdbf 100644 --- a/internal/service/contentprovider/moduleconfig.go +++ b/internal/service/contentprovider/moduleconfig.go @@ -77,18 +77,19 @@ type Manager struct { } type ModuleConfig struct { - Name string `yaml:"name" comment:"required, the name of the Module"` - Version string `yaml:"version" comment:"required, the version of the Module"` - Channel string `yaml:"channel" comment:"required, channel that should be used in the ModuleTemplate"` - ManifestPath string `yaml:"manifest" comment:"required, relative path or remote URL to the manifests"` - Mandatory bool `yaml:"mandatory" comment:"optional, default=false, indicates whether the module is mandatory to be installed on all clusters"` - DefaultCRPath string `yaml:"defaultCR" comment:"optional, relative path or remote URL to a YAML file containing the default CR for the module"` - ResourceName string `yaml:"resourceName" comment:"optional, default={name}-{channel}, when channel is 'none', the default is {name}-{version}, the name for the ModuleTemplate that will be created"` - Namespace string `yaml:"namespace" comment:"optional, default=kcp-system, the namespace where the ModuleTemplate will be deployed"` - Security string `yaml:"security" comment:"optional, name of the security scanners config file"` - Internal bool `yaml:"internal" comment:"optional, default=false, determines whether the ModuleTemplate should have the internal flag or not"` - Beta bool `yaml:"beta" comment:"optional, default=false, determines whether the ModuleTemplate should have the beta flag or not"` - Labels map[string]string `yaml:"labels" comment:"optional, additional labels for the ModuleTemplate"` - Annotations map[string]string `yaml:"annotations" comment:"optional, additional annotations for the ModuleTemplate"` - Manager *Manager `yaml:"manager" comment:"optional, the module resource that can be used to indicate the installation readiness of the module. This is typically the manager deployment of the module"` + Name string `yaml:"name" comment:"required, the name of the Module"` + Version string `yaml:"version" comment:"required, the version of the Module"` + Channel string `yaml:"channel" comment:"required, channel that should be used in the ModuleTemplate"` + ManifestPath string `yaml:"manifest" comment:"required, relative path or remote URL to the manifests"` + Mandatory bool `yaml:"mandatory" comment:"optional, default=false, indicates whether the module is mandatory to be installed on all clusters"` + DefaultCRPath string `yaml:"defaultCR" comment:"optional, relative path or remote URL to a YAML file containing the default CR for the module"` + ResourceName string `yaml:"resourceName" comment:"optional, default={name}-{channel}, when channel is 'none', the default is {name}-{version}, the name for the ModuleTemplate that will be created"` + Namespace string `yaml:"namespace" comment:"optional, default=kcp-system, the namespace where the ModuleTemplate will be deployed"` + Security string `yaml:"security" comment:"optional, name of the security scanners config file"` + Internal bool `yaml:"internal" comment:"optional, default=false, determines whether the ModuleTemplate should have the internal flag or not"` + Beta bool `yaml:"beta" comment:"optional, default=false, determines whether the ModuleTemplate should have the beta flag or not"` + Labels map[string]string `yaml:"labels" comment:"optional, additional labels for the ModuleTemplate"` + Annotations map[string]string `yaml:"annotations" comment:"optional, additional annotations for the ModuleTemplate"` + AssociatedResources []*metav1.GroupVersionKind `yaml:"associatedResources" comment:"optional, GVK of the resources which are associated to the ModuleTemplate"` + Manager *Manager `yaml:"manager" comment:"optional, the module resource that can be used to indicate the installation readiness of the module. This is typically the manager deployment of the module"` } diff --git a/internal/service/moduleconfig/generator/moduleconfig_generator_test.go b/internal/service/moduleconfig/generator/moduleconfig_generator_test.go index 2285bed1..62f1412d 100644 --- a/internal/service/moduleconfig/generator/moduleconfig_generator_test.go +++ b/internal/service/moduleconfig/generator/moduleconfig_generator_test.go @@ -131,6 +131,13 @@ func (*fileExistsStub) ReadFile(_ string) ([]byte, error) { Beta: false, Labels: map[string]string{"label1": "value1"}, Annotations: map[string]string{"annotation1": "value1"}, + AssociatedResources: []*metav1.GroupVersionKind{ + { + Group: "networking.istio.io", + Version: "v1alpha3", + Kind: "Gateway", + }, + }, Manager: &contentprovider.Manager{ Name: "manager-name", Namespace: "manager-namespace", diff --git a/internal/service/moduleconfig/reader/moduleconfig_reader.go b/internal/service/moduleconfig/reader/moduleconfig_reader.go index 96d315cc..1bc861dd 100644 --- a/internal/service/moduleconfig/reader/moduleconfig_reader.go +++ b/internal/service/moduleconfig/reader/moduleconfig_reader.go @@ -3,6 +3,7 @@ package moduleconfigreader import ( "errors" "fmt" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "net/url" "os" "path/filepath" @@ -148,6 +149,10 @@ func ValidateModuleConfig(moduleConfig *contentprovider.ModuleConfig) error { return fmt.Errorf("manifest path must not be empty: %w", commonerrors.ErrInvalidOption) } + if err := validateAssociatedResources(moduleConfig.AssociatedResources); err != nil { + return fmt.Errorf("failed to validate associated resources: %w", err) + } + if err := ValidateManager(moduleConfig.Manager); err != nil { return fmt.Errorf("failed to validate manager: %w", err) } @@ -155,6 +160,15 @@ func ValidateModuleConfig(moduleConfig *contentprovider.ModuleConfig) error { return nil } +func validateAssociatedResources(resources []*metav1.GroupVersionKind) error { + for _, resource := range resources { + if err := validation.ValidateGvk(resource.Group, resource.Version, resource.Kind); err != nil { + return fmt.Errorf("GVK is invalid: %w", err) + } + } + return nil +} + func ValidateManager(manager *contentprovider.Manager) error { if manager == nil { return nil @@ -164,16 +178,8 @@ func ValidateManager(manager *contentprovider.Manager) error { return fmt.Errorf("name must not be empty: %w", commonerrors.ErrInvalidOption) } - if manager.Kind == "" { - return fmt.Errorf("kind must not be empty: %w", commonerrors.ErrInvalidOption) - } - - if manager.Group == "" { - return fmt.Errorf("group must not be empty: %w", commonerrors.ErrInvalidOption) - } - - if manager.Version == "" { - return fmt.Errorf("version must not be empty: %w", commonerrors.ErrInvalidOption) + if err := validation.ValidateGvk(manager.Group, manager.Version, manager.Kind); err != nil { + return fmt.Errorf("GVK is invalid: %w", err) } if manager.Namespace != "" { diff --git a/internal/service/moduleconfig/reader/moduleconfig_reader_test.go b/internal/service/moduleconfig/reader/moduleconfig_reader_test.go index 468dd0d1..d7a82688 100644 --- a/internal/service/moduleconfig/reader/moduleconfig_reader_test.go +++ b/internal/service/moduleconfig/reader/moduleconfig_reader_test.go @@ -43,6 +43,9 @@ func Test_ParseModuleConfig_Returns_CorrectModuleConfig(t *testing.T) { require.False(t, result.Beta) require.Equal(t, map[string]string{"label1": "value1"}, result.Labels) require.Equal(t, map[string]string{"annotation1": "value1"}, result.Annotations) + require.Equal(t, "networking.istio.io", result.AssociatedResources[0].Group) + require.Equal(t, "v1alpha3", result.AssociatedResources[0].Version) + require.Equal(t, "Gateway", result.AssociatedResources[0].Kind) require.Equal(t, "manager-name", result.Manager.Name) require.Equal(t, "manager-namespace", result.Manager.Namespace) require.Equal(t, "apps", result.Manager.GroupVersionKind.Group) diff --git a/internal/service/templategenerator/templategenerator.go b/internal/service/templategenerator/templategenerator.go index f37db869..b0f76413 100644 --- a/internal/service/templategenerator/templategenerator.go +++ b/internal/service/templategenerator/templategenerator.go @@ -4,6 +4,7 @@ import ( "bytes" "errors" "fmt" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "strings" "text/template" @@ -60,6 +61,14 @@ metadata: spec: channel: {{.Channel}} mandatory: {{.Mandatory}} +{{- with .AssociatedResources}} + associatedResources: + {{- range .}} + - group: {{.Group}} + version: {{.Version}} + kind: {{.Kind}} + {{- end}} +{{- end}} {{- with .Data}} data: {{. | indent 4}} @@ -80,15 +89,16 @@ spec: ) type moduleTemplateData struct { - ResourceName string - Namespace string - Descriptor compdesc.ComponentDescriptorVersion - Channel string - Labels map[string]string - Annotations map[string]string - Mandatory bool - Data string - Manager *contentprovider.Manager + ResourceName string + Namespace string + Descriptor compdesc.ComponentDescriptorVersion + Channel string + Labels map[string]string + Annotations map[string]string + Mandatory bool + Data string + AssociatedResources []*metav1.GroupVersionKind + Manager *contentprovider.Manager } func (s *Service) GenerateModuleTemplate( @@ -132,14 +142,15 @@ func (s *Service) GenerateModuleTemplate( } mtData := moduleTemplateData{ - ResourceName: moduleConfig.ResourceName, - Namespace: moduleConfig.Namespace, - Descriptor: cva, - Channel: moduleConfig.Channel, - Labels: labels, - Annotations: annotations, - Mandatory: moduleConfig.Mandatory, - Manager: moduleConfig.Manager, + ResourceName: moduleConfig.ResourceName, + Namespace: moduleConfig.Namespace, + Descriptor: cva, + Channel: moduleConfig.Channel, + Labels: labels, + Annotations: annotations, + Mandatory: moduleConfig.Mandatory, + AssociatedResources: moduleConfig.AssociatedResources, + Manager: moduleConfig.Manager, } if len(data) > 0 { diff --git a/internal/service/templategenerator/templategenerator_test.go b/internal/service/templategenerator/templategenerator_test.go index e317ad33..51a23722 100644 --- a/internal/service/templategenerator/templategenerator_test.go +++ b/internal/service/templategenerator/templategenerator_test.go @@ -64,6 +64,43 @@ func TestGenerateModuleTemplate_Success(t *testing.T) { require.Contains(t, mockFS.writtenTemplate, "example.com/component") } +func TestGenerateModuleTemplateWithAssociatedResources_Success(t *testing.T) { + mockFS := &mockFileSystem{} + svc, _ := templategenerator.NewService(mockFS) + + moduleConfig := &contentprovider.ModuleConfig{ + ResourceName: "test-resource", + Namespace: "default", + Channel: "stable", + Labels: map[string]string{"key": "value"}, + Annotations: map[string]string{"annotation": "value"}, + Mandatory: true, + AssociatedResources: []*metav1.GroupVersionKind{ + { + Group: "networking.istio.io", + Version: "v1alpha3", + Kind: "Gateway", + }, + }, + } + descriptor := testutils.CreateComponentDescriptor("example.com/component", "1.0.0") + data := []byte("test-data") + + err := svc.GenerateModuleTemplate(moduleConfig, descriptor, data, true, "output.yaml") + + require.NoError(t, err) + require.Equal(t, "output.yaml", mockFS.path) + require.Contains(t, mockFS.writtenTemplate, "test-resource") + require.Contains(t, mockFS.writtenTemplate, "default") + require.Contains(t, mockFS.writtenTemplate, "stable") + require.Contains(t, mockFS.writtenTemplate, "test-data") + require.Contains(t, mockFS.writtenTemplate, "example.com/component") + require.Contains(t, mockFS.writtenTemplate, "associatedResources") + require.Contains(t, mockFS.writtenTemplate, "networking.istio.io") + require.Contains(t, mockFS.writtenTemplate, "v1alpha3") + require.Contains(t, mockFS.writtenTemplate, "Gateway") +} + func TestGenerateModuleTemplateWithManager_Success(t *testing.T) { mockFS := &mockFileSystem{} svc, _ := templategenerator.NewService(mockFS) diff --git a/tests/e2e/create/create_suite_test.go b/tests/e2e/create/create_suite_test.go index 1c4a8b7d..aa606a7a 100644 --- a/tests/e2e/create/create_suite_test.go +++ b/tests/e2e/create/create_suite_test.go @@ -26,14 +26,15 @@ const ( missingVersionConfig = invalidConfigs + "missing-version.yaml" missingManifestConfig = invalidConfigs + "missing-manifest.yaml" - validConfigs = testdataDir + "valid/" - minimalConfig = validConfigs + "minimal.yaml" - withAnnotationsConfig = validConfigs + "with-annotations.yaml" - withDefaultCrConfig = validConfigs + "with-defaultcr.yaml" - withSecurityConfig = validConfigs + "with-security.yaml" - withMandatoryConfig = validConfigs + "with-mandatory.yaml" - withManagerConfig = validConfigs + "with-manager.yaml" - withNoNamespaceManagerConfig = validConfigs + "with-manager-no-namespace.yaml" + validConfigs = testdataDir + "valid/" + minimalConfig = validConfigs + "minimal.yaml" + withAnnotationsConfig = validConfigs + "with-annotations.yaml" + withDefaultCrConfig = validConfigs + "with-defaultcr.yaml" + withSecurityConfig = validConfigs + "with-security.yaml" + withMandatoryConfig = validConfigs + "with-mandatory.yaml" + withAssociatedResourcesConfig = validConfigs + "with-associated-resources.yaml" + withManagerConfig = validConfigs + "with-manager.yaml" + withNoNamespaceManagerConfig = validConfigs + "with-manager-no-namespace.yaml" ociRegistry = "http://k3d-oci.localhost:5001" templateOutputPath = "/tmp/template.yaml" diff --git a/tests/e2e/create/create_test.go b/tests/e2e/create/create_test.go index db12968d..260f31a6 100644 --- a/tests/e2e/create/create_test.go +++ b/tests/e2e/create/create_test.go @@ -183,6 +183,9 @@ var _ = Describe("Test 'create' command", Ordered, func() { By("And spec.mandatory should be false") Expect(template.Spec.Mandatory).To(BeFalse()) + By("And spec.associatedResources should be emptz") + Expect(template.Spec.AssociatedResources).To(BeEmpty()) + By("And spec.manager should be nil") Expect(template.Spec.Manager).To(BeNil()) }) @@ -390,6 +393,42 @@ var _ = Describe("Test 'create' command", Ordered, func() { }) }) + Context("Given 'modulectl create' command", func() { + var cmd createCmd + It("When invoked with valid module-config containing associatedResources list", func() { + cmd = createCmd{ + moduleConfigFile: withAssociatedResourcesConfig, + registry: ociRegistry, + insecure: true, + output: templateOutputPath, + } + }) + It("Then the command should succeed", func() { + Expect(cmd.execute()).To(Succeed()) + + By("And module template file should be generated") + Expect(filesIn("/tmp/")).Should(ContainElement("template.yaml")) + }) + It("Then module template should contain the expected content", func() { + template, err := readModuleTemplate(templateOutputPath) + Expect(err).ToNot(HaveOccurred()) + descriptor := getDescriptor(template) + Expect(descriptor).ToNot(BeNil()) + + By("And annotation should have correct version") + annotations := template.Annotations + Expect(annotations[shared.ModuleVersionAnnotation]).To(Equal("1.0.5")) + + By("And spec.associatedResources should be correct") + resources := template.Spec.AssociatedResources + Expect(resources).ToNot(BeEmpty()) + Expect(len(resources)).To(Equal(1)) + Expect(resources[0].Group).To(Equal("networking.istio.io")) + Expect(resources[0].Version).To(Equal("v1alpha3")) + Expect(resources[0].Kind).To(Equal("Gateway")) + }) + }) + Context("Given 'modulectl create' command", func() { var cmd createCmd It("When invoked with valid module-config containing manager field and different version", func() { diff --git a/tests/e2e/create/testdata/moduleconfig/valid/with-associated-resources.yaml b/tests/e2e/create/testdata/moduleconfig/valid/with-associated-resources.yaml new file mode 100644 index 00000000..bd405fa5 --- /dev/null +++ b/tests/e2e/create/testdata/moduleconfig/valid/with-associated-resources.yaml @@ -0,0 +1,8 @@ +name: kyma-project.io/module/template-operator +channel: regular +version: 1.0.6 +manifest: https://github.com/kyma-project/template-operator/releases/download/1.0.1/template-operator.yaml +associatedResources: + - group: networking.istio.io + version: v1alpha3 + kind: Gateway \ No newline at end of file From b6b47fb92de5ff91d6d41b5602082208404d1878 Mon Sep 17 00:00:00 2001 From: Hukumraj Singh Deora Date: Mon, 21 Oct 2024 01:17:15 +0200 Subject: [PATCH 02/12] fix: unit test --- .../moduleconfig/reader/moduleconfig_reader_test.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/internal/service/moduleconfig/reader/moduleconfig_reader_test.go b/internal/service/moduleconfig/reader/moduleconfig_reader_test.go index d7a82688..d7a8c473 100644 --- a/internal/service/moduleconfig/reader/moduleconfig_reader_test.go +++ b/internal/service/moduleconfig/reader/moduleconfig_reader_test.go @@ -373,6 +373,13 @@ var expectedReturnedModuleConfig = contentprovider.ModuleConfig{ Beta: false, Labels: map[string]string{"label1": "value1"}, Annotations: map[string]string{"annotation1": "value1"}, + AssociatedResources: []*metav1.GroupVersionKind{ + { + Group: "networking.istio.io", + Version: "v1alpha3", + Kind: "Gateway", + }, + }, Manager: &contentprovider.Manager{ Name: "manager-name", Namespace: "manager-namespace", From 6851e73374ef7ca16ee35fe3926ca445cafa7df0 Mon Sep 17 00:00:00 2001 From: Hukumraj Singh Deora Date: Mon, 21 Oct 2024 01:25:27 +0200 Subject: [PATCH 03/12] refactor: lint issue --- internal/common/validation/validation.go | 2 +- internal/common/validation/validation_test.go | 24 ++++++++++++------- .../reader/moduleconfig_reader.go | 5 ++-- .../templategenerator/templategenerator.go | 8 +++---- 4 files changed, 23 insertions(+), 16 deletions(-) diff --git a/internal/common/validation/validation.go b/internal/common/validation/validation.go index 67db4c35..b7eb43d7 100644 --- a/internal/common/validation/validation.go +++ b/internal/common/validation/validation.go @@ -2,10 +2,10 @@ package validation import ( "fmt" - "github.com/Masterminds/semver/v3" "regexp" "strings" + "github.com/Masterminds/semver/v3" commonerrors "github.com/kyma-project/modulectl/internal/common/errors" ) diff --git a/internal/common/validation/validation_test.go b/internal/common/validation/validation_test.go index fe7dc64e..adeb11c4 100644 --- a/internal/common/validation/validation_test.go +++ b/internal/common/validation/validation_test.go @@ -237,18 +237,26 @@ func TestValidateGvk(t *testing.T) { args args wantErr bool }{ - {name: "valid GVK", + { + name: "valid GVK", args: args{group: "kyma-project.io", version: "v1alpha1", kind: "Module"}, - wantErr: false}, - {name: "invalid GVK when group empty", + wantErr: false, + }, + { + name: "invalid GVK when group empty", args: args{version: "v1alpha1", kind: "Module"}, - wantErr: true}, - {name: "invalid GVK when version empty", + wantErr: true, + }, + { + name: "invalid GVK when version empty", args: args{group: "kyma-project.io", kind: "Module"}, - wantErr: true}, - {name: "invalid GVK when kind empty", + wantErr: true, + }, + { + name: "invalid GVK when kind empty", args: args{group: "kyma-project.io", version: "v1alpha1"}, - wantErr: true}, + wantErr: true, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { diff --git a/internal/service/moduleconfig/reader/moduleconfig_reader.go b/internal/service/moduleconfig/reader/moduleconfig_reader.go index 1bc861dd..14b22726 100644 --- a/internal/service/moduleconfig/reader/moduleconfig_reader.go +++ b/internal/service/moduleconfig/reader/moduleconfig_reader.go @@ -3,16 +3,15 @@ package moduleconfigreader import ( "errors" "fmt" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "net/url" "os" "path/filepath" - "gopkg.in/yaml.v3" - commonerrors "github.com/kyma-project/modulectl/internal/common/errors" "github.com/kyma-project/modulectl/internal/common/validation" "github.com/kyma-project/modulectl/internal/service/contentprovider" + "gopkg.in/yaml.v3" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) var ErrNoPathForDefaultCR = errors.New("no path for default CR given") diff --git a/internal/service/templategenerator/templategenerator.go b/internal/service/templategenerator/templategenerator.go index b0f76413..2de2f97b 100644 --- a/internal/service/templategenerator/templategenerator.go +++ b/internal/service/templategenerator/templategenerator.go @@ -4,17 +4,17 @@ import ( "bytes" "errors" "fmt" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "strings" "text/template" - "github.com/kyma-project/lifecycle-manager/api/shared" + commonerrors "github.com/kyma-project/modulectl/internal/common/errors" + "github.com/kyma-project/modulectl/internal/service/contentprovider" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "ocm.software/ocm/api/oci" "ocm.software/ocm/api/ocm/compdesc" "sigs.k8s.io/yaml" - commonerrors "github.com/kyma-project/modulectl/internal/common/errors" - "github.com/kyma-project/modulectl/internal/service/contentprovider" + "github.com/kyma-project/lifecycle-manager/api/shared" ) var ( From 5e376b5d951f3e22bdb74dee39b5b4002e8efa28 Mon Sep 17 00:00:00 2001 From: Hukumraj Singh Deora Date: Mon, 21 Oct 2024 01:27:36 +0200 Subject: [PATCH 04/12] test: fix e2e --- tests/e2e/create/create_test.go | 72 +++++++++---------- .../valid/with-associated-resources.yaml | 2 +- 2 files changed, 37 insertions(+), 37 deletions(-) diff --git a/tests/e2e/create/create_test.go b/tests/e2e/create/create_test.go index 260f31a6..fb5f8862 100644 --- a/tests/e2e/create/create_test.go +++ b/tests/e2e/create/create_test.go @@ -393,42 +393,6 @@ var _ = Describe("Test 'create' command", Ordered, func() { }) }) - Context("Given 'modulectl create' command", func() { - var cmd createCmd - It("When invoked with valid module-config containing associatedResources list", func() { - cmd = createCmd{ - moduleConfigFile: withAssociatedResourcesConfig, - registry: ociRegistry, - insecure: true, - output: templateOutputPath, - } - }) - It("Then the command should succeed", func() { - Expect(cmd.execute()).To(Succeed()) - - By("And module template file should be generated") - Expect(filesIn("/tmp/")).Should(ContainElement("template.yaml")) - }) - It("Then module template should contain the expected content", func() { - template, err := readModuleTemplate(templateOutputPath) - Expect(err).ToNot(HaveOccurred()) - descriptor := getDescriptor(template) - Expect(descriptor).ToNot(BeNil()) - - By("And annotation should have correct version") - annotations := template.Annotations - Expect(annotations[shared.ModuleVersionAnnotation]).To(Equal("1.0.5")) - - By("And spec.associatedResources should be correct") - resources := template.Spec.AssociatedResources - Expect(resources).ToNot(BeEmpty()) - Expect(len(resources)).To(Equal(1)) - Expect(resources[0].Group).To(Equal("networking.istio.io")) - Expect(resources[0].Version).To(Equal("v1alpha3")) - Expect(resources[0].Kind).To(Equal("Gateway")) - }) - }) - Context("Given 'modulectl create' command", func() { var cmd createCmd It("When invoked with valid module-config containing manager field and different version", func() { @@ -503,6 +467,42 @@ var _ = Describe("Test 'create' command", Ordered, func() { Expect(manager.Kind).To(Equal("Deployment")) }) }) + + Context("Given 'modulectl create' command", func() { + var cmd createCmd + It("When invoked with valid module-config containing associatedResources list", func() { + cmd = createCmd{ + moduleConfigFile: withAssociatedResourcesConfig, + registry: ociRegistry, + insecure: true, + output: templateOutputPath, + } + }) + It("Then the command should succeed", func() { + Expect(cmd.execute()).To(Succeed()) + + By("And module template file should be generated") + Expect(filesIn("/tmp/")).Should(ContainElement("template.yaml")) + }) + It("Then module template should contain the expected content", func() { + template, err := readModuleTemplate(templateOutputPath) + Expect(err).ToNot(HaveOccurred()) + descriptor := getDescriptor(template) + Expect(descriptor).ToNot(BeNil()) + + By("And annotation should have correct version") + annotations := template.Annotations + Expect(annotations[shared.ModuleVersionAnnotation]).To(Equal("1.0.7")) + + By("And spec.associatedResources should be correct") + resources := template.Spec.AssociatedResources + Expect(resources).ToNot(BeEmpty()) + Expect(len(resources)).To(Equal(1)) + Expect(resources[0].Group).To(Equal("networking.istio.io")) + Expect(resources[0].Version).To(Equal("v1alpha3")) + Expect(resources[0].Kind).To(Equal("Gateway")) + }) + }) }) // Test helper functions diff --git a/tests/e2e/create/testdata/moduleconfig/valid/with-associated-resources.yaml b/tests/e2e/create/testdata/moduleconfig/valid/with-associated-resources.yaml index bd405fa5..29341c06 100644 --- a/tests/e2e/create/testdata/moduleconfig/valid/with-associated-resources.yaml +++ b/tests/e2e/create/testdata/moduleconfig/valid/with-associated-resources.yaml @@ -1,6 +1,6 @@ name: kyma-project.io/module/template-operator channel: regular -version: 1.0.6 +version: 1.0.7 manifest: https://github.com/kyma-project/template-operator/releases/download/1.0.1/template-operator.yaml associatedResources: - group: networking.istio.io From 5848d55c04670dc21f43432cb6f3cb487a780d0a Mon Sep 17 00:00:00 2001 From: Hukumraj Singh Deora Date: Mon, 21 Oct 2024 01:38:59 +0200 Subject: [PATCH 05/12] refactor: lint --- internal/common/validation/validation.go | 1 + internal/service/moduleconfig/reader/moduleconfig_reader.go | 5 +++-- internal/service/templategenerator/templategenerator.go | 6 +++--- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/internal/common/validation/validation.go b/internal/common/validation/validation.go index b7eb43d7..828eb562 100644 --- a/internal/common/validation/validation.go +++ b/internal/common/validation/validation.go @@ -6,6 +6,7 @@ import ( "strings" "github.com/Masterminds/semver/v3" + commonerrors "github.com/kyma-project/modulectl/internal/common/errors" ) diff --git a/internal/service/moduleconfig/reader/moduleconfig_reader.go b/internal/service/moduleconfig/reader/moduleconfig_reader.go index 14b22726..f64641c0 100644 --- a/internal/service/moduleconfig/reader/moduleconfig_reader.go +++ b/internal/service/moduleconfig/reader/moduleconfig_reader.go @@ -7,11 +7,12 @@ import ( "os" "path/filepath" + "gopkg.in/yaml.v3" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + commonerrors "github.com/kyma-project/modulectl/internal/common/errors" "github.com/kyma-project/modulectl/internal/common/validation" "github.com/kyma-project/modulectl/internal/service/contentprovider" - "gopkg.in/yaml.v3" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) var ErrNoPathForDefaultCR = errors.New("no path for default CR given") diff --git a/internal/service/templategenerator/templategenerator.go b/internal/service/templategenerator/templategenerator.go index 2de2f97b..d8161f90 100644 --- a/internal/service/templategenerator/templategenerator.go +++ b/internal/service/templategenerator/templategenerator.go @@ -7,14 +7,14 @@ import ( "strings" "text/template" - commonerrors "github.com/kyma-project/modulectl/internal/common/errors" - "github.com/kyma-project/modulectl/internal/service/contentprovider" + "github.com/kyma-project/lifecycle-manager/api/shared" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "ocm.software/ocm/api/oci" "ocm.software/ocm/api/ocm/compdesc" "sigs.k8s.io/yaml" - "github.com/kyma-project/lifecycle-manager/api/shared" + commonerrors "github.com/kyma-project/modulectl/internal/common/errors" + "github.com/kyma-project/modulectl/internal/service/contentprovider" ) var ( From 37c72edd4f1918ba100fac2fedda2a4c06109e62 Mon Sep 17 00:00:00 2001 From: Raj <54686422+LeelaChacha@users.noreply.github.com> Date: Wed, 23 Oct 2024 09:34:21 +0200 Subject: [PATCH 06/12] refactor: Fix typo Co-authored-by: Nesma Badr --- tests/e2e/create/create_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/e2e/create/create_test.go b/tests/e2e/create/create_test.go index fb5f8862..6f4aeab5 100644 --- a/tests/e2e/create/create_test.go +++ b/tests/e2e/create/create_test.go @@ -183,7 +183,7 @@ var _ = Describe("Test 'create' command", Ordered, func() { By("And spec.mandatory should be false") Expect(template.Spec.Mandatory).To(BeFalse()) - By("And spec.associatedResources should be emptz") + By("And spec.associatedResources should be empty") Expect(template.Spec.AssociatedResources).To(BeEmpty()) By("And spec.manager should be nil") From 12dcdce92df95381f68304db159dcb9520e09c11 Mon Sep 17 00:00:00 2001 From: Hukumraj Singh Deora Date: Wed, 23 Oct 2024 09:52:54 +0200 Subject: [PATCH 07/12] refactor: Enhance comment in ModuleConfig struct --- .../service/contentprovider/moduleconfig.go | 6 ++--- .../generator/moduleconfig_generator_test.go | 26 +++++++++--------- .../reader/moduleconfig_reader_test.go | 27 ++++++++++--------- 3 files changed, 30 insertions(+), 29 deletions(-) diff --git a/internal/service/contentprovider/moduleconfig.go b/internal/service/contentprovider/moduleconfig.go index e3e255ad..31137255 100644 --- a/internal/service/contentprovider/moduleconfig.go +++ b/internal/service/contentprovider/moduleconfig.go @@ -83,9 +83,9 @@ type ModuleConfig struct { Name string `yaml:"name" comment:"required, the name of the Module"` Version string `yaml:"version" comment:"required, the version of the Module"` Channel string `yaml:"channel" comment:"required, channel that should be used in the ModuleTemplate"` - ManifestPath string `yaml:"manifest" comment:"required, relative path or remote URL to the manifests"` + Manifest string `yaml:"manifest" comment:"required, relative path or remote URL to the manifests"` Mandatory bool `yaml:"mandatory" comment:"optional, default=false, indicates whether the module is mandatory to be installed on all clusters"` - DefaultCRPath string `yaml:"defaultCR" comment:"optional, relative path or remote URL to a YAML file containing the default CR for the module"` + DefaultCR string `yaml:"defaultCR" comment:"optional, relative path or remote URL to a YAML file containing the default CR for the module"` ResourceName string `yaml:"resourceName" comment:"optional, default={name}-{channel}, when channel is 'none', the default is {name}-{version}, the name for the ModuleTemplate that will be created"` Namespace string `yaml:"namespace" comment:"optional, default=kcp-system, the namespace where the ModuleTemplate will be deployed"` Security string `yaml:"security" comment:"optional, name of the security scanners config file"` @@ -93,7 +93,7 @@ type ModuleConfig struct { Beta bool `yaml:"beta" comment:"optional, default=false, determines whether the ModuleTemplate should have the beta flag or not"` Labels map[string]string `yaml:"labels" comment:"optional, additional labels for the ModuleTemplate"` Annotations map[string]string `yaml:"annotations" comment:"optional, additional annotations for the ModuleTemplate"` - AssociatedResources []*metav1.GroupVersionKind `yaml:"associatedResources" comment:"optional, GVK of the resources which are associated to the ModuleTemplate"` + AssociatedResources []*metav1.GroupVersionKind `yaml:"associatedResources" comment:"optional, GVK of the resources which are associated with the module and have to be deleted with module deletion"` Manager *Manager `yaml:"manager" comment:"optional, the module resource that can be used to indicate the installation readiness of the module. This is typically the manager deployment of the module"` Resources ResourcesMap `yaml:"resources,omitempty" comment:"optional, additional resources of the ModuleTemplate that may be fetched"` } diff --git a/internal/service/moduleconfig/generator/moduleconfig_generator_test.go b/internal/service/moduleconfig/generator/moduleconfig_generator_test.go index 62f1412d..bbfc056a 100644 --- a/internal/service/moduleconfig/generator/moduleconfig_generator_test.go +++ b/internal/service/moduleconfig/generator/moduleconfig_generator_test.go @@ -118,19 +118,19 @@ func (*fileExistsStub) FileExists(_ string) (bool, error) { func (*fileExistsStub) ReadFile(_ string) ([]byte, error) { moduleConfig := contentprovider.ModuleConfig{ - Name: "module-name", - Version: "0.0.1", - Channel: "regular", - ManifestPath: "path/to/manifests", - Mandatory: false, - DefaultCRPath: "path/to/defaultCR", - ResourceName: "module-name-0.0.1", - Namespace: "kcp-system", - Security: "path/to/securityConfig", - Internal: false, - Beta: false, - Labels: map[string]string{"label1": "value1"}, - Annotations: map[string]string{"annotation1": "value1"}, + Name: "module-name", + Version: "0.0.1", + Channel: "regular", + Manifest: "path/to/manifests", + Mandatory: false, + DefaultCR: "path/to/defaultCR", + ResourceName: "module-name-0.0.1", + Namespace: "kcp-system", + Security: "path/to/securityConfig", + Internal: false, + Beta: false, + Labels: map[string]string{"label1": "value1"}, + Annotations: map[string]string{"annotation1": "value1"}, AssociatedResources: []*metav1.GroupVersionKind{ { Group: "networking.istio.io", diff --git a/internal/service/moduleconfig/reader/moduleconfig_reader_test.go b/internal/service/moduleconfig/reader/moduleconfig_reader_test.go index c3c1650e..e602d0f2 100644 --- a/internal/service/moduleconfig/reader/moduleconfig_reader_test.go +++ b/internal/service/moduleconfig/reader/moduleconfig_reader_test.go @@ -288,25 +288,26 @@ func (*fileExistsStub) FileExists(_ string) (bool, error) { } var expectedReturnedModuleConfig = contentprovider.ModuleConfig{ - Name: "github.com/module-name", - Version: "0.0.1", - Channel: "regular", - ManifestPath: "path/to/manifests", - Mandatory: false, - DefaultCRPath: "path/to/defaultCR", - ResourceName: "module-name-0.0.1", - Namespace: "kcp-system", - Security: "path/to/securityConfig", - Internal: false, - Beta: false, - Labels: map[string]string{"label1": "value1"}, - Annotations: map[string]string{"annotation1": "value1"}, + Name: "github.com/module-name", + Version: "0.0.1", + Channel: "regular", + Manifest: "path/to/manifests", + Mandatory: false, + DefaultCR: "path/to/defaultCR", + ResourceName: "module-name-0.0.1", + Namespace: "kcp-system", + Security: "path/to/securityConfig", + Internal: false, + Beta: false, + Labels: map[string]string{"label1": "value1"}, + Annotations: map[string]string{"annotation1": "value1"}, AssociatedResources: []*metav1.GroupVersionKind{ { Group: "networking.istio.io", Version: "v1alpha3", Kind: "Gateway", }, + }, Resources: contentprovider.ResourcesMap{ "rawManifest": "https://github.com/kyma-project/template-operator/releases/download/1.0.1/template-operator.yaml", }, From a0b8ef8f2c140cff230ec3aca070ef6775dc6190 Mon Sep 17 00:00:00 2001 From: Hukumraj Singh Deora Date: Wed, 23 Oct 2024 10:00:58 +0200 Subject: [PATCH 08/12] refactor: Lint --- .../templategenerator/templategenerator.go | 34 +++++++++---------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/internal/service/templategenerator/templategenerator.go b/internal/service/templategenerator/templategenerator.go index 5860ca8e..08e06f1b 100644 --- a/internal/service/templategenerator/templategenerator.go +++ b/internal/service/templategenerator/templategenerator.go @@ -96,17 +96,17 @@ spec: ) type moduleTemplateData struct { - ResourceName string - Namespace string - Descriptor compdesc.ComponentDescriptorVersion - Channel string - Labels map[string]string - Annotations map[string]string - Mandatory bool - Data string + ResourceName string + Namespace string + Descriptor compdesc.ComponentDescriptorVersion + Channel string + Labels map[string]string + Annotations map[string]string + Mandatory bool + Data string AssociatedResources []*metav1.GroupVersionKind - Resources contentprovider.ResourcesMap - Manager *contentprovider.Manager + Resources contentprovider.ResourcesMap + Manager *contentprovider.Manager } func (s *Service) GenerateModuleTemplate( @@ -150,13 +150,13 @@ func (s *Service) GenerateModuleTemplate( } mtData := moduleTemplateData{ - ResourceName: moduleConfig.ResourceName, - Namespace: moduleConfig.Namespace, - Descriptor: cva, - Channel: moduleConfig.Channel, - Labels: labels, - Annotations: annotations, - Mandatory: moduleConfig.Mandatory, + ResourceName: moduleConfig.ResourceName, + Namespace: moduleConfig.Namespace, + Descriptor: cva, + Channel: moduleConfig.Channel, + Labels: labels, + Annotations: annotations, + Mandatory: moduleConfig.Mandatory, AssociatedResources: moduleConfig.AssociatedResources, Resources: contentprovider.ResourcesMap{ "rawManifest": moduleConfig.Manifest, // defaults rawManifest to Manifest; may be overwritten by explicitly provided entries From 4716394b6abbb3b46fabc6ff640f64932338e7b4 Mon Sep 17 00:00:00 2001 From: Hukumraj Singh Deora Date: Thu, 24 Oct 2024 14:27:37 +0200 Subject: [PATCH 09/12] test: Add unit test for AssociatedResources validation --- .../reader/moduleconfig_reader.go | 7 +-- .../reader/moduleconfig_reader_test.go | 43 +++++++++++++++++++ 2 files changed, 45 insertions(+), 5 deletions(-) diff --git a/internal/service/moduleconfig/reader/moduleconfig_reader.go b/internal/service/moduleconfig/reader/moduleconfig_reader.go index 6f9f45f7..4b58955c 100644 --- a/internal/service/moduleconfig/reader/moduleconfig_reader.go +++ b/internal/service/moduleconfig/reader/moduleconfig_reader.go @@ -1,7 +1,6 @@ package moduleconfigreader import ( - "errors" "fmt" "gopkg.in/yaml.v3" @@ -12,8 +11,6 @@ import ( "github.com/kyma-project/modulectl/internal/service/contentprovider" ) -var ErrNoPathForDefaultCR = errors.New("no path for default CR given") - type FileSystem interface { ReadFile(path string) ([]byte, error) } @@ -77,7 +74,7 @@ func ValidateModuleConfig(moduleConfig *contentprovider.ModuleConfig) error { } } - if err := validateAssociatedResources(moduleConfig.AssociatedResources); err != nil { + if err := ValidateAssociatedResources(moduleConfig.AssociatedResources); err != nil { return fmt.Errorf("failed to validate associated resources: %w", err) } @@ -88,7 +85,7 @@ func ValidateModuleConfig(moduleConfig *contentprovider.ModuleConfig) error { return nil } -func validateAssociatedResources(resources []*metav1.GroupVersionKind) error { +func ValidateAssociatedResources(resources []*metav1.GroupVersionKind) error { for _, resource := range resources { if err := validation.ValidateGvk(resource.Group, resource.Version, resource.Kind); err != nil { return fmt.Errorf("GVK is invalid: %w", err) diff --git a/internal/service/moduleconfig/reader/moduleconfig_reader_test.go b/internal/service/moduleconfig/reader/moduleconfig_reader_test.go index a2d15e87..9e2201fd 100644 --- a/internal/service/moduleconfig/reader/moduleconfig_reader_test.go +++ b/internal/service/moduleconfig/reader/moduleconfig_reader_test.go @@ -360,3 +360,46 @@ var errReadingFile = errors.New("some error reading file") func (*fileDoesNotExistStub) ReadFile(_ string) ([]byte, error) { return nil, errReadingFile } + +func Test_ValidateAssociatedResources(t *testing.T) { + type args struct { + resources []*metav1.GroupVersionKind + } + tests := []struct { + name string + args args + wantErr bool + }{ + {"pass on empty resources", args{resources: []*metav1.GroupVersionKind{}}, false}, + {"pass when all resources are valid", args{resources: []*metav1.GroupVersionKind{ + { + Group: "networking.istio.io", + Version: "v1alpha3", + Kind: "Gateway", + }, + { + Group: "apps", + Version: "v1", + Kind: "Deployment", + }, + }}, false}, + {"fail when even one resources is invalid", args{resources: []*metav1.GroupVersionKind{ + { + Group: "networking.istio.io", + Version: "v1alpha3", + Kind: "Gateway", + }, + { + Group: "apps", + Kind: "Deployment", + }, + }}, true}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := moduleconfigreader.ValidateAssociatedResources(tt.args.resources); (err != nil) != tt.wantErr { + t.Errorf("validateAssociatedResources() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} From de6b4d316d8e4bbe4c04d05457fa5af11332a9ad Mon Sep 17 00:00:00 2001 From: Hukumraj Singh Deora Date: Thu, 24 Oct 2024 14:32:55 +0200 Subject: [PATCH 10/12] chore: Update unit test coverage requirement --- .../reader/moduleconfig_reader_test.go | 34 +++++++++---------- unit-test-coverage.yaml | 2 +- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/internal/service/moduleconfig/reader/moduleconfig_reader_test.go b/internal/service/moduleconfig/reader/moduleconfig_reader_test.go index 9e2201fd..af2124da 100644 --- a/internal/service/moduleconfig/reader/moduleconfig_reader_test.go +++ b/internal/service/moduleconfig/reader/moduleconfig_reader_test.go @@ -345,22 +345,6 @@ var expectedReturnedModuleConfig = contentprovider.ModuleConfig{ }, } -func (*fileExistsStub) ReadFile(_ string) ([]byte, error) { - return yaml.Marshal(expectedReturnedModuleConfig) -} - -type fileDoesNotExistStub struct{} - -func (*fileDoesNotExistStub) FileExists(_ string) (bool, error) { - return false, nil -} - -var errReadingFile = errors.New("some error reading file") - -func (*fileDoesNotExistStub) ReadFile(_ string) ([]byte, error) { - return nil, errReadingFile -} - func Test_ValidateAssociatedResources(t *testing.T) { type args struct { resources []*metav1.GroupVersionKind @@ -398,8 +382,24 @@ func Test_ValidateAssociatedResources(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := moduleconfigreader.ValidateAssociatedResources(tt.args.resources); (err != nil) != tt.wantErr { - t.Errorf("validateAssociatedResources() error = %v, wantErr %v", err, tt.wantErr) + t.Errorf("ValidateAssociatedResources() error = %v, wantErr %v", err, tt.wantErr) } }) } } + +func (*fileExistsStub) ReadFile(_ string) ([]byte, error) { + return yaml.Marshal(expectedReturnedModuleConfig) +} + +type fileDoesNotExistStub struct{} + +func (*fileDoesNotExistStub) FileExists(_ string) (bool, error) { + return false, nil +} + +var errReadingFile = errors.New("some error reading file") + +func (*fileDoesNotExistStub) ReadFile(_ string) ([]byte, error) { + return nil, errReadingFile +} diff --git a/unit-test-coverage.yaml b/unit-test-coverage.yaml index 933014e3..83223ef4 100644 --- a/unit-test-coverage.yaml +++ b/unit-test-coverage.yaml @@ -8,7 +8,7 @@ packages: internal/service/filegenerator/reusefilegenerator: 94 internal/service/fileresolver: 100 internal/service/moduleconfig/generator: 100 - internal/service/moduleconfig/reader: 78 + internal/service/moduleconfig/reader: 76 internal/service/create: 43 internal/service/componentdescriptor: 78 internal/service/templategenerator: 85 From 0836eb063e645fee8bdcc367839ee77d9a9455a8 Mon Sep 17 00:00:00 2001 From: Hukumraj Singh Deora Date: Thu, 24 Oct 2024 14:40:16 +0200 Subject: [PATCH 11/12] refactor: Indentation --- .../reader/moduleconfig_reader_test.go | 98 +++++++++++-------- 1 file changed, 55 insertions(+), 43 deletions(-) diff --git a/internal/service/moduleconfig/reader/moduleconfig_reader_test.go b/internal/service/moduleconfig/reader/moduleconfig_reader_test.go index af2124da..a4cdd8b4 100644 --- a/internal/service/moduleconfig/reader/moduleconfig_reader_test.go +++ b/internal/service/moduleconfig/reader/moduleconfig_reader_test.go @@ -302,6 +302,61 @@ func Test_ValidateManager(t *testing.T) { } } +func Test_ValidateAssociatedResources(t *testing.T) { + type args struct { + resources []*metav1.GroupVersionKind + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + "pass on empty resources", + args{resources: []*metav1.GroupVersionKind{}}, + false, + }, + { + "pass when all resources are valid", + args{resources: []*metav1.GroupVersionKind{ + { + Group: "networking.istio.io", + Version: "v1alpha3", + Kind: "Gateway", + }, + { + Group: "apps", + Version: "v1", + Kind: "Deployment", + }, + }}, + false, + }, + { + "fail when even one resources is invalid", + args{resources: []*metav1.GroupVersionKind{ + { + Group: "networking.istio.io", + Version: "v1alpha3", + Kind: "Gateway", + }, + { + Group: "apps", + Kind: "Deployment", + }, + }}, + true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := moduleconfigreader.ValidateAssociatedResources(tt.args.resources); (err != nil) != tt.wantErr { + t.Errorf("ValidateAssociatedResources() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} + // Test Stubs type fileExistsStub struct{} @@ -345,49 +400,6 @@ var expectedReturnedModuleConfig = contentprovider.ModuleConfig{ }, } -func Test_ValidateAssociatedResources(t *testing.T) { - type args struct { - resources []*metav1.GroupVersionKind - } - tests := []struct { - name string - args args - wantErr bool - }{ - {"pass on empty resources", args{resources: []*metav1.GroupVersionKind{}}, false}, - {"pass when all resources are valid", args{resources: []*metav1.GroupVersionKind{ - { - Group: "networking.istio.io", - Version: "v1alpha3", - Kind: "Gateway", - }, - { - Group: "apps", - Version: "v1", - Kind: "Deployment", - }, - }}, false}, - {"fail when even one resources is invalid", args{resources: []*metav1.GroupVersionKind{ - { - Group: "networking.istio.io", - Version: "v1alpha3", - Kind: "Gateway", - }, - { - Group: "apps", - Kind: "Deployment", - }, - }}, true}, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - if err := moduleconfigreader.ValidateAssociatedResources(tt.args.resources); (err != nil) != tt.wantErr { - t.Errorf("ValidateAssociatedResources() error = %v, wantErr %v", err, tt.wantErr) - } - }) - } -} - func (*fileExistsStub) ReadFile(_ string) ([]byte, error) { return yaml.Marshal(expectedReturnedModuleConfig) } From b5c34df49960d7bf05621e99daca15ac20783be4 Mon Sep 17 00:00:00 2001 From: Hukumraj Singh Deora Date: Thu, 24 Oct 2024 14:48:45 +0200 Subject: [PATCH 12/12] refactor: Reformat Unit Test --- .../reader/moduleconfig_reader_test.go | 33 +++++++++---------- 1 file changed, 15 insertions(+), 18 deletions(-) diff --git a/internal/service/moduleconfig/reader/moduleconfig_reader_test.go b/internal/service/moduleconfig/reader/moduleconfig_reader_test.go index a4cdd8b4..8e60a6f4 100644 --- a/internal/service/moduleconfig/reader/moduleconfig_reader_test.go +++ b/internal/service/moduleconfig/reader/moduleconfig_reader_test.go @@ -303,22 +303,19 @@ func Test_ValidateManager(t *testing.T) { } func Test_ValidateAssociatedResources(t *testing.T) { - type args struct { - resources []*metav1.GroupVersionKind - } tests := []struct { - name string - args args - wantErr bool + name string + resources []*metav1.GroupVersionKind + wantErr bool }{ { - "pass on empty resources", - args{resources: []*metav1.GroupVersionKind{}}, - false, + name: "pass on empty resources", + resources: []*metav1.GroupVersionKind{}, + wantErr: false, }, { - "pass when all resources are valid", - args{resources: []*metav1.GroupVersionKind{ + name: "pass when all resources are valid", + resources: []*metav1.GroupVersionKind{ { Group: "networking.istio.io", Version: "v1alpha3", @@ -329,12 +326,12 @@ func Test_ValidateAssociatedResources(t *testing.T) { Version: "v1", Kind: "Deployment", }, - }}, - false, + }, + wantErr: false, }, { - "fail when even one resources is invalid", - args{resources: []*metav1.GroupVersionKind{ + name: "fail when even one resources is invalid", + resources: []*metav1.GroupVersionKind{ { Group: "networking.istio.io", Version: "v1alpha3", @@ -344,13 +341,13 @@ func Test_ValidateAssociatedResources(t *testing.T) { Group: "apps", Kind: "Deployment", }, - }}, - true, + }, + wantErr: true, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - if err := moduleconfigreader.ValidateAssociatedResources(tt.args.resources); (err != nil) != tt.wantErr { + if err := moduleconfigreader.ValidateAssociatedResources(tt.resources); (err != nil) != tt.wantErr { t.Errorf("ValidateAssociatedResources() error = %v, wantErr %v", err, tt.wantErr) } })