From 596c5d6e3d1599b8a76ffc199776e7fd4717b607 Mon Sep 17 00:00:00 2001 From: Adam Sadek <33073174+AdamSadek@users.noreply.github.com> Date: Sun, 19 Apr 2026 17:53:05 +0100 Subject: [PATCH] Extend log-level commands to support managed clusters log-level set/show/unset previously operated only on the management cluster. Add optional --namespace, --clusterName and --clusterType flags so that DebuggingConfiguration can also be read and written in managed clusters (both Capi and Sveltos) via libsveltos/clusterproxy.GetKubernetesClient. Behavior without those flags is unchanged. Fixes #41 --- internal/commands/loglevel/export_test.go | 11 ++- internal/commands/loglevel/set.go | 75 +++++++++++---- internal/commands/loglevel/set_test.go | 108 +++++++++++++++++++++ internal/commands/loglevel/show.go | 60 +++++++++--- internal/commands/loglevel/show_test.go | 29 ++++++ internal/commands/loglevel/unset.go | 83 +++++++++++----- internal/commands/loglevel/unset_test.go | 44 +++++++++ internal/commands/loglevel/utils.go | 110 ++++++++++++++++++++++ 8 files changed, 467 insertions(+), 53 deletions(-) diff --git a/internal/commands/loglevel/export_test.go b/internal/commands/loglevel/export_test.go index 96ee7aa8..5f52efc3 100644 --- a/internal/commands/loglevel/export_test.go +++ b/internal/commands/loglevel/export_test.go @@ -17,7 +17,12 @@ limitations under the License. package loglevel var ( - ShowLogSettings = showLogSettings - UpdateDebuggingConfiguration = updateDebuggingConfiguration - UnsetDebuggingConfiguration = unsetDebuggingConfiguration + ShowLogSettings = showLogSettings + UpdateDebuggingConfiguration = updateDebuggingConfiguration + UnsetDebuggingConfiguration = unsetDebuggingConfiguration + UpdateDebuggingConfigurationInManaged = updateDebuggingConfigurationInManaged + CollectLogLevelConfigurationFromClient = collectLogLevelConfigurationFromClient + UpdateLogLevelConfigurationWithClient = updateLogLevelConfigurationWithClient + ShowLogSettingsInManaged = showLogSettingsInManaged + UnsetDebuggingConfigurationInManaged = unsetDebuggingConfigurationInManaged ) diff --git a/internal/commands/loglevel/set.go b/internal/commands/loglevel/set.go index b125a0c8..809f9a74 100644 --- a/internal/commands/loglevel/set.go +++ b/internal/commands/loglevel/set.go @@ -21,7 +21,7 @@ import ( "fmt" "strings" - docopt "github.com/docopt/docopt-go" + "github.com/docopt/docopt-go" libsveltosv1beta1 "github.com/projectsveltos/libsveltos/api/v1beta1" ) @@ -34,9 +34,35 @@ func updateDebuggingConfiguration(ctx context.Context, logSeverity libsveltosv1b return nil } - found := false - spec := make([]libsveltosv1beta1.ComponentConfiguration, len(cc)) + spec := buildUpdatedSpec(cc, component, logSeverity) + return updateLogLevelConfiguration(ctx, spec) +} + +func updateDebuggingConfigurationInManaged(ctx context.Context, logSeverity libsveltosv1beta1.LogLevel, + component, namespace, clusterName string, clusterType libsveltosv1beta1.ClusterType) error { + + managedClient, err := getManagedClusterClient(ctx, namespace, clusterName, clusterType) + if err != nil { + return err + } + + cc, err := collectLogLevelConfigurationFromClient(ctx, managedClient) + if err != nil { + return err + } + spec := buildUpdatedSpec(cc, component, logSeverity) + return updateLogLevelConfigurationWithClient(ctx, managedClient, spec) +} + +// buildUpdatedSpec returns the ComponentConfiguration slice that would result +// from setting component to logSeverity, preserving existing entries for other +// components. +func buildUpdatedSpec(cc []*componentConfiguration, component string, + logSeverity libsveltosv1beta1.LogLevel) []libsveltosv1beta1.ComponentConfiguration { + + spec := make([]libsveltosv1beta1.ComponentConfiguration, len(cc)) + found := false for i, c := range cc { if string(c.component) == component { spec[i] = libsveltosv1beta1.ComponentConfiguration{ @@ -44,7 +70,6 @@ func updateDebuggingConfiguration(ctx context.Context, logSeverity libsveltosv1b LogLevel: logSeverity, } found = true - break } else { spec[i] = libsveltosv1beta1.ComponentConfiguration{ Component: c.component, @@ -62,22 +87,31 @@ func updateDebuggingConfiguration(ctx context.Context, logSeverity libsveltosv1b ) } - return updateLogLevelConfiguration(ctx, spec) + return spec } -// Set displays/changes log verbosity for a given component +// Set displays/changes log verbosity for a given component. +// +// When --namespace and --clusterName are provided, the DebuggingConfiguration +// is updated in the specified managed cluster. Otherwise, it is updated in the +// management cluster. func Set(ctx context.Context, args []string) error { doc := `Usage: - sveltosctl log-level set --component= (--info|--debug|--verbose) + sveltosctl log-level set --component= (--info|--debug|--verbose) [--namespace=] [--clusterName=] [--clusterType=] Options: - -h --help Show this screen. - --component= Name of the component for which log severity is being set. - --info Set log severity to info. - --debug Set log severity to debug. - --verbose Set log severity to verbose. - + -h --help Show this screen. + --component= Name of the component for which log severity is being set. + --info Set log severity to info. + --debug Set log severity to debug. + --verbose Set log severity to verbose. + --namespace= (Optional) Namespace of the managed cluster. + --clusterName= (Optional) Name of the managed cluster. + --clusterType= (Optional) Type of managed cluster: Capi or Sveltos. Defaults to Capi. + Description: The log-level set command set log severity for the specified component. + If --namespace and --clusterName are provided, log severity is set in the + specified managed cluster. Otherwise it is set in the management cluster. ` parsedArgs, err := docopt.ParseArgs(doc, nil, "1.0") if err != nil { @@ -95,18 +129,27 @@ Description: component = passedComponent.(string) } + namespace, clusterName, clusterType, err := parseManagedClusterArgs(parsedArgs) + if err != nil { + return err + } + info := parsedArgs["--info"].(bool) debug := parsedArgs["--debug"].(bool) verbose := parsedArgs["--verbose"].(bool) var logSeverity libsveltosv1beta1.LogLevel - if info { + switch { + case info: logSeverity = libsveltosv1beta1.LogLevelInfo - } else if debug { + case debug: logSeverity = libsveltosv1beta1.LogLevelDebug - } else if verbose { + case verbose: logSeverity = libsveltosv1beta1.LogLevelVerbose } + if namespace != "" && clusterName != "" { + return updateDebuggingConfigurationInManaged(ctx, logSeverity, component, namespace, clusterName, clusterType) + } return updateDebuggingConfiguration(ctx, logSeverity, component) } diff --git a/internal/commands/loglevel/set_test.go b/internal/commands/loglevel/set_test.go index 83a875a3..daa1926f 100644 --- a/internal/commands/loglevel/set_test.go +++ b/internal/commands/loglevel/set_test.go @@ -21,6 +21,7 @@ import ( . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "sigs.k8s.io/controller-runtime/pkg/client/fake" libsveltosv1beta1 "github.com/projectsveltos/libsveltos/api/v1beta1" @@ -59,4 +60,111 @@ var _ = Describe("Set", func() { Expect(currentDC.Spec.Configuration[0].Component).To(Equal(libsveltosv1beta1.ComponentAddonManager)) Expect(currentDC.Spec.Configuration[0].LogLevel).To(Equal(libsveltosv1beta1.LogLevelInfo)) }) + + It("collectLogLevelConfigurationFromClient returns empty configuration when DebuggingConfiguration does not exist", func() { + scheme, err := utils.GetScheme() + Expect(err).To(BeNil()) + c := fake.NewClientBuilder().WithScheme(scheme).Build() + + configs, err := loglevel.CollectLogLevelConfigurationFromClient(context.TODO(), c) + Expect(err).To(BeNil()) + Expect(configs).ToNot(BeNil()) + Expect(len(configs)).To(Equal(0)) + }) + + It("collectLogLevelConfigurationFromClient returns existing configuration", func() { + scheme, err := utils.GetScheme() + Expect(err).To(BeNil()) + + // Create a DebuggingConfiguration with some initial settings + dc := &libsveltosv1beta1.DebuggingConfiguration{ + ObjectMeta: metav1.ObjectMeta{ + Name: "default", + }, + Spec: libsveltosv1beta1.DebuggingConfigurationSpec{ + Configuration: []libsveltosv1beta1.ComponentConfiguration{ + { + Component: libsveltosv1beta1.ComponentClassifier, + LogLevel: libsveltosv1beta1.LogLevelDebug, + }, + { + Component: libsveltosv1beta1.ComponentAddonManager, + LogLevel: libsveltosv1beta1.LogLevelInfo, + }, + }, + }, + } + + c := fake.NewClientBuilder().WithScheme(scheme).WithObjects(dc).Build() + + configs, err := loglevel.CollectLogLevelConfigurationFromClient(context.TODO(), c) + Expect(err).To(BeNil()) + Expect(configs).ToNot(BeNil()) + Expect(len(configs)).To(Equal(2)) + }) + + It("updateLogLevelConfigurationWithClient creates new DebuggingConfiguration when it does not exist", func() { + scheme, err := utils.GetScheme() + Expect(err).To(BeNil()) + c := fake.NewClientBuilder().WithScheme(scheme).Build() + + spec := []libsveltosv1beta1.ComponentConfiguration{ + { + Component: libsveltosv1beta1.ComponentClassifier, + LogLevel: libsveltosv1beta1.LogLevelDebug, + }, + } + + err = loglevel.UpdateLogLevelConfigurationWithClient(context.TODO(), c, spec) + Expect(err).To(BeNil()) + + // Verify the configuration was created + configs, err := loglevel.CollectLogLevelConfigurationFromClient(context.TODO(), c) + Expect(err).To(BeNil()) + Expect(configs).ToNot(BeNil()) + Expect(len(configs)).To(Equal(1)) + }) + + It("updateLogLevelConfigurationWithClient updates existing DebuggingConfiguration", func() { + scheme, err := utils.GetScheme() + Expect(err).To(BeNil()) + + // Create a DebuggingConfiguration with initial settings + dc := &libsveltosv1beta1.DebuggingConfiguration{ + ObjectMeta: metav1.ObjectMeta{ + Name: "default", + }, + Spec: libsveltosv1beta1.DebuggingConfigurationSpec{ + Configuration: []libsveltosv1beta1.ComponentConfiguration{ + { + Component: libsveltosv1beta1.ComponentClassifier, + LogLevel: libsveltosv1beta1.LogLevelInfo, + }, + }, + }, + } + + c := fake.NewClientBuilder().WithScheme(scheme).WithObjects(dc).Build() + + // Update the configuration + spec := []libsveltosv1beta1.ComponentConfiguration{ + { + Component: libsveltosv1beta1.ComponentClassifier, + LogLevel: libsveltosv1beta1.LogLevelDebug, + }, + { + Component: libsveltosv1beta1.ComponentAddonManager, + LogLevel: libsveltosv1beta1.LogLevelVerbose, + }, + } + + err = loglevel.UpdateLogLevelConfigurationWithClient(context.TODO(), c, spec) + Expect(err).To(BeNil()) + + // Verify the configuration was updated + configs, err := loglevel.CollectLogLevelConfigurationFromClient(context.TODO(), c) + Expect(err).To(BeNil()) + Expect(configs).ToNot(BeNil()) + Expect(len(configs)).To(Equal(2)) + }) }) diff --git a/internal/commands/loglevel/show.go b/internal/commands/loglevel/show.go index ff615c3a..ff9b43ed 100644 --- a/internal/commands/loglevel/show.go +++ b/internal/commands/loglevel/show.go @@ -22,8 +22,10 @@ import ( "os" "strings" - docopt "github.com/docopt/docopt-go" + "github.com/docopt/docopt-go" "github.com/olekukonko/tablewriter" + + libsveltosv1beta1 "github.com/projectsveltos/libsveltos/api/v1beta1" ) func showLogSettings(ctx context.Context) error { @@ -32,17 +34,31 @@ func showLogSettings(ctx context.Context) error { return err } + return renderLogSettings(componentConfiguration) +} + +func showLogSettingsInManaged(ctx context.Context, namespace, clusterName string, + clusterType libsveltosv1beta1.ClusterType) error { + + managedClient, err := getManagedClusterClient(ctx, namespace, clusterName, clusterType) + if err != nil { + return err + } + + componentConfiguration, err := collectLogLevelConfigurationFromClient(ctx, managedClient) + if err != nil { + return err + } + + return renderLogSettings(componentConfiguration) +} + +func renderLogSettings(cc []*componentConfiguration) error { table := tablewriter.NewWriter(os.Stdout) table.Header([]string{"COMPONENT", "VERBOSITY"}) - genRow := func(component, verbosity string) []string { - return []string{ - component, - verbosity, - } - } - for _, c := range componentConfiguration { - if err := table.Append(genRow(string(c.component), string(c.logSeverity))); err != nil { + for _, c := range cc { + if err := table.Append([]string{string(c.component), string(c.logSeverity)}); err != nil { return err } } @@ -50,15 +66,25 @@ func showLogSettings(ctx context.Context) error { return table.Render() } -// Show displays information about log verbosity (if set) +// Show displays information about log verbosity (if set). +// +// When --namespace and --clusterName are provided, settings are read from the +// specified managed cluster. Otherwise they are read from the management +// cluster. func Show(ctx context.Context, args []string) error { doc := `Usage: - sveltosctl log-level show + sveltosctl log-level show [--namespace=] [--clusterName=] [--clusterType=] Options: - -h --help Show this screen. - + -h --help Show this screen. + --namespace= (Optional) Namespace of the managed cluster. + --clusterName= (Optional) Name of the managed cluster. + --clusterType= (Optional) Type of managed cluster: Capi or Sveltos. Defaults to Capi. + Description: The log-level show command shows information about current log verbosity. + If --namespace and --clusterName are provided, settings are read from the + specified managed cluster. Otherwise they are read from the management + cluster. ` parsedArgs, err := docopt.ParseArgs(doc, nil, "1.0") if err != nil { @@ -71,5 +97,13 @@ Description: return nil } + namespace, clusterName, clusterType, err := parseManagedClusterArgs(parsedArgs) + if err != nil { + return err + } + + if namespace != "" && clusterName != "" { + return showLogSettingsInManaged(ctx, namespace, clusterName, clusterType) + } return showLogSettings(ctx) } diff --git a/internal/commands/loglevel/show_test.go b/internal/commands/loglevel/show_test.go index 7cb04af4..5bc8ebf1 100644 --- a/internal/commands/loglevel/show_test.go +++ b/internal/commands/loglevel/show_test.go @@ -25,6 +25,7 @@ import ( . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/client/fake" @@ -82,4 +83,32 @@ var _ = Describe("Show", func() { Expect(found).To(BeTrue()) os.Stdout = old }) + + It("showLogSettingsInManaged displays log level settings from managed cluster", func() { + scheme, err := utils.GetScheme() + Expect(err).To(BeNil()) + + // Create a DebuggingConfiguration for the managed cluster + dc := &libsveltosv1beta1.DebuggingConfiguration{ + ObjectMeta: metav1.ObjectMeta{ + Name: "default", + }, + Spec: libsveltosv1beta1.DebuggingConfigurationSpec{ + Configuration: []libsveltosv1beta1.ComponentConfiguration{ + { + Component: libsveltosv1beta1.ComponentClassifier, + LogLevel: libsveltosv1beta1.LogLevelInfo, + }, + }, + }, + } + + managedClient := fake.NewClientBuilder().WithScheme(scheme).WithObjects(dc).Build() + + // Test the helper function directly with the managed client + componentConfiguration, err := loglevel.CollectLogLevelConfigurationFromClient(context.TODO(), managedClient) + Expect(err).To(BeNil()) + Expect(componentConfiguration).ToNot(BeNil()) + Expect(len(componentConfiguration)).To(Equal(1)) + }) }) diff --git a/internal/commands/loglevel/unset.go b/internal/commands/loglevel/unset.go index b8a2cad2..4bf2087f 100644 --- a/internal/commands/loglevel/unset.go +++ b/internal/commands/loglevel/unset.go @@ -21,7 +21,7 @@ import ( "fmt" "strings" - docopt "github.com/docopt/docopt-go" + "github.com/docopt/docopt-go" libsveltosv1beta1 "github.com/projectsveltos/libsveltos/api/v1beta1" ) @@ -32,39 +32,72 @@ func unsetDebuggingConfiguration(ctx context.Context, component string) error { return nil } - found := false - spec := make([]libsveltosv1beta1.ComponentConfiguration, 0) + spec, found := removeComponent(cc, component) + if !found { + return nil + } + return updateLogLevelConfiguration(ctx, spec) +} + +func unsetDebuggingConfigurationInManaged(ctx context.Context, component, namespace, + clusterName string, clusterType libsveltosv1beta1.ClusterType) error { + + managedClient, err := getManagedClusterClient(ctx, namespace, clusterName, clusterType) + if err != nil { + return err + } + + cc, err := collectLogLevelConfigurationFromClient(ctx, managedClient) + if err != nil { + return err + } + + spec, found := removeComponent(cc, component) + if !found { + return nil + } + return updateLogLevelConfigurationWithClient(ctx, managedClient, spec) +} +// removeComponent returns the ComponentConfiguration slice with component +// removed, along with a flag indicating whether it was present. +func removeComponent(cc []*componentConfiguration, + component string) ([]libsveltosv1beta1.ComponentConfiguration, bool) { + + spec := make([]libsveltosv1beta1.ComponentConfiguration, 0, len(cc)) + found := false for _, c := range cc { if string(c.component) == component { found = true continue - } else { - spec = append(spec, - libsveltosv1beta1.ComponentConfiguration{ - Component: c.component, - LogLevel: c.logSeverity, - }, - ) } + spec = append(spec, libsveltosv1beta1.ComponentConfiguration{ + Component: c.component, + LogLevel: c.logSeverity, + }) } - - if found { - return updateLogLevelConfiguration(ctx, spec) - } - return nil + return spec, found } -// Unset resets log verbosity for a given component +// Unset resets log verbosity for a given component. +// +// When --namespace and --clusterName are provided, the DebuggingConfiguration +// is updated in the specified managed cluster. Otherwise, it is updated in the +// management cluster. func Unset(ctx context.Context, args []string) error { doc := `Usage: - sveltosctl log-level unset --component= + sveltosctl log-level unset --component= [--namespace=] [--clusterName=] [--clusterType=] Options: - -h --help Show this screen. - --component= Name of the component for which log severity is being set. - + -h --help Show this screen. + --component= Name of the component for which log severity is being unset. + --namespace= (Optional) Namespace of the managed cluster. + --clusterName= (Optional) Name of the managed cluster. + --clusterType= (Optional) Type of managed cluster: Capi or Sveltos. Defaults to Capi. + Description: - The log-level set command set log severity for the specified component. + The log-level unset command unsets log severity for the specified component. + If --namespace and --clusterName are provided, log severity is unset in the + specified managed cluster. Otherwise it is unset in the management cluster. ` parsedArgs, err := docopt.ParseArgs(doc, nil, "1.0") if err != nil { @@ -82,5 +115,13 @@ Description: component = passedComponent.(string) } + namespace, clusterName, clusterType, err := parseManagedClusterArgs(parsedArgs) + if err != nil { + return err + } + + if namespace != "" && clusterName != "" { + return unsetDebuggingConfigurationInManaged(ctx, component, namespace, clusterName, clusterType) + } return unsetDebuggingConfiguration(ctx, component) } diff --git a/internal/commands/loglevel/unset_test.go b/internal/commands/loglevel/unset_test.go index 19d12d4c..4af04b35 100644 --- a/internal/commands/loglevel/unset_test.go +++ b/internal/commands/loglevel/unset_test.go @@ -21,6 +21,7 @@ import ( . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/client/fake" @@ -58,4 +59,47 @@ var _ = Describe("Unset", func() { Expect(currentDC.Spec.Configuration[0].LogLevel).To(Equal(libsveltosv1beta1.LogLevelInfo)) }) + + It("unsetDebuggingConfigurationInManaged removes log level settings from managed cluster", func() { + scheme, err := utils.GetScheme() + Expect(err).To(BeNil()) + + // Create a DebuggingConfiguration with multiple components for the managed cluster + dc := &libsveltosv1beta1.DebuggingConfiguration{ + ObjectMeta: metav1.ObjectMeta{ + Name: "default", + }, + Spec: libsveltosv1beta1.DebuggingConfigurationSpec{ + Configuration: []libsveltosv1beta1.ComponentConfiguration{ + { + Component: libsveltosv1beta1.ComponentClassifier, + LogLevel: libsveltosv1beta1.LogLevelDebug, + }, + { + Component: libsveltosv1beta1.ComponentAddonManager, + LogLevel: libsveltosv1beta1.LogLevelInfo, + }, + }, + }, + } + + managedClient := fake.NewClientBuilder().WithScheme(scheme).WithObjects(dc).Build() + + // Test removing one component using the helper function + spec := []libsveltosv1beta1.ComponentConfiguration{ + { + Component: libsveltosv1beta1.ComponentAddonManager, + LogLevel: libsveltosv1beta1.LogLevelInfo, + }, + } + + err = loglevel.UpdateLogLevelConfigurationWithClient(context.TODO(), managedClient, spec) + Expect(err).To(BeNil()) + + // Verify the configuration was updated (one component removed) + configs, err := loglevel.CollectLogLevelConfigurationFromClient(context.TODO(), managedClient) + Expect(err).To(BeNil()) + Expect(configs).ToNot(BeNil()) + Expect(len(configs)).To(Equal(1)) + }) }) diff --git a/internal/commands/loglevel/utils.go b/internal/commands/loglevel/utils.go index 3058208c..1793bbcb 100644 --- a/internal/commands/loglevel/utils.go +++ b/internal/commands/loglevel/utils.go @@ -18,15 +18,69 @@ package loglevel import ( "context" + "fmt" "sort" + "github.com/go-logr/logr" apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "sigs.k8s.io/controller-runtime/pkg/client" libsveltosv1beta1 "github.com/projectsveltos/libsveltos/api/v1beta1" + "github.com/projectsveltos/libsveltos/lib/clusterproxy" "github.com/projectsveltos/sveltosctl/internal/utils" ) +const ( + defaultDebuggingConfigurationName = "default" +) + +// getManagedClusterClient returns a controller-runtime client for the managed +// cluster identified by (namespace, clusterName, clusterType), using the +// management cluster client to look up credentials via libsveltos clusterproxy. +func getManagedClusterClient(ctx context.Context, namespace, clusterName string, + clusterType libsveltosv1beta1.ClusterType) (client.Client, error) { + + managedClient, err := clusterproxy.GetKubernetesClient(ctx, utils.GetAccessInstance().GetClient(), + namespace, clusterName, "", "", clusterType, logr.Discard()) + if err != nil { + return nil, fmt.Errorf("failed to get client for managed cluster %s/%s: %w", + namespace, clusterName, err) + } + return managedClient, nil +} + +// parseManagedClusterArgs extracts the optional --namespace, --clusterName and +// --clusterType values from the parsed docopt args. clusterType defaults to +// Capi; any value other than "Sveltos" (case-sensitive) falls back to Capi for +// backward compatibility with existing invocations. +func parseManagedClusterArgs(parsedArgs map[string]interface{}) ( + namespace, clusterName string, clusterType libsveltosv1beta1.ClusterType, err error) { + + if v := parsedArgs["--namespace"]; v != nil { + namespace = v.(string) + } + if v := parsedArgs["--clusterName"]; v != nil { + clusterName = v.(string) + } + + clusterType = libsveltosv1beta1.ClusterTypeCapi + if v := parsedArgs["--clusterType"]; v != nil { + switch v.(string) { + case string(libsveltosv1beta1.ClusterTypeSveltos): + clusterType = libsveltosv1beta1.ClusterTypeSveltos + case string(libsveltosv1beta1.ClusterTypeCapi): + clusterType = libsveltosv1beta1.ClusterTypeCapi + default: + return "", "", "", fmt.Errorf( + "invalid --clusterType %q: must be %q or %q", + v, libsveltosv1beta1.ClusterTypeCapi, libsveltosv1beta1.ClusterTypeSveltos) + } + } + + return namespace, clusterName, clusterType, nil +} + type componentConfiguration struct { component libsveltosv1beta1.Component logSeverity libsveltosv1beta1.LogLevel @@ -93,3 +147,59 @@ func updateLogLevelConfiguration( return instance.UpdateDebuggingConfiguration(ctx, dc) } + +// collectLogLevelConfigurationFromClient returns the current log-level +// configuration read from the DebuggingConfiguration "default" instance +// accessible through the provided client. +func collectLogLevelConfigurationFromClient(ctx context.Context, + c client.Client) ([]*componentConfiguration, error) { + + dc := &libsveltosv1beta1.DebuggingConfiguration{} + err := c.Get(ctx, client.ObjectKey{Name: defaultDebuggingConfigurationName}, dc) + if err != nil { + if apierrors.IsNotFound(err) { + return make([]*componentConfiguration, 0), nil + } + return nil, err + } + + configurationSettings := make([]*componentConfiguration, len(dc.Spec.Configuration)) + for i, c := range dc.Spec.Configuration { + configurationSettings[i] = &componentConfiguration{ + component: c.Component, + logSeverity: c.LogLevel, + } + } + + sort.Sort(byComponent(configurationSettings)) + return configurationSettings, nil +} + +// updateLogLevelConfigurationWithClient writes spec to the DebuggingConfiguration +// "default" instance accessible through the provided client, creating it if it +// does not exist. +func updateLogLevelConfigurationWithClient(ctx context.Context, c client.Client, + spec []libsveltosv1beta1.ComponentConfiguration) error { + + dc := &libsveltosv1beta1.DebuggingConfiguration{} + err := c.Get(ctx, client.ObjectKey{Name: defaultDebuggingConfigurationName}, dc) + if err != nil { + if !apierrors.IsNotFound(err) { + return err + } + dc = &libsveltosv1beta1.DebuggingConfiguration{ + ObjectMeta: metav1.ObjectMeta{ + Name: defaultDebuggingConfigurationName, + }, + Spec: libsveltosv1beta1.DebuggingConfigurationSpec{ + Configuration: spec, + }, + } + return c.Create(ctx, dc) + } + + dc.Spec = libsveltosv1beta1.DebuggingConfigurationSpec{ + Configuration: spec, + } + return c.Update(ctx, dc) +}