Search in sources :

Example 11 with FilePermissions

use of com.google.cloud.tools.jib.api.buildplan.FilePermissions in project jib by GoogleContainerTools.

the class JavaContainerBuilderHelper method extraDirectoryLayerConfiguration.

/**
 * Returns a {@link FileEntriesLayer} for adding the extra directory to the container.
 *
 * @param sourceDirectory the source extra directory path
 * @param targetDirectory the root directory on the container to place the files in
 * @param includes the list of glob patterns to include from the source directory
 * @param excludes the list of glob patterns to exclude from the source directory
 * @param extraDirectoryPermissions map from path on container to file permissions
 * @param modificationTimeProvider file modification time provider
 * @return a {@link FileEntriesLayer} for adding the extra directory to the container
 * @throws IOException if walking the extra directory fails
 */
public static FileEntriesLayer extraDirectoryLayerConfiguration(Path sourceDirectory, AbsoluteUnixPath targetDirectory, List<String> includes, List<String> excludes, Map<String, FilePermissions> extraDirectoryPermissions, ModificationTimeProvider modificationTimeProvider) throws IOException {
    FileEntriesLayer.Builder builder = FileEntriesLayer.builder().setName(LayerType.EXTRA_FILES.getName());
    Map<PathMatcher, FilePermissions> permissionsPathMatchers = new LinkedHashMap<>();
    for (Map.Entry<String, FilePermissions> entry : extraDirectoryPermissions.entrySet()) {
        permissionsPathMatchers.put(FileSystems.getDefault().getPathMatcher(GLOB_PREFIX + entry.getKey()), entry.getValue());
    }
    DirectoryWalker walker = new DirectoryWalker(sourceDirectory).filterRoot();
    // add exclusion filters
    excludes.stream().map(pattern -> FileSystems.getDefault().getPathMatcher(GLOB_PREFIX + pattern)).forEach(pathMatcher -> walker.filter(path -> !pathMatcher.matches(sourceDirectory.relativize(path))));
    // add an inclusion filter
    includes.stream().map(pattern -> FileSystems.getDefault().getPathMatcher(GLOB_PREFIX + pattern)).map(pathMatcher -> (Predicate<Path>) path -> pathMatcher.matches(sourceDirectory.relativize(path))).reduce((matches1, matches2) -> matches1.or(matches2)).ifPresent(walker::filter);
    // walk the source tree and add layer entries
    walker.walk(localPath -> {
        AbsoluteUnixPath pathOnContainer = targetDirectory.resolve(sourceDirectory.relativize(localPath));
        Instant modificationTime = modificationTimeProvider.get(localPath, pathOnContainer);
        Optional<FilePermissions> permissions = determinePermissions(pathOnContainer, extraDirectoryPermissions, permissionsPathMatchers);
        if (permissions.isPresent()) {
            builder.addEntry(localPath, pathOnContainer, permissions.get(), modificationTime);
        } else {
            builder.addEntry(localPath, pathOnContainer, modificationTime);
        }
    });
    return builder.build();
}
Also used : AbsoluteUnixPath(com.google.cloud.tools.jib.api.buildplan.AbsoluteUnixPath) JibContainerBuilder(com.google.cloud.tools.jib.api.JibContainerBuilder) Files(java.nio.file.Files) Predicate(java.util.function.Predicate) FilePermissions(com.google.cloud.tools.jib.api.buildplan.FilePermissions) Set(java.util.Set) DirectoryWalker(com.google.cloud.tools.jib.filesystem.DirectoryWalker) IOException(java.io.IOException) JavaContainerBuilder(com.google.cloud.tools.jib.api.JavaContainerBuilder) FileEntriesLayer(com.google.cloud.tools.jib.api.buildplan.FileEntriesLayer) ModificationTimeProvider(com.google.cloud.tools.jib.api.buildplan.ModificationTimeProvider) Instant(java.time.Instant) LinkedHashMap(java.util.LinkedHashMap) LayerType(com.google.cloud.tools.jib.api.JavaContainerBuilder.LayerType) List(java.util.List) Paths(java.nio.file.Paths) Map(java.util.Map) RelativeUnixPath(com.google.cloud.tools.jib.api.buildplan.RelativeUnixPath) PathMatcher(java.nio.file.PathMatcher) Optional(java.util.Optional) Path(java.nio.file.Path) FileSystems(java.nio.file.FileSystems) AbsoluteUnixPath(com.google.cloud.tools.jib.api.buildplan.AbsoluteUnixPath) RelativeUnixPath(com.google.cloud.tools.jib.api.buildplan.RelativeUnixPath) Path(java.nio.file.Path) Instant(java.time.Instant) FileEntriesLayer(com.google.cloud.tools.jib.api.buildplan.FileEntriesLayer) DirectoryWalker(com.google.cloud.tools.jib.filesystem.DirectoryWalker) LinkedHashMap(java.util.LinkedHashMap) PathMatcher(java.nio.file.PathMatcher) AbsoluteUnixPath(com.google.cloud.tools.jib.api.buildplan.AbsoluteUnixPath) FilePermissions(com.google.cloud.tools.jib.api.buildplan.FilePermissions) LinkedHashMap(java.util.LinkedHashMap) Map(java.util.Map)

Example 12 with FilePermissions

use of com.google.cloud.tools.jib.api.buildplan.FilePermissions in project jib by GoogleContainerTools.

the class Layers method toLayers.

/**
 * Convert a layer spec to a list of layer objects.
 *
 * <p>Does not handle missing directories for files added via this method. We can either prefill
 * directories here, or allow passing of the file entry information directly to the reproducible
 * layer builder
 *
 * @param buildRoot the directory to resolve relative paths, usually the directory where the build
 *     config file is located
 * @param layersSpec a layersSpec containing configuration for all layers
 * @return a {@link List} of {@link FileEntriesLayer} to use as part of a jib container build
 * @throws IOException if traversing a directory fails
 */
static List<FileEntriesLayer> toLayers(Path buildRoot, LayersSpec layersSpec) throws IOException {
    List<FileEntriesLayer> layers = new ArrayList<>();
    FilePropertiesStack filePropertiesStack = new FilePropertiesStack();
    // base properties
    layersSpec.getProperties().ifPresent(filePropertiesStack::push);
    for (LayerSpec entry : layersSpec.getEntries()) {
        // each loop is a new layer
        if (entry instanceof FileLayerSpec) {
            FileEntriesLayer.Builder layerBuiler = FileEntriesLayer.builder();
            FileLayerSpec fileLayer = (FileLayerSpec) entry;
            layerBuiler.setName(fileLayer.getName());
            // layer properties
            fileLayer.getProperties().ifPresent(filePropertiesStack::push);
            for (CopySpec copySpec : ((FileLayerSpec) entry).getFiles()) {
                // copy spec properties
                copySpec.getProperties().ifPresent(filePropertiesStack::push);
                // relativize all paths to the buildRoot location
                Path rawSrc = copySpec.getSrc();
                Path src = rawSrc.isAbsolute() ? rawSrc : buildRoot.resolve(rawSrc);
                AbsoluteUnixPath dest = copySpec.getDest();
                if (!Files.isDirectory(src) && !Files.isRegularFile(src)) {
                    throw new UnsupportedOperationException("Cannot create FileLayers from non-file, non-directory: " + src.toString());
                }
                if (Files.isRegularFile(src)) {
                    // regular file
                    if (!copySpec.getExcludes().isEmpty() || !copySpec.getIncludes().isEmpty()) {
                        throw new UnsupportedOperationException("Cannot apply includes/excludes on single file copy directives.");
                    }
                    layerBuiler.addEntry(src, copySpec.isDestEndsWithSlash() ? dest.resolve(src.getFileName()) : dest, filePropertiesStack.getFilePermissions(), filePropertiesStack.getModificationTime(), filePropertiesStack.getOwnership());
                } else if (Files.isDirectory(src)) {
                    // directory
                    List<PathMatcher> excludes = copySpec.getExcludes().stream().map(Layers::toPathMatcher).collect(Collectors.toList());
                    List<PathMatcher> includes = copySpec.getIncludes().stream().map(Layers::toPathMatcher).collect(Collectors.toList());
                    try (Stream<Path> dirWalk = Files.walk(src)) {
                        List<Path> filtered = dirWalk.filter(path -> excludes.stream().noneMatch(exclude -> exclude.matches(path))).filter(path -> {
                            // if there are no includes directives, include everything
                            if (includes.isEmpty()) {
                                return true;
                            }
                            // if there are includes directives, only include those specified
                            for (PathMatcher matcher : includes) {
                                if (matcher.matches(path)) {
                                    return true;
                                }
                            }
                            return false;
                        }).collect(Collectors.toList());
                        BiFunction<Path, FilePermissions, FileEntry> newEntry = (file, permission) -> new FileEntry(file, dest.resolve(src.relativize(file)), permission, filePropertiesStack.getModificationTime(), filePropertiesStack.getOwnership());
                        Set<Path> addedDirectories = new HashSet<>();
                        for (Path path : filtered) {
                            if (!Files.isDirectory(path) && !Files.isRegularFile(path)) {
                                throw new UnsupportedOperationException("Cannot create FileLayers from non-file, non-directory: " + src.toString());
                            }
                            if (Files.isDirectory(path)) {
                                addedDirectories.add(path);
                                layerBuiler.addEntry(newEntry.apply(path, filePropertiesStack.getDirectoryPermissions()));
                            } else if (Files.isRegularFile(path)) {
                                if (!path.startsWith(src)) {
                                    // be from a link scenario that we do not understand.
                                    throw new IllegalStateException(src.toString() + " is not a parent of " + path.toString());
                                }
                                Path parent = Verify.verifyNotNull(path.getParent());
                                while (true) {
                                    if (addedDirectories.contains(parent)) {
                                        break;
                                    }
                                    layerBuiler.addEntry(newEntry.apply(parent, filePropertiesStack.getDirectoryPermissions()));
                                    addedDirectories.add(parent);
                                    if (parent.equals(src)) {
                                        break;
                                    }
                                    parent = Verify.verifyNotNull(parent.getParent());
                                }
                                layerBuiler.addEntry(newEntry.apply(path, filePropertiesStack.getFilePermissions()));
                            }
                        }
                    }
                }
                copySpec.getProperties().ifPresent(ignored -> filePropertiesStack.pop());
            }
            fileLayer.getProperties().ifPresent(ignored -> filePropertiesStack.pop());
            // TODO: add logging/handling for empty layers
            layers.add(layerBuiler.build());
        } else {
            throw new UnsupportedOperationException("Only FileLayers are supported at this time.");
        }
    }
    layersSpec.getProperties().ifPresent(ignored -> filePropertiesStack.pop());
    return layers;
}
Also used : AbsoluteUnixPath(com.google.cloud.tools.jib.api.buildplan.AbsoluteUnixPath) Path(java.nio.file.Path) AbsoluteUnixPath(com.google.cloud.tools.jib.api.buildplan.AbsoluteUnixPath) Verify(com.google.common.base.Verify) Files(java.nio.file.Files) BiFunction(java.util.function.BiFunction) FilePermissions(com.google.cloud.tools.jib.api.buildplan.FilePermissions) Set(java.util.Set) IOException(java.io.IOException) FileEntriesLayer(com.google.cloud.tools.jib.api.buildplan.FileEntriesLayer) Collectors(java.util.stream.Collectors) ArrayList(java.util.ArrayList) HashSet(java.util.HashSet) List(java.util.List) Stream(java.util.stream.Stream) FileEntry(com.google.cloud.tools.jib.api.buildplan.FileEntry) PathMatcher(java.nio.file.PathMatcher) VisibleForTesting(com.google.common.annotations.VisibleForTesting) Path(java.nio.file.Path) FileSystems(java.nio.file.FileSystems) Set(java.util.Set) HashSet(java.util.HashSet) FileEntriesLayer(com.google.cloud.tools.jib.api.buildplan.FileEntriesLayer) ArrayList(java.util.ArrayList) AbsoluteUnixPath(com.google.cloud.tools.jib.api.buildplan.AbsoluteUnixPath) PathMatcher(java.nio.file.PathMatcher) BiFunction(java.util.function.BiFunction) ArrayList(java.util.ArrayList) List(java.util.List) Stream(java.util.stream.Stream) FileEntry(com.google.cloud.tools.jib.api.buildplan.FileEntry)

Example 13 with FilePermissions

use of com.google.cloud.tools.jib.api.buildplan.FilePermissions 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()));
    }
}
Also used : Path(java.nio.file.Path) AbsoluteUnixPath(com.google.cloud.tools.jib.api.buildplan.AbsoluteUnixPath) AbsoluteUnixPath(com.google.cloud.tools.jib.api.buildplan.AbsoluteUnixPath) FilePermissions(com.google.cloud.tools.jib.api.buildplan.FilePermissions) FileEntriesLayer(com.google.cloud.tools.jib.api.buildplan.FileEntriesLayer) FileEntry(com.google.cloud.tools.jib.api.buildplan.FileEntry) Test(org.junit.Test)

Example 14 with FilePermissions

use of com.google.cloud.tools.jib.api.buildplan.FilePermissions 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()));
    }
}
Also used : Path(java.nio.file.Path) AbsoluteUnixPath(com.google.cloud.tools.jib.api.buildplan.AbsoluteUnixPath) AbsoluteUnixPath(com.google.cloud.tools.jib.api.buildplan.AbsoluteUnixPath) FilePermissions(com.google.cloud.tools.jib.api.buildplan.FilePermissions) FileEntriesLayer(com.google.cloud.tools.jib.api.buildplan.FileEntriesLayer) FileEntry(com.google.cloud.tools.jib.api.buildplan.FileEntry) Test(org.junit.Test)

Aggregations

FilePermissions (com.google.cloud.tools.jib.api.buildplan.FilePermissions)14 AbsoluteUnixPath (com.google.cloud.tools.jib.api.buildplan.AbsoluteUnixPath)12 Path (java.nio.file.Path)12 FileEntriesLayer (com.google.cloud.tools.jib.api.buildplan.FileEntriesLayer)10 FileEntry (com.google.cloud.tools.jib.api.buildplan.FileEntry)8 Test (org.junit.Test)6 PathMatcher (java.nio.file.PathMatcher)5 LinkedHashMap (java.util.LinkedHashMap)5 List (java.util.List)5 IOException (java.io.IOException)4 FileSystems (java.nio.file.FileSystems)4 Files (java.nio.file.Files)4 Map (java.util.Map)4 Set (java.util.Set)4 DirectoryWalker (com.google.cloud.tools.jib.filesystem.DirectoryWalker)3 Instant (java.time.Instant)3 ArrayList (java.util.ArrayList)3 JavaContainerBuilder (com.google.cloud.tools.jib.api.JavaContainerBuilder)2 LayerType (com.google.cloud.tools.jib.api.JavaContainerBuilder.LayerType)2 JibContainerBuilder (com.google.cloud.tools.jib.api.JibContainerBuilder)2