summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--client/go/cmd/config.go4
-rw-r--r--client/go/cmd/curl.go2
-rw-r--r--client/go/cmd/document.go2
-rw-r--r--client/go/cmd/document_test.go2
-rw-r--r--client/go/cmd/helpers.go44
-rw-r--r--client/go/cmd/query.go2
-rw-r--r--client/go/cmd/query_test.go2
-rw-r--r--client/go/cmd/test.go363
-rw-r--r--client/go/vespa/deploy.go2
-rw-r--r--client/go/vespa/target.go18
-rw-r--r--client/go/vespa/target_test.go14
-rw-r--r--vespa-osgi-testrunner/src/main/java/com/yahoo/vespa/testrunner/VespaCliTestRunner.java4
-rw-r--r--vespa-osgi-testrunner/src/test/java/com/yahoo/vespa/testrunner/VespaCliTestRunnerTest.java4
13 files changed, 379 insertions, 84 deletions
diff --git a/client/go/cmd/config.go b/client/go/cmd/config.go
index ac23eb8d59d..966080dbdc2 100644
--- a/client/go/cmd/config.go
+++ b/client/go/cmd/config.go
@@ -133,14 +133,14 @@ func (c *Config) Write() error {
}
func (c *Config) CertificatePath(app vespa.ApplicationID) (string, error) {
- if override, _ := c.Get(dataPlaneCertFlag); override != "" {
+ if override, ok := os.LookupEnv("VESPA_CLI_DATA_PLANE_CERT_FILE"); ok {
return override, nil
}
return c.applicationFilePath(app, "data-plane-public-cert.pem")
}
func (c *Config) PrivateKeyPath(app vespa.ApplicationID) (string, error) {
- if override, _ := c.Get(dataPlaneKeyFlag); override != "" {
+ if override, ok := os.LookupEnv("VESPA_CLI_DATA_PLANE_KEY_FILE"); ok {
return override, nil
}
return c.applicationFilePath(app, "data-plane-private-key.pem")
diff --git a/client/go/cmd/curl.go b/client/go/cmd/curl.go
index bd9fad1b47e..2496ddc3abc 100644
--- a/client/go/cmd/curl.go
+++ b/client/go/cmd/curl.go
@@ -46,7 +46,7 @@ $ vespa curl -t local -- -v /search/?yql=query
fatalErr(err)
return
}
- service := getService("query", 0)
+ service := getService("query", 0, "")
url := joinURL(service.BaseURL, args[len(args)-1])
rawArgs := args[:len(args)-1]
c, err := curl.RawArgs(url, rawArgs...)
diff --git a/client/go/cmd/document.go b/client/go/cmd/document.go
index cd0170684cf..84c384e701e 100644
--- a/client/go/cmd/document.go
+++ b/client/go/cmd/document.go
@@ -118,7 +118,7 @@ var documentGetCmd = &cobra.Command{
},
}
-func documentService() *vespa.Service { return getService("document", 0) }
+func documentService() *vespa.Service { return getService("document", 0, "") }
func operationOptions() vespa.OperationOptions {
return vespa.OperationOptions{
diff --git a/client/go/cmd/document_test.go b/client/go/cmd/document_test.go
index 649aca8703a..f3a5fbe9543 100644
--- a/client/go/cmd/document_test.go
+++ b/client/go/cmd/document_test.go
@@ -161,5 +161,5 @@ func assertDocumentServerError(t *testing.T, status int, errorMessage string) {
}
func documentServiceURL(client *mockHttpClient) string {
- return getService("document", 0).BaseURL
+ return getService("document", 0, "").BaseURL
}
diff --git a/client/go/cmd/helpers.go b/client/go/cmd/helpers.go
index 79ba1fcef26..9ccc4513ce3 100644
--- a/client/go/cmd/helpers.go
+++ b/client/go/cmd/helpers.go
@@ -6,6 +6,7 @@ package cmd
import (
"crypto/tls"
+ "encoding/json"
"fmt"
"io/ioutil"
"log"
@@ -129,19 +130,21 @@ func getTargetType() string {
return target
}
-func getService(service string, sessionOrRunID int64) *vespa.Service {
+func getService(service string, sessionOrRunID int64, cluster string) *vespa.Service {
t := getTarget()
timeout := time.Duration(waitSecsArg) * time.Second
if timeout > 0 {
log.Printf("Waiting up to %d %s for service to become available ...", color.Cyan(waitSecsArg), color.Cyan("seconds"))
}
- s, err := t.Service(service, timeout, sessionOrRunID)
+ s, err := t.Service(service, timeout, sessionOrRunID, cluster)
if err != nil {
fatalErr(err, "Invalid service: ", service)
}
return s
}
+func getEndpointsOverride() string { return os.Getenv("VESPA_CLI_ENDPOINTS") }
+
func getSystem() string { return os.Getenv("VESPA_CLI_CLOUD_SYSTEM") }
func getSystemName() string {
@@ -175,12 +178,13 @@ func getTarget() vespa.Target {
case "local":
return vespa.LocalTarget()
case "cloud":
- deployment := deploymentFromArgs()
cfg, err := LoadConfig()
if err != nil {
fatalErr(err, "Could not load config")
return nil
}
+ deployment := deploymentFromArgs()
+
var apiKey []byte = nil
apiKey, err = ioutil.ReadFile(cfg.APIKeyPath(deployment.Application.Tenant))
if !vespa.Auth0AccessTokenEnabled() {
@@ -228,14 +232,15 @@ func getTarget() vespa.Target {
},
cfg.AuthConfigPath(),
getSystemName(),
- cloudAuth)
+ cloudAuth,
+ getEndpointsFromEnv())
}
fatalErrHint(fmt.Errorf("Invalid target: %s", targetType), "Valid targets are 'local', 'cloud' or an URL")
return nil
}
func waitForService(service string, sessionOrRunID int64) {
- s := getService(service, sessionOrRunID)
+ s := getService(service, sessionOrRunID, "")
timeout := time.Duration(waitSecsArg) * time.Second
if timeout > 0 {
log.Printf("Waiting up to %d %s for service to become ready ...", color.Cyan(waitSecsArg), color.Cyan("seconds"))
@@ -271,3 +276,32 @@ func getDeploymentOpts(cfg *Config, pkg vespa.ApplicationPackage, target vespa.T
}
return opts
}
+
+func getEndpointsFromEnv() map[string]string {
+ endpointsString := getEndpointsOverride()
+ if endpointsString == "" {
+ return nil
+ }
+
+ var endpoints endpoints
+ urlsByCluster := make(map[string]string)
+ if err := json.Unmarshal([]byte(endpointsString), &endpoints); err != nil {
+ fatalErrHint(err, "Endpoints must be valid JSON")
+ }
+ if len(endpoints.Endpoints) == 0 {
+ fatalErr(fmt.Errorf("endpoints must be non-empty"))
+ }
+ for _, endpoint := range endpoints.Endpoints {
+ urlsByCluster[endpoint.Cluster] = endpoint.URL
+ }
+ return urlsByCluster
+}
+
+type endpoints struct {
+ Endpoints []endpoint `json:"endpoints"`
+}
+
+type endpoint struct {
+ Cluster string `json:"cluster"`
+ URL string `json:"url"`
+}
diff --git a/client/go/cmd/query.go b/client/go/cmd/query.go
index 76688438fb4..6638c275330 100644
--- a/client/go/cmd/query.go
+++ b/client/go/cmd/query.go
@@ -39,7 +39,7 @@ can be set by the syntax [parameter-name]=[value].`,
}
func query(arguments []string) {
- service := getService("query", 0)
+ service := getService("query", 0, "")
url, _ := url.Parse(service.BaseURL + "/search/")
urlQuery := url.Query()
for i := 0; i < len(arguments); i++ {
diff --git a/client/go/cmd/query_test.go b/client/go/cmd/query_test.go
index ec6c3063906..55046ae49ba 100644
--- a/client/go/cmd/query_test.go
+++ b/client/go/cmd/query_test.go
@@ -75,5 +75,5 @@ func assertQueryServiceError(t *testing.T, status int, errorMessage string) {
}
func queryServiceURL(client *mockHttpClient) string {
- return getService("query", 0).BaseURL
+ return getService("query", 0, "").BaseURL
}
diff --git a/client/go/cmd/test.go b/client/go/cmd/test.go
index a13fd999be9..6e6ac048650 100644
--- a/client/go/cmd/test.go
+++ b/client/go/cmd/test.go
@@ -5,31 +5,25 @@
package cmd
import (
+ "bytes"
"encoding/json"
"fmt"
- "github.com/vespa-engine/vespa/client/go/vespa"
- "log"
-
"github.com/spf13/cobra"
-)
-
-const (
- endpointsFlag = "endpoints"
- dataPlaneCertFlag = "data-plane-public-cert"
- dataPlaneKeyFlag = "data-plane-private-key"
-)
-
-var (
- endpointsArg string
- dataPlaneCertArg string
- dataPlaneKeyArg string
+ "github.com/vespa-engine/vespa/client/go/util"
+ "github.com/vespa-engine/vespa/client/go/vespa"
+ "io"
+ "io/ioutil"
+ "math"
+ "net/http"
+ "net/url"
+ "os"
+ "path"
+ "strings"
+ "time"
)
func init() {
rootCmd.AddCommand(testCmd)
- testCmd.PersistentFlags().StringVar(&endpointsArg, endpointsFlag, "", "The endpoints to use, for each container cluster")
- testCmd.PersistentFlags().StringVar(&dataPlaneCertArg, dataPlaneCertFlag, "", "Override for location of data plane public certificate")
- testCmd.PersistentFlags().StringVar(&dataPlaneKeyArg, dataPlaneKeyFlag, "", "Override for location of data plane private key")
}
var testCmd = &cobra.Command{
@@ -46,55 +40,318 @@ $ vespa test src/test/application/tests/system-test/feed-and-query.json`,
Args: cobra.MaximumNArgs(1),
DisableAutoGenTag: true,
Run: func(cmd *cobra.Command, args []string) {
- cfg, err := LoadConfig()
+ target := getTarget()
+ testPath := "."
+ if len(args) > 0 {
+ testPath = args[0]
+ }
+ if count, failed := runTests(testPath, target); len(failed) != 0 {
+ _, _ = fmt.Fprintf(stdout, "\nFailed %d of %d tests:\n", len(failed), count)
+ for _, test := range failed {
+ _, _ = fmt.Fprintln(stdout, test)
+ }
+ exitFunc(3)
+ } else if count == 0 {
+ _, _ = fmt.Fprintf(stdout, "Failed to find any tests at '%v'\n", testPath)
+ exitFunc(3)
+ } else {
+ _, _ = fmt.Fprintf(stdout, "%d tests completed successfully\n", count)
+ }
+ },
+}
+
+func runTests(rootPath string, target vespa.Target) (int, []string) {
+ count := 0
+ failed := make([]string, 0)
+ if stat, err := os.Stat(rootPath); err != nil {
+ fatalErr(err, "Failed reading specified test path")
+ } else if stat.IsDir() {
+ tests, err := os.ReadDir(rootPath)
if err != nil {
- fatalErr(err, "Could not load config")
- return
+ fatalErr(err, "Failed reading specified test directory")
+ }
+ for _, test := range tests {
+ if !test.IsDir() && strings.HasSuffix(test.Name(), ".json") {
+ testPath := path.Join(rootPath, test.Name())
+ failure := runTest(testPath, target)
+ if failure != "" {
+ failed = append(failed, failure)
+ }
+ count++
+ }
+ }
+ } else if strings.HasSuffix(stat.Name(), ".json") {
+ failure := runTest(rootPath, target)
+ if failure != "" {
+ failed = append(failed, failure)
}
+ count++
+ }
+ return count, failed
+}
- app, endpoints := getApplicationOrEndpoints(cfg)
- keyPath, _ := cfg.PrivateKeyPath(app)
- certPath, _ := cfg.CertificatePath(app)
- log.Printf("Key path: %q, Cert path: %q, Endpoints: %q", keyPath, certPath, endpoints)
+// Runs the test at the given path, and returns the specified test name if the test fails
+func runTest(testPath string, target vespa.Target) string {
+ var test test
+ bytes := readFile(testPath)
+ if err := json.Unmarshal(bytes, &test); err != nil {
+ fatalErr(err, fmt.Sprintf("Failed to parse test file '%s", testPath))
+ }
- exitFunc(3)
- },
-}
+ testName := test.Name
+ if test.Name == "" {
+ testName = testPath
+ }
+ _, _ = fmt.Fprintf(stdout, "Running %s: ", testName)
-func getApplicationOrEndpoints(cfg *Config) (vespa.ApplicationID, map[string]string) {
- appString, _ := cfg.Get(applicationFlag)
- endpointsString, _ := cfg.Get(endpointsFlag)
- if (appString == "") == (endpointsString == "") {
- fatalErr(fmt.Errorf("must specify exactly one of application or endpoints"))
+ defaultParameters, err := getParameters(test.Defaults.ParametersRaw, path.Dir(testPath))
+ if err != nil {
+ fatalErr(err, fmt.Sprintf("Invalid default parameters for '%s'", testName))
}
- if endpointsString == "" {
- app, err := vespa.ApplicationFromString(appString)
+
+ for i, assertion := range test.Assertions {
+ assertionName := assertion.Name
+ if assertionName == "" {
+ assertionName = fmt.Sprintf("assertion %d", i)
+ }
+ failure, err := verify(assertion, path.Dir(testPath), test.Defaults.Cluster, defaultParameters, target)
if err != nil {
- fatalErrHint(err, "Application format is <tenant>.<app>.<instance>")
+ fatalErr(err, fmt.Sprintf("\nError verifying %s", assertionName))
}
- return app, nil
- } else {
- var endpoints deploymentResponse
- urlsByCluster := make(map[string]string)
- if err := json.Unmarshal([]byte(endpointsString), &endpoints); err != nil {
- fatalErrHint(err, "Endpoints must be valid JSON")
+ if failure != "" {
+ _, _ = fmt.Fprintf(stdout, "\nFailed verifying %s: \n%s\n", assertionName, failure)
+ return fmt.Sprintf("%v: %v", testName, assertionName)
}
- if len(endpoints.Endpoints) == 0 {
- fatalErr(fmt.Errorf("endpoints must be non-empty"))
+ fmt.Print(".")
+ }
+ fmt.Println(" OK!")
+ return ""
+}
+
+// Asserts specified response is obtained for request, or returns a failure message, or an error if this fails
+func verify(assertion assertion, testsPath string, defaultCluster string, defaultParameters map[string]string, target vespa.Target) (string, error) {
+ requestBody, err := getBody(assertion.Request.BodyRaw, testsPath)
+ if err != nil {
+ return "", err
+ }
+
+ parameters, err := getParameters(assertion.Request.ParametersRaw, testsPath)
+ if err != nil {
+ return "", err
+ }
+ for name, value := range defaultParameters {
+ if _, present := parameters[name]; !present {
+ parameters[name] = value
}
- for _, endpoint := range endpoints.Endpoints {
- urlsByCluster[endpoint.Cluster] = endpoint.URL
+ }
+
+ cluster := assertion.Request.Cluster
+ if cluster == "" {
+ cluster = defaultCluster
+ }
+
+ service, err := target.Service("query", 0, 0, cluster)
+ if err != nil {
+ return "", err
+ }
+
+ method := assertion.Request.Method
+ if method == "" {
+ method = "GET"
+ }
+
+ pathAndQuery := assertion.Request.URI
+ if pathAndQuery == "" {
+ pathAndQuery = "/search/"
+ }
+ requestUrl, err := url.ParseRequestURI(service.BaseURL + pathAndQuery)
+ if err != nil {
+ return "", err
+ }
+ query := requestUrl.Query()
+ for name, value := range parameters {
+ query.Add(name, value)
+ }
+ requestUrl.RawQuery = query.Encode()
+
+ header := http.Header{}
+ header.Add("Content-Type", "application/json")
+
+ request := &http.Request{
+ URL: requestUrl,
+ Method: method,
+ Header: header,
+ Body: ioutil.NopCloser(bytes.NewReader(requestBody)),
+ }
+ defer request.Body.Close()
+
+ response, err := service.Do(request, 600*time.Second) // Vespa should provide a response within the given request timeout
+ if err != nil {
+ return "", err
+ }
+ defer response.Body.Close()
+
+ statusCode := assertion.Response.Code
+ if statusCode == 0 {
+ statusCode = 200
+ }
+ if statusCode != response.StatusCode {
+ return fmt.Sprintf("Expected status code %d, but got %d, and body:\n%s", statusCode, response.StatusCode, util.ReaderToJSON(response.Body)), nil
+ }
+
+ responseBodySpecBytes, err := getBody(assertion.Response.BodyRaw, testsPath)
+ if err != nil {
+ return "", err
+ }
+ if responseBodySpecBytes == nil {
+ return "", nil
+ }
+ var responseBodySpec interface{}
+ err = json.Unmarshal(responseBodySpecBytes, &responseBodySpec)
+ if err != nil {
+ return "", err
+ }
+
+ responseBodyBytes, err := ioutil.ReadAll(response.Body)
+ if err != nil {
+ return "", err
+ }
+ var responseBody interface{}
+ err = json.Unmarshal(responseBodyBytes, &responseBody)
+ if err != nil {
+ return "", err
+ }
+
+ return compare(responseBodySpec, responseBody, "")
+}
+
+func compare(expected interface{}, actual interface{}, path string) (string, error) {
+ typeMatch := false
+ valueMatch := false
+ switch u := expected.(type) {
+ case nil:
+ typeMatch = actual == nil
+ valueMatch = actual == nil
+ case bool:
+ v, ok := actual.(bool)
+ typeMatch = ok
+ valueMatch = ok && u == v
+ case float64:
+ v, ok := actual.(float64)
+ typeMatch = ok
+ valueMatch = ok && math.Abs(u-v) < 1e-9
+ case string:
+ v, ok := actual.(string)
+ typeMatch = ok
+ valueMatch = ok && (u == v)
+ case []interface{}:
+ v, ok := actual.([]interface{})
+ typeMatch = ok
+ if ok && len(u) == len(v) {
+ for i, e := range u {
+ result, err := compare(e, v[i], fmt.Sprintf("%s[%d]", path, i))
+ if result != "" || err != nil {
+ return result, err
+ }
+ }
+ valueMatch = true
+ }
+ case map[string]interface{}:
+ v, ok := actual.(map[string]interface{})
+ typeMatch = ok
+ if ok {
+ for n, e := range u {
+ result, err := compare(e, v[n], fmt.Sprintf("%s['%s']", path, n))
+ if result != "" || err != nil {
+ return result, err
+ }
+ }
+ valueMatch = true
+ }
+ default:
+ return "", fmt.Errorf("unexpected expected JSON type for value '%v'", expected)
+ }
+
+ if !(typeMatch && valueMatch) {
+ if path == "" {
+ path = "root"
}
- return vespa.ApplicationID{}, urlsByCluster
+ expectedJson, _ := json.MarshalIndent(expected, "", " ")
+ actualJson, _ := json.MarshalIndent(actual, "", " ")
+ mismatched := "Type"
+ if typeMatch {
+ mismatched = "Value"
+ }
+ return fmt.Sprintf("%s mismatch at %s: <<< expected === actual >>>\n<<<\n%s\n===\n%s\n>>>\n", mismatched, path, expectedJson, actualJson), nil
+ }
+ return "", nil
+}
+
+func getParameters(parametersRaw []byte, testsPath string) (map[string]string, error) {
+ if parametersRaw != nil {
+ var parametersPath string
+ if err := json.Unmarshal(parametersRaw, &parametersPath); err == nil {
+ parametersRaw = readFile(path.Join(testsPath, parametersPath))
+ }
+ var parameters map[string]string
+ if err := json.Unmarshal(parametersRaw, &parameters); err != nil {
+ return nil, fmt.Errorf("request parameters must be JSON with only string values: %v", err)
+ }
+ return parameters, nil
+ }
+ return make(map[string]string), nil
+}
+
+func getBody(bodyRaw []byte, testsPath string) ([]byte, error) {
+ var bodyPath string
+ if err := json.Unmarshal(bodyRaw, &bodyPath); err == nil {
+ return readFile(path.Join(testsPath, bodyPath)), nil
+ }
+ return bodyRaw, nil
+}
+
+func readFile(filePath string) []byte {
+ file, err := os.Open(filePath)
+ if err != nil {
+ fatalErr(err, fmt.Sprintf("Failed to open file at '%v'", filePath))
+ }
+ fileBytes, err := io.ReadAll(file)
+ if err != nil {
+ fatalErr(err, fmt.Sprintf("Failed to read file at '%v'", filePath))
}
+ err = file.Close()
+ if err != nil {
+ fatalErr(err, fmt.Sprintf("Failed to closse file at '%v'", filePath))
+ }
+ return fileBytes
+}
+
+type test struct {
+ Name string `json:"name"`
+ Defaults defaults `json:"defaults"`
+ Assertions []assertion `json:"assertions"`
+}
+
+type defaults struct {
+ Cluster string `json:"cluster"`
+ ParametersRaw json.RawMessage `json:"parameters"`
+}
+
+type assertion struct {
+ Name string `json:"name"`
+ Request request `json:"request"`
+ Response response `json:"response"`
}
-type deploymentEndpoint struct {
- Cluster string `json:"cluster"`
- URL string `json:"url"`
- Scope string `json:"scope"`
+type request struct {
+ Cluster string `json:"cluster"`
+ Method string `json:"method"`
+ URI string `json:"uri"`
+ ParametersRaw json.RawMessage `json:"parameters"`
+ BodyRaw json.RawMessage `json:"body"`
}
-type deploymentResponse struct {
- Endpoints []deploymentEndpoint `json:"endpoints"`
+type response struct {
+ Code int `json:"code"`
+ BodyRaw json.RawMessage `json:"body"`
}
diff --git a/client/go/vespa/deploy.go b/client/go/vespa/deploy.go
index 252a646bcfc..c1cc868e16f 100644
--- a/client/go/vespa/deploy.go
+++ b/client/go/vespa/deploy.go
@@ -73,7 +73,7 @@ func (d DeploymentOpts) String() string {
func (d *DeploymentOpts) IsCloud() bool { return d.Target.Type() == cloudTargetType }
func (d *DeploymentOpts) url(path string) (*url.URL, error) {
- service, err := d.Target.Service(deployService, 0, 0)
+ service, err := d.Target.Service(deployService, 0, 0, "")
if err != nil {
return nil, err
}
diff --git a/client/go/vespa/target.go b/client/go/vespa/target.go
index 093cb2b5cad..72b62b505fd 100644
--- a/client/go/vespa/target.go
+++ b/client/go/vespa/target.go
@@ -39,7 +39,6 @@ type Service struct {
BaseURL string
Name string
TLSOptions TLSOptions
- Target *Target
}
// Target represents a Vespa platform, running named Vespa services.
@@ -48,7 +47,7 @@ type Target interface {
Type() string
// Service returns the service for given name. If timeout is non-zero, wait for the service to converge.
- Service(name string, timeout time.Duration, sessionOrRunID int64) (*Service, error)
+ Service(name string, timeout time.Duration, sessionOrRunID int64, cluster string) (*Service, error)
// PrintLog writes the logs of this deployment using given options to control output.
PrintLog(options LogOptions) error
@@ -129,7 +128,7 @@ func (s *Service) Description() string {
func (t *customTarget) Type() string { return t.targetType }
-func (t *customTarget) Service(name string, timeout time.Duration, sessionID int64) (*Service, error) {
+func (t *customTarget) Service(name string, timeout time.Duration, _ int64, _ string) (*Service, error) {
if timeout > 0 && name != deployService {
if err := t.waitForConvergence(timeout); err != nil {
return nil, err
@@ -171,7 +170,7 @@ func (t *customTarget) urlWithPort(serviceName string) (string, error) {
}
func (t *customTarget) waitForConvergence(timeout time.Duration) error {
- deployer, err := t.Service(deployService, 0, 0)
+ deployer, err := t.Service(deployService, 0, 0, "")
if err != nil {
return err
}
@@ -241,8 +240,8 @@ func (t *cloudTarget) resolveEndpoint(cluster string) (string, error) {
func (t *cloudTarget) Type() string { return t.targetType }
-func (t *cloudTarget) Service(name string, timeout time.Duration, runID int64) (*Service, error) {
- if name != deployService {
+func (t *cloudTarget) Service(name string, timeout time.Duration, runID int64, cluster string) (*Service, error) {
+ if name != deployService && t.urlsByCluster == nil {
if err := t.waitForEndpoints(timeout, runID); err != nil {
return nil, err
}
@@ -251,13 +250,13 @@ func (t *cloudTarget) Service(name string, timeout time.Duration, runID int64) (
case deployService:
return &Service{Name: name, BaseURL: t.apiURL}, nil
case queryService:
- queryURL, err := t.resolveEndpoint("")
+ queryURL, err := t.resolveEndpoint(cluster)
if err != nil {
return nil, err
}
return &Service{Name: name, BaseURL: queryURL, TLSOptions: t.tlsOptions}, nil
case documentService:
- documentURL, err := t.resolveEndpoint("")
+ documentURL, err := t.resolveEndpoint(cluster)
if err != nil {
return nil, err
}
@@ -489,7 +488,7 @@ func CustomTarget(baseURL string) Target {
// CloudTarget creates a Target for the Vespa Cloud platform.
func CloudTarget(apiURL string, deployment Deployment, apiKey []byte, tlsOptions TLSOptions, logOptions LogOptions,
- authConfigPath string, systemName string, cloudAuth string) Target {
+ authConfigPath string, systemName string, cloudAuth string, urlsByCluster map[string]string) Target {
return &cloudTarget{
apiURL: apiURL,
targetType: cloudTargetType,
@@ -500,6 +499,7 @@ func CloudTarget(apiURL string, deployment Deployment, apiKey []byte, tlsOptions
authConfigPath: authConfigPath,
systemName: systemName,
cloudAuth: cloudAuth,
+ urlsByCluster: urlsByCluster,
}
}
diff --git a/client/go/vespa/target_test.go b/client/go/vespa/target_test.go
index 9d2418897e3..0cfe9f1962c 100644
--- a/client/go/vespa/target_test.go
+++ b/client/go/vespa/target_test.go
@@ -82,11 +82,11 @@ func TestCustomTargetWait(t *testing.T) {
defer srv.Close()
target := CustomTarget(srv.URL)
- _, err := target.Service("query", time.Millisecond, 42)
+ _, err := target.Service("query", time.Millisecond, 42, "")
assert.NotNil(t, err)
vc.deploymentConverged = true
- _, err = target.Service("query", time.Millisecond, 42)
+ _, err = target.Service("query", time.Millisecond, 42, "")
assert.Nil(t, err)
assertServiceWait(t, 200, target, "deploy")
@@ -104,11 +104,11 @@ func TestCloudTargetWait(t *testing.T) {
target := createCloudTarget(t, srv.URL, &logWriter)
assertServiceWait(t, 200, target, "deploy")
- _, err := target.Service("query", time.Millisecond, 42)
+ _, err := target.Service("query", time.Millisecond, 42, "")
assert.NotNil(t, err)
vc.deploymentConverged = true
- _, err = target.Service("query", time.Millisecond, 42)
+ _, err = target.Service("query", time.Millisecond, 42, "")
assert.Nil(t, err)
assertServiceWait(t, 500, target, "query")
@@ -152,7 +152,7 @@ func createCloudTarget(t *testing.T, url string, logWriter io.Writer) Target {
target := CloudTarget("https://example.com", Deployment{
Application: ApplicationID{Tenant: "t1", Application: "a1", Instance: "i1"},
Zone: ZoneID{Environment: "dev", Region: "us-north-1"},
- }, apiKey, TLSOptions{KeyPair: x509KeyPair}, LogOptions{Writer: logWriter}, "", "", "")
+ }, apiKey, TLSOptions{KeyPair: x509KeyPair}, LogOptions{Writer: logWriter}, "", "", "", nil)
if ct, ok := target.(*cloudTarget); ok {
ct.apiURL = url
} else {
@@ -162,13 +162,13 @@ func createCloudTarget(t *testing.T, url string, logWriter io.Writer) Target {
}
func assertServiceURL(t *testing.T, url string, target Target, service string) {
- s, err := target.Service(service, 0, 42)
+ s, err := target.Service(service, 0, 42, "")
assert.Nil(t, err)
assert.Equal(t, url, s.BaseURL)
}
func assertServiceWait(t *testing.T, expectedStatus int, target Target, service string) {
- s, err := target.Service(service, 0, 42)
+ s, err := target.Service(service, 0, 42, "")
assert.Nil(t, err)
status, err := s.Wait(0)
diff --git a/vespa-osgi-testrunner/src/main/java/com/yahoo/vespa/testrunner/VespaCliTestRunner.java b/vespa-osgi-testrunner/src/main/java/com/yahoo/vespa/testrunner/VespaCliTestRunner.java
index 29857102151..06df43be6a4 100644
--- a/vespa-osgi-testrunner/src/main/java/com/yahoo/vespa/testrunner/VespaCliTestRunner.java
+++ b/vespa-osgi-testrunner/src/main/java/com/yahoo/vespa/testrunner/VespaCliTestRunner.java
@@ -101,7 +101,9 @@ public class VespaCliTestRunner implements TestRunner {
.flatMap(testsPath -> getChildDirectory(testsPath, toSuiteDirectoryName(suite)))
.orElseThrow(() -> new IllegalStateException("No tests found, for suite '" + suite + "'"));
- ProcessBuilder builder = new ProcessBuilder("vespa", "test", suitePath.toAbsolutePath().toString());
+ ProcessBuilder builder = new ProcessBuilder("vespa", "test", suitePath.toAbsolutePath().toString(),
+ "--application", config.application().toFullString(),
+ "--zone", config.zone().value());
builder.redirectErrorStream(true);
builder.environment().put("VESPA_CLI_ENDPOINTS", toEndpointsConfig(config));
builder.environment().put("VESPA_CLI_DATA_PLANE_KEY_FILE", artifactsPath.resolve("key").toAbsolutePath().toString());
diff --git a/vespa-osgi-testrunner/src/test/java/com/yahoo/vespa/testrunner/VespaCliTestRunnerTest.java b/vespa-osgi-testrunner/src/test/java/com/yahoo/vespa/testrunner/VespaCliTestRunnerTest.java
index 54554bd3a2e..0b1420e85bf 100644
--- a/vespa-osgi-testrunner/src/test/java/com/yahoo/vespa/testrunner/VespaCliTestRunnerTest.java
+++ b/vespa-osgi-testrunner/src/test/java/com/yahoo/vespa/testrunner/VespaCliTestRunnerTest.java
@@ -55,7 +55,9 @@ class VespaCliTestRunnerTest {
Path systemTests = Files.createDirectory(tests.resolve("system-test"));
ProcessBuilder builder = runner.testRunProcessBuilder(TestRunner.Suite.SYSTEM_TEST, testConfig);
- assertEquals(List.of("vespa", "test", systemTests.toAbsolutePath().toString()),
+ assertEquals(List.of("vespa", "test", systemTests.toAbsolutePath().toString(),
+ "--application", "t.a.i.",
+ "--zone", "dev.aws-us-east-1c"),
builder.command());
assertEquals("{\"endpoints\":[{\"cluster\":\"default\",\"url\":\"https://dev.endpoint:443/\"}]}",
builder.environment().get("VESPA_CLI_ENDPOINTS"));