/* * Copyright 2018 ThoughtWorks, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package cd.go.artifact.docker.registry.executors; import cd.go.artifact.docker.registry.ConsoleLogger; import cd.go.artifact.docker.registry.DockerClientFactory; import cd.go.artifact.docker.registry.DockerProgressHandler; import cd.go.artifact.docker.registry.model.ArtifactStoreConfig; import cd.go.artifact.docker.registry.model.FetchArtifactConfig; import com.google.gson.Gson; import com.spotify.docker.client.DefaultDockerClient; import com.spotify.docker.client.exceptions.DockerCertificateException; import com.spotify.docker.client.exceptions.DockerException; import com.thoughtworks.go.plugin.api.request.GoPluginApiRequest; import com.thoughtworks.go.plugin.api.response.GoPluginApiResponse; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; import org.mockito.Mock; import java.util.HashMap; import static cd.go.artifact.docker.registry.executors.FetchArtifactExecutor.FetchArtifactRequest; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.when; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.times; import static org.mockito.MockitoAnnotations.initMocks; public class FetchArtifactExecutorTest { @Rule public ExpectedException thrown = ExpectedException.none(); @Mock private GoPluginApiRequest request; @Mock private DockerClientFactory dockerClientFactory; @Mock private DefaultDockerClient dockerClient; @Mock private DockerProgressHandler dockerProgressHandler; @Mock private ConsoleLogger consoleLogger; @Before public void setUp() throws InterruptedException, DockerException, DockerCertificateException { initMocks(this); when(dockerClientFactory.docker(any())).thenReturn(dockerClient); } @Test public void shouldFetchArtifact() { final ArtifactStoreConfig storeConfig = new ArtifactStoreConfig("localhost:5000", "other", "admin", "admin123"); final HashMap<String, String> artifactMetadata = new HashMap<>(); artifactMetadata.put("image", "localhost:5000/alpine:v1"); artifactMetadata.put("digest", "foo"); FetchArtifactConfig fetchArtifactConfig = new FetchArtifactConfig("PREFIX", null); final FetchArtifactRequest fetchArtifactRequest = new FetchArtifactRequest(storeConfig, artifactMetadata, fetchArtifactConfig); when(request.requestBody()).thenReturn(new Gson().toJson(fetchArtifactRequest)); when(dockerProgressHandler.getDigest()).thenReturn("foo"); final GoPluginApiResponse response = new FetchArtifactExecutor(request, consoleLogger, dockerProgressHandler, dockerClientFactory).execute(); assertThat(response.responseCode()).isEqualTo(200); assertThat(response.responseBody()).isEqualTo("[{\"name\":\"PREFIX_ARTIFACT_IMAGE\",\"value\":\"localhost:5000/alpine:v1\"}]"); } @Test public void shouldNotFetchArtifactWhenSkipImagePullingIsToggled() { final ArtifactStoreConfig storeConfig = new ArtifactStoreConfig("localhost:5000", "other", "admin", "admin123"); final HashMap<String, String> artifactMetadata = new HashMap<>(); artifactMetadata.put("image", "localhost:5000/alpine:v1"); artifactMetadata.put("digest", "foo"); FetchArtifactConfig fetchArtifactConfig = new FetchArtifactConfig("", "true"); final FetchArtifactRequest fetchArtifactRequest = new FetchArtifactRequest(storeConfig, artifactMetadata, fetchArtifactConfig); when(request.requestBody()).thenReturn(new Gson().toJson(fetchArtifactRequest)); when(dockerProgressHandler.getDigest()).thenReturn("foo"); final GoPluginApiResponse response = new FetchArtifactExecutor(request, consoleLogger, dockerProgressHandler, dockerClientFactory).execute(); try { verify(dockerClient, times(0)).pull("localhost:5000/alpine:v1", dockerProgressHandler); } catch (DockerException | InterruptedException e) { /* Should never happen */ } assertThat(response.responseCode()).isEqualTo(200); } @Test public void shouldSetEnvironmentVariablesWithImageInformationInResponseRegardlessOfWhetherThePrefixIsProvided() { final ArtifactStoreConfig storeConfig = new ArtifactStoreConfig("localhost:5000", "other", "admin", "admin123"); final HashMap<String, String> artifactMetadata = new HashMap<>(); artifactMetadata.put("image", "localhost:5000/alpine:v1"); artifactMetadata.put("digest", "foo"); final FetchArtifactRequest fetchArtifactRequest = new FetchArtifactRequest(storeConfig, artifactMetadata, new FetchArtifactConfig()); when(request.requestBody()).thenReturn(new Gson().toJson(fetchArtifactRequest)); when(dockerProgressHandler.getDigest()).thenReturn("foo"); final GoPluginApiResponse response = new FetchArtifactExecutor(request, consoleLogger, dockerProgressHandler, dockerClientFactory).execute(); assertThat(response.responseCode()).isEqualTo(200); assertThat(response.responseBody()).isEqualTo("[{\"name\":\"ARTIFACT_IMAGE\",\"value\":\"localhost:5000/alpine:v1\"}]"); } @Test public void shouldErrorOutWhenDigestIsNotSame() { final ArtifactStoreConfig storeConfig = new ArtifactStoreConfig("localhost:5000", "other", "admin", "admin123"); final HashMap<String, String> artifactMetadata = new HashMap<>(); artifactMetadata.put("image", "localhost:5000/alpine:v1"); artifactMetadata.put("digest", "foo"); final FetchArtifactRequest fetchArtifactRequest = new FetchArtifactRequest(storeConfig, artifactMetadata, new FetchArtifactConfig()); when(request.requestBody()).thenReturn(new Gson().toJson(fetchArtifactRequest)); when(dockerProgressHandler.getDigest()).thenReturn("bar"); final GoPluginApiResponse response = new FetchArtifactExecutor(request, consoleLogger, dockerProgressHandler, dockerClientFactory).execute(); assertThat(response.responseCode()).isEqualTo(500); assertThat(response.responseBody()).isEqualTo("Failed pull docker image: java.lang.RuntimeException: Expecting pulled image digest to be [foo] but it is [bar]."); } @Test public void shouldErrorOutWhenFailedToPull() throws DockerException, InterruptedException { final ArtifactStoreConfig storeConfig = new ArtifactStoreConfig("localhost:5000", "other", "admin", "admin123"); final HashMap<String, String> artifactMetadata = new HashMap<>(); artifactMetadata.put("image", "localhost:5000/alpine:v1"); artifactMetadata.put("digest", "foo"); final FetchArtifactRequest fetchArtifactRequest = new FetchArtifactRequest(storeConfig, artifactMetadata, new FetchArtifactConfig()); when(request.requestBody()).thenReturn(new Gson().toJson(fetchArtifactRequest)); doThrow(new RuntimeException("Some error")).when(dockerClient).pull("localhost:5000/alpine:v1", dockerProgressHandler); final GoPluginApiResponse response = new FetchArtifactExecutor(request, consoleLogger, dockerProgressHandler, dockerClientFactory).execute(); assertThat(response.responseCode()).isEqualTo(500); assertThat(response.responseBody()).isEqualTo("Failed pull docker image: java.lang.RuntimeException: Some error"); } }