From 9fb9c76a8e138fed49a7231cd4543f0afd837b70 Mon Sep 17 00:00:00 2001 From: cmoulliard Date: Thu, 19 Dec 2024 15:02:55 +0100 Subject: [PATCH 01/13] Improve the code to print the secrets using the cli-runtime line and printTable. #463 Signed-off-by: cmoulliard --- pkg/cmd/get/clusters.go | 38 ++++---- pkg/cmd/get/root.go | 2 +- pkg/cmd/get/secrets.go | 138 +++++++++++++++-------------- pkg/cmd/get/secrets_test.go | 7 +- pkg/cmd/get/templates/secrets.tmpl | 7 -- pkg/util/util.go | 45 ++++++++++ 6 files changed, 141 insertions(+), 96 deletions(-) delete mode 100644 pkg/cmd/get/templates/secrets.tmpl diff --git a/pkg/cmd/get/clusters.go b/pkg/cmd/get/clusters.go index 6c3bac36..5c29d628 100644 --- a/pkg/cmd/get/clusters.go +++ b/pkg/cmd/get/clusters.go @@ -1,7 +1,6 @@ package get import ( - "bytes" "context" "fmt" "github.com/cnoe-io/idpbuilder/api/v1alpha1" @@ -14,7 +13,6 @@ import ( "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" - "k8s.io/cli-runtime/pkg/printers" "k8s.io/client-go/tools/clientcmd" "k8s.io/client-go/tools/clientcmd/api" "sigs.k8s.io/controller-runtime/pkg/client" @@ -74,9 +72,27 @@ func list(cmd *cobra.Command, args []string) error { if err != nil { return err } else { - // Convert the list of the clusters to Table of clusters - printTable(printers.PrintOptions{}, generateClusterTable(clusters)) - return nil + // Convert the list of the clusters to a Table of clusters and print the table using the format selected + err := printClustersOutput(clusters, outputFormat) + if err != nil { + return err + } else { + return nil + } + } +} + +func printClustersOutput(clusters []Cluster, format string) error { + switch format { + case "json": + return util.PrintDataAsJson(clusters) + case "yaml": + return util.PrintDataAsYaml(clusters) + case "": + return util.PrintTable(generateClusterTable(clusters)) + default: + + return fmt.Errorf("output format %s is not supported", format) } } @@ -232,18 +248,6 @@ func generateClusterTable(clusterTable []Cluster) metav1.Table { return *table } -func printTable(opts printers.PrintOptions, table metav1.Table) { - logger := helpers.CmdLogger - out := bytes.NewBuffer([]byte{}) - printer := printers.NewTablePrinter(opts) - err := printer.PrintObj(&table, out) - if err != nil { - logger.Error(err, "failed to print the table.") - return - } - fmt.Println(out.String()) -} - func generateNodeData(nodes []Node) string { var result string for i, aNode := range nodes { diff --git a/pkg/cmd/get/root.go b/pkg/cmd/get/root.go index c767b8c4..23ea8c15 100644 --- a/pkg/cmd/get/root.go +++ b/pkg/cmd/get/root.go @@ -22,7 +22,7 @@ func init() { GetCmd.AddCommand(ClustersCmd) GetCmd.AddCommand(SecretsCmd) GetCmd.PersistentFlags().StringSliceVarP(&packages, "packages", "p", []string{}, "names of packages.") - GetCmd.PersistentFlags().StringVarP(&outputFormat, "output", "o", "", "Output format. json or yaml.") + GetCmd.PersistentFlags().StringVarP(&outputFormat, "output", "o", "", "Output format. table or json.") GetCmd.PersistentFlags().StringVarP(&helpers.KubeConfigPath, "kubeconfig", "", "", "kube config file Path.") } diff --git a/pkg/cmd/get/secrets.go b/pkg/cmd/get/secrets.go index dc6d94c2..f9f2edab 100644 --- a/pkg/cmd/get/secrets.go +++ b/pkg/cmd/get/secrets.go @@ -2,13 +2,10 @@ package get import ( "context" - "embed" - "encoding/json" "fmt" - "io" - "os" + "github.com/cnoe-io/idpbuilder/pkg/util" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "path/filepath" - "text/template" "github.com/cnoe-io/idpbuilder/api/v1alpha1" "github.com/cnoe-io/idpbuilder/pkg/build" @@ -20,19 +17,14 @@ import ( "k8s.io/apimachinery/pkg/selection" "k8s.io/client-go/util/homedir" "sigs.k8s.io/controller-runtime/pkg/client" - "sigs.k8s.io/yaml" ) const ( - secretTemplatePath = "templates/secrets.tmpl" argoCDAdminUsername = "admin" argoCDInitialAdminSecretName = "argocd-initial-admin-secret" giteaAdminSecretName = "gitea-credential" ) -//go:embed templates -var templates embed.FS - var SecretsCmd = &cobra.Command{ Use: "secrets", Short: "retrieve secrets from the cluster", @@ -42,10 +34,12 @@ var SecretsCmd = &cobra.Command{ } // well known secrets that are part of the core packages -var corePkgSecrets = map[string][]string{ - "argocd": []string{argoCDInitialAdminSecretName}, - "gitea": []string{giteaAdminSecretName}, -} +var ( + corePkgSecrets = map[string][]string{ + "argocd": []string{argoCDInitialAdminSecretName}, + "gitea": []string{giteaAdminSecretName}, + } +) type TemplateData struct { Name string `json:"name"` @@ -53,6 +47,14 @@ type TemplateData struct { Data map[string]string `json:"data"` } +type Secret struct { + Name string `json:"name"` + Namespace string `json:"namespace"` + Username string `json:"username"` + Password string `json:"password"` + Token string `json:"token"` +} + func getSecretsE(cmd *cobra.Command, args []string) error { ctx, ctxCancel := context.WithCancel(cmd.Context()) defer ctxCancel() @@ -77,15 +79,15 @@ func getSecretsE(cmd *cobra.Command, args []string) error { } if len(packages) == 0 { - return printAllPackageSecrets(ctx, os.Stdout, kubeClient, outputFormat) + return printAllPackageSecrets(ctx, kubeClient, outputFormat) } - return printPackageSecrets(ctx, os.Stdout, kubeClient, outputFormat) + return printPackageSecrets(ctx, kubeClient, outputFormat) } -func printAllPackageSecrets(ctx context.Context, outWriter io.Writer, kubeClient client.Client, format string) error { +func printAllPackageSecrets(ctx context.Context, kubeClient client.Client, format string) error { selector := labels.NewSelector() - secretsToPrint := make([]any, 0, 2) + secrets := []Secret{} for k, v := range corePkgSecrets { for i := range v { @@ -96,29 +98,29 @@ func printAllPackageSecrets(ctx context.Context, outWriter io.Writer, kubeClient } return fmt.Errorf("getting secret %s in %s: %w", v[i], k, sErr) } - secretsToPrint = append(secretsToPrint, secretToTemplateData(secret)) + secrets = append(secrets, generateSecret(secret)) } } - secrets, err := getSecretsByCNOELabel(ctx, kubeClient, selector) + cnoeLabelSecrets, err := getSecretsByCNOELabel(ctx, kubeClient, selector) if err != nil { return fmt.Errorf("listing secrets: %w", err) } - for i := range secrets.Items { - secretsToPrint = append(secretsToPrint, secretToTemplateData(secrets.Items[i])) + for i := range cnoeLabelSecrets.Items { + secrets = append(secrets, generateSecret(cnoeLabelSecrets.Items[i])) } - if len(secretsToPrint) == 0 { + if len(secrets) == 0 { fmt.Println("no secrets found") return nil } - return printOutput(secretTemplatePath, outWriter, secretsToPrint, format) + return printSecretsOutput(secrets, format) } -func printPackageSecrets(ctx context.Context, outWriter io.Writer, kubeClient client.Client, format string) error { +func printPackageSecrets(ctx context.Context, kubeClient client.Client, format string) error { selector := labels.NewSelector() - secretsToPrint := make([]any, 0, 2) + secrets := []Secret{} for i := range packages { p := packages[i] @@ -132,7 +134,7 @@ func printPackageSecrets(ctx context.Context, outWriter io.Writer, kubeClient cl } return fmt.Errorf("getting secret %s in %s: %w", secretNames[j], p, sErr) } - secretsToPrint = append(secretsToPrint, secretToTemplateData(secret)) + secrets = append(secrets, generateSecret(secret)) } continue } @@ -144,69 +146,71 @@ func printPackageSecrets(ctx context.Context, outWriter io.Writer, kubeClient cl pkgSelector := selector.Add(*req) - secrets, pErr := getSecretsByCNOELabel(ctx, kubeClient, pkgSelector) - if pErr != nil { - return fmt.Errorf("listing secrets: %w", pErr) + cnoeLabelSecrets, err := getSecretsByCNOELabel(ctx, kubeClient, pkgSelector) + if err != nil { + return fmt.Errorf("listing secrets: %w", err) + } + + for i := range cnoeLabelSecrets.Items { + secrets = append(secrets, generateSecret(cnoeLabelSecrets.Items[i])) } - for j := range secrets.Items { - secretsToPrint = append(secretsToPrint, secretToTemplateData(secrets.Items[j])) + if len(secrets) == 0 { + fmt.Println("no secrets found") + return nil } } - return printOutput(secretTemplatePath, outWriter, secretsToPrint, format) + return printSecretsOutput(secrets, format) } -func renderTemplate(templatePath string, outWriter io.Writer, data []any) error { - tmpl, err := templates.ReadFile(templatePath) - if err != nil { - return fmt.Errorf("failed to read template: %w", err) - } - - t, err := template.New("secrets").Parse(string(tmpl)) - if err != nil { - return fmt.Errorf("parsing template: %w", err) - } - for i := range data { - tErr := t.Execute(outWriter, data[i]) - if tErr != nil { - return fmt.Errorf("executing template for data %s : %w", data[i], tErr) +func generateSecretTable(secretTable []Secret) metav1.Table { + table := &metav1.Table{} + table.ColumnDefinitions = []metav1.TableColumnDefinition{ + {Name: "Name", Type: "string"}, + {Name: "Namespace", Type: "string"}, + {Name: "Username", Type: "string"}, + {Name: "Password", Type: "string"}, + {Name: "Token", Type: "string"}, + } + for _, secret := range secretTable { + row := metav1.TableRow{ + Cells: []interface{}{ + secret.Name, + secret.Namespace, + secret.Username, + secret.Password, + secret.Token, + }, } + table.Rows = append(table.Rows, row) } - return nil + return *table } -func printOutput(templatePath string, outWriter io.Writer, data []any, format string) error { +func printSecretsOutput(secrets []Secret, format string) error { switch format { case "json": - enc := json.NewEncoder(outWriter) - enc.SetEscapeHTML(false) - enc.SetIndent("", " ") - return enc.Encode(data) + return util.PrintDataAsJson(secrets) case "yaml": - b, err := yaml.Marshal(data) - if err != nil { - return err - } - _, err = outWriter.Write(b) - return err + return util.PrintDataAsYaml(secrets) case "": - return renderTemplate(templatePath, outWriter, data) + return util.PrintTable(generateSecretTable(secrets)) default: + return fmt.Errorf("output format %s is not supported", format) } } -func secretToTemplateData(s v1.Secret) TemplateData { - data := TemplateData{ +func generateSecret(s v1.Secret) Secret { + secret := Secret{ Name: s.Name, Namespace: s.Namespace, - Data: make(map[string]string), - } - for k, v := range s.Data { - data.Data[k] = string(v) + Username: string(s.Data["username"]), + Password: string(s.Data["password"]), + Token: string(s.Data["token"]), } - return data + return secret } func getSecretsByCNOELabel(ctx context.Context, kubeClient client.Client, l labels.Selector) (v1.SecretList, error) { diff --git a/pkg/cmd/get/secrets_test.go b/pkg/cmd/get/secrets_test.go index 6bd3d0f0..83e7a23a 100644 --- a/pkg/cmd/get/secrets_test.go +++ b/pkg/cmd/get/secrets_test.go @@ -4,7 +4,6 @@ import ( "bytes" "context" "encoding/json" - "io" "testing" "github.com/cnoe-io/idpbuilder/api/v1alpha1" @@ -97,7 +96,7 @@ func TestPrintPackageSecrets(t *testing.T) { fClient.On("Get", ctx, c.getKeys[j], mock.Anything, mock.Anything).Return(c.err) } - err := printPackageSecrets(ctx, io.Discard, fClient, "") + err := printPackageSecrets(ctx, fClient, "") fClient.AssertExpectations(t) assert.Nil(t, err) } @@ -134,7 +133,7 @@ func TestPrintAllPackageSecrets(t *testing.T) { for j := range c.getKeys { fClient.On("Get", ctx, c.getKeys[j], mock.Anything, mock.Anything).Return(c.err) } - err := printAllPackageSecrets(ctx, io.Discard, fClient, "") + err := printAllPackageSecrets(ctx, fClient, "") fClient.AssertExpectations(t) assert.Nil(t, err) } @@ -212,7 +211,7 @@ func TestOutput(t *testing.T) { var b []byte buffer := bytes.NewBuffer(b) - err := printAllPackageSecrets(ctx, buffer, fClient, "json") + err := printAllPackageSecrets(ctx, fClient, "json") fClient.AssertExpectations(t) assert.Nil(t, err) diff --git a/pkg/cmd/get/templates/secrets.tmpl b/pkg/cmd/get/templates/secrets.tmpl deleted file mode 100644 index 18bc9029..00000000 --- a/pkg/cmd/get/templates/secrets.tmpl +++ /dev/null @@ -1,7 +0,0 @@ ---------------------------- -Name: {{ .Name }} -Namespace: {{ .Namespace }} -Data: -{{- range $key, $value := .Data }} - {{ $key }} : {{ $value }} -{{- end }} diff --git a/pkg/util/util.go b/pkg/util/util.go index dbd606fe..a89839af 100644 --- a/pkg/util/util.go +++ b/pkg/util/util.go @@ -1,10 +1,13 @@ package util import ( + "bytes" "context" "crypto/rand" "crypto/tls" + "encoding/json" "fmt" + "k8s.io/cli-runtime/pkg/printers" "math" "math/big" mathrand "math/rand" @@ -16,9 +19,11 @@ import ( "time" "github.com/cnoe-io/idpbuilder/api/v1alpha1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/kind/pkg/cluster" + "sigs.k8s.io/yaml" ) const ( @@ -183,3 +188,43 @@ func SetPackageLabels(obj client.Object) { labels[v1alpha1.PackageTypeLabelKey] = v1alpha1.PackageTypeLabelCustom } } + +func PrintTable(table metav1.Table) error { + out := bytes.NewBuffer([]byte{}) + printer := printers.NewTablePrinter(printers.PrintOptions{}) + err := printer.PrintObj(&table, out) + if err != nil { + return fmt.Errorf("failed to print the table %w", err) + } + fmt.Println(out) + return nil +} + +func PrintDataAsJson(data any) error { + out := bytes.NewBuffer([]byte{}) + enc := json.NewEncoder(out) + enc.SetEscapeHTML(false) + enc.SetIndent("", " ") + if err := enc.Encode(data); err != nil { + return err + } else { + fmt.Println(out) + return nil + } + +} + +func PrintDataAsYaml(data any) error { + out := bytes.NewBuffer([]byte{}) + b, err := yaml.Marshal(data) + if err != nil { + return err + } + _, err = out.Write(b) + if err != nil { + return err + } else { + fmt.Println(out) + return nil + } +} From 666bfc71490eb24e0a47c21c08e69978bd4ebfda Mon Sep 17 00:00:00 2001 From: cmoulliard Date: Thu, 19 Dec 2024 15:33:06 +0100 Subject: [PATCH 02/13] Pass the writer using stdout to the functions Signed-off-by: cmoulliard --- pkg/cmd/get/clusters.go | 12 +++++++----- pkg/cmd/get/secrets.go | 23 ++++++++++++----------- pkg/cmd/get/secrets_test.go | 7 ++++--- pkg/util/util.go | 37 +++++++++---------------------------- 4 files changed, 32 insertions(+), 47 deletions(-) diff --git a/pkg/cmd/get/clusters.go b/pkg/cmd/get/clusters.go index 5c29d628..8d880765 100644 --- a/pkg/cmd/get/clusters.go +++ b/pkg/cmd/get/clusters.go @@ -9,12 +9,14 @@ import ( "github.com/cnoe-io/idpbuilder/pkg/kind" "github.com/cnoe-io/idpbuilder/pkg/util" "github.com/spf13/cobra" + "io" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" "k8s.io/client-go/tools/clientcmd" "k8s.io/client-go/tools/clientcmd/api" + "os" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/kind/pkg/cluster" "slices" @@ -73,7 +75,7 @@ func list(cmd *cobra.Command, args []string) error { return err } else { // Convert the list of the clusters to a Table of clusters and print the table using the format selected - err := printClustersOutput(clusters, outputFormat) + err := printClustersOutput(os.Stdout, clusters, outputFormat) if err != nil { return err } else { @@ -82,14 +84,14 @@ func list(cmd *cobra.Command, args []string) error { } } -func printClustersOutput(clusters []Cluster, format string) error { +func printClustersOutput(outWriter io.Writer, clusters []Cluster, format string) error { switch format { case "json": - return util.PrintDataAsJson(clusters) + return util.PrintDataAsJson(clusters, outWriter) case "yaml": - return util.PrintDataAsYaml(clusters) + return util.PrintDataAsYaml(clusters, outWriter) case "": - return util.PrintTable(generateClusterTable(clusters)) + return util.PrintTable(generateClusterTable(clusters), outWriter) default: return fmt.Errorf("output format %s is not supported", format) diff --git a/pkg/cmd/get/secrets.go b/pkg/cmd/get/secrets.go index f9f2edab..b09a24f9 100644 --- a/pkg/cmd/get/secrets.go +++ b/pkg/cmd/get/secrets.go @@ -4,7 +4,9 @@ import ( "context" "fmt" "github.com/cnoe-io/idpbuilder/pkg/util" + "io" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "os" "path/filepath" "github.com/cnoe-io/idpbuilder/api/v1alpha1" @@ -79,13 +81,13 @@ func getSecretsE(cmd *cobra.Command, args []string) error { } if len(packages) == 0 { - return printAllPackageSecrets(ctx, kubeClient, outputFormat) + return printAllPackageSecrets(ctx, os.Stdout, kubeClient, outputFormat) } - return printPackageSecrets(ctx, kubeClient, outputFormat) + return printPackageSecrets(ctx, os.Stdout, kubeClient, outputFormat) } -func printAllPackageSecrets(ctx context.Context, kubeClient client.Client, format string) error { +func printAllPackageSecrets(ctx context.Context, outWriter io.Writer, kubeClient client.Client, format string) error { selector := labels.NewSelector() secrets := []Secret{} @@ -115,10 +117,10 @@ func printAllPackageSecrets(ctx context.Context, kubeClient client.Client, forma fmt.Println("no secrets found") return nil } - return printSecretsOutput(secrets, format) + return printSecretsOutput(outWriter, secrets, format) } -func printPackageSecrets(ctx context.Context, kubeClient client.Client, format string) error { +func printPackageSecrets(ctx context.Context, outWriter io.Writer, kubeClient client.Client, format string) error { selector := labels.NewSelector() secrets := []Secret{} @@ -161,7 +163,7 @@ func printPackageSecrets(ctx context.Context, kubeClient client.Client, format s } } - return printSecretsOutput(secrets, format) + return printSecretsOutput(outWriter, secrets, format) } func generateSecretTable(secretTable []Secret) metav1.Table { @@ -188,16 +190,15 @@ func generateSecretTable(secretTable []Secret) metav1.Table { return *table } -func printSecretsOutput(secrets []Secret, format string) error { +func printSecretsOutput(outWriter io.Writer, secrets []Secret, format string) error { switch format { case "json": - return util.PrintDataAsJson(secrets) + return util.PrintDataAsJson(secrets, outWriter) case "yaml": - return util.PrintDataAsYaml(secrets) + return util.PrintDataAsYaml(secrets, outWriter) case "": - return util.PrintTable(generateSecretTable(secrets)) + return util.PrintTable(generateSecretTable(secrets), outWriter) default: - return fmt.Errorf("output format %s is not supported", format) } } diff --git a/pkg/cmd/get/secrets_test.go b/pkg/cmd/get/secrets_test.go index 83e7a23a..d55572ef 100644 --- a/pkg/cmd/get/secrets_test.go +++ b/pkg/cmd/get/secrets_test.go @@ -4,6 +4,7 @@ import ( "bytes" "context" "encoding/json" + "io" "testing" "github.com/cnoe-io/idpbuilder/api/v1alpha1" @@ -96,7 +97,7 @@ func TestPrintPackageSecrets(t *testing.T) { fClient.On("Get", ctx, c.getKeys[j], mock.Anything, mock.Anything).Return(c.err) } - err := printPackageSecrets(ctx, fClient, "") + err := printPackageSecrets(ctx, io.Discard, fClient, "") fClient.AssertExpectations(t) assert.Nil(t, err) } @@ -133,7 +134,7 @@ func TestPrintAllPackageSecrets(t *testing.T) { for j := range c.getKeys { fClient.On("Get", ctx, c.getKeys[j], mock.Anything, mock.Anything).Return(c.err) } - err := printAllPackageSecrets(ctx, fClient, "") + err := printAllPackageSecrets(ctx, io.Discard, fClient, "") fClient.AssertExpectations(t) assert.Nil(t, err) } @@ -211,7 +212,7 @@ func TestOutput(t *testing.T) { var b []byte buffer := bytes.NewBuffer(b) - err := printAllPackageSecrets(ctx, fClient, "json") + err := printAllPackageSecrets(ctx, io.Discard, fClient, "json") fClient.AssertExpectations(t) assert.Nil(t, err) diff --git a/pkg/util/util.go b/pkg/util/util.go index a89839af..4a21b8c1 100644 --- a/pkg/util/util.go +++ b/pkg/util/util.go @@ -1,12 +1,12 @@ package util import ( - "bytes" "context" "crypto/rand" "crypto/tls" "encoding/json" "fmt" + "io" "k8s.io/cli-runtime/pkg/printers" "math" "math/big" @@ -189,42 +189,23 @@ func SetPackageLabels(obj client.Object) { } } -func PrintTable(table metav1.Table) error { - out := bytes.NewBuffer([]byte{}) +func PrintTable(table metav1.Table, outWriter io.Writer) error { printer := printers.NewTablePrinter(printers.PrintOptions{}) - err := printer.PrintObj(&table, out) - if err != nil { - return fmt.Errorf("failed to print the table %w", err) - } - fmt.Println(out) - return nil + return printer.PrintObj(&table, outWriter) } -func PrintDataAsJson(data any) error { - out := bytes.NewBuffer([]byte{}) - enc := json.NewEncoder(out) +func PrintDataAsJson(data any, outWriter io.Writer) error { + enc := json.NewEncoder(outWriter) enc.SetEscapeHTML(false) enc.SetIndent("", " ") - if err := enc.Encode(data); err != nil { - return err - } else { - fmt.Println(out) - return nil - } - + return enc.Encode(data) } -func PrintDataAsYaml(data any) error { - out := bytes.NewBuffer([]byte{}) +func PrintDataAsYaml(data any, outWriter io.Writer) error { b, err := yaml.Marshal(data) if err != nil { return err } - _, err = out.Write(b) - if err != nil { - return err - } else { - fmt.Println(out) - return nil - } + _, err = outWriter.Write(b) + return err } From cc43fcce674aff53ec38b3ad52eed862a764a122 Mon Sep 17 00:00:00 2001 From: cmoulliard Date: Thu, 19 Dec 2024 15:48:17 +0100 Subject: [PATCH 03/13] Fix wrong writer used: io.Discard => buffer Signed-off-by: cmoulliard --- pkg/cmd/get/secrets_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/cmd/get/secrets_test.go b/pkg/cmd/get/secrets_test.go index d55572ef..6bd3d0f0 100644 --- a/pkg/cmd/get/secrets_test.go +++ b/pkg/cmd/get/secrets_test.go @@ -212,7 +212,7 @@ func TestOutput(t *testing.T) { var b []byte buffer := bytes.NewBuffer(b) - err := printAllPackageSecrets(ctx, io.Discard, fClient, "json") + err := printAllPackageSecrets(ctx, buffer, fClient, "json") fClient.AssertExpectations(t) assert.Nil(t, err) From 08cbf2db00ded6f55debd1b84bceeb5cae59c42d Mon Sep 17 00:00:00 2001 From: cmoulliard Date: Thu, 19 Dec 2024 18:16:31 +0100 Subject: [PATCH 04/13] Fix the issue with the test case: secrets_test.go. Set a new parameter: isCore to make the distinction betweek the core secrets and secrets having the CNOE label Signed-off-by: cmoulliard --- pkg/cmd/get/secrets.go | 55 +++++++++++++++++++++++++++---------- pkg/cmd/get/secrets_test.go | 42 ++++++++++++++++------------ 2 files changed, 65 insertions(+), 32 deletions(-) diff --git a/pkg/cmd/get/secrets.go b/pkg/cmd/get/secrets.go index b09a24f9..07ac9496 100644 --- a/pkg/cmd/get/secrets.go +++ b/pkg/cmd/get/secrets.go @@ -8,6 +8,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "os" "path/filepath" + "strings" "github.com/cnoe-io/idpbuilder/api/v1alpha1" "github.com/cnoe-io/idpbuilder/pkg/build" @@ -50,11 +51,13 @@ type TemplateData struct { } type Secret struct { - Name string `json:"name"` - Namespace string `json:"namespace"` - Username string `json:"username"` - Password string `json:"password"` - Token string `json:"token"` + isCore bool + Name string `json:"name"` + Namespace string `json:"namespace"` + Username string `json:"username,omitempty"` + Password string `json:"password,omitempty"` + Token string `json:"token,omitempty"` + Data map[string]string `json:"data,omitempty"` } func getSecretsE(cmd *cobra.Command, args []string) error { @@ -100,7 +103,7 @@ func printAllPackageSecrets(ctx context.Context, outWriter io.Writer, kubeClient } return fmt.Errorf("getting secret %s in %s: %w", v[i], k, sErr) } - secrets = append(secrets, generateSecret(secret)) + secrets = append(secrets, generateSecret(secret, true)) } } @@ -110,7 +113,7 @@ func printAllPackageSecrets(ctx context.Context, outWriter io.Writer, kubeClient } for i := range cnoeLabelSecrets.Items { - secrets = append(secrets, generateSecret(cnoeLabelSecrets.Items[i])) + secrets = append(secrets, generateSecret(cnoeLabelSecrets.Items[i], false)) } if len(secrets) == 0 { @@ -136,7 +139,7 @@ func printPackageSecrets(ctx context.Context, outWriter io.Writer, kubeClient cl } return fmt.Errorf("getting secret %s in %s: %w", secretNames[j], p, sErr) } - secrets = append(secrets, generateSecret(secret)) + secrets = append(secrets, generateSecret(secret, true)) } continue } @@ -154,7 +157,7 @@ func printPackageSecrets(ctx context.Context, outWriter io.Writer, kubeClient cl } for i := range cnoeLabelSecrets.Items { - secrets = append(secrets, generateSecret(cnoeLabelSecrets.Items[i])) + secrets = append(secrets, generateSecret(cnoeLabelSecrets.Items[i], false)) } if len(secrets) == 0 { @@ -174,8 +177,17 @@ func generateSecretTable(secretTable []Secret) metav1.Table { {Name: "Username", Type: "string"}, {Name: "Password", Type: "string"}, {Name: "Token", Type: "string"}, + {Name: "Data", Type: "string"}, } for _, secret := range secretTable { + var dataEntries []string + + if !secret.isCore { + for key, value := range secret.Data { + dataEntries = append(dataEntries, fmt.Sprintf("%s=%s", key, value)) + } + } + dataString := strings.Join(dataEntries, ", ") row := metav1.TableRow{ Cells: []interface{}{ secret.Name, @@ -183,6 +195,7 @@ func generateSecretTable(secretTable []Secret) metav1.Table { secret.Username, secret.Password, secret.Token, + dataString, }, } table.Rows = append(table.Rows, row) @@ -196,21 +209,35 @@ func printSecretsOutput(outWriter io.Writer, secrets []Secret, format string) er return util.PrintDataAsJson(secrets, outWriter) case "yaml": return util.PrintDataAsYaml(secrets, outWriter) - case "": + case "", "table": return util.PrintTable(generateSecretTable(secrets), outWriter) default: return fmt.Errorf("output format %s is not supported", format) } } -func generateSecret(s v1.Secret) Secret { +func generateSecret(s v1.Secret, isCoreSecret bool) Secret { secret := Secret{ Name: s.Name, Namespace: s.Namespace, - Username: string(s.Data["username"]), - Password: string(s.Data["password"]), - Token: string(s.Data["token"]), } + + if isCoreSecret { + secret.isCore = true + secret.Username = string(s.Data["username"]) + secret.Password = string(s.Data["password"]) + secret.Token = string(s.Data["token"]) + secret.Data = nil + } else { + newData := make(map[string]string) + for key, value := range s.Data { + newData[key] = string(value) + } + if len(newData) > 0 { + secret.Data = newData + } + } + return secret } diff --git a/pkg/cmd/get/secrets_test.go b/pkg/cmd/get/secrets_test.go index 6bd3d0f0..8346bf9d 100644 --- a/pkg/cmd/get/secrets_test.go +++ b/pkg/cmd/get/secrets_test.go @@ -144,26 +144,24 @@ func TestOutput(t *testing.T) { ctx := context.Background() r, _ := labels.NewRequirement(v1alpha1.CLISecretLabelKey, selection.Equals, []string{v1alpha1.CLISecretLabelValue}) - corePkgData := map[string]TemplateData{ + corePkgData := map[string]Secret{ argoCDInitialAdminSecretName: { + isCore: true, Name: argoCDInitialAdminSecretName, Namespace: "argocd", - Data: map[string]string{ - "username": "admin", - "password": "abc", - }, + Username: "admin", + Password: "abc", }, giteaAdminSecretName: { + isCore: true, Name: giteaAdminSecretName, Namespace: "gitea", - Data: map[string]string{ - "username": "admin", - "password": "abc", - }, + Username: "admin", + Password: "abc", }, } - packageData := map[string]TemplateData{ + packageData := map[string]Secret{ "name1": { Name: "name1", Namespace: "ns1", @@ -190,12 +188,12 @@ func TestOutput(t *testing.T) { fClient.On("Get", ctx, client.ObjectKey{Name: argoCDInitialAdminSecretName, Namespace: "argocd"}, mock.Anything, mock.Anything).Run(func(args mock.Arguments) { arg := args.Get(2).(*v1.Secret) - sec := templateDataToSecret(corePkgData[argoCDInitialAdminSecretName]) + sec := secretDataToSecret(corePkgData[argoCDInitialAdminSecretName]) *arg = sec }).Return(nil) fClient.On("Get", ctx, client.ObjectKey{Name: giteaAdminSecretName, Namespace: "gitea"}, mock.Anything, mock.Anything).Run(func(args mock.Arguments) { arg := args.Get(2).(*v1.Secret) - sec := templateDataToSecret(corePkgData[giteaAdminSecretName]) + sec := secretDataToSecret(corePkgData[giteaAdminSecretName]) *arg = sec }).Return(nil) @@ -203,7 +201,7 @@ func TestOutput(t *testing.T) { arg := args.Get(1).(*v1.SecretList) secs := make([]v1.Secret, 0, 2) for k := range packageData { - s := templateDataToSecret(packageData[k]) + s := secretDataToSecret(packageData[k]) secs = append(secs, s) } arg.Items = secs @@ -217,7 +215,7 @@ func TestOutput(t *testing.T) { assert.Nil(t, err) // verify received json data - var received []TemplateData + var received []Secret err = json.Unmarshal(buffer.Bytes(), &received) assert.Nil(t, err) assert.Equal(t, 4, len(received)) @@ -226,6 +224,8 @@ func TestOutput(t *testing.T) { rec := received[i] c, ok := corePkgData[rec.Name] if ok { + // Set the isCore bool field to true as the v1.Secret don't include it ! + rec.isCore = true assert.Equal(t, c, rec) delete(corePkgData, rec.Name) continue @@ -236,17 +236,23 @@ func TestOutput(t *testing.T) { delete(packageData, rec.Name) continue } - t.Fatalf("found an invalid element: %s", rec) + t.Fatalf("found an invalid element: %s", rec.Name) } } assert.Equal(t, 0, len(corePkgData)) assert.Equal(t, 0, len(packageData)) } -func templateDataToSecret(data TemplateData) v1.Secret { +func secretDataToSecret(data Secret) v1.Secret { d := make(map[string][]byte) - for k := range data.Data { - d[k] = []byte(data.Data[k]) + if data.isCore { + d["username"] = []byte(data.Username) + d["password"] = []byte(data.Password) + d["token"] = []byte(data.Token) + } else { + for k := range data.Data { + d[k] = []byte(data.Data[k]) + } } return v1.Secret{ ObjectMeta: metav1.ObjectMeta{Name: data.Name, Namespace: data.Namespace}, From 913f60a8f44538cece05cfbbda8d99c681e08a63 Mon Sep 17 00:00:00 2001 From: cmoulliard Date: Thu, 19 Dec 2024 18:22:15 +0100 Subject: [PATCH 05/13] Improve the description of the flag: outputFormat to mention the 3 formats supported Signed-off-by: cmoulliard --- pkg/cmd/get/root.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/cmd/get/root.go b/pkg/cmd/get/root.go index 23ea8c15..88d95545 100644 --- a/pkg/cmd/get/root.go +++ b/pkg/cmd/get/root.go @@ -22,7 +22,7 @@ func init() { GetCmd.AddCommand(ClustersCmd) GetCmd.AddCommand(SecretsCmd) GetCmd.PersistentFlags().StringSliceVarP(&packages, "packages", "p", []string{}, "names of packages.") - GetCmd.PersistentFlags().StringVarP(&outputFormat, "output", "o", "", "Output format. table or json.") + GetCmd.PersistentFlags().StringVarP(&outputFormat, "output", "o", "", "Output format: table (default if not specified), json or yaml.") GetCmd.PersistentFlags().StringVarP(&helpers.KubeConfigPath, "kubeconfig", "", "", "kube config file Path.") } From 288284e4c83f0f3fa863628b46ea8e04be759b52 Mon Sep 17 00:00:00 2001 From: cmoulliard Date: Fri, 20 Dec 2024 09:44:19 +0100 Subject: [PATCH 06/13] Set the default outputFormat as: table Signed-off-by: cmoulliard --- pkg/cmd/get/clusters.go | 2 +- pkg/cmd/get/root.go | 2 +- pkg/cmd/get/secrets.go | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pkg/cmd/get/clusters.go b/pkg/cmd/get/clusters.go index 8d880765..3cc3babb 100644 --- a/pkg/cmd/get/clusters.go +++ b/pkg/cmd/get/clusters.go @@ -90,7 +90,7 @@ func printClustersOutput(outWriter io.Writer, clusters []Cluster, format string) return util.PrintDataAsJson(clusters, outWriter) case "yaml": return util.PrintDataAsYaml(clusters, outWriter) - case "": + case "table": return util.PrintTable(generateClusterTable(clusters), outWriter) default: diff --git a/pkg/cmd/get/root.go b/pkg/cmd/get/root.go index 88d95545..0bd62036 100644 --- a/pkg/cmd/get/root.go +++ b/pkg/cmd/get/root.go @@ -22,7 +22,7 @@ func init() { GetCmd.AddCommand(ClustersCmd) GetCmd.AddCommand(SecretsCmd) GetCmd.PersistentFlags().StringSliceVarP(&packages, "packages", "p", []string{}, "names of packages.") - GetCmd.PersistentFlags().StringVarP(&outputFormat, "output", "o", "", "Output format: table (default if not specified), json or yaml.") + GetCmd.PersistentFlags().StringVarP(&outputFormat, "output", "o", "table", "Output format: table (default if not specified), json or yaml.") GetCmd.PersistentFlags().StringVarP(&helpers.KubeConfigPath, "kubeconfig", "", "", "kube config file Path.") } diff --git a/pkg/cmd/get/secrets.go b/pkg/cmd/get/secrets.go index 07ac9496..1a688e33 100644 --- a/pkg/cmd/get/secrets.go +++ b/pkg/cmd/get/secrets.go @@ -209,7 +209,7 @@ func printSecretsOutput(outWriter io.Writer, secrets []Secret, format string) er return util.PrintDataAsJson(secrets, outWriter) case "yaml": return util.PrintDataAsYaml(secrets, outWriter) - case "", "table": + case "table": return util.PrintTable(generateSecretTable(secrets), outWriter) default: return fmt.Errorf("output format %s is not supported", format) From 771fd890bcd9db767508e9a6989db79f0dd2c725 Mon Sep 17 00:00:00 2001 From: cmoulliard Date: Fri, 20 Dec 2024 09:53:59 +0100 Subject: [PATCH 07/13] Moving the print functions to a new package: printer Signed-off-by: cmoulliard --- pkg/cmd/get/clusters.go | 7 ++++--- pkg/cmd/get/secrets.go | 8 ++++---- pkg/printer/printer.go | 30 ++++++++++++++++++++++++++++++ pkg/util/util.go | 26 -------------------------- 4 files changed, 38 insertions(+), 33 deletions(-) create mode 100644 pkg/printer/printer.go diff --git a/pkg/cmd/get/clusters.go b/pkg/cmd/get/clusters.go index 3cc3babb..b3c8ed91 100644 --- a/pkg/cmd/get/clusters.go +++ b/pkg/cmd/get/clusters.go @@ -7,6 +7,7 @@ import ( "github.com/cnoe-io/idpbuilder/pkg/cmd/helpers" "github.com/cnoe-io/idpbuilder/pkg/k8s" "github.com/cnoe-io/idpbuilder/pkg/kind" + "github.com/cnoe-io/idpbuilder/pkg/printer" "github.com/cnoe-io/idpbuilder/pkg/util" "github.com/spf13/cobra" "io" @@ -87,11 +88,11 @@ func list(cmd *cobra.Command, args []string) error { func printClustersOutput(outWriter io.Writer, clusters []Cluster, format string) error { switch format { case "json": - return util.PrintDataAsJson(clusters, outWriter) + return printer.PrintDataAsJson(clusters, outWriter) case "yaml": - return util.PrintDataAsYaml(clusters, outWriter) + return printer.PrintDataAsYaml(clusters, outWriter) case "table": - return util.PrintTable(generateClusterTable(clusters), outWriter) + return printer.PrintTable(generateClusterTable(clusters), outWriter) default: return fmt.Errorf("output format %s is not supported", format) diff --git a/pkg/cmd/get/secrets.go b/pkg/cmd/get/secrets.go index 1a688e33..53b3840e 100644 --- a/pkg/cmd/get/secrets.go +++ b/pkg/cmd/get/secrets.go @@ -3,7 +3,7 @@ package get import ( "context" "fmt" - "github.com/cnoe-io/idpbuilder/pkg/util" + "github.com/cnoe-io/idpbuilder/pkg/printer" "io" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "os" @@ -206,11 +206,11 @@ func generateSecretTable(secretTable []Secret) metav1.Table { func printSecretsOutput(outWriter io.Writer, secrets []Secret, format string) error { switch format { case "json": - return util.PrintDataAsJson(secrets, outWriter) + return printer.PrintDataAsJson(secrets, outWriter) case "yaml": - return util.PrintDataAsYaml(secrets, outWriter) + return printer.PrintDataAsYaml(secrets, outWriter) case "table": - return util.PrintTable(generateSecretTable(secrets), outWriter) + return printer.PrintTable(generateSecretTable(secrets), outWriter) default: return fmt.Errorf("output format %s is not supported", format) } diff --git a/pkg/printer/printer.go b/pkg/printer/printer.go new file mode 100644 index 00000000..1c31240b --- /dev/null +++ b/pkg/printer/printer.go @@ -0,0 +1,30 @@ +package printer + +import ( + "encoding/json" + "io" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/cli-runtime/pkg/printers" + "sigs.k8s.io/yaml" +) + +func PrintTable(table metav1.Table, outWriter io.Writer) error { + printer := printers.NewTablePrinter(printers.PrintOptions{}) + return printer.PrintObj(&table, outWriter) +} + +func PrintDataAsJson(data any, outWriter io.Writer) error { + enc := json.NewEncoder(outWriter) + enc.SetEscapeHTML(false) + enc.SetIndent("", " ") + return enc.Encode(data) +} + +func PrintDataAsYaml(data any, outWriter io.Writer) error { + b, err := yaml.Marshal(data) + if err != nil { + return err + } + _, err = outWriter.Write(b) + return err +} diff --git a/pkg/util/util.go b/pkg/util/util.go index 4a21b8c1..dbd606fe 100644 --- a/pkg/util/util.go +++ b/pkg/util/util.go @@ -4,10 +4,7 @@ import ( "context" "crypto/rand" "crypto/tls" - "encoding/json" "fmt" - "io" - "k8s.io/cli-runtime/pkg/printers" "math" "math/big" mathrand "math/rand" @@ -19,11 +16,9 @@ import ( "time" "github.com/cnoe-io/idpbuilder/api/v1alpha1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/kind/pkg/cluster" - "sigs.k8s.io/yaml" ) const ( @@ -188,24 +183,3 @@ func SetPackageLabels(obj client.Object) { labels[v1alpha1.PackageTypeLabelKey] = v1alpha1.PackageTypeLabelCustom } } - -func PrintTable(table metav1.Table, outWriter io.Writer) error { - printer := printers.NewTablePrinter(printers.PrintOptions{}) - return printer.PrintObj(&table, outWriter) -} - -func PrintDataAsJson(data any, outWriter io.Writer) error { - enc := json.NewEncoder(outWriter) - enc.SetEscapeHTML(false) - enc.SetIndent("", " ") - return enc.Encode(data) -} - -func PrintDataAsYaml(data any, outWriter io.Writer) error { - b, err := yaml.Marshal(data) - if err != nil { - return err - } - _, err = outWriter.Write(b) - return err -} From 813c0cd3bff7f5e7fba1ecc6b7f5ab114d4e0cc8 Mon Sep 17 00:00:00 2001 From: cmoulliard Date: Fri, 20 Dec 2024 09:57:34 +0100 Subject: [PATCH 08/13] Rename generateSecret to populateSecret Signed-off-by: cmoulliard --- pkg/cmd/get/secrets.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/pkg/cmd/get/secrets.go b/pkg/cmd/get/secrets.go index 53b3840e..5e885dd6 100644 --- a/pkg/cmd/get/secrets.go +++ b/pkg/cmd/get/secrets.go @@ -103,7 +103,7 @@ func printAllPackageSecrets(ctx context.Context, outWriter io.Writer, kubeClient } return fmt.Errorf("getting secret %s in %s: %w", v[i], k, sErr) } - secrets = append(secrets, generateSecret(secret, true)) + secrets = append(secrets, populateSecret(secret, true)) } } @@ -113,7 +113,7 @@ func printAllPackageSecrets(ctx context.Context, outWriter io.Writer, kubeClient } for i := range cnoeLabelSecrets.Items { - secrets = append(secrets, generateSecret(cnoeLabelSecrets.Items[i], false)) + secrets = append(secrets, populateSecret(cnoeLabelSecrets.Items[i], false)) } if len(secrets) == 0 { @@ -139,7 +139,7 @@ func printPackageSecrets(ctx context.Context, outWriter io.Writer, kubeClient cl } return fmt.Errorf("getting secret %s in %s: %w", secretNames[j], p, sErr) } - secrets = append(secrets, generateSecret(secret, true)) + secrets = append(secrets, populateSecret(secret, true)) } continue } @@ -157,7 +157,7 @@ func printPackageSecrets(ctx context.Context, outWriter io.Writer, kubeClient cl } for i := range cnoeLabelSecrets.Items { - secrets = append(secrets, generateSecret(cnoeLabelSecrets.Items[i], false)) + secrets = append(secrets, populateSecret(cnoeLabelSecrets.Items[i], false)) } if len(secrets) == 0 { @@ -216,7 +216,7 @@ func printSecretsOutput(outWriter io.Writer, secrets []Secret, format string) er } } -func generateSecret(s v1.Secret, isCoreSecret bool) Secret { +func populateSecret(s v1.Secret, isCoreSecret bool) Secret { secret := Secret{ Name: s.Name, Namespace: s.Namespace, From 580042fa19690c663ccdf77de4aa90a9d6c05a60 Mon Sep 17 00:00:00 2001 From: cmoulliard Date: Fri, 20 Dec 2024 12:16:51 +0100 Subject: [PATCH 09/13] Moving the function PrintOutput to the printer package. WIP Signed-off-by: cmoulliard --- pkg/cmd/get/clusters.go | 46 +++++++++++++++++++++++++++-------------- pkg/cmd/get/secrets.go | 17 ++------------- pkg/printer/printer.go | 16 +++++++++++++- 3 files changed, 48 insertions(+), 31 deletions(-) diff --git a/pkg/cmd/get/clusters.go b/pkg/cmd/get/clusters.go index b3c8ed91..ac3c6b47 100644 --- a/pkg/cmd/get/clusters.go +++ b/pkg/cmd/get/clusters.go @@ -10,7 +10,6 @@ import ( "github.com/cnoe-io/idpbuilder/pkg/printer" "github.com/cnoe-io/idpbuilder/pkg/util" "github.com/spf13/cobra" - "io" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -18,6 +17,7 @@ import ( "k8s.io/client-go/tools/clientcmd" "k8s.io/client-go/tools/clientcmd/api" "os" + "reflect" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/kind/pkg/cluster" "slices" @@ -76,7 +76,7 @@ func list(cmd *cobra.Command, args []string) error { return err } else { // Convert the list of the clusters to a Table of clusters and print the table using the format selected - err := printClustersOutput(os.Stdout, clusters, outputFormat) + err := printer.PrintOutput(os.Stdout, clusters, generateClusterTable(clusters), outputFormat) if err != nil { return err } else { @@ -85,18 +85,22 @@ func list(cmd *cobra.Command, args []string) error { } } -func printClustersOutput(outWriter io.Writer, clusters []Cluster, format string) error { - switch format { - case "json": - return printer.PrintDataAsJson(clusters, outWriter) - case "yaml": - return printer.PrintDataAsYaml(clusters, outWriter) - case "table": - return printer.PrintTable(generateClusterTable(clusters), outWriter) - default: - - return fmt.Errorf("output format %s is not supported", format) +func ConvertTypeToAnySlice[T any](input []T) ([]any, error) { + var results []any + + for _, item := range input { + itemValue := reflect.ValueOf(item) + itemType := reflect.TypeOf(item) + + if itemValue.Type().ConvertibleTo(itemType) { + convertedValue := itemValue.Convert(itemType) + results = append(results, convertedValue.Interface()) + } else { + return nil, fmt.Errorf("item of type %s is not convertible to %s", itemValue.Type(), itemType) + } } + + return results, nil } func populateClusterList() ([]Cluster, error) { @@ -225,7 +229,7 @@ func populateClusterList() ([]Cluster, error) { return clusterList, nil } -func generateClusterTable(clusterTable []Cluster) metav1.Table { +func generateClusterTable(input []Cluster) metav1.Table { table := &metav1.Table{} table.ColumnDefinitions = []metav1.TableColumnDefinition{ {Name: "Name", Type: "string"}, @@ -235,7 +239,8 @@ func generateClusterTable(clusterTable []Cluster) metav1.Table { {Name: "Kube-Port", Type: "string"}, {Name: "Nodes", Type: "string"}, } - for _, cluster := range clusterTable { + + for _, cluster := range input { row := metav1.TableRow{ Cells: []interface{}{ cluster.Name, @@ -251,6 +256,17 @@ func generateClusterTable(clusterTable []Cluster) metav1.Table { return *table } +func convertArrayAnyToClusters(input []any) []Cluster { + var clusters []Cluster + for _, item := range input { + cluster, ok := item.(Cluster) + if ok { + clusters = append(clusters, cluster) + } + } + return clusters +} + func generateNodeData(nodes []Node) string { var result string for i, aNode := range nodes { diff --git a/pkg/cmd/get/secrets.go b/pkg/cmd/get/secrets.go index 5e885dd6..2ac6130c 100644 --- a/pkg/cmd/get/secrets.go +++ b/pkg/cmd/get/secrets.go @@ -120,7 +120,7 @@ func printAllPackageSecrets(ctx context.Context, outWriter io.Writer, kubeClient fmt.Println("no secrets found") return nil } - return printSecretsOutput(outWriter, secrets, format) + return printer.PrintOutput(outWriter, secrets, generateSecretTable(secrets), format) } func printPackageSecrets(ctx context.Context, outWriter io.Writer, kubeClient client.Client, format string) error { @@ -166,7 +166,7 @@ func printPackageSecrets(ctx context.Context, outWriter io.Writer, kubeClient cl } } - return printSecretsOutput(outWriter, secrets, format) + return printer.PrintOutput(outWriter, secrets, generateSecretTable(secrets), format) } func generateSecretTable(secretTable []Secret) metav1.Table { @@ -203,19 +203,6 @@ func generateSecretTable(secretTable []Secret) metav1.Table { return *table } -func printSecretsOutput(outWriter io.Writer, secrets []Secret, format string) error { - switch format { - case "json": - return printer.PrintDataAsJson(secrets, outWriter) - case "yaml": - return printer.PrintDataAsYaml(secrets, outWriter) - case "table": - return printer.PrintTable(generateSecretTable(secrets), outWriter) - default: - return fmt.Errorf("output format %s is not supported", format) - } -} - func populateSecret(s v1.Secret, isCoreSecret bool) Secret { secret := Secret{ Name: s.Name, diff --git a/pkg/printer/printer.go b/pkg/printer/printer.go index 1c31240b..ae54f3a6 100644 --- a/pkg/printer/printer.go +++ b/pkg/printer/printer.go @@ -2,13 +2,27 @@ package printer import ( "encoding/json" + "fmt" "io" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/cli-runtime/pkg/printers" "sigs.k8s.io/yaml" ) -func PrintTable(table metav1.Table, outWriter io.Writer) error { +func PrintOutput[T any](outWriter io.Writer, input []T, inputTable metav1.Table, format string) error { + switch format { + case "json": + return PrintDataAsJson(input, outWriter) + case "yaml": + return PrintDataAsYaml(input, outWriter) + case "table": + return PrintDataAsTable(inputTable, outWriter) + default: + return fmt.Errorf("output format %s is not supported", format) + } +} + +func PrintDataAsTable(table metav1.Table, outWriter io.Writer) error { printer := printers.NewTablePrinter(printers.PrintOptions{}) return printer.PrintObj(&table, outWriter) } From 13b4ad97f2d3e313ecc7ecd3b09a4e1b93e157e4 Mon Sep 17 00:00:00 2001 From: cmoulliard Date: Fri, 20 Dec 2024 13:40:03 +0100 Subject: [PATCH 10/13] Created entity package to manage the internal types: Secret, Cluster, Node, etc. and created printer methods. WIP Signed-off-by: cmoulliard --- pkg/cmd/get/clusters.go | 123 ++++-------------------------------- pkg/cmd/get/secrets.go | 39 ++++++------ pkg/cmd/get/secrets_test.go | 19 +++--- pkg/entity/allocated.go | 6 ++ pkg/entity/capacity.go | 7 ++ pkg/entity/cluster.go | 10 +++ pkg/entity/node.go | 9 +++ pkg/entity/secret.go | 11 ++++ pkg/printer/printer.go | 114 +++++++++++++++++++++++++++++++++ 9 files changed, 200 insertions(+), 138 deletions(-) create mode 100644 pkg/entity/allocated.go create mode 100644 pkg/entity/capacity.go create mode 100644 pkg/entity/cluster.go create mode 100644 pkg/entity/node.go create mode 100644 pkg/entity/secret.go diff --git a/pkg/cmd/get/clusters.go b/pkg/cmd/get/clusters.go index ac3c6b47..22a13be2 100644 --- a/pkg/cmd/get/clusters.go +++ b/pkg/cmd/get/clusters.go @@ -5,6 +5,7 @@ import ( "fmt" "github.com/cnoe-io/idpbuilder/api/v1alpha1" "github.com/cnoe-io/idpbuilder/pkg/cmd/helpers" + "github.com/cnoe-io/idpbuilder/pkg/entity" "github.com/cnoe-io/idpbuilder/pkg/k8s" "github.com/cnoe-io/idpbuilder/pkg/kind" "github.com/cnoe-io/idpbuilder/pkg/printer" @@ -17,7 +18,6 @@ import ( "k8s.io/client-go/tools/clientcmd" "k8s.io/client-go/tools/clientcmd/api" "os" - "reflect" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/kind/pkg/cluster" "slices" @@ -29,34 +29,6 @@ type ClusterManager struct { clients map[string]client.Client // map of cluster name to client } -type Cluster struct { - Name string - URLKubeApi string - KubePort int32 - TlsCheck bool - ExternalPort int32 - Nodes []Node -} - -type Node struct { - Name string - InternalIP string - ExternalIP string - Capacity Capacity - Allocated Allocated -} - -type Capacity struct { - Memory float64 - Pods int64 - Cpu int64 -} - -type Allocated struct { - Cpu string - Memory string -} - var ClustersCmd = &cobra.Command{ Use: "clusters", Short: "Get idp clusters", @@ -75,35 +47,15 @@ func list(cmd *cobra.Command, args []string) error { if err != nil { return err } else { - // Convert the list of the clusters to a Table of clusters and print the table using the format selected - err := printer.PrintOutput(os.Stdout, clusters, generateClusterTable(clusters), outputFormat) - if err != nil { - return err - } else { - return nil + clusterPrinter := printer.ClusterPrinter{ + Clusters: clusters, + OutWriter: os.Stdout, } + return clusterPrinter.PrintOutput(outputFormat) } } -func ConvertTypeToAnySlice[T any](input []T) ([]any, error) { - var results []any - - for _, item := range input { - itemValue := reflect.ValueOf(item) - itemType := reflect.TypeOf(item) - - if itemValue.Type().ConvertibleTo(itemType) { - convertedValue := itemValue.Convert(itemType) - results = append(results, convertedValue.Interface()) - } else { - return nil, fmt.Errorf("item of type %s is not convertible to %s", itemValue.Type(), itemType) - } - } - - return results, nil -} - -func populateClusterList() ([]Cluster, error) { +func populateClusterList() ([]entity.Cluster, error) { logger := helpers.CmdLogger detectOpt, err := util.DetectKindNodeProvider() @@ -129,7 +81,7 @@ func populateClusterList() ([]Cluster, error) { } // Create an empty array of clusters to collect the information - clusterList := []Cluster{} + clusterList := []entity.Cluster{} // List the idp builder clusters according to the provider: podman or docker provider := cluster.NewProvider(cluster.ProviderWithLogger(kind.KindLoggerFromLogr(&logger)), detectOpt) @@ -145,7 +97,7 @@ func populateClusterList() ([]Cluster, error) { } for _, cluster := range clusters { - aCluster := Cluster{Name: cluster} + aCluster := entity.Cluster{Name: cluster} // Search about the idp cluster within the kubeconfig file and show information c, found := findClusterByName(config, "kind-"+cluster) @@ -187,7 +139,7 @@ func populateClusterList() ([]Cluster, error) { for _, node := range nodeList.Items { nodeName := node.Name - aNode := Node{} + aNode := entity.Node{} aNode.Name = nodeName for _, addr := range node.Status.Addresses { @@ -206,7 +158,7 @@ func populateClusterList() ([]Cluster, error) { cpu := resources[corev1.ResourceCPU] pods := resources[corev1.ResourcePods] - aNode.Capacity = Capacity{ + aNode.Capacity = entity.Capacity{ Memory: float64(memory.Value()) / (1024 * 1024 * 1024), Cpu: cpu.Value(), Pods: pods.Value(), @@ -229,60 +181,11 @@ func populateClusterList() ([]Cluster, error) { return clusterList, nil } -func generateClusterTable(input []Cluster) metav1.Table { - table := &metav1.Table{} - table.ColumnDefinitions = []metav1.TableColumnDefinition{ - {Name: "Name", Type: "string"}, - {Name: "External-Port", Type: "string"}, - {Name: "Kube-Api", Type: "string"}, - {Name: "TLS", Type: "string"}, - {Name: "Kube-Port", Type: "string"}, - {Name: "Nodes", Type: "string"}, - } - - for _, cluster := range input { - row := metav1.TableRow{ - Cells: []interface{}{ - cluster.Name, - cluster.ExternalPort, - cluster.URLKubeApi, - cluster.TlsCheck, - cluster.KubePort, - generateNodeData(cluster.Nodes), - }, - } - table.Rows = append(table.Rows, row) - } - return *table -} - -func convertArrayAnyToClusters(input []any) []Cluster { - var clusters []Cluster - for _, item := range input { - cluster, ok := item.(Cluster) - if ok { - clusters = append(clusters, cluster) - } - } - return clusters -} - -func generateNodeData(nodes []Node) string { - var result string - for i, aNode := range nodes { - result += aNode.Name - if i < len(nodes)-1 { - result += "," - } - } - return result -} - -func printAllocatedResources(ctx context.Context, k8sClient client.Client, nodeName string) (Allocated, error) { +func printAllocatedResources(ctx context.Context, k8sClient client.Client, nodeName string) (entity.Allocated, error) { // List all pods on the specified node var podList corev1.PodList if err := k8sClient.List(ctx, &podList, client.MatchingFields{"spec.nodeName": nodeName}); err != nil { - return Allocated{}, fmt.Errorf("failed to list pods on node %s.", nodeName) + return entity.Allocated{}, fmt.Errorf("failed to list pods on node %s.", nodeName) } // Initialize counters for CPU and memory requests @@ -301,7 +204,7 @@ func printAllocatedResources(ctx context.Context, k8sClient client.Client, nodeN } } - allocated := Allocated{ + allocated := entity.Allocated{ Memory: totalMemory.String(), Cpu: totalCPU.String(), } diff --git a/pkg/cmd/get/secrets.go b/pkg/cmd/get/secrets.go index 2ac6130c..e731b24c 100644 --- a/pkg/cmd/get/secrets.go +++ b/pkg/cmd/get/secrets.go @@ -3,6 +3,7 @@ package get import ( "context" "fmt" + "github.com/cnoe-io/idpbuilder/pkg/entity" "github.com/cnoe-io/idpbuilder/pkg/printer" "io" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -50,16 +51,6 @@ type TemplateData struct { Data map[string]string `json:"data"` } -type Secret struct { - isCore bool - Name string `json:"name"` - Namespace string `json:"namespace"` - Username string `json:"username,omitempty"` - Password string `json:"password,omitempty"` - Token string `json:"token,omitempty"` - Data map[string]string `json:"data,omitempty"` -} - func getSecretsE(cmd *cobra.Command, args []string) error { ctx, ctxCancel := context.WithCancel(cmd.Context()) defer ctxCancel() @@ -92,7 +83,11 @@ func getSecretsE(cmd *cobra.Command, args []string) error { func printAllPackageSecrets(ctx context.Context, outWriter io.Writer, kubeClient client.Client, format string) error { selector := labels.NewSelector() - secrets := []Secret{} + secrets := []entity.Secret{} + secretPrinter := printer.SecretPrinter{ + Secrets: secrets, + OutWriter: outWriter, + } for k, v := range corePkgSecrets { for i := range v { @@ -120,12 +115,17 @@ func printAllPackageSecrets(ctx context.Context, outWriter io.Writer, kubeClient fmt.Println("no secrets found") return nil } - return printer.PrintOutput(outWriter, secrets, generateSecretTable(secrets), format) + + secretPrinter.Secrets = secrets + return secretPrinter.PrintOutput(format) } func printPackageSecrets(ctx context.Context, outWriter io.Writer, kubeClient client.Client, format string) error { selector := labels.NewSelector() - secrets := []Secret{} + secrets := []entity.Secret{} + secretPrinter := printer.SecretPrinter{ + OutWriter: outWriter, + } for i := range packages { p := packages[i] @@ -166,10 +166,11 @@ func printPackageSecrets(ctx context.Context, outWriter io.Writer, kubeClient cl } } - return printer.PrintOutput(outWriter, secrets, generateSecretTable(secrets), format) + secretPrinter.Secrets = secrets + return secretPrinter.PrintOutput(format) } -func generateSecretTable(secretTable []Secret) metav1.Table { +func generateSecretTable(secretTable []entity.Secret) metav1.Table { table := &metav1.Table{} table.ColumnDefinitions = []metav1.TableColumnDefinition{ {Name: "Name", Type: "string"}, @@ -182,7 +183,7 @@ func generateSecretTable(secretTable []Secret) metav1.Table { for _, secret := range secretTable { var dataEntries []string - if !secret.isCore { + if !secret.IsCore { for key, value := range secret.Data { dataEntries = append(dataEntries, fmt.Sprintf("%s=%s", key, value)) } @@ -203,14 +204,14 @@ func generateSecretTable(secretTable []Secret) metav1.Table { return *table } -func populateSecret(s v1.Secret, isCoreSecret bool) Secret { - secret := Secret{ +func populateSecret(s v1.Secret, isCoreSecret bool) entity.Secret { + secret := entity.Secret{ Name: s.Name, Namespace: s.Namespace, } if isCoreSecret { - secret.isCore = true + secret.IsCore = true secret.Username = string(s.Data["username"]) secret.Password = string(s.Data["password"]) secret.Token = string(s.Data["token"]) diff --git a/pkg/cmd/get/secrets_test.go b/pkg/cmd/get/secrets_test.go index 8346bf9d..ef4eb97c 100644 --- a/pkg/cmd/get/secrets_test.go +++ b/pkg/cmd/get/secrets_test.go @@ -8,6 +8,7 @@ import ( "testing" "github.com/cnoe-io/idpbuilder/api/v1alpha1" + "github.com/cnoe-io/idpbuilder/pkg/entity" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" v1 "k8s.io/api/core/v1" @@ -144,16 +145,16 @@ func TestOutput(t *testing.T) { ctx := context.Background() r, _ := labels.NewRequirement(v1alpha1.CLISecretLabelKey, selection.Equals, []string{v1alpha1.CLISecretLabelValue}) - corePkgData := map[string]Secret{ + corePkgData := map[string]entity.Secret{ argoCDInitialAdminSecretName: { - isCore: true, + IsCore: true, Name: argoCDInitialAdminSecretName, Namespace: "argocd", Username: "admin", Password: "abc", }, giteaAdminSecretName: { - isCore: true, + IsCore: true, Name: giteaAdminSecretName, Namespace: "gitea", Username: "admin", @@ -161,7 +162,7 @@ func TestOutput(t *testing.T) { }, } - packageData := map[string]Secret{ + packageData := map[string]entity.Secret{ "name1": { Name: "name1", Namespace: "ns1", @@ -215,7 +216,7 @@ func TestOutput(t *testing.T) { assert.Nil(t, err) // verify received json data - var received []Secret + var received []entity.Secret err = json.Unmarshal(buffer.Bytes(), &received) assert.Nil(t, err) assert.Equal(t, 4, len(received)) @@ -224,8 +225,8 @@ func TestOutput(t *testing.T) { rec := received[i] c, ok := corePkgData[rec.Name] if ok { - // Set the isCore bool field to true as the v1.Secret don't include it ! - rec.isCore = true + // Set the IsCore bool field to true as the v1.Secret don't include it ! + rec.IsCore = true assert.Equal(t, c, rec) delete(corePkgData, rec.Name) continue @@ -243,9 +244,9 @@ func TestOutput(t *testing.T) { assert.Equal(t, 0, len(packageData)) } -func secretDataToSecret(data Secret) v1.Secret { +func secretDataToSecret(data entity.Secret) v1.Secret { d := make(map[string][]byte) - if data.isCore { + if data.IsCore { d["username"] = []byte(data.Username) d["password"] = []byte(data.Password) d["token"] = []byte(data.Token) diff --git a/pkg/entity/allocated.go b/pkg/entity/allocated.go new file mode 100644 index 00000000..297f024b --- /dev/null +++ b/pkg/entity/allocated.go @@ -0,0 +1,6 @@ +package entity + +type Allocated struct { + Cpu string + Memory string +} diff --git a/pkg/entity/capacity.go b/pkg/entity/capacity.go new file mode 100644 index 00000000..cbe910dd --- /dev/null +++ b/pkg/entity/capacity.go @@ -0,0 +1,7 @@ +package entity + +type Capacity struct { + Memory float64 + Pods int64 + Cpu int64 +} diff --git a/pkg/entity/cluster.go b/pkg/entity/cluster.go new file mode 100644 index 00000000..582e29c0 --- /dev/null +++ b/pkg/entity/cluster.go @@ -0,0 +1,10 @@ +package entity + +type Cluster struct { + Name string + URLKubeApi string + KubePort int32 + TlsCheck bool + ExternalPort int32 + Nodes []Node +} diff --git a/pkg/entity/node.go b/pkg/entity/node.go new file mode 100644 index 00000000..7d07d5a6 --- /dev/null +++ b/pkg/entity/node.go @@ -0,0 +1,9 @@ +package entity + +type Node struct { + Name string + InternalIP string + ExternalIP string + Capacity Capacity + Allocated Allocated +} diff --git a/pkg/entity/secret.go b/pkg/entity/secret.go new file mode 100644 index 00000000..f7c2b53a --- /dev/null +++ b/pkg/entity/secret.go @@ -0,0 +1,11 @@ +package entity + +type Secret struct { + IsCore bool + Name string `json:"name"` + Namespace string `json:"namespace"` + Username string `json:"username,omitempty"` + Password string `json:"password,omitempty"` + Token string `json:"token,omitempty"` + Data map[string]string `json:"data,omitempty"` +} diff --git a/pkg/printer/printer.go b/pkg/printer/printer.go index ae54f3a6..265e0fbf 100644 --- a/pkg/printer/printer.go +++ b/pkg/printer/printer.go @@ -3,12 +3,126 @@ package printer import ( "encoding/json" "fmt" + "github.com/cnoe-io/idpbuilder/pkg/entity" "io" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/cli-runtime/pkg/printers" "sigs.k8s.io/yaml" + "strings" ) +type Printer interface { + PrintOutput() +} + +type ClusterPrinter struct { + Clusters []entity.Cluster + OutWriter io.Writer +} + +type SecretPrinter struct { + Secrets []entity.Secret + OutWriter io.Writer +} + +func (sp SecretPrinter) PrintOutput(format string) error { + switch format { + case "json": + return PrintDataAsJson(sp.Secrets, sp.OutWriter) + case "yaml": + return PrintDataAsYaml(sp.Secrets, sp.OutWriter) + case "table": + return PrintDataAsTable(sp.generateSecretTable(sp.Secrets), sp.OutWriter) + default: + return fmt.Errorf("output format %s is not supported", format) + } +} + +func (sp SecretPrinter) generateSecretTable(secretTable []entity.Secret) metav1.Table { + table := &metav1.Table{} + table.ColumnDefinitions = []metav1.TableColumnDefinition{ + {Name: "Name", Type: "string"}, + {Name: "Namespace", Type: "string"}, + {Name: "Username", Type: "string"}, + {Name: "Password", Type: "string"}, + {Name: "Token", Type: "string"}, + {Name: "Data", Type: "string"}, + } + for _, secret := range secretTable { + var dataEntries []string + + if !secret.IsCore { + for key, value := range secret.Data { + dataEntries = append(dataEntries, fmt.Sprintf("%s=%s", key, value)) + } + } + dataString := strings.Join(dataEntries, ", ") + row := metav1.TableRow{ + Cells: []interface{}{ + secret.Name, + secret.Namespace, + secret.Username, + secret.Password, + secret.Token, + dataString, + }, + } + table.Rows = append(table.Rows, row) + } + return *table +} + +func (cp ClusterPrinter) PrintOutput(format string) error { + switch format { + case "json": + return PrintDataAsJson(cp.Clusters, cp.OutWriter) + case "yaml": + return PrintDataAsYaml(cp.Clusters, cp.OutWriter) + case "table": + return PrintDataAsTable(cp.generateClusterTable(cp.Clusters), cp.OutWriter) + default: + return fmt.Errorf("output format %s is not supported", format) + } +} + +func (cp ClusterPrinter) generateClusterTable(input []entity.Cluster) metav1.Table { + table := &metav1.Table{} + table.ColumnDefinitions = []metav1.TableColumnDefinition{ + {Name: "Name", Type: "string"}, + {Name: "External-Port", Type: "string"}, + {Name: "Kube-Api", Type: "string"}, + {Name: "TLS", Type: "string"}, + {Name: "Kube-Port", Type: "string"}, + {Name: "Nodes", Type: "string"}, + } + + for _, cluster := range input { + row := metav1.TableRow{ + Cells: []interface{}{ + cluster.Name, + cluster.ExternalPort, + cluster.URLKubeApi, + cluster.TlsCheck, + cluster.KubePort, + generateNodeData(cluster.Nodes), + }, + } + table.Rows = append(table.Rows, row) + } + return *table +} + +func generateNodeData(nodes []entity.Node) string { + var result string + for i, aNode := range nodes { + result += aNode.Name + if i < len(nodes)-1 { + result += "," + } + } + return result +} + func PrintOutput[T any](outWriter io.Writer, input []T, inputTable metav1.Table, format string) error { switch format { case "json": From 358c83b08ad37a86f165864b5b3a4d2195166632 Mon Sep 17 00:00:00 2001 From: cmoulliard Date: Fri, 20 Dec 2024 13:47:04 +0100 Subject: [PATCH 11/13] Replace the emtpty format value with the default: table Signed-off-by: cmoulliard --- pkg/cmd/get/secrets_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/cmd/get/secrets_test.go b/pkg/cmd/get/secrets_test.go index ef4eb97c..07842c1c 100644 --- a/pkg/cmd/get/secrets_test.go +++ b/pkg/cmd/get/secrets_test.go @@ -98,7 +98,7 @@ func TestPrintPackageSecrets(t *testing.T) { fClient.On("Get", ctx, c.getKeys[j], mock.Anything, mock.Anything).Return(c.err) } - err := printPackageSecrets(ctx, io.Discard, fClient, "") + err := printPackageSecrets(ctx, io.Discard, fClient, "table") fClient.AssertExpectations(t) assert.Nil(t, err) } @@ -135,7 +135,7 @@ func TestPrintAllPackageSecrets(t *testing.T) { for j := range c.getKeys { fClient.On("Get", ctx, c.getKeys[j], mock.Anything, mock.Anything).Return(c.err) } - err := printAllPackageSecrets(ctx, io.Discard, fClient, "") + err := printAllPackageSecrets(ctx, io.Discard, fClient, "table") fClient.AssertExpectations(t) assert.Nil(t, err) } From 3a2c119455e742d715a63fefb8a6bbaa3bf8333c Mon Sep 17 00:00:00 2001 From: cmoulliard Date: Fri, 20 Dec 2024 14:22:02 +0100 Subject: [PATCH 12/13] Move the code to their corresponding go file Signed-off-by: cmoulliard --- pkg/printer/cluster.go | 64 +++++++++++++++++++++ pkg/printer/printer.go | 128 ----------------------------------------- pkg/printer/secret.go | 61 ++++++++++++++++++++ 3 files changed, 125 insertions(+), 128 deletions(-) create mode 100644 pkg/printer/cluster.go create mode 100644 pkg/printer/secret.go diff --git a/pkg/printer/cluster.go b/pkg/printer/cluster.go new file mode 100644 index 00000000..8cdb5a8d --- /dev/null +++ b/pkg/printer/cluster.go @@ -0,0 +1,64 @@ +package printer + +import ( + "fmt" + "github.com/cnoe-io/idpbuilder/pkg/entity" + "io" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +type ClusterPrinter struct { + Clusters []entity.Cluster + OutWriter io.Writer +} + +func (cp ClusterPrinter) PrintOutput(format string) error { + switch format { + case "json": + return PrintDataAsJson(cp.Clusters, cp.OutWriter) + case "yaml": + return PrintDataAsYaml(cp.Clusters, cp.OutWriter) + case "table": + return PrintDataAsTable(cp.generateClusterTable(cp.Clusters), cp.OutWriter) + default: + return fmt.Errorf("output format %s is not supported", format) + } +} + +func (cp ClusterPrinter) generateClusterTable(input []entity.Cluster) metav1.Table { + table := &metav1.Table{} + table.ColumnDefinitions = []metav1.TableColumnDefinition{ + {Name: "Name", Type: "string"}, + {Name: "External-Port", Type: "string"}, + {Name: "Kube-Api", Type: "string"}, + {Name: "TLS", Type: "string"}, + {Name: "Kube-Port", Type: "string"}, + {Name: "Nodes", Type: "string"}, + } + + for _, cluster := range input { + row := metav1.TableRow{ + Cells: []interface{}{ + cluster.Name, + cluster.ExternalPort, + cluster.URLKubeApi, + cluster.TlsCheck, + cluster.KubePort, + generateNodeData(cluster.Nodes), + }, + } + table.Rows = append(table.Rows, row) + } + return *table +} + +func generateNodeData(nodes []entity.Node) string { + var result string + for i, aNode := range nodes { + result += aNode.Name + if i < len(nodes)-1 { + result += "," + } + } + return result +} diff --git a/pkg/printer/printer.go b/pkg/printer/printer.go index 265e0fbf..634c314e 100644 --- a/pkg/printer/printer.go +++ b/pkg/printer/printer.go @@ -2,140 +2,12 @@ package printer import ( "encoding/json" - "fmt" - "github.com/cnoe-io/idpbuilder/pkg/entity" "io" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/cli-runtime/pkg/printers" "sigs.k8s.io/yaml" - "strings" ) -type Printer interface { - PrintOutput() -} - -type ClusterPrinter struct { - Clusters []entity.Cluster - OutWriter io.Writer -} - -type SecretPrinter struct { - Secrets []entity.Secret - OutWriter io.Writer -} - -func (sp SecretPrinter) PrintOutput(format string) error { - switch format { - case "json": - return PrintDataAsJson(sp.Secrets, sp.OutWriter) - case "yaml": - return PrintDataAsYaml(sp.Secrets, sp.OutWriter) - case "table": - return PrintDataAsTable(sp.generateSecretTable(sp.Secrets), sp.OutWriter) - default: - return fmt.Errorf("output format %s is not supported", format) - } -} - -func (sp SecretPrinter) generateSecretTable(secretTable []entity.Secret) metav1.Table { - table := &metav1.Table{} - table.ColumnDefinitions = []metav1.TableColumnDefinition{ - {Name: "Name", Type: "string"}, - {Name: "Namespace", Type: "string"}, - {Name: "Username", Type: "string"}, - {Name: "Password", Type: "string"}, - {Name: "Token", Type: "string"}, - {Name: "Data", Type: "string"}, - } - for _, secret := range secretTable { - var dataEntries []string - - if !secret.IsCore { - for key, value := range secret.Data { - dataEntries = append(dataEntries, fmt.Sprintf("%s=%s", key, value)) - } - } - dataString := strings.Join(dataEntries, ", ") - row := metav1.TableRow{ - Cells: []interface{}{ - secret.Name, - secret.Namespace, - secret.Username, - secret.Password, - secret.Token, - dataString, - }, - } - table.Rows = append(table.Rows, row) - } - return *table -} - -func (cp ClusterPrinter) PrintOutput(format string) error { - switch format { - case "json": - return PrintDataAsJson(cp.Clusters, cp.OutWriter) - case "yaml": - return PrintDataAsYaml(cp.Clusters, cp.OutWriter) - case "table": - return PrintDataAsTable(cp.generateClusterTable(cp.Clusters), cp.OutWriter) - default: - return fmt.Errorf("output format %s is not supported", format) - } -} - -func (cp ClusterPrinter) generateClusterTable(input []entity.Cluster) metav1.Table { - table := &metav1.Table{} - table.ColumnDefinitions = []metav1.TableColumnDefinition{ - {Name: "Name", Type: "string"}, - {Name: "External-Port", Type: "string"}, - {Name: "Kube-Api", Type: "string"}, - {Name: "TLS", Type: "string"}, - {Name: "Kube-Port", Type: "string"}, - {Name: "Nodes", Type: "string"}, - } - - for _, cluster := range input { - row := metav1.TableRow{ - Cells: []interface{}{ - cluster.Name, - cluster.ExternalPort, - cluster.URLKubeApi, - cluster.TlsCheck, - cluster.KubePort, - generateNodeData(cluster.Nodes), - }, - } - table.Rows = append(table.Rows, row) - } - return *table -} - -func generateNodeData(nodes []entity.Node) string { - var result string - for i, aNode := range nodes { - result += aNode.Name - if i < len(nodes)-1 { - result += "," - } - } - return result -} - -func PrintOutput[T any](outWriter io.Writer, input []T, inputTable metav1.Table, format string) error { - switch format { - case "json": - return PrintDataAsJson(input, outWriter) - case "yaml": - return PrintDataAsYaml(input, outWriter) - case "table": - return PrintDataAsTable(inputTable, outWriter) - default: - return fmt.Errorf("output format %s is not supported", format) - } -} - func PrintDataAsTable(table metav1.Table, outWriter io.Writer) error { printer := printers.NewTablePrinter(printers.PrintOptions{}) return printer.PrintObj(&table, outWriter) diff --git a/pkg/printer/secret.go b/pkg/printer/secret.go new file mode 100644 index 00000000..206aa7cb --- /dev/null +++ b/pkg/printer/secret.go @@ -0,0 +1,61 @@ +package printer + +import ( + "fmt" + "github.com/cnoe-io/idpbuilder/pkg/entity" + "io" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "strings" +) + +type SecretPrinter struct { + Secrets []entity.Secret + OutWriter io.Writer +} + +func (sp SecretPrinter) PrintOutput(format string) error { + switch format { + case "json": + return PrintDataAsJson(sp.Secrets, sp.OutWriter) + case "yaml": + return PrintDataAsYaml(sp.Secrets, sp.OutWriter) + case "table": + return PrintDataAsTable(sp.generateSecretTable(sp.Secrets), sp.OutWriter) + default: + return fmt.Errorf("output format %s is not supported", format) + } +} + +func (sp SecretPrinter) generateSecretTable(secretTable []entity.Secret) metav1.Table { + table := &metav1.Table{} + table.ColumnDefinitions = []metav1.TableColumnDefinition{ + {Name: "Name", Type: "string"}, + {Name: "Namespace", Type: "string"}, + {Name: "Username", Type: "string"}, + {Name: "Password", Type: "string"}, + {Name: "Token", Type: "string"}, + {Name: "Data", Type: "string"}, + } + for _, secret := range secretTable { + var dataEntries []string + + if !secret.IsCore { + for key, value := range secret.Data { + dataEntries = append(dataEntries, fmt.Sprintf("%s=%s", key, value)) + } + } + dataString := strings.Join(dataEntries, ", ") + row := metav1.TableRow{ + Cells: []interface{}{ + secret.Name, + secret.Namespace, + secret.Username, + secret.Password, + secret.Token, + dataString, + }, + } + table.Rows = append(table.Rows, row) + } + return *table +} From 4127914e0d3e93080bc50d355e17b11d80bb71c8 Mon Sep 17 00:00:00 2001 From: cmoulliard Date: Fri, 20 Dec 2024 14:57:06 +0100 Subject: [PATCH 13/13] Remove the need to use the type to access the function Signed-off-by: cmoulliard --- pkg/printer/cluster.go | 4 ++-- pkg/printer/secret.go | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pkg/printer/cluster.go b/pkg/printer/cluster.go index 8cdb5a8d..4ebd4c55 100644 --- a/pkg/printer/cluster.go +++ b/pkg/printer/cluster.go @@ -19,13 +19,13 @@ func (cp ClusterPrinter) PrintOutput(format string) error { case "yaml": return PrintDataAsYaml(cp.Clusters, cp.OutWriter) case "table": - return PrintDataAsTable(cp.generateClusterTable(cp.Clusters), cp.OutWriter) + return PrintDataAsTable(generateClusterTable(cp.Clusters), cp.OutWriter) default: return fmt.Errorf("output format %s is not supported", format) } } -func (cp ClusterPrinter) generateClusterTable(input []entity.Cluster) metav1.Table { +func generateClusterTable(input []entity.Cluster) metav1.Table { table := &metav1.Table{} table.ColumnDefinitions = []metav1.TableColumnDefinition{ {Name: "Name", Type: "string"}, diff --git a/pkg/printer/secret.go b/pkg/printer/secret.go index 206aa7cb..425f961d 100644 --- a/pkg/printer/secret.go +++ b/pkg/printer/secret.go @@ -20,13 +20,13 @@ func (sp SecretPrinter) PrintOutput(format string) error { case "yaml": return PrintDataAsYaml(sp.Secrets, sp.OutWriter) case "table": - return PrintDataAsTable(sp.generateSecretTable(sp.Secrets), sp.OutWriter) + return PrintDataAsTable(generateSecretTable(sp.Secrets), sp.OutWriter) default: return fmt.Errorf("output format %s is not supported", format) } } -func (sp SecretPrinter) generateSecretTable(secretTable []entity.Secret) metav1.Table { +func generateSecretTable(secretTable []entity.Secret) metav1.Table { table := &metav1.Table{} table.ColumnDefinitions = []metav1.TableColumnDefinition{ {Name: "Name", Type: "string"},