diff --git a/jib-gradle-plugin/src/integration-test/java/com/google/cloud/tools/jib/gradle/JibPluginIntegrationTest.java b/jib-gradle-plugin/src/integration-test/java/com/google/cloud/tools/jib/gradle/JibPluginIntegrationTest.java index 3dcc0fe04d..88acd452f8 100644 --- a/jib-gradle-plugin/src/integration-test/java/com/google/cloud/tools/jib/gradle/JibPluginIntegrationTest.java +++ b/jib-gradle-plugin/src/integration-test/java/com/google/cloud/tools/jib/gradle/JibPluginIntegrationTest.java @@ -35,6 +35,9 @@ public class JibPluginIntegrationTest { @ClassRule public static final TestProject simpleTestProject = new TestProject("simple"); + @ClassRule + public static final TestProject defaultTargetTestProject = new TestProject("default-target"); + private static String buildAndRun(TestProject testProject, String imageReference) throws IOException, InterruptedException { BuildResult buildResult = testProject.build("clean", JibPlugin.BUILD_IMAGE_TASK_NAME); @@ -98,6 +101,22 @@ public void testBuild_simple() throws IOException, InterruptedException { buildAndRun(simpleTestProject, "gcr.io/jib-integration-testing/simpleimage:gradle")); } + @Test + public void testBuild_defaultTarget() { + // Test error when 'to' is missing + try { + defaultTargetTestProject.build("clean", JibPlugin.BUILD_IMAGE_TASK_NAME, "-x=classes"); + Assert.fail(); + } catch (UnexpectedBuildFailure ex) { + Assert.assertThat( + ex.getMessage(), + CoreMatchers.containsString( + "Missing target image parameter. Add a 'jib.to.image' configuration parameter to " + + "your build.gradle or set the parameter via commandline (e.g. 'gradle jib " + + "--image ').")); + } + } + @Test public void testDockerDaemon_empty() throws IOException, InterruptedException { Assert.assertEquals( @@ -114,6 +133,14 @@ public void testDockerDaemon_simple() throws IOException, InterruptedException { simpleTestProject, "gcr.io/jib-integration-testing/simpleimage:gradle")); } + @Test + public void testDockerDaemon_defaultTarget() throws IOException, InterruptedException { + Assert.assertEquals( + "Hello, world. An argument.\n", + buildToDockerDaemonAndRun( + defaultTargetTestProject, "default-target-name:default-target-version")); + } + @Test public void testDockerContext() throws IOException, InterruptedException { BuildResult buildResult = diff --git a/jib-gradle-plugin/src/integration-test/resources/projects/default-target/build.gradle b/jib-gradle-plugin/src/integration-test/resources/projects/default-target/build.gradle new file mode 100644 index 0000000000..55abf85a12 --- /dev/null +++ b/jib-gradle-plugin/src/integration-test/resources/projects/default-target/build.gradle @@ -0,0 +1,22 @@ +plugins { + id 'java' + id 'com.google.cloud.tools.jib' +} + +sourceCompatibility = 1.8 +targetCompatibility = 1.8 + +repositories { + mavenCentral() +} + +dependencies { + compile files('libs/dependency-1.0.0.jar') +} + +jib { + args = ['An argument.'] + + // Does not have tests use user-level cache for base image layers. + useOnlyProjectCache = true +} diff --git a/jib-gradle-plugin/src/integration-test/resources/projects/default-target/gradle.properties b/jib-gradle-plugin/src/integration-test/resources/projects/default-target/gradle.properties new file mode 100644 index 0000000000..efba5ed4cf --- /dev/null +++ b/jib-gradle-plugin/src/integration-test/resources/projects/default-target/gradle.properties @@ -0,0 +1 @@ +version = default-target-version \ No newline at end of file diff --git a/jib-gradle-plugin/src/integration-test/resources/projects/default-target/libs/dependency-1.0.0.jar b/jib-gradle-plugin/src/integration-test/resources/projects/default-target/libs/dependency-1.0.0.jar new file mode 100644 index 0000000000..333ceb39b2 Binary files /dev/null and b/jib-gradle-plugin/src/integration-test/resources/projects/default-target/libs/dependency-1.0.0.jar differ diff --git a/jib-gradle-plugin/src/integration-test/resources/projects/default-target/settings.gradle b/jib-gradle-plugin/src/integration-test/resources/projects/default-target/settings.gradle new file mode 100644 index 0000000000..56b2fa2d74 --- /dev/null +++ b/jib-gradle-plugin/src/integration-test/resources/projects/default-target/settings.gradle @@ -0,0 +1 @@ +rootProject.name = 'default-target-name' diff --git a/jib-gradle-plugin/src/integration-test/resources/projects/default-target/src/main/java/com/test/HelloWorld.java b/jib-gradle-plugin/src/integration-test/resources/projects/default-target/src/main/java/com/test/HelloWorld.java new file mode 100644 index 0000000000..5fc6d1cf3a --- /dev/null +++ b/jib-gradle-plugin/src/integration-test/resources/projects/default-target/src/main/java/com/test/HelloWorld.java @@ -0,0 +1,41 @@ +/* + * 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.test; + +import dependency.Greeting; +import java.io.IOException; +import java.net.URISyntaxException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; + +/** Example class that uses a dependency and a resource file. */ +public class HelloWorld { + + public static void main(String[] args) throws IOException, URISyntaxException { + // 'Greeting' comes from the dependency artfiact. + String greeting = Greeting.getGreeting(); + + // Gets the contents of the resource file 'world'. + ClassLoader classLoader = HelloWorld.class.getClassLoader(); + Path worldFile = Paths.get(classLoader.getResource("world").toURI()); + String world = new String(Files.readAllBytes(worldFile), StandardCharsets.UTF_8); + + System.out.println(greeting + ", " + world + ". " + (args.length > 0 ? args[0] : "")); + } +} diff --git a/jib-gradle-plugin/src/integration-test/resources/projects/default-target/src/main/resources/world b/jib-gradle-plugin/src/integration-test/resources/projects/default-target/src/main/resources/world new file mode 100644 index 0000000000..04fea06420 --- /dev/null +++ b/jib-gradle-plugin/src/integration-test/resources/projects/default-target/src/main/resources/world @@ -0,0 +1 @@ +world \ No newline at end of file diff --git a/jib-gradle-plugin/src/main/java/com/google/cloud/tools/jib/gradle/BuildDockerTask.java b/jib-gradle-plugin/src/main/java/com/google/cloud/tools/jib/gradle/BuildDockerTask.java index aa246030af..3384c73f54 100644 --- a/jib-gradle-plugin/src/main/java/com/google/cloud/tools/jib/gradle/BuildDockerTask.java +++ b/jib-gradle-plugin/src/main/java/com/google/cloud/tools/jib/gradle/BuildDockerTask.java @@ -28,6 +28,7 @@ import com.google.cloud.tools.jib.registry.RegistryClient; import com.google.cloud.tools.jib.registry.credentials.RegistryCredentials; import com.google.common.base.Preconditions; +import com.google.common.base.Strings; import javax.annotation.Nullable; import org.gradle.api.DefaultTask; import org.gradle.api.GradleException; @@ -56,7 +57,7 @@ public JibExtension getJib() { return jibExtension; } - /** The target image can be overriden with the {@code --image} command line option. */ + /** The target image can be overridden with the {@code --image} command line option. */ @Option(option = "image", description = "The image reference for the target image") public void setTargetImage(String targetImage) { Preconditions.checkNotNull(jibExtension).getTo().setImage(targetImage); @@ -80,10 +81,17 @@ public void buildDocker() throws InvalidImageReferenceException { GradleProjectProperties gradleProjectProperties = GradleProjectProperties.getForProject(getProject(), gradleBuildLogger); String mainClass = gradleProjectProperties.getMainClass(jibExtension); + + // TODO: Validate that project name and version are valid repository/tag + ImageReference targetImage = + Strings.isNullOrEmpty(jibExtension.getTargetImage()) + ? ImageReference.of(null, getProject().getName(), getProject().getVersion().toString()) + : ImageReference.parse(jibExtension.getTargetImage()); + BuildConfiguration buildConfiguration = BuildConfiguration.builder(gradleBuildLogger) .setBaseImage(ImageReference.parse(jibExtension.getBaseImage())) - .setTargetImage(ImageReference.parse(jibExtension.getTargetImage())) + .setTargetImage(targetImage) .setBaseImageCredentialHelperName(jibExtension.getFrom().getCredHelper()) .setKnownBaseRegistryCredentials(knownBaseRegistryCredentials) .setMainClass(mainClass) diff --git a/jib-gradle-plugin/src/main/java/com/google/cloud/tools/jib/gradle/BuildImageTask.java b/jib-gradle-plugin/src/main/java/com/google/cloud/tools/jib/gradle/BuildImageTask.java index f25ed5bf75..ec78c079ef 100644 --- a/jib-gradle-plugin/src/main/java/com/google/cloud/tools/jib/gradle/BuildImageTask.java +++ b/jib-gradle-plugin/src/main/java/com/google/cloud/tools/jib/gradle/BuildImageTask.java @@ -27,6 +27,7 @@ import com.google.cloud.tools.jib.registry.RegistryClient; import com.google.cloud.tools.jib.registry.credentials.RegistryCredentials; import com.google.common.base.Preconditions; +import com.google.common.base.Strings; import javax.annotation.Nullable; import org.gradle.api.DefaultTask; import org.gradle.api.GradleException; @@ -55,7 +56,7 @@ public JibExtension getJib() { return jibExtension; } - /** The target image can be overriden with the {@code --image} command line option. */ + /** The target image can be overridden with the {@code --image} command line option. */ @Option(option = "image", description = "The image reference for the target image") public void setTargetImage(String targetImage) { Preconditions.checkNotNull(jibExtension).getTo().setImage(targetImage); @@ -66,6 +67,13 @@ public void buildImage() throws InvalidImageReferenceException { // Asserts required @Input parameters are not null. Preconditions.checkNotNull(jibExtension); + if (Strings.isNullOrEmpty(jibExtension.getTargetImage())) { + throw new GradleException( + "Missing target image parameter. Add a 'jib.to.image' configuration parameter to your " + + "build.gradle or set the parameter via commandline (e.g. 'gradle jib --image " + + "')."); + } + RegistryCredentials knownBaseRegistryCredentials = null; RegistryCredentials knownTargetRegistryCredentials = null; Authorization fromAuthorization = jibExtension.getFrom().getImageAuthorization(); diff --git a/jib-gradle-plugin/src/main/java/com/google/cloud/tools/jib/gradle/ImageConfiguration.java b/jib-gradle-plugin/src/main/java/com/google/cloud/tools/jib/gradle/ImageConfiguration.java index 5a93165eea..ceea789b7e 100644 --- a/jib-gradle-plugin/src/main/java/com/google/cloud/tools/jib/gradle/ImageConfiguration.java +++ b/jib-gradle-plugin/src/main/java/com/google/cloud/tools/jib/gradle/ImageConfiguration.java @@ -47,6 +47,7 @@ public ImageConfiguration(ObjectFactory objectFactory) { @Input @Nullable + @Optional public String getImage() { return image; } diff --git a/jib-gradle-plugin/src/main/java/com/google/cloud/tools/jib/gradle/JibExtension.java b/jib-gradle-plugin/src/main/java/com/google/cloud/tools/jib/gradle/JibExtension.java index 8985350c22..991fc0ec32 100644 --- a/jib-gradle-plugin/src/main/java/com/google/cloud/tools/jib/gradle/JibExtension.java +++ b/jib-gradle-plugin/src/main/java/com/google/cloud/tools/jib/gradle/JibExtension.java @@ -145,8 +145,9 @@ String getBaseImage() { } @Internal + @Nullable String getTargetImage() { - return Preconditions.checkNotNull(to.getImage()); + return to.getImage(); } @Nested @@ -155,6 +156,8 @@ ImageConfiguration getFrom() { return from; } + @Nested + @Optional ImageConfiguration getTo() { return to; } diff --git a/jib-maven-plugin/src/main/java/com/google/cloud/tools/jib/maven/BuildDockerMojo.java b/jib-maven-plugin/src/main/java/com/google/cloud/tools/jib/maven/BuildDockerMojo.java index 2b7d53750b..bd694cc2ae 100644 --- a/jib-maven-plugin/src/main/java/com/google/cloud/tools/jib/maven/BuildDockerMojo.java +++ b/jib-maven-plugin/src/main/java/com/google/cloud/tools/jib/maven/BuildDockerMojo.java @@ -27,6 +27,7 @@ import com.google.cloud.tools.jib.registry.credentials.RegistryCredentials; import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Preconditions; +import com.google.common.base.Strings; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugins.annotations.Mojo; import org.apache.maven.plugins.annotations.ResolutionScope; @@ -54,7 +55,12 @@ public void execute() throws MojoExecutionException { // Parses 'from' and 'to' into image reference. ImageReference baseImage = parseBaseImageReference(getBaseImage()); - ImageReference targetImage = parseTargetImageReference(getTargetImage()); + + // TODO: Validate that project name and version are valid repository/tag + ImageReference targetImage = + Strings.isNullOrEmpty(getTargetImage()) + ? ImageReference.of(null, getProject().getName(), getProject().getVersion()) + : parseTargetImageReference(getTargetImage()); // Checks Maven settings for registry credentials. MavenSettingsServerCredentials mavenSettingsServerCredentials = diff --git a/jib-maven-plugin/src/main/java/com/google/cloud/tools/jib/maven/BuildImageMojo.java b/jib-maven-plugin/src/main/java/com/google/cloud/tools/jib/maven/BuildImageMojo.java index 526c4d04c3..b055322434 100644 --- a/jib-maven-plugin/src/main/java/com/google/cloud/tools/jib/maven/BuildImageMojo.java +++ b/jib-maven-plugin/src/main/java/com/google/cloud/tools/jib/maven/BuildImageMojo.java @@ -29,6 +29,7 @@ import com.google.cloud.tools.jib.registry.credentials.RegistryCredentials; import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Preconditions; +import com.google.common.base.Strings; import java.util.Arrays; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.MojoFailureException; @@ -80,8 +81,17 @@ public void execute() throws MojoExecutionException, MojoFailureException { + "'."); } - // Parses 'from' and 'to' into image reference. + // Parses 'from' into image reference. ImageReference baseImage = parseBaseImageReference(getBaseImage()); + + // Parses 'to' into image reference. + if (Strings.isNullOrEmpty(getTargetImage())) { + // TODO: Consolidate with gradle message + throw new MojoFailureException( + "Missing target image parameter. Add a configuration parameter to your " + + "pom.xml or set the parameter via commandline (e.g. 'mvn compile jib:build " + + "-Dimage=')."); + } ImageReference targetImage = parseTargetImageReference(getTargetImage()); // Checks Maven settings for registry credentials. diff --git a/jib-maven-plugin/src/main/java/com/google/cloud/tools/jib/maven/JibPluginConfiguration.java b/jib-maven-plugin/src/main/java/com/google/cloud/tools/jib/maven/JibPluginConfiguration.java index 82ba92972b..09b973a9c5 100644 --- a/jib-maven-plugin/src/main/java/com/google/cloud/tools/jib/maven/JibPluginConfiguration.java +++ b/jib-maven-plugin/src/main/java/com/google/cloud/tools/jib/maven/JibPluginConfiguration.java @@ -48,9 +48,7 @@ public static class FromConfiguration { /** Configuration for {@code to} parameter, where image is required. */ public static class ToConfiguration { - @Nullable - @Parameter(required = true) - private String image; + @Nullable @Parameter private String image; @Nullable @Parameter private String credHelper; @@ -85,11 +83,10 @@ static ImageReference parseTargetImageReference(String to) { @Parameter(defaultValue = "${session}", readonly = true) MavenSession session; - @Nullable @Parameter private FromConfiguration from = new FromConfiguration(); + @Parameter private FromConfiguration from = new FromConfiguration(); - @Nullable - @Parameter(property = "image", required = true) - private ToConfiguration to; + @Parameter(property = "image") + private ToConfiguration to = new ToConfiguration(); @Parameter private List jvmFlags = Collections.emptyList(); @@ -119,8 +116,9 @@ String getBaseImageCredentialHelperName() { return Preconditions.checkNotNull(from).credHelper; } + @Nullable String getTargetImage() { - return Preconditions.checkNotNull(Preconditions.checkNotNull(to).image); + return to.image; } @Nullable diff --git a/jib-maven-plugin/src/test/java/com/google/cloud/tools/jib/maven/BuildDockerMojoIntegrationTest.java b/jib-maven-plugin/src/test/java/com/google/cloud/tools/jib/maven/BuildDockerMojoIntegrationTest.java index 5c63eebe9d..675c31cf9e 100644 --- a/jib-maven-plugin/src/test/java/com/google/cloud/tools/jib/maven/BuildDockerMojoIntegrationTest.java +++ b/jib-maven-plugin/src/test/java/com/google/cloud/tools/jib/maven/BuildDockerMojoIntegrationTest.java @@ -36,6 +36,10 @@ public class BuildDockerMojoIntegrationTest { @ClassRule public static final TestProject emptyTestProject = new TestProject(testPlugin, "empty"); + @ClassRule + public static final TestProject defaultTargetTestProject = + new TestProject(testPlugin, "default-target"); + /** * Builds and runs jib:buildDocker on a project at {@code projectRoot} pushing to {@code * imageReference}. @@ -69,4 +73,14 @@ public void testExecute_empty() throws InterruptedException, IOException, Verifi buildToDockerDaemonAndRun( emptyTestProject.getProjectRoot(), "gcr.io/jib-integration-testing/emptyimage:maven")); } + + @Test + public void testExecute_defaultTarget() + throws VerificationException, IOException, InterruptedException { + Assert.assertEquals( + "Hello, world. An argument.\n", + buildToDockerDaemonAndRun( + defaultTargetTestProject.getProjectRoot(), + "default-target-name:default-target-version")); + } } diff --git a/jib-maven-plugin/src/test/java/com/google/cloud/tools/jib/maven/BuildImageMojoIntegrationTest.java b/jib-maven-plugin/src/test/java/com/google/cloud/tools/jib/maven/BuildImageMojoIntegrationTest.java index 1b24daccc2..e17a3de09b 100644 --- a/jib-maven-plugin/src/test/java/com/google/cloud/tools/jib/maven/BuildImageMojoIntegrationTest.java +++ b/jib-maven-plugin/src/test/java/com/google/cloud/tools/jib/maven/BuildImageMojoIntegrationTest.java @@ -38,6 +38,10 @@ public class BuildImageMojoIntegrationTest { @ClassRule public static final TestProject emptyTestProject = new TestProject(testPlugin, "empty"); + @ClassRule + public static final TestProject defaultTargetTestProject = + new TestProject(testPlugin, "default-target"); + /** * Builds and runs jib:build on a project at {@code projectRoot} pushing to {@code * imageReference}. @@ -102,4 +106,22 @@ public void testExecute_empty() throws InterruptedException, IOException, Verifi buildAndRun( emptyTestProject.getProjectRoot(), "gcr.io/jib-integration-testing/emptyimage:maven")); } + + @Test + public void testExecute_defaultTarget() { + // Test error when 'to' is missing + try { + Verifier verifier = new Verifier(defaultTargetTestProject.getProjectRoot().toString()); + verifier.setAutoclean(false); + verifier.executeGoals(Arrays.asList("clean", "jib:" + BuildImageMojo.GOAL_NAME)); + Assert.fail(); + } catch (VerificationException ex) { + Assert.assertThat( + ex.getMessage(), + CoreMatchers.containsString( + "Missing target image parameter. Add a configuration parameter to your " + + "pom.xml or set the parameter via commandline (e.g. 'mvn compile jib:build " + + "-Dimage=').")); + } + } } diff --git a/jib-maven-plugin/src/test/resources/projects/default-target/libs/dependency-1.0.0.jar b/jib-maven-plugin/src/test/resources/projects/default-target/libs/dependency-1.0.0.jar new file mode 100644 index 0000000000..333ceb39b2 Binary files /dev/null and b/jib-maven-plugin/src/test/resources/projects/default-target/libs/dependency-1.0.0.jar differ diff --git a/jib-maven-plugin/src/test/resources/projects/default-target/pom.xml b/jib-maven-plugin/src/test/resources/projects/default-target/pom.xml new file mode 100644 index 0000000000..37f1d55759 --- /dev/null +++ b/jib-maven-plugin/src/test/resources/projects/default-target/pom.xml @@ -0,0 +1,48 @@ + + 4.0.0 + + com.test + default-target-name + default-target-version + + + 1.8 + UTF-8 + UTF-8 + @@PluginVersion@@ + + + + + com.test + dependency + 1.0.0 + system + ${project.basedir}/libs/dependency-1.0.0.jar + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + 1.8 + 1.8 + + + + + com.google.cloud.tools + jib-maven-plugin + ${jib-maven-plugin.version} + + An argument. + + true + + + + + diff --git a/jib-maven-plugin/src/test/resources/projects/default-target/src/main/java/com/test/HelloWorld.java b/jib-maven-plugin/src/test/resources/projects/default-target/src/main/java/com/test/HelloWorld.java new file mode 100644 index 0000000000..5fc6d1cf3a --- /dev/null +++ b/jib-maven-plugin/src/test/resources/projects/default-target/src/main/java/com/test/HelloWorld.java @@ -0,0 +1,41 @@ +/* + * 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.test; + +import dependency.Greeting; +import java.io.IOException; +import java.net.URISyntaxException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; + +/** Example class that uses a dependency and a resource file. */ +public class HelloWorld { + + public static void main(String[] args) throws IOException, URISyntaxException { + // 'Greeting' comes from the dependency artfiact. + String greeting = Greeting.getGreeting(); + + // Gets the contents of the resource file 'world'. + ClassLoader classLoader = HelloWorld.class.getClassLoader(); + Path worldFile = Paths.get(classLoader.getResource("world").toURI()); + String world = new String(Files.readAllBytes(worldFile), StandardCharsets.UTF_8); + + System.out.println(greeting + ", " + world + ". " + (args.length > 0 ? args[0] : "")); + } +} diff --git a/jib-maven-plugin/src/test/resources/projects/default-target/src/main/resources/world b/jib-maven-plugin/src/test/resources/projects/default-target/src/main/resources/world new file mode 100644 index 0000000000..04fea06420 --- /dev/null +++ b/jib-maven-plugin/src/test/resources/projects/default-target/src/main/resources/world @@ -0,0 +1 @@ +world \ No newline at end of file