Skip to content

Commit

Permalink
Separate out project dependencies, add integration test to verify
Browse files Browse the repository at this point in the history
  • Loading branch information
loosebazooka committed Jun 20, 2019
1 parent ab22479 commit 158fa93
Show file tree
Hide file tree
Showing 19 changed files with 383 additions and 6 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
package com.google.cloud.tools.jib.gradle;

import com.google.common.collect.ImmutableList;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
import java.util.zip.GZIPInputStream;
import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
import org.apache.commons.compress.archivers.tar.TarArchiveInputStream;
import org.junit.Assert;
import org.junit.ClassRule;
import org.junit.Test;

public class GradleLayerConfigurationIntegrationTest {

@ClassRule
public static final TestProject multiTestProject = new TestProject("all-local-multi-service");

@Test
public void testGradleLayerConfiguration_multiModule() throws IOException {
multiTestProject.build(":complex-service:jibBuildTar");

Path jibTar = multiTestProject.getProjectRoot().resolve("complex-service/build/jib-image.tar");

List<List<String>> layers = getLayers(jibTar);

Assert.assertEquals(6, layers.size());

// the expected order is:
// no base image layers (scratch)
// extra-files (0)
// classes (1)
// resources (2)
// project dependencies (3)
// snapshot dependencies (4)
// dependencies (5)

Path complexServiceRoot = multiTestProject.getProjectRoot().resolve("complex-service");
// verify dependencies
List<String> dependencies = layers.get(5);
List<String> expectedDependencies =
ImmutableList.of("app/", "app/libs/", "app/libs/dependency-1.0.0.jar");
Assert.assertEquals(expectedDependencies, dependencies);

// verify snapshot dependencies
List<String> snapshotDependencies = layers.get(4);
List<String> expectedSnapshotDependencies =
ImmutableList.of("app/", "app/libs/", "app/libs/dependencyX-1.0.0-SNAPSHOT.jar");
Assert.assertEquals(expectedSnapshotDependencies, snapshotDependencies);

// verify project dependencies
List<String> projectDependencies = layers.get(3);
List<String> expectedProjectDependencies =
ImmutableList.of("app/", "app/libs/", "app/libs/lib.jar");
Assert.assertEquals(expectedProjectDependencies, projectDependencies);

// verify resources
List<String> resources = layers.get(2);
List<String> expectedResources =
ImmutableList.of(
"app/", "app/resources/", "app/resources/resource1.txt", "app/resources/resource2.txt");
Assert.assertEquals(expectedResources, resources);

// verify classes
List<String> classes = layers.get(1);
List<String> expectedClasses =
ImmutableList.of(
"app/",
"app/classes/",
"app/classes/com/",
"app/classes/com/test/",
"app/classes/com/test/HelloWorld.class");
Assert.assertEquals(expectedClasses, classes);

// verify extra files
List<String> extraFiles = layers.get(0);
List<String> expectedExtraFiles = ImmutableList.of("extra-file");
Assert.assertEquals(expectedExtraFiles, extraFiles);
}

@Test
public void testGradleLayerConfiguration_simpleModule() throws IOException {
multiTestProject.build(":simple-service:jibBuildTar");

Path jibTar = multiTestProject.getProjectRoot().resolve("simple-service/build/jib-image.tar");

List<List<String>> layers = getLayers(jibTar);

Assert.assertEquals(1, layers.size());

// the expected order is:
// no base image layers (scratch)
// classes (0)

// verify classes
List<String> classes = layers.get(0);
List<String> expectedClasses =
ImmutableList.of(
"app/",
"app/classes/",
"app/classes/com/",
"app/classes/com/test/",
"app/classes/com/test/HelloWorld.class");
Assert.assertEquals(expectedClasses, classes);
}

// returns all files in layers (*.tar.gz) in a image tar
private List<List<String>> getLayers(Path tar) throws IOException {
List<List<String>> layers = new ArrayList<>();

try (TarArchiveInputStream image = new TarArchiveInputStream(Files.newInputStream(tar))) {
TarArchiveEntry entry;
while ((entry = image.getNextTarEntry()) != null) {
System.out.println(entry.getName());
if (entry.getName().endsWith(".tar.gz")) {
@SuppressWarnings("resource") // must not close sub-streams
TarArchiveInputStream layer = new TarArchiveInputStream(new GZIPInputStream(image));
TarArchiveEntry layerEntry;
List<String> layerFiles = new ArrayList<>();
while ((layerEntry = layer.getNextTarEntry()) != null) {
layerFiles.add(layerEntry.getName());
}
layers.add(0, layerFiles);
}
}
}
return layers;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,11 @@
import org.gradle.api.GradleException;
import org.gradle.api.JavaVersion;
import org.gradle.api.Project;
import org.gradle.api.artifacts.ResolvedArtifact;
import org.gradle.api.artifacts.component.ProjectComponentIdentifier;
import org.gradle.api.file.FileCollection;
import org.gradle.api.logging.Logger;
import org.gradle.api.plugins.JavaPlugin;
import org.gradle.api.plugins.JavaPluginConvention;
import org.gradle.api.plugins.WarPlugin;
import org.gradle.api.tasks.SourceSet;
Expand Down Expand Up @@ -149,21 +152,43 @@ public JibContainerBuilder createContainerBuilder(
Path resourcesOutputDirectory = mainSourceSet.getOutput().getResourcesDir().toPath();
FileCollection allFiles = mainSourceSet.getRuntimeClasspath().filter(File::exists);

FileCollection allDependencyFiles =
FileCollection projectDependencies =
project.files(
project
.getConfigurations()
.getByName(JavaPlugin.RUNTIME_CLASSPATH_CONFIGURATION_NAME)
.getResolvedConfiguration()
.getResolvedArtifacts()
.stream()
.filter(
artifact ->
artifact.getId().getComponentIdentifier()
instanceof ProjectComponentIdentifier)
.map(ResolvedArtifact::getFile)
.collect(Collectors.toList()));

FileCollection nonProjectDependencies =
allFiles
.minus(classesOutputDirectories)
.minus(projectDependencies)
.filter(file -> !file.toPath().equals(resourcesOutputDirectory));

FileCollection snapshotDependencyFiles =
allDependencyFiles.filter(file -> file.getName().contains("SNAPSHOT"));
FileCollection dependencyFiles = allDependencyFiles.minus(snapshotDependencyFiles);
FileCollection snapshotDependencies =
nonProjectDependencies.filter(file -> file.getName().contains("SNAPSHOT"));
FileCollection dependencies = nonProjectDependencies.minus(snapshotDependencies);

// Adds dependency files
javaContainerBuilder
.addDependencies(
dependencyFiles.getFiles().stream().map(File::toPath).collect(Collectors.toList()))
dependencies.getFiles().stream().map(File::toPath).collect(Collectors.toList()))
.addSnapshotDependencies(
snapshotDependencyFiles
snapshotDependencies
.getFiles()
.stream()
.map(File::toPath)
.collect(Collectors.toList()))
.addProjectDependencies(
projectDependencies
.getFiles()
.stream()
.map(File::toPath)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@
import org.gradle.StartParameter;
import org.gradle.api.JavaVersion;
import org.gradle.api.Project;
import org.gradle.api.artifacts.ConfigurationContainer;
import org.gradle.api.file.ConfigurableFileCollection;
import org.gradle.api.file.FileCollection;
import org.gradle.api.internal.file.AbstractFileCollection;
import org.gradle.api.internal.file.FileResolver;
Expand All @@ -60,6 +62,7 @@
import org.gradle.api.logging.Logger;
import org.gradle.api.logging.configuration.ConsoleOutput;
import org.gradle.api.plugins.Convention;
import org.gradle.api.plugins.JavaPlugin;
import org.gradle.api.plugins.JavaPluginConvention;
import org.gradle.api.plugins.PluginContainer;
import org.gradle.api.plugins.WarPlugin;
Expand Down Expand Up @@ -198,6 +201,21 @@ public void setup() throws URISyntaxException, IOException {
Mockito.when(mockGradle.getStartParameter()).thenReturn(mockStartParameter);
Mockito.when(mockStartParameter.getConsoleOutput()).thenReturn(ConsoleOutput.Auto);

// mocking to complete ignore project dependency resolution
Mockito.when(mockProject.getConfigurations())
.thenReturn(Mockito.mock(ConfigurationContainer.class, Mockito.RETURNS_DEEP_STUBS));
Mockito.when(
mockProject
.getConfigurations()
.getByName(JavaPlugin.RUNTIME_CLASSPATH_CONFIGURATION_NAME)
.getResolvedConfiguration()
.getResolvedArtifacts())
.thenReturn(ImmutableSet.of());
ConfigurableFileCollection emptyFileCollection = Mockito.mock(ConfigurableFileCollection.class);
Mockito.when(emptyFileCollection.getFiles()).thenReturn(ImmutableSet.of());
Mockito.when(mockProject.files(ImmutableList.of())).thenReturn(emptyFileCollection);
// done mocking project dependency resolution

Set<Path> classesFiles = ImmutableSet.of(getResource("gradle/application/classes"));
FileCollection classesFileCollection = new TestFileCollection(classesFiles);
Path resourcesOutputDir = getResource("gradle/application/resources");
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
plugins {
id 'java'
id 'com.google.cloud.tools.jib'
}

sourceCompatibility = 1.8
targetCompatibility = 1.8

repositories {
mavenCentral()
}

// this code is for GradleProjectPropertiesTest (we execute this task to inspect the deep layer configuration)
import com.google.cloud.tools.jib.gradle.*
import com.google.cloud.tools.jib.plugins.common.*
import com.google.cloud.tools.jib.api.*

subprojects {
task inspectLayers {
dependsOn "classes"
doLast {
def projectProps = new GradleProjectProperties(project, project.logger)
def jibContainerBuilder = projectProps.createContainerBuilder(
RegistryImage.named(ImageReference.scratch()),
AbsoluteUnixPath.get(project.appRoot), //injected on commandline with -PappRoot
ContainerizingMode.EXPLODED);

jibContainerBuilder.layerConfigurations.each { layerConfiguration ->
layerConfiguration.layerEntries.each { layerEntry ->
println layerConfiguration.name + "," + layerEntry.sourceFile + "," + layerEntry.extractionPath
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
plugins {
id 'java'
id 'com.google.cloud.tools.jib'
}

sourceCompatibility = 1.8
targetCompatibility = 1.8

repositories {
flatDir {
dirs "libs"
}
}

jib {
from {
image = "scratch"
}
extraDirectories {
paths = file('src/main/other-jib')
}
}

sourceSets {
main {
resources {
srcDirs "src/main/extra-resources-1", "src/main/extra-resources-2"
}
}
}

dependencies {
compile project(':lib')
compile name: "dependency-1.0.0"
compile name: "dependencyX-1.0.0-SNAPSHOT"
}
Binary file not shown.
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/*
* 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.test;

public class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello world");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
plugins {
id 'java'
}

sourceCompatibility = 1.8
targetCompatibility = 1.8

repositories {
mavenCentral()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/*
* 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.lib;

/** Shared Code! */
public class Lib {

public String getThing() {
return "thing";
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
hi
Loading

0 comments on commit 158fa93

Please sign in to comment.