diff --git a/cmd/all.go b/cmd/all.go index e6cdb468..ba80c8a1 100644 --- a/cmd/all.go +++ b/cmd/all.go @@ -12,6 +12,9 @@ func init() { Use: "all", Short: "Run sync and render", Long: "Run sync and render", + Annotations: map[string]string{ + ANNOTATION_SMART_MODE: ANNOTATION_TRUE, + }, Run: func(cmd *cobra.Command, args []string) { g := myks.New(".") diff --git a/cmd/render.go b/cmd/render.go index 0cb3319d..e9afad0f 100644 --- a/cmd/render.go +++ b/cmd/render.go @@ -12,6 +12,9 @@ func init() { Use: "render", Short: "Render manifests", Long: "Render manifests", + Annotations: map[string]string{ + ANNOTATION_SMART_MODE: ANNOTATION_TRUE, + }, Run: func(cmd *cobra.Command, args []string) { g := myks.New(".") diff --git a/cmd/root.go b/cmd/root.go index a421e486..0ebc5fa3 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -16,6 +16,11 @@ import ( "github.com/mykso/myks/internal/myks" ) +const ( + ANNOTATION_SMART_MODE = "feat:smart-mode" + ANNOTATION_TRUE = "true" +) + var ( cfgFile string targetEnvironments []string @@ -26,7 +31,7 @@ var ( var rootCmd = &cobra.Command{ Use: "myks", Short: "Myks helps to manage configuration for kubernetes clusters", - Long: `Myks fetches K8s workloads from a variety of sources, e.g. Helm charts or Git Repositories. It renders their respective yaml files to the file system in a structure of environments and their applications. + Long: `Myks fetches K8s workloads from a variety of sources, e.g. Helm charts or Git Repositories. It renders their respective yaml files to the file system in a structure of environments and their applications. It supports prototype applications that can be shared between environments and inheritance of configuration from parent environments to their "children". @@ -37,57 +42,6 @@ Myks supports two positional arguments: If you do not provide any positional arguments, myks will run in "Smart Mode". In Smart Mode, myks will only render environments and applications that have changed since the last run. `, - PersistentPreRunE: func(cmd *cobra.Command, args []string) (err error) { - // Check positional arguments: - // 1. Comma-separated list of environment search paths or ALL to search everywhere (default: ALL) - // 2. Comma-separated list of application names or none to process all applications (default: none) - - targetEnvironments = nil - targetApplications = nil - - onlyArgs := args - - for _, subcmd := range cmd.Commands() { - if subcmd.Name() == args[0] { - onlyArgs = args[1:] - break - } - } - - switch len(onlyArgs) { - case 0: - // smart mode requires instantiation of globe object to get the list of environments - // the globe object will not be used later in the process. It is only used to get the list of all environments and their apps. - globeAllEnvsAndApps := myks.New(".") - targetEnvironments, targetApplications, err = globeAllEnvsAndApps.InitSmartMode() - if err != nil { - log.Warn().Err(err).Msg("Unable to run Smart Mode. Rendering everything.") - } - if targetEnvironments == nil && targetApplications == nil { - log.Warn().Msg("Smart Mode did not find any changes. Existing.") - os.Exit(0) - } - case 1: - if onlyArgs[0] != "ALL" { - targetEnvironments = strings.Split(onlyArgs[0], ",") - } - case 2: - if onlyArgs[0] != "ALL" { - targetEnvironments = strings.Split(onlyArgs[0], ",") - } - if onlyArgs[1] != "ALL" { - targetApplications = strings.Split(onlyArgs[1], ",") - } - default: - err := errors.New("Too many positional arguments") - log.Error().Err(err).Msg("Unable to parse positional arguments") - return err - } - - log.Debug().Strs("environments", targetEnvironments).Strs("applications", targetApplications).Msg("Parsed arguments") - - return nil - }, } func init() { @@ -103,6 +57,53 @@ func init() { } rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is the first .myks.yaml up the directory tree)") + + rootCmd.PersistentPreRunE = detectTargetEnvsAndApps +} + +func detectTargetEnvsAndApps(cmd *cobra.Command, args []string) (err error) { + // Check positional arguments for Smart Mode: + // 1. Comma-separated list of environment search paths or ALL to search everywhere (default: ALL) + // 2. Comma-separated list of application names or none to process all applications (default: none) + + if cmd.Annotations[ANNOTATION_SMART_MODE] != ANNOTATION_TRUE { + log.Debug().Msg("Smart Mode is not supported for this command.") + return + } + + switch len(args) { + case 0: + // smart mode requires instantiation of globe object to get the list of environments + // the globe object will not be used later in the process. It is only used to get the list of all environments and their apps. + globeAllEnvsAndApps := myks.New(".") + targetEnvironments, targetApplications, err = globeAllEnvsAndApps.InitSmartMode() + if err != nil { + log.Warn().Err(err).Msg("Unable to run Smart Mode. Rendering everything.") + } + if targetEnvironments == nil && targetApplications == nil { + log.Warn().Msg("Smart Mode did not find any changes. Exiting.") + os.Exit(0) + } + case 1: + if args[0] != "ALL" { + targetEnvironments = strings.Split(args[0], ",") + } + case 2: + if args[0] != "ALL" { + targetEnvironments = strings.Split(args[0], ",") + } + if args[1] != "ALL" { + targetApplications = strings.Split(args[1], ",") + } + default: + err := errors.New("Too many positional arguments") + log.Error().Err(err).Msg("Unable to parse positional arguments") + return err + } + + log.Debug().Strs("environments", targetEnvironments).Strs("applications", targetApplications).Msg("Parsed arguments") + + return nil } func initConfig() { diff --git a/cmd/sync.go b/cmd/sync.go index c4848059..bd48048a 100644 --- a/cmd/sync.go +++ b/cmd/sync.go @@ -11,11 +11,14 @@ func init() { cmd := &cobra.Command{ Use: "sync", Short: "Sync vendir configs", - Long: `Sync vendir configs. This will run vendir sync for all applications. + Long: `Sync vendir configs. This will run vendir sync for all applications. -Authentication against protected repositories is achieved with environment variables prefixed with "VENDIR_SECRET_". -For example, if you reference a secret named "mycreds" in your vendir.yaml, you need to export the variables "VENDIR_SECRET_MYCREDS_USERNAME" and +Authentication against protected repositories is achieved with environment variables prefixed with "VENDIR_SECRET_". +For example, if you reference a secret named "mycreds" in your vendir.yaml, you need to export the variables "VENDIR_SECRET_MYCREDS_USERNAME" and "VENDIR_SECRET_MYCREDS_PASSWORD" in your environment.`, + Annotations: map[string]string{ + ANNOTATION_SMART_MODE: ANNOTATION_TRUE, + }, Run: func(cmd *cobra.Command, args []string) { log.Info().Msg("Syncing vendir configs") g := myks.New(".") diff --git a/go.mod b/go.mod index 517b8829..fb5ebbc1 100644 --- a/go.mod +++ b/go.mod @@ -8,6 +8,7 @@ require ( github.com/rs/zerolog v1.29.1 github.com/spf13/cobra v1.7.0 github.com/spf13/viper v1.16.0 + golang.org/x/exp v0.0.0-20230817173708-d852ddb80c63 golang.org/x/sync v0.3.0 gopkg.in/yaml.v3 v3.0.1 ) @@ -26,7 +27,6 @@ require ( github.com/spf13/jwalterweatherman v1.1.0 // indirect github.com/spf13/pflag v1.0.5 // indirect github.com/subosito/gotenv v1.4.2 // indirect - golang.org/x/exp v0.0.0-20230817173708-d852ddb80c63 // indirect golang.org/x/sys v0.11.0 // indirect golang.org/x/text v0.9.0 // indirect gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect diff --git a/go.sum b/go.sum index 6d8960e3..e75efacc 100644 --- a/go.sum +++ b/go.sum @@ -329,8 +329,6 @@ golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.10.0 h1:SqMFp9UcQJZa+pmYuAKjd9xq1f0j5rLcDIk0mj4qAsA= -golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0 h1:eG7RXZHdqOJ1i+0lgLgCpSXAp6M3LYlAo6osgSi0xOM= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=