Skip to content

Commit

Permalink
feat(Maintenance Windows): Add requires downtime to moduleconfig (#132)
Browse files Browse the repository at this point in the history
* Support RequiresDowntime

* Adjust documentation

* Bump lifecycle-manager api

* Fix test

* Bump lifecycle-manager api
  • Loading branch information
nesmabadr authored Dec 24, 2024
1 parent 2f6ef4b commit fb9a7a9
Show file tree
Hide file tree
Showing 12 changed files with 152 additions and 45 deletions.
1 change: 1 addition & 0 deletions cmd/modulectl/create/long.txt
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ The module config file is a YAML file used to configure the following attributes
- resources: # a map with string keys and values, optional, additional resources of the module that may be fetched
- name: a string, required, the name of the resource
link: a URL, required, the link to the resource
- requiresDowntime: a boolean, optional, default=false, indicates whether the module requires downtime to support maintenance windows during module upgrades
```

The **manifest** file contains all the module's resources in a single, multi-document YAML file. These resources will be created in the Kyma cluster when the module is activated.
Expand Down
1 change: 1 addition & 0 deletions docs/gen-docs/modulectl_create.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ The module config file is a YAML file used to configure the following attributes
- resources: # a map with string keys and values, optional, additional resources of the module that may be fetched
- name: a string, required, the name of the resource
link: a URL, required, the link to the resource
- requiresDowntime: a boolean, optional, default=false, indicates whether the module requires downtime to support maintenance windows during module upgrades
```
The **manifest** file contains all the module's resources in a single, multi-document YAML file. These resources will be created in the Kyma cluster when the module is activated.
Expand Down
7 changes: 3 additions & 4 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
module github.com/kyma-project/modulectl

go 1.23.2
go 1.23.4

require (
github.com/Masterminds/semver/v3 v3.3.1
github.com/go-git/go-git/v5 v5.12.0
github.com/kyma-project/lifecycle-manager/api v0.0.0-20241112094726-752a03026e0d
github.com/kyma-project/lifecycle-manager/api v0.0.0-20241220120036-4210b9ef25e5
github.com/mandelsoft/vfs v0.4.4
github.com/onsi/ginkgo/v2 v2.22.0
github.com/onsi/gomega v1.36.1
Expand Down Expand Up @@ -311,7 +311,6 @@ require (
golang.org/x/time v0.7.0 // indirect
golang.org/x/tools v0.26.0 // indirect
golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da // indirect
gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect
google.golang.org/api v0.200.0 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20241007155032-5fefd90f89a9 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20241007155032-5fefd90f89a9 // indirect
Expand All @@ -331,7 +330,7 @@ require (
k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f // indirect
k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 // indirect
oras.land/oras-go v1.2.6 // indirect
sigs.k8s.io/controller-runtime v0.19.1 // indirect
sigs.k8s.io/controller-runtime v0.19.3 // indirect
sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 // indirect
sigs.k8s.io/kustomize/api v0.18.0 // indirect
sigs.k8s.io/kustomize/kyaml v0.18.1 // indirect
Expand Down
12 changes: 4 additions & 8 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -370,8 +370,6 @@ github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.m
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5/go.mod h1:a2zkGnVExMxdzMo3M0Hi/3sEU+cWnZpSni0O6/Yb/P0=
github.com/evanphx/json-patch v5.9.0+incompatible h1:fBXyNpNMuTTDdquAq/uisOr2lShz4oaXpDTX2bLe7ls=
github.com/evanphx/json-patch v5.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
github.com/evanphx/json-patch/v5 v5.9.0 h1:kcBlZQbplgElYIlo/n1hJbls2z/1awpXxpRi0/FOJfg=
github.com/evanphx/json-patch/v5 v5.9.0/go.mod h1:VNkHZ/282BpEyt/tObQO8s5CMPmYYq14uClGH4abBuQ=
github.com/exponent-io/jsonpath v0.0.0-20210407135951-1de76d718b3f h1:Wl78ApPPB2Wvf/TIe2xdyJxTlb6obmF18d8QdkxNDu4=
Expand Down Expand Up @@ -678,8 +676,8 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
github.com/kyma-project/lifecycle-manager/api v0.0.0-20241112094726-752a03026e0d h1:Y43fJO4PaZZI8Tgfh8tJIQNPZ9NdJJrieU00tCXoWJ8=
github.com/kyma-project/lifecycle-manager/api v0.0.0-20241112094726-752a03026e0d/go.mod h1:/Q0vAD9Lxzhp5BKjttYv5P/Wjhep+eBOuJirubdQUwM=
github.com/kyma-project/lifecycle-manager/api v0.0.0-20241220120036-4210b9ef25e5 h1:uMSo/hRLADb6HDVzdGCLRvHMM8V3zkxKVrdP8GuBLGk=
github.com/kyma-project/lifecycle-manager/api v0.0.0-20241220120036-4210b9ef25e5/go.mod h1:ZaRuKNJjlJpvRi2uPcZOISKGdP2b1hfvlgsDZEfgG6c=
github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
github.com/letsencrypt/boulder v0.0.0-20241010192615-6692160cedfa h1:/kPrcWfMENmWJh9AceGWaTJ0QBS3OyCDENx2vI71T8k=
Expand Down Expand Up @@ -1243,8 +1241,6 @@ golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8T
golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8=
golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da h1:noIWHXmPHxILtqtCOPIhSt0ABwskkZKjD3bXGnZGpNY=
golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da/go.mod h1:NDW/Ps6MPRej6fsCIbMTohpP40sJ/P/vI1MoTEGwX90=
gomodules.xyz/jsonpatch/v2 v2.4.0 h1:Ci3iUJyx9UeRx7CeFN8ARgGbkESwJK+KB9lLcWxY/Zw=
gomodules.xyz/jsonpatch/v2 v2.4.0/go.mod h1:AH3dM2RI6uoBZxn3LVrfvJ3E0/9dG4cSrbuBJT4moAY=
google.golang.org/api v0.200.0 h1:0ytfNWn101is6e9VBoct2wrGDjOi5vn7jw5KtaQgDrU=
google.golang.org/api v0.200.0/go.mod h1:Tc5u9kcbjO7A8SwGlYj4IiVifJU01UqXtEgDMYmBmV8=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
Expand Down Expand Up @@ -1347,8 +1343,8 @@ ocm.software/ocm v0.18.0 h1:q+h2d+V6LbcCuGibpuBnZJlRCsgoPgJIwnSk9fE0T3Q=
ocm.software/ocm v0.18.0/go.mod h1:xq9F/coh18kZtA+74PNDjlin7YenNUP1qZ4+PSGofh8=
oras.land/oras-go v1.2.6 h1:z8cmxQXBU8yZ4mkytWqXfo6tZcamPwjsuxYU81xJ8Lk=
oras.land/oras-go v1.2.6/go.mod h1:OVPc1PegSEe/K8YiLfosrlqlqTN9PUyFvOw5Y9gwrT8=
sigs.k8s.io/controller-runtime v0.19.1 h1:Son+Q40+Be3QWb+niBXAg2vFiYWolDjjRfO8hn/cxOk=
sigs.k8s.io/controller-runtime v0.19.1/go.mod h1:iRmWllt8IlaLjvTTDLhRBXIEtkCK6hwVBJJsYS9Ajf4=
sigs.k8s.io/controller-runtime v0.19.3 h1:XO2GvC9OPftRst6xWCpTgBZO04S2cbp0Qqkj8bX1sPw=
sigs.k8s.io/controller-runtime v0.19.3/go.mod h1:j4j87DqtsThvwTv5/Tc5NFRyyF/RF0ip4+62tbTSIUM=
sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 h1:gBQPwqORJ8d8/YNZWEjoZs7npUVDpVXUUOFfW6CgAqE=
sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8/go.mod h1:mdzfpAEoE6DHQEN0uh9ZbOCuHbLK5wOm7dK4ctXE9Tg=
sigs.k8s.io/kustomize/api v0.18.0 h1:hTzp67k+3NEVInwz5BHyzc9rGxIauoXferXyjv5lWPo=
Expand Down
1 change: 1 addition & 0 deletions internal/service/contentprovider/moduleconfig.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ type ModuleConfig struct {
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 Resources `yaml:"resources,omitempty" comment:"optional, additional resources of the ModuleTemplate that may be fetched"`
RequiresDowntime bool `yaml:"requiresDowntime" comment:"optional, default=false, indicates whether the module requires downtime to support maintenance windows during module upgrades"`
}

type Manager struct {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -118,15 +118,16 @@ func (*fileExistsStub) FileExists(_ string) (bool, error) {

func (*fileExistsStub) ReadFile(_ string) ([]byte, error) {
moduleConfig := contentprovider.ModuleConfig{
Name: "module-name",
Version: "0.0.1",
Manifest: "path/to/manifests",
Mandatory: false,
DefaultCR: "path/to/defaultCR",
Namespace: "kcp-system",
Security: "path/to/securityConfig",
Labels: map[string]string{"label1": "value1"},
Annotations: map[string]string{"annotation1": "value1"},
Name: "module-name",
Version: "0.0.1",
Manifest: "path/to/manifests",
Mandatory: false,
RequiresDowntime: false,
DefaultCR: "path/to/defaultCR",
Namespace: "kcp-system",
Security: "path/to/securityConfig",
Labels: map[string]string{"label1": "value1"},
Annotations: map[string]string{"annotation1": "value1"},
AssociatedResources: []*metav1.GroupVersionKind{
{
Group: "networking.istio.io",
Expand Down
23 changes: 14 additions & 9 deletions internal/service/moduleconfig/reader/moduleconfig_reader_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ func Test_ParseModuleConfig_Returns_CorrectModuleConfig(t *testing.T) {
"module-icon": "https://example.com/path/to/some-icon",
}, result.Icons)
require.False(t, result.Mandatory)
require.False(t, result.RequiresDowntime)
require.Equal(t, "kcp-system", result.Namespace)
require.Equal(t, "path/to/securityConfig", result.Security)
require.Equal(t, map[string]string{"label1": "value1"}, result.Labels)
Expand Down Expand Up @@ -86,7 +87,8 @@ func Test_ValidateModuleConfig(t *testing.T) {
"module-icon": "https://example.com/path/to/some-icon",
},
},
expectedError: fmt.Errorf("opts.ModuleName must match the required pattern, e.g: 'github.com/path-to/your-repo': %w", commonerrors.ErrInvalidOption),
expectedError: fmt.Errorf("opts.ModuleName must match the required pattern, e.g: 'github.com/path-to/your-repo': %w",
commonerrors.ErrInvalidOption),
},
{
name: "invalid module version",
Expand All @@ -101,7 +103,8 @@ func Test_ValidateModuleConfig(t *testing.T) {
"module-icon": "https://example.com/path/to/some-icon",
},
},
expectedError: fmt.Errorf("opts.ModuleVersion failed to be parsed as semantic version: %w", commonerrors.ErrInvalidOption),
expectedError: fmt.Errorf("opts.ModuleVersion failed to be parsed as semantic version: %w",
commonerrors.ErrInvalidOption),
},
{
name: "invalid module namespace",
Expand All @@ -116,7 +119,8 @@ func Test_ValidateModuleConfig(t *testing.T) {
"module-icon": "https://example.com/path/to/some-icon",
},
},
expectedError: fmt.Errorf("namespace must match the required pattern, only small alphanumeric characters and hyphens: %w", commonerrors.ErrInvalidOption),
expectedError: fmt.Errorf("namespace must match the required pattern, only small alphanumeric characters and hyphens: %w",
commonerrors.ErrInvalidOption),
},
{
name: "empty manifest path",
Expand Down Expand Up @@ -530,12 +534,13 @@ var expectedReturnedModuleConfig = contentprovider.ModuleConfig{
Icons: contentprovider.Icons{
"module-icon": "https://example.com/path/to/some-icon",
},
Mandatory: false,
DefaultCR: "https://example.com/path/to/defaultCR",
Namespace: "kcp-system",
Security: "path/to/securityConfig",
Labels: map[string]string{"label1": "value1"},
Annotations: map[string]string{"annotation1": "value1"},
Mandatory: false,
RequiresDowntime: false,
DefaultCR: "https://example.com/path/to/defaultCR",
Namespace: "kcp-system",
Security: "path/to/securityConfig",
Labels: map[string]string{"label1": "value1"},
Annotations: map[string]string{"annotation1": "value1"},
AssociatedResources: []*metav1.GroupVersionKind{
{
Group: "networking.istio.io",
Expand Down
5 changes: 4 additions & 1 deletion internal/service/templategenerator/templategenerator.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ spec:
moduleName: {{.ModuleName}}
version: {{.ModuleVersion}}
mandatory: {{.Mandatory}}
requiresDowntime: {{.RequiresDowntime}}
info:
repository: {{.Repository}}
documentation: {{.Documentation}}
Expand Down Expand Up @@ -122,6 +123,7 @@ type moduleTemplateData struct {
AssociatedResources []*metav1.GroupVersionKind
Resources contentprovider.Resources
Manager *contentprovider.Manager
RequiresDowntime bool
}

func (s *Service) GenerateModuleTemplate(
Expand Down Expand Up @@ -178,7 +180,8 @@ func (s *Service) GenerateModuleTemplate(
Resources: contentprovider.Resources{
"rawManifest": moduleConfig.Manifest, // defaults rawManifest to Manifest; may be overwritten by explicitly provided entries
},
Manager: moduleConfig.Manager,
Manager: moduleConfig.Manager,
RequiresDowntime: moduleConfig.RequiresDowntime,
}

if len(data) > 0 {
Expand Down
69 changes: 69 additions & 0 deletions internal/service/templategenerator/templategenerator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,75 @@ func TestGenerateModuleTemplateWithMandatoryFalse_Success(t *testing.T) {
"\"operator.kyma-project.io/mandatory-module\"")
}

func TestGenerateModuleTemplateWithRequiresDowntimeFalse_Success(t *testing.T) {
mockFS := &mockFileSystem{}
svc, _ := templategenerator.NewService(mockFS)

moduleConfig := &contentprovider.ModuleConfig{
Namespace: "default",
Version: "1.0.0",
Labels: map[string]string{"key": "value"},
Annotations: map[string]string{"annotation": "value"},
Mandatory: false,
RequiresDowntime: false,
Manifest: "https://github.com/kyma-project/template-operator/releases/download/1.0.1/template-operator.yaml",
Resources: contentprovider.Resources{"someResource": "https://some.other/location/template-operator.yaml"},
}
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, "version: 1.0.0")
require.Contains(t, mockFS.writtenTemplate, "moduleName: component")
require.Contains(t, mockFS.writtenTemplate, "component-1.0.0")
require.Contains(t, mockFS.writtenTemplate, "default")
require.Contains(t, mockFS.writtenTemplate, "test-data")
require.Contains(t, mockFS.writtenTemplate, "example.com/component")
require.Contains(t, mockFS.writtenTemplate, "someResource")
require.Contains(t, mockFS.writtenTemplate, "https://some.other/location/template-operator.yaml")
require.Contains(t, mockFS.writtenTemplate, "rawManifest")
require.Contains(t, mockFS.writtenTemplate,
"https://github.com/kyma-project/template-operator/releases/download/1.0.1/template-operator.yaml")
require.Contains(t, mockFS.writtenTemplate, "requiresDowntime: false")
}

func TestGenerateModuleTemplateWithRequiresDowntimeTrue_Success(t *testing.T) {
mockFS := &mockFileSystem{}
svc, _ := templategenerator.NewService(mockFS)

moduleConfig := &contentprovider.ModuleConfig{
Namespace: "default",
Version: "1.0.0",
Labels: map[string]string{"key": "value"},
Annotations: map[string]string{"annotation": "value"},
RequiresDowntime: true,
Manifest: "https://github.com/kyma-project/template-operator/releases/download/1.0.1/template-operator.yaml",
Resources: contentprovider.Resources{"someResource": "https://some.other/location/template-operator.yaml"},
}
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, "version: 1.0.0")
require.Contains(t, mockFS.writtenTemplate, "moduleName: component")
require.Contains(t, mockFS.writtenTemplate, "component-1.0.0")
require.Contains(t, mockFS.writtenTemplate, "default")
require.Contains(t, mockFS.writtenTemplate, "test-data")
require.Contains(t, mockFS.writtenTemplate, "example.com/component")
require.Contains(t, mockFS.writtenTemplate, "someResource")
require.Contains(t, mockFS.writtenTemplate, "https://some.other/location/template-operator.yaml")
require.Contains(t, mockFS.writtenTemplate, "rawManifest")
require.Contains(t, mockFS.writtenTemplate,
"https://github.com/kyma-project/template-operator/releases/download/1.0.1/template-operator.yaml")
require.Contains(t, mockFS.writtenTemplate, "requiresDowntime: true")
}

type mockFileSystem struct {
path, writtenTemplate string
}
Expand Down
1 change: 1 addition & 0 deletions tests/e2e/create/create_suite_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ const (
withResourcesOverwrite = validConfigs + "with-resources-overwrite.yaml"
withManagerConfig = validConfigs + "with-manager.yaml"
withNoNamespaceManagerConfig = validConfigs + "with-manager-no-namespace.yaml"
withRequiresDowntimeConfig = validConfigs + "with-requiresDowntime.yaml"

ociRegistry = "http://k3d-oci.localhost:5001"
templateOutputPath = "/tmp/template.yaml"
Expand Down
49 changes: 35 additions & 14 deletions tests/e2e/create/create_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -366,6 +366,9 @@ var _ = Describe("Test 'create' command", Ordered, func() {
Expect(template.Spec.Resources).To(HaveLen(1))
Expect(template.Spec.Resources[0].Name).To(Equal("rawManifest"))
Expect(template.Spec.Resources[0].Link).To(Equal("https://github.com/kyma-project/template-operator/releases/download/1.0.1/template-operator.yaml"))

By("And spec.requiresDowntime should be set to false")
Expect(template.Spec.RequiresDowntime).To(BeFalse())
})
})

Expand Down Expand Up @@ -801,6 +804,36 @@ var _ = Describe("Test 'create' command", Ordered, func() {
Expect(err.Error()).Should(ContainSubstring("failed to parse module config: failed to validate module config: failed to validate default CR: '/tmp/default-sample-cr.yaml' is not using https scheme: invalid Option"))
})
})

Context("Given 'modulectl create' command", func() {
var cmd createCmd
It("When invoked with valid module-config containing requiresDowntime true and different version", func() {
cmd = createCmd{
moduleConfigFile: withRequiresDowntimeConfig,
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())
Expect(template.Name).To(Equal("template-operator-1.0.10"))
Expect(template.Spec.ModuleName).To(Equal("template-operator"))
Expect(template.Spec.Version).To(Equal("1.0.10"))

By("And module template should have spec.requiresDowntime set to true")
Expect(template.Spec.RequiresDowntime).To(BeTrue())
})
})
})

// Test helper functions
Expand All @@ -818,27 +851,15 @@ func readModuleTemplate(filepath string) (*v1beta2.ModuleTemplate, error) {
return moduleTemplate, err
}

func getDescriptor(template *v1beta2.ModuleTemplate) *v1beta2.Descriptor {
if template.Spec.Descriptor.Object != nil {
desc, ok := template.Spec.Descriptor.Object.(*v1beta2.Descriptor)
if !ok || desc == nil {
return nil
}
return desc
}
func getDescriptor(template *v1beta2.ModuleTemplate) *compdesc.ComponentDescriptor {
ocmDesc, err := compdesc.Decode(
template.Spec.Descriptor.Raw,
[]compdesc.DecodeOption{compdesc.DisableValidation(true)}...)
if err != nil {
return nil
}
template.Spec.Descriptor.Object = &v1beta2.Descriptor{ComponentDescriptor: ocmDesc}
desc, ok := template.Spec.Descriptor.Object.(*v1beta2.Descriptor)
if !ok {
return nil
}

return desc
return ocmDesc
}

func flatten(labels ocmv1.Labels) map[string]string {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
name: kyma-project.io/module/template-operator
version: 1.0.10
manifest: https://github.com/kyma-project/template-operator/releases/download/1.0.1/template-operator.yaml
repository: https://github.com/kyma-project/template-operator
documentation: https://github.com/kyma-project/template-operator/blob/main/README.md
icons:
- name: module-icon
link: https://github.com/kyma-project/template-operator/blob/main/docs/assets/logo.png
requiresDowntime: true

0 comments on commit fb9a7a9

Please sign in to comment.