summaryrefslogtreecommitdiffstats
path: root/client/go/cmd/helpers.go
diff options
context:
space:
mode:
Diffstat (limited to 'client/go/cmd/helpers.go')
-rw-r--r--client/go/cmd/helpers.go199
1 files changed, 123 insertions, 76 deletions
diff --git a/client/go/cmd/helpers.go b/client/go/cmd/helpers.go
index 547126a8156..ab47a0e6d88 100644
--- a/client/go/cmd/helpers.go
+++ b/client/go/cmd/helpers.go
@@ -5,6 +5,8 @@
package cmd
import (
+ "crypto/tls"
+ "crypto/x509"
"encoding/json"
"fmt"
"log"
@@ -29,6 +31,40 @@ func printSuccess(msg ...interface{}) {
log.Print(color.Green("Success: "), fmt.Sprint(msg...))
}
+func athenzPath(filename string) (string, error) {
+ userHome, err := os.UserHomeDir()
+ if err != nil {
+ return "", err
+ }
+ return filepath.Join(userHome, ".athenz", filename), nil
+}
+
+func athenzKeyPair() (tls.Certificate, error) {
+ certFile, err := athenzPath("cert")
+ if err != nil {
+ return tls.Certificate{}, err
+ }
+ keyFile, err := athenzPath("key")
+ if err != nil {
+ return tls.Certificate{}, err
+ }
+ kp, err := tls.LoadX509KeyPair(certFile, keyFile)
+ if err != nil {
+ return tls.Certificate{}, err
+ }
+ cert, err := x509.ParseCertificate(kp.Certificate[0])
+ if err != nil {
+ return tls.Certificate{}, err
+ }
+ now := time.Now()
+ expiredAt := cert.NotAfter
+ if expiredAt.Before(now) {
+ delta := now.Sub(expiredAt).Truncate(time.Second)
+ return tls.Certificate{}, errHint(fmt.Errorf("certificate %s expired at %s (%s ago)", certFile, cert.NotAfter, delta), "Try renewing certificate with 'athenz-user-cert'")
+ }
+ return kp, nil
+}
+
func vespaCliHome() (string, error) {
home := os.Getenv("VESPA_CLI_HOME")
if home == "" {
@@ -59,16 +95,20 @@ func vespaCliCacheDir() (string, error) {
return cacheDir, nil
}
-func deploymentFromArgs() (vespa.Deployment, error) {
- zone, err := vespa.ZoneFromString(zoneArg)
- if err != nil {
- return vespa.Deployment{}, err
+func deploymentFromArgs(system vespa.System) (vespa.Deployment, error) {
+ zone := system.DefaultZone
+ var err error
+ if zoneArg != "" {
+ zone, err = vespa.ZoneFromString(zoneArg)
+ if err != nil {
+ return vespa.Deployment{}, err
+ }
}
app, err := getApplication()
if err != nil {
return vespa.Deployment{}, err
}
- return vespa.Deployment{Application: app, Zone: zone}, nil
+ return vespa.Deployment{System: system, Application: app, Zone: zone}, nil
}
func applicationSource(args []string) string {
@@ -124,28 +164,18 @@ func getService(service string, sessionOrRunID int64, cluster string) (*vespa.Se
func getEndpointsOverride() string { return os.Getenv("VESPA_CLI_ENDPOINTS") }
-func getSystem() string { return os.Getenv("VESPA_CLI_CLOUD_SYSTEM") }
-
-func getSystemName() string {
- if getSystem() == "publiccd" {
- return "publiccd"
+func getSystem(targetType string) (vespa.System, error) {
+ name := os.Getenv("VESPA_CLI_CLOUD_SYSTEM")
+ if name != "" {
+ return vespa.GetSystem(name)
}
- return "public"
-}
-
-func getConsoleURL() string {
- if getSystem() == "publiccd" {
- return "https://console-cd.vespa.oath.cloud"
- }
- return "https://console.vespa.oath.cloud"
-
-}
-
-func getApiURL() string {
- if getSystem() == "publiccd" {
- return "https://api.vespa-external-cd.aws.oath.cloud:4443"
+ switch targetType {
+ case vespa.TargetHosted:
+ return vespa.MainSystem, nil
+ case vespa.TargetCloud:
+ return vespa.PublicSystem, nil
}
- return "https://api.vespa-external.aws.oath.cloud:4443"
+ return vespa.System{}, fmt.Errorf("no default system found for %s target", targetType)
}
func getTarget() (vespa.Target, error) {
@@ -172,53 +202,80 @@ func createTarget() (vespa.Target, error) {
return vespa.CustomTarget(targetType), nil
}
switch targetType {
- case "local":
+ case vespa.TargetLocal:
return vespa.LocalTarget(), nil
- case "cloud":
- cfg, err := LoadConfig()
- if err != nil {
- return nil, err
- }
- deployment, err := deploymentFromArgs()
- if err != nil {
- return nil, err
- }
- endpoints, err := getEndpointsFromEnv()
- if err != nil {
- return nil, err
- }
+ case vespa.TargetCloud, vespa.TargetHosted:
+ return createCloudTarget(targetType)
+ }
+ return nil, errHint(fmt.Errorf("invalid target: %s", targetType), "Valid targets are 'local', 'cloud', 'hosted' or an URL")
+}
- var apiKey []byte = nil
- if cfg.UseAPIKey(deployment.Application.Tenant) {
+func createCloudTarget(targetType string) (vespa.Target, error) {
+ cfg, err := LoadConfig()
+ if err != nil {
+ return nil, err
+ }
+ system, err := getSystem(targetType)
+ if err != nil {
+ return nil, err
+ }
+ deployment, err := deploymentFromArgs(system)
+ if err != nil {
+ return nil, err
+ }
+ endpoints, err := getEndpointsFromEnv()
+ if err != nil {
+ return nil, err
+ }
+ var (
+ apiKey []byte
+ authConfigPath string
+ apiTLSOptions vespa.TLSOptions
+ deploymentTLSOptions vespa.TLSOptions
+ )
+ if targetType == vespa.TargetCloud {
+ if cfg.UseAPIKey(system, deployment.Application.Tenant) {
apiKey, err = cfg.ReadAPIKey(deployment.Application.Tenant)
if err != nil {
return nil, err
}
}
+ authConfigPath = cfg.AuthConfigPath()
kp, err := cfg.X509KeyPair(deployment.Application)
if err != nil {
return nil, errHint(err, "Deployment to cloud requires a certificate. Try 'vespa auth cert'")
}
-
- return vespa.CloudTarget(
- getApiURL(),
- deployment,
- apiKey,
- vespa.TLSOptions{
- KeyPair: kp.KeyPair,
- CertificateFile: kp.CertificateFile,
- PrivateKeyFile: kp.PrivateKeyFile,
- },
- vespa.LogOptions{
- Writer: stdout,
- Level: vespa.LogLevel(logLevelArg),
- },
- cfg.AuthConfigPath(),
- getSystemName(),
- endpoints,
- ), nil
- }
- return nil, errHint(fmt.Errorf("invalid target: %s", targetType), "Valid targets are 'local', 'cloud' or an URL")
+ deploymentTLSOptions = vespa.TLSOptions{
+ KeyPair: kp.KeyPair,
+ CertificateFile: kp.CertificateFile,
+ PrivateKeyFile: kp.PrivateKeyFile,
+ }
+ } else if targetType == vespa.TargetHosted {
+ kp, err := athenzKeyPair()
+ if err != nil {
+ return nil, err
+ }
+ apiTLSOptions = vespa.TLSOptions{KeyPair: kp}
+ deploymentTLSOptions = apiTLSOptions
+ } else {
+ return nil, fmt.Errorf("invalid cloud target: %s", targetType)
+ }
+ apiOptions := vespa.APIOptions{
+ System: system,
+ TLSOptions: apiTLSOptions,
+ APIKey: apiKey,
+ AuthConfigPath: authConfigPath,
+ }
+ deploymentOptions := vespa.CloudDeploymentOptions{
+ Deployment: deployment,
+ TLSOptions: deploymentTLSOptions,
+ ClusterURLs: endpoints,
+ }
+ logOptions := vespa.LogOptions{
+ Writer: stdout,
+ Level: vespa.LogLevel(logLevelArg),
+ }
+ return vespa.CloudTarget(apiOptions, deploymentOptions, logOptions)
}
func waitForService(service string, sessionOrRunID int64) error {
@@ -242,25 +299,15 @@ func waitForService(service string, sessionOrRunID int64) error {
return nil
}
-func getDeploymentOpts(cfg *Config, pkg vespa.ApplicationPackage, target vespa.Target) (vespa.DeploymentOpts, error) {
- opts := vespa.DeploymentOpts{ApplicationPackage: pkg, Target: target}
+func getDeploymentOptions(cfg *Config, pkg vespa.ApplicationPackage, target vespa.Target) (vespa.DeploymentOptions, error) {
+ opts := vespa.DeploymentOptions{ApplicationPackage: pkg, Target: target}
if opts.IsCloud() {
- deployment, err := deploymentFromArgs()
- if err != nil {
- return vespa.DeploymentOpts{}, err
- }
- if !opts.ApplicationPackage.HasCertificate() {
+ if target.Type() == vespa.TargetCloud && !opts.ApplicationPackage.HasCertificate() {
hint := "Try 'vespa auth cert'"
- return vespa.DeploymentOpts{}, errHint(fmt.Errorf("missing certificate in application package"), "Applications in Vespa Cloud require a certificate", hint)
- }
- if cfg.UseAPIKey(deployment.Application.Tenant) {
- opts.APIKey, err = cfg.ReadAPIKey(deployment.Application.Tenant)
- if err != nil {
- return vespa.DeploymentOpts{}, err
- }
+ return vespa.DeploymentOptions{}, errHint(fmt.Errorf("missing certificate in application package"), "Applications in Vespa Cloud require a certificate", hint)
}
- opts.Deployment = deployment
}
+ opts.Timeout = time.Duration(waitSecsArg) * time.Second
return opts, nil
}