Skip to content

Commit

Permalink
feat: func domain route
Browse files Browse the repository at this point in the history
Adds the --domain flag which, when provided sets the value of the
func.domain label on the deployed knative service.  The cluster can then
use this to choose which route to create for multi-route clusters.
Optional.
  • Loading branch information
lkingland committed Apr 25, 2023
1 parent 506cb71 commit 8e04b97
Show file tree
Hide file tree
Showing 4 changed files with 88 additions and 7 deletions.
64 changes: 57 additions & 7 deletions cmd/deploy.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ SYNOPSIS
{{rootCmdUse}} deploy [-R|--remote] [-r|--registry] [-i|--image] [-n|--namespace]
[-e|env] [-g|--git-url] [-t|git-branch] [-d|--git-dir]
[-b|--build] [--builder] [--builder-image] [-p|--push]
[--platform] [-c|--confirm] [-v|--verbose]
[--domain] [--platform] [-c|--confirm] [-v|--verbose]
DESCRIPTION
Expand Down Expand Up @@ -76,6 +76,14 @@ DESCRIPTION
of a git repository instead of local source, combine with '--git-url':
'{{rootCmdUse}} deploy --remote --git-url=git.example.com/alice/f.git'
Domain
When deploying, a function's route is automatically generated using the
default domain with which the target platform has been configured. The
optional flag --domain can be used to choose this domain explicitly for
clusters which have been configured with support for function domain
selectors. Note that the domain specified must be one of those configured
or the flag will be ignored.
EXAMPLES
o Deploy the function
Expand Down Expand Up @@ -116,7 +124,7 @@ EXAMPLES
`,
SuggestFor: []string{"delpoy", "deplyo"},
PreRunE: bindEnv("confirm", "env", "git-url", "git-branch", "git-dir", "remote", "build", "builder", "builder-image", "image", "registry", "push", "platform", "namespace", "path", "verbose", "pvc-size"),
PreRunE: bindEnv("build", "builder", "builder-image", "confirm", "domain", "env", "git-branch", "git-dir", "git-url", "image", "namespace", "path", "platform", "push", "pvc-size", "registry", "remote", "verbose"),
RunE: func(cmd *cobra.Command, args []string) error {
return runDeploy(cmd, newClient)
},
Expand Down Expand Up @@ -152,11 +160,15 @@ EXAMPLES
builderImage := f.Build.BuilderImages[f.Build.Builder]
cmd.Flags().String("builder-image", builderImage,
"Specify a custom builder image for use by the builder other than its default. ($FUNC_BUILDER_IMAGE)")
cmd.Flags().StringP("image", "i", f.Image, "Full image name in the form [registry]/[namespace]/[name]:[tag]@[digest]. This option takes precedence over --registry. Specifying digest is optional, but if it is given, 'build' and 'push' phases are disabled. (Env: $FUNC_IMAGE)")

cmd.Flags().StringArrayP("env", "e", []string{}, "Environment variable to set in the form NAME=VALUE. "+
"You may provide this flag multiple times for setting multiple environment variables. "+
"To unset, specify the environment variable name followed by a \"-\" (e.g., NAME-).")
cmd.Flags().StringP("image", "i", f.Image,
"Full image name in the form [registry]/[namespace]/[name]:[tag]@[digest]. This option takes precedence over --registry. Specifying digest is optional, but if it is given, 'build' and 'push' phases are disabled. ($FUNC_IMAGE)")

cmd.Flags().StringArrayP("env", "e", []string{},
"Environment variable to set in the form NAME=VALUE. "+
"You may provide this flag multiple times for setting multiple environment variables. "+
"To unset, specify the environment variable name followed by a \"-\" (e.g., NAME-).")
cmd.Flags().String("domain", f.Domain,
"Domain to use for the function's route. Cluster must be configured with domain matching for the given domain (ignored if unrecognized) ($FUNC_DOMAIN)")
cmd.Flags().StringP("git-url", "g", f.Build.Git.URL,
"Repository url containing the function to build (Env: $FUNC_GIT_URL)")
cmd.Flags().StringP("git-branch", "t", f.Build.Git.Revision,
Expand Down Expand Up @@ -351,6 +363,42 @@ type deployConfig struct {
// Env variables. May include removals using a "-"
Env []string

// Domain to use for the function's route. Default is to let the cluster
// apply its default. If configured to use domain matching, the given domain
// will be used. This configuration, in short, is to configure the
// cluster's config-domain map to match on the `func.domain` label and use
// its value as the domain... presuming it is one of those explicitly
// enumerated. This allows a function to be deployed explicitly choosing
// a route from one of the domains in a cluster with multiple configured
// domains. Example:
// func create -l go hello && func deploy --domain domain2.org
// -> Func created as hello.[namespace].domain2.org
// This can also be useful to configure a cluster to deploy functions at
// the domain root when requested, but only be cluster-local (unexposed) by
// default. This is accomplished by configuring the cluster-domain map to
// have the domain "cluster.local" as the default (empty selector), and
// the domain map template to omit the namespace interstitial.
// Example:
// func create -l go myclusterservice && func deploy
// -> func creates myclusterservice.cluster.local which is not exposed
// publicly outside the cluster
// func create -l go www && func deploy --domain example.com
// -> func deploys www.example.com as a publicly exposed service.
// TODO: allow for a simplified syntax of simply using the function's name
// as its route, and automatically parse off the domain suffix and validate
// the prefix is a dns label (ideally even validating the domain suffix is
// currently available and configured on the cluster).
// Example:
// func create -l go www.example.com
// -> func creates service www, with label func.domain as example.com, which
// is one which the cluster has configured to server, so it is deployed with
// a publicly accessible route
// -> func create -l go myclusterservice.cluster.local
// is equivalent to `func create -l go myclusterservice`
// All func commands which operate on function name now instead can use
// the FWDN. Example `func delete www.example.com`
Domain string

// Git branch for remote builds
GitBranch string

Expand Down Expand Up @@ -383,6 +431,7 @@ func newDeployConfig(cmd *cobra.Command) (c deployConfig) {
buildConfig: newBuildConfig(),
Build: viper.GetString("build"),
Env: viper.GetStringSlice("env"),
Domain: viper.GetString("domain"),
GitBranch: viper.GetString("git-branch"),
GitDir: viper.GetString("git-dir"),
GitURL: viper.GetString("git-url"),
Expand Down Expand Up @@ -415,6 +464,7 @@ func (c deployConfig) Configure(f fn.Function) (fn.Function, error) {
f = c.buildConfig.Configure(f) // also configures .buildConfig.Global

// Configure basic members
f.Domain = c.Domain
f.Build.Git.URL = c.GitURL
f.Build.Git.ContextDir = c.GitDir
f.Build.Git.Revision = c.GitBranch // TODO: should match; perhaps "refSpec"
Expand Down
22 changes: 22 additions & 0 deletions pkg/functions/function.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,28 @@ type Function struct {
// Name of the function.
Name string `yaml:"name,omitempty" jsonschema:"pattern=^[a-z0-9]([-a-z0-9]*[a-z0-9])?$"`

// Domain of the function optionally specifies the domain to use as the
// route of the function. By default the cluster's default will be used.
// Note that the value defined here must be one which the cluster is
// configured to recognize, or this will have no effect and the cluster
// default will be applied. This value shuld therefore ideally be
// validated by the client.
//
// Matching a valid domain name using a regular expression can be quite
// complex, as there are many rules for domain names. However, below uses
// a simplified regular expression that matches most common domain names:
//
// 1 can contain letters (a-z, A-Z), digits (0-9), and hyphens (-).
// 2 cannot start or end with a hyphen.
// 3 Domain name components can be up to 63 characters long.
// 4 The top-level domain (TLD) should have at least two letters and max six.
//
// This regular expression doesn't cover all possible domain names, as there
// are more complex rules regarding internationalized domain names (IDNs) and
// new top-level domains (TLDs). Additionally, it does not validate against
// the list of known TLDs. However, it should work for most common domains.
Domain string `yaml:"domain,omitempty" jsonschema:"pattern=\"^(?:(?:[a-zA-Z0-9](?:[a-zA-Z0-9\\-]{0,61}[a-zA-Z0-9])?\\.)+[a-zA-Z]{2,6}\\.?|[a-zA-Z0-9\\-]+\\.([a-zA-Z]{2,}\\.?))$\""`

// Runtime is the language plus context. nodejs|go|quarkus|rust etc.
Runtime string `yaml:"runtime,omitempty"`

Expand Down
4 changes: 4 additions & 0 deletions pkg/knative/deployer.go
Original file line number Diff line number Diff line change
Expand Up @@ -391,6 +391,10 @@ func generateServiceLabels(f fn.Function, d DeployDecorator) (ll map[string]stri
return
}

if f.Domain != "" {
ll["func.domain"] = f.Domain
}

if d != nil {
ll = d.UpdateLabels(f, ll)
}
Expand Down
5 changes: 5 additions & 0 deletions schema/func_yaml-schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@
"Function": {
"required": [
"specVersion",
"domain",
"registry",
"image",
"created"
Expand All @@ -122,6 +123,10 @@
"type": "string",
"description": "Name of the function."
},
"domain": {
"type": "string",
"description": "Domain of the function optionally specifies the domain to use as the\nroute of the function. By default the cluster's default will be used.\nNote that the value defined here must be one which the cluster is\nconfigured to recognize, or this will have no effect and the cluster\ndefault will be applied. This value shuld therefore ideally be\nvalidated by the client.\n\nMatching a valid domain name using a regular expression can be quite\ncomplex, as there are many rules for domain names. However, below uses\na simplified regular expression that matches most common domain names:\n\n 1 can contain letters (a-z, A-Z), digits (0-9), and hyphens (-).\n 2 cannot start or end with a hyphen.\n 3 Domain name components can be up to 63 characters long.\n 4 The top-level domain (TLD) should have at least two letters and max six.\n\nThis regular expression doesn't cover all possible domain names, as there\nare more complex rules regarding internationalized domain names (IDNs) and\nnew top-level domains (TLDs). Additionally, it does not validate against\nthe list of known TLDs. However, it should work for most common domains."
},
"runtime": {
"type": "string",
"description": "Runtime is the language plus context. nodejs|go|quarkus|rust etc."
Expand Down

0 comments on commit 8e04b97

Please sign in to comment.