Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore(camel): Support system properties and envVars on Camel JBang #1256

Merged
merged 1 commit into from
Nov 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@ public class JBangSupport {

private final Map<String, String> systemProperties = new HashMap<>();

private final Map<String, String> envVars = new HashMap<>();

private String app;

/**
Expand All @@ -92,7 +94,7 @@ public static JBangSupport jbang() {
* Get JBang version.
*/
public String version() {
ProcessAndOutput p = execute(jBang("version"));
ProcessAndOutput p = execute(jBang("version"), envVars);
return p.getOutput();
}

Expand Down Expand Up @@ -122,6 +124,24 @@ public JBangSupport withSystemProperties(Map<String, String> systemProperties) {
return this;
}

/**
* Adds environment variables to command line.
* @return
*/
public JBangSupport withEnv(String name, String value) {
this.systemProperties.put(name, value);
return this;
}

/**
* Adds environment variables to command line.
* @return
*/
public JBangSupport withEnvs(Map<String, String> envVars) {
this.envVars.putAll(envVars);
return this;
}

public JBangSupport app(String name) {
this.app = name;
return this;
Expand All @@ -139,7 +159,7 @@ public ProcessAndOutput run(String command, String... args) {
* Command can be a script file or an app command.
*/
public ProcessAndOutput run(String command, List<String> args) {
return execute(jBang(systemProperties, constructAllArgs(command, args)));
return execute(jBang(systemProperties, constructAllArgs(command, args)), envVars);
}

/**
Expand Down Expand Up @@ -248,7 +268,7 @@ private static void download() {
}

private static ProcessAndOutput getVersion() {
return execute(jBang("version"));
return execute(jBang("version"), null);
}

/**
Expand All @@ -260,7 +280,7 @@ private static ProcessAndOutput getVersion() {
*/
private static void addTrust(String url) {
if (trustUrls.add(url)) {
ProcessAndOutput result = execute(jBang("trust", "add", url));
ProcessAndOutput result = execute(jBang("trust", "add", url), null);
int exitValue = result.getProcess().exitValue();
if (exitValue != OK_EXIT_CODE && exitValue != 1) {
throw new CitrusRuntimeException("Error while trusting JBang URLs. Exit code: " + exitValue);
Expand Down Expand Up @@ -321,15 +341,21 @@ private static String getSystemPropertyArgs(Map<String, String> systemProperties
* Execute JBang command using the process API. Waits for the process to complete and returns the process instance so
* caller is able to access the exit code and process output.
* @param command
* @param envVars
* @return
*/
private static ProcessAndOutput execute(List<String> command) {
private static ProcessAndOutput execute(List<String> command, Map<String, String> envVars) {
try {
LOG.info("Executing JBang command: %s".formatted(String.join(" ", command)));

Process p = new ProcessBuilder(command)
.redirectErrorStream(true)
.start();
ProcessBuilder pBuilder = new ProcessBuilder(command)
.redirectErrorStream(true);

if (envVars != null && !envVars.isEmpty()) {
pBuilder.environment().putAll(envVars);
}

Process p = pBuilder.start();

String output = FileUtils.readToString(p.getInputStream(), StandardCharsets.UTF_8);
p.waitFor();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

import org.citrusframework.camel.jbang.CamelJBangSettings;
import org.citrusframework.context.TestContext;
Expand All @@ -33,6 +36,8 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import static org.citrusframework.camel.dsl.CamelSupport.camel;

/**
* Runs given Camel integration with Camel JBang tooling.
*/
Expand All @@ -50,6 +55,14 @@ public class CamelRunIntegrationAction extends AbstractCamelJBangAction {
/** Source code to run as a Camel integration */
private final String sourceCode;

/** Environment variables set on the Camel JBang process */
private final Map<String, String> envVars;

/** System properties set on the Camel JBang process */
private final Map<String, String> systemProperties;

private final boolean autoRemoveResources;

/**
* Default constructor.
*/
Expand All @@ -59,6 +72,9 @@ public CamelRunIntegrationAction(Builder builder) {
this.integrationName = builder.integrationName;
this.integrationResource = builder.integrationResource;
this.sourceCode = builder.sourceCode;
this.envVars = builder.envVars;
this.systemProperties = builder.systemProperties;
this.autoRemoveResources = builder.autoRemoveResources;
}

@Override
Expand All @@ -83,6 +99,9 @@ public void doExecute(TestContext context) {
throw new CitrusRuntimeException("Missing Camel integration source code or file");
}

camelJBang().camelApp().withEnvs(context.resolveDynamicValuesInMap(envVars));
camelJBang().camelApp().withSystemProperties(context.resolveDynamicValuesInMap(systemProperties));

ProcessAndOutput pao = camelJBang().run(name, integrationToRun);

if (!pao.getProcess().isAlive()) {
Expand All @@ -97,6 +116,12 @@ public void doExecute(TestContext context) {
context.setVariable(name + ":process:" + pid, pao);

logger.info("Started Camel integration '%s' (%s)".formatted(name, pid));

if (autoRemoveResources) {
context.doFinally(camel()
.jbang()
.stop(name));
}
} catch (IOException e) {
throw new CitrusRuntimeException("Failed to create temporary file from Camel integration");
}
Expand Down Expand Up @@ -133,6 +158,13 @@ public static final class Builder extends AbstractCamelJBangAction.Builder<Camel
private String integrationName = "route";
private Resource integrationResource;

private final Map<String, String> envVars = new HashMap<>();
private Resource envVarsFile;
private final Map<String, String> systemProperties = new HashMap<>();
private Resource systemPropertiesFile;

private boolean autoRemoveResources = CamelJBangSettings.isAutoRemoveResources();

/**
* Runs Camel integration from given source code.
* @param sourceCode
Expand Down Expand Up @@ -178,8 +210,95 @@ public Builder integrationName(String name) {
return this;
}

/**
* Adds an environment variable.
* @param key
* @param value
* @return
*/
public Builder withEnv(String key, String value) {
this.envVars.put(key, value);
return this;
}

/**
* Adds environment variables.
* @param envVars
* @return
*/
public Builder withEnvs(Map<String, String> envVars) {
this.envVars.putAll(envVars);
return this;
}

/**
* Adds environment variables from given file resource.
* @param envVarsFile
* @return
*/
public Builder withEnvs(Resource envVarsFile) {
this.envVarsFile = envVarsFile;
return this;
}

/**
* Adds a system properties.
* @param key
* @param value
* @return
*/
public Builder withSystemProperty(String key, String value) {
this.systemProperties.put(key, value);
return this;
}

/**
* Adds system properties.
* @param systemProperties
* @return
*/
public Builder withSystemProperties(Map<String, String> systemProperties) {
this.systemProperties.putAll(systemProperties);
return this;
}

/**
* Adds system properties from given file resource.
* @param systemPropertiesFile
* @return
*/
public Builder withSystemProperties(Resource systemPropertiesFile) {
this.systemPropertiesFile = systemPropertiesFile;
return this;
}

public Builder autoRemove(boolean enabled) {
this.autoRemoveResources = enabled;
return this;
}

@Override
public CamelRunIntegrationAction build() {
if (systemPropertiesFile != null) {
Properties props = new Properties();
try {
props.load(systemPropertiesFile.getInputStream());
props.forEach((k, v) -> withSystemProperty(k.toString(), v.toString()));
} catch (IOException e) {
throw new CitrusRuntimeException("Failed to read properties file", e);
}
}

if (envVarsFile != null) {
Properties props = new Properties();
try {
props.load(envVarsFile.getInputStream());
props.forEach((k, v) -> withEnv(k.toString(), v.toString()));
} catch (IOException e) {
throw new CitrusRuntimeException("Failed to read properties file", e);
}
}

return new CamelRunIntegrationAction(this);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@

public final class CamelJBangSettings {

private static final String JBANG_PROPERTY_PREFIX = "citrus.jbang.camel.";
private static final String JBANG_ENV_PREFIX = "CITRUS_JBANG_CAMEL_";
private static final String JBANG_PROPERTY_PREFIX = "citrus.camel.jbang.";
private static final String JBANG_ENV_PREFIX = "CITRUS_CAMEL_JBANG_";

private static final String WORK_DIR_PROPERTY = JBANG_PROPERTY_PREFIX + "work.dir";
private static final String WORK_DIR_ENV = JBANG_ENV_PREFIX + "WORK_DIR";
Expand Down Expand Up @@ -54,6 +54,10 @@ public final class CamelJBangSettings {
private static final String CAMEL_DUMP_INTEGRATION_OUTPUT_ENV = JBANG_ENV_PREFIX + "DUMP_INTEGRATION_OUTPUT";
private static final String CAMEL_DUMP_INTEGRATION_OUTPUT_DEFAULT = "false";

private static final String AUTO_REMOVE_RESOURCES_PROPERTY = JBANG_PROPERTY_PREFIX + "auto.remove.resources";
private static final String AUTO_REMOVE_RESOURCES_ENV = JBANG_ENV_PREFIX + "AUTO_REMOVE_RESOURCES";
private static final String AUTO_REMOVE_RESOURCES_DEFAULT = "false";

private CamelJBangSettings() {
// prevent instantiation of utility class
}
Expand Down Expand Up @@ -138,4 +142,15 @@ public static String getKameletsVersion() {
System.getenv(KAMELETS_VERSION_ENV) != null ? System.getenv(KAMELETS_VERSION_ENV) : KAMELETS_VERSION_DEFAULT);
}

/**
* When set to true Camel JBang resources created during the test are
* automatically removed after the test.
* @return
*/
public static boolean isAutoRemoveResources() {
return Boolean.parseBoolean(System.getProperty(AUTO_REMOVE_RESOURCES_PROPERTY,
System.getenv(AUTO_REMOVE_RESOURCES_ENV) != null ? System.getenv(AUTO_REMOVE_RESOURCES_ENV) : AUTO_REMOVE_RESOURCES_DEFAULT));
}


}
Original file line number Diff line number Diff line change
Expand Up @@ -149,14 +149,38 @@ public Camel setJBang(JBang jbang) {
CamelRunIntegrationAction.Builder builder = new CamelRunIntegrationAction.Builder()
.integrationName(jbang.getRun().getIntegration().getName());

if (jbang.getRun().getIntegration().getSourceCode() != null) {
builder.integration(jbang.getRun().getIntegration().getSourceCode());
if (jbang.getRun().getIntegration().getSource() != null) {
builder.integration(jbang.getRun().getIntegration().getSource());
}

builder.autoRemove(jbang.getRun().getIntegration().isAutoRemove());

if (jbang.getRun().getIntegration().getFile() != null) {
builder.integration(Resources.create(jbang.getRun().getIntegration().getFile()));
}

if (jbang.getRun().getIntegration().getSystemProperties() != null) {
if (jbang.getRun().getIntegration().getSystemProperties().getFile() != null) {
builder.withSystemProperties(Resources.create(
jbang.getRun().getIntegration().getSystemProperties().getFile()));
}

jbang.getRun().getIntegration().getSystemProperties()
.getProperties()
.forEach(property -> builder.withSystemProperty(property.getName(), property.getValue()));
}

if (jbang.getRun().getIntegration().getEnvironment() != null) {
if (jbang.getRun().getIntegration().getEnvironment().getFile() != null) {
builder.withEnvs(Resources.create(
jbang.getRun().getIntegration().getEnvironment().getFile()));
}

jbang.getRun().getIntegration().getEnvironment()
.getVariables()
.forEach(variable -> builder.withEnv(variable.getName(), variable.getValue()));
}

this.builder = builder;
} else if (jbang.getStop() != null) {
CamelStopIntegrationAction.Builder builder = new CamelStopIntegrationAction.Builder()
Expand Down
Loading
Loading