This is an automated email from the ASF dual-hosted git repository. davsclaus pushed a commit to branch main in repository https://gitbox.apache.org/repos/asf/camel.git
commit b4dc6d3f9cdda8ee26067509a9c8bdd3230ab0a2 Author: Claus Ibsen <claus.ib...@gmail.com> AuthorDate: Sat Jan 7 10:46:01 2023 +0100 CAMEL-18674: camel-jbang - Run in background --- .../dsl/jbang/core/commands/CamelJBangMain.java | 1 + .../dsl/jbang/core/commands/ExportBaseCommand.java | 4 +- .../apache/camel/dsl/jbang/core/commands/Run.java | 69 ++++++++++--- .../dsl/jbang/core/commands/RunBackground.java | 111 +++++++++++++++++++++ .../camel/dsl/jbang/core/common/RuntimeUtil.java | 5 +- .../main/resources/log4j2-background.properties | 31 ++++++ 6 files changed, 203 insertions(+), 18 deletions(-) diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/CamelJBangMain.java b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/CamelJBangMain.java index 5176926abe2..fd989e523d8 100644 --- a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/CamelJBangMain.java +++ b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/CamelJBangMain.java @@ -73,6 +73,7 @@ public class CamelJBangMain implements Callable<Integer> { commandLine = new CommandLine(main) .addSubcommand("init", new CommandLine(new Init(main))) .addSubcommand("run", new CommandLine(new Run(main))) + .addSubcommand("run-background", new CommandLine(new RunBackground(main))) .addSubcommand("log", new CommandLine(new CamelLogAction(main))) .addSubcommand("ps", new CommandLine(new ListProcess(main))) .addSubcommand("stop", new CommandLine(new StopProcess(main))) diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ExportBaseCommand.java b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ExportBaseCommand.java index 54139ce6228..c31689c3abe 100644 --- a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ExportBaseCommand.java +++ b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ExportBaseCommand.java @@ -143,9 +143,9 @@ abstract class ExportBaseCommand extends CamelCommand { public Integer call() throws Exception { // configure logging first if (logging) { - RuntimeUtil.configureLog(loggingLevel, false, false, false, true); + RuntimeUtil.configureLog(loggingLevel, false, false, false, true, false); } else { - RuntimeUtil.configureLog("off", false, false, false, true); + RuntimeUtil.configureLog("off", false, false, false, true, false); } // export return export(); diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Run.java b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Run.java index 5dabdaed640..ce7d3fe78d1 100644 --- a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Run.java +++ b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Run.java @@ -39,6 +39,7 @@ import java.util.Properties; import java.util.Set; import java.util.Stack; import java.util.StringJoiner; +import java.util.concurrent.Callable; import java.util.function.Supplier; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -92,6 +93,7 @@ class Run extends CamelCommand { private boolean silentRun; private boolean pipeRun; + private boolean backgroundRun; private File logFile; @@ -102,6 +104,9 @@ class Run extends CamelCommand { List<String> files = new ArrayList<>(); + @Option(names = { "--background" }, defaultValue = "false", description = "Run in the background") + boolean background; + @Option(names = { "--profile" }, scope = CommandLine.ScopeType.INHERIT, defaultValue = "application", description = "Profile to use, which refers to loading properties file with the given profile name. By default application.properties is loaded.") String profile; @@ -222,6 +227,11 @@ class Run extends CamelCommand { return run(); } + protected Integer runBackground() throws Exception { + backgroundRun = true; + return run(); + } + private void writeSetting(KameletMain main, Properties existing, String key, String value) { String val = existing != null ? existing.getProperty(key, value) : value; if (val != null) { @@ -262,9 +272,11 @@ class Run extends CamelCommand { } private int run() throws Exception { - File work = new File(WORK_DIR); - removeDir(work); - work.mkdirs(); + if (!backgroundRun) { + File work = new File(WORK_DIR); + removeDir(work); + work.mkdirs(); + } Properties profileProperties = null; File profilePropertiesFile = new File(getProfile() + ".properties"); @@ -277,7 +289,7 @@ class Run extends CamelCommand { loggingJson = "true".equals(profileProperties.getProperty("loggingJson", loggingJson ? "true" : "false")); if (propertiesFiles == null) { - propertiesFiles = "file:" + profilePropertiesFile.getName(); + propertiesFiles = "file:" + getProfile() + ".properties"; } else { propertiesFiles = propertiesFiles + ",file:" + profilePropertiesFile.getName(); } @@ -286,6 +298,7 @@ class Run extends CamelCommand { mavenSettingsSecurity = profileProperties.getProperty("camel.jbang.maven-settings-security", mavenSettingsSecurity); openapi = profileProperties.getProperty("camel.jbang.openApi", openapi); download = "true".equals(profileProperties.getProperty("camel.jbang.download", download ? "true" : "false")); + background = "true".equals(profileProperties.getProperty("camel.jbang.background", background ? "true" : "false")); } // generate open-api early @@ -393,7 +406,7 @@ class Run extends CamelCommand { () -> maxIdleSeconds > 0 ? String.valueOf(maxIdleSeconds) : null); writeSetting(main, profileProperties, "camel.jbang.platform-http.port", () -> port > 0 ? String.valueOf(port) : null); - writeSetting(main, profileProperties, "camel.jbang.jfr", jfr || jfrProfile != null ? "jfr" : null); + writeSetting(main, profileProperties, "camel.jbang.jfr", jfr || jfrProfile != null ? "jfr" : null); // TODO: "true" instead of "jfr" ? writeSetting(main, profileProperties, "camel.jbang.jfr-profile", jfrProfile != null ? jfrProfile : null); StringJoiner js = new StringJoiner(","); @@ -559,15 +572,17 @@ class Run extends CamelCommand { writeSettings("camel.component.properties.location", loc); } - main.start(); - main.run(); - - // cleanup and delete log file - if (logFile != null) { - FileUtil.deleteFile(logFile); + RunMainTask run = new RunMainTask(main, logFile); + if (background) { + // run as background + ProcessBuilder pb = new ProcessBuilder(); + pb.command("camel", "run-background"); + Process p = pb.start(); + System.out.println("Running Camel integration: " + name + " in background with PID: " + p.pid()); + return 0; + } else { + return run.call(); } - - return main.getExitCode(); } private String loadFromCode(String code) throws IOException { @@ -704,7 +719,7 @@ class Run extends CamelCommand { if (silentRun) { // do not configure logging } else if (logging) { - RuntimeUtil.configureLog(loggingLevel, loggingColor, loggingJson, pipeRun, false); + RuntimeUtil.configureLog(loggingLevel, loggingColor, loggingJson, pipeRun, false, background); writeSettings("loggingLevel", loggingLevel); writeSettings("loggingColor", loggingColor ? "true" : "false"); writeSettings("loggingJson", loggingJson ? "true" : "false"); @@ -716,7 +731,7 @@ class Run extends CamelCommand { logFile.deleteOnExit(); } } else { - RuntimeUtil.configureLog("off", false, false, false, false); + RuntimeUtil.configureLog("off", false, false, false, false, false); writeSettings("loggingLevel", "off"); } } @@ -921,4 +936,28 @@ class Run extends CamelCommand { } } + static class RunMainTask implements Callable<Integer> { + + private final KameletMain main; + private final File logFile; + + public RunMainTask(KameletMain main, File logFile) { + this.main = main; + this.logFile = logFile; + } + + @Override + public Integer call() throws Exception { + main.start(); + main.run(); + + // cleanup and delete log file + if (logFile != null) { + FileUtil.deleteFile(logFile); + } + + return main.getExitCode(); + } + } + } diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/RunBackground.java b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/RunBackground.java new file mode 100644 index 00000000000..0ed5ec865b1 --- /dev/null +++ b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/RunBackground.java @@ -0,0 +1,111 @@ +/* + * 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.util.Properties; +import java.util.StringJoiner; + +import org.apache.camel.dsl.jbang.core.common.RuntimeUtil; +import org.apache.camel.util.CamelCaseOrderedProperties; +import picocli.CommandLine; + +@CommandLine.Command(name = "run-background", description = "Run Camel integration in background") +public class RunBackground extends CamelCommand { + + public RunBackground(CamelJBangMain main) { + super(main); + } + + @Override + public Integer call() throws Exception { + return run(); + } + + private int run() throws Exception { + File source = new File(Run.WORK_DIR + "/" + Run.RUN_SETTINGS_FILE); + Properties settings = loadProfileProperties(source); + if (settings.isEmpty()) { + System.err.println("Cannot load settings. Use camel run --background instead!"); + return 1; + } + + Run run = new Run(getMain()); + return runBackground(run, settings); + } + + private Properties loadProfileProperties(File source) throws Exception { + Properties prop = new CamelCaseOrderedProperties(); + RuntimeUtil.loadProperties(prop, source); + + // special for routes include pattern that we need to "fix" after reading from properties + // to make this work in run command + String value = prop.getProperty("camel.main.routesIncludePattern"); + if (value != null) { + // if not scheme then must use file: as this is what run command expects + StringJoiner sj = new StringJoiner(","); + for (String part : value.split(",")) { + if (!part.contains(":")) { + part = "file:" + part; + } + sj.add(part); + } + value = sj.toString(); + prop.setProperty("camel.main.routesIncludePattern", value); + } + + return prop; + } + + protected Integer runBackground(Run cmd, Properties settings) throws Exception { + cmd.profile = Run.WORK_DIR + "/camel-jbang-run"; + cmd.loggingLevel = settings.getProperty("loggingLevel", "INFO"); + cmd.loggingColor = "true".equals(settings.getProperty("loggingColor", "true")); + cmd.loggingJson = "true".equals(settings.getProperty("loggingJson", "false")); + cmd.loggingLevel = settings.getProperty("loggingLevel"); + cmd.name = settings.getProperty("camel.main.name", "CamelJBang"); + cmd.dev = "true".equals(settings.getProperty("camel.main.sourceLocationEnabled")); + cmd.trace = "true".equals(settings.getProperty("camel.main.tracing")); + cmd.modeline = "true".equals(settings.getProperty("camel.main.modeline")); + cmd.openapi = settings.getProperty("camel.jbang.openApi"); + cmd.repos = settings.getProperty("camel.jbang.repos"); + cmd.health = "true".equals(settings.getProperty("camel.jbang.health")); + cmd.console = "true".equals(settings.getProperty("camel.jbang.console")); + String s = settings.getProperty("camel.main.durationMaxMessages"); + if (s != null) { + cmd.maxMessages = Integer.parseInt(s); + } + s = settings.getProperty("camel.main.durationMaxSeconds"); + if (s != null) { + cmd.maxSeconds = Integer.parseInt(s); + } + s = settings.getProperty("camel.main.durationMaxIdleSeconds"); + if (s != null) { + cmd.maxIdleSeconds = Integer.parseInt(s); + } + s = settings.getProperty("camel.jbang.platform-http.port"); + if (s != null) { + cmd.port = Integer.parseInt(s); + } + cmd.jfr = "jfr".equals(settings.getProperty("camel.jbang.jfr-profile")); + cmd.jfrProfile = settings.getProperty("camel.jbang.jfr-profile"); + cmd.propertiesFiles = settings.getProperty("camel.component.properties.location"); + + return cmd.runBackground(); + } + +} diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/common/RuntimeUtil.java b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/common/RuntimeUtil.java index 4dc5f495950..905d3ddf58b 100644 --- a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/common/RuntimeUtil.java +++ b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/common/RuntimeUtil.java @@ -32,13 +32,16 @@ public final class RuntimeUtil { private RuntimeUtil() { } - public static void configureLog(String level, boolean color, boolean json, boolean pipe, boolean export) { + public static void configureLog( + String level, boolean color, boolean json, boolean pipe, boolean export, boolean background) { if (INIT_DONE.compareAndSet(false, true)) { long pid = ProcessHandle.current().pid(); System.setProperty("pid", "" + pid); if (export) { Configurator.initialize("CamelJBang", "log4j2-export.properties"); + } else if (background) { + Configurator.initialize("CamelJBang", "log4j2-background.properties"); } else if (pipe) { Configurator.initialize("CamelJBang", "log4j2-pipe.properties"); } else if (json) { diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/resources/log4j2-background.properties b/dsl/camel-jbang/camel-jbang-core/src/main/resources/log4j2-background.properties new file mode 100644 index 00000000000..5e700f81157 --- /dev/null +++ b/dsl/camel-jbang/camel-jbang-core/src/main/resources/log4j2-background.properties @@ -0,0 +1,31 @@ +## --------------------------------------------------------------------------- +## 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. +## --------------------------------------------------------------------------- + +# file logger +appender.file.type = File +appender.file.name = file +appender.file.fileName = ${sys:user.home}/.camel/${sys:pid}.log +appender.file.createOnDemand = true +appender.file.append = false +appender.file.layout.type = PatternLayout +# logging style that is similar to spring boot +appender.file.layout.pattern = %style{%d{yyyy-MM-dd HH:mm:ss.SSS}}{Dim} %highlight{%5p} %style{%pid}{Magenta} %style{---}{Dim} %style{[%15.15t]}{Dim} %style{%-35.35c}{Cyan} : %m%n + +# log to file +rootLogger = INFO,file +rootLogger.level = INFO +