diff --git a/cmd/build.go b/cmd/build.go index 8e1986b5..a60231d7 100644 --- a/cmd/build.go +++ b/cmd/build.go @@ -84,7 +84,7 @@ kn func build --builder cnbs/sample-builder:bionic return cmd } -func ValidNamespaceAndRegistry() survey.Validator { +func ValidNamespaceAndRegistry(path string) survey.Validator { return func(val interface{}) error { // if the value passed in is the zero value of the appropriate type @@ -92,10 +92,10 @@ func ValidNamespaceAndRegistry() survey.Validator { return errors.New("Value is required") } - _, err := fn.DerivedImage("", val.(string)) //image can be derived without any error + _, err := fn.DerivedImage(path, val.(string)) //image can be derived without any error if err != nil { - return errors.New(val.(string) + " Registry and Namespace are required (ie. docker.io/tigerteam). The image name will be derived from the function name.") + return fmt.Errorf("Invalid registry [%s] %v", val.(string), err) } return nil } @@ -120,6 +120,14 @@ func runBuild(cmd *cobra.Command, _ []string, clientFn buildClientFn) (err error return fmt.Errorf("the given path '%v' does not contain an initialized function. Please create one at this path before deploying", config.Path) } + // If a registry name was provided as a command line flag, it should be validated + if config.Registry != "" { + err = ValidNamespaceAndRegistry(config.Path)(config.Registry) + if err != nil { + return + } + } + // If the Function does not yet have an image name and one was not provided on the command line if function.Image == "" { // AND a --registry was not provided, then we need to @@ -129,7 +137,7 @@ func runBuild(cmd *cobra.Command, _ []string, clientFn buildClientFn) (err error err = survey.AskOne( &survey.Input{Message: "Registry for Function images:"}, - &config.Registry, survey.WithValidator(ValidNamespaceAndRegistry())) + &config.Registry, survey.WithValidator(ValidNamespaceAndRegistry(config.Path))) if err != nil { if err == terminal.InterruptErr { return nil diff --git a/cmd/build_test.go b/cmd/build_test.go new file mode 100644 index 00000000..199a46a2 --- /dev/null +++ b/cmd/build_test.go @@ -0,0 +1,51 @@ +package cmd + +import ( + "io/ioutil" + "testing" + + fn "knative.dev/kn-plugin-func" + "knative.dev/kn-plugin-func/mock" +) + +// TestBuildInvalidRegistry ensures that running build specifying the name of the +// registry explicitly as an argument invokes the registry validation code. +func TestBuildInvalidRegistry(t *testing.T) { + var ( + args = []string{"--registry", "foo/bar/foobar/boofar"} // provide an invalid registry name + builder = mock.NewBuilder() // with a mock builder + ) + + // Run this test in a temporary directory + defer fromTempDir(t)() + // Write a func.yaml config which does not specify an image + funcYaml := `name: testymctestface +namespace: "" +runtime: go +image: "" +imageDigest: "" +builder: quay.io/boson/faas-go-builder +builders: + default: quay.io/boson/faas-go-builder +envs: [] +annotations: {} +labels: [] +created: 2021-01-01T00:00:00+00:00 +` + if err := ioutil.WriteFile("func.yaml", []byte(funcYaml), 0600); err != nil { + t.Fatal(err) + } + + // Create a command with a client constructor fn that instantiates a client + // with a the mocked builder. + cmd := NewBuildCmd(func(_ buildConfig) (*fn.Client, error) { + return fn.New(fn.WithBuilder(builder)), nil + }) + + // Execute the command + cmd.SetArgs(args) + err := cmd.Execute() + if err == nil { + t.Fatal("Expected error") + } +}