package com.github.dockerjava.netty.exec;
import static com.github.dockerjava.utils.TestUtils.getVersion;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.isEmptyString;
import static org.hamcrest.Matchers.not;
import static org.hamcrest.Matchers.nullValue;
import static org.hamcrest.Matchers.containsInAnyOrder;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.UUID;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.filefilter.TrueFileFilter;
import org.testng.ITestResult;
import org.testng.SkipException;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.AfterTest;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test;
import com.github.dockerjava.api.command.BuildImageCmd;
import com.github.dockerjava.api.command.CreateContainerResponse;
import com.github.dockerjava.api.command.InspectContainerResponse;
import com.github.dockerjava.api.command.InspectImageResponse;
import com.github.dockerjava.api.exception.DockerClientException;
import com.github.dockerjava.api.model.AuthConfig;
import com.github.dockerjava.api.model.AuthConfigurations;
import com.github.dockerjava.api.model.ExposedPort;
import com.github.dockerjava.api.model.PortBinding;
import com.github.dockerjava.api.model.Ports;
import com.github.dockerjava.api.model.Ports.Binding;
import com.github.dockerjava.core.RemoteApiVersion;
import com.github.dockerjava.core.command.BuildImageResultCallback;
import com.github.dockerjava.core.command.PushImageResultCallback;
import com.github.dockerjava.core.command.WaitContainerResultCallback;
import com.github.dockerjava.core.util.CompressArchiveUtil;
import com.github.dockerjava.netty.AbstractNettyDockerClientTest;
@Test(groups = "integration")
public class BuildImageCmdExecTest extends AbstractNettyDockerClientTest {
@BeforeTest
public void beforeTest() throws Exception {
super.beforeTest();
}
@AfterTest
public void afterTest() {
super.afterTest();
}
@BeforeMethod
public void beforeMethod(Method method) {
super.beforeMethod(method);
}
@AfterMethod
public void afterMethod(ITestResult result) {
super.afterMethod(result);
}
@Test
public void author() throws Exception {
String imageId = buildImage(fileFromBuildTestResource("AUTHOR"));
InspectImageResponse inspectImageResponse = dockerClient.inspectImageCmd(imageId).exec();
assertThat(inspectImageResponse, not(nullValue()));
LOG.info("Image Inspect: {}", inspectImageResponse.toString());
assertThat(inspectImageResponse.getAuthor(), equalTo("Guillaume J. Charmes \"guillaume@dotcloud.com\""));
}
@Test
public void buildImageFromTar() throws Exception {
File baseDir = fileFromBuildTestResource("ADD/file");
Collection<File> files = FileUtils.listFiles(baseDir, TrueFileFilter.INSTANCE, TrueFileFilter.INSTANCE);
File tarFile = CompressArchiveUtil.archiveTARFiles(baseDir, files, UUID.randomUUID().toString());
String response = dockerfileBuild(new FileInputStream(tarFile));
assertThat(response, containsString("Successfully executed testrun.sh"));
}
@Test
public void buildImageFromTarWithDockerfileNotInBaseDirectory() throws Exception {
File baseDir = fileFromBuildTestResource("dockerfileNotInBaseDirectory");
Collection<File> files = FileUtils.listFiles(baseDir, TrueFileFilter.INSTANCE, TrueFileFilter.INSTANCE);
File tarFile = CompressArchiveUtil.archiveTARFiles(baseDir, files, UUID.randomUUID().toString());
String response = dockerfileBuild(new FileInputStream(tarFile), "dockerfileFolder/Dockerfile");
assertThat(response, containsString("Successfully executed testrun.sh"));
}
@Test
public void onBuild() throws Exception {
File baseDir = fileFromBuildTestResource("ONBUILD/parent");
dockerClient.buildImageCmd(baseDir).withNoCache(true).withTag("docker-java-onbuild")
.exec(new BuildImageResultCallback()).awaitImageId();
baseDir = fileFromBuildTestResource("ONBUILD/child");
String response = dockerfileBuild(baseDir);
assertThat(response, containsString("Successfully executed testrun.sh"));
}
@Test
public void addUrl() throws Exception {
File baseDir = fileFromBuildTestResource("ADD/url");
String response = dockerfileBuild(baseDir);
assertThat(response, containsString("Example Domain"));
}
@Test
public void addFileInSubfolder() throws Exception {
File baseDir = fileFromBuildTestResource("ADD/fileInSubfolder");
String response = dockerfileBuild(baseDir);
assertThat(response, containsString("Successfully executed testrun.sh"));
}
@Test
public void addFilesViaWildcard() throws Exception {
File baseDir = fileFromBuildTestResource("ADD/filesViaWildcard");
String response = dockerfileBuild(baseDir);
assertThat(response, containsString("Successfully executed testinclude1.sh"));
assertThat(response, not(containsString("Successfully executed testinclude2.sh")));
}
@Test
public void addFolder() throws Exception {
File baseDir = fileFromBuildTestResource("ADD/folder");
String response = dockerfileBuild(baseDir);
assertThat(response, containsString("Successfully executed testAddFolder.sh"));
}
private String dockerfileBuild(InputStream tarInputStream, String dockerFilePath) throws Exception {
return execBuild(dockerClient.buildImageCmd().withTarInputStream(tarInputStream).withDockerfilePath(dockerFilePath));
}
private String dockerfileBuild(InputStream tarInputStream) throws Exception {
return execBuild(dockerClient.buildImageCmd().withTarInputStream(tarInputStream));
}
private String dockerfileBuild(File baseDir) throws Exception {
return execBuild(dockerClient.buildImageCmd(baseDir));
}
private String execBuild(BuildImageCmd buildImageCmd) throws Exception {
String imageId = buildImageCmd.withNoCache(true).exec(new BuildImageResultCallback()).awaitImageId();
// Create container based on image
CreateContainerResponse container = dockerClient.createContainerCmd(imageId).exec();
LOG.info("Created container: {}", container.toString());
assertThat(container.getId(), not(isEmptyString()));
dockerClient.startContainerCmd(container.getId()).exec();
dockerClient.waitContainerCmd(container.getId()).exec(new WaitContainerResultCallback()).awaitStatusCode();
return containerLog(container.getId());
}
@Test(expectedExceptions = {DockerClientException.class})
public void dockerignoreDockerfileIgnored() throws Exception {
File baseDir = fileFromBuildTestResource("dockerignore/DockerfileIgnored");
dockerClient.buildImageCmd(baseDir).withNoCache(true).exec(new BuildImageResultCallback()).awaitImageId();
}
@Test
public void dockerignoreDockerfileNotIgnored() throws Exception {
File baseDir = fileFromBuildTestResource("dockerignore/DockerfileNotIgnored");
dockerClient.buildImageCmd(baseDir).withNoCache(true).exec(new BuildImageResultCallback()).awaitImageId();
}
@Test(expectedExceptions = {DockerClientException.class})
public void dockerignoreInvalidDockerIgnorePattern() throws Exception {
File baseDir = fileFromBuildTestResource("dockerignore/InvalidDockerignorePattern");
dockerClient.buildImageCmd(baseDir).withNoCache(true).exec(new BuildImageResultCallback()).awaitImageId();
}
@Test()
public void dockerignoreValidDockerIgnorePattern() throws Exception {
File baseDir = fileFromBuildTestResource("dockerignore/ValidDockerignorePattern");
String response = dockerfileBuild(baseDir);
assertThat(response, containsString("/tmp/a/a /tmp/a/c /tmp/a/d"));
}
@Test
public void env() throws Exception {
File baseDir = fileFromBuildTestResource("ENV");
String response = dockerfileBuild(baseDir);
assertThat(response, containsString("testENVSubstitution successfully completed"));
}
@Test
public void fromPrivateRegistry() throws Exception {
File baseDir = new File(Thread.currentThread().getContextClassLoader().getResource("privateRegistry").getFile());
String imageId = buildImage(baseDir);
InspectImageResponse inspectImageResponse = dockerClient.inspectImageCmd(imageId).exec();
assertThat(inspectImageResponse, not(nullValue()));
LOG.info("Image Inspect: {}", inspectImageResponse.toString());
dockerClient.tagImageCmd(imageId, "testregistry", "2").withForce().exec();
// see https://github.com/docker/distribution/blob/master/docs/deploying.md#native-basic-auth
CreateContainerResponse testregistry = dockerClient
.createContainerCmd("testregistry:2")
.withName("registry")
.withPortBindings(new PortBinding(Binding.bindPort(5000), ExposedPort.tcp(5000)))
.withEnv("REGISTRY_AUTH=htpasswd", "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm",
"REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd", "REGISTRY_LOG_LEVEL=debug",
"REGISTRY_HTTP_TLS_CERTIFICATE=/certs/domain.crt", "REGISTRY_HTTP_TLS_KEY=/certs/domain.key")
.exec();
dockerClient.startContainerCmd(testregistry.getId()).exec();
// wait for registry to boot
Thread.sleep(3000);
// credentials as configured in /auth/htpasswd
AuthConfig authConfig = new AuthConfig()
.withUsername("testuser")
.withPassword("testpassword")
.withEmail("foo@bar.de")
.withRegistryAddress("localhost:5000");
dockerClient.authCmd().withAuthConfig(authConfig).exec();
dockerClient.tagImageCmd("busybox:latest", "localhost:5000/testuser/busybox", "latest").withForce().exec();
dockerClient.pushImageCmd("localhost:5000/testuser/busybox").withTag("latest").withAuthConfig(authConfig)
.exec(new PushImageResultCallback()).awaitSuccess();
dockerClient.removeImageCmd("localhost:5000/testuser/busybox").withForce(true).exec();
baseDir = fileFromBuildTestResource("FROM/privateRegistry");
AuthConfigurations authConfigurations = new AuthConfigurations();
authConfigurations.addConfig(authConfig);
imageId = dockerClient.buildImageCmd(baseDir).withNoCache(true).withBuildAuthConfigs(authConfigurations)
.exec(new BuildImageResultCallback()).awaitImageId();
inspectImageResponse = dockerClient.inspectImageCmd(imageId).exec();
assertThat(inspectImageResponse, not(nullValue()));
LOG.info("Image Inspect: {}", inspectImageResponse.toString());
}
@Test
public void buildArgs() throws Exception {
File baseDir = fileFromBuildTestResource("buildArgs");
String imageId = dockerClient.buildImageCmd(baseDir).withNoCache(true).withBuildArg("testArg", "abc")
.exec(new BuildImageResultCallback())
.awaitImageId();
InspectImageResponse inspectImageResponse = dockerClient.inspectImageCmd(imageId).exec();
assertThat(inspectImageResponse, not(nullValue()));
LOG.info("Image Inspect: {}", inspectImageResponse.toString());
assertThat(inspectImageResponse.getConfig().getLabels().get("test"), equalTo("abc"));
}
@Test
public void labels() throws Exception {
if (!getVersion(dockerClient).isGreaterOrEqual(RemoteApiVersion.VERSION_1_23)) {
throw new SkipException("API version should be >= 1.23");
}
File baseDir = fileFromBuildTestResource("labels");
String imageId = dockerClient.buildImageCmd(baseDir).withNoCache(true)
.withLabels(Collections.singletonMap("test", "abc"))
.exec(new BuildImageResultCallback())
.awaitImageId();
InspectImageResponse inspectImageResponse = dockerClient.inspectImageCmd(imageId).exec();
assertThat(inspectImageResponse, not(nullValue()));
LOG.info("Image Inspect: {}", inspectImageResponse.toString());
assertThat(inspectImageResponse.getConfig().getLabels().get("test"), equalTo("abc"));
}
@Test
public void multipleTags() throws Exception {
if (!getVersion(dockerClient).isGreaterOrEqual(RemoteApiVersion.VERSION_1_21)) {
throw new SkipException("API version should be >= 1.21");
}
File baseDir = fileFromBuildTestResource("labels");
String imageId = dockerClient.buildImageCmd(baseDir).withNoCache(true)
.withTag("fallback-when-withTags-not-called")
.withTags(new HashSet<>(Arrays.asList("docker-java-test:tag1", "docker-java-test:tag2")))
.exec(new BuildImageResultCallback())
.awaitImageId();
InspectImageResponse inspectImageResponse = dockerClient.inspectImageCmd(imageId).exec();
assertThat(inspectImageResponse, not(nullValue()));
LOG.info("Image Inspect: {}", inspectImageResponse.toString());
assertThat(inspectImageResponse.getRepoTags().size(), equalTo(2));
assertThat(inspectImageResponse.getRepoTags(), containsInAnyOrder("docker-java-test:tag1", "docker-java-test:tag2"));
}
public void dockerfileNotInBaseDirectory() throws Exception {
File baseDirectory = fileFromBuildTestResource("dockerfileNotInBaseDirectory");
File dockerfile = fileFromBuildTestResource("dockerfileNotInBaseDirectory/dockerfileFolder/Dockerfile");
BuildImageCmd command = dockerClient.buildImageCmd()
.withBaseDirectory(baseDirectory)
.withDockerfile(dockerfile);
String response = execBuild(command);
assertThat(response, containsString("Successfully executed testrun.sh"));
}
private File fileFromBuildTestResource(String resource) {
return new File(Thread.currentThread().getContextClassLoader()
.getResource("buildTests/" + resource).getFile());
}
}