diff options
18 files changed, 227 insertions, 95 deletions
diff --git a/client/go/internal/cli/cmd/deploy.go b/client/go/internal/cli/cmd/deploy.go index 4792088a915..d3bda1089a7 100644 --- a/client/go/internal/cli/cmd/deploy.go +++ b/client/go/internal/cli/cmd/deploy.go @@ -185,8 +185,10 @@ func waitForVespaReady(target vespa.Target, sessionOrRunID int64, waiter *Waiter if _, err := waiter.Deployment(target, sessionOrRunID); err != nil { return err } - // Wait for healthy services - if hasTimeout { + // Wait for healthy services where we expect them to be reachable (cloud and local). When using a custom target, + // we do not wait for services as there is no guarantee that they are reachable from the machine executing + // deploy. + if hasTimeout && (target.IsCloud() || target.Type() == vespa.TargetLocal) { _, err := waiter.Services(target) return err } diff --git a/client/go/internal/cli/cmd/log.go b/client/go/internal/cli/cmd/log.go index 77ef7f68130..53b7079f428 100644 --- a/client/go/internal/cli/cmd/log.go +++ b/client/go/internal/cli/cmd/log.go @@ -6,6 +6,7 @@ import ( "time" "github.com/spf13/cobra" + "github.com/vespa-engine/vespa/client/go/internal/version" "github.com/vespa-engine/vespa/client/go/internal/vespa" ) @@ -34,7 +35,7 @@ $ vespa log --follow`, SilenceUsage: true, Args: cobra.MaximumNArgs(1), RunE: func(cmd *cobra.Command, args []string) error { - target, err := cli.target(targetOptions{logLevel: levelArg, supportedType: cloudTargetOnly}) + target, err := cli.target(targetOptions{logLevel: levelArg}) if err != nil { return err } @@ -58,7 +59,12 @@ $ vespa log --follow`, options.To = to } if err := target.PrintLog(options); err != nil { - return fmt.Errorf("could not retrieve logs: %w", err) + versionWithLogContainer := version.MustParse("8.359.0") + var hints []string + if err := target.CompatibleWith(versionWithLogContainer); err != nil { + hints = []string{fmt.Sprintf("This command requires a newer version of the Vespa platform: %s", err)} + } + return errHint(fmt.Errorf("could not retrieve logs: %w", err), hints...) } return nil }, diff --git a/client/go/internal/cli/cmd/log_test.go b/client/go/internal/cli/cmd/log_test.go index c1cab951793..e8e8a76b988 100644 --- a/client/go/internal/cli/cmd/log_test.go +++ b/client/go/internal/cli/cmd/log_test.go @@ -9,7 +9,7 @@ import ( "github.com/vespa-engine/vespa/client/go/internal/version" ) -func TestLog(t *testing.T) { +func TestLogCloud(t *testing.T) { _, pkgDir := mock.ApplicationPackageDir(t, false, false) httpClient := &mock.HTTPClient{} httpClient.NextResponseString(200, `1632738690.905535 host1a.dev.aws-us-east-1c 806/53 logserver-container Container.com.yahoo.container.jdisc.ConfiguredApplication info Switching to the latest deployed set of configurations and components. Application config generation: 52532`) @@ -30,14 +30,13 @@ func TestLog(t *testing.T) { assert.Contains(t, stderr.String(), "Error: invalid period: cannot combine --from/--to with relative value: 1h\n") } -func TestLogOldClient(t *testing.T) { +func TestLogCloudIncompatible(t *testing.T) { cli, _, stderr := newTestCLI(t) cli.version = version.MustParse("7.0.0") _, pkgDir := mock.ApplicationPackageDir(t, false, false) httpClient := &mock.HTTPClient{} httpClient.NextResponseString(200, `{"minVersion": "8.0.0"}`) - httpClient.NextResponseString(200, `1632738690.905535 host1a.dev.aws-us-east-1c 806/53 logserver-container Container.com.yahoo.container.jdisc.ConfiguredApplication info Switching to the latest deployed set of configurations and components. Application config generation: 52532`) cli.httpClient = httpClient assert.Nil(t, cli.Run("config", "set", "application", "t1.a1.i1")) @@ -46,6 +45,37 @@ func TestLogOldClient(t *testing.T) { assert.Nil(t, cli.Run("auth", "cert", pkgDir)) assert.Nil(t, cli.Run("log")) - expected := "Warning: client version 7.0.0 is less than the minimum supported version: 8.0.0\nHint: This version may not work as expected\nHint: Try 'vespa version' to check for a new version\n" + expected := "Warning: client version 7.0.0 is less than the minimum supported version: 8.0.0\nHint: This version of CLI may not work as expected\nHint: Try 'vespa version' to check for a new version\n" assert.Contains(t, stderr.String(), expected) } + +func TestLogLocal(t *testing.T) { + httpClient := &mock.HTTPClient{} + httpClient.NextResponseString(200, `1632738690.905535 localhost 806/53 logserver-container Container.com.yahoo.container.jdisc.ConfiguredApplication info Switching to the latest deployed set of configurations and components. Application config generation: 52532`) + cli, stdout, stderr := newTestCLI(t) + cli.httpClient = httpClient + + assert.Nil(t, cli.Run("log", "--from", "2021-09-27T10:00:00Z", "--to", "2021-09-27T11:00:00Z")) + expected := "[2021-09-27 10:31:30.905535] localhost info logserver-container Container.com.yahoo.container.jdisc.ConfiguredApplication Switching to the latest deployed set of configurations and components. Application config generation: 52532\n" + assert.Equal(t, expected, stdout.String()) + + assert.NotNil(t, cli.Run("log", "--from", "2021-09-27T13:12:49Z", "--to", "2021-09-27T13:15:00", "1h")) + assert.Contains(t, stderr.String(), "Error: invalid period: cannot combine --from/--to with relative value: 1h\n") +} + +func TestLogLocalIncompatible(t *testing.T) { + httpClient := &mock.HTTPClient{} + httpClient.NextResponseString(404, `not found`) + httpClient.NextResponse(mock.HTTPResponse{ + URI: "/state/v1/version", + Status: 200, + Body: []byte(`{"version": "8.358.0"}`), + }) + cli, _, stderr := newTestCLI(t) + cli.httpClient = httpClient + + assert.NotNil(t, cli.Run("log", "--from", "2021-09-27T10:00:00Z", "--to", "2021-09-27T11:00:00Z")) + assert.Equal(t, `Error: could not retrieve logs: failed to read logs: aborting wait: got status 404 +Hint: This command requires a newer version of the Vespa platform: platform version is older than required version: 8.358.0 < 8.359.0 +`, stderr.String()) +} diff --git a/client/go/internal/cli/cmd/root.go b/client/go/internal/cli/cmd/root.go index 5d5314d694f..c0f6f3af51e 100644 --- a/client/go/internal/cli/cmd/root.go +++ b/client/go/internal/cli/cmd/root.go @@ -405,9 +405,9 @@ func (c *CLI) target(opts targetOptions) (vespa.Target, error) { if err != nil { return nil, err } - if !c.isCloudCI() { // Vespa Cloud always runs an up-to-date version - if err := target.CheckVersion(c.version); err != nil { - c.printWarning(err, "This version may not work as expected", "Try 'vespa version' to check for a new version") + if target.IsCloud() && !c.isCloudCI() { // Vespa Cloud always runs an up-to-date version + if err := target.CompatibleWith(c.version); err != nil { + c.printWarning(err, "This version of CLI may not work as expected", "Try 'vespa version' to check for a new version") } } return target, nil diff --git a/client/go/internal/vespa/target.go b/client/go/internal/vespa/target.go index 5270b5669f9..674bedc9343 100644 --- a/client/go/internal/vespa/target.go +++ b/client/go/internal/vespa/target.go @@ -3,11 +3,14 @@ package vespa import ( + "bytes" "crypto/tls" "errors" "fmt" "io" + "math" "net/http" + "strconv" "strings" "time" @@ -120,8 +123,8 @@ type Target interface { // PrintLog writes the logs of this deployment using given options to control output. PrintLog(options LogOptions) error - // CheckVersion verifies whether clientVersion is compatible with this target. - CheckVersion(clientVersion version.Version) error + // CompatibleWith returns nil if target is compatible with the given version. + CompatibleWith(version version.Version) error } // TLSOptions holds the client certificate to use for cloud API or service requests. @@ -252,6 +255,64 @@ func isOK(status int) (bool, error) { } } +func deployServiceWait(target Target, fn responseFunc, reqFn requestFunc, timeout, retryInterval time.Duration) (int, error) { + deployService, err := target.DeployService() + if err != nil { + return 0, err + } + return wait(deployService, fn, reqFn, timeout, retryInterval) +} + +func pollLogs(target Target, logsURL string, options LogOptions, retryInterval time.Duration) error { + req, err := http.NewRequest("GET", logsURL, nil) + if err != nil { + return err + } + lastFrom := options.From + requestFunc := func() *http.Request { + fromMillis := lastFrom.Unix() * 1000 + q := req.URL.Query() + q.Set("from", strconv.FormatInt(fromMillis, 10)) + if !options.To.IsZero() { + toMillis := options.To.Unix() * 1000 + q.Set("to", strconv.FormatInt(toMillis, 10)) + } + req.URL.RawQuery = q.Encode() + return req + } + logFunc := func(status int, response []byte) (bool, error) { + if ok, err := isOK(status); !ok { + return ok, err + } + logEntries, err := ReadLogEntries(bytes.NewReader(response)) + if err != nil { + return false, err + } + for _, le := range logEntries { + if !le.Time.After(lastFrom) { + continue + } + if LogLevel(le.Level) > options.Level { + continue + } + fmt.Fprintln(options.Writer, le.Format(options.Dequote)) + } + if len(logEntries) > 0 { + lastFrom = logEntries[len(logEntries)-1].Time + } + return false, nil + } + var timeout time.Duration + if options.Follow { + timeout = math.MaxInt64 // No timeout + } + // Ignore wait error because logFunc has no concept of completion, we just want to print log entries until timeout is reached + if _, err := deployServiceWait(target, logFunc, requestFunc, timeout, retryInterval); err != nil && !errors.Is(err, ErrWaitTimeout) { + return fmt.Errorf("failed to read logs: %s", err) + } + return nil +} + // responseFunc returns whether a HTTP request is considered successful, based on its status and response data. // Returning false indicates that the operation should be retried. An error is returned if the response is considered // terminal and that the request should not be retried. diff --git a/client/go/internal/vespa/target_cloud.go b/client/go/internal/vespa/target_cloud.go index 6883515cee5..05d6bdd224e 100644 --- a/client/go/internal/vespa/target_cloud.go +++ b/client/go/internal/vespa/target_cloud.go @@ -2,11 +2,8 @@ package vespa import ( - "bytes" "encoding/json" - "errors" "fmt" - "math" "net/http" "sort" "strconv" @@ -148,7 +145,7 @@ func (t *cloudTarget) ContainerServices(timeout time.Duration) ([]*Service, erro return services, nil } -func (t *cloudTarget) CheckVersion(clientVersion version.Version) error { +func (t *cloudTarget) CompatibleWith(clientVersion version.Version) error { if clientVersion.IsZero() { // development version is always fine return nil } @@ -190,61 +187,7 @@ func (t *cloudTarget) logsURL() string { } func (t *cloudTarget) PrintLog(options LogOptions) error { - req, err := http.NewRequest("GET", t.logsURL(), nil) - if err != nil { - return err - } - lastFrom := options.From - requestFunc := func() *http.Request { - fromMillis := lastFrom.Unix() * 1000 - q := req.URL.Query() - q.Set("from", strconv.FormatInt(fromMillis, 10)) - if !options.To.IsZero() { - toMillis := options.To.Unix() * 1000 - q.Set("to", strconv.FormatInt(toMillis, 10)) - } - req.URL.RawQuery = q.Encode() - return req - } - logFunc := func(status int, response []byte) (bool, error) { - if ok, err := isOK(status); !ok { - return ok, err - } - logEntries, err := ReadLogEntries(bytes.NewReader(response)) - if err != nil { - return false, err - } - for _, le := range logEntries { - if !le.Time.After(lastFrom) { - continue - } - if LogLevel(le.Level) > options.Level { - continue - } - fmt.Fprintln(options.Writer, le.Format(options.Dequote)) - } - if len(logEntries) > 0 { - lastFrom = logEntries[len(logEntries)-1].Time - } - return false, nil - } - var timeout time.Duration - if options.Follow { - timeout = math.MaxInt64 // No timeout - } - // Ignore wait error because logFunc has no concept of completion, we just want to print log entries until timeout is reached - if _, err := t.deployServiceWait(logFunc, requestFunc, timeout); err != nil && !errors.Is(err, ErrWaitTimeout) { - return fmt.Errorf("failed to read logs: %s", err) - } - return nil -} - -func (t *cloudTarget) deployServiceWait(fn responseFunc, reqFn requestFunc, timeout time.Duration) (int, error) { - deployService, err := t.DeployService() - if err != nil { - return 0, err - } - return wait(deployService, fn, reqFn, timeout, t.retryInterval) + return pollLogs(t, t.logsURL(), options, t.retryInterval) } func (t *cloudTarget) discoverLatestRun(timeout time.Duration) (int64, error) { @@ -269,7 +212,7 @@ func (t *cloudTarget) discoverLatestRun(timeout time.Duration) (int64, error) { } return false, nil } - _, err = t.deployServiceWait(jobsSuccessFunc, requestFunc, timeout) + _, err = deployServiceWait(t, jobsSuccessFunc, requestFunc, timeout, t.retryInterval) return lastRunID, err } @@ -314,7 +257,7 @@ func (t *cloudTarget) AwaitDeployment(runID int64, timeout time.Duration) (int64 success = true return success, nil } - _, err = t.deployServiceWait(jobSuccessFunc, requestFunc, timeout) + _, err = deployServiceWait(t, jobSuccessFunc, requestFunc, timeout, t.retryInterval) if err != nil { return 0, fmt.Errorf("deployment run %d not yet complete%s: %w", runID, waitDescription(timeout), err) } @@ -378,7 +321,7 @@ func (t *cloudTarget) discoverEndpoints(timeout time.Duration) (map[string]strin } return true, nil } - if _, err := t.deployServiceWait(endpointFunc, func() *http.Request { return req }, timeout); err != nil { + if _, err := deployServiceWait(t, endpointFunc, func() *http.Request { return req }, timeout, t.retryInterval); err != nil { return nil, fmt.Errorf("no endpoints found in zone %s%s: %w", t.deploymentOptions.Deployment.Zone, waitDescription(timeout), err) } if len(urlsByCluster) == 0 { diff --git a/client/go/internal/vespa/target_custom.go b/client/go/internal/vespa/target_custom.go index 9d62f7dc297..1f72308178a 100644 --- a/client/go/internal/vespa/target_custom.go +++ b/client/go/internal/vespa/target_custom.go @@ -64,10 +64,48 @@ func (t *customTarget) IsCloud() bool { return false } func (t *customTarget) Deployment() Deployment { return DefaultDeployment } func (t *customTarget) PrintLog(options LogOptions) error { - return fmt.Errorf("log access is only supported on cloud: run vespa-logfmt on the admin node instead, or export from a container image (here named 'vespa') using docker exec vespa vespa-logfmt") + deployService, err := t.DeployService() + if err != nil { + return err + } + logsURL := deployService.BaseURL + "/application/v2/tenant/default/application/default/environment/prod/region/default/instance/default/logs" + return pollLogs(t, logsURL, options, t.retryInterval) } -func (t *customTarget) CheckVersion(version version.Version) error { return nil } +func (t *customTarget) CompatibleWith(minVersion version.Version) error { + if minVersion.IsZero() { // development version is always fine + return nil + } + deployService, err := t.DeployService() + if err != nil { + return err + } + versionURL := deployService.BaseURL + "/state/v1/version" + req, err := http.NewRequest("GET", versionURL, nil) + if err != nil { + return err + } + var versionResponse struct { + Version string `json:"version"` + } + response, err := deployService.Do(req, 10*time.Second) + if err != nil { + return err + } + defer response.Body.Close() + dec := json.NewDecoder(response.Body) + if err := dec.Decode(&versionResponse); err != nil { + return err + } + targetVersion, err := version.Parse(versionResponse.Version) + if err != nil { + return err + } + if targetVersion.Less(minVersion) { + return fmt.Errorf("platform version is older than required version: %s < %s", targetVersion, minVersion) + } + return nil +} func (t *customTarget) newService(url, name string, deployAPI bool) *Service { return &Service{ diff --git a/client/go/internal/vespa/target_test.go b/client/go/internal/vespa/target_test.go index 4c2fda8368e..f886c9117a9 100644 --- a/client/go/internal/vespa/target_test.go +++ b/client/go/internal/vespa/target_test.go @@ -117,6 +117,22 @@ func TestCustomTargetAwaitDeployment(t *testing.T) { assert.Equal(t, int64(42), convergedID) } +func TestCustomTargetCompatibleWith(t *testing.T) { + client := &mock.HTTPClient{} + target := CustomTarget(client, "http://192.0.2.42", TLSOptions{}, 0) + for i := 0; i < 3; i++ { + client.NextResponse(mock.HTTPResponse{ + URI: "/state/v1/version", + Status: 200, + Body: []byte(`{"version": "1.2.3"}`), + }) + } + assert.Nil(t, target.CompatibleWith(version.MustParse("1.2.2"))) + assert.Nil(t, target.CompatibleWith(version.MustParse("1.2.3"))) + assert.NotNil(t, target.CompatibleWith(version.MustParse("1.2.4"))) + assert.True(t, client.Consumed()) +} + func TestCloudTargetWait(t *testing.T) { var logWriter bytes.Buffer target, client := createCloudTarget(t, &logWriter) @@ -231,14 +247,14 @@ func TestLog(t *testing.T) { assert.Equal(t, expected, buf.String()) } -func TestCheckVersion(t *testing.T) { +func TestCloudCompatibleWith(t *testing.T) { target, client := createCloudTarget(t, io.Discard) for i := 0; i < 3; i++ { client.NextResponse(mock.HTTPResponse{URI: "/cli/v1/", Status: 200, Body: []byte(`{"minVersion":"8.0.0"}`)}) } - assert.Nil(t, target.CheckVersion(version.MustParse("8.0.0"))) - assert.Nil(t, target.CheckVersion(version.MustParse("8.1.0"))) - assert.NotNil(t, target.CheckVersion(version.MustParse("7.0.0"))) + assert.Nil(t, target.CompatibleWith(version.MustParse("8.0.0"))) + assert.Nil(t, target.CompatibleWith(version.MustParse("8.1.0"))) + assert.NotNil(t, target.CompatibleWith(version.MustParse("7.0.0"))) } func createCloudTarget(t *testing.T, logWriter io.Writer) (Target, *mock.HTTPClient) { diff --git a/config-model/src/main/java/com/yahoo/vespa/model/admin/LogserverContainer.java b/config-model/src/main/java/com/yahoo/vespa/model/admin/LogserverContainer.java index db9f97451b8..12892cb12ac 100644 --- a/config-model/src/main/java/com/yahoo/vespa/model/admin/LogserverContainer.java +++ b/config-model/src/main/java/com/yahoo/vespa/model/admin/LogserverContainer.java @@ -13,7 +13,6 @@ public class LogserverContainer extends Container { public LogserverContainer(TreeConfigProducer<?> parent, DeployState deployState) { super(parent, "" + 0, 0, deployState); - useDynamicPorts(); } @Override diff --git a/config-model/src/main/java/com/yahoo/vespa/model/builder/xml/dom/DomAdminV2Builder.java b/config-model/src/main/java/com/yahoo/vespa/model/builder/xml/dom/DomAdminV2Builder.java index a5cf9df45a1..34df7e9d963 100644 --- a/config-model/src/main/java/com/yahoo/vespa/model/builder/xml/dom/DomAdminV2Builder.java +++ b/config-model/src/main/java/com/yahoo/vespa/model/builder/xml/dom/DomAdminV2Builder.java @@ -78,6 +78,7 @@ public class DomAdminV2Builder extends DomAdminBuilderBase { logserverClusterModel.setCluster(logServerCluster); LogserverContainer container = new LogserverContainer(logServerCluster, deployState); + container.useDynamicPorts(); container.setHostResource(hostResource); container.initService(deployState); logServerCluster.addContainer(container); diff --git a/config-model/src/main/java/com/yahoo/vespa/model/builder/xml/dom/DomAdminV4Builder.java b/config-model/src/main/java/com/yahoo/vespa/model/builder/xml/dom/DomAdminV4Builder.java index 347bb504857..c6086327a1c 100644 --- a/config-model/src/main/java/com/yahoo/vespa/model/builder/xml/dom/DomAdminV4Builder.java +++ b/config-model/src/main/java/com/yahoo/vespa/model/builder/xml/dom/DomAdminV4Builder.java @@ -111,6 +111,8 @@ public class DomAdminV4Builder extends DomAdminBuilderBase { logserverClusterModel.setCluster(logServerCluster); LogserverContainer container = new LogserverContainer(logServerCluster, deployState); + if (deployState.getProperties().applicationId().instance().isTester()) + container.useDynamicPorts(); // TODO: read current version in ApplicationRepository, and always use this. container.setHostResource(hostResource); container.initService(deployState); logServerCluster.addContainer(container); diff --git a/flags/src/main/java/com/yahoo/vespa/flags/Flags.java b/flags/src/main/java/com/yahoo/vespa/flags/Flags.java index de52dfe612b..67f1cf25510 100644 --- a/flags/src/main/java/com/yahoo/vespa/flags/Flags.java +++ b/flags/src/main/java/com/yahoo/vespa/flags/Flags.java @@ -451,6 +451,13 @@ public class Flags { "Takes effect immediately", INSTANCE_ID); + public static final UnboundBooleanFlag ENABLE_NEW_TRIAL = defineFeatureFlag( + "enable-new-trial", false, + List.of("bjorncs"), "2024-06-18", "2025-01-01", + "Whether to enable the new trial experience", + "Takes effect immediately", + TENANT_ID); + public static final UnboundBooleanFlag ENFORCE_STRICTLY_INCREASING_CLUSTER_STATE_VERSIONS = defineFeatureFlag( "enforce-strictly-increasing-cluster-state-versions", false, List.of("vekterli"), "2024-06-03", "2024-08-01", diff --git a/logforwarder/src/apps/vespa-otelcol-start/child-handler.cpp b/logforwarder/src/apps/vespa-otelcol-start/child-handler.cpp index 4c5882b9710..a69f090e4df 100644 --- a/logforwarder/src/apps/vespa-otelcol-start/child-handler.cpp +++ b/logforwarder/src/apps/vespa-otelcol-start/child-handler.cpp @@ -58,10 +58,18 @@ void ChildHandler::startChild(const std::string &progPath, const std::string &cf return; } if (child == 0) { - std::string cfArg1{"--config=file:" "/etc/otelcol/gw-config.yaml"}; - std::string cfArg2{"--config=file:" + cfPath}; - const char *cargv[] = { progPath.c_str(), cfArg1.c_str(), cfArg2.c_str(), nullptr }; - execv(progPath.c_str(), const_cast<char **>(cargv)); + std::string cfgPrefix{"--config=file:"}; + const char *gwCfg = "/etc/otelcol/gw-config.yaml"; + std::string cfArg1{cfgPrefix + gwCfg}; + std::string cfArg2{cfgPrefix + cfPath}; + if (access(gwCfg, R_OK) == 0) { + const char *cargv[] = { progPath.c_str(), cfArg1.c_str(), cfArg2.c_str(), nullptr }; + execv(progPath.c_str(), const_cast<char **>(cargv)); + } else { + fprintf(stderr, "info\tMissing config file: %s (running without it)\n", gwCfg); + const char *cargv[] = { progPath.c_str(), cfArg2.c_str(), nullptr }; + execv(progPath.c_str(), const_cast<char **>(cargv)); + } // if execv fails: perror(progPath.c_str()); std::_Exit(1); diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/lb/LoadBalancer.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/lb/LoadBalancer.java index 0135f89c47e..1ec2e43bac0 100644 --- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/lb/LoadBalancer.java +++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/lb/LoadBalancer.java @@ -80,6 +80,17 @@ public class LoadBalancer { return new LoadBalancer(id, idSeed, Optional.of(instance), state, changedAt); } + @Override + public String toString() { + return "LoadBalancer{" + + "id=" + id + + ", idSeed='" + idSeed + '\'' + + ", instance=" + instance + + ", state=" + state + + ", changedAt=" + changedAt + + '}'; + } + /** Returns the effective container ID of given cluster. For combined clusters this returns the ID of the container cluster */ public static ClusterSpec.Id containerId(ClusterSpec cluster) { return cluster.combinedId().orElse(cluster.id()); diff --git a/searchlib/src/tests/searchcommon/schema/schema_test.cpp b/searchlib/src/tests/searchcommon/schema/schema_test.cpp index ad36454b6d7..6e33662a83e 100644 --- a/searchlib/src/tests/searchcommon/schema/schema_test.cpp +++ b/searchlib/src/tests/searchcommon/schema/schema_test.cpp @@ -3,6 +3,7 @@ #include <vespa/searchcommon/common/schema.h> #include <vespa/searchcommon/common/schemaconfigurer.h> #include <vespa/vespalib/gtest/gtest.h> +#include <vespa/vespalib/testkit/test_path.h> #include <vespa/vespalib/stllike/string.h> #include <fstream> @@ -18,6 +19,10 @@ using schema::CollectionType; using SIAF = Schema::ImportedAttributeField; using SIF = Schema::IndexField; +vespalib::string src_path(vespalib::stringref prefix, vespalib::stringref path) { + return prefix + TEST_PATH(path); +} + void assertField(const Schema::Field& exp, const Schema::Field& act) { @@ -144,7 +149,7 @@ TEST(SchemaTest, test_load_and_save) { // load from config -> save to file -> load from file Schema s; - SchemaConfigurer configurer(s, "dir:load-save-cfg"); + SchemaConfigurer configurer(s, src_path("dir:", "load-save-cfg")); EXPECT_EQ(3u, s.getNumIndexFields()); assertIndexField(SIF("a", SDT::STRING), s.getIndexField(0)); assertIndexField(SIF("b", SDT::INT64), s.getIndexField(1)); @@ -308,7 +313,7 @@ TEST(SchemaTest, require_that_imported_attribute_fields_are_not_saved_to_disk) TEST(SchemaTest, require_that_schema_can_be_built_with_imported_attribute_fields) { Schema s; - SchemaConfigurer configurer(s, "dir:imported-fields-cfg"); + SchemaConfigurer configurer(s, src_path("dir:", "imported-fields-cfg")); const auto &imported = s.getImportedAttributeFields(); ASSERT_EQ(2u, imported.size()); @@ -323,7 +328,7 @@ TEST(SchemaTest, require_that_schema_can_be_built_with_imported_attribute_fields TEST(SchemaTest, require_that_index_field_is_loaded_with_default_values_when_properties_are_not_set) { Schema s; - s.loadFromFile("schema-without-index-field-properties.txt"); + s.loadFromFile(TEST_PATH("schema-without-index-field-properties.txt")); const auto& index_fields = s.getIndexFields(); ASSERT_EQ(1, index_fields.size()); @@ -336,7 +341,7 @@ TEST(SchemaTest, require_that_index_field_is_loaded_with_default_values_when_pro TEST(SchemaTest, test_load_from_saved_schema_with_summary_fields) { - vespalib::string schema_name("old-schema-with-summary-fields.txt"); + vespalib::string schema_name(TEST_PATH("old-schema-with-summary-fields.txt")); Schema s; s.addIndexField(Schema::IndexField("ifoo", DataType::STRING)); s.addIndexField(Schema::IndexField("ibar", DataType::INT32)); diff --git a/storage/src/tests/distributor/distributor_host_info_reporter_test.cpp b/storage/src/tests/distributor/distributor_host_info_reporter_test.cpp index e9c1cea38f3..c56911a066e 100644 --- a/storage/src/tests/distributor/distributor_host_info_reporter_test.cpp +++ b/storage/src/tests/distributor/distributor_host_info_reporter_test.cpp @@ -9,6 +9,7 @@ #include <vespa/vespalib/stllike/asciistream.h> #include <chrono> #include <vespa/vespalib/gtest/gtest.h> +#include <vespa/vespalib/testkit/test_path.h> namespace storage::distributor { @@ -182,7 +183,7 @@ TEST_F(DistributorHostInfoReporterTest, generate_example_json) { std::string jsonString = json.str(); - std::string path = "../../../../protocols/getnodestate/distributor.json"; + std::string path = TEST_PATH("../../../../protocols/getnodestate/distributor.json"); std::string goldenString = File::readAll(path); vespalib::Memory goldenMemory(goldenString); diff --git a/storage/src/tests/distributor/getoperationtest.cpp b/storage/src/tests/distributor/getoperationtest.cpp index 4450d21c651..cad8252772e 100644 --- a/storage/src/tests/distributor/getoperationtest.cpp +++ b/storage/src/tests/distributor/getoperationtest.cpp @@ -17,7 +17,8 @@ #include <vespa/storage/distributor/operations/external/getoperation.h> #include <vespa/storageapi/message/persistence.h> #include <iomanip> -#include <gtest/gtest.h> +#include <vespa/vespalib/gtest/gtest.h> +#include <vespa/vespalib/testkit/test_path.h> #include <gmock/gmock.h> using config::ConfigGetter; @@ -43,7 +44,7 @@ struct GetOperationTest : Test, DistributorStripeTestUtil { _repo.reset( new document::DocumentTypeRepo(*ConfigGetter<DocumenttypesConfig>:: getConfig("config-doctypes", - FileSpec("../config-doctypes.cfg")))); + FileSpec(TEST_PATH("../config-doctypes.cfg"))))); createLinks(); docId = document::DocumentId("id:ns:text/html::uri"); diff --git a/storage/src/tests/distributor/updateoperationtest.cpp b/storage/src/tests/distributor/updateoperationtest.cpp index e00ce249298..d8a1affde58 100644 --- a/storage/src/tests/distributor/updateoperationtest.cpp +++ b/storage/src/tests/distributor/updateoperationtest.cpp @@ -11,7 +11,8 @@ #include <vespa/storageapi/message/bucket.h> #include <vespa/storageapi/message/persistence.h> #include <vespa/storageapi/message/state.h> -#include <gtest/gtest.h> +#include <vespa/vespalib/gtest/gtest.h> +#include <vespa/vespalib/testkit/test_path.h> using config::ConfigGetter; using config::FileSpec; @@ -31,7 +32,7 @@ struct UpdateOperationTest : Test, DistributorStripeTestUtil { UpdateOperationTest() : _repo(std::make_shared<DocumentTypeRepo>(*ConfigGetter<DocumenttypesConfig>:: - getConfig("config-doctypes", FileSpec("../config-doctypes.cfg")))), + getConfig("config-doctypes", FileSpec(TEST_PATH("../config-doctypes.cfg"))))), _html_type(_repo->getDocumentType("text/html")) { } |