use of com.google.cloud.tools.jib.api.Jib in project quarkus by quarkusio.
the class JibProcessor method handleExtraFiles.
/**
* Allow users to have custom files in {@code src/main/jib} that will be copied into the built container's file system
* in same manner as the Jib Maven and Gradle plugins do.
* For example, {@code src/main/jib/foo/bar} would add {@code /foo/bar} into the container filesystem.
*
* See: https://github.com/GoogleContainerTools/jib/blob/v0.15.0-core/docs/faq.md#can-i-add-a-custom-directory-to-the-image
*/
private void handleExtraFiles(OutputTargetBuildItem outputTarget, JibContainerBuilder jibContainerBuilder) {
Path outputDirectory = outputTarget.getOutputDirectory();
PathsUtil.findMainSourcesRoot(outputTarget.getOutputDirectory());
Map.Entry<Path, Path> mainSourcesRoot = findMainSourcesRoot(outputDirectory);
if (mainSourcesRoot == null) {
// this should never happen
return;
}
Path jibFilesRoot = mainSourcesRoot.getKey().resolve("jib");
if (!jibFilesRoot.toFile().exists()) {
return;
}
FileEntriesLayer extraFilesLayer;
try {
extraFilesLayer = ContainerBuilderHelper.extraDirectoryLayerConfiguration(jibFilesRoot, AbsoluteUnixPath.get("/"), Collections.emptyMap(), (localPath, ignored2) -> {
try {
return Files.getLastModifiedTime(localPath).toInstant();
} catch (IOException e) {
throw new UncheckedIOException(e);
}
});
jibContainerBuilder.addFileEntriesLayer(extraFilesLayer);
} catch (IOException e) {
throw new UncheckedIOException("Unable to add extra files in '" + jibFilesRoot.toAbsolutePath().toString() + "' to the container", e);
}
}
use of com.google.cloud.tools.jib.api.Jib in project quarkus by quarkusio.
the class JibProcessor method createContainerBuilderFromLegacyJar.
private JibContainerBuilder createContainerBuilderFromLegacyJar(String baseJvmImage, JibConfig jibConfig, ContainerImageConfig containerImageConfig, JarBuildItem sourceJarBuildItem, OutputTargetBuildItem outputTargetBuildItem, MainClassBuildItem mainClassBuildItem, List<ContainerImageLabelBuildItem> containerImageLabels) {
try {
// not ideal since this has been previously zipped - we would like to just reuse it
Path classesDir = outputTargetBuildItem.getOutputDirectory().resolve("jib");
ZipUtils.unzip(sourceJarBuildItem.getPath(), classesDir);
JavaContainerBuilder javaContainerBuilder = JavaContainerBuilder.from(toRegistryImage(ImageReference.parse(baseJvmImage), jibConfig.baseRegistryUsername, jibConfig.baseRegistryPassword)).addResources(classesDir, IS_CLASS_PREDICATE.negate()).addClasses(classesDir, IS_CLASS_PREDICATE);
// when there is no custom entry point, we just set everything up for a regular java run
if (!jibConfig.jvmEntrypoint.isPresent()) {
javaContainerBuilder.addJvmFlags(determineEffectiveJvmArguments(jibConfig, Optional.empty())).setMainClass(mainClassBuildItem.getClassName());
}
if (sourceJarBuildItem.getLibraryDir() != null) {
try (Stream<Path> dependenciesPaths = Files.list(sourceJarBuildItem.getLibraryDir())) {
javaContainerBuilder.addDependencies(dependenciesPaths.filter(p -> Files.isRegularFile(p) && p.getFileName().toString().endsWith(".jar")).sorted(Comparator.comparing(Path::getFileName)).collect(Collectors.toList()));
}
}
JibContainerBuilder jibContainerBuilder = javaContainerBuilder.toContainerBuilder().setEnvironment(getEnvironmentVariables(jibConfig)).setLabels(allLabels(jibConfig, containerImageConfig, containerImageLabels));
if (jibConfig.useCurrentTimestamp) {
jibContainerBuilder.setCreationTime(Instant.now());
}
if (jibConfig.jvmEntrypoint.isPresent()) {
jibContainerBuilder.setEntrypoint(jibConfig.jvmEntrypoint.get());
}
return jibContainerBuilder;
} catch (IOException e) {
throw new UncheckedIOException(e);
} catch (InvalidImageReferenceException e) {
throw new RuntimeException(e);
}
}
use of com.google.cloud.tools.jib.api.Jib in project jib by GoogleContainerTools.
the class PluginConfigurationProcessor method getSkaffoldSyncMap.
/**
* Generate a skaffold syncmap JSON string for an image build configuration.
*
* @param rawConfiguration the raw configuration from the plugin
* @param projectProperties an plugin specific implementation of {@link ProjectProperties}
* @param excludes a set of paths to exclude, directories include in this list will be expanded
* @return new json string representation of the Sync Map
* @throws InvalidImageReferenceException if the image reference is invalid
* @throws MainClassInferenceException if a main class could not be found
* @throws InvalidAppRootException if the specific path for application root is invalid
* @throws IOException if an error occurs creating the container builder
* @throws InvalidWorkingDirectoryException if the working directory specified for the build is
* invalid
* @throws InvalidPlatformException if there exists a {@link PlatformConfiguration} in the
* specified platforms list that is missing required fields or has invalid values
* @throws InvalidContainerVolumeException if a specific container volume is invalid
* @throws IncompatibleBaseImageJavaVersionException if the base image java version cannot support
* this build
* @throws NumberFormatException if a string to number conversion operation fails
* @throws InvalidContainerizingModeException if an invalid {@link ContainerizingMode} was
* specified
* @throws InvalidFilesModificationTimeException if configured modification time could not be
* parsed
* @throws InvalidCreationTimeException if configured creation time could not be parsed
* @throws ExtraDirectoryNotFoundException if the extra directory specified for the build is not
* found
*/
public static String getSkaffoldSyncMap(RawConfiguration rawConfiguration, ProjectProperties projectProperties, Set<Path> excludes) throws IOException, InvalidCreationTimeException, InvalidImageReferenceException, IncompatibleBaseImageJavaVersionException, InvalidPlatformException, InvalidContainerVolumeException, MainClassInferenceException, InvalidAppRootException, InvalidWorkingDirectoryException, InvalidFilesModificationTimeException, InvalidContainerizingModeException, ExtraDirectoryNotFoundException {
JibContainerBuilder jibContainerBuilder = processCommonConfiguration(rawConfiguration, ignored -> Optional.empty(), projectProperties);
SkaffoldSyncMapTemplate syncMap = new SkaffoldSyncMapTemplate();
// since jib has already expanded out directories after processing everything, we just
// ignore directories and provide only files to watch
Set<Path> excludesExpanded = getAllFiles(excludes);
for (LayerObject layerObject : jibContainerBuilder.toContainerBuildPlan().getLayers()) {
Verify.verify(layerObject instanceof FileEntriesLayer, "layer types other than FileEntriesLayer not yet supported in build plan layers");
FileEntriesLayer layer = (FileEntriesLayer) layerObject;
if (CONST_LAYERS.contains(layer.getName())) {
continue;
}
if (GENERATED_LAYERS.contains(layer.getName())) {
layer.getEntries().stream().filter(layerEntry -> Files.isRegularFile(layerEntry.getSourceFile())).filter(layerEntry -> !excludesExpanded.contains(layerEntry.getSourceFile().toAbsolutePath())).forEach(syncMap::addGenerated);
} else {
// this is a direct layer
layer.getEntries().stream().filter(layerEntry -> Files.isRegularFile(layerEntry.getSourceFile())).filter(layerEntry -> !excludesExpanded.contains(layerEntry.getSourceFile().toAbsolutePath())).forEach(syncMap::addDirect);
}
}
return syncMap.getJsonString();
}
use of com.google.cloud.tools.jib.api.Jib in project jib by google.
the class PluginConfigurationProcessor method computeEntrypoint.
/**
* Computes the container entrypoint.
*
* <p>Computation occurs in this order:
*
* <ol>
* <li>null (inheriting from the base image), if the user specified value is {@code INHERIT}
* <li>the user specified one, if set
* <li>for a WAR project, null (inheriting) if a custom base image is specified, and {@code
* ["java", "-jar", "/usr/local/jetty/start.jar"]} otherwise (default Jetty base image)
* <li>for a non-WAR project, by resolving the main class
* </ol>
*
* @param rawConfiguration raw configuration data
* @param projectProperties used for providing additional information
* @param jibContainerBuilder container builder
* @return the entrypoint
* @throws MainClassInferenceException if no valid main class is configured or discovered
* @throws InvalidAppRootException if {@code appRoot} value is not an absolute Unix path
* @throws InvalidContainerizingModeException if {@code containerizingMode} value is invalid
*/
@Nullable
@VisibleForTesting
static List<String> computeEntrypoint(RawConfiguration rawConfiguration, ProjectProperties projectProperties, JibContainerBuilder jibContainerBuilder) throws MainClassInferenceException, InvalidAppRootException, IOException, InvalidContainerizingModeException {
Optional<List<String>> rawEntrypoint = rawConfiguration.getEntrypoint();
List<String> rawExtraClasspath = rawConfiguration.getExtraClasspath();
boolean entrypointDefined = rawEntrypoint.isPresent() && !rawEntrypoint.get().isEmpty();
if (entrypointDefined && (rawConfiguration.getMainClass().isPresent() || !rawConfiguration.getJvmFlags().isEmpty() || !rawExtraClasspath.isEmpty() || rawConfiguration.getExpandClasspathDependencies())) {
projectProperties.log(LogEvent.warn("mainClass, extraClasspath, jvmFlags, and expandClasspathDependencies are ignored " + "when entrypoint is specified"));
}
if (projectProperties.isWarProject()) {
if (entrypointDefined) {
return rawEntrypoint.get().size() == 1 && "INHERIT".equals(rawEntrypoint.get().get(0)) ? null : rawEntrypoint.get();
}
if (rawConfiguration.getMainClass().isPresent() || !rawConfiguration.getJvmFlags().isEmpty() || !rawExtraClasspath.isEmpty() || rawConfiguration.getExpandClasspathDependencies()) {
projectProperties.log(LogEvent.warn("mainClass, extraClasspath, jvmFlags, and expandClasspathDependencies are ignored " + "for WAR projects"));
}
return rawConfiguration.getFromImage().isPresent() ? // Inherit if a custom base image.
null : Arrays.asList("java", "-jar", "/usr/local/jetty/start.jar");
}
List<String> classpath = new ArrayList<>(rawExtraClasspath);
AbsoluteUnixPath appRoot = getAppRootChecked(rawConfiguration, projectProperties);
ContainerizingMode mode = getContainerizingModeChecked(rawConfiguration, projectProperties);
switch(mode) {
case EXPLODED:
classpath.add(appRoot.resolve("resources").toString());
classpath.add(appRoot.resolve("classes").toString());
break;
case PACKAGED:
classpath.add(appRoot.resolve("classpath/*").toString());
break;
default:
throw new IllegalStateException("unknown containerizing mode: " + mode);
}
if (projectProperties.getMajorJavaVersion() >= 9 || rawConfiguration.getExpandClasspathDependencies()) {
List<Path> jars = projectProperties.getDependencies();
Map<String, Long> occurrences = jars.stream().map(path -> path.getFileName().toString()).collect(Collectors.groupingBy(filename -> filename, Collectors.counting()));
List<String> duplicates = occurrences.entrySet().stream().filter(entry -> entry.getValue() > 1).map(Map.Entry::getKey).collect(Collectors.toList());
for (Path jar : jars) {
// Handle duplicates by appending filesize to the end of the file. This renaming logic
// must be in sync with the code that does the same in the other place. See
// https://github.com/GoogleContainerTools/jib/issues/3331
String jarName = jar.getFileName().toString();
if (duplicates.contains(jarName)) {
jarName = jarName.replaceFirst("\\.jar$", "-" + Files.size(jar)) + ".jar";
}
classpath.add(appRoot.resolve("libs").resolve(jarName).toString());
}
} else {
classpath.add(appRoot.resolve("libs/*").toString());
}
String classpathString = String.join(":", classpath);
String mainClass;
try {
mainClass = MainClassResolver.resolveMainClass(rawConfiguration.getMainClass().orElse(null), projectProperties);
} catch (MainClassInferenceException ex) {
if (entrypointDefined) {
// We will use the user-given entrypoint, so don't fail.
mainClass = "could-not-infer-a-main-class";
} else {
throw ex;
}
}
addJvmArgFilesLayer(rawConfiguration, projectProperties, jibContainerBuilder, classpathString, mainClass);
if (projectProperties.getMajorJavaVersion() >= 9) {
classpathString = "@" + appRoot.resolve(JIB_CLASSPATH_FILE);
}
if (entrypointDefined) {
return rawEntrypoint.get().size() == 1 && "INHERIT".equals(rawEntrypoint.get().get(0)) ? null : rawEntrypoint.get();
}
List<String> entrypoint = new ArrayList<>(4 + rawConfiguration.getJvmFlags().size());
entrypoint.add("java");
entrypoint.addAll(rawConfiguration.getJvmFlags());
entrypoint.add("-cp");
entrypoint.add(classpathString);
entrypoint.add(mainClass);
return entrypoint;
}
use of com.google.cloud.tools.jib.api.Jib in project jib by google.
the class PluginConfigurationProcessor method getSkaffoldSyncMap.
/**
* Generate a skaffold syncmap JSON string for an image build configuration.
*
* @param rawConfiguration the raw configuration from the plugin
* @param projectProperties an plugin specific implementation of {@link ProjectProperties}
* @param excludes a set of paths to exclude, directories include in this list will be expanded
* @return new json string representation of the Sync Map
* @throws InvalidImageReferenceException if the image reference is invalid
* @throws MainClassInferenceException if a main class could not be found
* @throws InvalidAppRootException if the specific path for application root is invalid
* @throws IOException if an error occurs creating the container builder
* @throws InvalidWorkingDirectoryException if the working directory specified for the build is
* invalid
* @throws InvalidPlatformException if there exists a {@link PlatformConfiguration} in the
* specified platforms list that is missing required fields or has invalid values
* @throws InvalidContainerVolumeException if a specific container volume is invalid
* @throws IncompatibleBaseImageJavaVersionException if the base image java version cannot support
* this build
* @throws NumberFormatException if a string to number conversion operation fails
* @throws InvalidContainerizingModeException if an invalid {@link ContainerizingMode} was
* specified
* @throws InvalidFilesModificationTimeException if configured modification time could not be
* parsed
* @throws InvalidCreationTimeException if configured creation time could not be parsed
* @throws ExtraDirectoryNotFoundException if the extra directory specified for the build is not
* found
*/
public static String getSkaffoldSyncMap(RawConfiguration rawConfiguration, ProjectProperties projectProperties, Set<Path> excludes) throws IOException, InvalidCreationTimeException, InvalidImageReferenceException, IncompatibleBaseImageJavaVersionException, InvalidPlatformException, InvalidContainerVolumeException, MainClassInferenceException, InvalidAppRootException, InvalidWorkingDirectoryException, InvalidFilesModificationTimeException, InvalidContainerizingModeException, ExtraDirectoryNotFoundException {
JibContainerBuilder jibContainerBuilder = processCommonConfiguration(rawConfiguration, ignored -> Optional.empty(), projectProperties);
SkaffoldSyncMapTemplate syncMap = new SkaffoldSyncMapTemplate();
// since jib has already expanded out directories after processing everything, we just
// ignore directories and provide only files to watch
Set<Path> excludesExpanded = getAllFiles(excludes);
for (LayerObject layerObject : jibContainerBuilder.toContainerBuildPlan().getLayers()) {
Verify.verify(layerObject instanceof FileEntriesLayer, "layer types other than FileEntriesLayer not yet supported in build plan layers");
FileEntriesLayer layer = (FileEntriesLayer) layerObject;
if (CONST_LAYERS.contains(layer.getName())) {
continue;
}
if (GENERATED_LAYERS.contains(layer.getName())) {
layer.getEntries().stream().filter(layerEntry -> Files.isRegularFile(layerEntry.getSourceFile())).filter(layerEntry -> !excludesExpanded.contains(layerEntry.getSourceFile().toAbsolutePath())).forEach(syncMap::addGenerated);
} else {
// this is a direct layer
layer.getEntries().stream().filter(layerEntry -> Files.isRegularFile(layerEntry.getSourceFile())).filter(layerEntry -> !excludesExpanded.contains(layerEntry.getSourceFile().toAbsolutePath())).forEach(syncMap::addDirect);
}
}
return syncMap.getJsonString();
}
Aggregations