Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update gradle extraDirectory config parameter to include path and permissions field #1178

Merged
merged 7 commits into from
Oct 23, 2018
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion jib-gradle-plugin/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,10 @@ All notable changes to this project will be documented in this file.
- `jib.to.credHelper` and `jib.from.credHelper` can be used to specify a credential helper suffix or a full path to a credential helper executable ([#925](https://github.com/GoogleContainerTools/jib/issues/925))
- `container.user` configuration parameter to configure the user and group to run the container as ([#1029](https://github.com/GoogleContainerTools/jib/issues/1029))
- Preliminary support for building images for WAR projects ([#431](https://github.com/GoogleContainerTools/jib/issues/431))

- `jib.extraDirectory` closure with a `path` and `permissions` field ([#794](https://github.com/GoogleContainerTools/jib/issues/794))
- `jib.extraDirectory.path` configures the extra layer directory (still also configurable via `jib.extraDirectory = file(...)`)
- `jib.extraDirectory.permissions` is a map from absolute path on container to the file's permission bits (represented as an octal string)

### Changed

- Removed deprecated `jib.jvmFlags`, `jib.mainClass`, `jib.args`, and `jib.format` in favor of the equivalents under `jib.container` ([#461](https://github.com/GoogleContainerTools/jib/issues/461))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ public void testBuild_simple() throws IOException, InterruptedException {

Instant beforeBuild = Instant.now();
Assert.assertEquals(
"Hello, world. An argument.\nfoo\ncat\n",
"Hello, world. An argument.\nrw-r--r--\nrw-r--r--\nfoo\ncat\n",
JibRunHelper.buildAndRun(simpleTestProject, targetImage));
assertDockerInspect(targetImage);
assertSimpleCreationTimeIsAfter(beforeBuild, targetImage);
Expand All @@ -153,7 +153,7 @@ public void testBuild_complex() throws IOException, InterruptedException {
String targetImage = "localhost:6000/compleximage:gradle" + System.nanoTime();
Instant beforeBuild = Instant.now();
Assert.assertEquals(
"Hello, world. An argument.\nfoo\ncat\n-Xms512m\n-Xdebug\nenvvalue1\nenvvalue2\n",
"Hello, world. An argument.\nrwxr-xr-x\nrwxrwxrwx\nfoo\ncat\n-Xms512m\n-Xdebug\nenvvalue1\nenvvalue2\n",
buildAndRunComplex(targetImage, "testuser2", "testpassword2", localRegistry2));
assertSimpleCreationTimeIsAfter(beforeBuild, targetImage);
}
Expand All @@ -163,7 +163,7 @@ public void testBuild_complex_sameFromAndToRegistry() throws IOException, Interr
String targetImage = "localhost:5000/compleximage:gradle" + System.nanoTime();
Instant beforeBuild = Instant.now();
Assert.assertEquals(
"Hello, world. An argument.\nfoo\ncat\n-Xms512m\n-Xdebug\nenvvalue1\nenvvalue2\n",
"Hello, world. An argument.\nrwxr-xr-x\nrwxrwxrwx\nfoo\ncat\n-Xms512m\n-Xdebug\nenvvalue1\nenvvalue2\n",
buildAndRunComplex(targetImage, "testuser", "testpassword", localRegistry1));
assertSimpleCreationTimeIsAfter(beforeBuild, targetImage);
}
Expand All @@ -173,7 +173,7 @@ public void testDockerDaemon_simple() throws IOException, InterruptedException {
String targetImage = "simpleimage:gradle" + System.nanoTime();
Instant beforeBuild = Instant.now();
Assert.assertEquals(
"Hello, world. An argument.\nfoo\ncat\n",
"Hello, world. An argument.\nrw-r--r--\nrw-r--r--\nfoo\ncat\n",
JibRunHelper.buildToDockerDaemonAndRun(simpleTestProject, targetImage));
assertSimpleCreationTimeIsAfter(beforeBuild, targetImage);
assertDockerInspect(targetImage);
Expand Down Expand Up @@ -201,7 +201,7 @@ public void testDockerContext() throws IOException, InterruptedException {

assertDockerInspect(imageName);
Assert.assertEquals(
"Hello, world. An argument.\nfoo\ncat\n",
"Hello, world. An argument.\nrw-r--r--\nrw-r--r--\nfoo\ncat\n",
new Command("docker", "run", "--rm", imageName).run());

// Checks that generating the Docker context again is skipped.
Expand Down Expand Up @@ -249,7 +249,7 @@ public void testBuildTar_simple() throws IOException, InterruptedException {

new Command("docker", "load", "--input", outputPath).run();
Assert.assertEquals(
"Hello, world. An argument.\nfoo\ncat\n",
"Hello, world. An argument.\nrw-r--r--\nrw-r--r--\nfoo\ncat\n",
new Command("docker", "run", "--rm", targetImage).run());
assertDockerInspect(targetImage);
assertSimpleCreationTimeIsAfter(beforeBuild, targetImage);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,11 @@ jib {
ports = ['1000/tcp', '2000-2003/udp']
labels = [key1:'value1', key2:'value2']
}
extraDirectory {
path = file('src/main/custom-extra-dir')
permissions = ['/foo':'755', '/bar/cat':'777']
}
allowInsecureRegistries = true
extraDirectory = file('src/main/custom-extra-dir')

// Does not have tests use user-level cache for base image layers.
useOnlyProjectCache = true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.attribute.PosixFilePermissions;

/** Example class that uses a dependency and a resource file. */
public class HelloWorld {
Expand All @@ -41,6 +42,10 @@ public static void main(String[] args) throws IOException, URISyntaxException {

// Prints the contents of the extra files.
if (Files.exists(Paths.get("/foo"))) {
System.out.println(
PosixFilePermissions.toString(Files.getPosixFilePermissions(Paths.get("/foo"))));
System.out.println(
PosixFilePermissions.toString(Files.getPosixFilePermissions(Paths.get("/bar/cat"))));
System.out.println(new String(Files.readAllBytes(Paths.get("/foo")), StandardCharsets.UTF_8));
System.out.println(
new String(Files.readAllBytes(Paths.get("/bar/cat")), StandardCharsets.UTF_8));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,11 @@ public void buildDocker()
AbsoluteUnixPath appRoot = PluginConfigurationProcessor.getAppRootChecked(jibExtension);
GradleProjectProperties gradleProjectProperties =
GradleProjectProperties.getForProject(
getProject(), getLogger(), jibExtension.getExtraDirectoryPath(), appRoot);
getProject(),
getLogger(),
jibExtension.getExtraDirectory().getPath(),
jibExtension.getExtraDirectory().getPermissions(),
appRoot);

GradleHelpfulSuggestionsBuilder gradleHelpfulSuggestionsBuilder =
new GradleHelpfulSuggestionsBuilder(HELPFUL_SUGGESTIONS_PREFIX, jibExtension);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,11 @@ public void buildImage()
AbsoluteUnixPath appRoot = PluginConfigurationProcessor.getAppRootChecked(jibExtension);
GradleProjectProperties gradleProjectProperties =
GradleProjectProperties.getForProject(
getProject(), getLogger(), jibExtension.getExtraDirectoryPath(), appRoot);
getProject(),
getLogger(),
jibExtension.getExtraDirectory().getPath(),
jibExtension.getExtraDirectory().getPermissions(),
appRoot);

if (Strings.isNullOrEmpty(jibExtension.getTo().getImage())) {
throw new GradleException(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,8 @@ public void setTargetImage(String targetImage) {
@InputFiles
public FileCollection getInputFiles() {
return GradleProjectProperties.getInputFiles(
Preconditions.checkNotNull(jibExtension).getExtraDirectoryPath().toFile(), getProject());
Preconditions.checkNotNull(jibExtension).getExtraDirectory().getPath().toFile(),
getProject());
}

/**
Expand Down Expand Up @@ -109,7 +110,11 @@ public void buildTar()
AbsoluteUnixPath appRoot = PluginConfigurationProcessor.getAppRootChecked(jibExtension);
GradleProjectProperties gradleProjectProperties =
GradleProjectProperties.getForProject(
getProject(), getLogger(), jibExtension.getExtraDirectoryPath(), appRoot);
getProject(),
getLogger(),
jibExtension.getExtraDirectory().getPath(),
jibExtension.getExtraDirectory().getPermissions(),
appRoot);

GradleHelpfulSuggestionsBuilder gradleHelpfulSuggestionsBuilder =
new GradleHelpfulSuggestionsBuilder(HELPFUL_SUGGESTIONS_PREFIX, jibExtension);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,8 @@ public JibExtension getJib() {
@InputFiles
public FileCollection getInputFiles() {
return GradleProjectProperties.getInputFiles(
Preconditions.checkNotNull(jibExtension).getExtraDirectoryPath().toFile(), getProject());
Preconditions.checkNotNull(jibExtension).getExtraDirectory().getPath().toFile(),
getProject());
}

/**
Expand Down Expand Up @@ -110,7 +111,11 @@ public void generateDockerContext() {
AbsoluteUnixPath appRoot = PluginConfigurationProcessor.getAppRootChecked(jibExtension);
GradleProjectProperties gradleProjectProperties =
GradleProjectProperties.getForProject(
getProject(), getLogger(), jibExtension.getExtraDirectoryPath(), appRoot);
getProject(),
getLogger(),
jibExtension.getExtraDirectory().getPath(),
jibExtension.getExtraDirectory().getPermissions(),
appRoot);
String targetDir = getTargetDir();

List<String> entrypoint =
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
/*
* 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.gradle;

import com.google.cloud.tools.jib.plugins.common.ConfigurationPropertyValidator;
import com.google.cloud.tools.jib.plugins.common.PropertyNames;
import java.io.File;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Collections;
import java.util.Map;
import javax.inject.Inject;
import org.gradle.api.tasks.Input;
import org.gradle.api.tasks.Internal;

/** Object in {@link JibExtension} that configures the extra directory. */
public class ExtraDirectoryParameters {

private static Path resolveDefaultExtraDirectory(Path projectDirectory) {
TadCordle marked this conversation as resolved.
Show resolved Hide resolved
return projectDirectory.resolve("src").resolve("main").resolve("jib");
}

private Path path;
private Map<String, String> permissions = Collections.emptyMap();

@Inject
public ExtraDirectoryParameters(Path projectDirectory) {
path = resolveDefaultExtraDirectory(projectDirectory);
}

@Input
public String getPathString() {
// Gradle warns about @Input annotations on File objects, so we have to expose a getter for a
// String to make them go away.
if (System.getProperty(PropertyNames.EXTRA_DIRECTORY_PATH) != null) {
return System.getProperty(PropertyNames.EXTRA_DIRECTORY_PATH);
}
return path.toString();
}

@Internal
public Path getPath() {
// Gradle warns about @Input annotations on File objects, so we have to expose a getter for a
// String to make them go away.
if (System.getProperty(PropertyNames.EXTRA_DIRECTORY_PATH) != null) {
return Paths.get(System.getProperty(PropertyNames.EXTRA_DIRECTORY_PATH));
}
return path;
}

public void setPath(File path) {
this.path = path.toPath();
}

/**
* Gets the permissions for files in the extra layer on the container. Maps from absolute path on
* the container to a 3-digit octal string representation of the file permission bits (e.g. {@code
* "/path/on/container" -> "755"}).
*
* @return the permissions map from path on container to file permissions
*/
@Input
public Map<String, String> getPermissions() {
TadCordle marked this conversation as resolved.
Show resolved Hide resolved
if (System.getProperty(PropertyNames.EXTRA_DIRECTORY_PERMISSIONS) != null) {
return ConfigurationPropertyValidator.parseMapProperty(
System.getProperty(PropertyNames.EXTRA_DIRECTORY_PERMISSIONS));
}
return permissions;
}

public void setPermissions(Map<String, String> permissions) {
this.permissions = permissions;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -149,8 +149,8 @@ public void listFiles() {
printProjectFiles(project);

// Print extra layer
if (Files.exists(jibExtension.getExtraDirectoryPath())) {
System.out.println(jibExtension.getExtraDirectoryPath());
if (Files.exists(jibExtension.getExtraDirectory().getPath())) {
System.out.println(jibExtension.getExtraDirectory().getPath());
}

// Find project dependencies
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

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

import com.google.cloud.tools.jib.configuration.FilePermissions;
import com.google.cloud.tools.jib.filesystem.AbsoluteUnixPath;
import com.google.cloud.tools.jib.frontend.JavaEntrypointConstructor;
import com.google.cloud.tools.jib.frontend.JavaLayerConfigurations;
Expand All @@ -26,6 +27,7 @@
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Map;
import org.gradle.api.Project;
import org.gradle.api.file.FileCollection;
import org.gradle.api.logging.Logger;
Expand All @@ -49,13 +51,17 @@ class GradleLayerConfigurations {
* @throws IOException if an I/O exception occurred during resolution
*/
static JavaLayerConfigurations getForProject(
Project project, Logger logger, Path extraDirectory, AbsoluteUnixPath appRoot)
Project project,
Logger logger,
Path extraDirectory,
Map<AbsoluteUnixPath, FilePermissions> permissions,
TadCordle marked this conversation as resolved.
Show resolved Hide resolved
AbsoluteUnixPath appRoot)
throws IOException {
if (GradleProjectProperties.getWarTask(project) != null) {
logger.info("WAR project identified, creating WAR image: " + project.getDisplayName());
return getForWarProject(project, logger, extraDirectory, appRoot);
return getForWarProject(project, extraDirectory, permissions, appRoot);
} else {
return getForNonWarProject(project, logger, extraDirectory, appRoot);
return getForNonWarProject(project, logger, extraDirectory, permissions, appRoot);
}
}

Expand All @@ -70,7 +76,11 @@ static JavaLayerConfigurations getForProject(
* @throws IOException if an I/O exception occurred during resolution
*/
private static JavaLayerConfigurations getForNonWarProject(
Project project, Logger logger, Path extraDirectory, AbsoluteUnixPath appRoot)
Project project,
Logger logger,
Path extraDirectory,
Map<AbsoluteUnixPath, FilePermissions> permissions,
TadCordle marked this conversation as resolved.
Show resolved Hide resolved
AbsoluteUnixPath appRoot)
throws IOException {
AbsoluteUnixPath dependenciesExtractionPath =
appRoot.resolve(JavaEntrypointConstructor.DEFAULT_RELATIVE_DEPENDENCIES_PATH_ON_IMAGE);
Expand Down Expand Up @@ -127,7 +137,11 @@ private static JavaLayerConfigurations getForNonWarProject(
// Adds all the extra files.
if (Files.exists(extraDirectory)) {
layerBuilder.addDirectoryContents(
LayerType.EXTRA_FILES, extraDirectory, path -> true, AbsoluteUnixPath.get("/"));
LayerType.EXTRA_FILES,
extraDirectory,
path -> true,
AbsoluteUnixPath.get("/"),
permissions);
}

return layerBuilder.build();
Expand All @@ -137,17 +151,21 @@ private static JavaLayerConfigurations getForNonWarProject(
* Resolves the {@link JavaLayerConfigurations} for a WAR Gradle {@link Project}.
*
* @param project the Gradle {@link Project}
* @param logger the build logger for providing feedback about the resolution
* @param extraDirectory path to the source directory for the extra files layer
* @param permissions map from path on container to file permissions
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's mention this applies only to the files from extraDirectory.

* @param appRoot root directory in the image where the app will be placed
* @return {@link JavaLayerConfigurations} for the layers for the Gradle {@link Project}
* @throws IOException if an I/O exception occurred during resolution
*/
private static JavaLayerConfigurations getForWarProject(
Project project, Logger logger, Path extraDirectory, AbsoluteUnixPath appRoot)
Project project,
Path extraDirectory,
Map<AbsoluteUnixPath, FilePermissions> permissions,
TadCordle marked this conversation as resolved.
Show resolved Hide resolved
AbsoluteUnixPath appRoot)
throws IOException {
Path explodedWarPath = GradleProjectProperties.getExplodedWarDirectory(project);
return JavaLayerConfigurationsHelper.fromExplodedWar(explodedWarPath, appRoot, extraDirectory);
return JavaLayerConfigurationsHelper.fromExplodedWar(
explodedWarPath, appRoot, extraDirectory, permissions);
}

private GradleLayerConfigurations() {}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import com.google.cloud.tools.jib.event.events.LogEvent;
import com.google.cloud.tools.jib.filesystem.AbsoluteUnixPath;
import com.google.cloud.tools.jib.frontend.JavaLayerConfigurations;
import com.google.cloud.tools.jib.plugins.common.ConfigurationPropertyValidator;
import com.google.cloud.tools.jib.plugins.common.MainClassInferenceException;
import com.google.cloud.tools.jib.plugins.common.MainClassResolver;
import com.google.cloud.tools.jib.plugins.common.ProjectProperties;
Expand All @@ -32,6 +33,7 @@
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.annotation.Nullable;
import org.gradle.api.GradleException;
Expand All @@ -57,12 +59,21 @@ class GradleProjectProperties implements ProjectProperties {

/** @return a GradleProjectProperties from the given project and logger. */
static GradleProjectProperties getForProject(
Project project, Logger logger, Path extraDirectory, AbsoluteUnixPath appRoot) {
Project project,
Logger logger,
Path extraDirectory,
Map<String, String> permissions,
AbsoluteUnixPath appRoot) {
try {
return new GradleProjectProperties(
project,
makeEventHandlers(logger),
GradleLayerConfigurations.getForProject(project, logger, extraDirectory, appRoot));
GradleLayerConfigurations.getForProject(
project,
logger,
extraDirectory,
ConfigurationPropertyValidator.convertPermissionsMap(permissions),
appRoot));

} catch (IOException ex) {
throw new GradleException("Obtaining project build output files failed", ex);
Expand Down
Loading