Skip to content

Commit

Permalink
add disable module
Browse files Browse the repository at this point in the history
  • Loading branch information
pPrecel committed Dec 14, 2024
1 parent 547adf9 commit f7f774a
Show file tree
Hide file tree
Showing 9 changed files with 623 additions and 17 deletions.
42 changes: 42 additions & 0 deletions internal/cmd/alpha/module/disable.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package module

import (
"github.com/kyma-project/cli.v3/internal/clierror"
"github.com/kyma-project/cli.v3/internal/cmdcommon"
"github.com/kyma-project/cli.v3/internal/modules"
"github.com/spf13/cobra"
)

type disableConfig struct {
*cmdcommon.KymaConfig

module string
}

func newDisableCMD(kymaConfig *cmdcommon.KymaConfig) *cobra.Command {
cfg := disableConfig{
KymaConfig: kymaConfig,
}

cmd := &cobra.Command{
Use: "disable",
Short: "Disable module",
Long: "Use this command to disable module",
Args: cobra.ExactArgs(1),
Run: func(cmd *cobra.Command, args []string) {
cfg.module = args[0]
clierror.Check(runDisable(&cfg))
},
}

return cmd
}

func runDisable(cfg *disableConfig) clierror.Error {
client, clierr := cfg.GetKubeClientWithClierr()
if clierr != nil {
return clierr
}

return modules.Disable(cfg.Ctx, client, cfg.module)
}
1 change: 1 addition & 0 deletions internal/cmd/alpha/module/module.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ func NewModuleCMD(kymaConfig *cmdcommon.KymaConfig) *cobra.Command {

cmd.AddCommand(newListCMD(kymaConfig))
cmd.AddCommand(newEnableCMD(kymaConfig))
cmd.AddCommand(newDisableCMD(kymaConfig))

return cmd
}
37 changes: 36 additions & 1 deletion internal/kube/kyma/kyma.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,12 @@ const (
type Interface interface {
ListModuleReleaseMeta(context.Context) (*ModuleReleaseMetaList, error)
ListModuleTemplate(context.Context) (*ModuleTemplateList, error)
GetModuleReleaseMetaForModule(context.Context, string) (*ModuleReleaseMeta, error)
GetModuleTemplateForModule(context.Context, string, string) (*ModuleTemplate, error)
GetDefaultKyma(context.Context) (*Kyma, error)
UpdateDefaultKyma(context.Context, *Kyma) error
WaitForModuleState(context.Context, string, ...string) error
GetModuleInfo(context.Context, string) (*KymaModuleInfo, error)
WaitForModuleState(context.Context, string, ...string) error
EnableModule(context.Context, string, string, string) error
DisableModule(context.Context, string) error
}
Expand All @@ -52,6 +54,39 @@ func (c *client) ListModuleTemplate(ctx context.Context) (*ModuleTemplateList, e
return list[ModuleTemplateList](ctx, c.dynamic, GVRModuleTemplate)
}

// GetModuleReleaseMetaForModule returns right ModuleReleaseMeta CR corelated with given module name
func (c *client) GetModuleReleaseMetaForModule(ctx context.Context, moduleName string) (*ModuleReleaseMeta, error) {
list, err := c.ListModuleReleaseMeta(ctx)
if err != nil {
return nil, err
}

for _, releaseMeta := range list.Items {
if releaseMeta.Spec.ModuleName == moduleName {
return &releaseMeta, nil
}
}

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

// GetModuleTemplateForModule returns ModuleTemplate CR corelated with given module name in right version
func (c *client) GetModuleTemplateForModule(ctx context.Context, moduleName, moduleVersion 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
}
}

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

// GetDefaultKyma gets the default Kyma CR from the kyma-system namespace and cast it to the Kyma structure
func (c *client) GetDefaultKyma(ctx context.Context) (*Kyma, error) {
u, err := c.dynamic.Resource(GVRKyma).
Expand Down
62 changes: 61 additions & 1 deletion internal/kube/kyma/kyma_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -433,7 +433,7 @@ func Test_client_ListModuleReleaseMeta(t *testing.T) {
}

func Test_client_ListModuleTemplate(t *testing.T) {
t.Run("list ModuleReleaseMeta", func(t *testing.T) {
t.Run("list ModuleTemplate", func(t *testing.T) {
scheme := runtime.NewScheme()
scheme.AddKnownTypes(GVRModuleTemplate.GroupVersion())
client := NewClient(dynamic_fake.NewSimpleDynamicClient(scheme,
Expand All @@ -451,6 +451,66 @@ func Test_client_ListModuleTemplate(t *testing.T) {
})
}

func Test_client_GetModuleReleaseMetaForModule(t *testing.T) {
t.Run("get module ModuleReleaseMeta", func(t *testing.T) {
scheme := runtime.NewScheme()
scheme.AddKnownTypes(GVRModuleReleaseMeta.GroupVersion())
client := NewClient(dynamic_fake.NewSimpleDynamicClient(scheme,
fixModuleReleaseMeta("test-1"),
fixModuleReleaseMeta("test-2"),
))

got, err := client.GetModuleReleaseMetaForModule(context.Background(), "test-2")

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

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

got, err := client.GetModuleReleaseMetaForModule(context.Background(), "test-123")

require.ErrorContains(t, err, "can't find ModuleReleaseMeta CR for module test-123")
require.Nil(t, got)
})
}

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

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

require.NoError(t, err)
require.Equal(t, fixModuleTemplateStruct("test-2"), *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"),
))

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

require.ErrorContains(t, err, "can't find ModuleTemplate CR for module test-2 in version 0.2")
require.Nil(t, got)
})
}

func Test_client_GetModuleInfo(t *testing.T) {
t.Run("get ModuleInfo", func(t *testing.T) {
scheme := runtime.NewScheme()
Expand Down
21 changes: 19 additions & 2 deletions internal/kube/rootlessdynamic/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ package rootlessdynamic
import (
"context"
"fmt"
"k8s.io/apimachinery/pkg/api/errors"
"strings"

"k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime/schema"
Expand All @@ -17,6 +17,7 @@ type applyFunc func(context.Context, dynamic.ResourceInterface, *unstructured.Un

type Interface interface {
Get(context.Context, *unstructured.Unstructured) (*unstructured.Unstructured, error)
List(context.Context, *unstructured.Unstructured) (*unstructured.UnstructuredList, error)
Apply(context.Context, *unstructured.Unstructured) error
ApplyMany(context.Context, []unstructured.Unstructured) error
Remove(context.Context, *unstructured.Unstructured) error
Expand Down Expand Up @@ -57,11 +58,27 @@ func (c *client) Get(ctx context.Context, resource *unstructured.Unstructured) (
}

if apiResource.Namespaced {
return c.dynamic.Resource(*gvr).Namespace("kyma-system").Get(ctx, resource.GetName(), metav1.GetOptions{})
return c.dynamic.Resource(*gvr).Namespace(resource.GetNamespace()).Get(ctx, resource.GetName(), metav1.GetOptions{})
}
return c.dynamic.Resource(*gvr).Get(ctx, resource.GetName(), metav1.GetOptions{})
}

func (c *client) List(ctx context.Context, resource *unstructured.Unstructured) (*unstructured.UnstructuredList, error) {
group, version := groupVersion(resource.GetAPIVersion())
apiResource, err := c.discoverAPIResource(group, version, resource.GetKind())
if err != nil {
return nil, fmt.Errorf("failed to discover API resource using discovery client: %w", err)
}

gvr := &schema.GroupVersionResource{
Group: group,
Version: version,
Resource: apiResource.Name,
}

return c.dynamic.Resource(*gvr).List(ctx, metav1.ListOptions{})
}

func (c *client) Apply(ctx context.Context, resource *unstructured.Unstructured) error {
group, version := groupVersion(resource.GetAPIVersion())
apiResource, err := c.discoverAPIResource(group, version, resource.GetKind())
Expand Down
68 changes: 68 additions & 0 deletions internal/kube/rootlessdynamic/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,74 @@ func Test_Get(t *testing.T) {
})
}

var (
secretListObject = map[string]interface{}{
"apiVersion": "v1",
"kind": "SecretList",
"metadata": map[string]interface{}{
"continue": "",
"resourceVersion": "",
},
}

clusterRoleListObject = map[string]interface{}{
"apiVersion": "rbac.authorization.k8s.io/v1",
"kind": "ClusterRoleList",
"metadata": map[string]interface{}{
"continue": "",
"resourceVersion": "",
},
}
)

func Test_List(t *testing.T) {
t.Run("list namespaced resource", func(t *testing.T) {
obj, apiResource := fixSecretObjectAndApiResource()
ctx := context.Background()
dynamic := dynamic_fake.NewSimpleDynamicClient(scheme.Scheme, obj)
client := fixRootlessDynamic(dynamic, []*metav1.APIResourceList{apiResource})

expectedResult := &unstructured.UnstructuredList{
Object: secretListObject,
Items: []unstructured.Unstructured{*obj},
}

result, err := client.List(ctx, obj)
require.NoError(t, err)
require.Equal(t, expectedResult, result)
})

t.Run("list cluster-scoped resource", func(t *testing.T) {
obj, apiResource := fixClusterRoleObjectAndApiResource()
ctx := context.Background()
dynamic := dynamic_fake.NewSimpleDynamicClient(scheme.Scheme, obj)
client := fixRootlessDynamic(dynamic, []*metav1.APIResourceList{apiResource})

expectedResult := &unstructured.UnstructuredList{
Object: clusterRoleListObject,
Items: []unstructured.Unstructured{*obj},
}

result, err := client.List(ctx, obj)
require.NoError(t, err)
require.Equal(t, expectedResult, result)
})

t.Run("get resource error because can't be discovered", func(t *testing.T) {
obj, _ := fixSecretObjectAndApiResource()
ctx := context.Background()
dynamic := dynamic_fake.NewSimpleDynamicClient(scheme.Scheme)
client := fixRootlessDynamic(dynamic, []*metav1.APIResourceList{
{
GroupVersion: "v1",
},
})

_, err := client.List(ctx, obj)
require.ErrorContains(t, err, "failed to discover API resource using discovery client: resource 'Secret' in group '', and version 'v1' not registered on cluster")
})
}

func Test_Remove(t *testing.T) {
t.Run("remove namespaced resource", func(t *testing.T) {
obj, apiResource := fixSecretObjectAndApiResource()
Expand Down
Loading

0 comments on commit f7f774a

Please sign in to comment.