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

New JavaLayerConfiguration API for more flexibility #1049

Merged
merged 8 commits into from
Sep 27, 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
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@
import java.nio.file.DirectoryNotEmptyException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Collections;
import java.util.List;
import java.util.Map;
Expand Down Expand Up @@ -98,13 +97,12 @@ private CopyDirective(
private static void addIfNotEmpty(
ImmutableList.Builder<CopyDirective> listBuilder,
ImmutableList<LayerEntry> layerEntries,
String directoryInContext,
AbsoluteUnixPath extractionPath) {
String directoryInContext) {
if (layerEntries.isEmpty()) {
return;
}

listBuilder.add(new CopyDirective(layerEntries, directoryInContext, extractionPath));
listBuilder.add(new CopyDirective(layerEntries, directoryInContext, AbsoluteUnixPath.get("/")));
}

/**
Expand Down Expand Up @@ -153,36 +151,30 @@ public JavaDockerContextGenerator(JavaLayerConfigurations javaLayerConfiguration
addIfNotEmpty(
copyDirectivesBuilder,
javaLayerConfigurations.getDependencyLayerEntries(),
DEPENDENCIES_LAYER_DIRECTORY,
javaLayerConfigurations.getDependencyExtractionPath());
DEPENDENCIES_LAYER_DIRECTORY);
addIfNotEmpty(
copyDirectivesBuilder,
javaLayerConfigurations.getSnapshotDependencyLayerEntries(),
SNAPSHOT_DEPENDENCIES_LAYER_DIRECTORY,
javaLayerConfigurations.getSnapshotDependencyExtractionPath());
SNAPSHOT_DEPENDENCIES_LAYER_DIRECTORY);
addIfNotEmpty(
copyDirectivesBuilder,
javaLayerConfigurations.getResourceLayerEntries(),
RESOURCES_LAYER_DIRECTORY,
javaLayerConfigurations.getResourceExtractionPath());
RESOURCES_LAYER_DIRECTORY);
addIfNotEmpty(
copyDirectivesBuilder,
javaLayerConfigurations.getClassLayerEntries(),
CLASSES_LAYER_DIRECTORY,
javaLayerConfigurations.getClassExtractionPath());
CLASSES_LAYER_DIRECTORY);
// TODO: remove this once we put files in WAR into the relevant layers (i.e., dependencies,
// snapshot dependencies, resources, and classes layers). Should copy files in the right
// directories. (For example, "resources" will go into the webapp root.)
addIfNotEmpty(
copyDirectivesBuilder,
javaLayerConfigurations.getExplodedWarEntries(),
EXPLODED_WAR_LAYER_DIRECTORY,
javaLayerConfigurations.getExplodedWarExtractionPath());
EXPLODED_WAR_LAYER_DIRECTORY);
addIfNotEmpty(
copyDirectivesBuilder,
javaLayerConfigurations.getExtraFilesLayerEntries(),
EXTRA_FILES_LAYER_DIRECTORY,
javaLayerConfigurations.getExtraFilesExtractionPath());
EXTRA_FILES_LAYER_DIRECTORY);
copyDirectives = copyDirectivesBuilder.build();
}

Expand Down Expand Up @@ -280,19 +272,13 @@ public void generate(Path targetDirectory) throws IOException {

// Copies the source files to the directoryInContext.
for (LayerEntry layerEntry : copyDirective.layerEntries) {
// This resolves the path to copy the source file to in the {@code directory}.
// For example, for a 'baseDirectory' of 'target/jib-docker-context/classes', a
// 'baseExtractionPath' of '/app/classes', and an 'actualExtractionPath' of
// '/app/classes/com/test/HelloWorld.class', the resolved destination would be
// 'target/jib-docker-context/classes/com/test/HelloWorld.class'.
Path baseExtractionPath = Paths.get(copyDirective.extractionPath.toString());
Path relativeEntryPath =
baseExtractionPath.relativize(Paths.get(layerEntry.getExtractionPath().toString()));
Path destination = directoryInContext.resolve(relativeEntryPath);
String noLeadingSlash = layerEntry.getAbsoluteExtractionPathString().substring(1);
Path destination = directoryInContext.resolve(noLeadingSlash);

if (Files.isDirectory(layerEntry.getSourceFile())) {
Files.createDirectories(destination);
} else {
Files.createDirectories(destination.getParent());
Files.copy(layerEntry.getSourceFile(), destination);
}
}
Expand All @@ -309,11 +295,11 @@ public void generate(Path targetDirectory) throws IOException {
* <pre>{@code
* FROM [base image]
*
* COPY libs [path/to/dependencies/]
* COPY snapshot-libs [path/to/dependencies/]
* COPY resources [path/to/resources/]
* COPY classes [path/to/classes/]
* COPY root [path/to/root/]
* COPY libs /
* COPY snapshot-libs /
* COPY resources /
* COPY classes /
* COPY root /
*
* EXPOSE [port]
* [More EXPOSE instructions, if necessary]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,7 @@
import com.google.common.collect.ImmutableMap;
import java.io.IOException;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.EnumMap;
import java.util.List;
import java.util.Map;

/** Builds {@link LayerConfiguration}s for a Java application. */
Expand Down Expand Up @@ -65,78 +63,136 @@ String getName() {
/** Builds with each layer's files. */
public static class Builder {

private final Map<LayerType, List<Path>> layerFilesMap = new EnumMap<>(LayerType.class);
private final Map<LayerType, AbsoluteUnixPath> extractionPathMap =
private final Map<LayerType, LayerConfiguration.Builder> layerBuilders =
new EnumMap<>(LayerType.class);

private Builder() {
for (LayerType layerType : LayerType.values()) {
layerFilesMap.put(layerType, new ArrayList<>());
extractionPathMap.put(layerType, AbsoluteUnixPath.get("/"));
layerBuilders.put(layerType, LayerConfiguration.builder());
}
}

public Builder setDependencyFiles(List<Path> dependencyFiles, AbsoluteUnixPath extractionPath) {
layerFilesMap.put(LayerType.DEPENDENCIES, dependencyFiles);
extractionPathMap.put(LayerType.DEPENDENCIES, extractionPath);
/**
* Adds a file to the dependency layer. If the source file is a directory, the directory and its
* contents will be added recursively. See {@link LayerConfiguration.Builder#addEntryRecursive}
* for concrete examples about how the file will be placed in the image.
*
* @param sourceFile the source file to add to the layer
* @param pathInContainer the path in the container file system corresponding to the {@code
* sourceFile}
* @return this
* @throws IOException if an exception occurred when recursively listing the directory
*/
public Builder addDependencyFile(Path sourceFile, AbsoluteUnixPath pathInContainer)
throws IOException {
Preconditions.checkNotNull(layerBuilders.get(LayerType.DEPENDENCIES))
.addEntryRecursive(sourceFile, pathInContainer);
return this;
}

public Builder setSnapshotDependencyFiles(
List<Path> snapshotDependencyFiles, AbsoluteUnixPath extractionPath) {
layerFilesMap.put(LayerType.SNAPSHOT_DEPENDENCIES, snapshotDependencyFiles);
extractionPathMap.put(LayerType.SNAPSHOT_DEPENDENCIES, extractionPath);
/**
* Adds a file to the snapshot dependency layer. If the source file is a directory, the
* directory and its contents will be added recursively. See {@link
* LayerConfiguration.Builder#addEntryRecursive} for concrete examples about how the file will
* be placed in the image.
*
* @param sourceFile the source file to add to the layer
* @param pathInContainer the path in the container file system corresponding to the {@code
* sourceFile}
* @return this
* @throws IOException if an exception occurred when recursively listing the directory
*/
public Builder addSnapshotDependencyFile(Path sourceFile, AbsoluteUnixPath pathInContainer)
throws IOException {
Preconditions.checkNotNull(layerBuilders.get(LayerType.SNAPSHOT_DEPENDENCIES))
.addEntryRecursive(sourceFile, pathInContainer);
return this;
}

public Builder setResourceFiles(List<Path> resourceFiles, AbsoluteUnixPath extractionPath) {
layerFilesMap.put(LayerType.RESOURCES, resourceFiles);
extractionPathMap.put(LayerType.RESOURCES, extractionPath);
/**
* Adds a file to the resource layer. If the source file is a directory, the directory and its
* contents will be added recursively. See {@link LayerConfiguration.Builder#addEntryRecursive}
* for concrete examples about how the file will be placed in the image.
*
* @param sourceFile the source file to add to the layer
* @param pathInContainer the path in the container file system corresponding to the {@code
* sourceFile}
* @return this
* @throws IOException if an exception occurred when recursively listing the directory
*/
public Builder addResourceFile(Path sourceFile, AbsoluteUnixPath pathInContainer)
throws IOException {
Preconditions.checkNotNull(layerBuilders.get(LayerType.RESOURCES))
.addEntryRecursive(sourceFile, pathInContainer);
return this;
}

public Builder setClassFiles(List<Path> classFiles, AbsoluteUnixPath extractionPath) {
layerFilesMap.put(LayerType.CLASSES, classFiles);
extractionPathMap.put(LayerType.CLASSES, extractionPath);
/**
* Adds a file to the classes layer. If the source file is a directory, the directory and its
* contents will be added recursively. See {@link LayerConfiguration.Builder#addEntryRecursive}
* for concrete examples about how the file will be placed in the image.
*
* @param sourceFile the source file to add to the layer
* @param pathInContainer the path in the container file system corresponding to the {@code
* sourceFile}
* @return this
* @throws IOException if an exception occurred when recursively listing the directory
*/
public Builder addClassFile(Path sourceFile, AbsoluteUnixPath pathInContainer)
throws IOException {
Preconditions.checkNotNull(layerBuilders.get(LayerType.CLASSES))
.addEntryRecursive(sourceFile, pathInContainer);
return this;
}

public Builder setExtraFiles(List<Path> extraFiles, AbsoluteUnixPath extractionPath) {
layerFilesMap.put(LayerType.EXTRA_FILES, extraFiles);
extractionPathMap.put(LayerType.EXTRA_FILES, extractionPath);
/**
* Adds a file to the extra files layer. If the source file is a directory, the directory and
* its contents will be added recursively. See {@link
* LayerConfiguration.Builder#addEntryRecursive} for concrete examples about how the file will
* be placed in the image.
*
* @param sourceFile the source file to add to the layer
* @param pathInContainer the path in the container file system corresponding to the {@code
* sourceFile}
* @return this
* @throws IOException if an exception occurred when recursively listing the directory
*/
public Builder addExtraFile(Path sourceFile, AbsoluteUnixPath pathInContainer)
throws IOException {
Preconditions.checkNotNull(layerBuilders.get(LayerType.EXTRA_FILES))
.addEntryRecursive(sourceFile, pathInContainer);
return this;
}

/**
* Adds a file to the exploded WAR layer. If the source file is a directory, the directory and
* its contents will be added recursively. See {@link
* LayerConfiguration.Builder#addEntryRecursive} for concrete examples about how the file will
* be placed in the image.
*
* @param sourceFile the source file to add to the layer
* @param pathInContainer the path in the container file system corresponding to the {@code
* sourceFile}
* @return this
* @throws IOException if an exception occurred when recursively listing the directory
*/
// TODO: remove this and put files in WAR into the relevant layers (i.e., dependencies, snapshot
// dependencies, resources, and classes layers).
public Builder setExplodedWarFiles(
List<Path> explodedWarFiles, AbsoluteUnixPath extractionPath) {
layerFilesMap.put(LayerType.EXPLODED_WAR, explodedWarFiles);
extractionPathMap.put(LayerType.EXPLODED_WAR, extractionPath);
public Builder addExplodedWarFile(Path sourceFile, AbsoluteUnixPath pathInContainer)
throws IOException {
Preconditions.checkNotNull(layerBuilders.get(LayerType.EXPLODED_WAR))
.addEntryRecursive(sourceFile, pathInContainer);
return this;
}

public JavaLayerConfigurations build() throws IOException {
public JavaLayerConfigurations build() {
ImmutableMap.Builder<LayerType, LayerConfiguration> layerConfigurationsMap =
ImmutableMap.builderWithExpectedSize(LayerType.values().length);
for (LayerType layerType : LayerType.values()) {
AbsoluteUnixPath extractionPath =
Preconditions.checkNotNull(extractionPathMap.get(layerType));

LayerConfiguration.Builder layerConfigurationBuilder =
LayerConfiguration.builder().setName(layerType.getName());

// Adds all the layer files recursively.
List<Path> layerFiles = Preconditions.checkNotNull(layerFilesMap.get(layerType));
for (Path layerFile : layerFiles) {
layerConfigurationBuilder.addEntryRecursive(
layerFile, extractionPath.resolve(layerFile.getFileName()));
}
ImmutableMap.builderWithExpectedSize(layerBuilders.size());

layerConfigurationsMap.put(layerType, layerConfigurationBuilder.build());
}
return new JavaLayerConfigurations(
layerConfigurationsMap.build(), ImmutableMap.copyOf(extractionPathMap));
layerBuilders.forEach(
(type, builder) ->
layerConfigurationsMap.put(type, builder.setName(type.getName()).build()));
return new JavaLayerConfigurations(layerConfigurationsMap.build());
}
}

Expand All @@ -151,13 +207,10 @@ public static Builder builder() {
public static final String DEFAULT_APP_ROOT = "/app";

private final ImmutableMap<LayerType, LayerConfiguration> layerConfigurationMap;
private final ImmutableMap<LayerType, AbsoluteUnixPath> extractionPathMap;

private JavaLayerConfigurations(
ImmutableMap<LayerType, LayerConfiguration> layerConfigurationMap,
ImmutableMap<LayerType, AbsoluteUnixPath> extractionPathMap) {
ImmutableMap<LayerType, LayerConfiguration> layerConfigurationMap) {
this.layerConfigurationMap = layerConfigurationMap;
this.extractionPathMap = extractionPathMap;
}

public ImmutableList<LayerConfiguration> getLayerConfigurations() {
Expand Down Expand Up @@ -190,35 +243,7 @@ public ImmutableList<LayerEntry> getExplodedWarEntries() {
return getLayerEntries(LayerType.EXPLODED_WAR);
}

public AbsoluteUnixPath getDependencyExtractionPath() {
return getExtractionPath(LayerType.DEPENDENCIES);
}

public AbsoluteUnixPath getSnapshotDependencyExtractionPath() {
return getExtractionPath(LayerType.SNAPSHOT_DEPENDENCIES);
}

public AbsoluteUnixPath getResourceExtractionPath() {
return getExtractionPath(LayerType.RESOURCES);
}

public AbsoluteUnixPath getClassExtractionPath() {
return getExtractionPath(LayerType.CLASSES);
}

public AbsoluteUnixPath getExtraFilesExtractionPath() {
return getExtractionPath(LayerType.EXTRA_FILES);
}

public AbsoluteUnixPath getExplodedWarExtractionPath() {
return getExtractionPath(LayerType.EXPLODED_WAR);
}

private ImmutableList<LayerEntry> getLayerEntries(LayerType layerType) {
return Preconditions.checkNotNull(layerConfigurationMap.get(layerType)).getLayerEntries();
}

private AbsoluteUnixPath getExtractionPath(LayerType layerType) {
return Preconditions.checkNotNull(extractionPathMap.get(layerType));
}
}
Loading