aboutsummaryrefslogtreecommitdiffstats
path: root/client
diff options
context:
space:
mode:
authorMartin Polden <mpolden@mpolden.no>2021-09-10 08:39:08 +0200
committerMartin Polden <mpolden@mpolden.no>2021-09-10 13:01:21 +0200
commit752bfd9eb3750383470013b146ae7afbcd972f30 (patch)
tree2d491f61696df85a8b754ce295b3d9ea559116ba /client
parent0f5f6a0bfa998c476db66c2c9dae39441810c4b9 (diff)
Refactor configuration
Diffstat (limited to 'client')
-rw-r--r--client/go/cmd/api_key.go12
-rw-r--r--client/go/cmd/api_key_test.go8
-rw-r--r--client/go/cmd/cert.go24
-rw-r--r--client/go/cmd/cert_test.go17
-rw-r--r--client/go/cmd/command_tester.go12
-rw-r--r--client/go/cmd/config.go162
-rw-r--r--client/go/cmd/config_test.go34
-rw-r--r--client/go/cmd/deploy.go61
-rw-r--r--client/go/cmd/deploy_test.go11
-rw-r--r--client/go/cmd/helpers.go48
-rw-r--r--client/go/cmd/root.go1
-rw-r--r--client/go/vespa/deploy.go2
12 files changed, 233 insertions, 159 deletions
diff --git a/client/go/cmd/api_key.go b/client/go/cmd/api_key.go
index c94faa0d5e3..90cbdbc5bc1 100644
--- a/client/go/cmd/api_key.go
+++ b/client/go/cmd/api_key.go
@@ -7,7 +7,6 @@ import (
"fmt"
"io/ioutil"
"log"
- "path/filepath"
"github.com/spf13/cobra"
"github.com/vespa-engine/vespa/client/go/util"
@@ -29,16 +28,17 @@ var apiKeyCmd = &cobra.Command{
DisableAutoGenTag: true,
Args: cobra.ExactArgs(0),
Run: func(cmd *cobra.Command, args []string) {
- configDir := configDir("")
- if configDir == "" {
- return
- }
app, err := vespa.ApplicationFromString(getApplication())
if err != nil {
fatalErr(err, "Could not parse application")
return
}
- apiKeyFile := filepath.Join(configDir, app.Tenant+".api-key.pem")
+ cfg, err := LoadConfig()
+ if err != nil {
+ fatalErr(err, "Could not load config")
+ return
+ }
+ apiKeyFile := cfg.APIKeyPath(app.Tenant)
if util.PathExists(apiKeyFile) && !overwriteKey {
printErrHint(fmt.Errorf("File %s already exists", apiKeyFile), "Use -f to overwrite it")
printPublicKey(apiKeyFile, app.Tenant)
diff --git a/client/go/cmd/api_key_test.go b/client/go/cmd/api_key_test.go
index 0e50fd6d669..c00f520aa25 100644
--- a/client/go/cmd/api_key_test.go
+++ b/client/go/cmd/api_key_test.go
@@ -11,13 +11,13 @@ import (
)
func TestAPIKey(t *testing.T) {
- configDir := t.TempDir()
- keyFile := configDir + "/.vespa/t1.api-key.pem"
+ homeDir := t.TempDir()
+ keyFile := homeDir + "/.vespa/t1.api-key.pem"
- out := execute(command{args: []string{"api-key", "-a", "t1.a1.i1"}, configDir: configDir}, t, nil)
+ out := execute(command{args: []string{"api-key", "-a", "t1.a1.i1"}, homeDir: homeDir}, t, nil)
assert.True(t, strings.HasPrefix(out, "Success: API private key written to "+keyFile+"\n"))
- out = execute(command{args: []string{"api-key", "-a", "t1.a1.i1"}, configDir: configDir}, t, nil)
+ out = execute(command{args: []string{"api-key", "-a", "t1.a1.i1"}, homeDir: homeDir}, t, nil)
assert.True(t, strings.HasPrefix(out, "Error: File "+keyFile+" already exists\nHint: Use -f to overwrite it\n"))
assert.True(t, strings.Contains(out, "This is your public key"))
}
diff --git a/client/go/cmd/cert.go b/client/go/cmd/cert.go
index e1e11b6f73e..078c0704f9d 100644
--- a/client/go/cmd/cert.go
+++ b/client/go/cmd/cert.go
@@ -28,20 +28,34 @@ var certCmd = &cobra.Command{
DisableAutoGenTag: true,
Args: cobra.MaximumNArgs(1),
Run: func(cmd *cobra.Command, args []string) {
- app := getApplication()
+ app, err := vespa.ApplicationFromString(getApplication())
+ if err != nil {
+ fatalErr(err)
+ return
+ }
pkg, err := vespa.ApplicationPackageFrom(applicationSource(args))
if err != nil {
fatalErr(err)
return
}
- configDir := configDir(app)
- if configDir == "" {
+ cfg, err := LoadConfig()
+ if err != nil {
+ fatalErr(err)
return
}
securityDir := filepath.Join(pkg.Path, "security")
pkgCertificateFile := filepath.Join(securityDir, "clients.pem")
- privateKeyFile := filepath.Join(configDir, "data-plane-private-key.pem")
- certificateFile := filepath.Join(configDir, "data-plane-public-cert.pem")
+ privateKeyFile, err := cfg.PrivateKeyPath(app)
+ if err != nil {
+ fatalErr(err)
+ return
+ }
+ certificateFile, err := cfg.CertificatePath(app)
+ if err != nil {
+ fatalErr(err)
+ return
+ }
+
if !overwriteCertificate {
for _, file := range []string{pkgCertificateFile, privateKeyFile, certificateFile} {
if util.PathExists(file) {
diff --git a/client/go/cmd/cert_test.go b/client/go/cmd/cert_test.go
index e655f76b0f1..174b5fe5e9d 100644
--- a/client/go/cmd/cert_test.go
+++ b/client/go/cmd/cert_test.go
@@ -11,20 +11,23 @@ import (
"testing"
"github.com/stretchr/testify/assert"
+ "github.com/vespa-engine/vespa/client/go/vespa"
)
func TestCert(t *testing.T) {
- tmpDir := t.TempDir()
- mockApplicationPackage(t, tmpDir)
- out := execute(command{args: []string{"cert", "-a", "t1.a1.i1", tmpDir}, configDir: tmpDir}, t, nil)
+ homeDir := t.TempDir()
+ mockApplicationPackage(t, homeDir)
+ out := execute(command{args: []string{"cert", "-a", "t1.a1.i1", homeDir}, homeDir: homeDir}, t, nil)
- pkgCertificate := filepath.Join(tmpDir, "security", "clients.pem")
- certificate := filepath.Join(tmpDir, ".vespa", "t1.a1.i1", "data-plane-public-cert.pem")
- privateKey := filepath.Join(tmpDir, ".vespa", "t1.a1.i1", "data-plane-private-key.pem")
+ app, err := vespa.ApplicationFromString("t1.a1.i1")
+ assert.Nil(t, err)
+ pkgCertificate := filepath.Join(homeDir, "security", "clients.pem")
+ certificate := filepath.Join(homeDir, ".vespa", app.String(), "data-plane-public-cert.pem")
+ privateKey := filepath.Join(homeDir, ".vespa", app.String(), "data-plane-private-key.pem")
assert.Equal(t, fmt.Sprintf("Success: Certificate written to %s\nSuccess: Certificate written to %s\nSuccess: Private key written to %s\n", pkgCertificate, certificate, privateKey), out)
- out = execute(command{args: []string{"cert", "-a", "t1.a1.i1", tmpDir}, configDir: tmpDir}, t, nil)
+ out = execute(command{args: []string{"cert", "-a", "t1.a1.i1", homeDir}, homeDir: homeDir}, t, nil)
assert.True(t, strings.HasPrefix(out, "Error: Certificate or private key"))
}
diff --git a/client/go/cmd/command_tester.go b/client/go/cmd/command_tester.go
index 42befbfb795..095a1af7ac3 100644
--- a/client/go/cmd/command_tester.go
+++ b/client/go/cmd/command_tester.go
@@ -24,9 +24,9 @@ import (
)
type command struct {
- configDir string
- args []string
- moreArgs []string
+ homeDir string
+ args []string
+ moreArgs []string
}
func execute(cmd command, t *testing.T, client *mockHttpClient) string {
@@ -38,11 +38,11 @@ func execute(cmd command, t *testing.T, client *mockHttpClient) string {
color = aurora.NewAurora(false)
// Set config dir. Use a separate one per test if none is specified
- if cmd.configDir == "" {
- cmd.configDir = t.TempDir()
+ if cmd.homeDir == "" {
+ cmd.homeDir = t.TempDir()
viper.Reset()
}
- os.Setenv("VESPA_CLI_HOME", filepath.Join(cmd.configDir, ".vespa"))
+ os.Setenv("VESPA_CLI_HOME", filepath.Join(cmd.homeDir, ".vespa"))
// Reset flags to their default value - persistent flags in Cobra persists over tests
rootCmd.Flags().VisitAll(func(f *pflag.Flag) {
diff --git a/client/go/cmd/config.go b/client/go/cmd/config.go
index af62b2509d2..262f5d584b4 100644
--- a/client/go/cmd/config.go
+++ b/client/go/cmd/config.go
@@ -6,6 +6,7 @@ package cmd
import (
"fmt"
+ "io/ioutil"
"log"
"os"
"path/filepath"
@@ -49,10 +50,17 @@ var setConfigCmd = &cobra.Command{
DisableAutoGenTag: true,
Args: cobra.ExactArgs(2),
Run: func(cmd *cobra.Command, args []string) {
- if err := setOption(args[0], args[1]); err != nil {
- log.Print(err)
+ cfg, err := LoadConfig()
+ if err != nil {
+ fatalErr(err, "Could not load config")
+ return
+ }
+ if err := cfg.Set(args[0], args[1]); err != nil {
+ fatalErr(err)
} else {
- writeConfig()
+ if err := cfg.Write(); err != nil {
+ fatalErr(err)
+ }
}
},
}
@@ -64,70 +72,121 @@ var getConfigCmd = &cobra.Command{
Args: cobra.MaximumNArgs(1),
DisableAutoGenTag: true,
Run: func(cmd *cobra.Command, args []string) {
+ cfg, err := LoadConfig()
+ if err != nil {
+ fatalErr(err, "Could not load config")
+ return
+ }
+
if len(args) == 0 { // Print all values
- printOption(targetFlag)
- printOption(applicationFlag)
+ printOption(cfg, targetFlag)
+ printOption(cfg, applicationFlag)
} else {
- printOption(args[0])
+ printOption(cfg, args[0])
}
},
}
-func printOption(option string) {
- value, err := getOption(option)
- if err != nil {
- value = color.Faint("<unset>").String()
- } else {
- value = color.Cyan(value).String()
- }
- log.Printf("%s = %s", option, value)
+type Config struct {
+ Home string
+ createDirs bool
}
-func configDir(application string) string {
+func LoadConfig() (*Config, error) {
home := os.Getenv("VESPA_CLI_HOME")
if home == "" {
var err error
home, err = os.UserHomeDir()
if err != nil {
- fatalErr(err, "Could not determine configuration directory")
- return ""
+ return nil, err
}
home = filepath.Join(home, ".vespa")
}
- configDir := filepath.Join(home, application)
- if err := os.MkdirAll(configDir, 0755); err != nil {
- fatalErr(err, "Could not create config directory")
- return ""
+ if err := os.MkdirAll(home, 0700); err != nil {
+ return nil, err
}
- return configDir
+ c := &Config{Home: home, createDirs: true}
+ if err := c.load(); err != nil {
+ return nil, err
+ }
+ return c, nil
}
-func bindFlagToConfig(option string, command *cobra.Command) {
- flagToConfigBindings[option] = command
+func (c *Config) Write() error {
+ if err := os.MkdirAll(c.Home, 0700); err != nil {
+ return err
+ }
+ configFile := filepath.Join(c.Home, configName+"."+configType)
+ if !util.PathExists(configFile) {
+ if _, err := os.Create(configFile); err != nil {
+ return err
+ }
+ }
+ return viper.WriteConfig()
+}
+
+func (c *Config) CertificatePath(app vespa.ApplicationID) (string, error) {
+ return c.applicationFilePath(app, "data-plane-public-cert.pem")
+}
+
+func (c *Config) PrivateKeyPath(app vespa.ApplicationID) (string, error) {
+ return c.applicationFilePath(app, "data-plane-private-key.pem")
+}
+
+func (c *Config) APIKeyPath(tenantName string) string {
+ return filepath.Join(c.Home, tenantName+".api-key.pem")
+}
+
+func (c *Config) ReadAPIKey(tenantName string) ([]byte, error) {
+ return ioutil.ReadFile(c.APIKeyPath(tenantName))
}
-func readConfig() {
- configDir := configDir("")
- if configDir == "" {
- return
+func (c *Config) ReadSessionID(app vespa.ApplicationID) (int64, error) {
+ sessionPath, err := c.applicationFilePath(app, "session_id")
+ if err != nil {
+ return 0, err
+ }
+ b, err := ioutil.ReadFile(sessionPath)
+ if err != nil {
+ return 0, err
}
+ return strconv.ParseInt(strings.TrimSpace(string(b)), 10, 64)
+}
+
+func (c *Config) WriteSessionID(app vespa.ApplicationID, sessionID int64) error {
+ sessionPath, err := c.applicationFilePath(app, "session_id")
+ if err != nil {
+ return err
+ }
+ return ioutil.WriteFile(sessionPath, []byte(fmt.Sprintf("%d\n", sessionID)), 0600)
+}
+
+func (c *Config) applicationFilePath(app vespa.ApplicationID, name string) (string, error) {
+ appDir := filepath.Join(c.Home, app.String())
+ if c.createDirs {
+ if err := os.MkdirAll(appDir, 0700); err != nil {
+ return "", err
+ }
+ }
+ return filepath.Join(appDir, name), nil
+}
+
+func (c *Config) load() error {
viper.SetConfigName(configName)
viper.SetConfigType(configType)
- viper.AddConfigPath(configDir)
+ viper.AddConfigPath(c.Home)
viper.AutomaticEnv()
for option, command := range flagToConfigBindings {
viper.BindPFlag(option, command.PersistentFlags().Lookup(option))
}
err := viper.ReadInConfig()
if _, ok := err.(viper.ConfigFileNotFoundError); ok {
- return // Fine
- }
- if err != nil {
- fatalErr(err, "Could not read configuration")
+ return nil
}
+ return err
}
-func getOption(option string) (string, error) {
+func (c *Config) Get(option string) (string, error) {
value := viper.GetString(option)
if value == "" {
return "", fmt.Errorf("no such option: %q", option)
@@ -135,7 +194,7 @@ func getOption(option string) (string, error) {
return value, nil
}
-func setOption(option, value string) error {
+func (c *Config) Set(option, value string) error {
switch option {
case targetFlag:
switch value {
@@ -163,29 +222,16 @@ func setOption(option, value string) error {
return fmt.Errorf("invalid option or value: %q: %q", option, value)
}
-func writeConfig() {
- configDir := configDir("")
- if configDir == "" {
- return
- }
-
- if !util.PathExists(configDir) {
- if err := os.MkdirAll(configDir, 0700); err != nil {
- fatalErr(err, "Could not create ", color.Cyan(configDir))
- return
- }
- }
-
- configFile := filepath.Join(configDir, configName+"."+configType)
- if !util.PathExists(configFile) {
- if _, err := os.Create(configFile); err != nil {
- fatalErr(err, "Could not create ", color.Cyan(configFile))
- return
- }
+func printOption(cfg *Config, option string) {
+ value, err := cfg.Get(option)
+ if err != nil {
+ value = color.Faint("<unset>").String()
+ } else {
+ value = color.Cyan(value).String()
}
+ log.Printf("%s = %s", option, value)
+}
- if err := viper.WriteConfig(); err != nil {
- fatalErr(err, "Could not write config")
- return
- }
+func bindFlagToConfig(option string, command *cobra.Command) {
+ flagToConfigBindings[option] = command
}
diff --git a/client/go/cmd/config_test.go b/client/go/cmd/config_test.go
index dee63bcb58f..07d165d58e0 100644
--- a/client/go/cmd/config_test.go
+++ b/client/go/cmd/config_test.go
@@ -7,24 +7,24 @@ import (
)
func TestConfig(t *testing.T) {
- configDir := t.TempDir()
- assert.Equal(t, "invalid option or value: \"foo\": \"bar\"\n", execute(command{configDir: configDir, args: []string{"config", "set", "foo", "bar"}}, t, nil))
- assert.Equal(t, "foo = <unset>\n", execute(command{configDir: configDir, args: []string{"config", "get", "foo"}}, t, nil))
- assert.Equal(t, "target = local\n", execute(command{configDir: configDir, args: []string{"config", "get", "target"}}, t, nil))
- assert.Equal(t, "", execute(command{configDir: configDir, args: []string{"config", "set", "target", "cloud"}}, t, nil))
- assert.Equal(t, "target = cloud\n", execute(command{configDir: configDir, args: []string{"config", "get", "target"}}, t, nil))
- assert.Equal(t, "", execute(command{configDir: configDir, args: []string{"config", "set", "target", "http://127.0.0.1:8080"}}, t, nil))
- assert.Equal(t, "", execute(command{configDir: configDir, args: []string{"config", "set", "target", "https://127.0.0.1"}}, t, nil))
- assert.Equal(t, "target = https://127.0.0.1\n", execute(command{configDir: configDir, args: []string{"config", "get", "target"}}, t, nil))
+ homeDir := t.TempDir()
+ assert.Equal(t, "invalid option or value: \"foo\": \"bar\"\n", execute(command{homeDir: homeDir, args: []string{"config", "set", "foo", "bar"}}, t, nil))
+ assert.Equal(t, "foo = <unset>\n", execute(command{homeDir: homeDir, args: []string{"config", "get", "foo"}}, t, nil))
+ assert.Equal(t, "target = local\n", execute(command{homeDir: homeDir, args: []string{"config", "get", "target"}}, t, nil))
+ assert.Equal(t, "", execute(command{homeDir: homeDir, args: []string{"config", "set", "target", "cloud"}}, t, nil))
+ assert.Equal(t, "target = cloud\n", execute(command{homeDir: homeDir, args: []string{"config", "get", "target"}}, t, nil))
+ assert.Equal(t, "", execute(command{homeDir: homeDir, args: []string{"config", "set", "target", "http://127.0.0.1:8080"}}, t, nil))
+ assert.Equal(t, "", execute(command{homeDir: homeDir, args: []string{"config", "set", "target", "https://127.0.0.1"}}, t, nil))
+ assert.Equal(t, "target = https://127.0.0.1\n", execute(command{homeDir: homeDir, args: []string{"config", "get", "target"}}, t, nil))
- assert.Equal(t, "invalid application: \"foo\"\n", execute(command{configDir: configDir, args: []string{"config", "set", "application", "foo"}}, t, nil))
- assert.Equal(t, "application = <unset>\n", execute(command{configDir: configDir, args: []string{"config", "get", "application"}}, t, nil))
- assert.Equal(t, "", execute(command{configDir: configDir, args: []string{"config", "set", "application", "t1.a1.i1"}}, t, nil))
- assert.Equal(t, "application = t1.a1.i1\n", execute(command{configDir: configDir, args: []string{"config", "get", "application"}}, t, nil))
+ assert.Equal(t, "invalid application: \"foo\"\n", execute(command{homeDir: homeDir, args: []string{"config", "set", "application", "foo"}}, t, nil))
+ assert.Equal(t, "application = <unset>\n", execute(command{homeDir: homeDir, args: []string{"config", "get", "application"}}, t, nil))
+ assert.Equal(t, "", execute(command{homeDir: homeDir, args: []string{"config", "set", "application", "t1.a1.i1"}}, t, nil))
+ assert.Equal(t, "application = t1.a1.i1\n", execute(command{homeDir: homeDir, args: []string{"config", "get", "application"}}, t, nil))
- assert.Equal(t, "target = https://127.0.0.1\napplication = t1.a1.i1\n", execute(command{configDir: configDir, args: []string{"config", "get"}}, t, nil))
+ assert.Equal(t, "target = https://127.0.0.1\napplication = t1.a1.i1\n", execute(command{homeDir: homeDir, args: []string{"config", "get"}}, t, nil))
- assert.Equal(t, "", execute(command{configDir: configDir, args: []string{"config", "set", "wait", "60"}}, t, nil))
- assert.Equal(t, "wait option must be an integer >= 0, got \"foo\"\n", execute(command{configDir: configDir, args: []string{"config", "set", "wait", "foo"}}, t, nil))
- assert.Equal(t, "wait = 60\n", execute(command{configDir: configDir, args: []string{"config", "get", "wait"}}, t, nil))
+ assert.Equal(t, "", execute(command{homeDir: homeDir, args: []string{"config", "set", "wait", "60"}}, t, nil))
+ assert.Equal(t, "wait option must be an integer >= 0, got \"foo\"\n", execute(command{homeDir: homeDir, args: []string{"config", "set", "wait", "foo"}}, t, nil))
+ assert.Equal(t, "wait = 60\n", execute(command{homeDir: homeDir, args: []string{"config", "get", "wait"}}, t, nil))
}
diff --git a/client/go/cmd/deploy.go b/client/go/cmd/deploy.go
index 19fa08ebaa4..d2836a6bcd1 100644
--- a/client/go/cmd/deploy.go
+++ b/client/go/cmd/deploy.go
@@ -6,12 +6,7 @@ package cmd
import (
"fmt"
- "io/ioutil"
"log"
- "os"
- "path/filepath"
- "strconv"
- "strings"
"github.com/spf13/cobra"
"github.com/vespa-engine/vespa/client/go/vespa"
@@ -51,6 +46,11 @@ If application directory is not specified, it defaults to working directory.`,
fatalErr(nil, err.Error())
return
}
+ cfg, err := LoadConfig()
+ if err != nil {
+ fatalErr(err, "Could not load config")
+ return
+ }
target := getTarget()
opts := vespa.DeploymentOpts{ApplicationPackage: pkg, Target: target}
if opts.IsCloud() {
@@ -58,7 +58,11 @@ If application directory is not specified, it defaults to working directory.`,
if !opts.ApplicationPackage.HasCertificate() {
fatalErrHint(fmt.Errorf("Missing certificate in application package"), "Applications in Vespa Cloud require a certificate", "Try 'vespa cert'")
}
- opts.APIKey = readAPIKey(deployment.Application.Tenant)
+ opts.APIKey, err = cfg.ReadAPIKey(deployment.Application.Tenant)
+ if err != nil {
+ fatalErrHint(err, "Deployment to cloud requires an API key. Try 'vespa api-key'")
+ return
+ }
opts.Deployment = deployment
}
if sessionOrRunID, err := vespa.Deploy(opts); err == nil {
@@ -93,8 +97,9 @@ var prepareCmd = &cobra.Command{
fatalErr(err, "Could not find application package")
return
}
- configDir := configDir("default")
- if configDir == "" {
+ cfg, err := LoadConfig()
+ if err != nil {
+ fatalErr(err, "Could not load config")
return
}
target := getTarget()
@@ -103,7 +108,10 @@ var prepareCmd = &cobra.Command{
Target: target,
})
if err == nil {
- writeSessionID(configDir, sessionID)
+ if err := cfg.WriteSessionID(vespa.DefaultApplication, sessionID); err != nil {
+ fatalErr(err, "Could not write session ID")
+ return
+ }
printSuccess("Prepared ", color.Cyan(pkg.Path), " with session ", sessionID)
} else {
fatalErr(nil, err.Error())
@@ -122,8 +130,16 @@ var activateCmd = &cobra.Command{
fatalErr(err, "Could not find application package")
return
}
- configDir := configDir("default")
- sessionID := readSessionID(configDir)
+ cfg, err := LoadConfig()
+ if err != nil {
+ fatalErr(err, "Could not load config")
+ return
+ }
+ sessionID, err := cfg.ReadSessionID(vespa.DefaultApplication)
+ if err != nil {
+ fatalErr(err, "Could not read session ID")
+ return
+ }
target := getTarget()
err = vespa.Activate(sessionID, vespa.DeploymentOpts{
ApplicationPackage: pkg,
@@ -144,26 +160,3 @@ func waitForQueryService(sessionOrRunID int64) {
waitForService("query", sessionOrRunID)
}
}
-
-func writeSessionID(appConfigDir string, sessionID int64) {
- if err := os.MkdirAll(appConfigDir, 0755); err != nil {
- fatalErr(err, "Could not create directory for session ID")
- }
- if err := ioutil.WriteFile(sessionIDFile(appConfigDir), []byte(fmt.Sprintf("%d\n", sessionID)), 0600); err != nil {
- fatalErr(err, "Could not write session ID")
- }
-}
-
-func readSessionID(appConfigDir string) int64 {
- b, err := ioutil.ReadFile(sessionIDFile(appConfigDir))
- if err != nil {
- fatalErr(err, "Could not read session ID")
- }
- id, err := strconv.ParseInt(strings.TrimSpace(string(b)), 10, 64)
- if err != nil {
- fatalErr(err, "Invalid session ID")
- }
- return id
-}
-
-func sessionIDFile(appConfigDir string) string { return filepath.Join(appConfigDir, "session_id") }
diff --git a/client/go/cmd/deploy_test.go b/client/go/cmd/deploy_test.go
index ff85cd3d835..f24ba0829f9 100644
--- a/client/go/cmd/deploy_test.go
+++ b/client/go/cmd/deploy_test.go
@@ -10,6 +10,7 @@ import (
"testing"
"github.com/stretchr/testify/assert"
+ "github.com/vespa-engine/vespa/client/go/vespa"
)
func TestPrepareZip(t *testing.T) {
@@ -124,12 +125,14 @@ func assertPrepare(applicationPackage string, arguments []string, t *testing.T)
func assertActivate(applicationPackage string, arguments []string, t *testing.T) {
client := &mockHttpClient{}
- configDir := t.TempDir()
- appConfigDir := filepath.Join(configDir, ".vespa", "default")
- writeSessionID(appConfigDir, 42)
+ homeDir := t.TempDir()
+ cfg := Config{Home: filepath.Join(homeDir, ".vespa"), createDirs: true}
+ if err := cfg.WriteSessionID(vespa.DefaultApplication, 42); err != nil {
+ t.Fatal(err)
+ }
assert.Equal(t,
"Success: Activated "+applicationPackage+" with session 42\n",
- execute(command{args: arguments, configDir: configDir}, t, client))
+ execute(command{args: arguments, homeDir: homeDir}, t, client))
url := "http://127.0.0.1:19071/application/v2/tenant/default/session/42/active"
assert.Equal(t, url, client.lastRequest.URL.String())
assert.Equal(t, "PUT", client.lastRequest.Method)
diff --git a/client/go/cmd/helpers.go b/client/go/cmd/helpers.go
index b672419cae6..14699abf40e 100644
--- a/client/go/cmd/helpers.go
+++ b/client/go/cmd/helpers.go
@@ -10,7 +10,6 @@ import (
"io/ioutil"
"log"
"os"
- "path/filepath"
"strings"
"time"
@@ -51,16 +50,6 @@ func printSuccess(msg ...interface{}) {
log.Print(color.Green("Success: "), fmt.Sprint(msg...))
}
-func readAPIKey(tenant string) []byte {
- configDir := configDir("")
- apiKeyPath := filepath.Join(configDir, tenant+".api-key.pem")
- key, err := ioutil.ReadFile(apiKeyPath)
- if err != nil {
- fatalErrHint(err, "Deployment to cloud requires an API key. Try 'vespa api-key'")
- }
- return key
-}
-
func deploymentFromArgs() vespa.Deployment {
zone, err := vespa.ZoneFromString(zoneArg)
if err != nil {
@@ -81,7 +70,12 @@ func applicationSource(args []string) string {
}
func getApplication() string {
- app, err := getOption(applicationFlag)
+ cfg, err := LoadConfig()
+ if err != nil {
+ fatalErr(err, "Could not load config")
+ return ""
+ }
+ app, err := cfg.Get(applicationFlag)
if err != nil {
fatalErr(err, "A valid application must be specified")
}
@@ -89,7 +83,12 @@ func getApplication() string {
}
func getTargetType() string {
- target, err := getOption(targetFlag)
+ cfg, err := LoadConfig()
+ if err != nil {
+ fatalErr(err, "Could not load config")
+ return ""
+ }
+ target, err := cfg.Get(targetFlag)
if err != nil {
fatalErr(err, "A valid target must be specified")
}
@@ -122,10 +121,25 @@ func getTarget() vespa.Target {
return vespa.LocalTarget()
case "cloud":
deployment := deploymentFromArgs()
- apiKey := readAPIKey(deployment.Application.Tenant)
- configDir := configDir(deployment.Application.String())
- privateKeyFile := filepath.Join(configDir, "data-plane-private-key.pem")
- certificateFile := filepath.Join(configDir, "data-plane-public-cert.pem")
+ cfg, err := LoadConfig()
+ if err != nil {
+ fatalErr(err, "Could not load config")
+ return nil
+ }
+ apiKey, err := ioutil.ReadFile(cfg.APIKeyPath(deployment.Application.Tenant))
+ if err != nil {
+ fatalErrHint(err, "Deployment to cloud requires an API key. Try 'vespa api-key'")
+ }
+ privateKeyFile, err := cfg.PrivateKeyPath(deployment.Application)
+ if err != nil {
+ fatalErr(err)
+ return nil
+ }
+ certificateFile, err := cfg.CertificatePath(deployment.Application)
+ if err != nil {
+ fatalErr(err)
+ return nil
+ }
kp, err := tls.LoadX509KeyPair(certificateFile, privateKeyFile)
if err != nil {
fatalErr(err, "Could not read key pair")
diff --git a/client/go/cmd/root.go b/client/go/cmd/root.go
index fde7d6edb5a..f8bf87b508c 100644
--- a/client/go/cmd/root.go
+++ b/client/go/cmd/root.go
@@ -49,7 +49,6 @@ func configureLogger() {
func init() {
configureLogger()
- cobra.OnInitialize(readConfig)
rootCmd.PersistentFlags().StringVarP(&targetArg, targetFlag, "t", "local", "The name or URL of the recipient of this command")
rootCmd.PersistentFlags().StringVarP(&applicationArg, applicationFlag, "a", "", "The application to manage")
rootCmd.PersistentFlags().IntVarP(&waitSecsArg, waitFlag, "w", 0, "Number of seconds to wait for a service to become ready")
diff --git a/client/go/vespa/deploy.go b/client/go/vespa/deploy.go
index 081e9fc17d2..22ab5380c23 100644
--- a/client/go/vespa/deploy.go
+++ b/client/go/vespa/deploy.go
@@ -23,6 +23,8 @@ import (
"github.com/vespa-engine/vespa/client/go/util"
)
+var DefaultApplication = ApplicationID{Tenant: "default", Application: "application", Instance: "default"}
+
type ApplicationID struct {
Tenant string
Application string