Skip to content

Commit

Permalink
Attach build to docker daemon functionality to maven goal (#266)
Browse files Browse the repository at this point in the history
  • Loading branch information
TadCordle authored May 10, 2018
1 parent a0ce78d commit e0fcb5d
Show file tree
Hide file tree
Showing 2 changed files with 182 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,126 @@

package com.google.cloud.tools.jib.maven;

import com.google.cloud.tools.jib.builder.BuildConfiguration;
import com.google.cloud.tools.jib.builder.SourceFilesConfiguration;
import com.google.cloud.tools.jib.frontend.BuildDockerStepsRunner;
import com.google.cloud.tools.jib.frontend.BuildImageStepsExecutionException;
import com.google.cloud.tools.jib.frontend.CacheDirectoryCreationException;
import com.google.cloud.tools.jib.frontend.HelpfulSuggestions;
import com.google.cloud.tools.jib.image.ImageReference;
import com.google.cloud.tools.jib.image.InvalidImageReferenceException;
import com.google.cloud.tools.jib.registry.credentials.RegistryCredentials;
import com.google.common.base.Preconditions;
import java.nio.file.Path;
import java.nio.file.Paths;
import javax.annotation.Nullable;
import org.apache.maven.execution.MavenSession;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.plugins.annotations.ResolutionScope;

/** Builds a container image and exports to the default Docker daemon. */
@Mojo(name = "buildDocker", requiresDependencyResolution = ResolutionScope.RUNTIME_PLUS_SYSTEM)
public class BuildDockerMojo extends JibPluginConfiguration {

/**
* Directory name for the cache. The directory will be relative to the build output directory.
*
* <p>TODO: Move to ProjectProperties.
*/
private static final String CACHE_DIRECTORY_NAME = "jib-cache";

private static final HelpfulSuggestions HELPFUL_SUGGESTIONS =
HelpfulSuggestionsProvider.get("Build image failed");

@Nullable
@Parameter(defaultValue = "${session}", readonly = true)
private MavenSession session;

/** TODO: Consolidate with BuildImageMojo. */
@Override
public void execute() throws MojoExecutionException, MojoFailureException {
getLog().warn("Doing maven jib:buildDocker!");
ProjectProperties projectProperties = new ProjectProperties(getProject(), getLog());
String inferredMainClass = projectProperties.getMainClass(getMainClass());

SourceFilesConfiguration sourceFilesConfiguration =
projectProperties.getSourceFilesConfiguration();

// Parses 'from' and 'to' into image reference.
ImageReference baseImage = getBaseImageReference();
ImageReference targetImage = getTargetImageReference();

// Checks Maven settings for registry credentials.
MavenSettingsServerCredentials mavenSettingsServerCredentials =
new MavenSettingsServerCredentials(Preconditions.checkNotNull(session).getSettings());
RegistryCredentials knownBaseRegistryCredentials =
mavenSettingsServerCredentials.retrieve(baseImage.getRegistry());

BuildConfiguration buildConfiguration =
BuildConfiguration.builder(new MavenBuildLogger(getLog()))
.setBaseImage(baseImage)
.setBaseImageCredentialHelperName(getBaseImageCredentialHelperName())
.setKnownBaseRegistryCredentials(knownBaseRegistryCredentials)
.setTargetImage(targetImage)
.setMainClass(inferredMainClass)
.setJvmFlags(getJvmFlags())
.setEnvironment(getEnvironment())
.build();

// Uses a directory in the Maven build cache as the Jib cache.
Path cacheDirectory = Paths.get(getProject().getBuild().getDirectory(), CACHE_DIRECTORY_NAME);
try {
BuildDockerStepsRunner buildDockerStepsRunner =
BuildDockerStepsRunner.newRunner(
buildConfiguration,
sourceFilesConfiguration,
cacheDirectory,
getUseOnlyProjectCache());

getLog().info("");
getLog().info("Building to docker daemon as " + targetImage);
getLog().info("");

buildDockerStepsRunner.buildDocker(HELPFUL_SUGGESTIONS);

getLog().info("");
getLog().info("Built image to Docker daemon as " + targetImage);
getLog().info("");

} catch (CacheDirectoryCreationException | BuildImageStepsExecutionException ex) {
throw new MojoExecutionException(ex.getMessage(), ex.getCause());
}
}

/** @return the {@link ImageReference} parsed from {@link #from}. */
private ImageReference getBaseImageReference() throws MojoFailureException {
try {
ImageReference baseImage = ImageReference.parse(getBaseImage());

if (baseImage.usesDefaultTag()) {
getLog()
.warn(
"Base image '"
+ baseImage
+ "' does not use a specific image digest - build may not be reproducible");
}

return baseImage;

} catch (InvalidImageReferenceException ex) {
throw new MojoFailureException("Parameter 'from' is invalid", ex);
}
}

/** @return the {@link ImageReference} parsed from {@link #to}. */
private ImageReference getTargetImageReference() throws MojoFailureException {
try {
return ImageReference.parse(getTargetImage());

} catch (InvalidImageReferenceException ex) {
throw new MojoFailureException("Parameter 'to' is invalid", ex);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
/*
* Copyright 2018 Google LLC. All rights reserved.
*
* 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.maven;

import com.google.cloud.tools.jib.Command;
import java.io.IOException;
import java.nio.file.Path;
import org.apache.maven.it.VerificationException;
import org.apache.maven.it.Verifier;
import org.junit.Assert;
import org.junit.ClassRule;
import org.junit.Test;

/** Integration tests for {@link BuildDockerMojo}. */
public class BuildDockerMojoIT {

@ClassRule public static final TestPlugin testPlugin = new TestPlugin();

@ClassRule
public static final TestProject simpleTestProject = new TestProject(testPlugin, "simple");

@ClassRule
public static final TestProject emptyTestProject = new TestProject(testPlugin, "empty");

/**
* Builds and runs jib:buildDocker on a project at {@code projectRoot} pushing to {@code
* imageReference}.
*/
private static String buildToDockerDaemonAndRun(Path projectRoot, String imageReference)
throws VerificationException, IOException, InterruptedException {
Verifier verifier = new Verifier(projectRoot.toString());
verifier.setAutoclean(false);
verifier.executeGoal("package");

// Builds twice, and checks if the second build took less time.
verifier.executeGoal("jib:buildDocker");
verifier.verifyErrorFreeLog();

return new Command("docker", "run", imageReference).run();
}

@Test
public void testExecute_simple() throws VerificationException, IOException, InterruptedException {
Assert.assertEquals(
"Hello, world\n",
buildToDockerDaemonAndRun(
simpleTestProject.getProjectRoot(),
"gcr.io/jib-integration-testing/simpleimage:maven"));
}

@Test
public void testExecute_empty() throws InterruptedException, IOException, VerificationException {
Assert.assertEquals(
"",
buildToDockerDaemonAndRun(
emptyTestProject.getProjectRoot(), "gcr.io/jib-integration-testing/emptyimage:maven"));
}
}

0 comments on commit e0fcb5d

Please sign in to comment.