aboutsummaryrefslogtreecommitdiffstats
path: root/configserver
diff options
context:
space:
mode:
authorHarald Musum <musum@verizonmedia.com>2020-03-11 12:28:21 +0100
committerHarald Musum <musum@verizonmedia.com>2020-03-11 12:28:21 +0100
commit5f620f817dd9778b5fc45e433368c1bb4d6e9f45 (patch)
tree93df3f7928dea89e899f14a51814dc470775f5f0 /configserver
parent811cb02ae056b5b61520fa578ec5a90bcb6a4c4f (diff)
Add support for using a Docker image repository when deploying an application
Preliminary support only, not completed
Diffstat (limited to 'configserver')
-rw-r--r--configserver/src/main/java/com/yahoo/vespa/config/server/ApplicationRepository.java4
-rw-r--r--configserver/src/main/java/com/yahoo/vespa/config/server/deploy/Deployment.java38
-rw-r--r--configserver/src/main/java/com/yahoo/vespa/config/server/deploy/ModelContextImpl.java7
-rw-r--r--configserver/src/main/java/com/yahoo/vespa/config/server/modelfactory/ActivatedModelsBuilder.java2
-rw-r--r--configserver/src/main/java/com/yahoo/vespa/config/server/modelfactory/ModelsBuilder.java14
-rw-r--r--configserver/src/main/java/com/yahoo/vespa/config/server/modelfactory/PreparedModelsBuilder.java6
-rw-r--r--configserver/src/main/java/com/yahoo/vespa/config/server/session/LocalSession.java6
-rw-r--r--configserver/src/main/java/com/yahoo/vespa/config/server/session/PrepareParams.java22
-rw-r--r--configserver/src/main/java/com/yahoo/vespa/config/server/session/RemoteSession.java1
-rw-r--r--configserver/src/main/java/com/yahoo/vespa/config/server/session/SessionFactoryImpl.java1
-rw-r--r--configserver/src/main/java/com/yahoo/vespa/config/server/session/SessionPreparer.java15
-rw-r--r--configserver/src/main/java/com/yahoo/vespa/config/server/session/SessionZooKeeperClient.java16
-rw-r--r--configserver/src/test/java/com/yahoo/vespa/config/server/ModelContextImplTest.java10
-rw-r--r--configserver/src/test/java/com/yahoo/vespa/config/server/deploy/DeployTester.java16
-rw-r--r--configserver/src/test/java/com/yahoo/vespa/config/server/deploy/HostedDeployTest.java14
-rw-r--r--configserver/src/test/java/com/yahoo/vespa/config/server/http/SessionHandlerTest.java29
-rw-r--r--configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/SessionPrepareHandlerTest.java68
17 files changed, 196 insertions, 73 deletions
diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/ApplicationRepository.java b/configserver/src/main/java/com/yahoo/vespa/config/server/ApplicationRepository.java
index d3f37eb320e..b10726cd73b 100644
--- a/configserver/src/main/java/com/yahoo/vespa/config/server/ApplicationRepository.java
+++ b/configserver/src/main/java/com/yahoo/vespa/config/server/ApplicationRepository.java
@@ -314,7 +314,9 @@ public class ApplicationRepository implements com.yahoo.config.provision.Deploye
tenant.getLocalSessionRepo().addSession(newSession);
return Optional.of(Deployment.unprepared(newSession, this, hostProvisioner, tenant, timeout, clock,
- false /* don't validate as this is already deployed */, newSession.getVespaVersion(),
+ false /* don't validate as this is already deployed */,
+ newSession.getDockerImageRepository(),
+ newSession.getVespaVersion(),
bootstrap));
}
diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/deploy/Deployment.java b/configserver/src/main/java/com/yahoo/vespa/config/server/deploy/Deployment.java
index 89d7c349d6b..9a46ce099f8 100644
--- a/configserver/src/main/java/com/yahoo/vespa/config/server/deploy/Deployment.java
+++ b/configserver/src/main/java/com/yahoo/vespa/config/server/deploy/Deployment.java
@@ -6,8 +6,6 @@ import com.yahoo.config.application.api.DeployLogger;
import com.yahoo.config.provision.ApplicationId;
import com.yahoo.config.provision.HostFilter;
import com.yahoo.config.provision.Provisioner;
-import com.yahoo.config.provision.zone.ZoneId;
-import com.yahoo.jdisc.Metric;
import com.yahoo.log.LogLevel;
import com.yahoo.transaction.NestedTransaction;
import com.yahoo.transaction.Transaction;
@@ -25,7 +23,6 @@ import com.yahoo.vespa.curator.Lock;
import java.time.Clock;
import java.time.Duration;
-import java.time.Instant;
import java.util.Optional;
import java.util.logging.Logger;
@@ -49,7 +46,10 @@ public class Deployment implements com.yahoo.config.provision.Deployment {
private final Duration timeout;
private final Clock clock;
private final DeployLogger logger = new SilentDeployLogger();
-
+
+ /** The repository part of docker image this application should run on. Version is separate from image repo */
+ Optional<String> dockerImageRepository;
+
/** The Vespa version this application should run on */
private final Version version;
@@ -65,8 +65,8 @@ public class Deployment implements com.yahoo.config.provision.Deployment {
private Deployment(LocalSession session, ApplicationRepository applicationRepository,
Optional<Provisioner> hostProvisioner, Tenant tenant,
- Duration timeout, Clock clock, boolean prepared, boolean validate, Version version,
- boolean isBootstrap) {
+ Duration timeout, Clock clock, boolean prepared, boolean validate,
+ Optional<String> dockerImageRepository, Version version, boolean isBootstrap) {
this.session = session;
this.applicationRepository = applicationRepository;
this.hostProvisioner = hostProvisioner;
@@ -75,23 +75,26 @@ public class Deployment implements com.yahoo.config.provision.Deployment {
this.clock = clock;
this.prepared = prepared;
this.validate = validate;
+ this.dockerImageRepository = dockerImageRepository;
this.version = version;
this.isBootstrap = isBootstrap;
}
public static Deployment unprepared(LocalSession session, ApplicationRepository applicationRepository,
Optional<Provisioner> hostProvisioner, Tenant tenant,
- Duration timeout, Clock clock, boolean validate, Version version,
+ Duration timeout, Clock clock, boolean validate,
+ Optional<String> dockerImageRepository, Version version,
boolean isBootstrap) {
return new Deployment(session, applicationRepository, hostProvisioner, tenant,
- timeout, clock, false, validate, version, isBootstrap);
+ timeout, clock, false, validate, dockerImageRepository, version, isBootstrap);
}
public static Deployment prepared(LocalSession session, ApplicationRepository applicationRepository,
Optional<Provisioner> hostProvisioner, Tenant tenant,
Duration timeout, Clock clock, boolean isBootstrap) {
return new Deployment(session, applicationRepository, hostProvisioner, tenant,
- timeout, clock, true, true, session.getVespaVersion(), isBootstrap);
+ timeout, clock, true, true, session.getDockerImageRepository(),
+ session.getVespaVersion(), isBootstrap);
}
public void setIgnoreSessionStaleFailure(boolean ignoreSessionStaleFailure) {
@@ -105,16 +108,13 @@ public class Deployment implements com.yahoo.config.provision.Deployment {
try (ActionTimer timer = applicationRepository.timerFor(session.getApplicationId(), "deployment.prepareMillis")) {
TimeoutBudget timeoutBudget = new TimeoutBudget(clock, timeout);
- session.prepare(logger,
- new PrepareParams.Builder().applicationId(session.getApplicationId())
- .timeoutBudget(timeoutBudget)
- .ignoreValidationErrors(!validate)
- .vespaVersion(version.toString())
- .isBootstrap(isBootstrap)
- .build(),
- Optional.empty(),
- tenant.getPath(),
- clock.instant());
+ PrepareParams.Builder params = new PrepareParams.Builder().applicationId(session.getApplicationId())
+ .timeoutBudget(timeoutBudget)
+ .ignoreValidationErrors(!validate)
+ .vespaVersion(version.toString())
+ .isBootstrap(isBootstrap);
+ dockerImageRepository.ifPresent(params::dockerImageRepository);
+ session.prepare(logger, params.build(), Optional.empty(), tenant.getPath(), clock.instant());
this.prepared = true;
}
}
diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/deploy/ModelContextImpl.java b/configserver/src/main/java/com/yahoo/vespa/config/server/deploy/ModelContextImpl.java
index db90d3f9976..55a1482cde8 100644
--- a/configserver/src/main/java/com/yahoo/vespa/config/server/deploy/ModelContextImpl.java
+++ b/configserver/src/main/java/com/yahoo/vespa/config/server/deploy/ModelContextImpl.java
@@ -43,6 +43,8 @@ public class ModelContextImpl implements ModelContext {
private final ModelContext.Properties properties;
private final Optional<File> appDir;
+ private final Optional<String> wantedDockerImageRepository;
+
/** The version of Vespa we are building a model for */
private final Version modelVespaVersion;
@@ -64,6 +66,7 @@ public class ModelContextImpl implements ModelContext {
Optional<HostProvisioner> hostProvisioner,
ModelContext.Properties properties,
Optional<File> appDir,
+ Optional<String> wantedDockerImageRepository,
Version modelVespaVersion,
Version wantedNodeVespaVersion) {
this.applicationPackage = applicationPackage;
@@ -75,6 +78,7 @@ public class ModelContextImpl implements ModelContext {
this.hostProvisioner = hostProvisioner;
this.properties = properties;
this.appDir = appDir;
+ this.wantedDockerImageRepository = wantedDockerImageRepository;
this.modelVespaVersion = modelVespaVersion;
this.wantedNodeVespaVersion = wantedNodeVespaVersion;
}
@@ -112,6 +116,9 @@ public class ModelContextImpl implements ModelContext {
public Optional<File> appDir() { return appDir; }
@Override
+ public Optional<String> wantedDockerImageRepository() { return wantedDockerImageRepository; }
+
+ @Override
public Version modelVespaVersion() { return modelVespaVersion; }
@Override
diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/modelfactory/ActivatedModelsBuilder.java b/configserver/src/main/java/com/yahoo/vespa/config/server/modelfactory/ActivatedModelsBuilder.java
index a2fc2bfd6a0..70faf3ff36f 100644
--- a/configserver/src/main/java/com/yahoo/vespa/config/server/modelfactory/ActivatedModelsBuilder.java
+++ b/configserver/src/main/java/com/yahoo/vespa/config/server/modelfactory/ActivatedModelsBuilder.java
@@ -83,6 +83,7 @@ public class ActivatedModelsBuilder extends ModelsBuilder<Application> {
protected Application buildModelVersion(ModelFactory modelFactory,
ApplicationPackage applicationPackage,
ApplicationId applicationId,
+ Optional<String> wantedDockerImageRepository,
Version wantedNodeVespaVersion,
Optional<AllocatedHosts> ignored, // Ignored since we have this in the app package for activated models
Instant now) {
@@ -99,6 +100,7 @@ public class ActivatedModelsBuilder extends ModelsBuilder<Application> {
createStaticProvisioner(applicationPackage.getAllocatedHosts(), modelContextProperties),
modelContextProperties,
Optional.empty(),
+ wantedDockerImageRepository,
modelFactory.version(),
wantedNodeVespaVersion);
MetricUpdater applicationMetricUpdater = metrics.getOrCreateMetricUpdater(Metrics.createDimensions(applicationId));
diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/modelfactory/ModelsBuilder.java b/configserver/src/main/java/com/yahoo/vespa/config/server/modelfactory/ModelsBuilder.java
index 2de64ed145c..5257fc6b72e 100644
--- a/configserver/src/main/java/com/yahoo/vespa/config/server/modelfactory/ModelsBuilder.java
+++ b/configserver/src/main/java/com/yahoo/vespa/config/server/modelfactory/ModelsBuilder.java
@@ -72,6 +72,7 @@ public abstract class ModelsBuilder<MODELRESULT extends ModelResult> {
* and assigns to this SettableOptional such that it can be used after this method returns
*/
public List<MODELRESULT> buildModels(ApplicationId applicationId,
+ Optional<String> dockerImageRepository,
Version wantedNodeVespaVersion,
ApplicationPackage applicationPackage,
SettableOptional<AllocatedHosts> allocatedHosts,
@@ -104,8 +105,9 @@ public abstract class ModelsBuilder<MODELRESULT extends ModelResult> {
int majorVersion = majorVersions.get(i);
try {
allApplicationModels.addAll(buildModelVersions(keepMajorVersion(majorVersion, versions),
- applicationId, wantedNodeVespaVersion, applicationPackage,
- allocatedHosts, now, buildLatestModelForThisMajor, majorVersion));
+ applicationId, dockerImageRepository, wantedNodeVespaVersion,
+ applicationPackage, allocatedHosts, now,
+ buildLatestModelForThisMajor, majorVersion));
buildLatestModelForThisMajor = false; // We have successfully built latest model version, do it only for this major
}
catch (OutOfCapacityException | ApplicationLockException | TransientException e) {
@@ -146,6 +148,7 @@ public abstract class ModelsBuilder<MODELRESULT extends ModelResult> {
// versions is the set of versions for one particular major version
private List<MODELRESULT> buildModelVersions(Set<Version> versions,
ApplicationId applicationId,
+ Optional<String> wantedDockerImageRepository,
Version wantedNodeVespaVersion,
ApplicationPackage applicationPackage,
SettableOptional<AllocatedHosts> allocatedHosts,
@@ -160,6 +163,7 @@ public abstract class ModelsBuilder<MODELRESULT extends ModelResult> {
MODELRESULT latestModelVersion = buildModelVersion(modelFactoryRegistry.getFactory(latest.get()),
applicationPackage,
applicationId,
+ wantedDockerImageRepository,
wantedNodeVespaVersion,
allocatedHosts.asOptional(),
now);
@@ -182,6 +186,7 @@ public abstract class ModelsBuilder<MODELRESULT extends ModelResult> {
modelVersion = buildModelVersion(modelFactoryRegistry.getFactory(version),
applicationPackage,
applicationId,
+ wantedDockerImageRepository,
wantedNodeVespaVersion,
allocatedHosts.asOptional(),
now);
@@ -236,9 +241,8 @@ public abstract class ModelsBuilder<MODELRESULT extends ModelResult> {
}
protected abstract MODELRESULT buildModelVersion(ModelFactory modelFactory, ApplicationPackage applicationPackage,
- ApplicationId applicationId,
- Version wantedNodeVespaVersion,
- Optional<AllocatedHosts> allocatedHosts,
+ ApplicationId applicationId, Optional<String> dockerImageRepository,
+ Version wantedNodeVespaVersion, Optional<AllocatedHosts> allocatedHosts,
Instant now);
/**
diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/modelfactory/PreparedModelsBuilder.java b/configserver/src/main/java/com/yahoo/vespa/config/server/modelfactory/PreparedModelsBuilder.java
index 9cacb78e53c..598cec325b6 100644
--- a/configserver/src/main/java/com/yahoo/vespa/config/server/modelfactory/PreparedModelsBuilder.java
+++ b/configserver/src/main/java/com/yahoo/vespa/config/server/modelfactory/PreparedModelsBuilder.java
@@ -82,8 +82,9 @@ public class PreparedModelsBuilder extends ModelsBuilder<PreparedModelsBuilder.P
@Override
protected PreparedModelResult buildModelVersion(ModelFactory modelFactory,
ApplicationPackage applicationPackage,
- ApplicationId applicationId,
- com.yahoo.component.Version wantedNodeVespaVersion,
+ ApplicationId applicationId,
+ Optional<String> wantedDockerImageRepository,
+ Version wantedNodeVespaVersion,
Optional<AllocatedHosts> allocatedHosts,
Instant now) {
Version modelVersion = modelFactory.version();
@@ -101,6 +102,7 @@ public class PreparedModelsBuilder extends ModelsBuilder<PreparedModelsBuilder.P
createHostProvisioner(allocatedHosts),
properties,
getAppDir(applicationPackage),
+ wantedDockerImageRepository,
modelVersion,
wantedNodeVespaVersion);
diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/session/LocalSession.java b/configserver/src/main/java/com/yahoo/vespa/config/server/session/LocalSession.java
index 2c6d7de8b0c..e9d1f39f788 100644
--- a/configserver/src/main/java/com/yahoo/vespa/config/server/session/LocalSession.java
+++ b/configserver/src/main/java/com/yahoo/vespa/config/server/session/LocalSession.java
@@ -138,6 +138,10 @@ public class LocalSession extends Session implements Comparable<LocalSession> {
zooKeeperClient.writeVespaVersion(version);
}
+ public void setDockerImageRepository(Optional<String> dockerImageRepository) {
+ zooKeeperClient.writeDockerImageRepository(dockerImageRepository);
+ }
+
public enum Mode {
READ, WRITE
}
@@ -148,6 +152,8 @@ public class LocalSession extends Session implements Comparable<LocalSession> {
public ApplicationId getApplicationId() { return zooKeeperClient.readApplicationId(); }
+ public Optional<String> getDockerImageRepository() { return zooKeeperClient.readDockerImageRepository(); }
+
public Version getVespaVersion() { return zooKeeperClient.readVespaVersion(); }
public AllocatedHosts getAllocatedHosts() {
diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/session/PrepareParams.java b/configserver/src/main/java/com/yahoo/vespa/config/server/session/PrepareParams.java
index 49f59773bca..e217bb39b39 100644
--- a/configserver/src/main/java/com/yahoo/vespa/config/server/session/PrepareParams.java
+++ b/configserver/src/main/java/com/yahoo/vespa/config/server/session/PrepareParams.java
@@ -35,6 +35,7 @@ public final class PrepareParams {
static final String CONTAINER_ENDPOINTS_PARAM_NAME = "containerEndpoints";
static final String TLS_SECRETS_KEY_NAME_PARAM_NAME = "tlsSecretsKeyName";
static final String ENDPOINT_CERTIFICATE_METADATA_PARAM_NAME = "endpointCertificateMetadata";
+ static final String DOCKER_IMAGE_REPOSITORY = "dockerImageRepository";
private final ApplicationId applicationId;
private final TimeoutBudget timeoutBudget;
@@ -46,11 +47,13 @@ public final class PrepareParams {
private final List<ContainerEndpoint> containerEndpoints;
private final Optional<String> tlsSecretsKeyName;
private final Optional<EndpointCertificateMetadata> endpointCertificateMetadata;
+ private final Optional<String> dockerImageRepository;
private PrepareParams(ApplicationId applicationId, TimeoutBudget timeoutBudget, boolean ignoreValidationErrors,
boolean dryRun, boolean verbose, boolean isBootstrap, Optional<Version> vespaVersion,
List<ContainerEndpoint> containerEndpoints, Optional<String> tlsSecretsKeyName,
- Optional<EndpointCertificateMetadata> endpointCertificateMetadata) {
+ Optional<EndpointCertificateMetadata> endpointCertificateMetadata,
+ Optional<String> dockerImageRepository) {
this.timeoutBudget = timeoutBudget;
this.applicationId = applicationId;
this.ignoreValidationErrors = ignoreValidationErrors;
@@ -61,6 +64,7 @@ public final class PrepareParams {
this.containerEndpoints = containerEndpoints;
this.tlsSecretsKeyName = tlsSecretsKeyName;
this.endpointCertificateMetadata = endpointCertificateMetadata;
+ this.dockerImageRepository = dockerImageRepository;
}
public static class Builder {
@@ -75,6 +79,7 @@ public final class PrepareParams {
private List<ContainerEndpoint> containerEndpoints = List.of();
private Optional<String> tlsSecretsKeyName = Optional.empty();
private Optional<EndpointCertificateMetadata> endpointCertificateMetadata = Optional.empty();
+ private Optional<String> dockerImageRepository = Optional.empty();
public Builder() { }
@@ -142,9 +147,16 @@ public final class PrepareParams {
return this;
}
+ public Builder dockerImageRepository(String dockerImageRepository) {
+ if (dockerImageRepository == null) return this;
+ this.dockerImageRepository = Optional.of(dockerImageRepository);
+ return this;
+ }
+
public PrepareParams build() {
return new PrepareParams(applicationId, timeoutBudget, ignoreValidationErrors, dryRun,
- verbose, isBootstrap, vespaVersion, containerEndpoints, tlsSecretsKeyName, endpointCertificateMetadata);
+ verbose, isBootstrap, vespaVersion, containerEndpoints, tlsSecretsKeyName,
+ endpointCertificateMetadata, dockerImageRepository);
}
}
@@ -159,6 +171,7 @@ public final class PrepareParams {
.containerEndpoints(request.getProperty(CONTAINER_ENDPOINTS_PARAM_NAME))
.tlsSecretsKeyName(request.getProperty(TLS_SECRETS_KEY_NAME_PARAM_NAME))
.endpointCertificateMetadata(request.getProperty(ENDPOINT_CERTIFICATE_METADATA_PARAM_NAME))
+ .dockerImageRepository(request.getProperty(DOCKER_IMAGE_REPOSITORY))
.build();
}
@@ -219,4 +232,9 @@ public final class PrepareParams {
public Optional<EndpointCertificateMetadata> endpointCertificateMetadata() {
return endpointCertificateMetadata;
}
+
+ public Optional<String> dockerImageRepository() {
+ return dockerImageRepository;
+ }
+
}
diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/session/RemoteSession.java b/configserver/src/main/java/com/yahoo/vespa/config/server/session/RemoteSession.java
index 26f437920ad..39c15474f0e 100644
--- a/configserver/src/main/java/com/yahoo/vespa/config/server/session/RemoteSession.java
+++ b/configserver/src/main/java/com/yahoo/vespa/config/server/session/RemoteSession.java
@@ -63,6 +63,7 @@ public class RemoteSession extends Session {
Optional<AllocatedHosts> allocatedHosts = applicationPackage.getAllocatedHosts();
return ApplicationSet.fromList(applicationLoader.buildModels(zooKeeperClient.readApplicationId(),
+ zooKeeperClient.readDockerImageRepository(),
zooKeeperClient.readVespaVersion(),
applicationPackage,
new SettableOptional<>(allocatedHosts),
diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/session/SessionFactoryImpl.java b/configserver/src/main/java/com/yahoo/vespa/config/server/session/SessionFactoryImpl.java
index cb1f6519f57..87dead8eed1 100644
--- a/configserver/src/main/java/com/yahoo/vespa/config/server/session/SessionFactoryImpl.java
+++ b/configserver/src/main/java/com/yahoo/vespa/config/server/session/SessionFactoryImpl.java
@@ -131,6 +131,7 @@ public class SessionFactoryImpl implements SessionFactory, LocalSessionLoader {
LocalSession session = create(existingApp, existingApplicationId, activeSessionId, internalRedeploy, timeoutBudget);
session.setApplicationId(existingApplicationId);
session.setVespaVersion(existingSession.getVespaVersion());
+ session.setDockerImageRepository(existingSession.getDockerImageRepository());
return session;
}
diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/session/SessionPreparer.java b/configserver/src/main/java/com/yahoo/vespa/config/server/session/SessionPreparer.java
index 0115876ded9..d2c7fe3718e 100644
--- a/configserver/src/main/java/com/yahoo/vespa/config/server/session/SessionPreparer.java
+++ b/configserver/src/main/java/com/yahoo/vespa/config/server/session/SessionPreparer.java
@@ -114,6 +114,7 @@ public class SessionPreparer {
try {
AllocatedHosts allocatedHosts = preparation.buildModels(now);
preparation.makeResult(allocatedHosts);
+ System.out.println("Dry run: " + params.isDryRun());
if ( ! params.isDryRun()) {
preparation.writeStateZK();
preparation.writeEndpointCertificateMetadataZK();
@@ -139,8 +140,11 @@ public class SessionPreparer {
final Path tenantPath;
final ApplicationId applicationId;
+ /** The repository part of docker image to be used for this deployment */
+ final Optional<String> dockerImageRepository;
+
/** The version of Vespa the application to be prepared specifies for its nodes */
- final com.yahoo.component.Version vespaVersion;
+ final Version vespaVersion;
final ContainerEndpointsCache containerEndpoints;
final Set<ContainerEndpoint> endpointsSet;
@@ -165,6 +169,7 @@ public class SessionPreparer {
this.tenantPath = tenantPath;
this.applicationId = params.getApplicationId();
+ this.dockerImageRepository = params.dockerImageRepository();
this.vespaVersion = params.vespaVersion().orElse(Vtag.currentVersion);
this.containerEndpoints = new ContainerEndpointsCache(tenantPath, curator);
this.endpointCertificateMetadataStore = new EndpointCertificateMetadataStore(curator, tenantPath);
@@ -223,7 +228,7 @@ public class SessionPreparer {
AllocatedHosts buildModels(Instant now) {
SettableOptional<AllocatedHosts> allocatedHosts = new SettableOptional<>();
- this.modelResultList = preparedModelsBuilder.buildModels(applicationId, vespaVersion,
+ this.modelResultList = preparedModelsBuilder.buildModels(applicationId, dockerImageRepository, vespaVersion,
applicationPackage, allocatedHosts, now);
checkTimeout("build models");
return allocatedHosts.get();
@@ -239,6 +244,7 @@ public class SessionPreparer {
writeStateToZooKeeper(context.getSessionZooKeeperClient(),
applicationPackage,
applicationId,
+ dockerImageRepository,
vespaVersion,
logger,
prepareResult.getFileRegistries(),
@@ -281,15 +287,18 @@ public class SessionPreparer {
private void writeStateToZooKeeper(SessionZooKeeperClient zooKeeperClient,
ApplicationPackage applicationPackage,
ApplicationId applicationId,
- com.yahoo.component.Version vespaVersion,
+ Optional<String> dockerImageRepository,
+ Version vespaVersion,
DeployLogger deployLogger,
Map<Version, FileRegistry> fileRegistryMap,
AllocatedHosts allocatedHosts) {
+ System.out.println("DEBUG DEBUG");
ZooKeeperDeployer zkDeployer = zooKeeperClient.createDeployer(deployLogger);
try {
zkDeployer.deploy(applicationPackage, fileRegistryMap, allocatedHosts);
zooKeeperClient.writeApplicationId(applicationId);
zooKeeperClient.writeVespaVersion(vespaVersion);
+ zooKeeperClient.writeDockerImageRepository(dockerImageRepository);
} catch (RuntimeException | IOException e) {
zkDeployer.cleanup();
throw new RuntimeException("Error preparing session", e);
diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/session/SessionZooKeeperClient.java b/configserver/src/main/java/com/yahoo/vespa/config/server/session/SessionZooKeeperClient.java
index 727d4e6d7bc..36415512491 100644
--- a/configserver/src/main/java/com/yahoo/vespa/config/server/session/SessionZooKeeperClient.java
+++ b/configserver/src/main/java/com/yahoo/vespa/config/server/session/SessionZooKeeperClient.java
@@ -41,6 +41,7 @@ public class SessionZooKeeperClient {
static final String APPLICATION_ID_PATH = "applicationId";
private static final String VERSION_PATH = "version";
private static final String CREATE_TIME_PATH = "createTime";
+ private static final String DOCKER_IMAGE_REPOSITORY_PATH = "dockerImageRepository";
private final Curator curator;
private final ConfigCurator configCurator;
private final Path sessionPath;
@@ -165,6 +166,10 @@ public class SessionZooKeeperClient {
return sessionPath.append(VERSION_PATH).getAbsolute();
}
+ private String dockerImageRepositoryPath() {
+ return sessionPath.append(DOCKER_IMAGE_REPOSITORY_PATH).getAbsolute();
+ }
+
public void writeVespaVersion(Version version) {
configCurator.putData(versionPath(), version.toString());
}
@@ -174,6 +179,17 @@ public class SessionZooKeeperClient {
return new Version(configCurator.getData(versionPath()));
}
+ public Optional<String> readDockerImageRepository() {
+ if ( ! configCurator.exists(dockerImageRepositoryPath())) return Optional.empty();
+ String dockerImageRepository = configCurator.getData(dockerImageRepositoryPath());
+ return dockerImageRepository.isEmpty() ? Optional.empty() : Optional.of(dockerImageRepository);
+ }
+
+ public void writeDockerImageRepository(Optional<String> dockerImageRepository) {
+ System.out.println("Writing docker image repo");
+ dockerImageRepository.ifPresent(repo -> configCurator.putData(dockerImageRepositoryPath(), repo));
+ }
+
// in seconds
public long readCreateTime() {
String path = getCreateTimePath();
diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/ModelContextImplTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/ModelContextImplTest.java
index 370e0bd3c0e..339c676000b 100644
--- a/configserver/src/test/java/com/yahoo/vespa/config/server/ModelContextImplTest.java
+++ b/configserver/src/test/java/com/yahoo/vespa/config/server/ModelContextImplTest.java
@@ -20,6 +20,7 @@ import java.util.Set;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.is;
+import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertThat;
@@ -60,8 +61,9 @@ public class ModelContextImplTest {
flagSource,
null),
Optional.empty(),
- new Version(6),
- new Version(6));
+ Optional.empty(),
+ new Version(7),
+ new Version(8));
assertTrue(context.applicationPackage() instanceof MockApplicationPackage);
assertFalse(context.hostProvisioner().isPresent());
assertFalse(context.permanentApplicationPackage().isPresent());
@@ -75,6 +77,10 @@ public class ModelContextImplTest {
assertFalse(context.properties().hostedVespa());
assertThat(context.properties().endpoints(), equalTo(endpoints));
assertThat(context.properties().isFirstTimeDeployment(), equalTo(false));
+
+ assertEquals(Optional.empty(), context.wantedDockerImageRepository());
+ assertEquals(new Version(7), context.modelVespaVersion());
+ assertEquals(new Version(8), context.wantedNodeVespaVersion());
}
}
diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/deploy/DeployTester.java b/configserver/src/test/java/com/yahoo/vespa/config/server/deploy/DeployTester.java
index 32b704dd551..85f07da0325 100644
--- a/configserver/src/test/java/com/yahoo/vespa/config/server/deploy/DeployTester.java
+++ b/configserver/src/test/java/com/yahoo/vespa/config/server/deploy/DeployTester.java
@@ -216,12 +216,28 @@ public class DeployTester {
return deployApp(applicationPath, vespaVersion, Instant.now());
}
+
+ /**
+ * Do the initial "deploy" with the existing API-less code as the deploy API doesn't support first deploys yet.
+ */
+ public PrepareResult deployApp(String applicationPath, String vespaVersion, String dockerImageRepository) {
+ return deployApp(applicationPath, vespaVersion, Instant.now(), dockerImageRepository);
+ }
+
/**
* Do the initial "deploy" with the existing API-less code as the deploy API doesn't support first deploys yet.
*/
public PrepareResult deployApp(String applicationPath, String vespaVersion, Instant now) {
+ return deployApp(applicationPath, vespaVersion, now, null);
+ }
+
+ /**
+ * Do the initial "deploy" with the existing API-less code as the deploy API doesn't support first deploys yet.
+ */
+ public PrepareResult deployApp(String applicationPath, String vespaVersion, Instant now, String dockerImageRepository) {
PrepareParams.Builder paramsBuilder = new PrepareParams.Builder()
.applicationId(applicationId)
+ .dockerImageRepository(dockerImageRepository)
.timeoutBudget(new TimeoutBudget(clock, Duration.ofSeconds(60)));
if (vespaVersion != null)
paramsBuilder.vespaVersion(vespaVersion);
diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/deploy/HostedDeployTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/deploy/HostedDeployTest.java
index dd0c4eaf342..5498d4b0315 100644
--- a/configserver/src/test/java/com/yahoo/vespa/config/server/deploy/HostedDeployTest.java
+++ b/configserver/src/test/java/com/yahoo/vespa/config/server/deploy/HostedDeployTest.java
@@ -87,6 +87,20 @@ public class HostedDeployTest {
}
@Test
+ public void testDeployWithWantedDockerImageRepository() throws IOException {
+ CountingModelFactory modelFactory = createHostedModelFactory(Version.fromString("4.5.6"), Clock.systemUTC());
+ DeployTester tester = new DeployTester(List.of(modelFactory), createConfigserverConfig());
+ String dockerImageRepository = "docker.foo.com:4443/bar/baz";
+ tester.deployApp("src/test/apps/hosted/", "4.5.6", dockerImageRepository);
+
+ Optional<com.yahoo.config.provision.Deployment> deployment = tester.redeployFromLocalActive(tester.applicationId());
+ assertTrue(deployment.isPresent());
+ deployment.get().activate();
+ assertEquals("4.5.6", ((Deployment) deployment.get()).session().getVespaVersion().toString());
+ assertEquals(dockerImageRepository, ((Deployment) deployment.get()).session().getDockerImageRepository().get());
+ }
+
+ @Test
public void testDeployMultipleVersions() throws IOException {
List<ModelFactory> modelFactories = List.of(createHostedModelFactory(Version.fromString("6.1.0")),
createHostedModelFactory(Version.fromString("6.2.0")),
diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/http/SessionHandlerTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/http/SessionHandlerTest.java
index 9a326a18dd5..70bba674778 100644
--- a/configserver/src/test/java/com/yahoo/vespa/config/server/http/SessionHandlerTest.java
+++ b/configserver/src/test/java/com/yahoo/vespa/config/server/http/SessionHandlerTest.java
@@ -42,6 +42,7 @@ import java.nio.charset.StandardCharsets;
import java.time.Instant;
import java.util.Collection;
import java.util.List;
+import java.util.Map;
import java.util.Optional;
/**
@@ -55,15 +56,27 @@ public class SessionHandlerTest {
public static final String hostname = "foo";
public static final int port = 1337;
- public static HttpRequest createTestRequest(String path, com.yahoo.jdisc.http.HttpRequest.Method method, Cmd cmd, Long id, String subPath, InputStream data) {
- return HttpRequest.createTestRequest("http://" + hostname + ":" + port + path + "/" + id + "/" + cmd.toString() + subPath, method, data);
+
+ public static HttpRequest createTestRequest(String path, com.yahoo.jdisc.http.HttpRequest.Method method,
+ Cmd cmd, Long id, String subPath, InputStream data, Map<String, String> properties) {
+ return HttpRequest.createTestRequest("http://" + hostname + ":" + port + path + "/" + id + "/" +
+ cmd.toString() + subPath, method, data, properties);
+ }
+
+ public static HttpRequest createTestRequest(String path, com.yahoo.jdisc.http.HttpRequest.Method method,
+ Cmd cmd, Long id, String subPath, InputStream data) {
+ return HttpRequest.createTestRequest("http://" + hostname + ":" + port + path + "/" + id + "/" +
+ cmd.toString() + subPath, method, data);
}
- public static HttpRequest createTestRequest(String path, com.yahoo.jdisc.http.HttpRequest.Method method, Cmd cmd, Long id, String subPath) {
- return HttpRequest.createTestRequest("http://" + hostname + ":" + port + path + "/" + id + "/" + cmd.toString() + subPath, method);
+ public static HttpRequest createTestRequest(String path, com.yahoo.jdisc.http.HttpRequest.Method method,
+ Cmd cmd, Long id, String subPath) {
+ return HttpRequest.createTestRequest("http://" + hostname + ":" + port + path + "/" + id + "/" +
+ cmd.toString() + subPath, method);
}
- public static HttpRequest createTestRequest(String path, com.yahoo.jdisc.http.HttpRequest.Method method, Cmd cmd, Long id) {
+ public static HttpRequest createTestRequest(String path, com.yahoo.jdisc.http.HttpRequest.Method method,
+ Cmd cmd, Long id) {
return createTestRequest(path, method, cmd, id, "");
}
@@ -88,6 +101,7 @@ public class SessionHandlerTest {
private ConfigChangeActions actions = new ConfigChangeActions();
private long createTime = System.currentTimeMillis() / 1000;
private ApplicationId applicationId;
+ private Optional<String> dockerImageRepository;
public MockSession(long id, ApplicationPackage app) {
this(id, app, new InMemoryFlagSource());
@@ -115,6 +129,7 @@ public class SessionHandlerTest {
@Override
public ConfigChangeActions prepare(DeployLogger logger, PrepareParams params, Optional<ApplicationSet> application, Path tenantPath, Instant now) {
status = Session.Status.PREPARE;
+ this.dockerImageRepository = params.dockerImageRepository();
if (doVerboseLogging) {
logger.log(LogLevel.DEBUG, "debuglog");
}
@@ -158,6 +173,10 @@ public class SessionHandlerTest {
@Override
public void delete(NestedTransaction transaction) { }
+ @Override
+ public Optional<String> getDockerImageRepository() {
+ return dockerImageRepository;
+ }
}
public enum Cmd {
diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/SessionPrepareHandlerTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/SessionPrepareHandlerTest.java
index 028f5f9eb8c..11cbdb03ccf 100644
--- a/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/SessionPrepareHandlerTest.java
+++ b/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/SessionPrepareHandlerTest.java
@@ -44,6 +44,7 @@ import java.time.Instant;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
+import java.util.Map;
import java.util.Optional;
import static com.yahoo.jdisc.Response.Status.BAD_REQUEST;
@@ -90,7 +91,7 @@ public class SessionPrepareHandlerTest extends SessionHandlerTest {
@Test
public void require_error_when_session_id_does_not_exist() throws Exception {
// No session with this id exists
- HttpResponse response = createHandler().handle(SessionHandlerTest.createTestRequest(pathPrefix, HttpRequest.Method.PUT, Cmd.PREPARED, 9999L));
+ HttpResponse response = request(HttpRequest.Method.PUT, 9999L);
assertHttpStatusCodeErrorCodeAndMessage(response, NOT_FOUND, HttpErrorResponse.errorCodes.NOT_FOUND, "Session 9999 was not found");
}
@@ -120,8 +121,7 @@ public class SessionPrepareHandlerTest extends SessionHandlerTest {
public void require_that_activate_url_is_returned_on_success() throws Exception {
MockSession session = new MockSession(1, null);
localRepo.addSession(session);
- HttpResponse response = createHandler().handle(
- SessionHandlerTest.createTestRequest(pathPrefix, HttpRequest.Method.PUT, Cmd.PREPARED, 1L));
+ HttpResponse response = request(HttpRequest.Method.PUT, 1L);
assertThat(session.getStatus(), is(Session.Status.PREPARE));
assertNotNull(response);
assertThat(response.getStatus(), is(OK));
@@ -155,13 +155,11 @@ public class SessionPrepareHandlerTest extends SessionHandlerTest {
public void require_get_response_activate_url_on_ok() throws Exception {
MockSession session = new MockSession(1, null);
localRepo.addSession(session);
- SessionHandler sessHandler = createHandler();
- sessHandler.handle(SessionHandlerTest.createTestRequest(pathPrefix, HttpRequest.Method.PUT, Cmd.PREPARED, 1L));
+ request(HttpRequest.Method.PUT, 1L);
session.setStatus(Session.Status.PREPARE);
SessionZooKeeperClient zooKeeperClient = createSessionZooKeeperClient(session);
zooKeeperClient.writeStatus(Session.Status.PREPARE);
- HttpResponse getResponse = sessHandler.handle(
- SessionHandlerTest.createTestRequest(pathPrefix, HttpRequest.Method.GET, Cmd.PREPARED, 1L));
+ HttpResponse getResponse = request(HttpRequest.Method.GET, 1L);
assertResponseContains(getResponse, "\"activate\":\"http://foo:1337" + pathPrefix +
"1/active\",\"message\":\"Session 1" + preparedMessage);
}
@@ -170,19 +168,16 @@ public class SessionPrepareHandlerTest extends SessionHandlerTest {
public void require_get_response_error_on_not_prepared() throws Exception {
MockSession session = new MockSession(1, null);
localRepo.addSession(session);
- SessionHandler sessHandler = createHandler();
session.setStatus(Session.Status.NEW);
SessionZooKeeperClient zooKeeperClient = createSessionZooKeeperClient(session);
zooKeeperClient.writeStatus(Session.Status.NEW);
- HttpResponse getResponse = sessHandler.handle(
- SessionHandlerTest.createTestRequest(pathPrefix, HttpRequest.Method.GET, Cmd.PREPARED, 1L));
+ HttpResponse getResponse = request(HttpRequest.Method.GET, 1L);
assertHttpStatusCodeErrorCodeAndMessage(getResponse, BAD_REQUEST,
HttpErrorResponse.errorCodes.BAD_REQUEST,
"Session not prepared: 1");
session.setStatus(Session.Status.ACTIVATE);
zooKeeperClient.writeStatus(Session.Status.ACTIVATE);
- getResponse = sessHandler.handle(
- SessionHandlerTest.createTestRequest(pathPrefix, HttpRequest.Method.GET, Cmd.PREPARED, 1L));
+ getResponse = request(HttpRequest.Method.GET, 1L);
assertHttpStatusCodeErrorCodeAndMessage(getResponse, BAD_REQUEST,
HttpErrorResponse.errorCodes.BAD_REQUEST,
"Session is active: 1");
@@ -193,9 +188,7 @@ public class SessionPrepareHandlerTest extends SessionHandlerTest {
MockSession session = new MockSession(1, null);
localRepo.addSession(session);
session.setStatus(Session.Status.ACTIVATE);
- SessionHandler sessionHandler = createHandler();
- HttpResponse putResponse = sessionHandler.handle(
- SessionHandlerTest.createTestRequest(pathPrefix, HttpRequest.Method.PUT, Cmd.PREPARED, 1L));
+ HttpResponse putResponse = request(HttpRequest.Method.PUT, 1L);
assertHttpStatusCodeErrorCodeAndMessage(putResponse, BAD_REQUEST,
HttpErrorResponse.errorCodes.BAD_REQUEST,
"Session is active: 1");
@@ -205,9 +198,7 @@ public class SessionPrepareHandlerTest extends SessionHandlerTest {
public void require_get_response_error_when_session_id_does_not_exist() throws Exception {
MockSession session = new MockSession(1, null);
localRepo.addSession(session);
- SessionHandler sessHandler = createHandler();
- HttpResponse getResponse = sessHandler.handle(
- SessionHandlerTest.createTestRequest(pathPrefix, HttpRequest.Method.GET, Cmd.PREPARED, 9999L));
+ HttpResponse getResponse = request(HttpRequest.Method.GET, 9999L);
assertHttpStatusCodeErrorCodeAndMessage(getResponse, NOT_FOUND,
HttpErrorResponse.errorCodes.NOT_FOUND,
"Session 9999 was not found");
@@ -217,8 +208,7 @@ public class SessionPrepareHandlerTest extends SessionHandlerTest {
public void require_that_tenant_is_in_response() throws Exception {
MockSession session = new MockSession(1, null);
localRepo.addSession(session);
- HttpResponse response = createHandler().handle(
- SessionHandlerTest.createTestRequest(pathPrefix, HttpRequest.Method.PUT, Cmd.PREPARED, 1L));
+ HttpResponse response = request(HttpRequest.Method.PUT, 1L);
assertNotNull(response);
assertThat(response.getStatus(), is(OK));
assertThat(session.getStatus(), is(Session.Status.PREPARE));
@@ -242,8 +232,7 @@ public class SessionPrepareHandlerTest extends SessionHandlerTest {
localRepoDefault.addSession(session);
pathPrefix = "/application/v2/tenant/" + defaultTenant + "/session/";
- HttpResponse response = handler.handle(
- SessionHandlerTest.createTestRequest(pathPrefix, HttpRequest.Method.PUT, Cmd.PREPARED, sessionId));
+ HttpResponse response = request(HttpRequest.Method.PUT, sessionId);
assertNotNull(response);
assertThat(SessionHandlerTest.getRenderedString(response), response.getStatus(), is(OK));
assertThat(session.getStatus(), is(Session.Status.PREPARE));
@@ -274,8 +263,7 @@ public class SessionPrepareHandlerTest extends SessionHandlerTest {
public void require_that_config_change_actions_are_in_response() throws Exception {
MockSession session = new MockSession(1, null);
localRepo.addSession(session);
- HttpResponse response = createHandler().handle(
- SessionHandlerTest.createTestRequest(pathPrefix, HttpRequest.Method.PUT, Cmd.PREPARED, 1L));
+ HttpResponse response = request(HttpRequest.Method.PUT, 1L);
assertResponseContains(response, "\"configChangeActions\":{\"restart\":[],\"refeed\":[]}");
}
@@ -289,8 +277,7 @@ public class SessionPrepareHandlerTest extends SessionHandlerTest {
new MockRefeedAction("change-id", false, "other change", services, "test")));
MockSession session = new MockSession(1, null, actions);
localRepo.addSession(session);
- HttpResponse response = createHandler().handle(
- SessionHandlerTest.createTestRequest(pathPrefix, HttpRequest.Method.PUT, Cmd.PREPARED, 1L));
+ HttpResponse response = request(HttpRequest.Method.PUT, 1L);
assertResponseContains(response,
"Change(s) between active and new application that require restart:\\nIn cluster 'foo' of type 'bar");
assertResponseContains(response,
@@ -301,8 +288,7 @@ public class SessionPrepareHandlerTest extends SessionHandlerTest {
public void require_that_config_change_actions_are_not_logged_if_not_existing() throws Exception {
MockSession session = new MockSession(1, null);
localRepo.addSession(session);
- HttpResponse response = createHandler().handle(
- SessionHandlerTest.createTestRequest(pathPrefix, HttpRequest.Method.PUT, Cmd.PREPARED, 1L));
+ HttpResponse response = request(HttpRequest.Method.PUT, 1L);
assertResponseNotContains(response, "Change(s) between active and new application that require restart");
assertResponseNotContains(response, "Change(s) between active and new application that require re-feed");
}
@@ -312,8 +298,7 @@ public class SessionPrepareHandlerTest extends SessionHandlerTest {
String message = "Internal error";
SessionThrowingException session = new SessionThrowingException(new OutOfCapacityException(message));
localRepo.addSession(session);
- HttpResponse response = createHandler()
- .handle(SessionHandlerTest.createTestRequest(pathPrefix, HttpRequest.Method.PUT, Cmd.PREPARED, 1L));
+ HttpResponse response = request(HttpRequest.Method.PUT, 1L);
assertEquals(400, response.getStatus());
Slime data = getData(response);
assertThat(data.get().field("error-code").asString(), is(HttpErrorResponse.errorCodes.OUT_OF_CAPACITY.name()));
@@ -325,8 +310,7 @@ public class SessionPrepareHandlerTest extends SessionHandlerTest {
String message = "No nodes available";
SessionThrowingException session = new SessionThrowingException(new NullPointerException(message));
localRepo.addSession(session);
- HttpResponse response = createHandler()
- .handle(SessionHandlerTest.createTestRequest(pathPrefix, HttpRequest.Method.PUT, Cmd.PREPARED, 1L));
+ HttpResponse response = request(HttpRequest.Method.PUT, 1L);
assertEquals(500, response.getStatus());
Slime data = getData(response);
assertThat(data.get().field("error-code").asString(), is(HttpErrorResponse.errorCodes.INTERNAL_SERVER_ERROR.name()));
@@ -339,14 +323,22 @@ public class SessionPrepareHandlerTest extends SessionHandlerTest {
SessionThrowingException session =
new SessionThrowingException(new ApplicationLockException(new UncheckedTimeoutException(message)));
localRepo.addSession(session);
- HttpResponse response = createHandler()
- .handle(SessionHandlerTest.createTestRequest(pathPrefix, HttpRequest.Method.PUT, Cmd.PREPARED, 1L));
+ HttpResponse response = request(HttpRequest.Method.PUT, 1L);
assertEquals(500, response.getStatus());
Slime data = getData(response);
assertThat(data.get().field("error-code").asString(), is(HttpErrorResponse.errorCodes.APPLICATION_LOCK_FAILURE.name()));
assertThat(data.get().field("message").asString(), is(message));
}
+ @Test
+ public void test_docker_image_repository() {
+ MockSession session = new MockSession(1, null);
+ localRepo.addSession(session);
+ String dockerImageRepository = "https://foo.bar.com:4443/baz";
+ request(HttpRequest.Method.PUT, 1L, Map.of("dockerImageRepository", dockerImageRepository));
+ assertEquals(dockerImageRepository, localRepo.getSession(1).getDockerImageRepository().get());
+ }
+
private Slime getData(HttpResponse response) throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
response.render(baos);
@@ -374,6 +366,14 @@ public class SessionPrepareHandlerTest extends SessionHandlerTest {
}
+ private HttpResponse request(HttpRequest.Method put, long l) {
+ return request(put, l, Map.of());
+ }
+
+ private HttpResponse request(HttpRequest.Method put, long l, Map<String, String> requestParameters) {
+ return createHandler().handle(SessionHandlerTest.createTestRequest(pathPrefix, put, Cmd.PREPARED, l, "", null, requestParameters));
+ }
+
public static class SessionThrowingException extends LocalSession {
private final RuntimeException exception;