diff options
author | Martin Polden <mpolden@mpolden.no> | 2023-05-19 18:36:45 +0200 |
---|---|---|
committer | Martin Polden <mpolden@mpolden.no> | 2023-05-22 09:29:43 +0200 |
commit | 0dd0d8b634fc14a1762cbe9595174694d27beec3 (patch) | |
tree | a1f0bcf432dfdcce969ad3ed81bcf894cfa4caad /client/go/internal/cli/cmd | |
parent | 531e4093e0a06c2868ec702c7a0a9235ad54a2c6 (diff) |
Resolve target based on URL
Diffstat (limited to 'client/go/internal/cli/cmd')
-rw-r--r-- | client/go/internal/cli/cmd/api_key.go | 4 | ||||
-rw-r--r-- | client/go/internal/cli/cmd/cert.go | 10 | ||||
-rw-r--r-- | client/go/internal/cli/cmd/config.go | 2 | ||||
-rw-r--r-- | client/go/internal/cli/cmd/config_test.go | 16 | ||||
-rw-r--r-- | client/go/internal/cli/cmd/login.go | 4 | ||||
-rw-r--r-- | client/go/internal/cli/cmd/logout.go | 4 | ||||
-rw-r--r-- | client/go/internal/cli/cmd/root.go | 66 |
7 files changed, 78 insertions, 28 deletions
diff --git a/client/go/internal/cli/cmd/api_key.go b/client/go/internal/cli/cmd/api_key.go index 367a515f3c3..8b3780ab82b 100644 --- a/client/go/internal/cli/cmd/api_key.go +++ b/client/go/internal/cli/cmd/api_key.go @@ -58,11 +58,11 @@ func doApiKey(cli *CLI, overwriteKey bool, args []string) error { if err != nil { return err } - targetType, err := cli.config.targetType() + targetType, err := cli.targetType() if err != nil { return err } - system, err := cli.system(targetType) + system, err := cli.system(targetType.name) if err != nil { return err } diff --git a/client/go/internal/cli/cmd/cert.go b/client/go/internal/cli/cmd/cert.go index 48bad974c3f..95206b7e77d 100644 --- a/client/go/internal/cli/cmd/cert.go +++ b/client/go/internal/cli/cmd/cert.go @@ -107,15 +107,15 @@ func doCert(cli *CLI, overwriteCertificate, noApplicationPackage bool, args []st return err } } - targetType, err := cli.config.targetType() + targetType, err := cli.targetType() if err != nil { return err } - privateKeyFile, err := cli.config.privateKeyPath(app, targetType) + privateKeyFile, err := cli.config.privateKeyPath(app, targetType.name) if err != nil { return err } - certificateFile, err := cli.config.certificatePath(app, targetType) + certificateFile, err := cli.config.certificatePath(app, targetType.name) if err != nil { return err } @@ -178,11 +178,11 @@ func doCertAdd(cli *CLI, overwriteCertificate bool, args []string) error { if err != nil { return err } - targetType, err := cli.config.targetType() + targetType, err := cli.targetType() if err != nil { return err } - certificateFile, err := cli.config.certificatePath(app, targetType) + certificateFile, err := cli.config.certificatePath(app, targetType.name) if err != nil { return err } diff --git a/client/go/internal/cli/cmd/config.go b/client/go/internal/cli/cmd/config.go index e2132814386..0e120546c8b 100644 --- a/client/go/internal/cli/cmd/config.go +++ b/client/go/internal/cli/cmd/config.go @@ -329,7 +329,7 @@ func (c *Config) write() error { return c.config.WriteFile(configFile) } -func (c *Config) targetType() (string, error) { +func (c *Config) targetOrURL() (string, error) { targetType, ok := c.get(targetFlag) if !ok { return "", fmt.Errorf("target is unset") diff --git a/client/go/internal/cli/cmd/config_test.go b/client/go/internal/cli/cmd/config_test.go index 66b65bf402b..3a81b93ea0d 100644 --- a/client/go/internal/cli/cmd/config_test.go +++ b/client/go/internal/cli/cmd/config_test.go @@ -261,6 +261,22 @@ func TestConfigReadTLSOptions(t *testing.T) { ) } +func TestConfigTargetResolving(t *testing.T) { + cli, _, _ := newTestCLI(t) + require.Nil(t, cli.Run("config", "set", "target", "https://example.com")) + assertTargetType(t, vespa.TargetCustom, cli) + require.Nil(t, cli.Run("config", "set", "target", "https://foo.bar.vespa-team.no-north-1.dev.z.vespa-app.cloud")) + assertTargetType(t, vespa.TargetCloud, cli) + require.Nil(t, cli.Run("config", "set", "target", "https://foo.bar.vespa-team.no-north-1.dev.z.vespa.oath.cloud:4443")) + assertTargetType(t, vespa.TargetHosted, cli) +} + +func assertTargetType(t *testing.T, expected string, cli *CLI) { + targetType, err := cli.targetType() + require.Nil(t, err) + assert.Equal(t, expected, targetType.name) +} + func assertTLSOptions(t *testing.T, homeDir string, app vespa.ApplicationID, target string, want vespa.TLSOptions, envVars ...string) { t.Helper() envVars = append(envVars, "VESPA_CLI_HOME="+homeDir) diff --git a/client/go/internal/cli/cmd/login.go b/client/go/internal/cli/cmd/login.go index 9ac2262e78d..d2075bdfcf0 100644 --- a/client/go/internal/cli/cmd/login.go +++ b/client/go/internal/cli/cmd/login.go @@ -27,11 +27,11 @@ func newLoginCmd(cli *CLI) *cobra.Command { SilenceUsage: true, RunE: func(cmd *cobra.Command, args []string) error { ctx := cmd.Context() - targetType, err := cli.config.targetType() + targetType, err := cli.targetType() if err != nil { return err } - system, err := cli.system(targetType) + system, err := cli.system(targetType.name) if err != nil { return err } diff --git a/client/go/internal/cli/cmd/logout.go b/client/go/internal/cli/cmd/logout.go index 32e7cd9783b..93f7cb6270f 100644 --- a/client/go/internal/cli/cmd/logout.go +++ b/client/go/internal/cli/cmd/logout.go @@ -14,11 +14,11 @@ func newLogoutCmd(cli *CLI) *cobra.Command { DisableAutoGenTag: true, SilenceUsage: true, RunE: func(cmd *cobra.Command, args []string) error { - targetType, err := cli.config.targetType() + targetType, err := cli.targetType() if err != nil { return err } - system, err := cli.system(targetType) + system, err := cli.system(targetType.name) if err != nil { return err } diff --git a/client/go/internal/cli/cmd/root.go b/client/go/internal/cli/cmd/root.go index c4012024426..17c4fc41625 100644 --- a/client/go/internal/cli/cmd/root.go +++ b/client/go/internal/cli/cmd/root.go @@ -6,6 +6,7 @@ import ( "fmt" "io" "log" + "net/url" "os" "os/exec" "strings" @@ -73,6 +74,11 @@ type targetOptions struct { noCertificate bool } +type targetType struct { + name string + url string +} + // errHint creates a new CLI error, with optional hints that will be printed after the error func errHint(err error, hints ...string) ErrCLI { return ErrCLI{Status: 1, hints: hints, error: err} } @@ -297,7 +303,19 @@ func (c *CLI) printWarning(msg interface{}, hints ...string) { // target creates a target according the configuration of this CLI and given opts. func (c *CLI) target(opts targetOptions) (vespa.Target, error) { - target, err := c.createTarget(opts) + targetType, err := c.targetType() + if err != nil { + return nil, err + } + var target vespa.Target + switch targetType.name { + case vespa.TargetLocal, vespa.TargetCustom: + target, err = c.createCustomTarget(targetType.name, targetType.url) + case vespa.TargetCloud, vespa.TargetHosted: + target, err = c.createCloudTarget(targetType.name, opts, targetType.url) + default: + return nil, errHint(fmt.Errorf("invalid target: %s", targetType), "Valid targets are 'local', 'cloud', 'hosted' or an URL") + } if err != nil { return nil, err } @@ -309,24 +327,39 @@ func (c *CLI) target(opts targetOptions) (vespa.Target, error) { return target, nil } -func (c *CLI) createTarget(opts targetOptions) (vespa.Target, error) { - targetType, err := c.config.targetType() +// targetType resolves the real target type and its custom URL (if any) +func (c *CLI) targetType() (targetType, error) { + v, err := c.config.targetOrURL() if err != nil { - return nil, err + return targetType{}, err } - customURL := "" - if strings.HasPrefix(targetType, "http") { - customURL = targetType - targetType = vespa.TargetCustom + tt := targetType{name: v} + if strings.HasPrefix(tt.name, "http://") || strings.HasPrefix(tt.name, "https://") { + tt.url = tt.name + tt.name, err = c.targetFromURL(tt.url) + if err != nil { + return targetType{}, err + } } - switch targetType { - case vespa.TargetLocal, vespa.TargetCustom: - return c.createCustomTarget(targetType, customURL) - case vespa.TargetCloud, vespa.TargetHosted: - return c.createCloudTarget(targetType, opts) - default: - return nil, errHint(fmt.Errorf("invalid target: %s", targetType), "Valid targets are 'local', 'cloud', 'hosted' or an URL") + return tt, nil +} + +func (c *CLI) targetFromURL(customURL string) (string, error) { + u, err := url.Parse(customURL) + if err != nil { + return "", err + } + // Check if URL belongs to a cloud target + for _, cloudTarget := range []string{vespa.TargetHosted, vespa.TargetCloud} { + system, err := c.system(cloudTarget) + if err != nil { + return "", err + } + if strings.HasSuffix(u.Hostname(), "."+system.EndpointDomain) { + return cloudTarget, nil + } } + return vespa.TargetCustom, nil } func (c *CLI) createCustomTarget(targetType, customURL string) (vespa.Target, error) { @@ -344,7 +377,7 @@ func (c *CLI) createCustomTarget(targetType, customURL string) (vespa.Target, er } } -func (c *CLI) createCloudTarget(targetType string, opts targetOptions) (vespa.Target, error) { +func (c *CLI) createCloudTarget(targetType string, opts targetOptions, customURL string) (vespa.Target, error) { system, err := c.system(targetType) if err != nil { return nil, err @@ -409,6 +442,7 @@ func (c *CLI) createCloudTarget(targetType string, opts targetOptions) (vespa.Ta deploymentOptions := vespa.CloudDeploymentOptions{ Deployment: deployment, TLSOptions: deploymentTLSOptions, + CustomURL: customURL, ClusterURLs: endpoints, } logLevel := opts.logLevel |