From 8f6903acfbf62c6dbaed09fff016b3b36ca73bed Mon Sep 17 00:00:00 2001 From: juliogreff Date: Fri, 4 Oct 2019 10:38:27 +0200 Subject: [PATCH 1/7] Makefile: also take into account subdirs as requirements Without this, `make build/shipperctl.darwin-amd64` wouldn't rebuild shipperctl even if files in `cmd/shipperctl/cmd/` changed. --- Makefile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index fcd598a92..ff260cc15 100644 --- a/Makefile +++ b/Makefile @@ -168,13 +168,13 @@ build-all: $(foreach os,$(OS),build/shipperctl.$(os)-amd64.tar.gz) build/sha256s build: mkdir -p build -build/shipper-state-metrics.%-amd64: cmd/shipper-state-metrics/*.go $(PKG) +build/shipper-state-metrics.%-amd64: $(PKG) cmd/shipper-state-metrics/* GOOS=$* GOARCH=amd64 go build $(LDFLAGS) -o build/shipper-state-metrics.$*-amd64 cmd/shipper-state-metrics/*.go -build/shipper.%-amd64: cmd/shipper/*.go $(PKG) +build/shipper.%-amd64: $(PKG) cmd/shipper/* GOOS=$* GOARCH=amd64 go build $(LDFLAGS) -o build/shipper.$*-amd64 cmd/shipper/*.go -build/shipperctl.%-amd64: cmd/shipperctl/*.go $(PKG) +build/shipperctl.%-amd64: $(PKG) cmd/shipperctl/**/* GOOS=$* GOARCH=amd64 go build $(LDFLAGS) -o build/shipperctl.$*-amd64 cmd/shipperctl/*.go build/e2e.test: $(PKG) test/e2e/* From fe8f0ff278b3d9d9feb7fc87d26173e3927c0759 Mon Sep 17 00:00:00 2001 From: hihilla Date: Wed, 25 Nov 2020 11:19:16 +0100 Subject: [PATCH 2/7] shipperctl: move commands to their own packages --- cmd/shipperctl/cmd/{ => clean}/decommission.go | 9 ++++++--- cmd/shipperctl/cmd/{ => clusters}/clusters.go | 2 +- cmd/shipperctl/cmd/{ => list}/list.go | 10 +++++++--- cmd/shipperctl/main.go | 10 ++++++---- 4 files changed, 20 insertions(+), 11 deletions(-) rename cmd/shipperctl/cmd/{ => clean}/decommission.go (97%) rename cmd/shipperctl/cmd/{ => clusters}/clusters.go (99%) rename cmd/shipperctl/cmd/{ => list}/list.go (96%) diff --git a/cmd/shipperctl/cmd/decommission.go b/cmd/shipperctl/cmd/clean/decommission.go similarity index 97% rename from cmd/shipperctl/cmd/decommission.go rename to cmd/shipperctl/cmd/clean/decommission.go index dc88d58ab..c8cd1a9aa 100644 --- a/cmd/shipperctl/cmd/decommission.go +++ b/cmd/shipperctl/cmd/clean/decommission.go @@ -1,4 +1,4 @@ -package cmd +package clean import ( "fmt" @@ -20,11 +20,14 @@ import ( const ( decommissionedClustersFlagName = "decommissionedClusters" + kubeConfigFlagName = "kubeconfig" ) var ( - clusters []string - dryrun bool + clusters []string + dryrun bool + kubeConfigFile string + managementClusterContext string CleanCmd = &cobra.Command{ Use: "clean", diff --git a/cmd/shipperctl/cmd/clusters.go b/cmd/shipperctl/cmd/clusters/clusters.go similarity index 99% rename from cmd/shipperctl/cmd/clusters.go rename to cmd/shipperctl/cmd/clusters/clusters.go index 928b0ee8e..cbf44e9ac 100644 --- a/cmd/shipperctl/cmd/clusters.go +++ b/cmd/shipperctl/cmd/clusters/clusters.go @@ -1,4 +1,4 @@ -package cmd +package clusters import ( "crypto/rand" diff --git a/cmd/shipperctl/cmd/list.go b/cmd/shipperctl/cmd/list/list.go similarity index 96% rename from cmd/shipperctl/cmd/list.go rename to cmd/shipperctl/cmd/list/list.go index 45501de2d..18eb14650 100644 --- a/cmd/shipperctl/cmd/list.go +++ b/cmd/shipperctl/cmd/list/list.go @@ -1,4 +1,4 @@ -package cmd +package list import ( "bytes" @@ -19,11 +19,15 @@ import ( ) const ( - clustersFlagName = "clusters" + clustersFlagName = "clusters" + kubeConfigFlagName = "kubeconfig" ) var ( - printOption string + clusters []string + printOption string + kubeConfigFile string + managementClusterContext string ListCmd = &cobra.Command{ Use: "list", diff --git a/cmd/shipperctl/main.go b/cmd/shipperctl/main.go index 0e59ff78c..5ba01232f 100644 --- a/cmd/shipperctl/main.go +++ b/cmd/shipperctl/main.go @@ -3,9 +3,11 @@ package main import ( "flag" "fmt" + "github.com/bookingcom/shipper/cmd/shipperctl/cmd/clean" + "github.com/bookingcom/shipper/cmd/shipperctl/cmd/clusters" + "github.com/bookingcom/shipper/cmd/shipperctl/cmd/list" "os" - "github.com/bookingcom/shipper/cmd/shipperctl/cmd" "github.com/bookingcom/shipper/cmd/shipperctl/cmd/backup" "github.com/spf13/cobra" ) @@ -18,9 +20,9 @@ var rootCmd = &cobra.Command{ } func init() { - rootCmd.AddCommand(cmd.ClustersCmd) - rootCmd.AddCommand(cmd.ListCmd) - rootCmd.AddCommand(cmd.CleanCmd) + rootCmd.AddCommand(clusters.ClustersCmd) + rootCmd.AddCommand(list.ListCmd) + rootCmd.AddCommand(clean.CleanCmd) rootCmd.AddCommand(backup.BackupCmd) } From f1c2f7115ce0ad38121bdb4cb2a48c486f7499ee Mon Sep 17 00:00:00 2001 From: hihilla Date: Wed, 25 Nov 2020 11:32:44 +0100 Subject: [PATCH 3/7] shipperctl: move kubeconfig functions to their own package --- cmd/shipperctl/cmd/backup/backup.go | 3 ++- cmd/shipperctl/cmd/backup/prepare.go | 9 ++------ cmd/shipperctl/cmd/backup/restore.go | 9 ++------ cmd/shipperctl/cmd/clean/decommission.go | 11 +++------- cmd/shipperctl/cmd/clusters/clusters.go | 2 +- cmd/shipperctl/cmd/list/list.go | 18 ++++------------ cmd/shipperctl/config/kubeconfig.go | 27 ++++++++++++++++++++++++ go.mod | 1 + 8 files changed, 42 insertions(+), 38 deletions(-) create mode 100644 cmd/shipperctl/config/kubeconfig.go diff --git a/cmd/shipperctl/cmd/backup/backup.go b/cmd/shipperctl/cmd/backup/backup.go index 399a41f0a..dc53875a6 100644 --- a/cmd/shipperctl/cmd/backup/backup.go +++ b/cmd/shipperctl/cmd/backup/backup.go @@ -8,6 +8,7 @@ import ( "github.com/spf13/cobra" "sigs.k8s.io/yaml" + "github.com/bookingcom/shipper/cmd/shipperctl/config" shipper "github.com/bookingcom/shipper/pkg/apis/shipper/v1alpha1" ) @@ -48,7 +49,7 @@ func init() { kubeConfigFlagName := "kubeconfig" fileFlagName := "file" - BackupCmd.PersistentFlags().StringVar(&kubeConfigFile, kubeConfigFlagName, "~/.kube/config", "The path to the Kubernetes configuration file") + config.RegisterFlag(BackupCmd.PersistentFlags(), &kubeConfigFile) if err := BackupCmd.MarkPersistentFlagFilename(kubeConfigFlagName, "yaml"); err != nil { BackupCmd.Printf("warning: could not mark %q for filename autocompletion: %s\n", kubeConfigFlagName, err) } diff --git a/cmd/shipperctl/cmd/backup/prepare.go b/cmd/shipperctl/cmd/backup/prepare.go index 0a8454da8..ba70a608a 100644 --- a/cmd/shipperctl/cmd/backup/prepare.go +++ b/cmd/shipperctl/cmd/backup/prepare.go @@ -9,7 +9,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/kubernetes" - "github.com/bookingcom/shipper/cmd/shipperctl/configurator" + "github.com/bookingcom/shipper/cmd/shipperctl/config" "github.com/bookingcom/shipper/cmd/shipperctl/release" "github.com/bookingcom/shipper/cmd/shipperctl/ui" shipperclientset "github.com/bookingcom/shipper/pkg/client/clientset/versioned" @@ -30,12 +30,7 @@ func init() { } func runPrepareCommand(cmd *cobra.Command, args []string) error { - kubeClient, err := configurator.NewKubeClientFromKubeConfig(kubeConfigFile, managementClusterContext) - if err != nil { - return err - } - - shipperClient, err := configurator.NewShipperClientFromKubeConfig(kubeConfigFile, managementClusterContext) + kubeClient, shipperClient, err := config.Load(kubeConfigFile, managementClusterContext) if err != nil { return err } diff --git a/cmd/shipperctl/cmd/backup/restore.go b/cmd/shipperctl/cmd/backup/restore.go index d117f1abc..21ee03edf 100644 --- a/cmd/shipperctl/cmd/backup/restore.go +++ b/cmd/shipperctl/cmd/backup/restore.go @@ -15,7 +15,7 @@ import ( "k8s.io/client-go/tools/cache" "sigs.k8s.io/yaml" - "github.com/bookingcom/shipper/cmd/shipperctl/configurator" + "github.com/bookingcom/shipper/cmd/shipperctl/config" "github.com/bookingcom/shipper/cmd/shipperctl/ui" shipper "github.com/bookingcom/shipper/pkg/apis/shipper/v1alpha1" shipperclientset "github.com/bookingcom/shipper/pkg/client/clientset/versioned" @@ -39,12 +39,7 @@ func init() { } func runRestoreCommand(cmd *cobra.Command, args []string) error { - kubeClient, err := configurator.NewKubeClientFromKubeConfig(kubeConfigFile, managementClusterContext) - if err != nil { - return err - } - - shipperClient, err := configurator.NewShipperClientFromKubeConfig(kubeConfigFile, managementClusterContext) + kubeClient, shipperClient, err := config.Load(kubeConfigFile, managementClusterContext) if err != nil { return err } diff --git a/cmd/shipperctl/cmd/clean/decommission.go b/cmd/shipperctl/cmd/clean/decommission.go index c8cd1a9aa..98a5c23ac 100644 --- a/cmd/shipperctl/cmd/clean/decommission.go +++ b/cmd/shipperctl/cmd/clean/decommission.go @@ -11,7 +11,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/kubernetes" - "github.com/bookingcom/shipper/cmd/shipperctl/configurator" + "github.com/bookingcom/shipper/cmd/shipperctl/config" "github.com/bookingcom/shipper/cmd/shipperctl/release" "github.com/bookingcom/shipper/cmd/shipperctl/ui" shipper "github.com/bookingcom/shipper/pkg/apis/shipper/v1alpha1" @@ -52,7 +52,7 @@ type releaseAndFilteredAnnotations struct { func init() { // Flags common to all commands under `shipperctl clean` - CleanCmd.PersistentFlags().StringVar(&kubeConfigFile, kubeConfigFlagName, "~/.kube/config", "The path to the Kubernetes configuration file") + config.RegisterFlag(CleanCmd.PersistentFlags(), &kubeConfigFile) if err := CleanCmd.MarkPersistentFlagFilename(kubeConfigFlagName, "yaml"); err != nil { CleanCmd.Printf("warning: could not mark %q for filename autocompletion: %s\n", kubeConfigFlagName, err) } @@ -68,12 +68,7 @@ func init() { } func runCleanCommand(cmd *cobra.Command, args []string) error { - kubeClient, err := configurator.NewKubeClientFromKubeConfig(kubeConfigFile, managementClusterContext) - if err != nil { - return err - } - - shipperClient, err := configurator.NewShipperClientFromKubeConfig(kubeConfigFile, managementClusterContext) + kubeClient, shipperClient, err := config.Load(kubeConfigFile, managementClusterContext) if err != nil { return err } diff --git a/cmd/shipperctl/cmd/clusters/clusters.go b/cmd/shipperctl/cmd/clusters/clusters.go index cbf44e9ac..b160037b2 100644 --- a/cmd/shipperctl/cmd/clusters/clusters.go +++ b/cmd/shipperctl/cmd/clusters/clusters.go @@ -74,7 +74,7 @@ const ( func init() { // Flags common to all commands under `shipperctl clusters` for _, cmd := range []*cobra.Command{joinCmd, setupMgmtCmd} { - cmd.Flags().StringVar(&kubeConfigFile, kubeConfigFlagName, "~/.kube/config", "the path to the Kubernetes configuration file") + config.RegisterFlag(cmd.Flags(), &kubeConfigFile) if err := cmd.MarkFlagFilename(kubeConfigFlagName, "yaml"); err != nil { cmd.Printf("warning: could not mark %q for filename autocompletion: %s\n", kubeConfigFlagName, err) } diff --git a/cmd/shipperctl/cmd/list/list.go b/cmd/shipperctl/cmd/list/list.go index 18eb14650..d6c29499d 100644 --- a/cmd/shipperctl/cmd/list/list.go +++ b/cmd/shipperctl/cmd/list/list.go @@ -13,7 +13,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "sigs.k8s.io/yaml" - "github.com/bookingcom/shipper/cmd/shipperctl/configurator" + "github.com/bookingcom/shipper/cmd/shipperctl/config" "github.com/bookingcom/shipper/cmd/shipperctl/release" shipper "github.com/bookingcom/shipper/pkg/apis/shipper/v1alpha1" ) @@ -64,7 +64,7 @@ type outputRelease struct { func init() { // Flags common to all commands under `shipperctl count` - ListCmd.PersistentFlags().StringVar(&kubeConfigFile, kubeConfigFlagName, "~/.kube/config", "The path to the Kubernetes configuration file") + config.RegisterFlag(ListCmd.PersistentFlags(), &kubeConfigFile) if err := ListCmd.MarkPersistentFlagFilename(kubeConfigFlagName, "yaml"); err != nil { ListCmd.Printf("warning: could not mark %q for filename autocompletion: %s\n", kubeConfigFlagName, err) } @@ -82,12 +82,7 @@ func init() { func runCountContenderCommand(cmd *cobra.Command, args []string) error { counter := 0 - kubeClient, err := configurator.NewKubeClientFromKubeConfig(kubeConfigFile, managementClusterContext) - if err != nil { - return err - } - - shipperClient, err := configurator.NewShipperClientFromKubeConfig(kubeConfigFile, managementClusterContext) + kubeClient, shipperClient, err := config.Load(kubeConfigFile, managementClusterContext) if err != nil { return err } @@ -136,12 +131,7 @@ func runCountContenderCommand(cmd *cobra.Command, args []string) error { func runCountReleasesCommand(cmd *cobra.Command, args []string) error { counter := 0 - kubeClient, err := configurator.NewKubeClientFromKubeConfig(kubeConfigFile, managementClusterContext) - if err != nil { - return err - } - - shipperClient, err := configurator.NewShipperClientFromKubeConfig(kubeConfigFile, managementClusterContext) + kubeClient, shipperClient, err := config.Load(kubeConfigFile, managementClusterContext) if err != nil { return err } diff --git a/cmd/shipperctl/config/kubeconfig.go b/cmd/shipperctl/config/kubeconfig.go new file mode 100644 index 000000000..9038df216 --- /dev/null +++ b/cmd/shipperctl/config/kubeconfig.go @@ -0,0 +1,27 @@ +package config + +import ( + "github.com/spf13/pflag" + + "k8s.io/client-go/kubernetes" + + "github.com/bookingcom/shipper/cmd/shipperctl/configurator" + shipperclientset "github.com/bookingcom/shipper/pkg/client/clientset/versioned" +) + +func RegisterFlag(flags *pflag.FlagSet, kubeConfigFile *string) { + flags.StringVar(kubeConfigFile, "kubeconfig", "~/.kube/config", "the path to the Kubernetes configuration file") +} + +func Load(kubeConfigFile, managementClusterContext string) (kubernetes.Interface, shipperclientset.Interface, error) { + kubeClient, err := configurator.NewKubeClientFromKubeConfig(kubeConfigFile, managementClusterContext) + if err != nil { + return nil, nil, err + } + + shipperClient, err := configurator.NewShipperClientFromKubeConfig(kubeConfigFile, managementClusterContext) + if err != nil { + return nil, nil, err + } + return kubeClient, shipperClient, nil +} diff --git a/go.mod b/go.mod index b5349ace0..3bba64fb9 100644 --- a/go.mod +++ b/go.mod @@ -20,6 +20,7 @@ require ( github.com/satori/go.uuid v1.2.0 // indirect github.com/spaolacci/murmur3 v1.1.0 // indirect github.com/spf13/cobra v1.0.0 + github.com/spf13/pflag v1.0.5 k8s.io/api v0.17.12 k8s.io/apiextensions-apiserver v0.17.12 k8s.io/apimachinery v0.17.12 From 7cc40eea631f96f9645f14c04126f5a031c556d3 Mon Sep 17 00:00:00 2001 From: hihilla Date: Wed, 25 Nov 2020 12:21:17 +0100 Subject: [PATCH 4/7] shipperctl: introduce `shipperctl chart render` It's useful to know what kind of objects shipper is rendering before they reach the api server. For debugging issues with YAML serializing/deserializing, for instance. For that, you can now run `shipperctl chart render --app foobar` or `shipperctl chart render --relelase foobar-deadbeef-0`, and shipperctl will print a whole bundle of YAML to stdout, with each object separated by a `---`. This is currently only useful for applications that already exist, as you can't manually pass standalone chart spec or values. We'll eventually support that once we figure out a non-awkard interface for doing that. from commit 96980a3740f268148d58bbb05c60172a3e76ad62 by Julio Greff --- cmd/shipperctl/cmd/chart/render.go | 141 +++++++++++++++++++++++++ cmd/shipperctl/configurator/cluster.go | 15 ++- 2 files changed, 153 insertions(+), 3 deletions(-) create mode 100644 cmd/shipperctl/cmd/chart/render.go diff --git a/cmd/shipperctl/cmd/chart/render.go b/cmd/shipperctl/cmd/chart/render.go new file mode 100644 index 000000000..971881b1e --- /dev/null +++ b/cmd/shipperctl/cmd/chart/render.go @@ -0,0 +1,141 @@ +package chart + +import ( + "fmt" + "os" + "path/filepath" + + "github.com/spf13/cobra" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + "github.com/bookingcom/shipper/cmd/shipperctl/config" + "github.com/bookingcom/shipper/cmd/shipperctl/configurator" + shipper "github.com/bookingcom/shipper/pkg/apis/shipper/v1alpha1" + shipperchart "github.com/bookingcom/shipper/pkg/chart" + "github.com/bookingcom/shipper/pkg/chart/repo" +) + +var ( + namespace string + appName string + releaseName string + kubeConfigFile string + managementClusterContext string + + Command = &cobra.Command{ + Use: "chart", + Short: "operate on Shipper Charts", + } + + renderCmd = &cobra.Command{ + Use: "render --app bikerental", + Short: "render Shipper Charts for an Application or Release", + RunE: renderChart, + } +) + +type ChartRenderConfig struct { + ChartSpec shipper.Chart + ChartValues *shipper.ChartValues + Namespace string + ReleaseName string +} + +func init() { + const kubeConfigFlagName = "kubeconfig" + config.RegisterFlag(Command.PersistentFlags(), &kubeConfigFile) + if err := Command.MarkPersistentFlagFilename(kubeConfigFlagName, "yaml"); err != nil { + Command.Printf("warning: could not mark %q for filename autocompletion: %s\n", kubeConfigFlagName, err) + } + Command.PersistentFlags().StringVar(&managementClusterContext, "management-cluster-context", "", "The name of the context to use to communicate with the management cluster. defaults to the current one") + Command.PersistentFlags().StringVarP(&namespace, "namespace", "n", "", "namespace where the app lives") + Command.PersistentFlags().StringVar(&appName, "app", "", "application that will have its chart rendered") + Command.PersistentFlags().StringVar(&releaseName, "release", "", "release that will have its chart rendered") + + Command.AddCommand(renderCmd) +} + +func renderChart(cmd *cobra.Command, args []string) error { + c, err := newChartRenderConfig() + if err != nil { + return err + } + + chartFetcher := newFetchChartFunc() + chart, err := chartFetcher(&c.ChartSpec) + if err != nil { + return err + } + + rendered, err := shipperchart.Render( + chart, + c.ReleaseName, + c.Namespace, + c.ChartValues, + ) + if err != nil { + return err + } + + for _, v := range rendered { + fmt.Printf("%s\n---\n", v) + } + + return nil +} + +func newChartRenderConfig() (ChartRenderConfig, error) { + c := ChartRenderConfig{ + } + clientConfig, _, err := configurator.ClientConfig(kubeConfigFile, managementClusterContext) + if err != nil { + return c, err + } + if namespace == "" { + namespace, _, err = clientConfig.Namespace() + if err != nil { + return c, err + } + } + c.Namespace = namespace + + _, shipperClient, err := config.Load(kubeConfigFile, managementClusterContext) + if err != nil { + return c, err + } + + getoptions := metav1.GetOptions{} + + if releaseName != "" { + rel, err := shipperClient.ShipperV1alpha1().Releases(namespace).Get(releaseName, getoptions) + if err != nil { + return c, err + } + + c.ReleaseName = releaseName + c.ChartSpec = rel.Spec.Environment.Chart + c.ChartValues = rel.Spec.Environment.Values + } else if appName != "" { + app, err := shipperClient.ShipperV1alpha1().Applications(namespace).Get(appName, getoptions) + if err != nil { + return c, err + } + + c.ReleaseName = fmt.Sprintf("%s-%s-%d", appName, "foobar", 0) + c.ChartSpec = app.Spec.Template.Chart + c.ChartValues = app.Spec.Template.Values + } + + return c, nil +} + +func newFetchChartFunc() repo.ChartFetcher { + stopCh := make(<-chan struct{}) + + repoCatalog := repo.NewCatalog( + repo.DefaultFileCacheFactory(filepath.Join(os.TempDir(), "chart-cache")), + repo.DefaultRemoteFetcher, + stopCh) + + return repo.FetchChartFunc(repoCatalog) +} diff --git a/cmd/shipperctl/configurator/cluster.go b/cmd/shipperctl/configurator/cluster.go index c70be933b..d50ae7e08 100644 --- a/cmd/shipperctl/configurator/cluster.go +++ b/cmd/shipperctl/configurator/cluster.go @@ -508,9 +508,17 @@ func (c *Cluster) CreateOrUpdateValidatingWebhookService(namespace string) error } func loadKubeConfig(kubeConfig, context string) (*rest.Config, error) { + clientConfig, config, err := ClientConfig(kubeConfig, context) + if err != nil { + return config, err + } + return clientConfig.ClientConfig() +} + +func ClientConfig(kubeConfig string, context string) (clientcmd.ClientConfig, *rest.Config, error) { path, err := homedir.Expand(kubeConfig) if err != nil { - return nil, err + return nil, nil, err } overrides := &clientcmd.ConfigOverrides{CurrentContext: context} @@ -518,8 +526,9 @@ func loadKubeConfig(kubeConfig, context string) (*rest.Config, error) { overrides.CurrentContext = context } - return clientcmd.NewNonInteractiveDeferredLoadingClientConfig( + clientConfig := clientcmd.NewNonInteractiveDeferredLoadingClientConfig( &clientcmd.ClientConfigLoadingRules{ExplicitPath: path}, overrides, - ).ClientConfig() + ) + return clientConfig, nil, nil } From 23ff16d11a43673834dceacaa933d68dd65fec4a Mon Sep 17 00:00:00 2001 From: hihilla Date: Thu, 26 Nov 2020 17:42:32 +0100 Subject: [PATCH 5/7] separate rendering chart of release and application to different command --- cmd/shipperctl/cmd/chart/app.go | 88 +++++++++++++++++++++++++ cmd/shipperctl/cmd/chart/release.go | 51 ++++++++++++++ cmd/shipperctl/cmd/chart/render.go | 64 ++++-------------- cmd/shipperctl/cmd/chart/render_test.go | 1 + cmd/shipperctl/main.go | 2 + 5 files changed, 153 insertions(+), 53 deletions(-) create mode 100644 cmd/shipperctl/cmd/chart/app.go create mode 100644 cmd/shipperctl/cmd/chart/release.go create mode 100644 cmd/shipperctl/cmd/chart/render_test.go diff --git a/cmd/shipperctl/cmd/chart/app.go b/cmd/shipperctl/cmd/chart/app.go new file mode 100644 index 000000000..65b5a0c0d --- /dev/null +++ b/cmd/shipperctl/cmd/chart/app.go @@ -0,0 +1,88 @@ +package chart + +import ( + "fmt" + "io/ioutil" + "os" + + "github.com/spf13/cobra" + "sigs.k8s.io/yaml" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + "github.com/bookingcom/shipper/cmd/shipperctl/config" + shipper "github.com/bookingcom/shipper/pkg/apis/shipper/v1alpha1" +) + +var ( + appName string + fileName string + + renderAppCmd = &cobra.Command{ + Use: "app", + Short: "render Shipper Charts for an Application", + RunE: renderChartFromApp, + PersistentPreRun: func(cmd *cobra.Command, args []string) { + if appName == "" && fileName == "" { + cmd.Printf("error: must have *one* of the flags: appName, filename\n") + os.Exit(1) + } + if appName != "" && fileName != "" { + cmd.Printf("error: must have *one* of the flags: appName, filename\n") + os.Exit(1) + } + }, + } +) + +func init() { + fileFlagName := "filename" + + renderAppCmd.Flags().StringVar(&appName, "appName", "", "The name of an existing application to render chart for") + renderAppCmd.Flags().StringVar(&fileName, fileFlagName, "", "An application manifest in the current context to render chart for (e.g. `applicastion.yaml`)") + err := renderAppCmd.MarkFlagFilename(fileFlagName, "yaml") + if err != nil { + renderAppCmd.Printf("warning: could not mark %q for filename yaml autocompletion: %s\n", fileFlagName, err) + } + + renderCmd.AddCommand(renderAppCmd) +} + +func renderChartFromApp(cmd *cobra.Command, args []string) error { + c, err := newChartRenderConfig() + if err != nil { + return err + } + _, shipperClient, err := config.Load(kubeConfigFile, managementClusterContext) + if err != nil { + return err + } + var application shipper.Application + if appName != "" { + applicationP, err := shipperClient.ShipperV1alpha1().Applications(namespace).Get(appName, metav1.GetOptions{}) + if err != nil { + return err + } + application = *applicationP + } else { + appYaml, err := ioutil.ReadFile(fileName) + if err != nil { + return err + } + + if err := yaml.Unmarshal(appYaml, &application); err != nil { + return err + } + + } + + c.ReleaseName = fmt.Sprintf("%s-%s-%d", application.Name, "foobar", 0) + c.ChartSpec = application.Spec.Template.Chart + c.ChartValues = application.Spec.Template.Values + rendered, err := render(c) + if err != nil { + return err + } + + cmd.Println(rendered) + return nil +} diff --git a/cmd/shipperctl/cmd/chart/release.go b/cmd/shipperctl/cmd/chart/release.go new file mode 100644 index 000000000..f90d7d434 --- /dev/null +++ b/cmd/shipperctl/cmd/chart/release.go @@ -0,0 +1,51 @@ +package chart + +import ( + "github.com/spf13/cobra" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + "github.com/bookingcom/shipper/cmd/shipperctl/config" +) + +var ( + releaseName string + + renderRelCmd = &cobra.Command{ + Use: "release bikerental-7abf46d4-0", + Short: "render Shipper Charts for a Release", + RunE: renderChartFromRel, + Args: cobra.ExactArgs(1), + } +) + +func init() { + renderCmd.AddCommand(renderRelCmd) +} + +func renderChartFromRel(cmd *cobra.Command, args []string) error { + releaseName = args[0] + c, err := newChartRenderConfig() + if err != nil { + return err + } + _, shipperClient, err := config.Load(kubeConfigFile, managementClusterContext) + if err != nil { + return err + } + + rel, err := shipperClient.ShipperV1alpha1().Releases(namespace).Get(releaseName, metav1.GetOptions{}) + if err != nil { + return err + } + c.ReleaseName = rel.Name + c.ChartSpec = rel.Spec.Environment.Chart + c.ChartValues = rel.Spec.Environment.Values + + rendered, err := render(c) + if err != nil { + return err + } + + cmd.Println(rendered) + return nil +} diff --git a/cmd/shipperctl/cmd/chart/render.go b/cmd/shipperctl/cmd/chart/render.go index 971881b1e..15059069f 100644 --- a/cmd/shipperctl/cmd/chart/render.go +++ b/cmd/shipperctl/cmd/chart/render.go @@ -1,12 +1,11 @@ package chart import ( - "fmt" "os" "path/filepath" + "strings" "github.com/spf13/cobra" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "github.com/bookingcom/shipper/cmd/shipperctl/config" "github.com/bookingcom/shipper/cmd/shipperctl/configurator" @@ -17,8 +16,6 @@ import ( var ( namespace string - appName string - releaseName string kubeConfigFile string managementClusterContext string @@ -28,9 +25,8 @@ var ( } renderCmd = &cobra.Command{ - Use: "render --app bikerental", - Short: "render Shipper Charts for an Application or Release", - RunE: renderChart, + Use: "render", + Short: "render Helm Charts for an Application or Release", } ) @@ -48,23 +44,16 @@ func init() { Command.Printf("warning: could not mark %q for filename autocompletion: %s\n", kubeConfigFlagName, err) } Command.PersistentFlags().StringVar(&managementClusterContext, "management-cluster-context", "", "The name of the context to use to communicate with the management cluster. defaults to the current one") - Command.PersistentFlags().StringVarP(&namespace, "namespace", "n", "", "namespace where the app lives") - Command.PersistentFlags().StringVar(&appName, "app", "", "application that will have its chart rendered") - Command.PersistentFlags().StringVar(&releaseName, "release", "", "release that will have its chart rendered") + Command.PersistentFlags().StringVarP(&namespace, "namespace", "n", "", "The namespace where the app lives") Command.AddCommand(renderCmd) } -func renderChart(cmd *cobra.Command, args []string) error { - c, err := newChartRenderConfig() - if err != nil { - return err - } - +func render(c ChartRenderConfig) (string, error) { chartFetcher := newFetchChartFunc() chart, err := chartFetcher(&c.ChartSpec) if err != nil { - return err + return "", err } rendered, err := shipperchart.Render( @@ -74,57 +63,26 @@ func renderChart(cmd *cobra.Command, args []string) error { c.ChartValues, ) if err != nil { - return err + return "", err } - for _, v := range rendered { - fmt.Printf("%s\n---\n", v) - } - - return nil + return strings.Join(rendered, "%s\n---\n"), nil } func newChartRenderConfig() (ChartRenderConfig, error) { c := ChartRenderConfig{ } - clientConfig, _, err := configurator.ClientConfig(kubeConfigFile, managementClusterContext) - if err != nil { - return c, err - } if namespace == "" { - namespace, _, err = clientConfig.Namespace() - if err != nil { - return c, err - } - } - c.Namespace = namespace - - _, shipperClient, err := config.Load(kubeConfigFile, managementClusterContext) - if err != nil { - return c, err - } - - getoptions := metav1.GetOptions{} - - if releaseName != "" { - rel, err := shipperClient.ShipperV1alpha1().Releases(namespace).Get(releaseName, getoptions) + clientConfig, _, err := configurator.ClientConfig(kubeConfigFile, managementClusterContext) if err != nil { return c, err } - - c.ReleaseName = releaseName - c.ChartSpec = rel.Spec.Environment.Chart - c.ChartValues = rel.Spec.Environment.Values - } else if appName != "" { - app, err := shipperClient.ShipperV1alpha1().Applications(namespace).Get(appName, getoptions) + namespace, _, err = clientConfig.Namespace() if err != nil { return c, err } - - c.ReleaseName = fmt.Sprintf("%s-%s-%d", appName, "foobar", 0) - c.ChartSpec = app.Spec.Template.Chart - c.ChartValues = app.Spec.Template.Values } + c.Namespace = namespace return c, nil } diff --git a/cmd/shipperctl/cmd/chart/render_test.go b/cmd/shipperctl/cmd/chart/render_test.go new file mode 100644 index 000000000..58a733f99 --- /dev/null +++ b/cmd/shipperctl/cmd/chart/render_test.go @@ -0,0 +1 @@ +package chart diff --git a/cmd/shipperctl/main.go b/cmd/shipperctl/main.go index 5ba01232f..8e58f958b 100644 --- a/cmd/shipperctl/main.go +++ b/cmd/shipperctl/main.go @@ -3,6 +3,7 @@ package main import ( "flag" "fmt" + "github.com/bookingcom/shipper/cmd/shipperctl/cmd/chart" "github.com/bookingcom/shipper/cmd/shipperctl/cmd/clean" "github.com/bookingcom/shipper/cmd/shipperctl/cmd/clusters" "github.com/bookingcom/shipper/cmd/shipperctl/cmd/list" @@ -24,6 +25,7 @@ func init() { rootCmd.AddCommand(list.ListCmd) rootCmd.AddCommand(clean.CleanCmd) rootCmd.AddCommand(backup.BackupCmd) + rootCmd.AddCommand(chart.Command) } func main() { From 5ceac1b69d52dc5f7fe36e64e81322c8cd17bcfe Mon Sep 17 00:00:00 2001 From: hihilla Date: Wed, 20 Jan 2021 12:23:57 +0100 Subject: [PATCH 6/7] Adding tests --- cmd/shipperctl/cmd/chart/render_test.go | 83 +++++++++++++++++++++++++ 1 file changed, 83 insertions(+) diff --git a/cmd/shipperctl/cmd/chart/render_test.go b/cmd/shipperctl/cmd/chart/render_test.go index 58a733f99..e728e8b31 100644 --- a/cmd/shipperctl/cmd/chart/render_test.go +++ b/cmd/shipperctl/cmd/chart/render_test.go @@ -1 +1,84 @@ package chart + +import ( + "fmt" + "net/url" + "reflect" + "testing" + + shipper "github.com/bookingcom/shipper/pkg/apis/shipper/v1alpha1" + shippererrors "github.com/bookingcom/shipper/pkg/errors" + shippertesting "github.com/bookingcom/shipper/pkg/testing" +) + +func TestRender(t *testing.T) { + tests := []struct { + Name string + C ChartRenderConfig + ExpectedYaml string + ExpectedErr error + }{ + { + Name: "Working chart", + C: ChartRenderConfig{ + ChartSpec: shipper.Chart{ + Name: "nginx", + Version: "0.0.1", + RepoURL: "https://raw.githubusercontent.com/bookingcom/shipper/master/test/e2e/testdata", + }, + ChartValues: &shipper.ChartValues{ + "replicaCount": 1, + }, + Namespace: "", + ReleaseName: "super-server-foobar-0", + }, + ExpectedYaml: "apiVersion: v1\nkind: Service\nmetadata:\n name: nginx\n labels:\n app: super-server-foobar-0-nginx\n chart: \"nginx-0.0.1\"\n release: \"super-server-foobar-0\"\n heritage: \"Tiller\"\nspec:\n type: ClusterIP\n ports:\n - name: http\n port: 80\n targetPort: http\n selector:\n shipper-app: super-server-foobar-0-nginx%s\n---\napiVersion: apps/v1\nkind: Deployment\nmetadata:\n name: super-server-foobar-0-nginx\n labels:\n app: super-server-foobar-0-nginx\n chart: \"nginx-0.0.1\"\n release: \"super-server-foobar-0\"\n heritage: \"Tiller\"\nspec:\n selector:\n matchLabels:\n shipper-app: super-server-foobar-0-nginx\n shipper-release: \"super-server-foobar-0\"\n replicas: 1\n template:\n metadata:\n labels:\n app: super-server-foobar-0-nginx\n chart: \"nginx-0.0.1\"\n release: \"super-server-foobar-0\"\n heritage: \"Tiller\"\n spec:\n containers:\n - name: super-server-foobar-0-nginx\n image: \"docker.io/bitnami/nginx:1.14.2\"\n imagePullPolicy: \"IfNotPresent\"\n ports:\n - name: http\n containerPort: 8080\n livenessProbe:\n httpGet:\n path: /\n port: http\n initialDelaySeconds: 30\n timeoutSeconds: 5\n failureThreshold: 6\n readinessProbe:\n httpGet:\n path: /\n port: http\n initialDelaySeconds: 5\n timeoutSeconds: 3\n periodSeconds: 5\n volumeMounts:\n volumes:", + ExpectedErr: nil, + }, + { + Name: "Invalid chart template", + C: ChartRenderConfig{ + ChartSpec: shipper.Chart{ + Name: "invalid-chart-template", + Version: "0.0.1", + RepoURL: "https://raw.githubusercontent.com/bookingcom/shipper/master/test/e2e/testdata", + }, + ChartValues: &shipper.ChartValues{}, + Namespace: "", + ReleaseName: "", + }, + ExpectedYaml: "", + ExpectedErr: fmt.Errorf("could not render the chart: render error in \"invalid-chart-template/templates/deployment.yaml\": template: invalid-chart-template/templates/deployment.yaml:4:20: executing \"invalid-chart-template/templates/deployment.yaml\" at <{{template \"some-nonsense.fullname\" .}}>: template \"some-nonsense.fullname\" not defined"), + }, + { + Name: "Invalid chart url", + C: ChartRenderConfig{ + ChartSpec: shipper.Chart{ + Name: "0", + Version: "0.0.1", + RepoURL: "0", + }, + ChartValues: &shipper.ChartValues{}, + Namespace: "", + ReleaseName: "", + }, + ExpectedYaml: "", + ExpectedErr: shippererrors.NewChartRepoInternalError(&url.Error{ + Op: "parse", + URL: "0", + Err: fmt.Errorf("invalid URI for request"), + }), + }, + } + + for _, test := range tests { + actualYaml, actualErr := render(test.C) + if !reflect.DeepEqual(actualErr, test.ExpectedErr) { + t.Fatalf("expected error \n%v\ngot error \n%v", test.ExpectedErr, actualErr) + } + eq, diff := shippertesting.DeepEqualDiff(actualYaml, test.ExpectedYaml) + if !eq { + t.Fatalf("rendered chart differ from expected:\n%s", diff) + } + } +} From 304abe499c1fa788595198c247ead4230c9cb155 Mon Sep 17 00:00:00 2001 From: hihilla Date: Thu, 21 Jan 2021 12:51:42 +0100 Subject: [PATCH 7/7] cleanup --- Makefile | 2 +- cmd/shipperctl/cmd/backup/backup.go | 24 ++++++++++++------------ cmd/shipperctl/cmd/backup/prepare.go | 2 +- cmd/shipperctl/cmd/backup/restore.go | 2 +- cmd/shipperctl/cmd/chart/app.go | 4 ++-- cmd/shipperctl/cmd/clean/decommission.go | 20 ++++++++++---------- cmd/shipperctl/cmd/clusters/clusters.go | 6 +++--- cmd/shipperctl/cmd/list/list.go | 18 +++++++++--------- cmd/shipperctl/main.go | 8 ++++---- 9 files changed, 43 insertions(+), 43 deletions(-) diff --git a/Makefile b/Makefile index ff260cc15..8b1e77d3d 100644 --- a/Makefile +++ b/Makefile @@ -168,7 +168,7 @@ build-all: $(foreach os,$(OS),build/shipperctl.$(os)-amd64.tar.gz) build/sha256s build: mkdir -p build -build/shipper-state-metrics.%-amd64: $(PKG) cmd/shipper-state-metrics/* +build/shipper-state-metrics.%-amd64: $(PKG) cmd/shipper-state-metrics/* GOOS=$* GOARCH=amd64 go build $(LDFLAGS) -o build/shipper-state-metrics.$*-amd64 cmd/shipper-state-metrics/*.go build/shipper.%-amd64: $(PKG) cmd/shipper/* diff --git a/cmd/shipperctl/cmd/backup/backup.go b/cmd/shipperctl/cmd/backup/backup.go index dc53875a6..5fe57057b 100644 --- a/cmd/shipperctl/cmd/backup/backup.go +++ b/cmd/shipperctl/cmd/backup/backup.go @@ -18,7 +18,7 @@ var ( managementClusterContext string verboseFlag bool - BackupCmd = &cobra.Command{ + Cmd = &cobra.Command{ Use: "backup", Short: "Backup and restore Shipper applications and releases", PersistentPreRun: func(cmd *cobra.Command, args []string) { @@ -49,23 +49,23 @@ func init() { kubeConfigFlagName := "kubeconfig" fileFlagName := "file" - config.RegisterFlag(BackupCmd.PersistentFlags(), &kubeConfigFile) - if err := BackupCmd.MarkPersistentFlagFilename(kubeConfigFlagName, "yaml"); err != nil { - BackupCmd.Printf("warning: could not mark %q for filename autocompletion: %s\n", kubeConfigFlagName, err) + config.RegisterFlag(Cmd.PersistentFlags(), &kubeConfigFile) + if err := Cmd.MarkPersistentFlagFilename(kubeConfigFlagName, "yaml"); err != nil { + Cmd.Printf("warning: could not mark %q for filename autocompletion: %s\n", kubeConfigFlagName, err) } - BackupCmd.PersistentFlags().StringVar(&managementClusterContext, "management-cluster-context", "", "The name of the context to use to communicate with the management cluster. defaults to the current one") - BackupCmd.PersistentFlags().BoolVarP(&verboseFlag, "verbose", "v", false, "Prints the list of backup items") - BackupCmd.PersistentFlags().StringVar(&outputFormat, "format", "yaml", "Output format. One of: json|yaml") + Cmd.PersistentFlags().StringVar(&managementClusterContext, "management-cluster-context", "", "The name of the context to use to communicate with the management cluster. defaults to the current one") + Cmd.PersistentFlags().BoolVarP(&verboseFlag, "verbose", "v", false, "Prints the list of backup items") + Cmd.PersistentFlags().StringVar(&outputFormat, "format", "yaml", "Output format. One of: json|yaml") - BackupCmd.PersistentFlags().StringVarP(&backupFile, fileFlagName, "f", "backup.yaml", "The path to a backup file") - err := BackupCmd.MarkPersistentFlagFilename(fileFlagName, "yaml") + Cmd.PersistentFlags().StringVarP(&backupFile, fileFlagName, "f", "backup.yaml", "The path to a backup file") + err := Cmd.MarkPersistentFlagFilename(fileFlagName, "yaml") if err != nil { - BackupCmd.Printf("warning: could not mark %q for filename yaml autocompletion: %s\n", fileFlagName, err) + Cmd.Printf("warning: could not mark %q for filename yaml autocompletion: %s\n", fileFlagName, err) } - err = BackupCmd.MarkPersistentFlagFilename(fileFlagName, "json") + err = Cmd.MarkPersistentFlagFilename(fileFlagName, "json") if err != nil { - BackupCmd.Printf("warning: could not mark %q for filename json autocompletion: %s\n", fileFlagName, err) + Cmd.Printf("warning: could not mark %q for filename json autocompletion: %s\n", fileFlagName, err) } } diff --git a/cmd/shipperctl/cmd/backup/prepare.go b/cmd/shipperctl/cmd/backup/prepare.go index ba70a608a..b8b087750 100644 --- a/cmd/shipperctl/cmd/backup/prepare.go +++ b/cmd/shipperctl/cmd/backup/prepare.go @@ -26,7 +26,7 @@ var ( ) func init() { - BackupCmd.AddCommand(prepareBackupCmd) + Cmd.AddCommand(prepareBackupCmd) } func runPrepareCommand(cmd *cobra.Command, args []string) error { diff --git a/cmd/shipperctl/cmd/backup/restore.go b/cmd/shipperctl/cmd/backup/restore.go index 21ee03edf..7fc8de0aa 100644 --- a/cmd/shipperctl/cmd/backup/restore.go +++ b/cmd/shipperctl/cmd/backup/restore.go @@ -35,7 +35,7 @@ var ( ) func init() { - BackupCmd.AddCommand(restoreBackupCmd) + Cmd.AddCommand(restoreBackupCmd) } func runRestoreCommand(cmd *cobra.Command, args []string) error { diff --git a/cmd/shipperctl/cmd/chart/app.go b/cmd/shipperctl/cmd/chart/app.go index 65b5a0c0d..686a60992 100644 --- a/cmd/shipperctl/cmd/chart/app.go +++ b/cmd/shipperctl/cmd/chart/app.go @@ -58,11 +58,11 @@ func renderChartFromApp(cmd *cobra.Command, args []string) error { } var application shipper.Application if appName != "" { - applicationP, err := shipperClient.ShipperV1alpha1().Applications(namespace).Get(appName, metav1.GetOptions{}) + applicationPointer, err := shipperClient.ShipperV1alpha1().Applications(namespace).Get(appName, metav1.GetOptions{}) if err != nil { return err } - application = *applicationP + application = *applicationPointer } else { appYaml, err := ioutil.ReadFile(fileName) if err != nil { diff --git a/cmd/shipperctl/cmd/clean/decommission.go b/cmd/shipperctl/cmd/clean/decommission.go index 98a5c23ac..f42520b2a 100644 --- a/cmd/shipperctl/cmd/clean/decommission.go +++ b/cmd/shipperctl/cmd/clean/decommission.go @@ -29,7 +29,7 @@ var ( kubeConfigFile string managementClusterContext string - CleanCmd = &cobra.Command{ + Cmd = &cobra.Command{ Use: "clean", Short: "clean Shipper objects", } @@ -52,19 +52,19 @@ type releaseAndFilteredAnnotations struct { func init() { // Flags common to all commands under `shipperctl clean` - config.RegisterFlag(CleanCmd.PersistentFlags(), &kubeConfigFile) - if err := CleanCmd.MarkPersistentFlagFilename(kubeConfigFlagName, "yaml"); err != nil { - CleanCmd.Printf("warning: could not mark %q for filename autocompletion: %s\n", kubeConfigFlagName, err) + config.RegisterFlag(Cmd.PersistentFlags(), &kubeConfigFile) + if err := Cmd.MarkPersistentFlagFilename(kubeConfigFlagName, "yaml"); err != nil { + Cmd.Printf("warning: could not mark %q for filename autocompletion: %s\n", kubeConfigFlagName, err) } - CleanCmd.PersistentFlags().BoolVar(&dryrun, "dryrun", false, "If true, only prints the objects that will be modified/deleted") - CleanCmd.PersistentFlags().StringVar(&managementClusterContext, "management-cluster-context", "", "The name of the context to use to communicate with the management cluster. defaults to the current one") - CleanCmd.PersistentFlags().StringSliceVar(&clusters, decommissionedClustersFlagName, clusters, "List of decommissioned clusters. (Required)") - if err := CleanCmd.MarkPersistentFlagRequired(decommissionedClustersFlagName); err != nil { - CleanCmd.Printf("warning: could not mark %q as required: %s\n", decommissionedClustersFlagName, err) + Cmd.PersistentFlags().BoolVar(&dryrun, "dryrun", false, "If true, only prints the objects that will be modified/deleted") + Cmd.PersistentFlags().StringVar(&managementClusterContext, "management-cluster-context", "", "The name of the context to use to communicate with the management cluster. defaults to the current one") + Cmd.PersistentFlags().StringSliceVar(&clusters, decommissionedClustersFlagName, clusters, "List of decommissioned clusters. (Required)") + if err := Cmd.MarkPersistentFlagRequired(decommissionedClustersFlagName); err != nil { + Cmd.Printf("warning: could not mark %q as required: %s\n", decommissionedClustersFlagName, err) } - CleanCmd.AddCommand(cleanDeadClustersCmd) + Cmd.AddCommand(cleanDeadClustersCmd) } func runCleanCommand(cmd *cobra.Command, args []string) error { diff --git a/cmd/shipperctl/cmd/clusters/clusters.go b/cmd/shipperctl/cmd/clusters/clusters.go index b160037b2..0e91489ce 100644 --- a/cmd/shipperctl/cmd/clusters/clusters.go +++ b/cmd/shipperctl/cmd/clusters/clusters.go @@ -52,7 +52,7 @@ var ( RunE: runJoinClustersCommand, } - ClustersCmd = &cobra.Command{ + Cmd = &cobra.Command{ Use: "clusters", Short: "manage Shipper clusters", } @@ -97,8 +97,8 @@ func init() { setupCmd.AddCommand(setupMgmtCmd) - ClustersCmd.AddCommand(setupCmd) - ClustersCmd.AddCommand(joinCmd) + Cmd.AddCommand(setupCmd) + Cmd.AddCommand(joinCmd) } func runSetupMgmtClusterCommand(cmd *cobra.Command, args []string) error { diff --git a/cmd/shipperctl/cmd/list/list.go b/cmd/shipperctl/cmd/list/list.go index d6c29499d..9c15901c4 100644 --- a/cmd/shipperctl/cmd/list/list.go +++ b/cmd/shipperctl/cmd/list/list.go @@ -29,7 +29,7 @@ var ( kubeConfigFile string managementClusterContext string - ListCmd = &cobra.Command{ + Cmd = &cobra.Command{ Use: "list", Short: "lists Shipper releases that are scheduled *only* on given clusters", PersistentPreRun: func(cmd *cobra.Command, args []string) { @@ -64,17 +64,17 @@ type outputRelease struct { func init() { // Flags common to all commands under `shipperctl count` - config.RegisterFlag(ListCmd.PersistentFlags(), &kubeConfigFile) - if err := ListCmd.MarkPersistentFlagFilename(kubeConfigFlagName, "yaml"); err != nil { - ListCmd.Printf("warning: could not mark %q for filename autocompletion: %s\n", kubeConfigFlagName, err) + config.RegisterFlag(Cmd.PersistentFlags(), &kubeConfigFile) + if err := Cmd.MarkPersistentFlagFilename(kubeConfigFlagName, "yaml"); err != nil { + Cmd.Printf("warning: could not mark %q for filename autocompletion: %s\n", kubeConfigFlagName, err) } - ListCmd.PersistentFlags().StringVar(&managementClusterContext, "management-cluster-context", "", "The name of the context to use to communicate with the management cluster. defaults to the current one") - ListCmd.PersistentFlags().StringSliceVar(&clusters, clustersFlagName, clusters, "List of comma separated clusters to list releases that are scheduled *only* on those clusters. If empty, will list without filtering") - ListCmd.PersistentFlags().StringVarP(&printOption, "output", "o", "", "Output format. One of: json|yaml. (Optional) defaults to verbose") + Cmd.PersistentFlags().StringVar(&managementClusterContext, "management-cluster-context", "", "The name of the context to use to communicate with the management cluster. defaults to the current one") + Cmd.PersistentFlags().StringSliceVar(&clusters, clustersFlagName, clusters, "List of comma separated clusters to list releases that are scheduled *only* on those clusters. If empty, will list without filtering") + Cmd.PersistentFlags().StringVarP(&printOption, "output", "o", "", "Output format. One of: json|yaml. (Optional) defaults to verbose") - ListCmd.AddCommand(countContendersCmd) - ListCmd.AddCommand(countReleasesCmd) + Cmd.AddCommand(countContendersCmd) + Cmd.AddCommand(countReleasesCmd) for _, command := range []*cobra.Command{countContendersCmd, countReleasesCmd} { command.SetOutput(os.Stdout) } diff --git a/cmd/shipperctl/main.go b/cmd/shipperctl/main.go index 8e58f958b..dbd5d0201 100644 --- a/cmd/shipperctl/main.go +++ b/cmd/shipperctl/main.go @@ -21,10 +21,10 @@ var rootCmd = &cobra.Command{ } func init() { - rootCmd.AddCommand(clusters.ClustersCmd) - rootCmd.AddCommand(list.ListCmd) - rootCmd.AddCommand(clean.CleanCmd) - rootCmd.AddCommand(backup.BackupCmd) + rootCmd.AddCommand(clusters.Cmd) + rootCmd.AddCommand(list.Cmd) + rootCmd.AddCommand(clean.Cmd) + rootCmd.AddCommand(backup.Cmd) rootCmd.AddCommand(chart.Command) }