feat: validation for registry/namespace to not contain image name (#601)

* initial validation for registry/namespace to not contain image name

* Update function.go

* supporting nested namespace
This commit is contained in:
salaboy 2021-10-26 19:13:21 +01:00 committed by GitHub
parent 4bba2b48cb
commit cf9596c83e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 30 additions and 6 deletions

View File

@ -588,7 +588,7 @@ func (c *Client) Build(ctx context.Context, path string) (err error) {
return
}
// TODO: create a statu structure and return it here for optional
// TODO: create a status structure and return it here for optional
// use by the cli for user echo (rather than rely on verbose mode here)
message := fmt.Sprintf("🙌 Function image built: %v", f.Image)
if runtime.GOOS == "windows" {

View File

@ -1,6 +1,7 @@
package cmd
import (
"errors"
"fmt"
"github.com/AlecAivazis/survey/v2"
@ -83,6 +84,23 @@ kn func build --builder cnbs/sample-builder:bionic
return cmd
}
func ValidNamespaceAndRegistry() survey.Validator {
return func(val interface{}) error {
// if the value passed in is the zero value of the appropriate type
if len(val.(string)) == 0 {
return errors.New("Value is required")
}
_, err := fn.DerivedImage("", 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 nil
}
}
func runBuild(cmd *cobra.Command, _ []string, clientFn buildClientFn) (err error) {
config, err := newBuildConfig().Prompt()
if err != nil {
@ -111,7 +129,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(survey.Required))
&config.Registry, survey.WithValidator(ValidNamespaceAndRegistry()))
if err != nil {
if err == terminal.InterruptErr {
return nil

View File

@ -156,7 +156,7 @@ func (f Function) ImageWithDigest() string {
// DerivedImage returns the derived image name (OCI container tag) of the
// Function whose source is at root, with the default registry for when
// the image has to be calculated (derived).
// The following are eqivalent due to the use of DefaultRegistry:
// The following are equivalent due to the use of DefaultRegistry:
// registry: docker.io/myname
// myname
// A full image name consists of registry, image name and tag.
@ -194,14 +194,20 @@ func DerivedImage(root, registry string) (image string, err error) {
// therefore derive the image tag from the defined registry and name.
// form: [registry]/[user]/[function]:latest
// example: quay.io/alice/my.function.name:latest
// Also nested namespaces should be supported:
// form: [registry]/[parent]/[user]/[function]:latest
// example: quay.io/project/alice/my.function.name:latest
registry = strings.Trim(registry, "/") // too defensive?
registryTokens := strings.Split(registry, "/")
if len(registryTokens) == 1 {
//namespace provided only 'alice'
image = DefaultRegistry + "/" + registry + "/" + f.Name
} else if len(registryTokens) == 2 {
} else if len(registryTokens) == 2 || len(registryTokens) == 3 {
// registry/namespace provided `quay.io/alice` or registry/parent-namespace/namespace provided `quay.io/project/alice`
image = registry + "/" + f.Name
} else {
err = fmt.Errorf("registry should be either 'namespace' or 'registry/namespace'")
} else if len(registryTokens) > 3 { // the name of the image is also provided `quay.io/alice/my.function.name`
err = fmt.Errorf("registry should be either 'namespace', 'registry/namespace' or 'registry/parent/namespace', the name of the image will be derived from the function name.")
return
}
// Explicitly append :latest. We currently expect source control to drive