Skip to content

Commit

Permalink
feat(dsl): camel jbang export property
Browse files Browse the repository at this point in the history
You can now use `camel export --property xyz=abc`

Closes CAMEL-21645
  • Loading branch information
squakez committed Jan 23, 2025
1 parent de39c53 commit c6367e3
Show file tree
Hide file tree
Showing 7 changed files with 180 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,7 @@ protected Integer export(ExportBaseCommand cmd) throws Exception {
cmd.excludes = this.excludes;
cmd.ignoreLoadingError = this.ignoreLoadingError;
cmd.lazyBean = this.lazyBean;
cmd.applicationProperties = this.applicationProperties;
// run export
return cmd.export();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,10 @@ public abstract class ExportBaseCommand extends CamelCommand {
description = "Maven/Gradle build properties, ex. --build-property=prop1=foo")
protected List<String> buildProperties = new ArrayList<>();

@CommandLine.Option(names = { "--property" },
description = "Camel application properties, ex. --property=prop1=foo")
String[] applicationProperties;

@CommandLine.Option(names = { "--logging" }, defaultValue = "false",
description = "Can be used to turn on logging (logs to file in <user home>/.camel directory)")
protected boolean logging;
Expand Down Expand Up @@ -328,6 +332,8 @@ protected Integer runSilently(boolean ignoreLoadingError, boolean lazyBean) thro
run.localKameletDir = localKameletDir;
run.ignoreLoadingError = ignoreLoadingError;
run.lazyBean = lazyBean;
run.property = applicationProperties;

return run.runExport(ignoreLoadingError);
}

Expand Down Expand Up @@ -699,6 +705,10 @@ protected void copySettingsAndProfile(
customize.apply(prop2);
}

// User properties
Properties prop3 = new CamelCaseOrderedProperties();
prepareUserProperties(prop3);

FileOutputStream fos = new FileOutputStream(new File(targetDir, "application.properties"), false);
try {
for (Map.Entry<Object, Object> entry : prop2.entrySet()) {
Expand Down Expand Up @@ -727,14 +737,37 @@ protected void copySettingsAndProfile(
fos.write("\n".getBytes(StandardCharsets.UTF_8));
}
}
for (Map.Entry<Object, Object> entryUserProp : prop3.entrySet()) {
String uK = entryUserProp.getKey().toString();
String uV = entryUserProp.getValue().toString();
String line = applicationPropertyLine(uK, uV);
if (line != null && !line.isBlank()) {
fos.write(line.getBytes(StandardCharsets.UTF_8));
fos.write("\n".getBytes(StandardCharsets.UTF_8));
}
}
}
} finally {
IOHelper.close(fos);
}
}

protected void prepareApplicationProperties(Properties properties) {
// noop
// NOOP
}

protected void prepareUserProperties(Properties properties) {
if (this.applicationProperties != null) {
for (String s : this.applicationProperties) {
String[] kv = s.split("=");
if (kv.length != 2) {
// likely a user mistake, we warn the user
printer().println("WARN: property '" + s + "'' has a bad format (should be 'key=value'), skipping.");
} else {
properties.put(kv[0], kv[1]);
}
}
}
}

// Returns true if it has either an openapi spec or it uses contract-first DSL
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,7 @@ public Integer export() throws Exception {

@Override
protected void prepareApplicationProperties(Properties properties) {
super.prepareApplicationProperties(properties);
// quarkus native compilation only works if we specify each resource explicit

StringJoiner sj = new StringJoiner(",");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -951,6 +951,7 @@ protected int runQuarkus() throws Exception {
eq.loggingLevel = "off";
eq.ignoreLoadingError = this.ignoreLoadingError;
eq.lazyBean = this.lazyBean;
eq.applicationProperties = this.property;

printer().println("Running using Quarkus v" + eq.quarkusVersion + " (preparing and downloading files)");

Expand Down Expand Up @@ -1026,6 +1027,7 @@ protected int runSpringBoot() throws Exception {
eq.loggingLevel = "off";
eq.ignoreLoadingError = this.ignoreLoadingError;
eq.lazyBean = this.lazyBean;
eq.applicationProperties = this.property;

printer().println("Running using Spring Boot v" + eq.springBootVersion + " (preparing and downloading files)");

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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.apache.camel.dsl.jbang.core.commands;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.util.Arrays;
import java.util.Properties;
import java.util.stream.Stream;

import org.apache.camel.dsl.jbang.core.common.RuntimeType;
import org.apache.camel.util.FileUtil;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
import picocli.CommandLine;

class ExportMainApplicationProperties {

private File workingDir;
private File profile = new File(".", "application.properties");

@BeforeEach
public void setup() throws IOException {
Path base = Paths.get("target");
workingDir = Files.createTempDirectory(base, "camel-export").toFile();
}

@AfterEach
public void end() throws IOException {
// force removing, since deleteOnExit is not removing.
FileUtil.removeDir(workingDir);
FileUtil.deleteFile(profile);
}

private static Stream<Arguments> runtimeProvider() {
return Stream.of(
Arguments.of(RuntimeType.quarkus),
Arguments.of(RuntimeType.springBoot),
Arguments.of(RuntimeType.main));
}

@ParameterizedTest
@MethodSource("runtimeProvider")
public void shouldExportUserPropertyOverride(RuntimeType rt) throws Exception {
// prepare as we need application.properties that contains configuration to be overridden
Files.copy(
new File("src/test/resources/sample-application.properties").toPath(),
profile.toPath(),
StandardCopyOption.REPLACE_EXISTING);

// We need a real file as we want to test the generated content
Export command = createCommand(rt,
new String[] { "src/test/resources/route.yaml", "src/test/resources/sample-application.properties" },
"--gav=examples:route:1.0.0", "--dir=" + workingDir, "--quiet",
"--property", "hello=test");
int exit = command.doCall();

Assertions.assertEquals(0, exit);
// Application properties
File appProperties = new File(workingDir + "/src/main/resources", "application.properties");
Assertions.assertTrue(appProperties.exists(), "Missing application properties");
Properties appProps = new Properties();
appProps.load(new FileInputStream(appProperties));
Assertions.assertEquals("test", appProps.getProperty("hello"));
Assertions.assertEquals("true", appProps.getProperty("another.property"));
}

private Export createCommand(RuntimeType rt, String[] files, String... args) {
Export command = new Export(new CamelJBangMain());
CommandLine.populateCommand(command, "--gav=examples:route:1.0.0", "--dir=" + workingDir, "--quiet",
"--runtime=%s".formatted(rt.runtime()));
if (args != null) {
CommandLine.populateCommand(command, args);
}
command.files = Arrays.asList(files);
return command;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.List;
import java.util.Properties;
import java.util.stream.Stream;

import org.apache.camel.dsl.jbang.core.common.RuntimeType;
Expand Down Expand Up @@ -483,4 +484,24 @@ public void assertApplicationPropertiesContentJava(RuntimeType rt, File appProps
}
}

@ParameterizedTest
@MethodSource("runtimeProvider")
public void shouldExportUserProperty(RuntimeType rt) throws Exception {
// We need a real file as we want to test the generated content
Export command = createCommand(rt, new String[] { "src/test/resources/route.yaml" },
"--gav=examples:route:1.0.0", "--dir=" + workingDir, "--quiet",
"--property", "hello=world");
int exit = command.doCall();

Assertions.assertEquals(0, exit);
// In this test we can validate any generic resource that must be created along the export.
// Exporting once to reduce the time to execute the test and the resource required to test.

// Application properties
File appProperties = new File(workingDir + "/src/main/resources", "application.properties");
Assertions.assertTrue(appProperties.exists(), "Missing application properties");
Properties appProps = new Properties();
appProps.load(new FileInputStream(appProperties));
Assertions.assertEquals("world", appProps.getProperty("hello"));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
## ---------------------------------------------------------------------------
## Licensed to the Apache Software Foundation (ASF) under one or more
## contributor license agreements. See the NOTICE file distributed with
## this work for additional information regarding copyright ownership.
## The ASF licenses this file to You 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.
## ---------------------------------------------------------------------------
hello=world
another.property=true

0 comments on commit c6367e3

Please sign in to comment.