summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--bundle-plugin/pom.xml4
-rw-r--r--configserver/src/main/java/com/yahoo/vespa/config/server/application/HttpProxy.java5
-rw-r--r--configserver/src/test/java/com/yahoo/vespa/config/server/application/HttpProxyTest.java9
-rw-r--r--container-core/src/main/java/com/yahoo/jdisc/http/server/jetty/JettyConnectionLogger.java2
-rw-r--r--controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/zone/ZoneRegistry.java3
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/ApplicationController.java2
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/Controller.java3
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/DeploymentStatus.java8
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/InternalStepRunner.java34
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/JobController.java4
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/JobList.java2
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/JobMetrics.java2
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/JobStatus.java15
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/Run.java10
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/RunStatus.java3
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/Step.java1
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/notify/Notifier.java38
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/persistence/RunSerializer.java4
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/deployment/Badges.java41
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/deployment/DeploymentContext.java29
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/deployment/InternalStepRunnerTest.java37
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/integration/ConfigServerMock.java11
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/integration/ZoneRegistryMock.java5
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/maintenance/JobRunnerTest.java1
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/notification/NotificationsDbTest.java3
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/deployment/BadgeApiTest.java8
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/deployment/responses/history.svg42
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/deployment/responses/history2.svg42
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/deployment/responses/overview.svg16
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/deployment/responses/single-done.svg10
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/deployment/responses/single-running.svg8
-rw-r--r--flags/src/main/java/com/yahoo/vespa/flags/Flags.java7
-rw-r--r--hosted-api/src/main/java/ai/vespa/hosted/api/ControllerHttpClient.java2
-rw-r--r--hosted-api/src/main/java/ai/vespa/hosted/api/Submission.java9
-rw-r--r--jdisc_core_test/test_bundles/cert-k-pkgs/src/main/java/com/yahoo/jdisc/bundle/k/CertificateK.java5
-rw-r--r--parent/pom.xml2
-rw-r--r--searchlib/src/main/java/com/yahoo/searchlib/expression/IntegerBucketResultNode.java10
-rw-r--r--searchlib/src/test/java/com/yahoo/searchlib/expression/IntegerBucketResultNodeTestCase.java13
-rw-r--r--searchlib/src/vespa/searchlib/features/dotproductfeature.cpp81
-rw-r--r--searchlib/src/vespa/searchlib/features/dotproductfeature.h30
-rw-r--r--searchlib/src/vespa/searchlib/tensor/hnsw_index.cpp1
-rw-r--r--vespa-maven-plugin/src/main/java/ai/vespa/hosted/plugin/SubmitMojo.java11
42 files changed, 339 insertions, 234 deletions
diff --git a/bundle-plugin/pom.xml b/bundle-plugin/pom.xml
index d53c2c94d5c..8f52187357f 100644
--- a/bundle-plugin/pom.xml
+++ b/bundle-plugin/pom.xml
@@ -19,6 +19,10 @@
</prerequisites>
<dependencies>
<dependency>
+ <groupId>com.google.guava</groupId>
+ <artifactId>guava</artifactId>
+ </dependency>
+ <dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-plugin-api</artifactId>
<version>3.8.5</version>
diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/application/HttpProxy.java b/configserver/src/main/java/com/yahoo/vespa/config/server/application/HttpProxy.java
index 5f7ace38a2c..66fd84e11d3 100644
--- a/configserver/src/main/java/com/yahoo/vespa/config/server/application/HttpProxy.java
+++ b/configserver/src/main/java/com/yahoo/vespa/config/server/application/HttpProxy.java
@@ -17,14 +17,11 @@ import com.yahoo.vespa.config.server.http.NotFoundException;
import com.yahoo.vespa.config.server.http.SimpleHttpFetcher;
import java.io.ByteArrayOutputStream;
-import java.io.FilterOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.charset.Charset;
-import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.logging.Logger;
-import java.util.regex.Pattern;
import static java.nio.charset.StandardCharsets.UTF_8;
@@ -63,7 +60,7 @@ public class HttpProxy {
.orElseThrow(() -> new NotFoundException("Failed to find HTTP state port"));
HttpURL url = HttpURL.create(Scheme.http, DomainName.of(host.getHostname()), port.getPort(), path, query);
- HttpResponse response = fetcher.get(new Params(2000), // 2_000 ms read timeout
+ HttpResponse response = fetcher.get(new Params(29_000), // 29 sec (30 sec on controller)
url.asURI());
return forwardedUrl == null ? response : new UrlRewritingProxyResponse(response, url, forwardedUrl);
}
diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/application/HttpProxyTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/application/HttpProxyTest.java
index 80e998521a9..e3820ff99be 100644
--- a/configserver/src/test/java/com/yahoo/vespa/config/server/application/HttpProxyTest.java
+++ b/configserver/src/test/java/com/yahoo/vespa/config/server/application/HttpProxyTest.java
@@ -2,13 +2,13 @@
package com.yahoo.vespa.config.server.application;
import ai.vespa.http.HttpURL;
+import ai.vespa.http.HttpURL.Path;
import ai.vespa.http.HttpURL.Query;
import com.yahoo.config.model.api.HostInfo;
import com.yahoo.config.model.api.Model;
import com.yahoo.config.model.api.ServiceInfo;
import com.yahoo.config.provision.ClusterSpec;
import com.yahoo.container.jdisc.HttpResponse;
-import ai.vespa.http.HttpURL.Path;
import com.yahoo.slime.Slime;
import com.yahoo.slime.SlimeUtils;
import com.yahoo.vespa.config.server.http.HttpFetcher;
@@ -21,8 +21,6 @@ import org.mockito.ArgumentCaptor;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.net.URI;
-import java.net.URL;
-import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.Collections;
@@ -30,7 +28,6 @@ import static com.yahoo.config.model.api.container.ContainerServiceType.CLUSTERC
import static com.yahoo.vespa.config.server.application.MockModel.createServiceInfo;
import static java.nio.charset.StandardCharsets.UTF_8;
import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotSame;
import static org.junit.Assert.assertSame;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doAnswer;
@@ -53,7 +50,7 @@ public class HttpProxyTest {
}
@Test
- public void testNormalGet() throws Exception {
+ public void testNormalGet() {
ArgumentCaptor<HttpFetcher.Params> actualParams = ArgumentCaptor.forClass(HttpFetcher.Params.class);
ArgumentCaptor<URI> actualUrl = ArgumentCaptor.forClass(URI.class);
HttpResponse response = new StaticResponse(200, "application/json", "body");
@@ -64,7 +61,7 @@ public class HttpProxyTest {
Query.parse("foo=bar"));
assertEquals(1, actualParams.getAllValues().size());
- assertEquals(2000, actualParams.getValue().readTimeoutMs);
+ assertEquals(29000, actualParams.getValue().readTimeoutMs);
assertEquals(1, actualUrl.getAllValues().size());
assertEquals(URI.create("http://" + hostname + ":" + port + "/clustercontroller-status/v1/clusterName?foo=bar"),
diff --git a/container-core/src/main/java/com/yahoo/jdisc/http/server/jetty/JettyConnectionLogger.java b/container-core/src/main/java/com/yahoo/jdisc/http/server/jetty/JettyConnectionLogger.java
index 4e3fd3f29b3..2e2eb257b6a 100644
--- a/container-core/src/main/java/com/yahoo/jdisc/http/server/jetty/JettyConnectionLogger.java
+++ b/container-core/src/main/java/com/yahoo/jdisc/http/server/jetty/JettyConnectionLogger.java
@@ -311,7 +311,7 @@ class JettyConnectionLogger extends AbstractLifeCycle implements Connection.List
this.sslSubjectAlternativeNames = X509CertificateUtils.getSubjectAlternativeNames(peerCertificate).stream()
.map(SubjectAlternativeName::getValue)
.collect(Collectors.toList());
- this.sslPeerIssuerSubject = peerCertificate.getIssuerDN().getName();
+ this.sslPeerIssuerSubject = peerCertificate.getIssuerX500Principal().getName();
this.sslPeerEncodedCertificate = peerCertificate.getEncoded();
} catch (SSLPeerUnverifiedException | CertificateEncodingException e) {
// Throw if peer is not authenticated (e.g when client auth is disabled)
diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/zone/ZoneRegistry.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/zone/ZoneRegistry.java
index 893b7a1b1dc..935ba17eed6 100644
--- a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/zone/ZoneRegistry.java
+++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/zone/ZoneRegistry.java
@@ -81,6 +81,9 @@ public interface ZoneRegistry {
/** Returns a URL where an informative dashboard can be found. */
URI dashboardUrl();
+ /** Returns a URL which displays information about the given tenant. */
+ URI dashboardUrl(TenantName id);
+
/** Returns a URL which displays information about the given application. */
URI dashboardUrl(ApplicationId id);
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/ApplicationController.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/ApplicationController.java
index 3be5345b377..0f7cbcee4ab 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/ApplicationController.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/ApplicationController.java
@@ -287,7 +287,7 @@ public class ApplicationController {
if (oldest == null || version.isBefore(oldest))
oldest = version;
- if (run.status() == RunStatus.success)
+ if (run.hasSucceeded())
return Optional.of(oldest);
}
// If no successful run was found, ask the node repository in the relevant zone.
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/Controller.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/Controller.java
index ca8f6a3ae33..48e663e7feb 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/Controller.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/Controller.java
@@ -13,7 +13,6 @@ import com.yahoo.config.provision.zone.ZoneApi;
import com.yahoo.container.jdisc.secretstore.SecretStore;
import com.yahoo.jdisc.Metric;
import com.yahoo.transaction.Mutex;
-import com.yahoo.vespa.curator.Lock;
import com.yahoo.vespa.flags.FlagSource;
import com.yahoo.vespa.hosted.controller.api.integration.ServiceRegistry;
import com.yahoo.vespa.hosted.controller.api.integration.maven.MavenRepository;
@@ -124,7 +123,7 @@ public class Controller extends AbstractComponent {
auditLogger = new AuditLogger(curator, clock);
jobControl = new JobControl(new JobControlFlags(curator, flagSource));
archiveBucketDb = new CuratorArchiveBucketDb(this);
- notifier = new Notifier(curator, serviceRegistry.mailer());
+ notifier = new Notifier(curator, serviceRegistry.zoneRegistry(), serviceRegistry.mailer());
notificationsDb = new NotificationsDb(this);
supportAccessControl = new SupportAccessControl(this);
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/DeploymentStatus.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/DeploymentStatus.java
index 0595245b3d7..cb2958745d0 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/DeploymentStatus.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/DeploymentStatus.java
@@ -321,7 +321,7 @@ public class DeploymentStatus {
.type(type).asList().stream()
.flatMap(status -> RunList.from(status)
.on(versions)
- .status(RunStatus.success)
+ .matching(Run::hasSucceeded)
.asList().stream()
.map(Run::start))
.min(naturalOrder());
@@ -860,7 +860,7 @@ public class DeploymentStatus {
Optional<Instant> end = Optional.empty();
for (Run run : job.runs().descendingMap().values()) {
if (run.versions().targetsMatch(change)) {
- if (run.status() == RunStatus.success) end = run.end();
+ if (run.hasSucceeded()) end = run.end();
}
else if (dependent.equals(job())) // If strict completion, consider only last time this change was deployed.
break;
@@ -887,7 +887,7 @@ public class DeploymentStatus {
Optional<Instant> deployedAt = status.jobSteps().get(prodId).completedAt(change, Optional.of(prodId));
return (dependent.equals(job()) ? job.lastTriggered().filter(run -> deployedAt.map(at -> ! run.start().isBefore(at)).orElse(false)).stream()
: job.runs().values().stream())
- .filter(run -> run.status() == RunStatus.success)
+ .filter(Run::hasSucceeded)
.filter(run -> run.versions().targetsMatch(change))
.flatMap(run -> run.end().stream()).findFirst();
}
@@ -907,7 +907,7 @@ public class DeploymentStatus {
status.systemVersion)))
.orElseGet(() -> (change.platform().isEmpty() || change.platform().get().equals(run.versions().targetPlatform()))
&& (change.revision().isEmpty() || change.revision().get().equals(run.versions().targetRevision()))))
- .status(RunStatus.success)
+ .matching(Run::hasSucceeded)
.asList().stream()
.map(run -> run.end().get())
.max(naturalOrder());
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/InternalStepRunner.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/InternalStepRunner.java
index ce4bb70c174..28d9439b457 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/InternalStepRunner.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/InternalStepRunner.java
@@ -23,8 +23,6 @@ import com.yahoo.security.SignatureAlgorithm;
import com.yahoo.security.X509CertificateBuilder;
import com.yahoo.security.X509CertificateUtils;
import com.yahoo.text.Text;
-import com.yahoo.vespa.flags.FetchVector;
-import com.yahoo.vespa.flags.Flags;
import com.yahoo.vespa.hosted.controller.Application;
import com.yahoo.vespa.hosted.controller.Controller;
import com.yahoo.vespa.hosted.controller.Instance;
@@ -36,7 +34,6 @@ import com.yahoo.vespa.hosted.controller.api.integration.configserver.Node;
import com.yahoo.vespa.hosted.controller.api.integration.configserver.NodeFilter;
import com.yahoo.vespa.hosted.controller.api.integration.configserver.PrepareResponse;
import com.yahoo.vespa.hosted.controller.api.integration.configserver.ServiceConvergence;
-import com.yahoo.vespa.hosted.controller.api.integration.deployment.ApplicationVersion;
import com.yahoo.vespa.hosted.controller.api.integration.deployment.JobType;
import com.yahoo.vespa.hosted.controller.api.integration.deployment.RevisionId;
import com.yahoo.vespa.hosted.controller.api.integration.deployment.RunId;
@@ -90,6 +87,7 @@ import static com.yahoo.vespa.hosted.controller.api.integration.configserver.Nod
import static com.yahoo.vespa.hosted.controller.deployment.RunStatus.deploymentFailed;
import static com.yahoo.vespa.hosted.controller.deployment.RunStatus.error;
import static com.yahoo.vespa.hosted.controller.deployment.RunStatus.installationFailed;
+import static com.yahoo.vespa.hosted.controller.deployment.RunStatus.noTests;
import static com.yahoo.vespa.hosted.controller.deployment.RunStatus.nodeAllocationFailure;
import static com.yahoo.vespa.hosted.controller.deployment.RunStatus.reset;
import static com.yahoo.vespa.hosted.controller.deployment.RunStatus.running;
@@ -638,6 +636,7 @@ public class InternalStepRunner implements StepRunner {
return Optional.of(running);
}
+ @SuppressWarnings("fallthrough")
private Optional<RunStatus> endTests(RunId id, boolean isSetup, DualLogger logger) {
Optional<Deployment> deployment = deployment(id.application(), id.type());
if (deployment.isEmpty()) {
@@ -679,12 +678,14 @@ public class InternalStepRunner implements StepRunner {
controller.jobController().updateTestReport(id);
return Optional.of(error);
case NO_TESTS:
- TesterCloud.Suite suite = TesterCloud.Suite.of(id.type(), isSetup);
- logger.log(INFO, "No tests were found in the test package, for test suite '" + suite + "'");
- logger.log(INFO, "The test package must either contain basic HTTP tests under 'tests/<suite-name>/', " +
- "or a Java test bundle under 'components/' with at least one test with the annotation " +
- "for this suite. See docs.vespa.ai/en/testing.html for details.");
- return Optional.of(allowNoTests(id.application()) ? running : testFailure);
+ if ( ! isSetup) { // TODO: consider changing this Laterâ„¢
+ TesterCloud.Suite suite = TesterCloud.Suite.of(id.type(), isSetup);
+ logger.log(INFO, "No tests were found in the test package, for test suite '" + suite + "'");
+ logger.log(INFO, "The test package should either contain basic HTTP tests under 'tests/<suite-name>/', " +
+ "or a Java test bundle under 'components/' with at least one test with the annotation " +
+ "for this suite. See docs.vespa.ai/en/testing.html for details.");
+ return Optional.of(noTests);
+ }
case SUCCESS:
logger.log("Tests completed successfully.");
controller.jobController().updateTestReport(id);
@@ -694,12 +695,6 @@ public class InternalStepRunner implements StepRunner {
}
}
- private boolean allowNoTests(ApplicationId appId) {
- return Flags.ALLOW_NO_TESTS.bindTo(controller.flagSource())
- .with(FetchVector.Dimension.TENANT_ID, appId.tenant().value())
- .value();
- }
-
private Optional<RunStatus> copyVespaLogs(RunId id, DualLogger logger) {
if (deployment(id.application(), id.type()).isPresent())
try {
@@ -835,6 +830,10 @@ public class InternalStepRunner implements StepRunner {
case testFailure:
updater.accept("one or more verification tests against the deployment failed. Please review test output in the deployment job log.");
return;
+ case noTests:
+ controller.notificationsDb().setNotification(source, Notification.Type.deployment, Notification.Level.warning,
+ "no tests were found for this job type. Please review test output in the deployment job log.");
+ return;
case error:
case endpointCertificateTimeout:
break;
@@ -849,6 +848,7 @@ public class InternalStepRunner implements StepRunner {
switch (run.status()) {
case running:
case aborted:
+ case noTests:
case success:
return Optional.empty();
case nodeAllocationFailure:
@@ -861,11 +861,11 @@ public class InternalStepRunner implements StepRunner {
return Optional.of(mails.testFailure(run.id(), recipients));
case error:
case endpointCertificateTimeout:
- return Optional.of(mails.systemError(run.id(), recipients));
+ break;
default:
logger.log(WARNING, "Don't know what mail to send for run status '" + run.status() + "'");
- return Optional.of(mails.systemError(run.id(), recipients));
}
+ return Optional.of(mails.systemError(run.id(), recipients));
}
/** Returns the deployment of the real application in the zone of the given job, if it exists. */
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/JobController.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/JobController.java
index 74730a78e31..b9ce094c1c0 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/JobController.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/JobController.java
@@ -400,7 +400,7 @@ public class JobController {
locked(id.application(), id.type(), runs -> {
runs.put(run.id(), finishedRun);
long last = id.number();
- long successes = runs.values().stream().filter(old -> old.status() == RunStatus.success).count();
+ long successes = runs.values().stream().filter(Run::hasSucceeded).count();
var oldEntries = runs.entrySet().iterator();
for (var old = oldEntries.next();
old.getKey().number() <= last - historyLength
@@ -409,7 +409,7 @@ public class JobController {
// Make sure we keep the last success and the first failing
if ( successes == 1
- && old.getValue().status() == RunStatus.success
+ && old.getValue().hasSucceeded()
&& ! old.getValue().start().isBefore(controller.clock().instant().minus(maxHistoryAge))) {
oldEntries.next();
continue;
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/JobList.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/JobList.java
index 639702128d3..387ea755414 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/JobList.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/JobList.java
@@ -120,7 +120,7 @@ public class JobList extends AbstractFilteringList<JobStatus, JobList> {
/** Returns the jobs with successful runs matching the given versions — targets only for system test, everything present otherwise. */
public JobList successOn(Versions versions) {
- return matching(job -> ! RunList.from(job).status(RunStatus.success).on(versions).isEmpty());
+ return matching(job -> ! RunList.from(job).matching(Run::hasSucceeded).on(versions).isEmpty());
}
// ----------------------------------- JobRun filtering
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/JobMetrics.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/JobMetrics.java
index 874b1828f5f..e95e515685f 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/JobMetrics.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/JobMetrics.java
@@ -21,6 +21,7 @@ public class JobMetrics {
public static final String deploymentFailure = "deployment.deploymentFailure";
public static final String convergenceFailure = "deployment.convergenceFailure";
public static final String testFailure = "deployment.testFailure";
+ public static final String noTests = "deployment.noTests";
public static final String error = "deployment.error";
public static final String abort = "deployment.abort";
public static final String success = "deployment.success";
@@ -56,6 +57,7 @@ public class JobMetrics {
case deploymentFailed: return deploymentFailure;
case installationFailed: return convergenceFailure;
case testFailure: return testFailure;
+ case noTests: return noTests;
case error: return error;
case aborted: return abort;
case success: return success;
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/JobStatus.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/JobStatus.java
index aad5d510261..45bf508f026 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/JobStatus.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/JobStatus.java
@@ -60,7 +60,7 @@ public class JobStatus {
}
public boolean isSuccess() {
- return lastStatus().isPresent() && lastStatus().get() == RunStatus.success;
+ return lastCompleted.map(last -> ! last.hasFailed()).orElse(false);
}
public boolean isRunning() {
@@ -90,18 +90,17 @@ public class JobStatus {
static Optional<Run> lastSuccess(NavigableMap<RunId, Run> runs) {
return runs.descendingMap().values().stream()
- .filter(run -> run.status() == RunStatus.success)
+ .filter(Run::hasSucceeded)
.findFirst();
}
static Optional<Run> firstFailing(NavigableMap<RunId, Run> runs) {
Run failed = null;
- loop: for (Run run : runs.descendingMap().values())
- switch (run.status()) {
- case running: continue loop;
- case success: break loop;
- default: failed = run;
- }
+ for (Run run : runs.descendingMap().values()) {
+ if ( ! run.hasEnded()) continue;
+ if ( ! run.hasFailed()) break;
+ failed = run;
+ }
return Optional.ofNullable(failed);
}
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/Run.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/Run.java
index dcde21c8cf5..03cc6c6ba8d 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/Run.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/Run.java
@@ -13,6 +13,7 @@ import java.util.Optional;
import java.util.stream.Collectors;
import static com.yahoo.vespa.hosted.controller.deployment.RunStatus.aborted;
+import static com.yahoo.vespa.hosted.controller.deployment.RunStatus.noTests;
import static com.yahoo.vespa.hosted.controller.deployment.RunStatus.running;
import static com.yahoo.vespa.hosted.controller.deployment.RunStatus.success;
import static com.yahoo.vespa.hosted.controller.deployment.Step.Status.succeeded;
@@ -80,8 +81,9 @@ public class Run {
EnumMap<Step, StepInfo> steps = new EnumMap<>(this.steps);
steps.put(step.get(), stepInfo.with(Step.Status.of(status)));
- return new Run(id, steps, versions, isRedeployment, start, end, sleepUntil, this.status == running ? status : this.status,
- lastTestRecord, lastVespaLogTimestamp, noNodesDownSince, convergenceSummary, testerCertificate, dryRun, reason);
+ RunStatus newStatus = hasFailed() || status == running ? this.status : status;
+ return new Run(id, steps, versions, isRedeployment, start, end, sleepUntil, newStatus, lastTestRecord,
+ lastVespaLogTimestamp, noNodesDownSince, convergenceSummary, testerCertificate, dryRun, reason);
}
/** Returns a new Run with a new start time*/
@@ -210,7 +212,7 @@ public class Run {
/** Returns whether the run has failed, and should switch to its run-always steps. */
public boolean hasFailed() {
- return status != running && status != success;
+ return status != running && status != success && status != noTests;
}
/** Returns whether the run has ended, i.e., has become inactive, and can no longer be updated. */
@@ -218,6 +220,8 @@ public class Run {
return end.isPresent();
}
+ public boolean hasSucceeded() { return hasEnded() && ! hasFailed(); }
+
/** Returns the target, and possibly source, versions for this run. */
public Versions versions() {
return versions;
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/RunStatus.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/RunStatus.java
index 0bb4a30425e..9ca634b19fd 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/RunStatus.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/RunStatus.java
@@ -26,6 +26,9 @@ public enum RunStatus {
/** The verification tests failed. */
testFailure,
+ /** No tests, for a test job. */
+ noTests,
+
/** An unexpected error occurred. */
error,
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/Step.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/Step.java
index 14d6b35f6ad..82d154dcf03 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/Step.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/Step.java
@@ -113,6 +113,7 @@ public enum Step {
case success : throw new AssertionError("Unexpected run status '" + status + "'!");
case reset :
case aborted : return unfinished;
+ case noTests :
case running : return succeeded;
default : return failed;
}
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/notify/Notifier.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/notify/Notifier.java
index 594908a3bc1..7692752f3ca 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/notify/Notifier.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/notify/Notifier.java
@@ -1,16 +1,21 @@
// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.vespa.hosted.controller.notify;
+import com.yahoo.config.provision.ApplicationId;
+import com.yahoo.config.provision.Environment;
import com.yahoo.text.Text;
+import com.yahoo.vespa.hosted.controller.api.integration.deployment.RunId;
import com.yahoo.vespa.hosted.controller.api.integration.organization.Mail;
import com.yahoo.vespa.hosted.controller.api.integration.organization.Mailer;
import com.yahoo.vespa.hosted.controller.api.integration.organization.MailerException;
+import com.yahoo.vespa.hosted.controller.api.integration.zone.ZoneRegistry;
import com.yahoo.vespa.hosted.controller.notification.Notification;
import com.yahoo.vespa.hosted.controller.notification.NotificationSource;
import com.yahoo.vespa.hosted.controller.persistence.CuratorDb;
import com.yahoo.vespa.hosted.controller.tenant.CloudTenant;
import com.yahoo.vespa.hosted.controller.tenant.TenantContacts;
+import java.net.URI;
import java.util.Collection;
import java.util.List;
import java.util.Objects;
@@ -25,12 +30,14 @@ import java.util.stream.Collectors;
*/
public class Notifier {
private final CuratorDb curatorDb;
+ private final ZoneRegistry zoneRegistry;
private final Mailer mailer;
private static final Logger log = Logger.getLogger(Notifier.class.getName());
- public Notifier(CuratorDb curatorDb, Mailer mailer) {
+ public Notifier(CuratorDb curatorDb, ZoneRegistry zoneRegistry, Mailer mailer) {
this.curatorDb = Objects.requireNonNull(curatorDb);
+ this.zoneRegistry = Objects.requireNonNull(zoneRegistry);
this.mailer = Objects.requireNonNull(mailer);
}
@@ -56,7 +63,12 @@ public class Notifier {
private boolean skipSource(NotificationSource source) {
// Limit sources to production systems only. Dev and test systems cause too much noise at the moment.
- return source.jobType().map(t -> !t.isProduction()).orElse(false);
+ if (source.zoneId().map(z -> z.environment() != Environment.prod).orElse(false)) {
+ return true;
+ } else if (source.jobType().map(t -> !t.isProduction()).orElse(false)) {
+ return true;
+ }
+ return false;
}
public void dispatch(Notification notification) {
@@ -82,12 +94,30 @@ public class Notifier {
}
private Mail mailOf(Notification n, Collection<String> recipients) {
- var subject = Text.format("[%s] Vespa Notification for %s", n.level().toString().toUpperCase(), n.type().name());
+ var source = n.source();
+ var subject = Text.format("[%s] %s Vespa Notification for %s - %s", n.level().toString().toUpperCase(), n.type().name(), source.tenant(), source.application());
var body = new StringBuilder();
body.append("Source: ").append(n.source().toString()).append("\n")
.append("\n")
- .append(String.join("\n", n.messages()));
+ .append(String.join("\n", n.messages()))
+ .append("\n")
+ .append(url(source).toString());
return new Mail(recipients, subject.toString(), body.toString());
}
+ private URI url(NotificationSource source) {
+ if (source.application().isPresent() && source.instance().isPresent()) {
+ if (source.jobType().isPresent() && source.runNumber().isPresent()) {
+ return zoneRegistry.dashboardUrl(
+ new RunId(ApplicationId.from(source.tenant(),
+ source.application().get(),
+ source.instance().get()),
+ source.jobType().get(),
+ source.runNumber().getAsLong()));
+ }
+ return zoneRegistry.dashboardUrl(ApplicationId.from(source.tenant(), source.application().get(), source.instance().get()));
+ }
+ return zoneRegistry.dashboardUrl(source.tenant());
+ }
+
}
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/persistence/RunSerializer.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/persistence/RunSerializer.java
index 731e5790a64..143aaaeabb8 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/persistence/RunSerializer.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/persistence/RunSerializer.java
@@ -35,6 +35,7 @@ import static com.yahoo.vespa.hosted.controller.deployment.RunStatus.deploymentF
import static com.yahoo.vespa.hosted.controller.deployment.RunStatus.endpointCertificateTimeout;
import static com.yahoo.vespa.hosted.controller.deployment.RunStatus.error;
import static com.yahoo.vespa.hosted.controller.deployment.RunStatus.installationFailed;
+import static com.yahoo.vespa.hosted.controller.deployment.RunStatus.noTests;
import static com.yahoo.vespa.hosted.controller.deployment.RunStatus.nodeAllocationFailure;
import static com.yahoo.vespa.hosted.controller.deployment.RunStatus.reset;
import static com.yahoo.vespa.hosted.controller.deployment.RunStatus.running;
@@ -342,6 +343,7 @@ class RunSerializer {
case deploymentFailed : return "deploymentFailed";
case installationFailed : return "installationFailed";
case testFailure : return "testFailure";
+ case noTests : return "noTests";
case error : return "error";
case success : return "success";
case aborted : return "aborted";
@@ -354,11 +356,11 @@ class RunSerializer {
static RunStatus runStatusOf(String status) {
switch (status) {
case "running" : return running;
- case "outOfCapacity" : return nodeAllocationFailure; // TODO: Remove after March 2022
case "nodeAllocationFailure" : return nodeAllocationFailure;
case "endpointCertificateTimeout" : return endpointCertificateTimeout;
case "deploymentFailed" : return deploymentFailed;
case "installationFailed" : return installationFailed;
+ case "noTests" : return noTests;
case "testFailure" : return testFailure;
case "error" : return error;
case "success" : return success;
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/deployment/Badges.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/deployment/Badges.java
index 1fe5ebfa9a9..7b4f2fec853 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/deployment/Badges.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/deployment/Badges.java
@@ -15,6 +15,7 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
+import java.util.Optional;
import static java.util.stream.Collectors.toList;
@@ -51,14 +52,18 @@ public class Badges {
return widthOf(text, 11);
}
- static String colorOf(Run run, Boolean wasOk) {
+ static String colorOf(Run run, Optional<RunStatus> previous) {
switch (run.status()) {
- case running:
- return wasOk ? "url(#run-on-success)" : "url(#run-on-failure)";
- case success:
- return success;
- default:
- return failure;
+ case running: switch (previous.orElse(RunStatus.success)) {
+ case success: return "url(#run-on-success)";
+ case aborted:
+ case noTests: return "url(#run-on-warning)";
+ default: return "url(#run-on-failure)";
+ }
+ case success: return success;
+ case aborted:
+ case noTests: return warning;
+ default: return failure;
}
}
@@ -71,9 +76,10 @@ public class Badges {
static final double xPad = 6;
static final double logoSize = 16;
static final String dark = "#404040";
- static final String success = "#00f244";
+ static final String success = "#00f844";
static final String running = "#ab83ff";
static final String failure = "#bf103c";
+ static final String warning = "#bd890b";
static void addText(List<String> texts, String text, double x, double width) {
addText(texts, text, x, width, 11);
@@ -116,13 +122,11 @@ public class Badges {
.limit(length)
.collect(toList());
- boolean isOk = status.lastCompleted().map(run -> run.status() == RunStatus.success).orElse(true);
-
text = lastTriggered.id().type().jobName();
textWidth = widthOf(text);
dx = xPad + textWidth + xPad;
addShade(sections, x, dx);
- sections.add(" <rect x='" + (x - 6) + "' rx='3' width='" + (dx + 6) + "' height='20' fill='" + colorOf(lastTriggered, isOk) + "'/>\n");
+ sections.add(" <rect x='" + (x - 6) + "' rx='3' width='" + (dx + 6) + "' height='20' fill='" + colorOf(lastTriggered, status.lastStatus()) + "'/>\n");
addShadow(sections, x + dx);
addText(texts, text, x + dx / 2, textWidth);
x += dx;
@@ -130,7 +134,7 @@ public class Badges {
dx = xPad * (192.0 / (32 + runs.size())); // Broader sections with shorter history.
for (Run run : runs) {
addShade(sections, x, dx);
- sections.add(" <rect x='" + (x - 6) + "' rx='3' width='" + (dx + 6) + "' height='20' fill='" + colorOf(run, null) + "'/>\n");
+ sections.add(" <rect x='" + (x - 6) + "' rx='3' width='" + (dx + 6) + "' height='20' fill='" + colorOf(run, Optional.empty()) + "'/>\n");
addShadow(sections, x + dx);
dx *= Math.pow(0.3, 1.0 / (runs.size() + 8)); // Gradually narrowing sections with age.
x += dx;
@@ -179,7 +183,7 @@ public class Badges {
text = nameOf(run.id().type());
textWidth = widthOf(text, isTest ? 9 : 11);
dx = xPad + textWidth + (isTest ? 0 : xPad);
- boolean wasOk = jobs.get(run.id().job()).flatMap(JobStatus::lastStatus).map(RunStatus.success::equals).orElse(true);
+ Optional<RunStatus> previous = jobs.get(run.id().job()).flatMap(JobStatus::lastStatus);
addText(texts, text, x + (dx - (isTest ? xPad : 0)) / 2, textWidth, isTest ? 9 : 11);
@@ -197,10 +201,10 @@ public class Badges {
// Add colored section for job ...
if (test == null)
- sections.add(" <rect x='" + (x - 16) + "' rx='3' width='" + (dx + 16) + "' height='20' fill='" + colorOf(run, wasOk) + "'/>\n");
+ sections.add(" <rect x='" + (x - 16) + "' rx='3' width='" + (dx + 16) + "' height='20' fill='" + colorOf(run, previous) + "'/>\n");
// ... with a slant if a test is next.
else
- sections.add(" <polygon points='" + (x - 6) + " 0 " + (x - 6) + " 20 " + (x + dx - 7) + " 20 " + (x + dx + 1) + " 0' fill='" + colorOf(run, wasOk) + "'/>\n");
+ sections.add(" <polygon points='" + (x - 6) + " 0 " + (x - 6) + " 20 " + (x + dx - 7) + " 20 " + (x + dx + 1) + " 0' fill='" + colorOf(run, previous) + "'/>\n");
// Cast a shadow onto the next zone ...
if (test == null)
@@ -255,6 +259,13 @@ public class Badges {
" <animate attributeName='x1' values='-110%;150%;20%;-110%' dur='6s' repeatCount='indefinite' />\n" +
" <animate attributeName='x2' values='-10%;250%;120%;-10%' dur='6s' repeatCount='indefinite' />\n" +
" </linearGradient>\n" +
+ // Running color sloshing back and forth on top of the warning color.
+ " <linearGradient id='run-on-warning' x1='40%' x2='80%' y2='0%'>\n" +
+ " <stop offset='0' stop-color='" + running + "' />\n" +
+ " <stop offset='1' stop-color='" + warning + "' />\n" +
+ " <animate attributeName='x1' values='-110%;150%;20%;-110%' dur='6s' repeatCount='indefinite' />\n" +
+ " <animate attributeName='x2' values='-10%;250%;120%;-10%' dur='6s' repeatCount='indefinite' />\n" +
+ " </linearGradient>\n" +
// Running color sloshing back and forth on top of the success color.
" <linearGradient id='run-on-success' x1='40%' x2='80%' y2='0%'>\n" +
" <stop offset='0' stop-color='" + running + "' />\n" +
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/deployment/DeploymentContext.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/deployment/DeploymentContext.java
index f18733fbcde..3765f815e49 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/deployment/DeploymentContext.java
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/deployment/DeploymentContext.java
@@ -28,6 +28,7 @@ import com.yahoo.vespa.hosted.controller.api.integration.deployment.RevisionId;
import com.yahoo.vespa.hosted.controller.api.integration.deployment.RunId;
import com.yahoo.vespa.hosted.controller.api.integration.deployment.SourceRevision;
import com.yahoo.vespa.hosted.controller.api.integration.deployment.TesterCloud;
+import com.yahoo.vespa.hosted.controller.api.integration.deployment.TesterCloud.Status;
import com.yahoo.vespa.hosted.controller.api.integration.deployment.TesterId;
import com.yahoo.vespa.hosted.controller.application.Deployment;
import com.yahoo.vespa.hosted.controller.application.EndpointId;
@@ -402,8 +403,34 @@ public class DeploymentContext {
return runJob(type, instanceId);
}
+ /** Runs the job, failing tests with noTests status, or with regular testFailure. */
+ public DeploymentContext failTests(JobType type, boolean noTests) {
+ if ( ! type.isTest()) throw new IllegalArgumentException(type + " does not run tests");
+ var job = new JobId(instanceId, type);
+ triggerJobs();
+ doDeploy(job);
+ if (job.type().isDeployment()) {
+ doUpgrade(job);
+ doConverge(job);
+ if (job.type().environment().isManuallyDeployed())
+ return this;
+ }
+
+ RunId id = currentRun(job).id();
+ ZoneId zone = zone(job);
+
+ assertEquals(unfinished, jobs.run(id).get().stepStatuses().get(Step.endTests));
+ tester.cloud().set(noTests ? Status.NO_TESTS : Status.FAILURE);
+ runner.advance(currentRun(job));
+ assertTrue(jobs.run(id).get().hasEnded());
+ assertEquals(noTests, jobs.run(id).get().hasSucceeded());
+ assertTrue(configServer().nodeRepository().list(zone, NodeFilter.all().applications(TesterId.of(instanceId).id())).isEmpty());
+
+ return this;
+ }
+
/** Pulls the ready job trigger, and then runs the whole of job for the given instance, successfully. */
- public DeploymentContext runJob(JobType type, ApplicationId instance) {
+ private DeploymentContext runJob(JobType type, ApplicationId instance) {
var job = new JobId(instance, type);
triggerJobs();
doDeploy(job);
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/deployment/InternalStepRunnerTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/deployment/InternalStepRunnerTest.java
index 98cbf33fb2b..15f729e7a55 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/deployment/InternalStepRunnerTest.java
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/deployment/InternalStepRunnerTest.java
@@ -24,6 +24,7 @@ import com.yahoo.vespa.hosted.controller.api.integration.deployment.JobType;
import com.yahoo.vespa.hosted.controller.api.integration.deployment.RunId;
import com.yahoo.vespa.hosted.controller.api.integration.deployment.TestReport;
import com.yahoo.vespa.hosted.controller.api.integration.deployment.TesterCloud;
+import com.yahoo.vespa.hosted.controller.api.integration.deployment.TesterCloud.Status;
import com.yahoo.vespa.hosted.controller.api.integration.stubs.MockMailer;
import com.yahoo.vespa.hosted.controller.application.SystemApplication;
import com.yahoo.vespa.hosted.controller.application.pkg.ApplicationPackage;
@@ -47,6 +48,8 @@ import java.util.List;
import java.util.Optional;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.function.Supplier;
import static com.yahoo.vespa.hosted.controller.api.integration.LogEntry.Type.error;
import static com.yahoo.vespa.hosted.controller.api.integration.LogEntry.Type.info;
@@ -55,6 +58,7 @@ import static com.yahoo.vespa.hosted.controller.deployment.DeploymentContext.app
import static com.yahoo.vespa.hosted.controller.deployment.DeploymentTester.instanceId;
import static com.yahoo.vespa.hosted.controller.deployment.RunStatus.deploymentFailed;
import static com.yahoo.vespa.hosted.controller.deployment.RunStatus.installationFailed;
+import static com.yahoo.vespa.hosted.controller.deployment.RunStatus.noTests;
import static com.yahoo.vespa.hosted.controller.deployment.RunStatus.running;
import static com.yahoo.vespa.hosted.controller.deployment.RunStatus.success;
import static com.yahoo.vespa.hosted.controller.deployment.Step.Status.failed;
@@ -62,6 +66,7 @@ import static com.yahoo.vespa.hosted.controller.deployment.Step.Status.succeeded
import static com.yahoo.vespa.hosted.controller.deployment.Step.Status.unfinished;
import static java.time.temporal.ChronoUnit.SECONDS;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertTrue;
@@ -123,22 +128,11 @@ public class InternalStepRunnerTest {
}
@Test
- // TODO jonmv: Change to only wait for restarts, and remove triggering of restarts from runner.
public void restartsServicesAndWaitsForRestartAndReboot() {
RunId id = app.newRun(JobType.productionUsCentral1);
ZoneId zone = id.type().zone(system());
HostName host = tester.configServer().hostFor(instanceId, zone);
- tester.configServer().setConfigChangeActions(new ConfigChangeActions(List.of(new RestartAction("cluster",
- "container",
- "search",
- List.of(new ServiceInfo("queries",
- "search",
- "config",
- host.value())),
- List.of("Restart it!"))),
- List.of(),
- List.of()));
tester.runner().run();
assertEquals(succeeded, tester.jobs().run(id).get().stepStatuses().get(Step.deployReal));
@@ -269,6 +263,27 @@ public class InternalStepRunnerTest {
}
@Test
+ public void noTestsThenErrorIsError() {
+ RunId id = app.startSystemTestTests();
+ Run run = tester.jobs().run(id).get();
+ run = run.with(noTests, new LockedStep(() -> { }, Step.endTests));
+ assertFalse(run.hasFailed());
+ run = run.with(RunStatus.error, new LockedStep(() -> { }, Step.deactivateReal));
+ assertTrue(run.hasFailed());
+ assertEquals(RunStatus.error, run.status());
+ }
+
+ @Test
+ public void noTestsThenSuccessIsNoTests() {
+ RunId id = app.startSystemTestTests();
+ tester.cloud().set(Status.NO_TESTS);
+ tester.runner().run();
+ assertEquals(succeeded, tester.jobs().run(id).get().stepStatuses().get(Step.endTests));
+ Run run = tester.jobs().run(id).get();
+ assertEquals(noTests, run.status());
+ }
+
+ @Test
public void testsFailIfTesterRestarts() {
RunId id = app.startSystemTestTests();
tester.cloud().set(TesterCloud.Status.NOT_STARTED);
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/integration/ConfigServerMock.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/integration/ConfigServerMock.java
index 644d60fbe72..1ed84659f58 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/integration/ConfigServerMock.java
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/integration/ConfigServerMock.java
@@ -98,7 +98,6 @@ public class ConfigServerMock extends AbstractComponent implements ConfigServer
private Version lastPrepareVersion = null;
private Consumer<ApplicationId> prepareException = null;
- private ConfigChangeActions configChangeActions = null;
private Supplier<String> log = () -> "INFO - All good";
@Inject
@@ -106,11 +105,6 @@ public class ConfigServerMock extends AbstractComponent implements ConfigServer
bootstrap(zoneRegistry.zones().all().ids(), SystemApplication.notController());
}
- /** Sets the ConfigChangeActions that will be returned on next deployment. */
- public void setConfigChangeActions(ConfigChangeActions configChangeActions) {
- this.configChangeActions = configChangeActions;
- }
-
/** Assigns a reserved tenant node to the given deployment, with initial versions. */
public void provision(ZoneId zone, ApplicationId application, ClusterSpec.Id clusterId) {
var current = new ClusterResources(2, 1, new NodeResources(2, 8, 50, 1, slow, remote));
@@ -428,10 +422,7 @@ public class ConfigServerMock extends AbstractComponent implements ConfigServer
PrepareResponse prepareResponse = new PrepareResponse();
prepareResponse.message = "foo";
- prepareResponse.configChangeActions = configChangeActions != null
- ? configChangeActions
- : new ConfigChangeActions(List.of(), List.of(), List.of());
- setConfigChangeActions(null);
+ prepareResponse.configChangeActions = new ConfigChangeActions(List.of(), List.of(), List.of());
prepareResponse.tenant = new TenantId("tenant");
prepareResponse.log = warnings.getOrDefault(id, Collections.emptyList());
return prepareResponse;
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/integration/ZoneRegistryMock.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/integration/ZoneRegistryMock.java
index 1f4218af1b6..1d8dba321a2 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/integration/ZoneRegistryMock.java
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/integration/ZoneRegistryMock.java
@@ -199,6 +199,11 @@ public class ZoneRegistryMock extends AbstractComponent implements ZoneRegistry
}
@Override
+ public URI dashboardUrl(TenantName tenantName) {
+ return URI.create("https://dashboard.tld/" + tenantName);
+ }
+
+ @Override
public URI dashboardUrl(RunId id) {
return URI.create("https://dashboard.tld/" + id.application() + "/" + id.type().jobName() + "/" + id.number());
}
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/maintenance/JobRunnerTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/maintenance/JobRunnerTest.java
index 9ccd7244392..610d8d4ca9a 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/maintenance/JobRunnerTest.java
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/maintenance/JobRunnerTest.java
@@ -413,6 +413,7 @@ public class JobRunnerTest {
assertEquals(1, metric.getMetric(context::equals, JobMetrics.nodeAllocationFailure).get().intValue());
assertEquals(1, metric.getMetric(context::equals, JobMetrics.endpointCertificateTimeout).get().intValue());
assertEquals(1, metric.getMetric(context::equals, JobMetrics.testFailure).get().intValue());
+ assertEquals(1, metric.getMetric(context::equals, JobMetrics.noTests).get().intValue());
}
private void start(JobController jobs, ApplicationId id, JobType type) {
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/notification/NotificationsDbTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/notification/NotificationsDbTest.java
index 28be68cf850..75b9b108377 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/notification/NotificationsDbTest.java
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/notification/NotificationsDbTest.java
@@ -15,6 +15,7 @@ import com.yahoo.vespa.hosted.controller.api.integration.deployment.JobType;
import com.yahoo.vespa.hosted.controller.api.integration.deployment.RunId;
import com.yahoo.vespa.hosted.controller.api.integration.stubs.MockMailer;
import com.yahoo.vespa.hosted.controller.application.TenantAndApplicationId;
+import com.yahoo.vespa.hosted.controller.integration.ZoneRegistryMock;
import com.yahoo.vespa.hosted.controller.notify.Notifier;
import com.yahoo.vespa.hosted.controller.persistence.MockCuratorDb;
import com.yahoo.vespa.hosted.controller.tenant.CloudTenant;
@@ -69,7 +70,7 @@ public class NotificationsDbTest {
private final ManualClock clock = new ManualClock(Instant.ofEpochSecond(12345));
private final MockCuratorDb curatorDb = new MockCuratorDb(SystemName.Public);
private final MockMailer mailer = new MockMailer();
- private final NotificationsDb notificationsDb = new NotificationsDb(clock, curatorDb, new Notifier(curatorDb, mailer));
+ private final NotificationsDb notificationsDb = new NotificationsDb(clock, curatorDb, new Notifier(curatorDb, new ZoneRegistryMock(SystemName.cd), mailer));
@Test
public void list_test() {
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/deployment/BadgeApiTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/deployment/BadgeApiTest.java
index cf6453235d3..c195b623c11 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/deployment/BadgeApiTest.java
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/deployment/BadgeApiTest.java
@@ -44,11 +44,15 @@ public class BadgeApiTest extends ControllerContainerTest {
.runJob(JobType.productionApSoutheast1)
.failDeployment(JobType.testApSoutheast1);
application.submit(applicationPackage)
- .runJob(JobType.systemTest)
+ .failTests(JobType.systemTest, true)
.runJob(JobType.stagingTest);
for (int i = 0; i < 31; i++)
- application.failDeployment(JobType.productionUsWest1);
+ if ((i & 1) == 0)
+ application.failDeployment(JobType.productionUsWest1);
+ else
+ application.triggerJobs().abortJob(JobType.productionUsWest1);
application.triggerJobs();
+ tester.controller().applications().deploymentTrigger().reTrigger(application.instanceId(), JobType.systemTest, "reason");
tester.controller().applications().deploymentTrigger().reTrigger(application.instanceId(), JobType.testEuWest1, "reason");
tester.assertResponse(authenticatedRequest("http://localhost:8080/badge/v1/tenant/application/default"),
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/deployment/responses/history.svg b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/deployment/responses/history.svg
index 0e30796bae2..c0566ade33a 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/deployment/responses/history.svg
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/deployment/responses/history.svg
@@ -33,9 +33,15 @@
<animate attributeName='x1' values='-110%;150%;20%;-110%' dur='6s' repeatCount='indefinite' />
<animate attributeName='x2' values='-10%;250%;120%;-10%' dur='6s' repeatCount='indefinite' />
</linearGradient>
+ <linearGradient id='run-on-warning' x1='40%' x2='80%' y2='0%'>
+ <stop offset='0' stop-color='#ab83ff' />
+ <stop offset='1' stop-color='#bd890b' />
+ <animate attributeName='x1' values='-110%;150%;20%;-110%' dur='6s' repeatCount='indefinite' />
+ <animate attributeName='x2' values='-10%;250%;120%;-10%' dur='6s' repeatCount='indefinite' />
+ </linearGradient>
<linearGradient id='run-on-success' x1='40%' x2='80%' y2='0%'>
<stop offset='0' stop-color='#ab83ff' />
- <stop offset='1' stop-color='#00f244' />
+ <stop offset='1' stop-color='#00f844' />
<animate attributeName='x1' values='-110%;150%;20%;-110%' dur='6s' repeatCount='indefinite' />
<animate attributeName='x2' values='-10%;250%;120%;-10%' dur='6s' repeatCount='indefinite' />
</linearGradient>
@@ -44,100 +50,100 @@
</clipPath>
<g clip-path='url(#rounded)'>
<rect x='653.26809109179' rx='3' width='8' height='20' fill='url(#shadow)'/>
- <rect x='646.1879570885093' rx='3' width='13.080134003280707' height='20' fill='#00f244'/>
+ <rect x='646.1879570885093' rx='3' width='13.080134003280707' height='20' fill='#00f844'/>
<rect x='646.1879570885093' rx='3' width='13.080134003280707' height='20' fill='url(#shade)'/>
<rect x='646.4043039211865' rx='3' width='8' height='20' fill='url(#shadow)'/>
- <rect x='639.1078230852286' rx='3' width='13.296480835957981' height='20' fill='#00f244'/>
+ <rect x='639.1078230852286' rx='3' width='13.296480835957981' height='20' fill='#00f844'/>
<rect x='639.1078230852286' rx='3' width='13.296480835957981' height='20' fill='url(#shade)'/>
<rect x='639.3307808029524' rx='3' width='8' height='20' fill='url(#shadow)'/>
<rect x='631.8113422492706' rx='3' width='13.519438553681752' height='20' fill='#bf103c'/>
<rect x='631.8113422492706' rx='3' width='13.519438553681752' height='20' fill='url(#shade)'/>
<rect x='632.0411128600877' rx='3' width='8' height='20' fill='url(#shadow)'/>
- <rect x='624.2919036955889' rx='3' width='13.749209164498811' height='20' fill='#bf103c'/>
+ <rect x='624.2919036955889' rx='3' width='13.749209164498811' height='20' fill='#bd890b'/>
<rect x='624.2919036955889' rx='3' width='13.749209164498811' height='20' fill='url(#shade)'/>
<rect x='624.5286953802824' rx='3' width='8' height='20' fill='url(#shadow)'/>
<rect x='616.5426945310901' rx='3' width='13.986000849192376' height='20' fill='#bf103c'/>
<rect x='616.5426945310901' rx='3' width='13.986000849192376' height='20' fill='url(#shade)'/>
<rect x='616.7867218317995' rx='3' width='8' height='20' fill='url(#shadow)'/>
- <rect x='608.5566936818977' rx='3' width='14.230028149901685' height='20' fill='#bf103c'/>
+ <rect x='608.5566936818977' rx='3' width='14.230028149901685' height='20' fill='#bd890b'/>
<rect x='608.5566936818977' rx='3' width='14.230028149901685' height='20' fill='url(#shade)'/>
<rect x='608.8081776965013' rx='3' width='8' height='20' fill='url(#shadow)'/>
<rect x='600.326665531996' rx='3' width='14.48151216450522' height='20' fill='#bf103c'/>
<rect x='600.326665531996' rx='3' width='14.48151216450522' height='20' fill='url(#shade)'/>
<rect x='600.5858341144344' rx='3' width='8' height='20' fill='url(#shadow)'/>
- <rect x='591.8451533674908' rx='3' width='14.740680746943664' height='20' fill='#bf103c'/>
+ <rect x='591.8451533674908' rx='3' width='14.740680746943664' height='20' fill='#bd890b'/>
<rect x='591.8451533674908' rx='3' width='14.740680746943664' height='20' fill='url(#shade)'/>
<rect x='592.1122413342111' rx='3' width='8' height='20' fill='url(#shadow)'/>
<rect x='583.1044726205471' rx='3' width='15.007768713664104' height='20' fill='#bf103c'/>
<rect x='583.1044726205471' rx='3' width='15.007768713664104' height='20' fill='url(#shade)'/>
<rect x='583.3797219632555' rx='3' width='8' height='20' fill='url(#shadow)'/>
- <rect x='574.096703906883' rx='3' width='15.283018056372542' height='20' fill='#bf103c'/>
+ <rect x='574.096703906883' rx='3' width='15.283018056372542' height='20' fill='#bd890b'/>
<rect x='574.096703906883' rx='3' width='15.283018056372542' height='20' fill='url(#shade)'/>
<rect x='574.380364011798' rx='3' width='8' height='20' fill='url(#shadow)'/>
<rect x='564.8136858505105' rx='3' width='15.566678161287442' height='20' fill='#bf103c'/>
<rect x='564.8136858505105' rx='3' width='15.566678161287442' height='20' fill='url(#shade)'/>
<rect x='565.1060137243161' rx='3' width='8' height='20' fill='url(#shadow)'/>
- <rect x='555.2470076892231' rx='3' width='15.859006035092985' height='20' fill='#bf103c'/>
+ <rect x='555.2470076892231' rx='3' width='15.859006035092985' height='20' fill='#bd890b'/>
<rect x='555.2470076892231' rx='3' width='15.859006035092985' height='20' fill='url(#shade)'/>
<rect x='555.5482681919269' rx='3' width='8' height='20' fill='url(#shadow)'/>
<rect x='545.3880016541301' rx='3' width='16.16026653779677' height='20' fill='#bf103c'/>
<rect x='545.3880016541301' rx='3' width='16.16026653779677' height='20' fill='url(#shade)'/>
<rect x='545.6984677390362' rx='3' width='8' height='20' fill='url(#shadow)'/>
- <rect x='535.2277351163333' rx='3' width='16.470732622702883' height='20' fill='#bf103c'/>
+ <rect x='535.2277351163333' rx='3' width='16.470732622702883' height='20' fill='#bd890b'/>
<rect x='535.2277351163333' rx='3' width='16.470732622702883' height='20' fill='url(#shade)'/>
<rect x='535.5476880773482' rx='3' width='8' height='20' fill='url(#shadow)'/>
<rect x='524.7570024936304' rx='3' width='16.790685583717845' height='20' fill='#bf103c'/>
<rect x='524.7570024936304' rx='3' width='16.790685583717845' height='20' fill='url(#shade)'/>
<rect x='525.0867322201259' rx='3' width='8' height='20' fill='url(#shadow)'/>
- <rect x='513.9663169099125' rx='3' width='17.12041531021341' height='20' fill='#bf103c'/>
+ <rect x='513.9663169099125' rx='3' width='17.12041531021341' height='20' fill='#bd890b'/>
<rect x='513.9663169099125' rx='3' width='17.12041531021341' height='20' fill='url(#shade)'/>
<rect x='514.3061221493763' rx='3' width='8' height='20' fill='url(#shadow)'/>
<rect x='502.84590159969906' rx='3' width='17.460220549677203' height='20' fill='#bf103c'/>
<rect x='502.84590159969906' rx='3' width='17.460220549677203' height='20' fill='url(#shade)'/>
<rect x='503.196090228411' rx='3' width='8' height='20' fill='url(#shadow)'/>
- <rect x='491.38568105002184' rx='3' width='17.810409178389147' height='20' fill='#bf103c'/>
+ <rect x='491.38568105002184' rx='3' width='17.810409178389147' height='20' fill='#bd890b'/>
<rect x='491.38568105002184' rx='3' width='17.810409178389147' height='20' fill='url(#shade)'/>
<rect x='491.7465703520016' rx='3' width='8' height='20' fill='url(#shadow)'/>
<rect x='479.5752718716327' rx='3' width='18.171298480368904' height='20' fill='#bf103c'/>
<rect x='479.5752718716327' rx='3' width='18.171298480368904' height='20' fill='url(#shade)'/>
<rect x='479.9471888261109' rx='3' width='8' height='20' fill='url(#shadow)'/>
- <rect x='467.40397339126383' rx='3' width='18.543215434847077' height='20' fill='#bf103c'/>
+ <rect x='467.40397339126383' rx='3' width='18.543215434847077' height='20' fill='#bd890b'/>
<rect x='467.40397339126383' rx='3' width='18.543215434847077' height='20' fill='url(#shade)'/>
<rect x='467.7872549689374' rx='3' width='8' height='20' fill='url(#shadow)'/>
<rect x='454.86075795641676' rx='3' width='18.92649701252067' height='20' fill='#bf103c'/>
<rect x='454.86075795641676' rx='3' width='18.92649701252067' height='20' fill='url(#shade)'/>
<rect x='455.25575142475725' rx='3' width='8' height='20' fill='url(#shadow)'/>
- <rect x='441.9342609438961' rx='3' width='19.32149048086113' height='20' fill='#bf103c'/>
+ <rect x='441.9342609438961' rx='3' width='19.32149048086113' height='20' fill='#bd890b'/>
<rect x='441.9342609438961' rx='3' width='19.32149048086113' height='20' fill='url(#shade)'/>
<rect x='442.3413241817867' rx='3' width='8' height='20' fill='url(#shadow)'/>
<rect x='428.61277046303496' rx='3' width='19.728553718751726' height='20' fill='#bf103c'/>
<rect x='428.61277046303496' rx='3' width='19.728553718751726' height='20' fill='url(#shade)'/>
<rect x='429.03227228502243' rx='3' width='8' height='20' fill='url(#shadow)'/>
- <rect x='414.8842167442832' rx='3' width='20.148055540739207' height='20' fill='#bf103c'/>
+ <rect x='414.8842167442832' rx='3' width='20.148055540739207' height='20' fill='#bd890b'/>
<rect x='414.8842167442832' rx='3' width='20.148055540739207' height='20' fill='url(#shade)'/>
<rect x='415.31653723473755' rx='3' width='8' height='20' fill='url(#shadow)'/>
<rect x='400.736161203544' rx='3' width='20.58037603119359' height='20' fill='#bf103c'/>
<rect x='400.736161203544' rx='3' width='20.58037603119359' height='20' fill='url(#shade)'/>
<rect x='401.1816920610293' rx='3' width='8' height='20' fill='url(#shadow)'/>
- <rect x='386.1557851723504' rx='3' width='21.025906888678875' height='20' fill='#bf103c'/>
+ <rect x='386.1557851723504' rx='3' width='21.025906888678875' height='20' fill='#bd890b'/>
<rect x='386.1557851723504' rx='3' width='21.025906888678875' height='20' fill='url(#shade)'/>
<rect x='386.61493006451815' rx='3' width='8' height='20' fill='url(#shadow)'/>
<rect x='371.12987828367153' rx='3' width='21.485051780846597' height='20' fill='#bf103c'/>
<rect x='371.12987828367153' rx='3' width='21.485051780846597' height='20' fill='url(#shade)'/>
<rect x='371.60305321299876' rx='3' width='8' height='20' fill='url(#shadow)'/>
- <rect x='355.6448265028249' rx='3' width='21.958226710173836' height='20' fill='#bf103c'/>
+ <rect x='355.6448265028249' rx='3' width='21.958226710173836' height='20' fill='#bd890b'/>
<rect x='355.6448265028249' rx='3' width='21.958226710173836' height='20' fill='url(#shade)'/>
<rect x='356.13246018352817' rx='3' width='8' height='20' fill='url(#shadow)'/>
<rect x='339.68659979265107' rx='3' width='22.445860390877083' height='20' fill='#bf103c'/>
<rect x='339.68659979265107' rx='3' width='22.445860390877083' height='20' fill='url(#shade)'/>
<rect x='340.18913403911733' rx='3' width='8' height='20' fill='url(#shadow)'/>
- <rect x='323.24073940177396' rx='3' width='22.948394637343355' height='20' fill='#bf103c'/>
+ <rect x='323.24073940177396' rx='3' width='22.948394637343355' height='20' fill='#bd890b'/>
<rect x='323.24073940177396' rx='3' width='22.948394637343355' height='20' fill='url(#shade)'/>
<rect x='323.7586295288612' rx='3' width='8' height='20' fill='url(#shadow)'/>
<rect x='306.2923447644306' rx='3' width='23.466284764430597' height='20' fill='#bf103c'/>
<rect x='306.2923447644306' rx='3' width='23.466284764430597' height='20' fill='url(#shade)'/>
<rect x='306.82606' rx='3' width='8' height='20' fill='url(#shadow)'/>
- <rect x='288.82606' rx='3' width='24.0' height='20' fill='#bf103c'/>
+ <rect x='288.82606' rx='3' width='24.0' height='20' fill='#bd890b'/>
<rect x='288.82606' rx='3' width='24.0' height='20' fill='url(#shade)'/>
<rect x='288.82606' rx='3' width='8' height='20' fill='url(#shadow)'/>
<rect x='163.18729000000002' rx='3' width='131.63876999999997' height='20' fill='url(#run-on-failure)'/>
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/deployment/responses/history2.svg b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/deployment/responses/history2.svg
index 73d65b08b69..e527fa8d80f 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/deployment/responses/history2.svg
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/deployment/responses/history2.svg
@@ -33,9 +33,15 @@
<animate attributeName='x1' values='-110%;150%;20%;-110%' dur='6s' repeatCount='indefinite' />
<animate attributeName='x2' values='-10%;250%;120%;-10%' dur='6s' repeatCount='indefinite' />
</linearGradient>
+ <linearGradient id='run-on-warning' x1='40%' x2='80%' y2='0%'>
+ <stop offset='0' stop-color='#ab83ff' />
+ <stop offset='1' stop-color='#bd890b' />
+ <animate attributeName='x1' values='-110%;150%;20%;-110%' dur='6s' repeatCount='indefinite' />
+ <animate attributeName='x2' values='-10%;250%;120%;-10%' dur='6s' repeatCount='indefinite' />
+ </linearGradient>
<linearGradient id='run-on-success' x1='40%' x2='80%' y2='0%'>
<stop offset='0' stop-color='#ab83ff' />
- <stop offset='1' stop-color='#00f244' />
+ <stop offset='1' stop-color='#00f844' />
<animate attributeName='x1' values='-110%;150%;20%;-110%' dur='6s' repeatCount='indefinite' />
<animate attributeName='x2' values='-10%;250%;120%;-10%' dur='6s' repeatCount='indefinite' />
</linearGradient>
@@ -44,103 +50,103 @@
</clipPath>
<g clip-path='url(#rounded)'>
<rect x='653.26809109179' rx='3' width='8' height='20' fill='url(#shadow)'/>
- <rect x='646.1879570885093' rx='3' width='13.080134003280707' height='20' fill='#00f244'/>
+ <rect x='646.1879570885093' rx='3' width='13.080134003280707' height='20' fill='#00f844'/>
<rect x='646.1879570885093' rx='3' width='13.080134003280707' height='20' fill='url(#shade)'/>
<rect x='646.4043039211865' rx='3' width='8' height='20' fill='url(#shadow)'/>
<rect x='639.1078230852286' rx='3' width='13.296480835957981' height='20' fill='#bf103c'/>
<rect x='639.1078230852286' rx='3' width='13.296480835957981' height='20' fill='url(#shade)'/>
<rect x='639.3307808029524' rx='3' width='8' height='20' fill='url(#shadow)'/>
- <rect x='631.8113422492706' rx='3' width='13.519438553681752' height='20' fill='#bf103c'/>
+ <rect x='631.8113422492706' rx='3' width='13.519438553681752' height='20' fill='#bd890b'/>
<rect x='631.8113422492706' rx='3' width='13.519438553681752' height='20' fill='url(#shade)'/>
<rect x='632.0411128600877' rx='3' width='8' height='20' fill='url(#shadow)'/>
<rect x='624.2919036955889' rx='3' width='13.749209164498811' height='20' fill='#bf103c'/>
<rect x='624.2919036955889' rx='3' width='13.749209164498811' height='20' fill='url(#shade)'/>
<rect x='624.5286953802824' rx='3' width='8' height='20' fill='url(#shadow)'/>
- <rect x='616.5426945310901' rx='3' width='13.986000849192376' height='20' fill='#bf103c'/>
+ <rect x='616.5426945310901' rx='3' width='13.986000849192376' height='20' fill='#bd890b'/>
<rect x='616.5426945310901' rx='3' width='13.986000849192376' height='20' fill='url(#shade)'/>
<rect x='616.7867218317995' rx='3' width='8' height='20' fill='url(#shadow)'/>
<rect x='608.5566936818977' rx='3' width='14.230028149901685' height='20' fill='#bf103c'/>
<rect x='608.5566936818977' rx='3' width='14.230028149901685' height='20' fill='url(#shade)'/>
<rect x='608.8081776965013' rx='3' width='8' height='20' fill='url(#shadow)'/>
- <rect x='600.326665531996' rx='3' width='14.48151216450522' height='20' fill='#bf103c'/>
+ <rect x='600.326665531996' rx='3' width='14.48151216450522' height='20' fill='#bd890b'/>
<rect x='600.326665531996' rx='3' width='14.48151216450522' height='20' fill='url(#shade)'/>
<rect x='600.5858341144344' rx='3' width='8' height='20' fill='url(#shadow)'/>
<rect x='591.8451533674908' rx='3' width='14.740680746943664' height='20' fill='#bf103c'/>
<rect x='591.8451533674908' rx='3' width='14.740680746943664' height='20' fill='url(#shade)'/>
<rect x='592.1122413342111' rx='3' width='8' height='20' fill='url(#shadow)'/>
- <rect x='583.1044726205471' rx='3' width='15.007768713664104' height='20' fill='#bf103c'/>
+ <rect x='583.1044726205471' rx='3' width='15.007768713664104' height='20' fill='#bd890b'/>
<rect x='583.1044726205471' rx='3' width='15.007768713664104' height='20' fill='url(#shade)'/>
<rect x='583.3797219632555' rx='3' width='8' height='20' fill='url(#shadow)'/>
<rect x='574.096703906883' rx='3' width='15.283018056372542' height='20' fill='#bf103c'/>
<rect x='574.096703906883' rx='3' width='15.283018056372542' height='20' fill='url(#shade)'/>
<rect x='574.380364011798' rx='3' width='8' height='20' fill='url(#shadow)'/>
- <rect x='564.8136858505105' rx='3' width='15.566678161287442' height='20' fill='#bf103c'/>
+ <rect x='564.8136858505105' rx='3' width='15.566678161287442' height='20' fill='#bd890b'/>
<rect x='564.8136858505105' rx='3' width='15.566678161287442' height='20' fill='url(#shade)'/>
<rect x='565.1060137243161' rx='3' width='8' height='20' fill='url(#shadow)'/>
<rect x='555.2470076892231' rx='3' width='15.859006035092985' height='20' fill='#bf103c'/>
<rect x='555.2470076892231' rx='3' width='15.859006035092985' height='20' fill='url(#shade)'/>
<rect x='555.5482681919269' rx='3' width='8' height='20' fill='url(#shadow)'/>
- <rect x='545.3880016541301' rx='3' width='16.16026653779677' height='20' fill='#bf103c'/>
+ <rect x='545.3880016541301' rx='3' width='16.16026653779677' height='20' fill='#bd890b'/>
<rect x='545.3880016541301' rx='3' width='16.16026653779677' height='20' fill='url(#shade)'/>
<rect x='545.6984677390362' rx='3' width='8' height='20' fill='url(#shadow)'/>
<rect x='535.2277351163333' rx='3' width='16.470732622702883' height='20' fill='#bf103c'/>
<rect x='535.2277351163333' rx='3' width='16.470732622702883' height='20' fill='url(#shade)'/>
<rect x='535.5476880773482' rx='3' width='8' height='20' fill='url(#shadow)'/>
- <rect x='524.7570024936304' rx='3' width='16.790685583717845' height='20' fill='#bf103c'/>
+ <rect x='524.7570024936304' rx='3' width='16.790685583717845' height='20' fill='#bd890b'/>
<rect x='524.7570024936304' rx='3' width='16.790685583717845' height='20' fill='url(#shade)'/>
<rect x='525.0867322201259' rx='3' width='8' height='20' fill='url(#shadow)'/>
<rect x='513.9663169099125' rx='3' width='17.12041531021341' height='20' fill='#bf103c'/>
<rect x='513.9663169099125' rx='3' width='17.12041531021341' height='20' fill='url(#shade)'/>
<rect x='514.3061221493763' rx='3' width='8' height='20' fill='url(#shadow)'/>
- <rect x='502.84590159969906' rx='3' width='17.460220549677203' height='20' fill='#bf103c'/>
+ <rect x='502.84590159969906' rx='3' width='17.460220549677203' height='20' fill='#bd890b'/>
<rect x='502.84590159969906' rx='3' width='17.460220549677203' height='20' fill='url(#shade)'/>
<rect x='503.196090228411' rx='3' width='8' height='20' fill='url(#shadow)'/>
<rect x='491.38568105002184' rx='3' width='17.810409178389147' height='20' fill='#bf103c'/>
<rect x='491.38568105002184' rx='3' width='17.810409178389147' height='20' fill='url(#shade)'/>
<rect x='491.7465703520016' rx='3' width='8' height='20' fill='url(#shadow)'/>
- <rect x='479.5752718716327' rx='3' width='18.171298480368904' height='20' fill='#bf103c'/>
+ <rect x='479.5752718716327' rx='3' width='18.171298480368904' height='20' fill='#bd890b'/>
<rect x='479.5752718716327' rx='3' width='18.171298480368904' height='20' fill='url(#shade)'/>
<rect x='479.9471888261109' rx='3' width='8' height='20' fill='url(#shadow)'/>
<rect x='467.40397339126383' rx='3' width='18.543215434847077' height='20' fill='#bf103c'/>
<rect x='467.40397339126383' rx='3' width='18.543215434847077' height='20' fill='url(#shade)'/>
<rect x='467.7872549689374' rx='3' width='8' height='20' fill='url(#shadow)'/>
- <rect x='454.86075795641676' rx='3' width='18.92649701252067' height='20' fill='#bf103c'/>
+ <rect x='454.86075795641676' rx='3' width='18.92649701252067' height='20' fill='#bd890b'/>
<rect x='454.86075795641676' rx='3' width='18.92649701252067' height='20' fill='url(#shade)'/>
<rect x='455.25575142475725' rx='3' width='8' height='20' fill='url(#shadow)'/>
<rect x='441.9342609438961' rx='3' width='19.32149048086113' height='20' fill='#bf103c'/>
<rect x='441.9342609438961' rx='3' width='19.32149048086113' height='20' fill='url(#shade)'/>
<rect x='442.3413241817867' rx='3' width='8' height='20' fill='url(#shadow)'/>
- <rect x='428.61277046303496' rx='3' width='19.728553718751726' height='20' fill='#bf103c'/>
+ <rect x='428.61277046303496' rx='3' width='19.728553718751726' height='20' fill='#bd890b'/>
<rect x='428.61277046303496' rx='3' width='19.728553718751726' height='20' fill='url(#shade)'/>
<rect x='429.03227228502243' rx='3' width='8' height='20' fill='url(#shadow)'/>
<rect x='414.8842167442832' rx='3' width='20.148055540739207' height='20' fill='#bf103c'/>
<rect x='414.8842167442832' rx='3' width='20.148055540739207' height='20' fill='url(#shade)'/>
<rect x='415.31653723473755' rx='3' width='8' height='20' fill='url(#shadow)'/>
- <rect x='400.736161203544' rx='3' width='20.58037603119359' height='20' fill='#bf103c'/>
+ <rect x='400.736161203544' rx='3' width='20.58037603119359' height='20' fill='#bd890b'/>
<rect x='400.736161203544' rx='3' width='20.58037603119359' height='20' fill='url(#shade)'/>
<rect x='401.1816920610293' rx='3' width='8' height='20' fill='url(#shadow)'/>
<rect x='386.1557851723504' rx='3' width='21.025906888678875' height='20' fill='#bf103c'/>
<rect x='386.1557851723504' rx='3' width='21.025906888678875' height='20' fill='url(#shade)'/>
<rect x='386.61493006451815' rx='3' width='8' height='20' fill='url(#shadow)'/>
- <rect x='371.12987828367153' rx='3' width='21.485051780846597' height='20' fill='#bf103c'/>
+ <rect x='371.12987828367153' rx='3' width='21.485051780846597' height='20' fill='#bd890b'/>
<rect x='371.12987828367153' rx='3' width='21.485051780846597' height='20' fill='url(#shade)'/>
<rect x='371.60305321299876' rx='3' width='8' height='20' fill='url(#shadow)'/>
<rect x='355.6448265028249' rx='3' width='21.958226710173836' height='20' fill='#bf103c'/>
<rect x='355.6448265028249' rx='3' width='21.958226710173836' height='20' fill='url(#shade)'/>
<rect x='356.13246018352817' rx='3' width='8' height='20' fill='url(#shadow)'/>
- <rect x='339.68659979265107' rx='3' width='22.445860390877083' height='20' fill='#bf103c'/>
+ <rect x='339.68659979265107' rx='3' width='22.445860390877083' height='20' fill='#bd890b'/>
<rect x='339.68659979265107' rx='3' width='22.445860390877083' height='20' fill='url(#shade)'/>
<rect x='340.18913403911733' rx='3' width='8' height='20' fill='url(#shadow)'/>
<rect x='323.24073940177396' rx='3' width='22.948394637343355' height='20' fill='#bf103c'/>
<rect x='323.24073940177396' rx='3' width='22.948394637343355' height='20' fill='url(#shade)'/>
<rect x='323.7586295288612' rx='3' width='8' height='20' fill='url(#shadow)'/>
- <rect x='306.2923447644306' rx='3' width='23.466284764430597' height='20' fill='#bf103c'/>
+ <rect x='306.2923447644306' rx='3' width='23.466284764430597' height='20' fill='#bd890b'/>
<rect x='306.2923447644306' rx='3' width='23.466284764430597' height='20' fill='url(#shade)'/>
<rect x='306.82606' rx='3' width='8' height='20' fill='url(#shadow)'/>
<rect x='288.82606' rx='3' width='24.0' height='20' fill='#bf103c'/>
<rect x='288.82606' rx='3' width='24.0' height='20' fill='url(#shade)'/>
<rect x='288.82606' rx='3' width='8' height='20' fill='url(#shadow)'/>
- <rect x='163.18729000000002' rx='3' width='131.63876999999997' height='20' fill='#00f244'/>
+ <rect x='163.18729000000002' rx='3' width='131.63876999999997' height='20' fill='#00f844'/>
<rect x='163.18729000000002' rx='3' width='131.63876999999997' height='20' fill='url(#shade)'/>
<rect width='169.18729000000002' height='20' fill='#404040'/>
<rect x='-6.0' rx='3' width='175.18729000000002' height='20' fill='url(#shade)'/>
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/deployment/responses/overview.svg b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/deployment/responses/overview.svg
index dde2b740e37..a0005ed6d76 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/deployment/responses/overview.svg
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/deployment/responses/overview.svg
@@ -33,9 +33,15 @@
<animate attributeName='x1' values='-110%;150%;20%;-110%' dur='6s' repeatCount='indefinite' />
<animate attributeName='x2' values='-10%;250%;120%;-10%' dur='6s' repeatCount='indefinite' />
</linearGradient>
+ <linearGradient id='run-on-warning' x1='40%' x2='80%' y2='0%'>
+ <stop offset='0' stop-color='#ab83ff' />
+ <stop offset='1' stop-color='#bd890b' />
+ <animate attributeName='x1' values='-110%;150%;20%;-110%' dur='6s' repeatCount='indefinite' />
+ <animate attributeName='x2' values='-10%;250%;120%;-10%' dur='6s' repeatCount='indefinite' />
+ </linearGradient>
<linearGradient id='run-on-success' x1='40%' x2='80%' y2='0%'>
<stop offset='0' stop-color='#ab83ff' />
- <stop offset='1' stop-color='#00f244' />
+ <stop offset='1' stop-color='#00f844' />
<animate attributeName='x1' values='-110%;150%;20%;-110%' dur='6s' repeatCount='indefinite' />
<animate attributeName='x2' values='-10%;250%;120%;-10%' dur='6s' repeatCount='indefinite' />
</linearGradient>
@@ -45,21 +51,21 @@
<g clip-path='url(#rounded)'>
<rect x='757.7809900000001' rx='3' width='8' height='20' fill='url(#shadow)'/>
<rect x='725.59036' rx='3' width='38.19063' height='20' fill='url(#run-on-success)'/>
- <polygon points='635.8470950000001 0 635.8470950000001 20 734.59036 20 742.59036 0' fill='#00f244'/>
+ <polygon points='635.8470950000001 0 635.8470950000001 20 734.59036 20 742.59036 0' fill='#00f844'/>
<rect x='635.8470950000001' rx='3' width='131.74345499999998' height='20' fill='url(#shade)'/>
<rect x='635.8470950000001' rx='3' width='8' height='20' fill='url(#shadow)'/>
<rect x='603.656465' rx='3' width='38.19063' height='20' fill='#bf103c'/>
- <polygon points='486.981225 0 486.981225 20 612.656465 20 620.656465 0' fill='#00f244'/>
+ <polygon points='486.981225 0 486.981225 20 612.656465 20 620.656465 0' fill='#00f844'/>
<rect x='486.981225' rx='3' width='158.67543' height='20' fill='url(#shade)'/>
<rect x='486.981225' rx='3' width='8' height='20' fill='url(#shadow)'/>
<rect x='348.865175' rx='3' width='144.11604999999997' height='20' fill='url(#run-on-success)'/>
<rect x='358.865175' rx='3' width='134.11604999999997' height='20' fill='url(#shade)'/>
<rect x='358.865175' rx='3' width='8' height='20' fill='url(#shadow)'/>
- <rect x='326.674545' rx='3' width='38.19063' height='20' fill='#00f244'/>
+ <rect x='326.674545' rx='3' width='38.19063' height='20' fill='#00f844'/>
<polygon points='237.71563000000003 0 237.71563000000003 20 335.674545 20 343.674545 0' fill='url(#run-on-failure)'/>
<rect x='237.71563000000003' rx='3' width='130.959105' height='20' fill='url(#shade)'/>
<rect x='237.71563000000003' rx='3' width='8' height='20' fill='url(#shadow)'/>
- <rect x='153.18729000000002' rx='3' width='90.52834000000001' height='20' fill='#00f244'/>
+ <rect x='153.18729000000002' rx='3' width='90.52834000000001' height='20' fill='url(#run-on-warning)'/>
<rect x='163.18729000000002' rx='3' width='80.52834000000001' height='20' fill='url(#shade)'/>
<rect width='169.18729000000002' height='20' fill='#404040'/>
<rect x='-6.0' rx='3' width='175.18729000000002' height='20' fill='url(#shade)'/>
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/deployment/responses/single-done.svg b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/deployment/responses/single-done.svg
index 3bcbed97499..0bdaa3f30ad 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/deployment/responses/single-done.svg
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/deployment/responses/single-done.svg
@@ -33,9 +33,15 @@
<animate attributeName='x1' values='-110%;150%;20%;-110%' dur='6s' repeatCount='indefinite' />
<animate attributeName='x2' values='-10%;250%;120%;-10%' dur='6s' repeatCount='indefinite' />
</linearGradient>
+ <linearGradient id='run-on-warning' x1='40%' x2='80%' y2='0%'>
+ <stop offset='0' stop-color='#ab83ff' />
+ <stop offset='1' stop-color='#bd890b' />
+ <animate attributeName='x1' values='-110%;150%;20%;-110%' dur='6s' repeatCount='indefinite' />
+ <animate attributeName='x2' values='-10%;250%;120%;-10%' dur='6s' repeatCount='indefinite' />
+ </linearGradient>
<linearGradient id='run-on-success' x1='40%' x2='80%' y2='0%'>
<stop offset='0' stop-color='#ab83ff' />
- <stop offset='1' stop-color='#00f244' />
+ <stop offset='1' stop-color='#00f844' />
<animate attributeName='x1' values='-110%;150%;20%;-110%' dur='6s' repeatCount='indefinite' />
<animate attributeName='x2' values='-10%;250%;120%;-10%' dur='6s' repeatCount='indefinite' />
</linearGradient>
@@ -44,7 +50,7 @@
</clipPath>
<g clip-path='url(#rounded)'>
<rect x='288.82606' rx='3' width='8' height='20' fill='url(#shadow)'/>
- <rect x='163.18729000000002' rx='3' width='131.63876999999997' height='20' fill='#00f244'/>
+ <rect x='163.18729000000002' rx='3' width='131.63876999999997' height='20' fill='#00f844'/>
<rect x='163.18729000000002' rx='3' width='131.63876999999997' height='20' fill='url(#shade)'/>
<rect width='169.18729000000002' height='20' fill='#404040'/>
<rect x='-6.0' rx='3' width='175.18729000000002' height='20' fill='url(#shade)'/>
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/deployment/responses/single-running.svg b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/deployment/responses/single-running.svg
index 27e967f8e46..1a38228e75d 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/deployment/responses/single-running.svg
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/deployment/responses/single-running.svg
@@ -33,9 +33,15 @@
<animate attributeName='x1' values='-110%;150%;20%;-110%' dur='6s' repeatCount='indefinite' />
<animate attributeName='x2' values='-10%;250%;120%;-10%' dur='6s' repeatCount='indefinite' />
</linearGradient>
+ <linearGradient id='run-on-warning' x1='40%' x2='80%' y2='0%'>
+ <stop offset='0' stop-color='#ab83ff' />
+ <stop offset='1' stop-color='#bd890b' />
+ <animate attributeName='x1' values='-110%;150%;20%;-110%' dur='6s' repeatCount='indefinite' />
+ <animate attributeName='x2' values='-10%;250%;120%;-10%' dur='6s' repeatCount='indefinite' />
+ </linearGradient>
<linearGradient id='run-on-success' x1='40%' x2='80%' y2='0%'>
<stop offset='0' stop-color='#ab83ff' />
- <stop offset='1' stop-color='#00f244' />
+ <stop offset='1' stop-color='#00f844' />
<animate attributeName='x1' values='-110%;150%;20%;-110%' dur='6s' repeatCount='indefinite' />
<animate attributeName='x2' values='-10%;250%;120%;-10%' dur='6s' repeatCount='indefinite' />
</linearGradient>
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 aa019ae5b39..597774e3ab9 100644
--- a/flags/src/main/java/com/yahoo/vespa/flags/Flags.java
+++ b/flags/src/main/java/com/yahoo/vespa/flags/Flags.java
@@ -369,13 +369,6 @@ public class Flags {
"Takes effect at redeployment",
ZONE_ID, APPLICATION_ID);
- public static final UnboundBooleanFlag ALLOW_NO_TESTS = defineFeatureFlag(
- "allow-no-tests", false,
- List.of("jonmv"), "2022-02-28", "2022-06-25",
- "Whether test jobs without any tests run are acceptable",
- "Takes effect immediately",
- TENANT_ID);
-
public static final UnboundBooleanFlag MERGE_GROUPING_RESULT_IN_SEARCH_INVOKER = defineFeatureFlag(
"merge-grouping-result-in-search-invoker", false,
List.of("bjorncs", "baldersheim"), "2022-02-23", "2022-08-01",
diff --git a/hosted-api/src/main/java/ai/vespa/hosted/api/ControllerHttpClient.java b/hosted-api/src/main/java/ai/vespa/hosted/api/ControllerHttpClient.java
index 2860b8878b7..67cd7e1477e 100644
--- a/hosted-api/src/main/java/ai/vespa/hosted/api/ControllerHttpClient.java
+++ b/hosted-api/src/main/java/ai/vespa/hosted/api/ControllerHttpClient.java
@@ -418,6 +418,8 @@ public abstract class ControllerHttpClient {
submission.sourceUrl().ifPresent(url -> rootObject.setString("sourceUrl", url));
submission.authorEmail().ifPresent(email -> rootObject.setString("authorEmail", email));
submission.projectId().ifPresent(projectId -> rootObject.setLong("projectId", projectId));
+ submission.risk().ifPresent(risk -> rootObject.setLong("risk", risk));
+ submission.description().ifPresent(description -> rootObject.setString("description", description));
return toJson(slime);
}
diff --git a/hosted-api/src/main/java/ai/vespa/hosted/api/Submission.java b/hosted-api/src/main/java/ai/vespa/hosted/api/Submission.java
index d3ebd715da8..173b4946d5a 100644
--- a/hosted-api/src/main/java/ai/vespa/hosted/api/Submission.java
+++ b/hosted-api/src/main/java/ai/vespa/hosted/api/Submission.java
@@ -20,10 +20,13 @@ public class Submission {
private final Path applicationZip;
private final Path applicationTestZip;
private final Optional<Long> projectId;
+ private final Optional<Integer> risk;
+ private final Optional<String> description;
public Submission(Optional<String> repository, Optional<String> branch, Optional<String> commit,
Optional<String> sourceUrl, Optional<String> authorEmail,
- Path applicationZip, Path applicationTestZip, Optional<Long> projectId) {
+ Path applicationZip, Path applicationTestZip, Optional<Long> projectId,
+ Optional<Integer> risk, Optional<String> description) {
this.repository = repository;
this.branch = branch;
this.commit = commit;
@@ -32,6 +35,8 @@ public class Submission {
this.applicationZip = applicationZip;
this.applicationTestZip = applicationTestZip;
this.projectId = projectId;
+ this.risk = risk;
+ this.description = description;
}
public Optional<String> repository() { return repository; }
@@ -42,5 +47,7 @@ public class Submission {
public Path applicationZip() { return applicationZip; }
public Path applicationTestZip() { return applicationTestZip; }
public Optional<Long> projectId() { return projectId; }
+ public Optional<Integer> risk() { return risk; }
+ public Optional<String> description() { return description; }
}
diff --git a/jdisc_core_test/test_bundles/cert-k-pkgs/src/main/java/com/yahoo/jdisc/bundle/k/CertificateK.java b/jdisc_core_test/test_bundles/cert-k-pkgs/src/main/java/com/yahoo/jdisc/bundle/k/CertificateK.java
index ad93a7f322c..f8d85233602 100644
--- a/jdisc_core_test/test_bundles/cert-k-pkgs/src/main/java/com/yahoo/jdisc/bundle/k/CertificateK.java
+++ b/jdisc_core_test/test_bundles/cert-k-pkgs/src/main/java/com/yahoo/jdisc/bundle/k/CertificateK.java
@@ -4,7 +4,7 @@ package com.yahoo.jdisc.bundle.k;
/**
* @author Simon Thoresen Hult
*/
-@SuppressWarnings({ "UnusedDeclaration", "deprecation" })
+@SuppressWarnings({ "UnusedDeclaration", "deprecation", "removal" })
public class CertificateK {
private final com.google.common.annotations.Beta beta = null;
@@ -37,6 +37,7 @@ public class CertificateK {
private final com.yahoo.yolean.trace.TraceNode traceNode = null;
private final com.sun.security.auth.LdapPrincipal principal = null;
private final com.sun.security.auth.module.JndiLoginModule jndiLoginModule = null;
+ private final java.security.cert.Certificate certificate = null;
private final javax.accessibility.Accessible accessible = null;
private final javax.annotation.PostConstruct postConstruct = null;
private final javax.annotation.processing.FilerException filerException = null;
@@ -82,7 +83,7 @@ public class CertificateK {
private final javax.security.auth.login.AccountException accountException = null;
private final javax.security.auth.spi.LoginModule loginModule = null;
private final javax.security.auth.x500.X500Principal x500Principal = null;
- private final javax.security.cert.Certificate certificate = null;
+ private final javax.security.cert.Certificate deprecatedCertificate = null;
private final javax.security.sasl.AuthorizeCallback authorizeCallback = null;
private final javax.sound.midi.ControllerEventListener controllerEventListener = null;
private final javax.sound.midi.spi.MidiDeviceProvider midiDeviceProvider = null;
diff --git a/parent/pom.xml b/parent/pom.xml
index 763310a4a55..ecf257727d1 100644
--- a/parent/pom.xml
+++ b/parent/pom.xml
@@ -951,7 +951,7 @@
<maven-javadoc-plugin.version>3.3.1</maven-javadoc-plugin.version>
<maven-plugin-tools.version>3.6.1</maven-plugin-tools.version>
<maven-resources-plugin.version>3.2.0</maven-resources-plugin.version>
- <maven-shade-plugin.version>3.2.4</maven-shade-plugin.version>
+ <maven-shade-plugin.version>3.3.0</maven-shade-plugin.version>
<maven-site-plugin.version>3.9.1</maven-site-plugin.version>
<maven-source-plugin.version>3.2.1</maven-source-plugin.version>
<mockito.version>4.0.0</mockito.version>
diff --git a/searchlib/src/main/java/com/yahoo/searchlib/expression/IntegerBucketResultNode.java b/searchlib/src/main/java/com/yahoo/searchlib/expression/IntegerBucketResultNode.java
index 4bf33b15ffe..c5d66406fd5 100644
--- a/searchlib/src/main/java/com/yahoo/searchlib/expression/IntegerBucketResultNode.java
+++ b/searchlib/src/main/java/com/yahoo/searchlib/expression/IntegerBucketResultNode.java
@@ -81,11 +81,11 @@ public class IntegerBucketResultNode extends BucketResultNode {
return (classId - rhs.getClassId());
}
IntegerBucketResultNode b = (IntegerBucketResultNode)rhs;
- long diff = from - b.from;
- if (diff == 0) {
- diff = to - b.to;
- }
- return ((diff == 0) ? 0 : ((diff < 0) ? -1 : 1));
+ if (from < b.from) return -1;
+ if (from > b.from) return 1;
+ if (to < b.to) return -1;
+ if (to > b.to) return 1;
+ return 0;
}
@Override
diff --git a/searchlib/src/test/java/com/yahoo/searchlib/expression/IntegerBucketResultNodeTestCase.java b/searchlib/src/test/java/com/yahoo/searchlib/expression/IntegerBucketResultNodeTestCase.java
index 00c0739ed9a..9c71625a85e 100644
--- a/searchlib/src/test/java/com/yahoo/searchlib/expression/IntegerBucketResultNodeTestCase.java
+++ b/searchlib/src/test/java/com/yahoo/searchlib/expression/IntegerBucketResultNodeTestCase.java
@@ -30,4 +30,17 @@ public class IntegerBucketResultNodeTestCase extends ResultNodeTest {
assertTrue(dumpNode(bucket).contains("to: 10"));
assertCorrectSerialization(bucket, new IntegerBucketResultNode());
}
+
+ private IntegerBucketResultNode createNode(long from, long to) {
+ return new IntegerBucketResultNode(from, to);
+ }
+
+ @Test
+ public void testCmp() {
+ assertOrder(createNode(Long.MIN_VALUE, 3), createNode(3, 9), createNode(9, Long.MAX_VALUE));
+ assertOrder(createNode(6, 9), createNode(7, 9), createNode(8, 9));
+ assertOrder(createNode(6, 7), createNode(6, 8), createNode(6, 9));
+ assertOrder(createNode(6, 3), createNode(7, 2), createNode(8, 1));
+ assertTrue(createNode(6, 8).onCmp(new NullResultNode()) != 0);
+ }
}
diff --git a/searchlib/src/vespa/searchlib/features/dotproductfeature.cpp b/searchlib/src/vespa/searchlib/features/dotproductfeature.cpp
index 8f75b6ecc7d..1ee5fe90773 100644
--- a/searchlib/src/vespa/searchlib/features/dotproductfeature.cpp
+++ b/searchlib/src/vespa/searchlib/features/dotproductfeature.cpp
@@ -52,49 +52,6 @@ template class VectorBase<uint32_t, uint32_t, double>;
template class IntegerVectorT<int64_t>;
-
-template <typename Vector, typename Buffer>
-DotProductExecutorByCopy<Vector, Buffer>::DotProductExecutorByCopy(const IAttributeVector * attribute, const Vector & queryVector) :
- FeatureExecutor(),
- _attribute(attribute),
- _queryVector(queryVector),
- _end(_queryVector.getDimMap().end()),
- _buffer(),
- _backing()
-{
- _buffer.allocate(_attribute->getMaxValueCount());
-}
-
-template <typename Vector, typename Buffer>
-DotProductExecutorByCopy<Vector, Buffer>::DotProductExecutorByCopy(const IAttributeVector * attribute, std::unique_ptr<Vector> queryVector) :
- FeatureExecutor(),
- _attribute(attribute),
- _queryVector(*queryVector),
- _end(_queryVector.getDimMap().end()),
- _buffer(),
- _backing(std::move(queryVector))
-{
- _buffer.allocate(_attribute->getMaxValueCount());
-}
-
-template <typename Vector, typename Buffer>
-DotProductExecutorByCopy<Vector, Buffer>::~DotProductExecutorByCopy() = default;
-
-template <typename Vector, typename Buffer>
-void
-DotProductExecutorByCopy<Vector, Buffer>::execute(uint32_t docId)
-{
- feature_t val = 0;
- _buffer.fill(*_attribute, docId);
- for (size_t i = 0; i < _buffer.size(); ++i) {
- auto itr = _queryVector.getDimMap().find(_buffer[i].getValue());
- if (itr != _end) {
- val += _buffer[i].getWeight() * itr->second;
- }
- }
- outputs().set_number(0, val);
-}
-
StringVector::StringVector() = default;
StringVector::~StringVector() = default;
@@ -229,6 +186,7 @@ template <typename BaseType>
class SingleDotProductByWeightedValueExecutor final : public fef::FeatureExecutor {
public:
using WeightedSetReadView = attribute::IWeightedSetReadView<BaseType>;
+ using StoredKeyType = std::conditional_t<std::is_same_v<BaseType,const char*>,vespalib::string,BaseType>;
SingleDotProductByWeightedValueExecutor(const WeightedSetReadView * weighted_set_read_view, BaseType key, feature_t value)
: _weighted_set_read_view(weighted_set_read_view),
_key(key),
@@ -247,7 +205,7 @@ public:
}
private:
const WeightedSetReadView* _weighted_set_read_view;
- BaseType _key;
+ StoredKeyType _key;
feature_t _value;
};
@@ -650,23 +608,38 @@ std::pair<T, feature_t> extractElem(const std::unique_ptr<dotproduct::wset::Inte
return extractElem(*v, idx);
}
-template <typename A, typename V>
+size_t extractSize(const dotproduct::wset::StringVector& v) {
+ return v.getVector().size();
+}
+
+std::pair<const char*, feature_t> extractElem(const dotproduct::wset::StringVector& v, size_t idx) {
+ const auto & pair = v.getVector()[idx];
+ return std::pair<const char*, feature_t>(pair.first.c_str(), pair.second);
+}
+
+size_t extractSize(const std::unique_ptr<dotproduct::wset::StringVector>& v) {
+ return extractSize(*v);
+}
+
+std::pair<const char*, feature_t> extractElem(const std::unique_ptr<dotproduct::wset::StringVector>& v, size_t idx) {
+ return extractElem(*v, idx);
+}
+
+template <typename T, typename V>
FeatureExecutor &
createForDirectWSetImpl(const IAttributeVector * attribute, V && vector, vespalib::Stash & stash)
{
using namespace dotproduct::wset;
- using T = typename A::BaseType;
- const A * iattr = dynamic_cast<const A *>(attribute);
using VT = multivalue::WeightedValue<T>;
auto weighted_set_read_view = make_multi_value_read_view<VT>(*attribute, stash);
- if (!attribute->isImported() && (iattr != nullptr) && weighted_set_read_view != nullptr) {
+ if (weighted_set_read_view != nullptr) {
if (extractSize(vector) == 1) {
auto elem = extractElem(vector, 0ul);
return stash.create<SingleDotProductByWeightedValueExecutor<T>>(weighted_set_read_view, elem.first, elem.second);
}
return stash.create<DotProductByWeightedSetReadViewExecutor<T>>(weighted_set_read_view, std::forward<V>(vector));
}
- return stash.create<DotProductExecutorByCopy<IntegerVectorT<T>, WeightedIntegerContent>>(attribute, std::forward<V>(vector));
+ return stash.create<SingleZeroValueExecutor>();
}
template <typename T>
@@ -676,7 +649,7 @@ createForDirectIntegerWSet(const IAttributeVector * attribute, const dotproduct:
using namespace dotproduct::wset;
return vector.empty()
? stash.create<SingleZeroValueExecutor>()
- : createForDirectWSetImpl<IntegerAttributeTemplate<T>>(attribute, vector, stash);
+ : createForDirectWSetImpl<T>(attribute, vector, stash);
}
FeatureExecutor &
@@ -727,14 +700,13 @@ createFromObject(const IAttributeVector * attribute, const fef::Anything & objec
}
return stash.create<DotProductExecutorByEnum>(weighted_set_enum_read_view, vector);
}
- return stash.create<DotProductExecutorByCopy<EnumVector, WeightedEnumContent>>(attribute, vector);
} else {
if (attribute->isStringType()) {
const auto & vector = dynamic_cast<const StringVector &>(object);
if (vector.empty()) {
return stash.create<SingleZeroValueExecutor>();
}
- return stash.create<DotProductExecutorByCopy<StringVector, WeightedConstCharContent>>(attribute, vector);
+ return createForDirectWSetImpl<const char*>(attribute, vector, stash);
} else if (attribute->isIntegerType()) {
if (attribute->getBasicType() == BasicType::INT32) {
return createForDirectIntegerWSet<int32_t>(attribute, dynamic_cast<const IntegerVectorT<int32_t> &>(object), stash);
@@ -800,7 +772,7 @@ createForDirectIntegerWSet(const IAttributeVector * attribute, const Property &
vector->syncMap();
return vector->empty()
? stash.create<SingleZeroValueExecutor>()
- : createForDirectWSetImpl<IntegerAttributeTemplate<T>>(attribute, std::move(vector), stash);
+ : createForDirectWSetImpl<T>(attribute, std::move(vector), stash);
}
FeatureExecutor &
@@ -822,7 +794,6 @@ createTypedWsetExecutor(const IAttributeVector * attribute, const Property & pro
}
return stash.create<DotProductExecutorByEnum>(weighted_set_enum_read_view, std::move(vector));
}
- return stash.create<DotProductExecutorByCopy<EnumVector, WeightedEnumContent>>(attribute, std::move(vector));
} else {
if (attribute->isStringType()) {
auto vector = std::make_unique<StringVector>();
@@ -831,7 +802,7 @@ createTypedWsetExecutor(const IAttributeVector * attribute, const Property & pro
return stash.create<SingleZeroValueExecutor>();
}
vector->syncMap();
- return stash.create<DotProductExecutorByCopy<StringVector, WeightedConstCharContent>>(attribute, std::move(vector));
+ return createForDirectWSetImpl<const char*>(attribute, std::move(vector), stash);
} else if (attribute->isIntegerType()) {
if (attribute->getBasicType() == BasicType::INT32) {
return createForDirectIntegerWSet<int32_t>(attribute, prop, stash);
diff --git a/searchlib/src/vespa/searchlib/features/dotproductfeature.h b/searchlib/src/vespa/searchlib/features/dotproductfeature.h
index 051a08025d8..ee0a85e689b 100644
--- a/searchlib/src/vespa/searchlib/features/dotproductfeature.h
+++ b/searchlib/src/vespa/searchlib/features/dotproductfeature.h
@@ -65,11 +65,14 @@ public:
bool empty() const { return _vector.empty(); }
};
+template <typename T>
+using NumericVectorBaseT = VectorBase<T, T, feature_t>;
+
/**
* Represents a vector where the dimensions are integers.
**/
template<typename T>
-class IntegerVectorT : public VectorBase<T, T, feature_t> {
+class IntegerVectorT : public NumericVectorBaseT<T> {
public:
void insert(vespalib::stringref label, vespalib::stringref value) {
this->_vector.emplace_back(util::strToNum<T>(label), util::strToNum<feature_t>(value));
@@ -82,10 +85,12 @@ extern template class IntegerVectorT<int64_t>;
using IntegerVector = IntegerVectorT<int64_t>;
+using StringVectorBase = VectorBase<vespalib::string, const char*, feature_t, ConstCharComparator>;
+
/**
* Represents a vector where the dimensions are string values.
**/
-class StringVector : public VectorBase<vespalib::string, const char *, feature_t, ConstCharComparator> {
+class StringVector : public StringVectorBase {
public:
StringVector();
StringVector(StringVector &&) = default;
@@ -121,7 +126,7 @@ template <typename BaseType>
class DotProductExecutorBase : public fef::FeatureExecutor {
public:
using AT = multivalue::WeightedValue<BaseType>;
- using V = VectorBase<BaseType, BaseType, feature_t>;
+ using V = std::conditional_t<std::is_same_v<BaseType,const char*>,StringVectorBase,NumericVectorBaseT<BaseType>>;
private:
const V & _queryVector;
const typename V::HashMap::const_iterator _end;
@@ -149,25 +154,6 @@ public:
~DotProductByWeightedSetReadViewExecutor();
};
-
-/**
- * Implements the executor for the dotproduct feature.
- */
-template <typename Vector, typename Buffer>
-class DotProductExecutorByCopy final : public fef::FeatureExecutor {
-private:
- const attribute::IAttributeVector * _attribute;
- const Vector & _queryVector;
- const typename Vector::HashMap::const_iterator _end;
- Buffer _buffer;
- std::unique_ptr<Vector> _backing;
-public:
- DotProductExecutorByCopy(const attribute::IAttributeVector * attribute, const Vector & queryVector);
- DotProductExecutorByCopy(const attribute::IAttributeVector * attribute, std::unique_ptr<Vector> queryVector);
- ~DotProductExecutorByCopy() override;
- void execute(uint32_t docId) override;
-};
-
}
namespace array {
diff --git a/searchlib/src/vespa/searchlib/tensor/hnsw_index.cpp b/searchlib/src/vespa/searchlib/tensor/hnsw_index.cpp
index 5ae26757b0d..8327db769d7 100644
--- a/searchlib/src/vespa/searchlib/tensor/hnsw_index.cpp
+++ b/searchlib/src/vespa/searchlib/tensor/hnsw_index.cpp
@@ -157,6 +157,7 @@ HnswIndex::shrink_if_needed(uint32_t docid, uint32_t level)
uint32_t max_links = max_links_for_level(level);
if (old_links.size() > max_links) {
HnswCandidateVector neighbors;
+ neighbors.reserve(old_links.size());
for (uint32_t neighbor_docid : old_links) {
double dist = calc_distance(docid, neighbor_docid);
neighbors.emplace_back(neighbor_docid, dist);
diff --git a/vespa-maven-plugin/src/main/java/ai/vespa/hosted/plugin/SubmitMojo.java b/vespa-maven-plugin/src/main/java/ai/vespa/hosted/plugin/SubmitMojo.java
index d2bad008003..f6ef17bc1b8 100644
--- a/vespa-maven-plugin/src/main/java/ai/vespa/hosted/plugin/SubmitMojo.java
+++ b/vespa-maven-plugin/src/main/java/ai/vespa/hosted/plugin/SubmitMojo.java
@@ -6,8 +6,6 @@ import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;
import java.nio.file.Paths;
-import java.util.Optional;
-import java.util.OptionalLong;
/**
* Submits a Vespa application package and corresponding test jars to the hosted Vespa API.
@@ -41,6 +39,12 @@ public class SubmitMojo extends AbstractVespaMojo {
@Parameter(property = "projectId")
private String projectId;
+ @Parameter(property = "risk")
+ private String risk;
+
+ @Parameter(property = "description")
+ private String description;
+
@Override
public void doExecute() {
applicationZip = firstNonBlank(applicationZip, projectPathOf("target", "application.zip")).orElseThrow();
@@ -48,7 +52,8 @@ public class SubmitMojo extends AbstractVespaMojo {
Submission submission = new Submission(optionalOf(repository), optionalOf(branch), optionalOf(commit),
optionalOf(sourceUrl), optionalOf(authorEmail),
Paths.get(applicationZip), Paths.get(applicationTestZip),
- optionalOf(projectId, Long::parseLong));
+ optionalOf(projectId, Long::parseLong), optionalOf(risk, Integer::parseInt),
+ optionalOf(description));
getLog().info(controller.submit(submission, id.tenant(), id.application()));
}