Skip to content

Commit

Permalink
fix: module delete should work with old module templates (#2326)
Browse files Browse the repository at this point in the history
  • Loading branch information
halamix2 authored Jan 23, 2025
1 parent e7fa138 commit 99785db
Show file tree
Hide file tree
Showing 4 changed files with 120 additions and 27 deletions.
17 changes: 17 additions & 0 deletions internal/kube/kyma/compatibility.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package kyma

import (
"fmt"
)

// Compatibility, remove when old moduleTemplate definitions are removed
// getOldModuleTemplate returns matching ModuleTemplate from list, based on old ModuleTemplate definitions
func getOldModuleTemplate(moduleTemplates *ModuleTemplateList, moduleName, moduleChannel string) *ModuleTemplate {
for _, moduleTemplate := range moduleTemplates.Items {
// old module templates have name in moduleName-moduleChannel format
if moduleTemplate.ObjectMeta.Name == fmt.Sprintf("%s-%s", moduleName, moduleChannel) {
return &moduleTemplate
}
}
return nil
}
50 changes: 43 additions & 7 deletions internal/kube/kyma/kyma.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@ import (
"context"
"errors"
"fmt"
"k8s.io/utils/ptr"
"slices"

"k8s.io/utils/ptr"

metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime"
Expand Down Expand Up @@ -73,20 +74,55 @@ func (c *client) GetModuleReleaseMetaForModule(ctx context.Context, moduleName s
}

// GetModuleTemplateForModule returns ModuleTemplate CR corelated with given module name in right version
func (c *client) GetModuleTemplateForModule(ctx context.Context, moduleName, moduleVersion string) (*ModuleTemplate, error) {
func (c *client) GetModuleTemplateForModule(ctx context.Context, moduleName, moduleChannel string) (*ModuleTemplate, error) {
moduleTemplates, err := c.ListModuleTemplate(ctx)
if err != nil {
return nil, err
}

for _, moduleTemplate := range moduleTemplates.Items {
if moduleTemplate.Spec.ModuleName == moduleName &&
moduleTemplate.Spec.Version == moduleVersion {
return &moduleTemplate, nil
// get ModuleReleaseMeta if the CRD exists
moduleReleaseMeta, err := c.GetModuleReleaseMetaForModule(ctx, moduleName)
if err != nil {
// new modules not detected, going old route
moduleTemplate := getOldModuleTemplate(moduleTemplates, moduleName, moduleChannel)
if moduleTemplate != nil {
return moduleTemplate, nil
}
return nil, fmt.Errorf("can't find neither ModuleReleaseMeta CR/CRD nor ModuleTemplate CR for module %s in channel %s", moduleName, moduleChannel)
}

moduleVersion := getModuleVersionForChannel(moduleReleaseMeta, moduleChannel)
if moduleVersion == "" {
return nil, fmt.Errorf("can't find ModuleReleaseMeta CR for module %s in channel %s", moduleName, moduleChannel)
}

ModuleTemplate := getModuleTemplate(moduleTemplates, moduleName, moduleVersion)
if ModuleTemplate != nil {
return ModuleTemplate, nil
}

return nil, fmt.Errorf("can't find ModuleTemplate CR for module %s in channel %s", moduleName, moduleChannel)
}

// getModuleVersionForChannel returns version of the module for given channel
func getModuleVersionForChannel(moduleReleaseMeta *ModuleReleaseMeta, moduleChannel string) string {
for _, channel := range moduleReleaseMeta.Spec.Channels {
if channel.Channel == moduleChannel {
return channel.Version
}
}
return ""
}

return nil, fmt.Errorf("can't find ModuleTemplate CR for module %s in version %s", moduleName, moduleVersion)
// getModuleTemplate returns matching ModuleTemplate from list
func getModuleTemplate(moduleTemplates *ModuleTemplateList, moduleName, moduleVersion string) *ModuleTemplate {
// we can either look for moduleTemplates named moduleName-moduleVersion or look for the same info in .Spec
for _, moduleTemplate := range moduleTemplates.Items {
if moduleTemplate.Spec.ModuleName == moduleName && moduleTemplate.Spec.Version == moduleVersion {
return &moduleTemplate
}
}
return nil
}

// GetDefaultKyma gets the default Kyma CR from the kyma-system namespace and cast it to the Kyma structure
Expand Down
78 changes: 59 additions & 19 deletions internal/kube/kyma/kyma_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@ package kyma
import (
"context"
"encoding/json"
"k8s.io/utils/ptr"
"fmt"
"reflect"
"testing"

"k8s.io/utils/ptr"

"github.com/stretchr/testify/require"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
Expand Down Expand Up @@ -438,16 +440,16 @@ func Test_client_ListModuleTemplate(t *testing.T) {
scheme := runtime.NewScheme()
scheme.AddKnownTypes(GVRModuleTemplate.GroupVersion())
client := NewClient(dynamic_fake.NewSimpleDynamicClient(scheme,
fixModuleTemplate("test-1"),
fixModuleTemplate("test-2"),
fixModuleTemplate("test-1", "0.1", ""),
fixModuleTemplate("test-2", "0.1", ""),
))

list, err := client.ListModuleTemplate(context.Background())

require.NoError(t, err)
require.Len(t, list.Items, 2)
require.Contains(t, list.Items, fixModuleTemplateStruct("test-1"))
require.Contains(t, list.Items, fixModuleTemplateStruct("test-2"))
require.Contains(t, list.Items, fixModuleTemplateStruct("test-1", "0.1", ""))
require.Contains(t, list.Items, fixModuleTemplateStruct("test-2", "0.1", ""))

})
}
Expand Down Expand Up @@ -486,28 +488,47 @@ func Test_client_GetModuleTemplateForModule(t *testing.T) {
t.Run("get module ModuleTemplate", func(t *testing.T) {
scheme := runtime.NewScheme()
scheme.AddKnownTypes(GVRModuleTemplate.GroupVersion())
scheme.AddKnownTypes(GVRModuleReleaseMeta.GroupVersion())
client := NewClient(dynamic_fake.NewSimpleDynamicClient(scheme,
fixModuleTemplate("test-1"),
fixModuleTemplate("test-2"),
fixModuleTemplate("test-1", "0.1", ""),
fixModuleTemplate("test-2", "0.1", ""),
fixModuleReleaseMeta("test-2"),
))
// NewSimpleDynamicClientWithCustomListKinds
got, err := client.GetModuleTemplateForModule(context.Background(), "test-2", "regular")

got, err := client.GetModuleTemplateForModule(context.Background(), "test-2", "0.1")
require.NoError(t, err)
require.Equal(t, fixModuleTemplateStruct("test-2", "0.1", ""), *got)
})

t.Run("get module ModuleTemplate for old module", func(t *testing.T) {
scheme := runtime.NewScheme()
scheme.AddKnownTypes(GVRModuleTemplate.GroupVersion())
client := NewClient(dynamic_fake.NewSimpleDynamicClient(scheme,
fixModuleTemplate("test-1", "0.1", ""),
fixModuleTemplate("test-2", "0.1", ""),
fixModuleTemplate("test", "", "fast"),
fixModuleReleaseMeta("test-2"),
))

got, err := client.GetModuleTemplateForModule(context.Background(), "test", "fast")

require.NoError(t, err)
require.Equal(t, fixModuleTemplateStruct("test-2"), *got)
require.Equal(t, fixModuleTemplateStruct("test", "", "fast"), *got)
})

t.Run("no ModuleReleaseMeta for module", func(t *testing.T) {
scheme := runtime.NewScheme()
scheme.AddKnownTypes(GVRModuleTemplate.GroupVersion())
client := NewClient(dynamic_fake.NewSimpleDynamicClient(scheme,
fixModuleTemplate("test-1"),
fixModuleTemplate("test-2"),
fixModuleTemplate("test-1", "0.1", ""),
fixModuleTemplate("test-2", "0.1", ""),
fixModuleReleaseMeta("test-1"),
))

got, err := client.GetModuleTemplateForModule(context.Background(), "test-2", "0.2")
got, err := client.GetModuleTemplateForModule(context.Background(), "test-2", "fast")

require.ErrorContains(t, err, "can't find ModuleTemplate CR for module test-2 in version 0.2")
require.ErrorContains(t, err, "can't find neither ModuleReleaseMeta CR/CRD nor ModuleTemplate CR for module test-2 in channel fast")
require.Nil(t, got)
})
}
Expand Down Expand Up @@ -569,8 +590,8 @@ func fixModuleReleaseMetaStruct(moduleName string) ModuleReleaseMeta {
}
}

func fixModuleTemplateStruct(moduleName string) ModuleTemplate {
return ModuleTemplate{
func fixModuleTemplateStruct(moduleName, moduleVersion, moduleChannel string) ModuleTemplate {
mt := ModuleTemplate{
TypeMeta: v1.TypeMeta{
APIVersion: "operator.kyma-project.io/v1beta2",
Kind: "ModuleTemplate",
Expand All @@ -581,9 +602,18 @@ func fixModuleTemplateStruct(moduleName string) ModuleTemplate {
},
Spec: ModuleTemplateSpec{
ModuleName: moduleName,
Version: "0.1",
},
}
if moduleVersion != "" {
mt.ObjectMeta.Name = fmt.Sprintf("%s-%s", moduleName, moduleVersion)
mt.Spec.Version = moduleVersion
}
if moduleChannel != "" {
mt.ObjectMeta.Name = fmt.Sprintf("%s-%s", moduleName, moduleChannel)
mt.Spec.Channel = moduleChannel
}

return mt
}

func fixModuleReleaseMeta(moduleName string) *unstructured.Unstructured {
Expand Down Expand Up @@ -612,8 +642,8 @@ func fixModuleReleaseMeta(moduleName string) *unstructured.Unstructured {
}
}

func fixModuleTemplate(moduleName string) *unstructured.Unstructured {
return &unstructured.Unstructured{
func fixModuleTemplate(moduleName, moduleVersion, moduleChannel string) *unstructured.Unstructured {
mt := &unstructured.Unstructured{
Object: map[string]interface{}{
"apiVersion": "operator.kyma-project.io/v1beta2",
"kind": "ModuleTemplate",
Expand All @@ -623,10 +653,20 @@ func fixModuleTemplate(moduleName string) *unstructured.Unstructured {
},
"spec": map[string]interface{}{
"moduleName": moduleName,
"version": "0.1",
},
},
}

if moduleVersion != "" {
_ = unstructured.SetNestedField(mt.Object, fmt.Sprintf("%s-%s", moduleName, moduleVersion), "metadata", "name")
_ = unstructured.SetNestedField(mt.Object, moduleVersion, "spec", "version")
}
if moduleChannel != "" {
_ = unstructured.SetNestedField(mt.Object, fmt.Sprintf("%s-%s", moduleName, moduleChannel), "metadata", "name")
_ = unstructured.SetNestedField(mt.Object, moduleChannel, "spec", "channel")
}

return mt
}

func Test_manageModule(t *testing.T) {
Expand Down
2 changes: 1 addition & 1 deletion internal/modules/disable.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ func removeModuleCR(writer io.Writer, ctx context.Context, client kube.Client, m
return nil
}

moduleTemplate, err := client.Kyma().GetModuleTemplateForModule(ctx, info.Status.Name, info.Status.Version)
moduleTemplate, err := client.Kyma().GetModuleTemplateForModule(ctx, info.Status.Name, info.Status.Channel)
if err != nil {
return clierror.Wrap(err, clierror.New("failed to get ModuleTemplate CR for module"))
}
Expand Down

0 comments on commit 99785db

Please sign in to comment.