Skip to content

Commit

Permalink
Merge pull request #14 from jfdenise/cli-v2
Browse files Browse the repository at this point in the history
Advertise all env variables in strongly suggested section
  • Loading branch information
jfdenise authored Oct 20, 2023
2 parents ac79675 + e1b39a7 commit a59ffea
Show file tree
Hide file tree
Showing 10 changed files with 224 additions and 58 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
target
cli/dependency-reduced-pom.xml
tests/.env

# Intellij
*.iml
Expand Down
107 changes: 80 additions & 27 deletions cli/src/main/java/org/wildfly/glow/cli/commands/ScanCommand.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,18 +26,19 @@
import org.wildfly.glow.Arguments;
import static org.wildfly.glow.Arguments.CLOUD_EXECUTION_CONTEXT;
import static org.wildfly.glow.Arguments.COMPACT_PROPERTY;
import org.wildfly.glow.DockerSupport;
import org.wildfly.glow.FeaturePacks;
import org.wildfly.glow.GlowMessageWriter;
import org.wildfly.glow.GlowSession;
import org.wildfly.glow.HiddenPropertiesAccessor;
import org.wildfly.glow.OutputContent;
import org.wildfly.glow.OutputFormat;
import static org.wildfly.glow.OutputFormat.BOOTABLE_JAR;
import static org.wildfly.glow.OutputFormat.DOCKER_IMAGE;
import static org.wildfly.glow.OutputFormat.PROVISIONING_XML;
import static org.wildfly.glow.OutputFormat.SERVER;
import org.wildfly.glow.ScanArguments.Builder;
import org.wildfly.glow.ScanResults;
import org.wildfly.glow.error.IdentifiedError;
import org.wildfly.glow.maven.MavenResolver;

import picocli.CommandLine;
Expand All @@ -49,6 +50,10 @@
)
public class ScanCommand extends AbstractCommand {

private static final String ADD_ADD_ONS_MSG="@|bold To enable add-ons add the|@ @|fg(yellow) " +
Constants.ADD_ONS_OPTION + "=<list of add-ons>|@ @|bold option to the|@ @|fg(yellow) " +
Constants.SCAN_COMMAND + "|@ @|bold command|@";

@CommandLine.Option(names = {Constants.CLOUD_OPTION_SHORT, Constants.CLOUD_OPTION})
Optional<Boolean> cloud;

Expand Down Expand Up @@ -140,58 +145,106 @@ public Integer call() throws Exception {
if (!compact) {
if (suggest.orElse(false)) {
if (!scanResults.getSuggestions().getPossibleAddOns().isEmpty() && addOns.isEmpty()) {
print("@|bold To enable add-ons add the|@ @|fg(yellow) %s=<list of add-ons>|@ @|bold option to the|@ @|fg(yellow) %s|@ @|bold command|@", Constants.ADD_ONS_OPTION, Constants.SCAN_COMMAND);
print(ADD_ADD_ONS_MSG);
}
if (!scanResults.getSuggestions().getPossibleProfiles().isEmpty()) {
print("@|bold To enable the HA profile add the|@ @|fg(yellow) %s|@ @|bold option to the|@ @|fg(yellow) %s|@ @|bold command|@", Constants.HA_OPTION, Constants.SCAN_COMMAND);
}
}
print("@|bold To provision the WildFly server for your deployment add the|@ @|fg(yellow) %s=SERVER|@ @|bold option to the|@ @|fg(yellow) %s|@ @|bold command|@", Constants.PROVISION_OPTION, Constants.SCAN_COMMAND);
if (scanResults.getErrorSession().hasErrors()) {
if (!suggest.orElse(false)) {
boolean hasAddOn = false;
// Do we have errors and add-ons to set?
for(IdentifiedError err : scanResults.getErrorSession().getErrors()) {
if (!err.getPossibleAddons().isEmpty()) {
hasAddOn = true;
break;
}
}
if (hasAddOn) {
System.out.println(CommandLine.Help.Ansi.AUTO.string(ADD_ADD_ONS_MSG));
}
}
print("@|bold Some errors have been reported, you should fix them prior to provision a server with the|@ @|fg(yellow) " + Constants.PROVISION_OPTION + "=SERVER|@ @|bold option of the|@ @|fg(yellow) " + Constants.SCAN_COMMAND + "|@ @|bold command|@");
} else {
print("@|bold To provision the WildFly server for your deployment add the|@ @|fg(yellow) " + Constants.PROVISION_OPTION + "=SERVER|@ @|bold option to the|@ @|fg(yellow) " + Constants.SCAN_COMMAND + "|@ @|bold command|@");
}
}
} else {
print();
Path target = null;
String vers = wildflyServerVersion.orElse(null) == null ? FeaturePacks.getLatestVersion() : wildflyServerVersion.get();
String doneMessage = null;
Path target = Paths.get("server-" + vers);
switch (provision.get()) {
case BOOTABLE_JAR: {
target = Paths.get("");
print("@|bold Building WildFly Bootable JAR file|@");
print("@|bold Building WildFly Bootable JAR file...|@");
break;
}
case PROVISIONING_XML: {
target = Paths.get("server-" + vers);
print("@|bold Generating provisioning configuration in %s/provisioning.xml file|@", target);
doneMessage = "@|bold Generation DONE. Provisioning configuration is located in " + target + "/provisioning.xml file|@";
print("@|bold Generating Galleon provisioning configuration file...|@");
break;
}
case SERVER: {
target = Paths.get("server-" + vers);
print("@|bold Provisioning server in %s directory|@", target);
if (cloud.orElse(false)) {
doneMessage = "@|bold Provisioning DONE. To run the server: 'JBOSS_HOME=" + target + " sh " + target + "/bin/openshift-launch.sh'|@";
} else {
doneMessage = "@|bold Provisioning DONE. To run the server: 'sh " + target + "/bin/standalone.sh'|@";
}
print("@|bold Provisioning server...|@", target);
break;
}
case DOCKER_IMAGE: {
target = Paths.get("server-" + vers);
String imageName = dockerImageName.isPresent()? dockerImageName.get() : DockerSupport.getImageName(target.toString());
print("@|bold Generating docker image '%s'|@", imageName);
doneMessage = "@|bold To run the image call: 'docker run " + imageName + "'|@";
print("@|bold Generating docker image...|@");
break;
}
}
Path actualTarget = scanResults.outputConfig(target, dockerImageName.orElse(null));
if (BOOTABLE_JAR.equals(provision.get())) {
doneMessage = "@|bold Bootable JAR build DONE. To run the jar: 'java -jar " + actualTarget + "'|@";
} else {
if (DOCKER_IMAGE.equals(provision.get())) {
print("@|bold Image generation DONE. Docker file generated in %s|@.", actualTarget.toAbsolutePath());
OutputContent content = scanResults.outputConfig(target, dockerImageName.orElse(null));
Path base = Paths.get("").toAbsolutePath();
for (OutputContent.OutputFile f : content.getFiles().keySet()) {
Path rel = base.relativize(content.getFiles().get(f));
switch (f) {
case BOOTABLE_JAR_FILE: {
print("@|bold Bootable JAR build DONE.|@");
print("@|bold To run the jar call: 'java -jar " + rel + "'|@");
break;
}
case DOCKER_FILE: {
print("@|bold Image generation DONE.|@.");
print("@|bold Docker file generated in %s|@.", rel);
break;
}
case ENV_FILE: {
print("@|bold The file " + rel + " contains the list of environment variables that you must set prior to start the server.|@");
switch (provision.get()) {
case SERVER: {
print("@|bold Export the suggested env variables for the server to take them into account.|@");
break;
}
case BOOTABLE_JAR: {
print("@|bold Export the suggested env variables for the bootable JAR to take them into account.|@");
break;
}
case DOCKER_IMAGE: {
print("@|bold For each env variable add `-e <env name>=<env value>` to the `docker run` command.|@");
break;
}
}
break;
}
case PROVISIONING_XML_FILE: {
print("@|bold Generation DONE.|@");
print("@|bold Galleon Provisioning configuration is located in " + rel + " file|@");
break;
}
case SERVER_DIR: {
print("@|bold Provisioning DONE.|@");
if (cloud.orElse(false)) {
print("@|bold To run the server call: 'JBOSS_HOME=" + rel + " sh " + rel + "/bin/openshift-launch.sh'|@");
} else {
print("@|bold To run the server call: 'sh " + rel + "/bin/standalone.sh'|@");
}
break;
}
}
}
print(doneMessage);
if (content.getDockerImageName() != null) {
print("@|bold To run the image call: 'docker run " + content.getDockerImageName() + "'|@");
}
}
return 0;
}
Expand Down
67 changes: 47 additions & 20 deletions core/src/main/java/org/wildfly/glow/GlowSession.java
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;
import static org.wildfly.glow.OutputFormat.BOOTABLE_JAR;
import static org.wildfly.glow.OutputFormat.DOCKER_IMAGE;

import static org.wildfly.glow.error.ErrorLevel.ERROR;

Expand Down Expand Up @@ -426,7 +428,15 @@ public ScanResults scan() throws Exception {
}
// END cleanup

errorSession.refreshErrors(allBaseLayers, mapping, allEnabledAddOns);
Map<Layer, Set<Env>> stronglySuggestConfigFixes = errorSession.refreshErrors(allBaseLayers, mapping, allEnabledAddOns);
for(Layer l : stronglySuggestConfigFixes.keySet()) {
Set<Env> envs = stronglySuggestedConfigurations.get(l);
if(envs == null) {
envs = new TreeSet<>();
stronglySuggestedConfigurations.put(l, envs);
}
envs.addAll(stronglySuggestConfigFixes.get(l));
}
// Identify the active feature-packs.
ProvisioningConfig activeConfig = buildProvisioningConfig(pConfig, layout,
universeResolver, allBaseLayers, baseLayer, decorators, excludedLayers, fpDependencies, arguments.getConfigName());
Expand All @@ -451,39 +461,53 @@ public ScanResults scan() throws Exception {
}
}

Path outputConfig(ScanResults scanResults, Path target, String dockerImageName) throws Exception {
OutputContent outputConfig(ScanResults scanResults, Path target, String dockerImageName) throws Exception {
if (arguments.getOutput() == null) {
throw new IllegalStateException("No output format set");
}
Path ret = null;
if (OutputFormat.DOCKER_IMAGE.equals(arguments.getOutput()) || OutputFormat.SERVER.equals(arguments.getOutput()) || OutputFormat.BOOTABLE_JAR.equals(arguments.getOutput())) {
Map<OutputContent.OutputFile, Path> files = new HashMap<>();
if (!OutputFormat.PROVISIONING_XML.equals(arguments.getOutput())) {
if (scanResults.getErrorSession().hasErrors()) {
writer.warn("You are provisioning a server although some errors still exist. You should first fix them.");
}
Path generatedArtifact = provisionServer(arguments.getBinaries(),
scanResults.getProvisioningConfig(), resolver, arguments.getOutput(),
arguments.isCloud(), target);
if (OutputFormat.DOCKER_IMAGE.equals(arguments.getOutput())) {
// generate docker image
String imageName = dockerImageName == null ? DockerSupport.getImageName(generatedArtifact.getFileName().toString()) : dockerImageName;
ret = DockerSupport.buildApplicationImage(imageName, generatedArtifact, arguments, writer);
switch (arguments.getOutput()) {
case DOCKER_IMAGE: {
// generate docker image
dockerImageName = dockerImageName == null ? DockerSupport.getImageName(generatedArtifact.getFileName().toString()) : dockerImageName;
Path origDockerFile = DockerSupport.buildApplicationImage(dockerImageName, generatedArtifact, arguments, writer);
IoUtils.recursiveDelete(generatedArtifact);
Files.createDirectories(target);
Path dockerFile = target.resolve("Dockerfile");
Files.copy(origDockerFile, dockerFile);
Files.delete(origDockerFile);
files.put(OutputContent.OutputFile.DOCKER_FILE,dockerFile.toAbsolutePath());
break;
}
case BOOTABLE_JAR: {
files.put(OutputContent.OutputFile.BOOTABLE_JAR_FILE, generatedArtifact.toAbsolutePath());
break;
}
case SERVER: {
files.put(OutputContent.OutputFile.SERVER_DIR, generatedArtifact.toAbsolutePath());
break;
}
}
IoUtils.recursiveDelete(generatedArtifact);
} else {
if (OutputFormat.PROVISIONING_XML.equals(arguments.getOutput())) {
IoUtils.recursiveDelete(target);
Files.createDirectories(target);
ret = target.resolve("provisioning.xml");
try (FileWriter fileWriter = new FileWriter(ret.toFile())) {
ProvisioningXmlWriter.getInstance().write(scanResults.getProvisioningConfig(), fileWriter);
}
IoUtils.recursiveDelete(target);
Files.createDirectories(target);
Path prov = target.resolve("provisioning.xml");
try (FileWriter fileWriter = new FileWriter(prov.toFile())) {
ProvisioningXmlWriter.getInstance().write(scanResults.getProvisioningConfig(), fileWriter);
}
files.put(OutputContent.OutputFile.PROVISIONING_XML_FILE, prov.toAbsolutePath());
}
StringBuilder envFileContent = new StringBuilder();
if (!scanResults.getSuggestions().getStronglySuggestedConfigurations().isEmpty() ||
(arguments.isSuggest() && !scanResults.getSuggestions().getSuggestedConfigurations().isEmpty())) {
envFileContent.append("Environment variables for ").
append(arguments.getExecutionContext()).append(" execution context.").append(System.lineSeparator());
envFileContent.append("Environment variables to set. ").append(System.lineSeparator());
}
if (!scanResults.getSuggestions().getStronglySuggestedConfigurations().isEmpty()) {
envFileContent.append(buildEnvs(scanResults.getSuggestions().
Expand All @@ -494,11 +518,14 @@ Path outputConfig(ScanResults scanResults, Path target, String dockerImageName)
getSuggestedConfigurations(), false)).append(System.lineSeparator());
}
if (envFileContent.length() != 0) {
if (!Files.exists(target)) {
Files.createDirectories(target);
}
Path p = target.resolve("configuration.env");
writer.info("The file " + p + " contains the environment variables to set in a " + arguments.getExecutionContext() + " context");
Files.write(p, envFileContent.toString().getBytes());
files.put(OutputContent.OutputFile.ENV_FILE, p.toAbsolutePath());
}
return ret;
return new OutputContent(files, dockerImageName);
}

private String buildEnvs(Map<Layer, Set<Env>> map, boolean isRequired) {
Expand Down
43 changes: 43 additions & 0 deletions core/src/main/java/org/wildfly/glow/OutputContent.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/*
* Click nbfs://nbhost/SystemFileSystem/Templates/Licenses/license-default.txt to change this license
* Click nbfs://nbhost/SystemFileSystem/Templates/Classes/Class.java to edit this template
*/
package org.wildfly.glow;

import java.nio.file.Path;
import java.util.Map;

/**
*
* @author jdenise
*/
public class OutputContent {
public enum OutputFile {
BOOTABLE_JAR_FILE,
DOCKER_FILE,
SERVER_DIR,
PROVISIONING_XML_FILE,
ENV_FILE
}

private final Map<OutputFile, Path> files;
private final String dockerImageName;
OutputContent(Map<OutputFile, Path> files, String dockerImageName) {
this.files = files;
this.dockerImageName = dockerImageName;
}

/**
* @return the files
*/
public Map<OutputFile, Path> getFiles() {
return files;
}

/**
* @return the dockerImageName
*/
public String getDockerImageName() {
return dockerImageName;
}
}
2 changes: 1 addition & 1 deletion core/src/main/java/org/wildfly/glow/ScanResults.java
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ public Set<AddOn> getEnabledAddOns() {
return enabledAddOns;
}

public Path outputConfig(Path target, String dockerImageName) throws Exception {
public OutputContent outputConfig(Path target, String dockerImageName) throws Exception {
return glowSession.outputConfig(this, target, dockerImageName);
}

Expand Down
17 changes: 11 additions & 6 deletions core/src/main/java/org/wildfly/glow/ScanResultsPrinter.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import java.io.IOException;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
Expand Down Expand Up @@ -166,12 +167,13 @@ private void detailed(ScanArguments arguments, ScanResults scanResults) throws E
for(Map.Entry<Layer, Set<Env>> entry : scanResults.getSuggestions().getStronglySuggestedConfigurations().entrySet()) {
writer.warn(buildSuggestions(entry.getKey(), entry.getValue()));
}
writer.warn("");
}

writer.info("suggestions");
String suggestedConfigs = buildSuggestions(scanResults.getSuggestions().getSuggestedConfigurations());

if (arguments.isSuggest()) {
writer.info("suggestions");
if (scanResults.getSuggestions().getPossibleAddOns().isEmpty() && scanResults.getSuggestions().getPossibleProfiles().isEmpty() && suggestedConfigs.isEmpty()) {
writer.info("none");
} else {
Expand Down Expand Up @@ -211,9 +213,7 @@ private void detailed(ScanArguments arguments, ScanResults scanResults) throws E
}
} else {
if (!scanResults.getSuggestions().getPossibleAddOns().isEmpty() || !scanResults.getSuggestions().getPossibleAddOns().isEmpty() || !suggestedConfigs.isEmpty()) {
writer.info("some suggestions have been found. You could enable suggestions with --suggest option.");
} else {
writer.info("none");
writer.info("Some suggestions have been found. You could enable suggestions with --suggest option.");
}
}
}
Expand All @@ -229,8 +229,13 @@ private static String buildSuggestions(Map<Layer, Set<Env>> map) throws URISynta
private static String buildSuggestions(Layer layer, Set<Env> envs) throws URISyntaxException, IOException {
StringBuilder suggestedConfigsBuilder = new StringBuilder();
suggestedConfigsBuilder.append("\n").append(layer.getName()).append(":\n");
for (Env e : envs) {
suggestedConfigsBuilder.append(" - ").append(e.getName()).append("=").append(e.getDescription()).append("\n");
Iterator<Env> it = envs.iterator();
while (it.hasNext()) {
Env e = it.next();
suggestedConfigsBuilder.append(" - ").append(e.getName()).append("=").append(e.getDescription());
if (it.hasNext()) {
suggestedConfigsBuilder.append("\n");
}
}
return suggestedConfigsBuilder.toString();
}}
Loading

0 comments on commit a59ffea

Please sign in to comment.