diff --git a/cmd/flux/create.go b/cmd/flux/create.go index 758a2f54..1c3d99ef 100644 --- a/cmd/flux/create.go +++ b/cmd/flux/create.go @@ -19,6 +19,7 @@ package main import ( "context" "fmt" + "regexp" "strings" "time" @@ -51,6 +52,18 @@ func init() { createCmd.PersistentFlags().BoolVar(&createArgs.export, "export", false, "export in YAML format to stdout") createCmd.PersistentFlags().StringSliceVar(&createArgs.labels, "label", nil, "set labels on the resource (can specify multiple labels with commas: label1=value1,label2=value2)") + createCmd.PersistentPreRunE = func(cmd *cobra.Command, args []string) error { + if len(args) < 1 { + return fmt.Errorf("name is required") + } + + name := args[0] + if !validateObjectName(name) { + return fmt.Errorf("name '%s' is invalid, it should adhere to standard defined in RFC 1123", name) + } + + return nil + } rootCmd.AddCommand(createCmd) } @@ -150,3 +163,8 @@ func parseLabels() (map[string]string, error) { return result, nil } + +func validateObjectName(name string) bool { + r := regexp.MustCompile("^[a-z0-9]([a-z0-9\\-]){0,61}[a-z0-9]$") + return r.MatchString(name) +} diff --git a/cmd/flux/create_secret_git_test.go b/cmd/flux/create_secret_git_test.go index 01a3e929..16ff400a 100644 --- a/cmd/flux/create_secret_git_test.go +++ b/cmd/flux/create_secret_git_test.go @@ -13,7 +13,7 @@ func TestCreateGitSecret(t *testing.T) { { name: "no args", args: "create secret git", - assert: assertError("secret name is required"), + assert: assertError("name is required"), }, { name: "basic secret", diff --git a/cmd/flux/create_secret_helm_test.go b/cmd/flux/create_secret_helm_test.go index 04c96dbb..fe0bc0c9 100644 --- a/cmd/flux/create_secret_helm_test.go +++ b/cmd/flux/create_secret_helm_test.go @@ -12,7 +12,7 @@ func TestCreateHelmSecret(t *testing.T) { }{ { args: "create secret helm", - assert: assertError("secret name is required"), + assert: assertError("name is required"), }, { args: "create secret helm helm-secret --username=my-username --password=my-password --namespace=my-namespace --export", diff --git a/cmd/flux/create_secret_tls_test.go b/cmd/flux/create_secret_tls_test.go index 8085c584..31d49200 100644 --- a/cmd/flux/create_secret_tls_test.go +++ b/cmd/flux/create_secret_tls_test.go @@ -12,7 +12,7 @@ func TestCreateTlsSecretNoArgs(t *testing.T) { }{ { args: "create secret tls", - assert: assertError("secret name is required"), + assert: assertError("name is required"), }, { args: "create secret tls certs --namespace=my-namespace --cert-file=./testdata/create_secret/tls/test-cert.pem --key-file=./testdata/create_secret/tls/test-key.pem --export", diff --git a/cmd/flux/create_source_git_test.go b/cmd/flux/create_source_git_test.go index 1b391bce..73c1724a 100644 --- a/cmd/flux/create_source_git_test.go +++ b/cmd/flux/create_source_git_test.go @@ -96,7 +96,7 @@ func TestCreateSourceGit(t *testing.T) { { "NoArgs", "create source git", - assertError("GitRepository source name is required"), + assertError("name is required"), nil, }, { "Succeeded", diff --git a/cmd/flux/create_test.go b/cmd/flux/create_test.go new file mode 100644 index 00000000..ee38fe50 --- /dev/null +++ b/cmd/flux/create_test.go @@ -0,0 +1,55 @@ +package main + +import ( + "testing" + + "k8s.io/apimachinery/pkg/util/rand" +) + +func Test_validateObjectName(t *testing.T) { + tests := []struct { + name string + valid bool + }{ + { + name: "flux-system", + valid: true, + }, + { + name: "-flux-system", + valid: false, + }, + { + name: "-flux-system-", + valid: false, + }, + { + name: "third.first", + valid: false, + }, + { + name: "THirdfirst", + valid: false, + }, + { + name: "THirdfirst", + valid: false, + }, + { + name: rand.String(63), + valid: true, + }, + { + name: rand.String(64), + valid: false, + }, + } + + for _, tt := range tests { + valid := validateObjectName(tt.name) + if valid != tt.valid { + t.Errorf("expected name %q to return %t for validateObjectName func but got %t", + tt.name, tt.valid, valid) + } + } +}