DefaultDockerCloudClient extends BuildServerAdapter implements DockerCloudClient { @Nonnull @Override public DockerInstance startNewInstance(@Nonnull final CloudImage image, @Nonnull final CloudInstanceUserData tag) throws QuotaException { LOG.info("Creating new instance from image: " + image); final DockerImage dockerImage = (DockerImage) image; DockerInstance instance = lock.call(() -> { DockerInstance instanceToStart = null; if (!canStartNewInstance(image)) { throw new QuotaException("Cannot start new instance."); } for (DockerInstance existingInstance : dockerImage.getInstances()) { if (existingInstance.getStatus() == InstanceStatus.STOPPED) { instanceToStart = existingInstance; break; } } if (instanceToStart == null) { instanceToStart = dockerImage.createInstance(); LOG.info("Created cloud instance " + instanceToStart.getUuid() + "."); } else { LOG.info("Reusing cloud instance " + instanceToStart.getUuid() + "."); } return instanceToStart; }); assert instance != null; tag.setAgentRemovePolicy(CloudConstants.AgentRemovePolicyValue.RemoveAgent); taskScheduler.scheduleInstanceTask( new DockerInstanceTask("Start of container", instance, InstanceStatus.SCHEDULED_TO_START) { @Override protected void callInternal() throws Exception { DockerInstance instance = getInstance(); LOG.info("Starting container " + instance.getUuid()); Optional<String> existingAgentHolderId = lock.callInterruptibly(() -> { checkReady(); instance.updateStartedTime(); instance.setStatus(InstanceStatus.STARTING); return instance.getAgentHolderId(); }); if (!existingAgentHolderId.isPresent()) { String serverAddress = serverURL != null ? serverURL.toString() : tag.getServerAddress(); CreateAgentParameters createAgentParameters = CreateAgentParameters. fromImageConfig(dockerImage.getConfig(), resolver, true); prepareLabelsMap(createAgentParameters, instance); prepareEnvMap(createAgentParameters, instance, serverAddress, tag); NewAgentHolderInfo agentHolder = clientFacade.createAgent(createAgentParameters); instance.bindWithAgentHolder(agentHolder); String agentHolderId = agentHolder.getId(); String taskId = clientFacade.startAgent(agentHolderId); instance.setTaskId(taskId); LOG.info("New container " + agentHolderId + " created."); } else { LOG.info("Reusing existing container: " + existingAgentHolderId); clientFacade.startAgent(existingAgentHolderId.get()); } scheduleDockerSync(); instance.setStatus(InstanceStatus.RUNNING); cloudState.registerRunningInstance(instance.getImageId(), instance.getInstanceId()); } }); return instance; } DefaultDockerCloudClient(@Nonnull DockerCloudClientConfig clientConfig,
                             @Nonnull final List<DockerImageConfig> imageConfigs,
                             @Nonnull final DockerImageNameResolver resolver,
                             @Nonnull CloudState cloudState,
                             @Nonnull final SBuildServer buildServer); @Nonnull @Override UUID getUuid(); @Nonnull @Override DockerCloudSupport getCloudSupport(); @Override void serverStartup(); @Override boolean isInitialized(); @Nullable @Override DockerImage findImageById(@Nonnull String id); @Nullable @Override DockerInstance findInstanceByAgent(@Nonnull AgentDescription agent); @Nonnull @Override Collection<DockerImage> getImages(); @Nullable @Override CloudErrorInfo getErrorInfo(); @Override boolean canStartNewInstance(@Nonnull CloudImage image); @Nullable @Override String generateAgentName(@Nonnull AgentDescription agent); @Nonnull @Override DockerInstance startNewInstance(@Nonnull final CloudImage image, @Nonnull final CloudInstanceUserData tag); @Override void restartInstance(@Nonnull final CloudInstance instance); @Override void terminateInstance(@Nonnull final CloudInstance instance); @Override void dispose(); Optional<Instant> getLastDockerSyncTime(); @Override void notifyFailure(@Nonnull String msg, @Nullable Throwable throwable);  }
@Test public void mustClearDockerInstanceWhenContainerDestroyed() { DefaultDockerCloudClient client = createClient(); DockerImage dockerImage = waitForImage(client); DockerInstance instance = client.startNewInstance(dockerImage, userData); waitForInstanceStatus(instance, InstanceStatus.RUNNING); TestDockerClientFacade clientFacade = testCloudSupport.getClientFacade(); clientFacade.removeAgentHolder(instance.getAgentHolderId().get()); waitUntil(() -> dockerImage.getInstances().isEmpty()); }
@Test public void mustClearDockerInstanceWhenContainerStopped() { DefaultDockerCloudClient client = createClient(); DockerImage dockerImage = waitForImage(client); DockerInstance instance = client.startNewInstance(dockerImage, userData); waitForInstanceStatus(instance, InstanceStatus.RUNNING); TestDockerClientFacade clientFacade = testCloudSupport.getClientFacade(); clientFacade.getAgentHolders().get(0).running(false); waitUntil(() -> dockerImage.getInstances().isEmpty()); }
@Test public void handlingOfDefaultServerURL() { serverURL = null; DefaultDockerCloudClient client = createClient(); DockerImage image = waitForImage(client); DockerInstance instance = client.startNewInstance(image, userData); waitForInstanceStatus(instance, InstanceStatus.RUNNING); assertThat(testCloudSupport.getClientFacade().getAgentHolders().get(0). getEnv().get(DockerCloudUtils.ENV_SERVER_URL)).isEqualTo(defaultServerURL.toString()); }
@Test public void registryAuthSuccessful() { registryCredentials = DockerRegistryCredentials.from("user", "password"); DefaultDockerCloudClient client = createClient(); DockerImage image = waitForImage(client); dockerImageResolver.image("registry-only-image"); testCloudSupport.getClientFacade(). registryImage("registry-only-image"). registryCredentials(DockerRegistryCredentials.from("user", "password")); DockerInstance instance = client.startNewInstance(image, userData); waitForInstanceStatus(instance, InstanceStatus.RUNNING); }
@Test public void registryAuthFailed() { registryCredentials = DockerRegistryCredentials.from("user", "password"); DefaultDockerCloudClient client = createClient(); DockerImage image = waitForImage(client); dockerImageResolver.image("registry-only-image"); testCloudSupport.getClientFacade(). registryImage("registry-only-image"). registryCredentials(DockerRegistryCredentials.from("user", "password")); DockerInstance instance = client.startNewInstance(image, userData); waitUntil(() -> instance.getStatus() == InstanceStatus.RUNNING); }
@Test public void imageResolutionFailure() { registryCredentials = DockerRegistryCredentials.from("user", "wrong password"); dockerImageResolver.image(null); DefaultDockerCloudClient client = createClient(); DockerImage image = waitForImage(client); dockerImageResolver.image("registry-only-image"); testCloudSupport.getClientFacade(). registryImage("registry-only-image"). registryCredentials(DockerRegistryCredentials.from("user", "password")); DockerInstance instance = client.startNewInstance(image, userData); waitUntil(() -> instance.getStatus() == InstanceStatus.ERROR); waitUntil(() -> image.getInstances().isEmpty()); }
@Test public void containerCreationException() { DefaultDockerCloudClient client = createClient(); DockerImage image = waitForImage(client); TestDockerClientFacade clientFacade = testCloudSupport.getClientFacade(); clientFacade.setFailOnCreateException(new DockerClientException("Simulated exception.")); DockerInstance instance = client.startNewInstance(image, userData); waitUntil(() -> instance.getStatus() == InstanceStatus.ERROR); waitUntil(() -> image.getInstances().isEmpty()); }
@Test public void startNewInstanceNoPull() { pullOnCreate = false; maxInstanceCount = 2; DefaultDockerCloudClient client = createClient(); DockerImage image = waitForImage(client); DockerInstance instance = client.startNewInstance(image, userData); waitUntil(() -> instance.getStatus() == InstanceStatus.RUNNING); assertThat(clientInterceptor.getInvocations().stream().filter(invocation -> invocation.getMethod().getName() .equals("pull"))).isEmpty(); }
@Test @SuppressWarnings("ConstantConditions") public void instanceErrorHandlingContainerExternallyTerminated() { DefaultDockerCloudClient client = createClient(); DockerImage image = waitForImage(client); DockerInstance instance = client.startNewInstance(image, userData); waitForInstanceStatus(instance, InstanceStatus.RUNNING); TestDockerClientFacade clientFacade = testCloudSupport.getClientFacade(); clientFacade.getAgentHolders().get(0).running(false); waitUntil(() -> instance.getStatus() == InstanceStatus.ERROR); waitUntil(() -> image.getInstances().isEmpty()); waitUntil(() -> clientFacade.getAgentHolders().isEmpty()); }
@Test public void mustSetContainerName() { DefaultDockerCloudClient client = createClient(); DockerImage image = waitForImage(client); testCloudSupport.getClientFacade().agentConfigurator((container -> container.name("test_container_name"))); DockerInstance instance = client.startNewInstance(image, userData); waitForInstanceStatus(instance, InstanceStatus.RUNNING); assertThat(instance.getAgentHolderName()).isEqualTo(Optional.of("test_container_name")); }
@Test public void mustSetInstanceTaskId() { DefaultDockerCloudClient client = createClient(); DockerImage image = waitForImage(client); DockerInstance instance = client.startNewInstance(image, userData); waitForInstanceStatus(instance, InstanceStatus.RUNNING); AgentHolder container = testCloudSupport.getClientFacade().getAgentHolders().get(0); assertThat(instance.getTaskId().get()).isEqualTo(container.getTaskId()); }
@Test public void mustSetInstanceAgentHolderId() { DefaultDockerCloudClient client = createClient(); DockerImage image = waitForImage(client); DockerInstance instance = client.startNewInstance(image, userData); waitForInstanceStatus(instance, InstanceStatus.RUNNING); AgentHolder agentHolder = testCloudSupport.getClientFacade().getAgentHolders().get(0); assertThat(instance.getAgentHolderId().get()).isEqualTo(agentHolder.getId()); }
@Test public void mustBindAgentHolderToInstance() { client = createClient(); DockerImage image = waitForImage(client); DockerInstance instance = client.startNewInstance(image, userData); waitForInstanceStatus(instance, InstanceStatus.RUNNING); TestDockerClientFacade clientFacade = testCloudSupport.getClientFacade(); AgentHolder agentHolder = clientFacade.getAgentHolders().iterator().next(); assertThat(instance.getAgentHolderId()).isEqualTo(Optional.of(agentHolder.getId())); assertThat(instance.getResolvedImageName()).isEqualTo(Optional.of("image:latest")); assertThat(instance.getAgentHolderName()).isEqualTo(Optional.of(agentHolder.getName())); }