summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMorten Tokle <mortent@verizonmedia.com>2020-06-15 13:18:59 +0200
committerGitHub <noreply@github.com>2020-06-15 13:18:59 +0200
commit37453541835fabe546a30caf554331e992649f50 (patch)
tree4b6a90bf1686db7db73a6aa682f95af7d4955c5c
parent0a6b384693e07bd4d07757d23e710c7721e6066a (diff)
parent27f7caad383b133836be7414309921cee3b23e2b (diff)
Merge pull request #13503 from vespa-engine/mortent/tenant-cd-impl
Split cd test module in implementation and api modules
-rw-r--r--cloud-tenant-base/OWNERS2
-rw-r--r--cloud-tenant-base/README1
-rw-r--r--cloud-tenant-base/pom.xml383
-rw-r--r--cloud-tenant-cd/pom.xml (renamed from tenant-cd/pom.xml)23
-rw-r--r--cloud-tenant-cd/src/main/java/ai/vespa/hosted/cd/VespaTestRuntime.java (renamed from tenant-cd/src/main/java/ai/vespa/hosted/cd/TestRuntime.java)49
-rw-r--r--cloud-tenant-cd/src/main/java/ai/vespa/hosted/cd/http/HttpDeployment.java (renamed from tenant-cd/src/main/java/ai/vespa/hosted/cd/http/HttpDeployment.java)2
-rw-r--r--cloud-tenant-cd/src/main/java/ai/vespa/hosted/cd/http/HttpEndpoint.java (renamed from tenant-cd/src/main/java/ai/vespa/hosted/cd/http/HttpEndpoint.java)2
-rw-r--r--cloud-tenant-cd/src/main/resources/META-INF/services/ai.vespa.hosted.cd.TestRuntime2
-rw-r--r--hosted-tenant-base/OWNERS2
-rw-r--r--hosted-tenant-base/README1
-rw-r--r--hosted-tenant-base/pom.xml408
-rw-r--r--pom.xml5
-rw-r--r--tenant-base/pom.xml36
-rw-r--r--tenant-cd-api/OWNERS (renamed from tenant-cd/OWNERS)0
-rw-r--r--tenant-cd-api/README (renamed from tenant-cd/README)0
-rw-r--r--tenant-cd-api/pom.xml29
-rw-r--r--tenant-cd-api/src/main/java/ai/vespa/hosted/cd/Deployment.java (renamed from tenant-cd/src/main/java/ai/vespa/hosted/cd/Deployment.java)0
-rw-r--r--tenant-cd-api/src/main/java/ai/vespa/hosted/cd/Endpoint.java (renamed from tenant-cd/src/main/java/ai/vespa/hosted/cd/Endpoint.java)9
-rw-r--r--tenant-cd-api/src/main/java/ai/vespa/hosted/cd/IntegrationTest.java (renamed from tenant-cd/src/main/java/ai/vespa/hosted/cd/IntegrationTest.java)0
-rw-r--r--tenant-cd-api/src/main/java/ai/vespa/hosted/cd/ProductionTest.java (renamed from tenant-cd/src/main/java/ai/vespa/hosted/cd/ProductionTest.java)1
-rw-r--r--tenant-cd-api/src/main/java/ai/vespa/hosted/cd/StagingSetup.java (renamed from tenant-cd/src/main/java/ai/vespa/hosted/cd/StagingSetup.java)0
-rw-r--r--tenant-cd-api/src/main/java/ai/vespa/hosted/cd/StagingTest.java (renamed from tenant-cd/src/main/java/ai/vespa/hosted/cd/StagingTest.java)0
-rw-r--r--tenant-cd-api/src/main/java/ai/vespa/hosted/cd/SystemTest.java (renamed from tenant-cd/src/main/java/ai/vespa/hosted/cd/SystemTest.java)0
-rw-r--r--tenant-cd-api/src/main/java/ai/vespa/hosted/cd/TestRuntime.java19
24 files changed, 898 insertions, 76 deletions
diff --git a/cloud-tenant-base/OWNERS b/cloud-tenant-base/OWNERS
new file mode 100644
index 00000000000..ff9741f2060
--- /dev/null
+++ b/cloud-tenant-base/OWNERS
@@ -0,0 +1,2 @@
+mortent
+bjorncs \ No newline at end of file
diff --git a/cloud-tenant-base/README b/cloud-tenant-base/README
new file mode 100644
index 00000000000..3863ef33b12
--- /dev/null
+++ b/cloud-tenant-base/README
@@ -0,0 +1 @@
+Parent pom for Vespa Cloud applications
diff --git a/cloud-tenant-base/pom.xml b/cloud-tenant-base/pom.xml
new file mode 100644
index 00000000000..8ffa6be4f9c
--- /dev/null
+++ b/cloud-tenant-base/pom.xml
@@ -0,0 +1,383 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright 2019 Oath Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <artifactId>cloud-tenant-base</artifactId>
+ <name>Vespa Cloud tenant base</name>
+ <version>7-SNAPSHOT</version>
+ <description>Parent POM for all Vespa Cloud applications.</description>
+ <url>https://github.com/vespa-engine</url>
+ <packaging>pom</packaging>
+
+ <parent>
+ <artifactId>hosted-tenant-base</artifactId>
+ <groupId>com.yahoo.vespa</groupId>
+ <version>7-SNAPSHOT</version>
+ <relativePath>../hosted-tenant-base/pom.xml</relativePath>
+ </parent>
+
+ <licenses>
+ <license>
+ <name>The Apache License, Version 2.0</name>
+ <url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
+ </license>
+ </licenses>
+ <developers>
+ <developer>
+ <name>Vespa</name>
+ <url>https://github.com/vespa-engine</url>
+ </developer>
+ </developers>
+ <scm>
+ <connection>scm:git:git@github.com:vespa-engine/vespa.git</connection>
+ <developerConnection>scm:git:git@github.com:vespa-engine/vespa.git</developerConnection>
+ <url>git@github.com:vespa-engine/vespa.git</url>
+ </scm>
+
+ <properties>
+ <endpoint>https://api.vespa-external.aws.oath.cloud:4443</endpoint>
+ </properties>
+
+ <dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>com.yahoo.vespa</groupId>
+ <artifactId>container-dependency-versions</artifactId>
+ <version>${vespaversion}</version>
+ <type>pom</type>
+ <scope>import</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.junit.vintage</groupId>
+ <artifactId>junit-vintage-engine</artifactId>
+ <version>${junit.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.junit.jupiter</groupId>
+ <artifactId>junit-jupiter-engine</artifactId>
+ <version>${junit.version}</version>
+ </dependency>
+ </dependencies>
+ </dependencyManagement>
+
+ <dependencies>
+ <dependency>
+ <groupId>com.yahoo.vespa</groupId>
+ <artifactId>container</artifactId>
+ <version>${vespaversion}</version>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>com.yahoo.vespa</groupId>
+ <artifactId>container-test</artifactId>
+ <version>${vespaversion}</version>
+ <scope>test</scope>
+ <exclusions>
+ <exclusion>
+ <groupId>org.apache.commons</groupId>
+ <artifactId>commons-exec</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>commons-lang</groupId>
+ <artifactId>commons-lang</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+
+ <dependency>
+ <groupId>com.yahoo.vespa</groupId>
+ <artifactId>cloud-tenant-cd</artifactId>
+ <version>${test-framework.version}</version>
+ <scope>runtime</scope>
+ </dependency>
+ </dependencies>
+
+ <profiles>
+ <profile>
+ <!-- Build *-fat-test.jar file that includes all non-test classes and resources
+ that are part of the class path during test and and test.jar that includes
+ all test classes and resources, and put it inside a zip:
+ 1. application classes and resources
+ 2. test classes and resources
+ 3. classes and resources in all dependencies of both (1) and (2)
+ 4. copy the fat-test-jar and test-jar to application-test/artifacts directory
+ 5. zip application-test -->
+ <id>fat-test-application</id>
+ <build>
+ <plugins>
+ <plugin>
+ <!-- dependencies, see (3) above -->
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-dependency-plugin</artifactId>
+ <version>3.1.1</version>
+ <executions>
+ <execution>
+ <!-- JAR-like dependencies -->
+ <id>unpack-dependencies</id>
+ <phase>prepare-package</phase>
+ <goals>
+ <goal>unpack-dependencies</goal>
+ </goals>
+ <configuration>
+ <includeTypes>jar,test-jar</includeTypes>
+ <outputDirectory>target/fat-test-classes</outputDirectory>
+ <!-- WARNING(2018-06-27): bcpkix-jdk15on-1.58.jar and
+ bcprov-jdk15on-1.58.jar are pulled in via
+ container-dev and both contains the same set of
+ bouncycastle signature files in META-INF:
+ BC1024KE.DSA, BC1024KE.SF, BC2048KE.DSA, and
+ BC2048KE.SF. By merging any of these two with any
+ other JAR file like we're doing here, the signatures
+ are wrong. Worse, what we're doing is WRONG but not
+ yet fatal.
+
+ The symptom of this happening is that the tester fails
+ to load the SystemTest class(!?), and subsequently
+ tries to run all test-like files in the fat test JAR.
+
+ The solution is to exclude such files. This happens
+ automatically with maven-assembly-plugin. -->
+ <excludes>META-INF/*.SF,META-INF/*.DSA</excludes>
+ </configuration>
+ </execution>
+ <execution>
+ <!-- non-JAR-like dependencies -->
+ <id>non-jar-dependencies</id>
+ <phase>prepare-package</phase>
+ <goals>
+ <goal>copy-dependencies</goal>
+ </goals>
+ <configuration>
+ <excludeTypes>jar,test-jar</excludeTypes>
+ <outputDirectory>target/fat-test-classes</outputDirectory>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <artifactId>maven-resources-plugin</artifactId>
+ <version>3.1.0</version>
+ <executions>
+ <execution>
+ <id>copy-resources</id>
+ <phase>prepare-package</phase>
+ <goals>
+ <goal>copy-resources</goal>
+ </goals>
+ <configuration>
+ <outputDirectory>target/fat-test-classes</outputDirectory>
+ <resources>
+ <!-- application classes and resources, see 1. above -->
+ <resource>
+ <directory>target/classes</directory>
+ </resource>
+ </resources>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-jar-plugin</artifactId>
+ <version>3.1.0</version>
+ <executions>
+ <execution>
+ <id>fat-test-jar</id>
+ <phase>package</phase>
+ <goals>
+ <goal>jar</goal>
+ </goals>
+ <configuration>
+ <classesDirectory>target/fat-test-classes</classesDirectory>
+ <classifier>fat-test</classifier>
+ </configuration>
+ </execution>
+ <execution>
+ <id>test-jar</id>
+ <phase>package</phase>
+ <goals>
+ <goal>test-jar</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-antrun-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>attach-artifact</id>
+ <phase>package</phase>
+ <goals>
+ <goal>run</goal>
+ </goals>
+ <configuration>
+ <tasks>
+ <!-- copy fat test-jar to application-test artifacts directory, see 4. above -->
+ <copy file="target/${project.artifactId}-fat-test.jar"
+ todir="target/application-test/artifacts/" />
+
+ <!-- copy slim test-jar to application-test artifacts directory, see 4. above -->
+ <copy file="target/${project.artifactId}-tests.jar"
+ todir="target/application-test/artifacts/" />
+
+ <!-- zip application-test, see 5. above -->
+ <zip destfile="target/application-test.zip"
+ basedir="target/application-test/" />
+ </tasks>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
+
+ <profile> <!-- Alias vespaversion with a more descriptive vespa.compile.version -->
+ <id>set-vespa-compile-version</id>
+ <activation>
+ <property>
+ <name>vespa.compile.version</name>
+ </property>
+ </activation>
+ <properties>
+ <vespaversion>${vespa.compile.version}</vespaversion>
+ </properties>
+ </profile>
+
+ <profile> <!-- Alias vespaVersion with a more descriptive vespa.runtime.version -->
+ <id>set-vespa-runtime-version</id>
+ <activation>
+ <property>
+ <name>vespa.runtime.version</name>
+ </property>
+ </activation>
+ <properties>
+ <vespaVersion>${vespa.runtime.version}</vespaVersion>
+ </properties>
+ </profile>
+ </profiles>
+
+ <build>
+ <finalName>${project.artifactId}</finalName>
+ <pluginManagement>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <version>${maven-surefire-plugin.version}</version>
+ <configuration>
+ <groups>${test.categories}</groups>
+ <redirectTestOutputToFile>false</redirectTestOutputToFile>
+ <trimStackTrace>false</trimStackTrace>
+ <systemPropertyVariables>
+ <application>${application}</application>
+ <tenant>${tenant}</tenant>
+ <instance>${instance}</instance>
+ <environment>${environment}</environment>
+ <region>${region}</region>
+ <endpoint>${endpoint}</endpoint>
+ <apiKeyFile>${apiKeyFile}</apiKeyFile>
+ <apiCertificateFile>${apiCertificateFile}</apiCertificateFile>
+ <dataPlaneKeyFile>${dataPlaneKeyFile}</dataPlaneKeyFile>
+ <dataPlaneCertificateFile>${dataPlaneCertificateFile}</dataPlaneCertificateFile>
+ </systemPropertyVariables>
+ </configuration>
+ </plugin>
+
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-report-plugin</artifactId>
+ <version>${maven-surefire-plugin.version}</version>
+ <configuration>
+ <reportsDirectory>${env.TEST_DIR}</reportsDirectory>
+ </configuration>
+ </plugin>
+ </plugins>
+ </pluginManagement>
+
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-enforcer-plugin</artifactId>
+ <version>3.0.0-M2</version>
+ <executions>
+ <execution>
+ <id>enforce-java</id>
+ <goals>
+ <goal>enforce</goal>
+ </goals>
+ <configuration>
+ <rules>
+ <requireJavaVersion>
+ <version>[11, )</version>
+ </requireJavaVersion>
+ <requireMavenVersion>
+ <version>[3.5, )</version>
+ </requireMavenVersion>
+ </rules>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <version>${maven-compiler-plugin.version}</version>
+ <configuration>
+ <source>${target_jdk_version}</source>
+ <target>${target_jdk_version}</target>
+ <showWarnings>true</showWarnings>
+ <showDeprecation>true</showDeprecation>
+ <compilerArgs>
+ <arg>-Xlint:all</arg>
+ <arg>-Werror</arg>
+ </compilerArgs>
+ </configuration>
+ </plugin>
+
+ <plugin>
+ <groupId>com.yahoo.vespa</groupId>
+ <artifactId>vespa-maven-plugin</artifactId>
+ <version>${vespaversion}</version>
+ </plugin>
+
+ <plugin>
+ <groupId>com.yahoo.vespa</groupId>
+ <artifactId>vespa-application-maven-plugin</artifactId>
+ <version>${vespaversion}</version>
+ <executions>
+ <execution>
+ <goals>
+ <goal>packageApplication</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+
+ <plugin>
+ <groupId>com.yahoo.vespa</groupId>
+ <artifactId>bundle-plugin</artifactId>
+ <version>${vespaversion}</version>
+ <extensions>true</extensions>
+ </plugin>
+
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ </plugin>
+
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-report-plugin</artifactId>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/tenant-cd/pom.xml b/cloud-tenant-cd/pom.xml
index 829b1de457b..cc0f0777008 100644
--- a/tenant-cd/pom.xml
+++ b/cloud-tenant-cd/pom.xml
@@ -1,14 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -->
+<!-- Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -->
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
-
- <groupId>com.yahoo.vespa</groupId>
- <artifactId>tenant-cd</artifactId>
- <name>Hosted Vespa tenant CD</name>
- <description>Test library for hosted Vespa applications.</description>
+ <artifactId>cloud-tenant-cd</artifactId>
+ <name>Vespa Cloud tenant CD implementation</name>
+ <description>Test library implementation for Vespa Cloud applications.</description>
<url>https://github.com/vespa-engine</url>
<packaging>jar</packaging>
@@ -22,6 +20,11 @@
<dependencies>
<dependency>
<groupId>com.yahoo.vespa</groupId>
+ <artifactId>tenant-cd-api</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>com.yahoo.vespa</groupId>
<artifactId>security-utils</artifactId>
<version>${project.version}</version>
</dependency>
@@ -49,11 +52,5 @@
<artifactId>hosted-api</artifactId>
<version>${project.version}</version>
</dependency>
-
- <dependency>
- <groupId>org.junit.jupiter</groupId>
- <artifactId>junit-jupiter-engine</artifactId>
- </dependency>
</dependencies>
-
-</project>
+</project> \ No newline at end of file
diff --git a/tenant-cd/src/main/java/ai/vespa/hosted/cd/TestRuntime.java b/cloud-tenant-cd/src/main/java/ai/vespa/hosted/cd/VespaTestRuntime.java
index c479bab6e13..f77716064e5 100644
--- a/tenant-cd/src/main/java/ai/vespa/hosted/cd/TestRuntime.java
+++ b/cloud-tenant-cd/src/main/java/ai/vespa/hosted/cd/VespaTestRuntime.java
@@ -1,8 +1,7 @@
-// Copyright 2020 Oath Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+// Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package ai.vespa.hosted.cd;
import ai.vespa.hosted.api.ControllerHttpClient;
-import ai.vespa.hosted.api.EndpointAuthenticator;
import ai.vespa.hosted.api.Properties;
import ai.vespa.hosted.api.TestConfig;
import ai.vespa.hosted.cd.http.HttpDeployment;
@@ -14,46 +13,24 @@ import java.nio.file.Files;
import java.nio.file.Paths;
/**
- * The place to obtain environment-dependent configuration for test of a Vespa deployment.
- *
- * @author jvenstad
+ * @author mortent
*/
-public class TestRuntime {
-
- private static TestRuntime theRuntime;
-
+public class VespaTestRuntime implements TestRuntime {
private final TestConfig config;
private final Deployment deploymentToTest;
- private TestRuntime(TestConfig config, EndpointAuthenticator authenticator) {
- this.config = config;
- this.deploymentToTest = new HttpDeployment(config.deployments().get(config.zone()), authenticator);
- }
-
- /**
- * Returns the config and authenticator to use when running integration tests.
- *
- * If the system property {@code "vespa.test.config"} is set (to a file path), a file at that location
- * is attempted read, and config parsed from it.
- * Otherwise, config is fetched over HTTP from the hosted Vespa API, assuming the deployment indicated
- * by the optional {@code "environment"} and {@code "region"} system properties exists.
- * When environment is not specified, it defaults to {@link Environment#dev},
- * while region must be set unless the environment is {@link Environment#dev} or {@link Environment#perf}.
- */
- public static synchronized TestRuntime get() {
- if (theRuntime == null) {
+ public VespaTestRuntime() {
String configPath = System.getProperty("vespa.test.config");
TestConfig config = configPath != null ? fromFile(configPath) : fromController();
- theRuntime = new TestRuntime(config,
- new ai.vespa.hosted.auth.EndpointAuthenticator(config.system()));
- }
- return theRuntime;
+ this.config = config;
+ this.deploymentToTest = new HttpDeployment(config.deployments().get(config.zone()), new ai.vespa.hosted.auth.EndpointAuthenticator(config.system()));
}
- /** Returns a copy of this runtime, with the given endpoint authenticator. */
- public TestRuntime with(EndpointAuthenticator authenticator) {
- return new TestRuntime(config, authenticator);
- }
+// In use ?
+// /** Returns a copy of this runtime, with the given endpoint authenticator. */
+// public TestRuntime with(EndpointAuthenticator authenticator) {
+// return new TestRuntime(config, authenticator);
+// }
/** Returns the full id of the application this is testing. */
public ApplicationId application() { return config.application(); }
@@ -62,6 +39,7 @@ public class TestRuntime {
public ZoneId zone() { return config.zone(); }
/** Returns the deployment this is testing. */
+ @Override
public Deployment deploymentToTest() { return deploymentToTest; }
private static TestConfig fromFile(String path) {
@@ -78,8 +56,7 @@ public class TestRuntime {
ApplicationId id = Properties.application();
Environment environment = Properties.environment().orElse(Environment.dev);
ZoneId zone = Properties.region().map(region -> ZoneId.from(environment, region))
- .orElseGet(() -> controller.defaultZone(environment));
+ .orElseGet(() -> controller.defaultZone(environment));
return controller.testConfig(id, zone);
}
-
}
diff --git a/tenant-cd/src/main/java/ai/vespa/hosted/cd/http/HttpDeployment.java b/cloud-tenant-cd/src/main/java/ai/vespa/hosted/cd/http/HttpDeployment.java
index e17589c325d..80d5416ab34 100644
--- a/tenant-cd/src/main/java/ai/vespa/hosted/cd/http/HttpDeployment.java
+++ b/cloud-tenant-cd/src/main/java/ai/vespa/hosted/cd/http/HttpDeployment.java
@@ -1,4 +1,4 @@
-// Copyright 2020 Oath Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+// Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package ai.vespa.hosted.cd.http;
import ai.vespa.hosted.api.EndpointAuthenticator;
diff --git a/tenant-cd/src/main/java/ai/vespa/hosted/cd/http/HttpEndpoint.java b/cloud-tenant-cd/src/main/java/ai/vespa/hosted/cd/http/HttpEndpoint.java
index 74eb765dd0b..a803fc3e0e2 100644
--- a/tenant-cd/src/main/java/ai/vespa/hosted/cd/http/HttpEndpoint.java
+++ b/cloud-tenant-cd/src/main/java/ai/vespa/hosted/cd/http/HttpEndpoint.java
@@ -1,4 +1,4 @@
-// Copyright 2020 Oath Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+// Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package ai.vespa.hosted.cd.http;
import ai.vespa.hosted.api.EndpointAuthenticator;
diff --git a/cloud-tenant-cd/src/main/resources/META-INF/services/ai.vespa.hosted.cd.TestRuntime b/cloud-tenant-cd/src/main/resources/META-INF/services/ai.vespa.hosted.cd.TestRuntime
new file mode 100644
index 00000000000..695fe363e4e
--- /dev/null
+++ b/cloud-tenant-cd/src/main/resources/META-INF/services/ai.vespa.hosted.cd.TestRuntime
@@ -0,0 +1,2 @@
+# Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+ai.vespa.hosted.cd.VespaTestRuntime \ No newline at end of file
diff --git a/hosted-tenant-base/OWNERS b/hosted-tenant-base/OWNERS
new file mode 100644
index 00000000000..ff9741f2060
--- /dev/null
+++ b/hosted-tenant-base/OWNERS
@@ -0,0 +1,2 @@
+mortent
+bjorncs \ No newline at end of file
diff --git a/hosted-tenant-base/README b/hosted-tenant-base/README
new file mode 100644
index 00000000000..fed0672dcec
--- /dev/null
+++ b/hosted-tenant-base/README
@@ -0,0 +1 @@
+Base pom for Vespa cloud application poms
diff --git a/hosted-tenant-base/pom.xml b/hosted-tenant-base/pom.xml
new file mode 100644
index 00000000000..6fc65398f72
--- /dev/null
+++ b/hosted-tenant-base/pom.xml
@@ -0,0 +1,408 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright 2019 Oath Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <!-- <version>7-SNAPSHOT</version>-->
+ <!-- <url>https://github.com/vespa-engine</url>-->
+ <!-- <packaging>pom</packaging>-->
+
+ <groupId>com.yahoo.vespa</groupId>
+ <artifactId>hosted-tenant-base</artifactId>
+ <version>7-SNAPSHOT</version>
+ <name>Base pom for all tenant base poms</name>
+ <description>Parent POM for all Vespa base poms.</description>
+ <url>https://github.com/vespa-engine</url>
+ <packaging>pom</packaging>
+
+ <licenses>
+ <license>
+ <name>The Apache License, Version 2.0</name>
+ <url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
+ </license>
+ </licenses>
+ <developers>
+ <developer>
+ <name>Vespa</name>
+ <url>https://github.com/vespa-engine</url>
+ </developer>
+ </developers>
+ <scm>
+ <connection>scm:git:git@github.com:vespa-engine/vespa.git</connection>
+ <developerConnection>scm:git:git@github.com:vespa-engine/vespa.git</developerConnection>
+ <url>git@github.com:vespa-engine/vespa.git</url>
+ </scm>
+
+ <properties>
+ <vespaversion>${project.version}</vespaversion>
+ <test-framework.version>${project.version}</test-framework.version>
+ <target_jdk_version>11</target_jdk_version>
+ <maven-compiler-plugin.version>3.8.0</maven-compiler-plugin.version>
+ <maven-surefire-plugin.version>2.22.0</maven-surefire-plugin.version>
+ <junit.version>5.4.2</junit.version>
+ <endpoint>https://api.vespa-external.aws.oath.cloud:4443</endpoint>
+ <test.categories>!integration</test.categories>
+ </properties>
+
+ <dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>com.yahoo.vespa</groupId>
+ <artifactId>container-dependency-versions</artifactId>
+ <version>${vespaversion}</version>
+ <type>pom</type>
+ <scope>import</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.junit.vintage</groupId>
+ <artifactId>junit-vintage-engine</artifactId>
+ <version>${junit.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.junit.jupiter</groupId>
+ <artifactId>junit-jupiter-engine</artifactId>
+ <version>${junit.version}</version>
+ </dependency>
+ </dependencies>
+ </dependencyManagement>
+
+ <dependencies>
+ <dependency>
+ <groupId>com.yahoo.vespa</groupId>
+ <artifactId>container</artifactId>
+ <version>${vespaversion}</version>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>com.yahoo.vespa</groupId>
+ <artifactId>container-test</artifactId>
+ <version>${vespaversion}</version>
+ <scope>runtime</scope>
+ <exclusions>
+ <exclusion>
+ <groupId>org.apache.commons</groupId>
+ <artifactId>commons-exec</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>commons-lang</groupId>
+ <artifactId>commons-lang</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+
+ <dependency>
+ <groupId>com.yahoo.vespa</groupId>
+ <artifactId>tenant-cd</artifactId>
+ <version>${test-framework.version}</version>
+ <scope>test</scope>
+ <exclusions>
+ <exclusion>
+ <groupId>net.java.dev.jna</groupId>
+ <artifactId>jna</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>org.apache.commons</groupId>
+ <artifactId>commons-exec</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>commons-lang</groupId>
+ <artifactId>commons-lang</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>com.yahoo.vespa</groupId>
+ <artifactId>cloud-tenant-cd</artifactId>
+ <version>${test-framework.version}</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <profiles>
+ <profile>
+ <!-- Build *-fat-test.jar file that includes all non-test classes and resources
+ that are part of the class path during test and and test.jar that includes
+ all test classes and resources, and put it inside a zip:
+ 1. application classes and resources
+ 2. test classes and resources
+ 3. classes and resources in all dependencies of both (1) and (2)
+ 4. copy the fat-test-jar and test-jar to application-test/artifacts directory
+ 5. zip application-test -->
+ <id>fat-test-application</id>
+ <build>
+ <plugins>
+ <plugin>
+ <!-- dependencies, see (3) above -->
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-dependency-plugin</artifactId>
+ <version>3.1.1</version>
+ <executions>
+ <execution>
+ <!-- JAR-like dependencies -->
+ <id>unpack-dependencies</id>
+ <phase>prepare-package</phase>
+ <goals>
+ <goal>unpack-dependencies</goal>
+ </goals>
+ <configuration>
+ <includeTypes>jar,test-jar</includeTypes>
+ <outputDirectory>target/fat-test-classes</outputDirectory>
+ <!-- WARNING(2018-06-27): bcpkix-jdk15on-1.58.jar and
+ bcprov-jdk15on-1.58.jar are pulled in via
+ container-dev and both contains the same set of
+ bouncycastle signature files in META-INF:
+ BC1024KE.DSA, BC1024KE.SF, BC2048KE.DSA, and
+ BC2048KE.SF. By merging any of these two with any
+ other JAR file like we're doing here, the signatures
+ are wrong. Worse, what we're doing is WRONG but not
+ yet fatal.
+
+ The symptom of this happening is that the tester fails
+ to load the SystemTest class(!?), and subsequently
+ tries to run all test-like files in the fat test JAR.
+
+ The solution is to exclude such files. This happens
+ automatically with maven-assembly-plugin. -->
+ <excludes>META-INF/*.SF,META-INF/*.DSA</excludes>
+ </configuration>
+ </execution>
+ <execution>
+ <!-- non-JAR-like dependencies -->
+ <id>non-jar-dependencies</id>
+ <phase>prepare-package</phase>
+ <goals>
+ <goal>copy-dependencies</goal>
+ </goals>
+ <configuration>
+ <excludeTypes>jar,test-jar</excludeTypes>
+ <outputDirectory>target/fat-test-classes</outputDirectory>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <artifactId>maven-resources-plugin</artifactId>
+ <version>3.1.0</version>
+ <executions>
+ <execution>
+ <id>copy-resources</id>
+ <phase>prepare-package</phase>
+ <goals>
+ <goal>copy-resources</goal>
+ </goals>
+ <configuration>
+ <outputDirectory>target/fat-test-classes</outputDirectory>
+ <resources>
+ <!-- application classes and resources, see 1. above -->
+ <resource>
+ <directory>target/classes</directory>
+ </resource>
+ </resources>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-jar-plugin</artifactId>
+ <version>3.1.0</version>
+ <executions>
+ <execution>
+ <id>fat-test-jar</id>
+ <phase>package</phase>
+ <goals>
+ <goal>jar</goal>
+ </goals>
+ <configuration>
+ <classesDirectory>target/fat-test-classes</classesDirectory>
+ <classifier>fat-test</classifier>
+ </configuration>
+ </execution>
+ <execution>
+ <id>test-jar</id>
+ <phase>package</phase>
+ <goals>
+ <goal>test-jar</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-antrun-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>attach-artifact</id>
+ <phase>package</phase>
+ <goals>
+ <goal>run</goal>
+ </goals>
+ <configuration>
+ <tasks>
+ <!-- copy fat test-jar to application-test artifacts directory, see 4. above -->
+ <copy file="target/${project.artifactId}-fat-test.jar"
+ todir="target/application-test/artifacts/" />
+
+ <!-- copy slim test-jar to application-test artifacts directory, see 4. above -->
+ <copy file="target/${project.artifactId}-tests.jar"
+ todir="target/application-test/artifacts/" />
+
+ <!-- zip application-test, see 5. above -->
+ <zip destfile="target/application-test.zip"
+ basedir="target/application-test/" />
+ </tasks>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
+
+ <profile> <!-- Alias vespaversion with a more descriptive vespa.compile.version -->
+ <id>set-vespa-compile-version</id>
+ <activation>
+ <property>
+ <name>vespa.compile.version</name>
+ </property>
+ </activation>
+ <properties>
+ <vespaversion>${vespa.compile.version}</vespaversion>
+ </properties>
+ </profile>
+
+ <profile> <!-- Alias vespaVersion with a more descriptive vespa.runtime.version -->
+ <id>set-vespa-runtime-version</id>
+ <activation>
+ <property>
+ <name>vespa.runtime.version</name>
+ </property>
+ </activation>
+ <properties>
+ <vespaVersion>${vespa.runtime.version}</vespaVersion>
+ </properties>
+ </profile>
+ </profiles>
+
+ <build>
+ <finalName>${project.artifactId}</finalName>
+ <pluginManagement>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <version>${maven-surefire-plugin.version}</version>
+ <configuration>
+ <groups>${test.categories}</groups>
+ <redirectTestOutputToFile>false</redirectTestOutputToFile>
+ <trimStackTrace>false</trimStackTrace>
+ <systemPropertyVariables>
+ <application>${application}</application>
+ <tenant>${tenant}</tenant>
+ <instance>${instance}</instance>
+ <environment>${environment}</environment>
+ <region>${region}</region>
+ <endpoint>${endpoint}</endpoint>
+ <apiKeyFile>${apiKeyFile}</apiKeyFile>
+ <apiCertificateFile>${apiCertificateFile}</apiCertificateFile>
+ <dataPlaneKeyFile>${dataPlaneKeyFile}</dataPlaneKeyFile>
+ <dataPlaneCertificateFile>${dataPlaneCertificateFile}</dataPlaneCertificateFile>
+ </systemPropertyVariables>
+ </configuration>
+ </plugin>
+
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-report-plugin</artifactId>
+ <version>${maven-surefire-plugin.version}</version>
+ <configuration>
+ <reportsDirectory>${env.TEST_DIR}</reportsDirectory>
+ </configuration>
+ </plugin>
+ </plugins>
+ </pluginManagement>
+
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-enforcer-plugin</artifactId>
+ <version>3.0.0-M2</version>
+ <executions>
+ <execution>
+ <id>enforce-java</id>
+ <goals>
+ <goal>enforce</goal>
+ </goals>
+ <configuration>
+ <rules>
+ <requireJavaVersion>
+ <version>[11, )</version>
+ </requireJavaVersion>
+ <requireMavenVersion>
+ <version>[3.5, )</version>
+ </requireMavenVersion>
+ </rules>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <version>${maven-compiler-plugin.version}</version>
+ <configuration>
+ <source>${target_jdk_version}</source>
+ <target>${target_jdk_version}</target>
+ <showWarnings>true</showWarnings>
+ <showDeprecation>true</showDeprecation>
+ <compilerArgs>
+ <arg>-Xlint:all</arg>
+ <arg>-Werror</arg>
+ </compilerArgs>
+ </configuration>
+ </plugin>
+
+ <plugin>
+ <groupId>com.yahoo.vespa</groupId>
+ <artifactId>vespa-maven-plugin</artifactId>
+ <version>${vespaversion}</version>
+ </plugin>
+
+ <plugin>
+ <groupId>com.yahoo.vespa</groupId>
+ <artifactId>vespa-application-maven-plugin</artifactId>
+ <version>${vespaversion}</version>
+ <executions>
+ <execution>
+ <goals>
+ <goal>packageApplication</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+
+ <plugin>
+ <groupId>com.yahoo.vespa</groupId>
+ <artifactId>bundle-plugin</artifactId>
+ <version>${vespaversion}</version>
+ <extensions>true</extensions>
+ </plugin>
+
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ </plugin>
+
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-report-plugin</artifactId>
+ </plugin>
+ </plugins>
+ </build>
+</project> \ No newline at end of file
diff --git a/pom.xml b/pom.xml
index 941cd18b9e8..ba9ad4b04a4 100644
--- a/pom.xml
+++ b/pom.xml
@@ -31,6 +31,8 @@
<module>bundle-plugin-test</module>
<module>chain</module>
<module>client</module>
+ <module>cloud-tenant-base</module>
+ <module>cloud-tenant-cd</module>
<module>clustercontroller-apps</module>
<module>clustercontroller-apputil</module>
<module>clustercontroller-core</module>
@@ -81,6 +83,7 @@
<module>flags</module>
<module>fsa</module>
<module>hosted-api</module>
+ <module>hosted-tenant-base</module>
<module>hosted-zone-api</module>
<module>http-utils</module>
<module>indexinglanguage</module>
@@ -125,7 +128,7 @@
<module>storage</module>
<module>tenant-auth</module>
<module>tenant-base</module>
- <module>tenant-cd</module>
+ <module>tenant-cd-api</module>
<module>testutil</module>
<module>vdslib</module>
<module>vespaclient-core</module>
diff --git a/tenant-base/pom.xml b/tenant-base/pom.xml
index a3fac22a93d..767119d2a02 100644
--- a/tenant-base/pom.xml
+++ b/tenant-base/pom.xml
@@ -93,23 +93,29 @@
<dependency>
<groupId>com.yahoo.vespa</groupId>
- <artifactId>tenant-cd</artifactId>
+ <artifactId>tenant-cd-api</artifactId>
<version>${test-framework.version}</version>
<scope>test</scope>
- <exclusions>
- <exclusion>
- <groupId>net.java.dev.jna</groupId>
- <artifactId>jna</artifactId>
- </exclusion>
- <exclusion>
- <groupId>org.apache.commons</groupId>
- <artifactId>commons-exec</artifactId>
- </exclusion>
- <exclusion>
- <groupId>commons-lang</groupId>
- <artifactId>commons-lang</artifactId>
- </exclusion>
- </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>com.yahoo.vespa</groupId>
+ <artifactId>cloud-tenant-cd</artifactId>
+ <version>${test-framework.version}</version>
+ <scope>test</scope>
+ <exclusions>
+ <exclusion>
+ <groupId>net.java.dev.jna</groupId>
+ <artifactId>jna</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>org.apache.commons</groupId>
+ <artifactId>commons-exec</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>commons-lang</groupId>
+ <artifactId>commons-lang</artifactId>
+ </exclusion>
+ </exclusions>
</dependency>
</dependencies>
diff --git a/tenant-cd/OWNERS b/tenant-cd-api/OWNERS
index d0a102ecbf4..d0a102ecbf4 100644
--- a/tenant-cd/OWNERS
+++ b/tenant-cd-api/OWNERS
diff --git a/tenant-cd/README b/tenant-cd-api/README
index a3803b81d53..a3803b81d53 100644
--- a/tenant-cd/README
+++ b/tenant-cd-api/README
diff --git a/tenant-cd-api/pom.xml b/tenant-cd-api/pom.xml
new file mode 100644
index 00000000000..b9b4d136317
--- /dev/null
+++ b/tenant-cd-api/pom.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <groupId>com.yahoo.vespa</groupId>
+ <artifactId>tenant-cd-api</artifactId>
+ <name>Hosted Vespa tenant CD API</name>
+ <description>Test API library for hosted Vespa applications.</description>
+ <url>https://github.com/vespa-engine</url>
+ <packaging>jar</packaging>
+
+ <parent>
+ <groupId>com.yahoo.vespa</groupId>
+ <artifactId>parent</artifactId>
+ <version>7-SNAPSHOT</version>
+ <relativePath>../parent</relativePath>
+ </parent>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.junit.jupiter</groupId>
+ <artifactId>junit-jupiter-engine</artifactId>
+ </dependency>
+ </dependencies>
+
+</project>
diff --git a/tenant-cd/src/main/java/ai/vespa/hosted/cd/Deployment.java b/tenant-cd-api/src/main/java/ai/vespa/hosted/cd/Deployment.java
index 7d7b2f74981..7d7b2f74981 100644
--- a/tenant-cd/src/main/java/ai/vespa/hosted/cd/Deployment.java
+++ b/tenant-cd-api/src/main/java/ai/vespa/hosted/cd/Deployment.java
diff --git a/tenant-cd/src/main/java/ai/vespa/hosted/cd/Endpoint.java b/tenant-cd-api/src/main/java/ai/vespa/hosted/cd/Endpoint.java
index bd6f30767f2..afc6aa1b519 100644
--- a/tenant-cd/src/main/java/ai/vespa/hosted/cd/Endpoint.java
+++ b/tenant-cd-api/src/main/java/ai/vespa/hosted/cd/Endpoint.java
@@ -1,19 +1,12 @@
// Copyright 2020 Oath Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package ai.vespa.hosted.cd;
-import ai.vespa.hosted.api.EndpointAuthenticator;
-
import java.net.URI;
-import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.charset.StandardCharsets;
import java.util.Collections;
import java.util.Map;
-import java.util.stream.Collectors;
-
-import static java.net.URLEncoder.encode;
-import static java.nio.charset.StandardCharsets.UTF_8;
/**
* An endpoint in a Vespa application {@link Deployment}, which allows document retrieval.
@@ -25,7 +18,7 @@ public interface Endpoint {
/** Returns the URI of the endpoint, with scheme, host and port. */
URI uri();
- /** Sends the given request with required authentication. See {@link EndpointAuthenticator#authenticated} and {@link HttpClient#send}. */
+ /** Sends the given request with required authentication. */
<T> HttpResponse<T> send(HttpRequest.Builder request, HttpResponse.BodyHandler<T> handler);
/** Sends the given request with required authentication. */
diff --git a/tenant-cd/src/main/java/ai/vespa/hosted/cd/IntegrationTest.java b/tenant-cd-api/src/main/java/ai/vespa/hosted/cd/IntegrationTest.java
index f9dc15df32e..f9dc15df32e 100644
--- a/tenant-cd/src/main/java/ai/vespa/hosted/cd/IntegrationTest.java
+++ b/tenant-cd-api/src/main/java/ai/vespa/hosted/cd/IntegrationTest.java
diff --git a/tenant-cd/src/main/java/ai/vespa/hosted/cd/ProductionTest.java b/tenant-cd-api/src/main/java/ai/vespa/hosted/cd/ProductionTest.java
index 53e7311fefc..b9054689b00 100644
--- a/tenant-cd/src/main/java/ai/vespa/hosted/cd/ProductionTest.java
+++ b/tenant-cd-api/src/main/java/ai/vespa/hosted/cd/ProductionTest.java
@@ -2,7 +2,6 @@
package ai.vespa.hosted.cd;
import org.junit.jupiter.api.Tag;
-import org.junit.jupiter.api.Test;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
diff --git a/tenant-cd/src/main/java/ai/vespa/hosted/cd/StagingSetup.java b/tenant-cd-api/src/main/java/ai/vespa/hosted/cd/StagingSetup.java
index bef3eabcef6..bef3eabcef6 100644
--- a/tenant-cd/src/main/java/ai/vespa/hosted/cd/StagingSetup.java
+++ b/tenant-cd-api/src/main/java/ai/vespa/hosted/cd/StagingSetup.java
diff --git a/tenant-cd/src/main/java/ai/vespa/hosted/cd/StagingTest.java b/tenant-cd-api/src/main/java/ai/vespa/hosted/cd/StagingTest.java
index 59360b2753c..59360b2753c 100644
--- a/tenant-cd/src/main/java/ai/vespa/hosted/cd/StagingTest.java
+++ b/tenant-cd-api/src/main/java/ai/vespa/hosted/cd/StagingTest.java
diff --git a/tenant-cd/src/main/java/ai/vespa/hosted/cd/SystemTest.java b/tenant-cd-api/src/main/java/ai/vespa/hosted/cd/SystemTest.java
index f01f2ca6c90..f01f2ca6c90 100644
--- a/tenant-cd/src/main/java/ai/vespa/hosted/cd/SystemTest.java
+++ b/tenant-cd-api/src/main/java/ai/vespa/hosted/cd/SystemTest.java
diff --git a/tenant-cd-api/src/main/java/ai/vespa/hosted/cd/TestRuntime.java b/tenant-cd-api/src/main/java/ai/vespa/hosted/cd/TestRuntime.java
new file mode 100644
index 00000000000..feea05b7064
--- /dev/null
+++ b/tenant-cd-api/src/main/java/ai/vespa/hosted/cd/TestRuntime.java
@@ -0,0 +1,19 @@
+// Copyright 2020 Oath Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+package ai.vespa.hosted.cd;
+
+import java.util.ServiceLoader;
+
+/**
+ * The place to obtain environment-dependent configuration for test of a Vespa deployment.
+ *
+ * @author jvenstad
+ * @author mortent
+ */
+public interface TestRuntime {
+ static TestRuntime get() {
+ ServiceLoader<TestRuntime> serviceLoader = ServiceLoader.load(TestRuntime.class);
+ return serviceLoader.findFirst().orElseThrow(() -> new RuntimeException("No TestRuntime implementation found"));
+ }
+
+ Deployment deploymentToTest();
+}