diff --git a/prospero-cli/pom.xml b/prospero-cli/pom.xml index 058f73e52..b4c05eced 100644 --- a/prospero-cli/pom.xml +++ b/prospero-cli/pom.xml @@ -13,6 +13,12 @@ jar + + + com.google.cloud.tools + jib-core + 0.27.1 + com.fasterxml.jackson.dataformat jackson-dataformat-yaml diff --git a/prospero-cli/src/main/java/org/wildfly/prospero/cli/CliMain.java b/prospero-cli/src/main/java/org/wildfly/prospero/cli/CliMain.java index 7b07049d5..1ec78021d 100644 --- a/prospero-cli/src/main/java/org/wildfly/prospero/cli/CliMain.java +++ b/prospero-cli/src/main/java/org/wildfly/prospero/cli/CliMain.java @@ -22,6 +22,7 @@ import org.jboss.logmanager.Level; import org.jboss.logmanager.PropertyConfigurator; import org.jboss.logmanager.config.LogContextConfiguration; +import org.wildfly.prospero.cli.commands.BuildImageCommand; import org.wildfly.prospero.cli.commands.ChannelCommand; import org.wildfly.prospero.cli.commands.CliConstants; import org.wildfly.prospero.cli.commands.CloneCommand; @@ -86,6 +87,8 @@ public static CommandLine createCommandLine(CliConsole console, String[] args, A commandLine.addSubcommand(new ChannelCommand(console, actionFactory)); commandLine.addSubcommand(new CompletionCommand()); + commandLine.addSubcommand(new BuildImageCommand(console, actionFactory)); + CommandLine channelCmd = commandLine.getSubcommands().get(CliConstants.Commands.CHANNEL); channelCmd.addSubcommand(new ChannelAddCommand(console, actionFactory)); channelCmd.addSubcommand(new ChannelRemoveCommand(console, actionFactory)); diff --git a/prospero-cli/src/main/java/org/wildfly/prospero/cli/commands/BuildImageCommand.java b/prospero-cli/src/main/java/org/wildfly/prospero/cli/commands/BuildImageCommand.java new file mode 100644 index 000000000..e13f403cb --- /dev/null +++ b/prospero-cli/src/main/java/org/wildfly/prospero/cli/commands/BuildImageCommand.java @@ -0,0 +1,97 @@ +/* + * Copyright 2022 Red Hat, Inc. and/or its affiliates + * and other contributors as indicated by the @author tags. + * + * 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 org.wildfly.prospero.cli.commands; + +import static com.google.cloud.tools.jib.api.buildplan.FileEntriesLayer.DEFAULT_MODIFICATION_TIME_PROVIDER; + +import java.nio.file.Path; +import java.util.Optional; + +import com.google.cloud.tools.jib.api.Containerizer; +import com.google.cloud.tools.jib.api.Jib; +import com.google.cloud.tools.jib.api.RegistryImage; +import com.google.cloud.tools.jib.api.buildplan.AbsoluteUnixPath; +import com.google.cloud.tools.jib.api.buildplan.FileEntriesLayer; +import com.google.cloud.tools.jib.api.buildplan.FilePermissions; +import com.google.cloud.tools.jib.api.buildplan.FilePermissionsProvider; +import com.google.cloud.tools.jib.api.buildplan.OwnershipProvider; +import org.jboss.logging.Logger; +import org.wildfly.prospero.cli.ActionFactory; +import org.wildfly.prospero.cli.CliConsole; +import org.wildfly.prospero.cli.ReturnCodes; +import picocli.CommandLine; + +@CommandLine.Command( + name = CliConstants.Commands.BUILD_IMAGE, + sortOptions = false +) +public class BuildImageCommand extends AbstractCommand { + + private static final Logger log = Logger.getLogger(BuildImageCommand.class); + + @CommandLine.Option(names = CliConstants.NAME) + String name; + + @CommandLine.Option(names = CliConstants.DIR) + Optional directory; + + @CommandLine.Option(names = CliConstants.USER) + Optional user; + + @CommandLine.Option(names = CliConstants.PASSWORD) + Optional password; + + @CommandLine.Option(names = CliConstants.RUNTIME_VERSION) + Optional runtimeVersion; + + private static final FilePermissionsProvider PERMISSIONS_PROVIDER = (sourcePath, destinationPath) -> FilePermissions.fromOctalString("775"); + + private static final OwnershipProvider JBOSS_ROOT_OWNER = (sourcePath, destinationPath) -> "jboss:root"; + + public BuildImageCommand(CliConsole console, ActionFactory actionFactory) { + super(console, actionFactory); + } + + @Override + public Integer call() throws Exception { + Path installationDirectory = determineInstallationDirectory(directory); + + String baseImage = "quay.io/wildfly/wildfly-runtime:" + runtimeVersion.orElse("latest"); + System.out.println("Creating image with installation at " + installationDirectory + " from " + baseImage); + + RegistryImage registryImage = RegistryImage.named(name); + if (user.isPresent() && password.isPresent()) { + registryImage.addCredential(user.get(), password.get()); + } + + FileEntriesLayer layer = FileEntriesLayer.builder() + .setName("wildfly") + .addEntryRecursive(installationDirectory, AbsoluteUnixPath.get("/opt/server/"), + PERMISSIONS_PROVIDER, + DEFAULT_MODIFICATION_TIME_PROVIDER, + JBOSS_ROOT_OWNER) + .build(); + + Jib.from(baseImage) + .addFileEntriesLayer(layer) + .containerize(Containerizer.to(registryImage)); + + return ReturnCodes.SUCCESS; + } + +} diff --git a/prospero-cli/src/main/java/org/wildfly/prospero/cli/commands/CliConstants.java b/prospero-cli/src/main/java/org/wildfly/prospero/cli/commands/CliConstants.java index 6fa3b30e4..3f6659874 100644 --- a/prospero-cli/src/main/java/org/wildfly/prospero/cli/commands/CliConstants.java +++ b/prospero-cli/src/main/java/org/wildfly/prospero/cli/commands/CliConstants.java @@ -38,6 +38,7 @@ private Commands() { public static final String APPLY = "apply"; public static final String CHANNEL = "channel"; public static final String CLONE = "clone"; + public static final String BUILD_IMAGE = "build-image"; public static final String CUSTOMIZATION_INIT_CHANNEL = "init"; public static final String CUSTOMIZATION_INITIALIZE_CHANNEL = "initialize"; public static final String CUSTOMIZATION_PROMOTE = "promote"; @@ -80,8 +81,10 @@ private Commands() { public static final String LAYERS = "--layers"; public static final String LIST_PROFILES = "--list-profiles"; public static final String LOCAL_CACHE = "--local-cache"; + public static final String NAME = "--name"; public static final String OFFLINE = "--offline"; public static final String PACKAGE_STABILITY_LEVEL = "--package-stability-level"; + public static final String PASSWORD = "--password"; public static final String PATH = ""; public static final String PRODUCT = "--product"; public static final String PROFILE = "--profile"; @@ -90,10 +93,12 @@ private Commands() { public static final String REPO_URL = ""; public static final String REPOSITORIES = "--repositories"; public static final String REVISION = "--revision"; + public static final String RUNTIME_VERSION = "--runtime-version"; public static final String SELF = "--self"; public static final String SHADE_REPOSITORIES = "--shade-repositories"; public static final String STABILITY_LEVEL = "--stability-level"; public static final String USE_LOCAL_MAVEN_CACHE = "--use-default-local-cache"; + public static final String USER = "--user"; public static final String TARGET_CONFIG = "--target-config"; public static final String V = "-v"; public static final String VERBOSE = "--verbose";