Skip to content

Commit

Permalink
Adds JibContainerBuilder#containerize. (#1076)
Browse files Browse the repository at this point in the history
  • Loading branch information
coollog committed Oct 8, 2018
1 parent bcfafec commit f474e47
Show file tree
Hide file tree
Showing 15 changed files with 403 additions and 45 deletions.
@@ -0,0 +1,86 @@
/*
* Copyright 2018 Google LLC.
*
* 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 com.google.cloud.tools.jib.api;

import com.google.cloud.tools.jib.Command;
import com.google.cloud.tools.jib.configuration.CacheDirectoryCreationException;
import com.google.cloud.tools.jib.configuration.credentials.Credential;
import com.google.cloud.tools.jib.image.ImageReference;
import com.google.cloud.tools.jib.image.InvalidImageReferenceException;
import com.google.cloud.tools.jib.registry.LocalRegistry;
import java.io.IOException;
import java.util.Optional;
import java.util.concurrent.ExecutionException;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.ClassRule;
import org.junit.Test;

/** Integration tests for {@link Jib}. */
public class JibIntegrationTest {

@ClassRule
public static final LocalRegistry localRegistry = new LocalRegistry(5000, "username", "password");

/**
* Pulls a built image and attempts to run it.
*
* @param imageReference the image reference of the built image
* @return the container output
* @throws IOException if an I/O exception occurs
* @throws InterruptedException if the process was interrupted
*/
private static String pullAndRunBuiltImage(String imageReference)
throws IOException, InterruptedException {
localRegistry.pull(imageReference);
return new Command("docker", "run", "--rm", imageReference).run();
}

@Before
public void setUp() {
System.setProperty("sendCredentialsOverHttp", "true");
}

@After
public void tearDown() {
System.clearProperty("sendCredentialsOverHttp");
}

@Test
public void testBasic_helloWorld()
throws InvalidImageReferenceException, InterruptedException, ExecutionException,
CacheDirectoryCreationException, IOException {
ImageReference targetImageReference =
ImageReference.of("localhost:5000", "jib-core", "basic-helloworld");
JibContainer jibContainer =
Jib.from("busybox")
.setEntrypoint("echo", "Hello World")
.containerize(
Containerizer.to(
RegistryImage.named(targetImageReference)
.addCredentialRetriever(
() -> Optional.of(Credential.basic("username", "password"))))
.setAllowInsecureRegistries(true));

Assert.assertEquals("Hello World\n", pullAndRunBuiltImage(targetImageReference.toString()));
Assert.assertEquals(
"Hello World\n",
pullAndRunBuiltImage(
targetImageReference.withTag(jibContainer.getDigest().toString()).toString()));
}
}
Expand Up @@ -76,6 +76,7 @@ public static Containerizer to(TarImage tarImage) {
private Path baseImageLayersCacheDirectory = DEFAULT_BASE_CACHE_DIRECTORY;
@Nullable private Path applicationLayersCacheDirectory;
@Nullable private EventHandlers eventHandlers;
private boolean allowInsecureRegistries = false;

/** Instantiate with {@link #to}. */
private Containerizer(TargetImage targetImage) {
Expand Down Expand Up @@ -131,6 +132,17 @@ public Containerizer setEventHandlers(EventHandlers eventHandlers) {
return this;
}

/**
* Sets whether or not to allow communication over HTTP/insecure HTTPS.
*
* @param allowInsecureRegistries if {@code true}, insecure connections will be allowed
* @return this
*/
public Containerizer setAllowInsecureRegistries(boolean allowInsecureRegistries) {
this.allowInsecureRegistries = allowInsecureRegistries;
return this;
}

TargetImage getTargetImage() {
return targetImage;
}
Expand Down Expand Up @@ -161,4 +173,8 @@ Path getApplicationLayersCacheDirectory() throws CacheDirectoryCreationException
Optional<EventHandlers> getEventHandlers() {
return Optional.ofNullable(eventHandlers);
}

boolean getAllowInsecureRegistries() {
return allowInsecureRegistries;
}
}
Expand Up @@ -17,7 +17,10 @@
package com.google.cloud.tools.jib.api;
// TODO: Move to com.google.cloud.tools.jib once that package is cleaned up.

import com.google.cloud.tools.jib.builder.BuildSteps;
import com.google.cloud.tools.jib.configuration.BuildConfiguration;
import com.google.cloud.tools.jib.configuration.ImageConfiguration;
import com.google.cloud.tools.jib.docker.DockerClient;
import com.google.cloud.tools.jib.image.ImageReference;
import com.google.cloud.tools.jib.image.InvalidImageReferenceException;
import java.nio.file.Path;
Expand Down Expand Up @@ -70,16 +73,17 @@ public DockerDaemonImage setDockerExecutable(Path dockerExecutable) {
return this;
}

/**
* Converts into an {@link ImageConfiguration}. For internal use only.
*
* @return an {@link ImageConfiguration}
*/
@Override
public ImageConfiguration toImageConfiguration() {
return ImageConfiguration.builder(imageReference).build();
}

@Override
public BuildSteps toBuildSteps(BuildConfiguration buildConfiguration) {
return BuildSteps.forBuildToDockerDaemon(
DockerClient.newClient(dockerExecutable), buildConfiguration);
}

/**
* Gets the path to the {@code docker} CLI.
*
Expand Down
@@ -0,0 +1,38 @@
/*
* Copyright 2018 Google LLC.
*
* 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 com.google.cloud.tools.jib.api;

import com.google.cloud.tools.jib.image.DescriptorDigest;

/** The container built by Jib. */
public class JibContainer {

private final DescriptorDigest imageDigest;

JibContainer(DescriptorDigest imageDigest) {
this.imageDigest = imageDigest;
}

/**
* Gets the digest of the container image built by Jib.
*
* @return the image digest
*/
public DescriptorDigest getDigest() {
return imageDigest;
}
}
Expand Up @@ -18,10 +18,13 @@
// TODO: Move to com.google.cloud.tools.jib once that package is cleaned up.

import com.google.cloud.tools.jib.configuration.BuildConfiguration;
import com.google.cloud.tools.jib.configuration.CacheDirectoryCreationException;
import com.google.cloud.tools.jib.configuration.ContainerConfiguration;
import com.google.cloud.tools.jib.configuration.LayerConfiguration;
import com.google.cloud.tools.jib.configuration.Port;
import com.google.cloud.tools.jib.event.DefaultEventDispatcher;
import com.google.cloud.tools.jib.filesystem.AbsoluteUnixPath;
import com.google.cloud.tools.jib.image.DescriptorDigest;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableList;
import java.io.IOException;
Expand All @@ -31,6 +34,7 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import javax.annotation.Nullable;

/**
Expand Down Expand Up @@ -301,20 +305,63 @@ public JibContainerBuilder addLabel(String key, String value) {
return this;
}

@VisibleForTesting
BuildConfiguration.Builder toBuildConfiguration(TargetImage targetImage) {
BuildConfiguration.Builder buildConfigurationBuilder = BuildConfiguration.builder();
/**
* Builds the container(s).
*
* @param containerizer the {@link Containerizer} that configures how to containerize
* @return the built container(s)
* @throws CacheDirectoryCreationException if a directory to be used for the cache could not be
* created
* @throws ExecutionException if an exception occurred during execution
* @throws InterruptedException if the execution was interrupted
* @throws IOException if an I/O exception occurs
*/
public JibContainer containerize(Containerizer containerizer)
throws InterruptedException, ExecutionException, IOException,
CacheDirectoryCreationException {
BuildConfiguration buildConfiguration =
toBuildConfiguration(BuildConfiguration.builder(), containerizer);
DescriptorDigest imageDigest =
containerizer.getTargetImage().toBuildSteps(buildConfiguration).run();

return new JibContainer(imageDigest);
}

/**
* Builds a {@link BuildConfiguration} using this and a {@link Containerizer}.
*
* @param buildConfigurationBuilder the {@link BuildConfiguration.Builder} to use
* @param containerizer the {@link Containerizer}
* @return the {@link BuildConfiguration}
* @throws CacheDirectoryCreationException if a cache directory could not be created
* @throws IOException if an I/O exception occurs
*/
@VisibleForTesting
BuildConfiguration toBuildConfiguration(
BuildConfiguration.Builder buildConfigurationBuilder, Containerizer containerizer)
throws CacheDirectoryCreationException, IOException {
buildConfigurationBuilder
.setBaseImageConfiguration(baseImage.toImageConfiguration())
.setTargetImageConfiguration(targetImage.toImageConfiguration())
.setTargetImageConfiguration(containerizer.getTargetImage().toImageConfiguration())
.setBaseImageLayersCacheDirectory(containerizer.getBaseImageLayersCacheDirectory())
.setApplicationLayersCacheDirectory(containerizer.getApplicationLayersCacheDirectory())
.setContainerConfiguration(toContainerConfiguration())
.setLayerConfigurations(layerConfigurations);
.setLayerConfigurations(layerConfigurations)
.setAllowInsecureRegistries(containerizer.getAllowInsecureRegistries());

containerizer.getExecutorService().ifPresent(buildConfigurationBuilder::setExecutorService);

containerizer
.getEventHandlers()
.ifPresent(
eventHandlers ->
buildConfigurationBuilder.setEventDispatcher(
new DefaultEventDispatcher(eventHandlers)));

// TODO: Allow users to configure this.
buildConfigurationBuilder.setToolName("jib-core");

return buildConfigurationBuilder;
return buildConfigurationBuilder.build();
}

@VisibleForTesting
Expand Down
Expand Up @@ -17,6 +17,8 @@
package com.google.cloud.tools.jib.api;
// TODO: Move to com.google.cloud.tools.jib once that package is cleaned up.

import com.google.cloud.tools.jib.builder.BuildSteps;
import com.google.cloud.tools.jib.configuration.BuildConfiguration;
import com.google.cloud.tools.jib.configuration.ImageConfiguration;
import com.google.cloud.tools.jib.configuration.credentials.Credential;
import com.google.cloud.tools.jib.configuration.credentials.CredentialRetriever;
Expand Down Expand Up @@ -115,15 +117,15 @@ public RegistryImage addCredentialRetriever(CredentialRetriever credentialRetrie
return this;
}

/**
* Converts into an {@link ImageConfiguration}. For internal use only.
*
* @return an {@link ImageConfiguration}
*/
@Override
public ImageConfiguration toImageConfiguration() {
return ImageConfiguration.builder(imageReference)
.setCredentialRetrievers(credentialRetrievers)
.build();
}

@Override
public BuildSteps toBuildSteps(BuildConfiguration buildConfiguration) {
return BuildSteps.forBuildToDockerRegistry(buildConfiguration);
}
}
Expand Up @@ -17,6 +17,8 @@
package com.google.cloud.tools.jib.api;
// TODO: Move to com.google.cloud.tools.jib once that package is cleaned up.

import com.google.cloud.tools.jib.builder.BuildSteps;
import com.google.cloud.tools.jib.configuration.BuildConfiguration;
import com.google.cloud.tools.jib.configuration.ImageConfiguration;
import com.google.cloud.tools.jib.image.ImageReference;
import com.google.cloud.tools.jib.image.InvalidImageReferenceException;
Expand Down Expand Up @@ -86,16 +88,16 @@ private TarImage(ImageReference imageReference, Path outputFile) {
this.outputFile = outputFile;
}

/**
* Converts into an {@link ImageConfiguration}. For internal use only.
*
* @return an {@link ImageConfiguration}
*/
@Override
public ImageConfiguration toImageConfiguration() {
return ImageConfiguration.builder(imageReference).build();
}

@Override
public BuildSteps toBuildSteps(BuildConfiguration buildConfiguration) {
return BuildSteps.forBuildToTar(outputFile, buildConfiguration);
}

/**
* Gets the output file to save the tarball archive to.
*
Expand Down
Expand Up @@ -17,10 +17,25 @@
package com.google.cloud.tools.jib.api;
// TODO: Move to com.google.cloud.tools.jib once that package is cleaned up.

import com.google.cloud.tools.jib.builder.BuildSteps;
import com.google.cloud.tools.jib.configuration.BuildConfiguration;
import com.google.cloud.tools.jib.configuration.ImageConfiguration;

/** Represents a destination for the Jib-built image. */
interface TargetImage {

/**
* Converts into an {@link ImageConfiguration}. For internal use only.
*
* @return an {@link ImageConfiguration}
*/
ImageConfiguration toImageConfiguration();

/**
* Converts into {@link BuildSteps}. For internal use only.
*
* @param buildConfiguration the {@link BuildConfiguration} to use
* @return {@link BuildSteps}
*/
BuildSteps toBuildSteps(BuildConfiguration buildConfiguration);
}
Expand Up @@ -30,7 +30,6 @@
import java.util.Collections;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import javax.annotation.Nullable;

/**
Expand Down Expand Up @@ -66,7 +65,7 @@ public StepsRunner(BuildConfiguration buildConfiguration) {
ExecutorService executorService =
JibSystemProperties.isSerializedExecutionEnabled()
? MoreExecutors.newDirectExecutorService()
: Executors.newCachedThreadPool();
: buildConfiguration.getExecutorService();
listeningExecutorService = MoreExecutors.listeningDecorator(executorService);
}

Expand Down

0 comments on commit f474e47

Please sign in to comment.