diff --git a/cmd/flags.go b/cmd/flags.go new file mode 100644 index 000000000..2ec101e1a --- /dev/null +++ b/cmd/flags.go @@ -0,0 +1,18 @@ +package cmd + +import ( + "fmt" + + cli "github.com/spf13/cobra" +) + +// mustMarkRequired marks each named flag as required. It panics when a flag +// is not defined on the command, so a mistyped or renamed flag name fails on +// the first run instead of silently making the flag optional. +func mustMarkRequired(cmd *cli.Command, names ...string) { + for _, name := range names { + if err := cmd.MarkFlagRequired(name); err != nil { + panic(fmt.Sprintf("marking --%s required on %q: %v", name, cmd.Name(), err)) + } + } +} diff --git a/cmd/flags_test.go b/cmd/flags_test.go new file mode 100644 index 000000000..cf88b32b0 --- /dev/null +++ b/cmd/flags_test.go @@ -0,0 +1,24 @@ +package cmd + +import ( + "testing" + + cli "github.com/spf13/cobra" + "github.com/stretchr/testify/assert" +) + +func TestMustMarkRequired(t *testing.T) { + t.Run("should mark an existing flag as required", func(t *testing.T) { + cmd := &cli.Command{Use: "test"} + cmd.Flags().String("file", "", "") + + assert.NotPanics(t, func() { mustMarkRequired(cmd, "file") }) + assert.Error(t, cmd.ValidateRequiredFlags()) + }) + + t.Run("should panic on an unknown flag name", func(t *testing.T) { + cmd := &cli.Command{Use: "test"} + + assert.Panics(t, func() { mustMarkRequired(cmd, "no-such-flag") }) + }) +} diff --git a/cmd/group.go b/cmd/group.go index 86d32dad6..aaa6ff736 100644 --- a/cmd/group.go +++ b/cmd/group.go @@ -86,9 +86,9 @@ func createGroupCommand(cliConfig *Config) *cli.Command { } cmd.Flags().StringVarP(&filePath, "file", "f", "", "Path to the group body file") - cmd.MarkFlagRequired("file") + mustMarkRequired(cmd, "file") cmd.Flags().StringVarP(&header, "header", "H", "", "Header :") - cmd.MarkFlagRequired("header") + mustMarkRequired(cmd, "header") return cmd } @@ -140,9 +140,9 @@ func editGroupCommand(cliConfig *Config) *cli.Command { } cmd.Flags().StringVarP(&filePath, "file", "f", "", "Path to the group body file") - cmd.MarkFlagRequired("file") + mustMarkRequired(cmd, "file") cmd.Flags().StringVarP(&header, "header", "H", "", "Header :") - cmd.MarkFlagRequired("header") + mustMarkRequired(cmd, "header") return cmd } @@ -219,7 +219,7 @@ func viewGroupCommand(cliConfig *Config) *cli.Command { cmd.Flags().BoolVarP(&metadata, "metadata", "m", false, "Set this flag to see metadata") cmd.Flags().StringVarP(&header, "header", "H", "", "Header :") - cmd.MarkFlagRequired("header") + mustMarkRequired(cmd, "header") return cmd } @@ -283,7 +283,7 @@ func listGroupCommand(cliConfig *Config) *cli.Command { } cmd.Flags().StringVarP(&header, "header", "H", "", "Header :") - cmd.MarkFlagRequired("header") + mustMarkRequired(cmd, "header") return cmd } diff --git a/cmd/namespace.go b/cmd/namespace.go index 7a8c8e32a..c259b122f 100644 --- a/cmd/namespace.go +++ b/cmd/namespace.go @@ -89,7 +89,7 @@ func viewNamespaceCommand(cliConfig *Config) *cli.Command { } cmd.Flags().StringVarP(&header, "header", "H", "", "Header :") - cmd.MarkFlagRequired("header") + mustMarkRequired(cmd, "header") return cmd } @@ -147,7 +147,7 @@ func listNamespaceCommand(cliConfig *Config) *cli.Command { } cmd.Flags().StringVarP(&header, "header", "H", "", "Header :") - cmd.MarkFlagRequired("header") + mustMarkRequired(cmd, "header") return cmd } diff --git a/cmd/organization.go b/cmd/organization.go index 0b20c3f30..2d2d68ea8 100644 --- a/cmd/organization.go +++ b/cmd/organization.go @@ -87,9 +87,9 @@ func createOrganizationCommand(cliConfig *Config) *cli.Command { } cmd.Flags().StringVarP(&filePath, "file", "f", "", "Path to the organization body file") - cmd.MarkFlagRequired("file") + mustMarkRequired(cmd, "file") cmd.Flags().StringVarP(&header, "header", "H", "", "Header :") - cmd.MarkFlagRequired("header") + mustMarkRequired(cmd, "header") return cmd } @@ -141,9 +141,9 @@ func editOrganizationCommand(cliConfig *Config) *cli.Command { } cmd.Flags().StringVarP(&filePath, "file", "f", "", "Path to the organization body file") - cmd.MarkFlagRequired("file") + mustMarkRequired(cmd, "file") cmd.Flags().StringVarP(&header, "header", "H", "", "Header :") - cmd.MarkFlagRequired("header") + mustMarkRequired(cmd, "header") return cmd } @@ -219,7 +219,7 @@ func viewOrganizationCommand(cliConfig *Config) *cli.Command { cmd.Flags().BoolVarP(&metadata, "metadata", "m", false, "Set this flag to see metadata") cmd.Flags().StringVarP(&header, "header", "H", "", "Header :") - cmd.MarkFlagRequired("header") + mustMarkRequired(cmd, "header") return cmd } @@ -280,7 +280,7 @@ func listOrganizationCommand(cliConfig *Config) *cli.Command { } cmd.Flags().StringVarP(&header, "header", "H", "", "Header :") - cmd.MarkFlagRequired("header") + mustMarkRequired(cmd, "header") return cmd } @@ -340,7 +340,7 @@ func admlistOrganizationCommand(cliConfig *Config) *cli.Command { } cmd.Flags().StringVarP(&header, "header", "H", "", "Header :") - cmd.MarkFlagRequired("header") + mustMarkRequired(cmd, "header") return cmd } diff --git a/cmd/permission.go b/cmd/permission.go index 90c7ac6a6..238a714c7 100644 --- a/cmd/permission.go +++ b/cmd/permission.go @@ -86,9 +86,9 @@ func createPermissionCommand(cliConfig *Config) *cli.Command { } cmd.Flags().StringVarP(&filePath, "file", "f", "", "Path to the permission body file") - cmd.MarkFlagRequired("file") + mustMarkRequired(cmd, "file") cmd.Flags().StringVarP(&header, "header", "H", "", "Header :") - cmd.MarkFlagRequired("header") + mustMarkRequired(cmd, "header") return cmd } @@ -140,9 +140,9 @@ func editPermissionCommand(cliConfig *Config) *cli.Command { } cmd.Flags().StringVarP(&filePath, "file", "f", "", "Path to the permission body file") - cmd.MarkFlagRequired("file") + mustMarkRequired(cmd, "file") cmd.Flags().StringVarP(&header, "header", "H", "", "Header :") - cmd.MarkFlagRequired("header") + mustMarkRequired(cmd, "header") return cmd } @@ -199,7 +199,7 @@ func viewPermissionCommand(cliConfig *Config) *cli.Command { } cmd.Flags().StringVarP(&header, "header", "H", "", "Header :") - cmd.MarkFlagRequired("header") + mustMarkRequired(cmd, "header") return cmd } @@ -261,7 +261,7 @@ func listPermissionCommand(cliConfig *Config) *cli.Command { } cmd.Flags().StringVarP(&header, "header", "H", "", "Header :") - cmd.MarkFlagRequired("header") + mustMarkRequired(cmd, "header") return cmd } diff --git a/cmd/policy.go b/cmd/policy.go index 998f415d4..2fb2281dc 100644 --- a/cmd/policy.go +++ b/cmd/policy.go @@ -84,9 +84,9 @@ func createPolicyCommand(cliConfig *Config) *cli.Command { } cmd.Flags().StringVarP(&filePath, "file", "f", "", "Path to the policy body file") - cmd.MarkFlagRequired("file") + mustMarkRequired(cmd, "file") cmd.Flags().StringVarP(&header, "header", "H", "", "Header :") - cmd.MarkFlagRequired("header") + mustMarkRequired(cmd, "header") return cmd } @@ -138,9 +138,9 @@ func editPolicyCommand(cliConfig *Config) *cli.Command { } cmd.Flags().StringVarP(&filePath, "file", "f", "", "Path to the policy body file") - cmd.MarkFlagRequired("file") + mustMarkRequired(cmd, "file") cmd.Flags().StringVarP(&header, "header", "H", "", "Header :") - cmd.MarkFlagRequired("header") + mustMarkRequired(cmd, "header") return cmd } @@ -198,7 +198,7 @@ func viewPolicyCommand(cliConfig *Config) *cli.Command { } cmd.Flags().StringVarP(&header, "header", "H", "", "Header :") - cmd.MarkFlagRequired("header") + mustMarkRequired(cmd, "header") return cmd } diff --git a/cmd/preferences.go b/cmd/preferences.go index 04a0abaa5..44cc6fe7f 100644 --- a/cmd/preferences.go +++ b/cmd/preferences.go @@ -83,7 +83,7 @@ func preferencesListCommand(cliConfig *Config) *cobra.Command { } cmd.Flags().StringVarP(&header, "header", "H", "", "Header :") - cmd.MarkFlagRequired("header") + mustMarkRequired(cmd, "header") return cmd } @@ -140,7 +140,7 @@ func preferencesSetCommand(cliConfig *Config) *cobra.Command { cmd.Flags().StringVarP(&name, "name", "n", "", "Name of the preference") cmd.Flags().StringVarP(&value, "value", "v", "", "Value of the preference") - cmd.MarkFlagRequired("header") + mustMarkRequired(cmd, "header") return cmd } @@ -182,7 +182,7 @@ func preferencesGetCommand(cliConfig *Config) *cobra.Command { }, } cmd.Flags().StringVarP(&header, "header", "H", "", "Header :") - cmd.MarkFlagRequired("header") + mustMarkRequired(cmd, "header") return cmd } diff --git a/cmd/project.go b/cmd/project.go index 8fe52429f..5f4d4f1a0 100644 --- a/cmd/project.go +++ b/cmd/project.go @@ -86,9 +86,9 @@ func createProjectCommand(cliConfig *Config) *cli.Command { } cmd.Flags().StringVarP(&filePath, "file", "f", "", "Path to the project body file") - cmd.MarkFlagRequired("file") + mustMarkRequired(cmd, "file") cmd.Flags().StringVarP(&header, "header", "H", "", "Header :") - cmd.MarkFlagRequired("header") + mustMarkRequired(cmd, "header") return cmd } @@ -140,9 +140,9 @@ func editProjectCommand(cliConfig *Config) *cli.Command { } cmd.Flags().StringVarP(&filePath, "file", "f", "", "Path to the project body file") - cmd.MarkFlagRequired("file") + mustMarkRequired(cmd, "file") cmd.Flags().StringVarP(&header, "header", "H", "", "Header :") - cmd.MarkFlagRequired("header") + mustMarkRequired(cmd, "header") return cmd } @@ -219,7 +219,7 @@ func viewProjectCommand(cliConfig *Config) *cli.Command { cmd.Flags().BoolVarP(&metadata, "metadata", "m", false, "Set this flag to see metadata") cmd.Flags().StringVarP(&header, "header", "H", "", "Header :") - cmd.MarkFlagRequired("header") + mustMarkRequired(cmd, "header") return cmd } @@ -283,7 +283,7 @@ func listProjectCommand(cliConfig *Config) *cli.Command { } cmd.Flags().StringVarP(&header, "header", "H", "", "Header :") - cmd.MarkFlagRequired("header") + mustMarkRequired(cmd, "header") return cmd } diff --git a/cmd/reconcile.go b/cmd/reconcile.go index 8be765855..eee6f8fe6 100644 --- a/cmd/reconcile.go +++ b/cmd/reconcile.go @@ -57,7 +57,7 @@ func ReconcileCommand(cliConfig *Config) *cli.Command { }, } cmd.Flags().StringVarP(&filePath, "file", "f", "", "Path to the desired-state YAML file") - cmd.MarkFlagRequired("file") + mustMarkRequired(cmd, "file") cmd.Flags().BoolVar(&dryRun, "dry-run", false, "Print the plan without applying changes") cmd.Flags().StringVarP(&header, "header", "H", "", "Header : for auth, e.g. 'Authorization:Basic '") bindFlagsFromClientConfig(cmd) diff --git a/cmd/role.go b/cmd/role.go index a7cc4c094..5d8e6c012 100644 --- a/cmd/role.go +++ b/cmd/role.go @@ -87,9 +87,9 @@ func createRoleCommand(cliConfig *Config) *cli.Command { } cmd.Flags().StringVarP(&filePath, "file", "f", "", "Path to the role body file") - cmd.MarkFlagRequired("file") + mustMarkRequired(cmd, "file") cmd.Flags().StringVarP(&header, "header", "H", "", "Header :") - cmd.MarkFlagRequired("header") + mustMarkRequired(cmd, "header") return cmd } @@ -141,9 +141,9 @@ func editRoleCommand(cliConfig *Config) *cli.Command { } cmd.Flags().StringVarP(&filePath, "file", "f", "", "Path to the role body file") - cmd.MarkFlagRequired("file") + mustMarkRequired(cmd, "file") cmd.Flags().StringVarP(&header, "header", "H", "", "Header :") - cmd.MarkFlagRequired("header") + mustMarkRequired(cmd, "header") return cmd } @@ -221,7 +221,7 @@ func viewRoleCommand(cliConfig *Config) *cli.Command { cmd.Flags().BoolVarP(&metadata, "metadata", "m", false, "Set this flag to see metadata") cmd.Flags().StringVarP(&header, "header", "H", "", "Header :") - cmd.MarkFlagRequired("header") + mustMarkRequired(cmd, "header") return cmd } @@ -284,7 +284,7 @@ func listRoleCommand(cliConfig *Config) *cli.Command { } cmd.Flags().StringVarP(&header, "header", "H", "", "Header :") - cmd.MarkFlagRequired("header") + mustMarkRequired(cmd, "header") return cmd } diff --git a/cmd/seed.go b/cmd/seed.go index 042f5614e..f5e44d1f2 100644 --- a/cmd/seed.go +++ b/cmd/seed.go @@ -89,7 +89,7 @@ func SeedCommand(cliConfig *Config) *cli.Command { bindFlagsFromClientConfig(cmd) cmd.Flags().StringVarP(&header, "header", "H", "", "Header ") - cmd.MarkFlagRequired("header") + mustMarkRequired(cmd, "header") cmd.Flags().StringVarP(&configFile, "config", "c", "", "config file path") return cmd } diff --git a/cmd/user.go b/cmd/user.go index fb54c2697..aaaa80e7a 100644 --- a/cmd/user.go +++ b/cmd/user.go @@ -91,9 +91,9 @@ func createUserCommand(cliConfig *Config) *cli.Command { } cmd.Flags().StringVarP(&filePath, "file", "f", "", "Path to the user body file") - cmd.MarkFlagRequired("file") + mustMarkRequired(cmd, "file") cmd.Flags().StringVarP(&header, "header", "H", "", "Header :") - cmd.MarkFlagRequired("header") + mustMarkRequired(cmd, "header") return cmd } @@ -146,9 +146,9 @@ func editUserCommand(cliConfig *Config) *cli.Command { } cmd.Flags().StringVarP(&filePath, "file", "f", "", "Path to the user body file") - cmd.MarkFlagRequired("file") + mustMarkRequired(cmd, "file") cmd.Flags().StringVarP(&header, "header", "H", "", "Header :") - cmd.MarkFlagRequired("header") + mustMarkRequired(cmd, "header") return cmd } @@ -222,7 +222,7 @@ func viewUserCommand(cliConfig *Config) *cli.Command { cmd.Flags().BoolVarP(&metadata, "metadata", "m", false, "Set this flag to see metadata") cmd.Flags().StringVarP(&header, "header", "H", "", "Header :") - cmd.MarkFlagRequired("header") + mustMarkRequired(cmd, "header") return cmd } @@ -280,7 +280,7 @@ func listUserCommand(cliConfig *Config) *cli.Command { } cmd.Flags().StringVarP(&header, "header", "H", "", "Header :") - cmd.MarkFlagRequired("header") + mustMarkRequired(cmd, "header") return cmd }