Skip to content

Commit

Permalink
Improve the code to print the secrets using the cli-runtime line and …
Browse files Browse the repository at this point in the history
…printTable. #463

Signed-off-by: cmoulliard <[email protected]>
  • Loading branch information
cmoulliard committed Dec 19, 2024
1 parent 406cc03 commit 9fb9c76
Show file tree
Hide file tree
Showing 6 changed files with 141 additions and 96 deletions.
38 changes: 21 additions & 17 deletions pkg/cmd/get/clusters.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package get

import (
"bytes"
"context"
"fmt"
"github.com/cnoe-io/idpbuilder/api/v1alpha1"
Expand All @@ -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"
Expand Down Expand Up @@ -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)
}
}

Expand Down Expand Up @@ -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 {
Expand Down
2 changes: 1 addition & 1 deletion pkg/cmd/get/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -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.")
}

Expand Down
138 changes: 71 additions & 67 deletions pkg/cmd/get/secrets.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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",
Expand All @@ -42,17 +34,27 @@ 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"`
Namespace string `json:"namespace"`
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()
Expand All @@ -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 {
Expand All @@ -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]
Expand All @@ -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
}
Expand All @@ -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) {
Expand Down
7 changes: 3 additions & 4 deletions pkg/cmd/get/secrets_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import (
"bytes"
"context"
"encoding/json"
"io"
"testing"

"github.com/cnoe-io/idpbuilder/api/v1alpha1"
Expand Down Expand Up @@ -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)
}
Expand Down Expand Up @@ -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)
}
Expand Down Expand Up @@ -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)

Expand Down
7 changes: 0 additions & 7 deletions pkg/cmd/get/templates/secrets.tmpl

This file was deleted.

Loading

0 comments on commit 9fb9c76

Please sign in to comment.