From 3619cb8bd1d5426c621673a48d2fd147ee79a51f Mon Sep 17 00:00:00 2001 From: circa10a Date: Sat, 3 Oct 2020 15:26:27 -0500 Subject: [PATCH] Switch get commands to use tables for output Signed-off-by: circa10a --- .github/workflows/e2e.yaml | 9 ++++++ cmd/gotk/get.go | 4 +++ cmd/gotk/get_helmrelease.go | 49 +++++++++++++++++++---------- cmd/gotk/get_kustomization.go | 49 +++++++++++++++++++---------- cmd/gotk/get_source_bucket.go | 46 +++++++++++++++++---------- cmd/gotk/get_source_git.go | 46 +++++++++++++++++---------- cmd/gotk/get_source_helm.go | 46 +++++++++++++++++---------- cmd/gotk/utils.go | 19 +++++++++++ docs/cmd/gotk_get.md | 3 +- docs/cmd/gotk_get_helmreleases.md | 1 + docs/cmd/gotk_get_kustomizations.md | 1 + docs/cmd/gotk_get_sources.md | 1 + docs/cmd/gotk_get_sources_bucket.md | 1 + docs/cmd/gotk_get_sources_git.md | 1 + docs/cmd/gotk_get_sources_helm.md | 1 + go.mod | 1 + go.sum | 4 +++ 17 files changed, 201 insertions(+), 81 deletions(-) diff --git a/.github/workflows/e2e.yaml b/.github/workflows/e2e.yaml index 80418375..4c23f27b 100644 --- a/.github/workflows/e2e.yaml +++ b/.github/workflows/e2e.yaml @@ -59,6 +59,9 @@ jobs: - name: gotk get sources git run: | ./bin/gotk get sources git + - name: gotk get sources git --all-namespaces + run: | + ./bin/gotk get sources git --all-namespaces - name: gotk create kustomization run: | ./bin/gotk create kustomization podinfo \ @@ -76,6 +79,9 @@ jobs: - name: gotk get kustomizations run: | ./bin/gotk get kustomizations + - name: gotk get kustomizations --all-namespaces + run: | + ./bin/gotk get kustomizations --all-namespaces - name: gotk suspend kustomization run: | ./bin/gotk suspend kustomization podinfo @@ -112,6 +118,9 @@ jobs: - name: gotk get helmreleases run: | ./bin/gotk get helmreleases + - name: gotk get helmreleases --all-namespaces + run: | + ./bin/gotk get helmreleases --all-namespaces - name: gotk export helmrelease run: | ./bin/gotk export hr --all diff --git a/cmd/gotk/get.go b/cmd/gotk/get.go index 1e722dad..c9486f7f 100644 --- a/cmd/gotk/get.go +++ b/cmd/gotk/get.go @@ -26,6 +26,10 @@ var getCmd = &cobra.Command{ Long: "The get sub-commands print the statuses of sources and resources.", } +var allNamespaces bool + func init() { + getCmd.PersistentFlags().BoolVarP(&allNamespaces, "all-namespaces", "A", false, + "list the requested object(s) across all namespaces") rootCmd.AddCommand(getCmd) } diff --git a/cmd/gotk/get_helmrelease.go b/cmd/gotk/get_helmrelease.go index b247726c..d810e598 100644 --- a/cmd/gotk/get_helmrelease.go +++ b/cmd/gotk/get_helmrelease.go @@ -18,6 +18,10 @@ package main import ( "context" + "os" + "strconv" + "strings" + "github.com/fluxcd/pkg/apis/meta" "github.com/spf13/cobra" @@ -51,8 +55,12 @@ func getHelmReleaseCmdRun(cmd *cobra.Command, args []string) error { return err } + var listOpts []client.ListOption + if !allNamespaces { + listOpts = append(listOpts, client.InNamespace(namespace)) + } var list helmv2.HelmReleaseList - err = kubeClient.List(ctx, &list, client.InNamespace(namespace)) + err = kubeClient.List(ctx, &list, listOpts...) if err != nil { return err } @@ -62,26 +70,35 @@ func getHelmReleaseCmdRun(cmd *cobra.Command, args []string) error { return nil } + header := []string{"Name", "Revision", "Suspended", "Ready", "Message"} + if allNamespaces { + header = append([]string{"Namespace"}, header...) + } + var rows [][]string for _, helmRelease := range list.Items { - if helmRelease.Spec.Suspend { - logger.Successf("%s is suspended", helmRelease.GetName()) - continue - } - isInitialized := false + row := []string{} if c := meta.GetCondition(helmRelease.Status.Conditions, meta.ReadyCondition); c != nil { - switch c.Status { - case corev1.ConditionTrue: - logger.Successf("%s last applied revision %s", helmRelease.GetName(), helmRelease.Status.LastAppliedRevision) - case corev1.ConditionUnknown: - logger.Successf("%s reconciling", helmRelease.GetName()) - default: - logger.Failuref("%s %s", helmRelease.GetName(), c.Message) + row = []string{ + helmRelease.GetName(), + helmRelease.Status.LastAppliedRevision, + strings.Title(strconv.FormatBool(helmRelease.Spec.Suspend)), + string(c.Status), + c.Message, + } + } else { + row = []string{ + helmRelease.GetName(), + helmRelease.Status.LastAppliedRevision, + strings.Title(strconv.FormatBool(helmRelease.Spec.Suspend)), + string(corev1.ConditionFalse), + "waiting to be reconciled", } - isInitialized = true } - if !isInitialized { - logger.Failuref("%s is not ready", helmRelease.GetName()) + if allNamespaces { + row = append([]string{helmRelease.Namespace}, row...) } + rows = append(rows, row) } + utils.printTable(os.Stdout, header, rows) return nil } diff --git a/cmd/gotk/get_kustomization.go b/cmd/gotk/get_kustomization.go index 38baf3a7..ac8374cd 100644 --- a/cmd/gotk/get_kustomization.go +++ b/cmd/gotk/get_kustomization.go @@ -18,6 +18,10 @@ package main import ( "context" + "os" + "strconv" + "strings" + "github.com/fluxcd/pkg/apis/meta" kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1beta1" @@ -50,8 +54,12 @@ func getKsCmdRun(cmd *cobra.Command, args []string) error { return err } + var listOpts []client.ListOption + if !allNamespaces { + listOpts = append(listOpts, client.InNamespace(namespace)) + } var list kustomizev1.KustomizationList - err = kubeClient.List(ctx, &list, client.InNamespace(namespace)) + err = kubeClient.List(ctx, &list, listOpts...) if err != nil { return err } @@ -61,26 +69,35 @@ func getKsCmdRun(cmd *cobra.Command, args []string) error { return nil } + header := []string{"Name", "Revision", "Suspended", "Ready", "Message"} + if allNamespaces { + header = append([]string{"Namespace"}, header...) + } + var rows [][]string for _, kustomization := range list.Items { - if kustomization.Spec.Suspend { - logger.Successf("%s is suspended", kustomization.GetName()) - continue - } - isInitialized := false + row := []string{} if c := meta.GetCondition(kustomization.Status.Conditions, meta.ReadyCondition); c != nil { - switch c.Status { - case corev1.ConditionTrue: - logger.Successf("%s last applied revision %s", kustomization.GetName(), kustomization.Status.LastAppliedRevision) - case corev1.ConditionUnknown: - logger.Successf("%s reconciling", kustomization.GetName()) - default: - logger.Failuref("%s %s", kustomization.GetName(), c.Message) + row = []string{ + kustomization.GetName(), + kustomization.Status.LastAppliedRevision, + strings.Title(strconv.FormatBool(kustomization.Spec.Suspend)), + string(c.Status), + c.Message, + } + } else { + row = []string{ + kustomization.GetName(), + kustomization.Status.LastAppliedRevision, + strings.Title(strconv.FormatBool(kustomization.Spec.Suspend)), + string(corev1.ConditionFalse), + "waiting to be reconciled", } - isInitialized = true } - if !isInitialized { - logger.Failuref("%s is not ready", kustomization.GetName()) + if allNamespaces { + row = append([]string{kustomization.Namespace}, row...) } + rows = append(rows, row) } + utils.printTable(os.Stdout, header, rows) return nil } diff --git a/cmd/gotk/get_source_bucket.go b/cmd/gotk/get_source_bucket.go index ee288ccd..c5d7d49c 100644 --- a/cmd/gotk/get_source_bucket.go +++ b/cmd/gotk/get_source_bucket.go @@ -18,6 +18,8 @@ package main import ( "context" + "os" + "github.com/fluxcd/pkg/apis/meta" sourcev1 "github.com/fluxcd/source-controller/api/v1beta1" @@ -49,36 +51,48 @@ func getSourceBucketCmdRun(cmd *cobra.Command, args []string) error { return err } + var listOpts []client.ListOption + if !allNamespaces { + listOpts = append(listOpts, client.InNamespace(namespace)) + } var list sourcev1.BucketList - err = kubeClient.List(ctx, &list, client.InNamespace(namespace)) + err = kubeClient.List(ctx, &list, listOpts...) if err != nil { return err } if len(list.Items) == 0 { - logger.Failuref("no sources found in %s namespace", namespace) + logger.Failuref("no bucket sources found in %s namespace", namespace) return nil } - // TODO(hidde): this should print a table, and should produce better output - // for items that have an artifact attached while they are in a reconciling - // 'Unknown' state. + header := []string{"Name", "Revision", "Ready", "Message"} + if allNamespaces { + header = append([]string{"Namespace"}, header...) + } + var rows [][]string for _, source := range list.Items { - isInitialized := false + row := []string{} if c := meta.GetCondition(source.Status.Conditions, meta.ReadyCondition); c != nil { - switch c.Status { - case corev1.ConditionTrue: - logger.Successf("%s last fetched revision: %s", source.GetName(), source.GetArtifact().Revision) - case corev1.ConditionUnknown: - logger.Successf("%s reconciling", source.GetName()) - default: - logger.Failuref("%s %s", source.GetName(), c.Message) + row = []string{ + source.GetName(), + source.GetArtifact().Revision, + string(c.Status), + c.Message, + } + } else { + row = []string{ + source.GetName(), + source.GetArtifact().Revision, + string(corev1.ConditionFalse), + "waiting to be reconciled", } - isInitialized = true } - if !isInitialized { - logger.Failuref("%s is not ready", source.GetName()) + if allNamespaces { + row = append([]string{source.Namespace}, row...) } + rows = append(rows, row) } + utils.printTable(os.Stdout, header, rows) return nil } diff --git a/cmd/gotk/get_source_git.go b/cmd/gotk/get_source_git.go index 4b981f09..3addb4d1 100644 --- a/cmd/gotk/get_source_git.go +++ b/cmd/gotk/get_source_git.go @@ -18,6 +18,8 @@ package main import ( "context" + "os" + "github.com/fluxcd/pkg/apis/meta" sourcev1 "github.com/fluxcd/source-controller/api/v1beta1" @@ -49,36 +51,48 @@ func getSourceGitCmdRun(cmd *cobra.Command, args []string) error { return err } + var listOpts []client.ListOption + if !allNamespaces { + listOpts = append(listOpts, client.InNamespace(namespace)) + } var list sourcev1.GitRepositoryList - err = kubeClient.List(ctx, &list, client.InNamespace(namespace)) + err = kubeClient.List(ctx, &list, listOpts...) if err != nil { return err } if len(list.Items) == 0 { - logger.Failuref("no sources found in %s namespace", namespace) + logger.Failuref("no git sources found in %s namespace", namespace) return nil } - // TODO(hidde): this should print a table, and should produce better output - // for items that have an artifact attached while they are in a reconciling - // 'Unknown' state. + header := []string{"Name", "Revision", "Ready", "Message"} + if allNamespaces { + header = append([]string{"Namespace"}, header...) + } + var rows [][]string for _, source := range list.Items { - isInitialized := false + row := []string{} if c := meta.GetCondition(source.Status.Conditions, meta.ReadyCondition); c != nil { - switch c.Status { - case corev1.ConditionTrue: - logger.Successf("%s last fetched revision: %s", source.GetName(), source.GetArtifact().Revision) - case corev1.ConditionUnknown: - logger.Successf("%s reconciling", source.GetName()) - default: - logger.Failuref("%s %s", source.GetName(), c.Message) + row = []string{ + source.GetName(), + "unknown", + string(c.Status), + c.Message, + } + } else { + row = []string{ + source.GetName(), + source.GetArtifact().Revision, + string(corev1.ConditionFalse), + "waiting to be reconciled", } - isInitialized = true } - if !isInitialized { - logger.Failuref("%s is not ready", source.GetName()) + if allNamespaces { + row = append([]string{source.Namespace}, row...) } + rows = append(rows, row) } + utils.printTable(os.Stdout, header, rows) return nil } diff --git a/cmd/gotk/get_source_helm.go b/cmd/gotk/get_source_helm.go index f2fcba33..7401263b 100644 --- a/cmd/gotk/get_source_helm.go +++ b/cmd/gotk/get_source_helm.go @@ -18,6 +18,8 @@ package main import ( "context" + "os" + "github.com/fluxcd/pkg/apis/meta" sourcev1 "github.com/fluxcd/source-controller/api/v1beta1" @@ -49,36 +51,48 @@ func getSourceHelmCmdRun(cmd *cobra.Command, args []string) error { return err } + var listOpts []client.ListOption + if !allNamespaces { + listOpts = append(listOpts, client.InNamespace(namespace)) + } var list sourcev1.HelmRepositoryList - err = kubeClient.List(ctx, &list, client.InNamespace(namespace)) + err = kubeClient.List(ctx, &list, listOpts...) if err != nil { return err } if len(list.Items) == 0 { - logger.Failuref("no sources found in %s namespace", namespace) + logger.Failuref("no helm sources found in %s namespace", namespace) return nil } - // TODO(hidde): this should print a table, and should produce better output - // for items that have an artifact attached while they are in a reconciling - // 'Unknown' state. + header := []string{"Name", "Revision", "Ready", "Message"} + if allNamespaces { + header = append([]string{"Namespace"}, header...) + } + var rows [][]string for _, source := range list.Items { - isInitialized := false + row := []string{} if c := meta.GetCondition(source.Status.Conditions, meta.ReadyCondition); c != nil { - switch c.Status { - case corev1.ConditionTrue: - logger.Successf("%s last fetched revision: %s", source.GetName(), source.GetArtifact().Revision) - case corev1.ConditionUnknown: - logger.Successf("%s reconciling", source.GetName()) - default: - logger.Failuref("%s %s", source.GetName(), c.Message) + row = []string{ + source.GetName(), + source.GetArtifact().Revision, + string(c.Status), + c.Message, + } + } else { + row = []string{ + source.GetName(), + source.GetArtifact().Revision, + string(corev1.ConditionFalse), + "waiting to be reconciled", } - isInitialized = true } - if !isInitialized { - logger.Failuref("%s is not ready", source.GetName()) + if allNamespaces { + row = append([]string{source.Namespace}, row...) } + rows = append(rows, row) } + utils.printTable(os.Stdout, header, rows) return nil } diff --git a/cmd/gotk/utils.go b/cmd/gotk/utils.go index e6a2ef2f..cc770073 100644 --- a/cmd/gotk/utils.go +++ b/cmd/gotk/utils.go @@ -44,6 +44,7 @@ import ( kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1beta1" "github.com/fluxcd/pkg/runtime/dependency" sourcev1 "github.com/fluxcd/source-controller/api/v1beta1" + "github.com/olekukonko/tablewriter" ) type Utils struct { @@ -297,3 +298,21 @@ func (*Utils) generateKustomizationYaml(dirPath string) error { } return nil } + +func (*Utils) printTable(writer io.Writer, header []string, rows [][]string) { + table := tablewriter.NewWriter(writer) + table.SetHeader(header) + table.SetAutoWrapText(false) + table.SetAutoFormatHeaders(true) + table.SetHeaderAlignment(tablewriter.ALIGN_LEFT) + table.SetAlignment(tablewriter.ALIGN_LEFT) + table.SetCenterSeparator("") + table.SetColumnSeparator("") + table.SetRowSeparator("") + table.SetHeaderLine(false) + table.SetBorder(false) + table.SetTablePadding("\t") + table.SetNoWhiteSpace(true) + table.AppendBulk(rows) + table.Render() +} diff --git a/docs/cmd/gotk_get.md b/docs/cmd/gotk_get.md index 96ad2b70..22163ae1 100644 --- a/docs/cmd/gotk_get.md +++ b/docs/cmd/gotk_get.md @@ -9,7 +9,8 @@ The get sub-commands print the statuses of sources and resources. ### Options ``` - -h, --help help for get + -A, --all-namespaces list the requested object(s) across all namespaces + -h, --help help for get ``` ### Options inherited from parent commands diff --git a/docs/cmd/gotk_get_helmreleases.md b/docs/cmd/gotk_get_helmreleases.md index 09edcbd5..b61d19bc 100644 --- a/docs/cmd/gotk_get_helmreleases.md +++ b/docs/cmd/gotk_get_helmreleases.md @@ -27,6 +27,7 @@ gotk get helmreleases [flags] ### Options inherited from parent commands ``` + -A, --all-namespaces list the requested object(s) across all namespaces --kubeconfig string path to the kubeconfig file (default "~/.kube/config") -n, --namespace string the namespace scope for this operation (default "gotk-system") --timeout duration timeout for this operation (default 5m0s) diff --git a/docs/cmd/gotk_get_kustomizations.md b/docs/cmd/gotk_get_kustomizations.md index d90846c7..a8128f81 100644 --- a/docs/cmd/gotk_get_kustomizations.md +++ b/docs/cmd/gotk_get_kustomizations.md @@ -27,6 +27,7 @@ gotk get kustomizations [flags] ### Options inherited from parent commands ``` + -A, --all-namespaces list the requested object(s) across all namespaces --kubeconfig string path to the kubeconfig file (default "~/.kube/config") -n, --namespace string the namespace scope for this operation (default "gotk-system") --timeout duration timeout for this operation (default 5m0s) diff --git a/docs/cmd/gotk_get_sources.md b/docs/cmd/gotk_get_sources.md index 3e649901..5b8881db 100644 --- a/docs/cmd/gotk_get_sources.md +++ b/docs/cmd/gotk_get_sources.md @@ -15,6 +15,7 @@ The get source sub-commands print the statuses of the sources. ### Options inherited from parent commands ``` + -A, --all-namespaces list the requested object(s) across all namespaces --kubeconfig string path to the kubeconfig file (default "~/.kube/config") -n, --namespace string the namespace scope for this operation (default "gotk-system") --timeout duration timeout for this operation (default 5m0s) diff --git a/docs/cmd/gotk_get_sources_bucket.md b/docs/cmd/gotk_get_sources_bucket.md index ab0ab9bc..6f08b235 100644 --- a/docs/cmd/gotk_get_sources_bucket.md +++ b/docs/cmd/gotk_get_sources_bucket.md @@ -27,6 +27,7 @@ gotk get sources bucket [flags] ### Options inherited from parent commands ``` + -A, --all-namespaces list the requested object(s) across all namespaces --kubeconfig string path to the kubeconfig file (default "~/.kube/config") -n, --namespace string the namespace scope for this operation (default "gotk-system") --timeout duration timeout for this operation (default 5m0s) diff --git a/docs/cmd/gotk_get_sources_git.md b/docs/cmd/gotk_get_sources_git.md index e6e51cb1..7ec32b6c 100644 --- a/docs/cmd/gotk_get_sources_git.md +++ b/docs/cmd/gotk_get_sources_git.md @@ -27,6 +27,7 @@ gotk get sources git [flags] ### Options inherited from parent commands ``` + -A, --all-namespaces list the requested object(s) across all namespaces --kubeconfig string path to the kubeconfig file (default "~/.kube/config") -n, --namespace string the namespace scope for this operation (default "gotk-system") --timeout duration timeout for this operation (default 5m0s) diff --git a/docs/cmd/gotk_get_sources_helm.md b/docs/cmd/gotk_get_sources_helm.md index 54de0b4f..9f2bc452 100644 --- a/docs/cmd/gotk_get_sources_helm.md +++ b/docs/cmd/gotk_get_sources_helm.md @@ -27,6 +27,7 @@ gotk get sources helm [flags] ### Options inherited from parent commands ``` + -A, --all-namespaces list the requested object(s) across all namespaces --kubeconfig string path to the kubeconfig file (default "~/.kube/config") -n, --namespace string the namespace scope for this operation (default "gotk-system") --timeout duration timeout for this operation (default 5m0s) diff --git a/go.mod b/go.mod index 2bf0ceb9..0a2595cf 100644 --- a/go.mod +++ b/go.mod @@ -14,6 +14,7 @@ require ( github.com/fluxcd/pkg/untar v0.0.5 github.com/fluxcd/source-controller/api v0.1.0 github.com/manifoldco/promptui v0.7.0 + github.com/olekukonko/tablewriter v0.0.4 github.com/spf13/cobra v1.0.0 golang.org/x/net v0.0.0-20200602114024-627f9648deb9 // indirect golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d // indirect diff --git a/go.sum b/go.sum index c4ad1f95..d8c629bb 100644 --- a/go.sum +++ b/go.sum @@ -377,6 +377,8 @@ github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNx github.com/mattn/go-isatty v0.0.8 h1:HLtExJ+uU2HOZ+wI0Tt5DtUDrx8yhUqDcp7fYERX4CE= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= +github.com/mattn/go-runewidth v0.0.7 h1:Ei8KR0497xHyKJPAv59M1dkC+rOZCMBJ+t3fZ+twI54= +github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/goveralls v0.0.2/go.mod h1:8d1ZMHsd7fW6IRPKQh46F2WRpyib5/X4FOpevwGNQEw= github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= @@ -409,6 +411,8 @@ github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= +github.com/olekukonko/tablewriter v0.0.4 h1:vHD/YYe1Wolo78koG299f7V/VAS08c6IpCLn+Ejf/w8= +github.com/olekukonko/tablewriter v0.0.4/go.mod h1:zq6QwlOf5SlnkVbMSr5EoBv3636FWnp+qbPhuoO21uA= github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=