use of com.google.cloud.tools.jib.api.buildplan.FileEntry in project jib by GoogleContainerTools.
the class JavaContainerBuilderHelperTest method testExtraDirectoryLayerConfiguration_overlappingPermissions.
@Test
public void testExtraDirectoryLayerConfiguration_overlappingPermissions() throws URISyntaxException, IOException {
Path extraFilesDirectory = Paths.get(Resources.getResource("core/layer").toURI());
Map<String, FilePermissions> permissionsMap = ImmutableMap.of("/a**", FilePermissions.fromOctalString("123"), // Should be ignored, since first match takes priority
"/a/b**", FilePermissions.fromOctalString("000"), // Should override first match since explicit path is used instead of glob
"/a/b/bar", FilePermissions.fromOctalString("765"));
FileEntriesLayer fileEntriesLayer = JavaContainerBuilderHelper.extraDirectoryLayerConfiguration(extraFilesDirectory, AbsoluteUnixPath.get("/"), Collections.emptyList(), Collections.emptyList(), permissionsMap, (ignored1, ignored2) -> Instant.EPOCH);
assertThat(fileEntriesLayer.getEntries()).comparingElementsUsing(EXTRACTION_PATH_OF).containsExactly("/a", "/a/b", "/a/b/bar", "/c", "/c/cat", "/foo");
Map<AbsoluteUnixPath, FilePermissions> expectedPermissions = ImmutableMap.<AbsoluteUnixPath, FilePermissions>builder().put(AbsoluteUnixPath.get("/a"), FilePermissions.fromOctalString("123")).put(AbsoluteUnixPath.get("/a/b"), FilePermissions.fromOctalString("123")).put(AbsoluteUnixPath.get("/a/b/bar"), FilePermissions.fromOctalString("765")).put(AbsoluteUnixPath.get("/c"), FilePermissions.DEFAULT_FOLDER_PERMISSIONS).put(AbsoluteUnixPath.get("/c/cat"), FilePermissions.DEFAULT_FILE_PERMISSIONS).put(AbsoluteUnixPath.get("/foo"), FilePermissions.DEFAULT_FILE_PERMISSIONS).build();
for (FileEntry entry : fileEntriesLayer.getEntries()) {
assertThat(entry.getPermissions()).isEqualTo(expectedPermissions.get(entry.getExtractionPath()));
}
}
use of com.google.cloud.tools.jib.api.buildplan.FileEntry in project jib by GoogleContainerTools.
the class JavaContainerBuilderHelperTest method testExtraDirectoryLayerConfiguration_globPermissions.
@Test
public void testExtraDirectoryLayerConfiguration_globPermissions() throws URISyntaxException, IOException {
Path extraFilesDirectory = Paths.get(Resources.getResource("core/layer").toURI());
Map<String, FilePermissions> permissionsMap = ImmutableMap.of("/a", FilePermissions.fromOctalString("123"), "/a/*", FilePermissions.fromOctalString("456"), "**/bar", FilePermissions.fromOctalString("765"));
FileEntriesLayer fileEntriesLayer = JavaContainerBuilderHelper.extraDirectoryLayerConfiguration(extraFilesDirectory, AbsoluteUnixPath.get("/"), Collections.emptyList(), Collections.emptyList(), permissionsMap, (ignored1, ignored2) -> Instant.EPOCH);
assertThat(fileEntriesLayer.getEntries()).comparingElementsUsing(EXTRACTION_PATH_OF).containsExactly("/a", "/a/b", "/a/b/bar", "/c", "/c/cat", "/foo");
Map<AbsoluteUnixPath, FilePermissions> expectedPermissions = ImmutableMap.<AbsoluteUnixPath, FilePermissions>builder().put(AbsoluteUnixPath.get("/a"), FilePermissions.fromOctalString("123")).put(AbsoluteUnixPath.get("/a/b"), FilePermissions.fromOctalString("456")).put(AbsoluteUnixPath.get("/a/b/bar"), FilePermissions.fromOctalString("765")).put(AbsoluteUnixPath.get("/c"), FilePermissions.DEFAULT_FOLDER_PERMISSIONS).put(AbsoluteUnixPath.get("/c/cat"), FilePermissions.DEFAULT_FILE_PERMISSIONS).put(AbsoluteUnixPath.get("/foo"), FilePermissions.DEFAULT_FILE_PERMISSIONS).build();
for (FileEntry entry : fileEntriesLayer.getEntries()) {
assertThat(entry.getPermissions()).isEqualTo(expectedPermissions.get(entry.getExtractionPath()));
}
}
use of com.google.cloud.tools.jib.api.buildplan.FileEntry in project jib by GoogleContainerTools.
the class ReproducibleLayerBuilderTest method testBuild_permissions.
@Test
public void testBuild_permissions() throws IOException {
Path testRoot = temporaryFolder.getRoot().toPath();
Path folder = Files.createDirectories(testRoot.resolve("files1"));
Path fileA = createFile(testRoot, "fileA", "abc", 54321);
Path fileB = createFile(testRoot, "fileB", "def", 54321);
Blob blob = new ReproducibleLayerBuilder(ImmutableList.of(defaultLayerEntry(fileA, AbsoluteUnixPath.get("/somewhere/fileA")), new FileEntry(fileB, AbsoluteUnixPath.get("/somewhere/fileB"), FilePermissions.fromOctalString("123"), FileEntriesLayer.DEFAULT_MODIFICATION_TIME), new FileEntry(folder, AbsoluteUnixPath.get("/somewhere/folder"), FilePermissions.fromOctalString("456"), FileEntriesLayer.DEFAULT_MODIFICATION_TIME))).build();
Path tarFile = temporaryFolder.newFile().toPath();
try (OutputStream out = new BufferedOutputStream(Files.newOutputStream(tarFile))) {
blob.writeTo(out);
}
try (TarArchiveInputStream in = new TarArchiveInputStream(Files.newInputStream(tarFile))) {
// Root folder (default folder permissions)
assertThat(in.getNextTarEntry().getMode()).isEqualTo(040755);
// fileA (default file permissions)
assertThat(in.getNextTarEntry().getMode()).isEqualTo(0100644);
// fileB (custom file permissions)
assertThat(in.getNextTarEntry().getMode()).isEqualTo(0100123);
// folder (custom folder permissions)
assertThat(in.getNextTarEntry().getMode()).isEqualTo(040456);
}
}
use of com.google.cloud.tools.jib.api.buildplan.FileEntry in project jib by GoogleContainerTools.
the class ReproducibleLayerBuilderTest method testBuild_timestampNonDefault.
@Test
public void testBuild_timestampNonDefault() throws IOException {
Path file = createFile(temporaryFolder.getRoot().toPath(), "fileA", "some content", 54321);
Blob blob = new ReproducibleLayerBuilder(ImmutableList.of(new FileEntry(file, AbsoluteUnixPath.get("/fileA"), FilePermissions.DEFAULT_FILE_PERMISSIONS, Instant.ofEpochSecond(123)))).build();
Path tarFile = temporaryFolder.newFile().toPath();
try (OutputStream out = new BufferedOutputStream(Files.newOutputStream(tarFile))) {
blob.writeTo(out);
}
// Reads the file back.
try (TarArchiveInputStream in = new TarArchiveInputStream(Files.newInputStream(tarFile))) {
assertThat(in.getNextEntry().getLastModifiedDate().toInstant()).isEqualTo(Instant.EPOCH.plusSeconds(123));
}
}
use of com.google.cloud.tools.jib.api.buildplan.FileEntry in project quarkus by quarkusio.
the class JibProcessor method createContainerBuilderFromFastJar.
/**
* We don't use Jib's JavaContainerBuilder here because we need to support the custom fast-jar format
* We create the following layers (least likely to change to most likely to change):
*
* <ul>
* <li>lib</li>
* <li>boot-lib</li>
* <li>quarkus-run.jar</li>
* <li>quarkus</li>
* <li>app</li>
* </ul>
*/
private JibContainerBuilder createContainerBuilderFromFastJar(String baseJvmImage, JibConfig jibConfig, ContainerImageConfig containerImageConfig, JarBuildItem sourceJarBuildItem, CurateOutcomeBuildItem curateOutcome, List<ContainerImageLabelBuildItem> containerImageLabels, Optional<AppCDSResultBuildItem> appCDSResult) {
Path componentsPath = sourceJarBuildItem.getPath().getParent();
Path appLibDir = componentsPath.resolve(JarResultBuildStep.LIB).resolve(JarResultBuildStep.MAIN);
AbsoluteUnixPath workDirInContainer = AbsoluteUnixPath.get(jibConfig.workingDirectory);
List<String> entrypoint;
if (jibConfig.jvmEntrypoint.isPresent()) {
entrypoint = jibConfig.jvmEntrypoint.get();
} else {
List<String> effectiveJvmArguments = determineEffectiveJvmArguments(jibConfig, appCDSResult);
entrypoint = new ArrayList<>(3 + effectiveJvmArguments.size());
entrypoint.add("java");
entrypoint.addAll(effectiveJvmArguments);
entrypoint.add("-jar");
entrypoint.add(JarResultBuildStep.QUARKUS_RUN_JAR);
}
List<ResolvedDependency> fastChangingLibs = new ArrayList<>();
Collection<ResolvedDependency> userDependencies = curateOutcome.getApplicationModel().getRuntimeDependencies();
for (ResolvedDependency artifact : userDependencies) {
if (artifact == null) {
continue;
}
String artifactVersion = artifact.getVersion();
if ((artifactVersion == null) || artifactVersion.isEmpty()) {
continue;
}
if (artifactVersion.toLowerCase().contains("snapshot")) {
fastChangingLibs.add(artifact);
}
}
Set<Path> fastChangingLibPaths = Collections.emptySet();
List<Path> nonFastChangingLibPaths = null;
if (!fastChangingLibs.isEmpty()) {
fastChangingLibPaths = new HashSet<>(fastChangingLibs.size());
Map<String, Path> libNameToPath = new HashMap<>();
try (DirectoryStream<Path> allLibPaths = Files.newDirectoryStream(appLibDir)) {
for (Path libPath : allLibPaths) {
libNameToPath.put(libPath.getFileName().toString(), libPath);
}
} catch (IOException e) {
throw new UncheckedIOException(e);
}
List<String> libFileNames = new ArrayList<>(libNameToPath.keySet());
for (ResolvedDependency appArtifact : fastChangingLibs) {
String matchingLibDirFileName = null;
for (Path appArtifactPath : appArtifact.getResolvedPaths()) {
for (String libFileName : libFileNames) {
if (libFileName.contains(appArtifact.getGroupId()) && libFileName.contains(appArtifactPath.getFileName().toString())) {
matchingLibDirFileName = libFileName;
break;
}
}
if (matchingLibDirFileName != null) {
break;
}
}
if (matchingLibDirFileName != null) {
fastChangingLibPaths.add(libNameToPath.get(matchingLibDirFileName));
}
}
Collection<Path> allLibPaths = libNameToPath.values();
nonFastChangingLibPaths = new ArrayList<>(allLibPaths.size() - fastChangingLibPaths.size());
for (Path libPath : allLibPaths) {
if (!fastChangingLibPaths.contains(libPath)) {
nonFastChangingLibPaths.add(libPath);
}
}
}
try {
Instant now = Instant.now();
JibContainerBuilder jibContainerBuilder = Jib.from(toRegistryImage(ImageReference.parse(baseJvmImage), jibConfig.baseRegistryUsername, jibConfig.baseRegistryPassword));
if (fastChangingLibPaths.isEmpty()) {
// just create a layer with the entire lib structure intact
jibContainerBuilder.addLayer(Collections.singletonList(componentsPath.resolve(JarResultBuildStep.LIB)), workDirInContainer);
} else {
// we need to manually create each layer
// the idea here is that the fast changing libraries are created in a later layer, thus when they do change,
// docker doesn't have to create an entire layer with all dependencies - only change the fast ones
FileEntriesLayer.Builder bootLibsLayerBuilder = FileEntriesLayer.builder();
Path bootLibPath = componentsPath.resolve(JarResultBuildStep.LIB).resolve(JarResultBuildStep.BOOT_LIB);
try (Stream<Path> boolLibPaths = Files.list(bootLibPath)) {
boolLibPaths.forEach(lib -> {
try {
AbsoluteUnixPath libPathInContainer = workDirInContainer.resolve(JarResultBuildStep.LIB).resolve(JarResultBuildStep.BOOT_LIB).resolve(lib.getFileName());
if (appCDSResult.isPresent()) {
// the boot lib jars need to preserve the modification time because otherwise AppCDS won't work
bootLibsLayerBuilder.addEntry(lib, libPathInContainer, Files.getLastModifiedTime(lib).toInstant());
} else {
bootLibsLayerBuilder.addEntry(lib, libPathInContainer);
}
} catch (IOException e) {
throw new UncheckedIOException(e);
}
});
}
jibContainerBuilder.addFileEntriesLayer(bootLibsLayerBuilder.build());
Path deploymentPath = componentsPath.resolve(JarResultBuildStep.LIB).resolve(JarResultBuildStep.DEPLOYMENT_LIB);
if (Files.exists(deploymentPath)) {
// this is the case of mutable-jar
FileEntriesLayer.Builder deploymentLayerBuilder = FileEntriesLayer.builder();
Files.list(deploymentPath).forEach(lib -> {
AbsoluteUnixPath libPathInContainer = workDirInContainer.resolve(JarResultBuildStep.LIB).resolve(JarResultBuildStep.DEPLOYMENT_LIB).resolve(lib.getFileName());
deploymentLayerBuilder.addEntry(lib, libPathInContainer);
});
jibContainerBuilder.addFileEntriesLayer(deploymentLayerBuilder.build());
}
jibContainerBuilder.addLayer(nonFastChangingLibPaths, workDirInContainer.resolve(JarResultBuildStep.LIB).resolve(JarResultBuildStep.MAIN));
jibContainerBuilder.addLayer(new ArrayList<>(fastChangingLibPaths), workDirInContainer.resolve(JarResultBuildStep.LIB).resolve(JarResultBuildStep.MAIN));
}
if (appCDSResult.isPresent()) {
jibContainerBuilder.addFileEntriesLayer(FileEntriesLayer.builder().addEntry(componentsPath.resolve(JarResultBuildStep.QUARKUS_RUN_JAR), workDirInContainer.resolve(JarResultBuildStep.QUARKUS_RUN_JAR), Files.getLastModifiedTime(componentsPath.resolve(JarResultBuildStep.QUARKUS_RUN_JAR)).toInstant()).build());
jibContainerBuilder.addLayer(Collections.singletonList(appCDSResult.get().getAppCDS()), workDirInContainer);
} else {
jibContainerBuilder.addFileEntriesLayer(FileEntriesLayer.builder().addEntry(componentsPath.resolve(JarResultBuildStep.QUARKUS_RUN_JAR), workDirInContainer.resolve(JarResultBuildStep.QUARKUS_RUN_JAR)).build());
}
jibContainerBuilder.addLayer(Collections.singletonList(componentsPath.resolve(JarResultBuildStep.APP)), workDirInContainer).addLayer(Collections.singletonList(componentsPath.resolve(JarResultBuildStep.QUARKUS)), workDirInContainer);
if (JibConfig.DEFAULT_WORKING_DIR.equals(jibConfig.workingDirectory)) {
// this layer ensures that the working directory is writeable
// see https://github.com/GoogleContainerTools/jib/issues/1270
// TODO: is this needed for all working directories?
jibContainerBuilder.addFileEntriesLayer(FileEntriesLayer.builder().addEntry(new FileEntry(Files.createTempDirectory("jib"), AbsoluteUnixPath.get(jibConfig.workingDirectory), FilePermissions.DEFAULT_FOLDER_PERMISSIONS, now, DEFAULT_BASE_IMAGE_USER)).build());
}
jibContainerBuilder.setWorkingDirectory(workDirInContainer).setEntrypoint(entrypoint).setEnvironment(getEnvironmentVariables(jibConfig)).setLabels(allLabels(jibConfig, containerImageConfig, containerImageLabels));
if (jibConfig.useCurrentTimestamp) {
jibContainerBuilder.setCreationTime(now);
}
for (int port : jibConfig.ports) {
jibContainerBuilder.addExposedPort(Port.tcp(port));
}
return jibContainerBuilder;
} catch (IOException e) {
throw new UncheckedIOException(e);
} catch (InvalidImageReferenceException e) {
throw new RuntimeException(e);
}
}
Aggregations