This is an automated email from the ASF dual-hosted git repository. davsclaus pushed a commit to branch feature/CAMEL-24226-resource-dirs in repository https://gitbox.apache.org/repos/asf/camel.git
commit 40e3d76596ffd6e0e6677798fca552d67f0ac085 Author: Claus Ibsen <[email protected]> AuthorDate: Tue Jul 21 16:06:36 2026 +0200 CAMEL-24226: camel run/export - add --resource-dirs option to copy directories preserving structure Co-Authored-By: Claude Opus 4.6 <[email protected]> Signed-off-by: Claus Ibsen <[email protected]> --- .../ROOT/pages/camel-jbang-configuration.adoc | 3 +- .../modules/ROOT/pages/camel-jbang-projects.adoc | 34 +++++ .../modules/ROOT/pages/camel-jbang-running.adoc | 30 ++++ .../pages/jbang-commands/camel-jbang-debug.adoc | 1 + .../camel-jbang-dependency-copy.adoc | 1 + .../camel-jbang-dependency-list.adoc | 1 + .../camel-jbang-dependency-update.adoc | 1 + .../ROOT/pages/jbang-commands/camel-jbang-dev.adoc | 1 + .../pages/jbang-commands/camel-jbang-export.adoc | 1 + .../ROOT/pages/jbang-commands/camel-jbang-run.adoc | 1 + .../pages/jbang-commands/camel-jbang-sbom.adoc | 1 + .../META-INF/camel-jbang-commands-metadata.json | 12 +- .../camel-jbang-configuration-metadata.json | 1 + .../dsl/jbang/core/commands/ExportBaseCommand.java | 44 ++++++ .../apache/camel/dsl/jbang/core/commands/Run.java | 48 +++++++ .../dsl/jbang/core/common/CamelJBangConstants.java | 4 + .../dsl/jbang/core/commands/ResourceDirsTest.java | 160 +++++++++++++++++++++ .../core/commands/kubernetes/KubernetesExport.java | 2 + .../core/commands/kubernetes/KubernetesRun.java | 6 + 19 files changed, 345 insertions(+), 7 deletions(-) diff --git a/docs/user-manual/modules/ROOT/pages/camel-jbang-configuration.adoc b/docs/user-manual/modules/ROOT/pages/camel-jbang-configuration.adoc index 4a38e58f513a..f37467779487 100644 --- a/docs/user-manual/modules/ROOT/pages/camel-jbang-configuration.adoc +++ b/docs/user-manual/modules/ROOT/pages/camel-jbang-configuration.adoc @@ -4,7 +4,7 @@ This page covers configuring the Camel CLI — available options, configuration // jbang options: START == Camel CLI configurations -The camel.jbang supports 49 options, which are listed below. +The camel.jbang supports 50 options, which are listed below. [width="100%",cols="2,5,^1,2",options="header"] |=== @@ -51,6 +51,7 @@ The camel.jbang supports 49 options, which are listed below. | *camel.jbang.quarkusVersion* | version of Quarkus Platform BOM | | String | *camel.jbang.readmeFiles* | README files included with the integration (Use commas to separate multiple files) | | String | *camel.jbang.repos* | Additional Maven repositories for download on-demand (Use commas to separate multiple repositories) | | String +| *camel.jbang.resourceDirs* | Additional resource directories to include recursively, preserving directory structure (Use commas to separate multiple directories) | | String | *camel.jbang.runtime* | Which runtime to use (camel-main, spring-boot, quarkus) | | String | *camel.jbang.scriptFiles* | Additional shell script files to export to src/main/scripts directory | | String | *camel.jbang.sourceDir* | Source directory for dynamically loading Camel file(s) to run. When using this, then files cannot be specified at the same time. | | String diff --git a/docs/user-manual/modules/ROOT/pages/camel-jbang-projects.adoc b/docs/user-manual/modules/ROOT/pages/camel-jbang-projects.adoc index 26b621316a9b..05e53e7039e5 100644 --- a/docs/user-manual/modules/ROOT/pages/camel-jbang-projects.adoc +++ b/docs/user-manual/modules/ROOT/pages/camel-jbang-projects.adoc @@ -103,6 +103,40 @@ camel export --runtime=quarkus --gav=com.foo:acme:1.0-SNAPSHOT --dep=camel:manag camel export --runtime=quarkus --gav=com.foo:acme:1.0-SNAPSHOT --dep=camel:cli-connector ---- +=== Including resource directories + +To include entire directories of resource files (such as XSD schemas, WSDL files, etc.) +in the exported project while preserving their directory structure, use `--resource-dirs`: + +[source,bash] +---- +camel export --resource-dirs=soap +---- + +This recursively copies all files from the `soap/` directory into `src/main/resources/soap/`, +preserving the directory structure. For example, `soap/schemas/common.xsd` becomes +`src/main/resources/soap/schemas/common.xsd`. + +Multiple directories can be specified with commas: + +[source,bash] +---- +camel export --resource-dirs=soap,wsdl +---- + +You can also reference directories outside the current project using relative paths. +When using `..` paths, only the last directory name is used as the target: + +[source,bash] +---- +camel export --resource-dirs=../shared/schemas +---- + +This copies the contents into `src/main/resources/schemas/`. + +NOTE: Absolute paths (e.g., `/some/path`) are not allowed. +The directory is limited to at most 1000 files as a safety measure. + === Troubleshooting exporting Use `--verbose` and `--logging` for more detail, or `--logging-level=DEBUG` for full output. diff --git a/docs/user-manual/modules/ROOT/pages/camel-jbang-running.adoc b/docs/user-manual/modules/ROOT/pages/camel-jbang-running.adoc index a80d34ef1ac6..4d56d7565df9 100644 --- a/docs/user-manual/modules/ROOT/pages/camel-jbang-running.adoc +++ b/docs/user-manual/modules/ROOT/pages/camel-jbang-running.adoc @@ -152,6 +152,36 @@ Multiple dependencies can be separated by comma: camel run foo.java --dep=camel-saxon,com.foo:acme:1.0 ---- +== Including resource directories + +To include entire directories of resource files (such as XSD schemas, WSDL files, etc.) +on the classpath while preserving their directory structure, use `--resource-dirs`: + +[source,bash] +---- +camel run route.yaml --resource-dirs=soap +---- + +This recursively adds all files from the `soap/` directory to the classpath, +preserving the directory structure (e.g., `soap/schemas/common.xsd` is accessible as `classpath:soap/schemas/common.xsd`). + +Multiple directories can be specified with commas: + +[source,bash] +---- +camel run route.yaml --resource-dirs=soap,wsdl +---- + +You can also reference directories outside the current project using relative paths: + +[source,bash] +---- +camel run route.yaml --resource-dirs=../shared/schemas +---- + +NOTE: Absolute paths (e.g., `/some/path`) are not allowed. +The directory is limited to at most 1000 files as a safety measure. + == Using 3rd-party Maven repositories By default, Camel CLI downloads from the local Maven repository and Maven Central. diff --git a/docs/user-manual/modules/ROOT/pages/jbang-commands/camel-jbang-debug.adoc b/docs/user-manual/modules/ROOT/pages/jbang-commands/camel-jbang-debug.adoc index 2874c142b913..0f9265a5fec2 100644 --- a/docs/user-manual/modules/ROOT/pages/jbang-commands/camel-jbang-debug.adoc +++ b/docs/user-manual/modules/ROOT/pages/jbang-commands/camel-jbang-debug.adoc @@ -83,6 +83,7 @@ camel debug [options] | `--reload,--dev` | Enables dev mode (live reload when source files are updated and saved) | | boolean | `--remote-attach` | Attaches debugger remotely to an existing running Camel integration. (Add camel-cli-debug JAR to the existing Camel application and run before attaching this debugger) | | boolean | `--repo,--repos` | Additional maven repositories for download on-demand (Use commas to separate multiple repositories) | | String +| `--resource-dir,--resource-dirs` | Additional resource directories to include on the classpath (recursive, preserving structure) | | List | `--runtime` | Runtime (camel-main, spring-boot, quarkus) | camel-main | RuntimeType | `--show-body` | Show message body in debug messages | true | boolean | `--show-exception` | Show exception and stacktrace for failed messages | true | boolean diff --git a/docs/user-manual/modules/ROOT/pages/jbang-commands/camel-jbang-dependency-copy.adoc b/docs/user-manual/modules/ROOT/pages/jbang-commands/camel-jbang-dependency-copy.adoc index d8c90d2e84ef..2149196f292e 100644 --- a/docs/user-manual/modules/ROOT/pages/jbang-commands/camel-jbang-dependency-copy.adoc +++ b/docs/user-manual/modules/ROOT/pages/jbang-commands/camel-jbang-dependency-copy.adoc @@ -65,6 +65,7 @@ camel dependency copy [options] | `--quarkus-version` | version of Quarkus Platform BOM; the default value is looked up in Quarkus Extension Registry | | String | `--quiet` | Will be quiet, only print when error occurs | false | boolean | `--repo,--repos` | Additional maven repositories for download on-demand (Use commas to separate multiple repositories) | | String +| `--resource-dir,--resource-dirs` | Additional resource directories to include in src/main/resources (recursive, preserving structure) | | List | `--runtime` | Runtime (camel-main, spring-boot, quarkus) | | RuntimeType | `--skip-plugins` | Skip plugins during export | false | boolean | `--spring-boot-version` | Spring Boot version | RuntimeType.SPRING_BOOT_VERSION | String diff --git a/docs/user-manual/modules/ROOT/pages/jbang-commands/camel-jbang-dependency-list.adoc b/docs/user-manual/modules/ROOT/pages/jbang-commands/camel-jbang-dependency-list.adoc index 575369f1c32b..a87b96fed253 100644 --- a/docs/user-manual/modules/ROOT/pages/jbang-commands/camel-jbang-dependency-list.adoc +++ b/docs/user-manual/modules/ROOT/pages/jbang-commands/camel-jbang-dependency-list.adoc @@ -64,6 +64,7 @@ camel dependency list [options] | `--quarkus-version` | version of Quarkus Platform BOM; the default value is looked up in Quarkus Extension Registry | | String | `--quiet` | Will be quiet, only print when error occurs | false | boolean | `--repo,--repos` | Additional maven repositories for download on-demand (Use commas to separate multiple repositories) | | String +| `--resource-dir,--resource-dirs` | Additional resource directories to include in src/main/resources (recursive, preserving structure) | | List | `--runtime` | Runtime (camel-main, spring-boot, quarkus) | | RuntimeType | `--skip-plugins` | Skip plugins during export | false | boolean | `--spring-boot-version` | Spring Boot version | RuntimeType.SPRING_BOOT_VERSION | String diff --git a/docs/user-manual/modules/ROOT/pages/jbang-commands/camel-jbang-dependency-update.adoc b/docs/user-manual/modules/ROOT/pages/jbang-commands/camel-jbang-dependency-update.adoc index f5310726df1c..bc3ff5357e69 100644 --- a/docs/user-manual/modules/ROOT/pages/jbang-commands/camel-jbang-dependency-update.adoc +++ b/docs/user-manual/modules/ROOT/pages/jbang-commands/camel-jbang-dependency-update.adoc @@ -65,6 +65,7 @@ camel dependency update [options] | `--quarkus-version` | version of Quarkus Platform BOM; the default value is looked up in Quarkus Extension Registry | | String | `--quiet` | Will be quiet, only print when error occurs | false | boolean | `--repo,--repos` | Additional maven repositories for download on-demand (Use commas to separate multiple repositories) | | String +| `--resource-dir,--resource-dirs` | Additional resource directories to include in src/main/resources (recursive, preserving structure) | | List | `--runtime` | Runtime (camel-main, spring-boot, quarkus) | | RuntimeType | `--scan-routes` | Sync dependencies from route definitions. Only manages org.apache.camel dependencies, preserving non-Camel dependencies. Removes unused Camel dependencies. | | boolean | `--skip-plugins` | Skip plugins during export | false | boolean diff --git a/docs/user-manual/modules/ROOT/pages/jbang-commands/camel-jbang-dev.adoc b/docs/user-manual/modules/ROOT/pages/jbang-commands/camel-jbang-dev.adoc index 69218ec9f4a0..1b69782e934c 100644 --- a/docs/user-manual/modules/ROOT/pages/jbang-commands/camel-jbang-dev.adoc +++ b/docs/user-manual/modules/ROOT/pages/jbang-commands/camel-jbang-dev.adoc @@ -76,6 +76,7 @@ camel dev [options] | `--quarkus-version` | version of Quarkus Platform BOM; the default value is looked up in Quarkus Extension Registry | | String | `--reload,--dev` | Enables dev mode (live reload when source files are updated and saved) | | boolean | `--repo,--repos` | Additional maven repositories for download on-demand (Use commas to separate multiple repositories) | | String +| `--resource-dir,--resource-dirs` | Additional resource directories to include on the classpath (recursive, preserving structure) | | List | `--runtime` | Runtime (camel-main, spring-boot, quarkus) | camel-main | RuntimeType | `--skip-plugins` | Skip resolving plugin dependencies | false | boolean | `--source-dir` | Source directory for dynamically loading Camel file(s) to run. When using this, then files cannot be specified at the same time. | | String diff --git a/docs/user-manual/modules/ROOT/pages/jbang-commands/camel-jbang-export.adoc b/docs/user-manual/modules/ROOT/pages/jbang-commands/camel-jbang-export.adoc index b78a1b2349f6..12278c201622 100644 --- a/docs/user-manual/modules/ROOT/pages/jbang-commands/camel-jbang-export.adoc +++ b/docs/user-manual/modules/ROOT/pages/jbang-commands/camel-jbang-export.adoc @@ -63,6 +63,7 @@ camel export [options] | `--quarkus-version` | version of Quarkus Platform BOM; the default value is looked up in Quarkus Extension Registry | | String | `--quiet` | Will be quiet, only print when error occurs | false | boolean | `--repo,--repos` | Additional maven repositories for download on-demand (Use commas to separate multiple repositories) | | String +| `--resource-dir,--resource-dirs` | Additional resource directories to include in src/main/resources (recursive, preserving structure) | | List | `--runtime` | Runtime (camel-main, spring-boot, quarkus) | | RuntimeType | `--skip-plugins` | Skip plugins during export | false | boolean | `--spring-boot-version` | Spring Boot version | RuntimeType.SPRING_BOOT_VERSION | String diff --git a/docs/user-manual/modules/ROOT/pages/jbang-commands/camel-jbang-run.adoc b/docs/user-manual/modules/ROOT/pages/jbang-commands/camel-jbang-run.adoc index ef505512255b..93c8bcfc962b 100644 --- a/docs/user-manual/modules/ROOT/pages/jbang-commands/camel-jbang-run.adoc +++ b/docs/user-manual/modules/ROOT/pages/jbang-commands/camel-jbang-run.adoc @@ -76,6 +76,7 @@ camel run [options] | `--quarkus-version` | version of Quarkus Platform BOM; the default value is looked up in Quarkus Extension Registry | | String | `--reload,--dev` | Enables dev mode (live reload when source files are updated and saved) | | boolean | `--repo,--repos` | Additional maven repositories for download on-demand (Use commas to separate multiple repositories) | | String +| `--resource-dir,--resource-dirs` | Additional resource directories to include on the classpath (recursive, preserving structure) | | List | `--runtime` | Runtime (camel-main, spring-boot, quarkus) | camel-main | RuntimeType | `--skip-plugins` | Skip resolving plugin dependencies | false | boolean | `--source-dir` | Source directory for dynamically loading Camel file(s) to run. When using this, then files cannot be specified at the same time. | | String diff --git a/docs/user-manual/modules/ROOT/pages/jbang-commands/camel-jbang-sbom.adoc b/docs/user-manual/modules/ROOT/pages/jbang-commands/camel-jbang-sbom.adoc index 06036a020a35..d0540d8eabbd 100644 --- a/docs/user-manual/modules/ROOT/pages/jbang-commands/camel-jbang-sbom.adoc +++ b/docs/user-manual/modules/ROOT/pages/jbang-commands/camel-jbang-sbom.adoc @@ -66,6 +66,7 @@ camel sbom [options] | `--quarkus-version` | version of Quarkus Platform BOM; the default value is looked up in Quarkus Extension Registry | | String | `--quiet` | Will be quiet, only print when error occurs | false | boolean | `--repo,--repos` | Additional maven repositories for download on-demand (Use commas to separate multiple repositories) | | String +| `--resource-dir,--resource-dirs` | Additional resource directories to include in src/main/resources (recursive, preserving structure) | | List | `--runtime` | Runtime (camel-main, spring-boot, quarkus) | | RuntimeType | `--sbom-format` | The SBOM format, possible values are cyclonedx or spdx | CYCLONEDX_FORMAT | String | `--sbom-output-format` | The SBOM output format, possible values are json or xml | SBOM_JSON_FORMAT | String diff --git a/dsl/camel-jbang/camel-jbang-core/src/generated/resources/META-INF/camel-jbang-commands-metadata.json b/dsl/camel-jbang/camel-jbang-core/src/generated/resources/META-INF/camel-jbang-commands-metadata.json index 7f66b663a036..85a31044c196 100644 --- a/dsl/camel-jbang/camel-jbang-core/src/generated/resources/META-INF/camel-jbang-commands-metadata.json +++ b/dsl/camel-jbang/camel-jbang-core/src/generated/resources/META-INF/camel-jbang-commands-metadata.json @@ -6,15 +6,15 @@ { "name": "cmd", "fullName": "cmd", "description": "Performs commands in the running Camel integrations, such as start\/stop route, or change logging levels.", "sourceClass": "org.apache.camel.dsl.jbang.core.commands.action.CamelAction", "options": [ { "names": "-h,--help", "description": "Display the help and sub-commands", "javaType": "boolean", "type": "boolean" } ], "subcommands": [ { "name": "browse", "fullName": "cmd browse", "description": "Browse pending messages on endpoints [...] { "name": "completion", "fullName": "completion", "description": "Generate completion script for bash\/zsh", "sourceClass": "org.apache.camel.dsl.jbang.core.commands.Complete", "options": [ { "names": "-h,--help", "description": "Display the help and sub-commands", "javaType": "boolean", "type": "boolean" } ] }, { "name": "config", "fullName": "config", "description": "Get and set user configuration values", "sourceClass": "org.apache.camel.dsl.jbang.core.commands.config.ConfigCommand", "options": [ { "names": "-h,--help", "description": "Display the help and sub-commands", "javaType": "boolean", "type": "boolean" } ], "subcommands": [ { "name": "get", "fullName": "config get", "description": "Display user configuration value", "sourceClass": "org.apache.camel.dsl.jbang.core.commands.config. [...] - { "name": "debug", "fullName": "debug", "description": "Debug local Camel integration", "sourceClass": "org.apache.camel.dsl.jbang.core.commands.Debug", "options": [ { "names": "--ago", "description": "Use ago instead of yyyy-MM-dd HH:mm:ss in timestamp.", "javaType": "boolean", "type": "boolean" }, { "names": "--background", "description": "Run in the background", "defaultValue": "false", "javaType": "boolean", "type": "boolean" }, { "names": "--background-wait", "description": "To [...] - { "name": "dependency", "fullName": "dependency", "description": "Displays all Camel dependencies required to run", "sourceClass": "org.apache.camel.dsl.jbang.core.commands.DependencyCommand", "options": [ { "names": "-h,--help", "description": "Display the help and sub-commands", "javaType": "boolean", "type": "boolean" } ], "subcommands": [ { "name": "copy", "fullName": "dependency copy", "description": "Copies all Camel dependencies required to run to a specific directory", "sourc [...] - { "name": "dev", "fullName": "dev", "description": "Run in dev mode with live reload", "sourceClass": "org.apache.camel.dsl.jbang.core.commands.Dev", "options": [ { "names": "--background", "description": "Run in the background", "defaultValue": "false", "javaType": "boolean", "type": "boolean" }, { "names": "--background-wait", "description": "To wait for run in background to startup successfully, before returning", "defaultValue": "true", "javaType": "boolean", "type": "boolean" }, [...] + { "name": "debug", "fullName": "debug", "description": "Debug local Camel integration", "sourceClass": "org.apache.camel.dsl.jbang.core.commands.Debug", "options": [ { "names": "--ago", "description": "Use ago instead of yyyy-MM-dd HH:mm:ss in timestamp.", "javaType": "boolean", "type": "boolean" }, { "names": "--background", "description": "Run in the background", "defaultValue": "false", "javaType": "boolean", "type": "boolean" }, { "names": "--background-wait", "description": "To [...] + { "name": "dependency", "fullName": "dependency", "description": "Displays all Camel dependencies required to run", "sourceClass": "org.apache.camel.dsl.jbang.core.commands.DependencyCommand", "options": [ { "names": "-h,--help", "description": "Display the help and sub-commands", "javaType": "boolean", "type": "boolean" } ], "subcommands": [ { "name": "copy", "fullName": "dependency copy", "description": "Copies all Camel dependencies required to run to a specific directory", "sourc [...] + { "name": "dev", "fullName": "dev", "description": "Run in dev mode with live reload", "sourceClass": "org.apache.camel.dsl.jbang.core.commands.Dev", "options": [ { "names": "--background", "description": "Run in the background", "defaultValue": "false", "javaType": "boolean", "type": "boolean" }, { "names": "--background-wait", "description": "To wait for run in background to startup successfully, before returning", "defaultValue": "true", "javaType": "boolean", "type": "boolean" }, [...] { "name": "dirty", "fullName": "dirty", "description": "Check if there are dirty files from previous Camel runs that did not terminate gracefully", "sourceClass": "org.apache.camel.dsl.jbang.core.commands.process.Dirty", "options": [ { "names": "--clean", "description": "Clean dirty files which are no longer in use", "defaultValue": "false", "javaType": "boolean", "type": "boolean" }, { "names": "-h,--help", "description": "Display the help and sub-commands", "javaType": "boolean", " [...] { "name": "doc", "fullName": "doc", "description": "Shows documentation for kamelet, component, and other Camel resources", "sourceClass": "org.apache.camel.dsl.jbang.core.commands.catalog.CatalogDoc", "options": [ { "names": "--camel-version", "description": "To use a different Camel version than the default version", "javaType": "java.lang.String", "type": "string" }, { "names": "--download", "description": "Whether to allow automatic downloading JAR dependencies (over the internet [...] { "name": "doctor", "fullName": "doctor", "description": "Checks the environment and reports potential issues", "sourceClass": "org.apache.camel.dsl.jbang.core.commands.Doctor", "options": [ { "names": "-h,--help", "description": "Display the help and sub-commands", "javaType": "boolean", "type": "boolean" } ] }, { "name": "eval", "fullName": "eval", "description": "Evaluate Camel expressions and scripts", "sourceClass": "org.apache.camel.dsl.jbang.core.commands.EvalCommand", "options": [ { "names": "-h,--help", "description": "Display the help and sub-commands", "javaType": "boolean", "type": "boolean" } ], "subcommands": [ { "name": "expression", "fullName": "eval expression", "description": "Evaluates Camel expression", "sourceClass": "org.apache.camel.dsl.jbang.core.commands.action.EvalEx [...] { "name": "explain", "fullName": "explain", "description": "Explain what a Camel route does using AI\/LLM", "sourceClass": "org.apache.camel.dsl.jbang.core.commands.Explain", "options": [ { "names": "--api-key", "description": "API key for authentication. Also reads ANTHROPIC_API_KEY, OPENAI_API_KEY, or LLM_API_KEY env vars", "javaType": "java.lang.String", "type": "string" }, { "names": "--api-type", "description": "API type: 'ollama', 'openai' (OpenAI-compatible), or 'anthropic' (A [...] - { "name": "export", "fullName": "export", "description": "Export to other runtimes (Camel Main, Spring Boot, or Quarkus)", "sourceClass": "org.apache.camel.dsl.jbang.core.commands.Export", "options": [ { "names": "--build-property", "description": "Maven build properties, ex. --build-property=prop1=foo", "javaType": "java.util.List", "type": "array" }, { "names": "--camel-spring-boot-version", "description": "Camel version to use with Spring Boot", "javaType": "java.lang.String", "ty [...] + { "name": "export", "fullName": "export", "description": "Export to other runtimes (Camel Main, Spring Boot, or Quarkus)", "sourceClass": "org.apache.camel.dsl.jbang.core.commands.Export", "options": [ { "names": "--build-property", "description": "Maven build properties, ex. --build-property=prop1=foo", "javaType": "java.util.List", "type": "array" }, { "names": "--camel-spring-boot-version", "description": "Camel version to use with Spring Boot", "javaType": "java.lang.String", "ty [...] { "name": "get", "fullName": "get", "description": "Get status of Camel integrations", "sourceClass": "org.apache.camel.dsl.jbang.core.commands.process.CamelStatus", "options": [ { "names": "--watch", "description": "Execute periodically and showing output fullscreen", "javaType": "boolean", "type": "boolean" }, { "names": "-h,--help", "description": "Display the help and sub-commands", "javaType": "boolean", "type": "boolean" } ], "subcommands": [ { "name": "activity", "fullName": " [...] { "name": "harden", "fullName": "harden", "description": "Suggest security hardening for Camel routes using AI\/LLM", "sourceClass": "org.apache.camel.dsl.jbang.core.commands.Harden", "options": [ { "names": "--api-key", "description": "API key for authentication. Also reads OPENAI_API_KEY or LLM_API_KEY env vars", "javaType": "java.lang.String", "type": "string" }, { "names": "--api-type", "description": "API type: 'ollama' or 'openai' (OpenAI-compatible)", "defaultValue": "ollama", [...] { "name": "hawtio", "fullName": "hawtio", "description": "Launch Hawtio web console", "sourceClass": "org.apache.camel.dsl.jbang.core.commands.process.Hawtio", "options": [ { "names": "--host", "description": "Hostname to bind the Hawtio web console to", "defaultValue": "127.0.0.1", "javaType": "java.lang.String", "type": "string" }, { "names": "--openUrl", "description": "To automatic open Hawtio web console in the web browser", "defaultValue": "true", "javaType": "boolean", "type": [...] @@ -26,8 +26,8 @@ { "name": "plugin", "fullName": "plugin", "description": "Manage plugins that add sub-commands to this CLI", "sourceClass": "org.apache.camel.dsl.jbang.core.commands.plugin.PluginCommand", "options": [ { "names": "-h,--help", "description": "Display the help and sub-commands", "javaType": "boolean", "type": "boolean" } ], "subcommands": [ { "name": "add", "fullName": "plugin add", "description": "Add new plugin", "sourceClass": "org.apache.camel.dsl.jbang.core.commands.plugin.PluginA [...] { "name": "ps", "fullName": "ps", "description": "List running Camel integrations", "sourceClass": "org.apache.camel.dsl.jbang.core.commands.process.ListProcess", "options": [ { "names": "--json", "description": "Output in JSON Format", "javaType": "boolean", "type": "boolean" }, { "names": "--pid", "description": "List only pid in the output", "javaType": "boolean", "type": "boolean" }, { "names": "--remote", "description": "Break down counters into remote\/total pairs", "javaType": [...] { "name": "restart", "fullName": "restart", "description": "Restarts running Camel integrations (stop + re-launch)", "sourceClass": "org.apache.camel.dsl.jbang.core.commands.process.RestartProcess", "options": [ { "names": "-h,--help", "description": "Display the help and sub-commands", "javaType": "boolean", "type": "boolean" } ] }, - { "name": "run", "fullName": "run", "description": "Run as local Camel integration", "sourceClass": "org.apache.camel.dsl.jbang.core.commands.Run", "options": [ { "names": "--background", "description": "Run in the background", "defaultValue": "false", "javaType": "boolean", "type": "boolean" }, { "names": "--background-wait", "description": "To wait for run in background to startup successfully, before returning", "defaultValue": "true", "javaType": "boolean", "type": "boolean" }, { [...] - { "name": "sbom", "fullName": "sbom", "description": "Generate a CycloneDX or SPDX SBOM for a specific project", "sourceClass": "org.apache.camel.dsl.jbang.core.commands.SBOMGenerator", "options": [ { "names": "--build-property", "description": "Maven build properties, ex. --build-property=prop1=foo", "javaType": "java.util.List", "type": "array" }, { "names": "--camel-spring-boot-version", "description": "Camel version to use with Spring Boot", "javaType": "java.lang.String", "type" [...] + { "name": "run", "fullName": "run", "description": "Run as local Camel integration", "sourceClass": "org.apache.camel.dsl.jbang.core.commands.Run", "options": [ { "names": "--background", "description": "Run in the background", "defaultValue": "false", "javaType": "boolean", "type": "boolean" }, { "names": "--background-wait", "description": "To wait for run in background to startup successfully, before returning", "defaultValue": "true", "javaType": "boolean", "type": "boolean" }, { [...] + { "name": "sbom", "fullName": "sbom", "description": "Generate a CycloneDX or SPDX SBOM for a specific project", "sourceClass": "org.apache.camel.dsl.jbang.core.commands.SBOMGenerator", "options": [ { "names": "--build-property", "description": "Maven build properties, ex. --build-property=prop1=foo", "javaType": "java.util.List", "type": "array" }, { "names": "--camel-spring-boot-version", "description": "Camel version to use with Spring Boot", "javaType": "java.lang.String", "type" [...] { "name": "script", "fullName": "script", "description": "Run Camel integration as shell script for terminal scripting", "sourceClass": "org.apache.camel.dsl.jbang.core.commands.Script", "options": [ { "names": "--logging", "description": "Can be used to turn on logging (logs to file in <user home>\/.camel directory)", "defaultValue": "false", "javaType": "boolean", "type": "boolean" }, { "names": "--logging-level", "description": "Logging level (ERROR, WARN, INFO, DEBUG, TRACE)", "d [...] { "name": "shell", "fullName": "shell", "description": "Interactive Camel CLI shell.", "sourceClass": "org.apache.camel.dsl.jbang.core.commands.Shell", "options": [ { "names": "-h,--help", "description": "Display the help and sub-commands", "javaType": "boolean", "type": "boolean" } ] }, { "name": "stop", "fullName": "stop", "description": "Shuts down running Camel integrations", "sourceClass": "org.apache.camel.dsl.jbang.core.commands.process.StopProcess", "options": [ { "names": "--kill", "description": "To force killing the process (SIGKILL)", "javaType": "boolean", "type": "boolean" }, { "names": "-h,--help", "description": "Display the help and sub-commands", "javaType": "boolean", "type": "boolean" } ] }, diff --git a/dsl/camel-jbang/camel-jbang-core/src/generated/resources/META-INF/camel-jbang-configuration-metadata.json b/dsl/camel-jbang/camel-jbang-core/src/generated/resources/META-INF/camel-jbang-configuration-metadata.json index c28faba036ef..38820baacb31 100644 --- a/dsl/camel-jbang/camel-jbang-core/src/generated/resources/META-INF/camel-jbang-configuration-metadata.json +++ b/dsl/camel-jbang/camel-jbang-core/src/generated/resources/META-INF/camel-jbang-configuration-metadata.json @@ -45,6 +45,7 @@ { "name": "camel.jbang.quarkusVersion", "required": false, "description": "version of Quarkus Platform BOM", "label": "quarkus", "type": "string", "javaType": "String", "secret": false }, { "name": "camel.jbang.readmeFiles", "required": false, "description": "README files included with the integration (Use commas to separate multiple files)", "type": "string", "javaType": "String", "secret": false }, { "name": "camel.jbang.repos", "required": false, "description": "Additional Maven repositories for download on-demand (Use commas to separate multiple repositories)", "label": "maven", "type": "string", "javaType": "String", "secret": false }, + { "name": "camel.jbang.resourceDirs", "required": false, "description": "Additional resource directories to include recursively, preserving directory structure (Use commas to separate multiple directories)", "type": "string", "javaType": "String", "secret": false }, { "name": "camel.jbang.runtime", "required": false, "description": "Which runtime to use (camel-main, spring-boot, quarkus)", "type": "enum", "javaType": "String", "secret": false, "enum": [ "camel-main", "spring-boot", "quarkus" ] }, { "name": "camel.jbang.scriptFiles", "required": false, "description": "Additional shell script files to export to src\/main\/scripts directory", "type": "string", "javaType": "String", "secret": false }, { "name": "camel.jbang.sourceDir", "required": false, "description": "Source directory for dynamically loading Camel file(s) to run. When using this, then files cannot be specified at the same time.", "label": "advanced", "type": "string", "javaType": "String", "secret": false }, 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 664a2c603a27..dc2304e28fcc 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 @@ -248,6 +248,11 @@ public abstract class ExportBaseCommand extends CamelCommand { description = "Whether to automatic package scan JARs for custom Spring or Quarkus beans making them available for Camel CLI") protected boolean packageScanJars; + @CommandLine.Option(names = { "--resource-dir", "--resource-dirs" }, + description = "Additional resource directories to include in src/main/resources (recursive, preserving structure)", + split = ",") + protected List<String> resourceDirs = new ArrayList<>(); + @CommandLine.Option(names = { "--build-property" }, description = "Maven build properties, ex. --build-property=prop1=foo") protected List<String> buildProperties = new ArrayList<>(); @@ -574,6 +579,7 @@ public abstract class ExportBaseCommand extends CamelCommand { run.kameletsVersion = kameletsVersion; run.javaVersion = javaVersion; run.localKameletDir = localKameletDir; + run.resourceDirs = resourceDirs; run.ignoreLoadingError = ignoreLoadingError; run.lazyBean = lazyBean; run.property = applicationProperties; @@ -896,6 +902,10 @@ public abstract class ExportBaseCommand extends CamelCommand { } else if (web) { targetDir = srcResourcesDir.resolve("META-INF/resources"); } else { + // skip files that belong to a resource dir (they are copied with structure preserved later) + if (isUnderResourceDir(f)) { + continue; + } targetDir = srcResourcesDir; } Files.createDirectories(targetDir); @@ -980,6 +990,8 @@ public abstract class ExportBaseCommand extends CamelCommand { } } + copyResourceDirs(srcResourcesDir); + if (!skipPlugins) { Set<PluginExporter> exporters = PluginHelper.getActivePlugins(getMain(), mavenResolver.repos()).values() .stream() @@ -995,6 +1007,38 @@ public abstract class ExportBaseCommand extends CamelCommand { } } + private void copyResourceDirs(Path srcResourcesDir) throws Exception { + if (resourceDirs == null || resourceDirs.isEmpty()) { + return; + } + for (String dir : resourceDirs) { + Path dirPath = Run.validateResourceDir(dir); + // use the last component as the target directory name + // so ../shared/schemas -> src/main/resources/schemas/ + Path baseName = dirPath.getFileName(); + for (Path source : Run.walkResourceDir(dirPath)) { + Path relativePath = dirPath.relativize(source); + Path target = srcResourcesDir.resolve(baseName).resolve(relativePath); + Files.createDirectories(target.getParent()); + Files.copy(source, target, StandardCopyOption.REPLACE_EXISTING); + } + } + } + + private boolean isUnderResourceDir(String file) { + if (resourceDirs == null || resourceDirs.isEmpty()) { + return false; + } + Path filePath = Paths.get(file).normalize(); + for (String dir : resourceDirs) { + Path dirPath = Paths.get(dir).normalize(); + if (filePath.startsWith(dirPath)) { + return true; + } + } + return false; + } + protected void adjustJavaSourceFileLine(String line, OutputStream fos) throws Exception { // noop } 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 e0e261bfb7f5..036bebb78412 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 @@ -180,6 +180,11 @@ public class Run extends CamelCommand { description = "Source directory for dynamically loading Camel file(s) to run. When using this, then files cannot be specified at the same time.") String sourceDir; + @Option(names = { "--resource-dir", "--resource-dirs" }, + description = "Additional resource directories to include on the classpath (recursive, preserving structure)", + split = ",") + List<String> resourceDirs = new ArrayList<>(); + @Option(names = { "--background" }, defaultValue = "false", description = "Run in the background") public boolean background; @@ -971,6 +976,16 @@ public class Run extends CamelCommand { } } + // walk resource directories and add files to classpath preserving directory structure + if (resourceDirs != null) { + for (String dir : resourceDirs) { + Path dirPath = validateResourceDir(dir); + for (Path f : walkResourceDir(dirPath)) { + sjClasspathFiles.add(f.toString()); + } + } + } + for (String file : files) { if (file.startsWith("clipboard") && !(Files.exists(Paths.get(file)))) { file = loadFromClipboard(file); @@ -1130,6 +1145,13 @@ public class Run extends CamelCommand { } else { writeSetting(main, profileProperties, JKUBE_FILES, () -> null); } + if (resourceDirs != null && !resourceDirs.isEmpty()) { + String dirs = String.join(",", resourceDirs); + main.addInitialProperty(RESOURCE_DIRS, dirs); + writeSettings(RESOURCE_DIRS, dirs); + } else { + writeSetting(main, profileProperties, RESOURCE_DIRS, () -> null); + } if (sjKamelets.length() > 0) { String loc = main.getInitialProperties().getProperty("camel.component.kamelet.location"); @@ -2669,6 +2691,32 @@ public class Run extends CamelCommand { return on.toLowerCase(Locale.ROOT).startsWith("readme"); } + static final int MAX_RESOURCE_DIR_FILES = 1000; + + static Path validateResourceDir(String dir) { + Path path = Paths.get(dir).normalize(); + if (path.isAbsolute()) { + throw new IllegalArgumentException("--resource-dirs only accepts relative paths: " + dir); + } + if (!Files.isDirectory(path)) { + throw new IllegalArgumentException("--resource-dirs path is not a directory: " + dir); + } + return path; + } + + static List<Path> walkResourceDir(Path dirPath) throws IOException { + try (Stream<Path> walk = Files.walk(dirPath)) { + List<Path> files = walk.filter(Files::isRegularFile).toList(); + if (files.size() > MAX_RESOURCE_DIR_FILES) { + throw new IllegalArgumentException( + "--resource-dirs directory contains " + files.size() + + " files which exceeds the limit of " + MAX_RESOURCE_DIR_FILES + ": " + + dirPath); + } + return files; + } + } + private void writeSettings(String key, String value) { try { // use java.util.Properties to ensure the value is escaped correctly diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/common/CamelJBangConstants.java b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/common/CamelJBangConstants.java index 403761e5997f..526867409907 100644 --- a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/common/CamelJBangConstants.java +++ b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/common/CamelJBangConstants.java @@ -60,6 +60,10 @@ public final class CamelJBangConstants { javaType = "String", label = "kubernetes") public static final String JKUBE_FILES = "camel.jbang.jkubeFiles"; + @Metadata(description = "Additional resource directories to include recursively, preserving directory structure (Use commas to separate multiple directories)", + javaType = "String") + public static final String RESOURCE_DIRS = "camel.jbang.resourceDirs"; + @Metadata(description = "Which runtime to use (camel-main, spring-boot, quarkus)", javaType = "String", enums = "camel-main,spring-boot,quarkus") public static final String RUNTIME = "camel.jbang.runtime"; diff --git a/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/ResourceDirsTest.java b/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/ResourceDirsTest.java new file mode 100644 index 000000000000..7eb3dd9fcffc --- /dev/null +++ b/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/ResourceDirsTest.java @@ -0,0 +1,160 @@ +/* + * 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.nio.file.Files; +import java.nio.file.Path; +import java.util.List; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.TempDir; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +class ResourceDirsTest { + + @Test + void validateShouldRejectAbsolutePath() { + assertThatThrownBy(() -> Run.validateResourceDir("/some/absolute/path")) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("only accepts relative paths"); + } + + @Test + void validateShouldRejectNonDirectory(@TempDir Path tempDir) throws Exception { + // create a regular file inside tempDir, then use a relative path to it + Path file = tempDir.resolve("notadir.txt"); + Files.writeString(file, "hello"); + + // use relative path from cwd to the file + Path relative = Path.of("").toAbsolutePath().relativize(file); + assertThatThrownBy(() -> Run.validateResourceDir(relative.toString())) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("not a directory"); + } + + @Test + void validateShouldAcceptRelativeDir(@TempDir Path tempDir) throws Exception { + Path dir = tempDir.resolve("soap"); + Files.createDirectories(dir); + + // use relative path from cwd to the dir + Path relative = Path.of("").toAbsolutePath().relativize(dir); + Path result = Run.validateResourceDir(relative.toString()); + assertThat(result).isNotNull(); + } + + @Test + void validateShouldAcceptDotDotPaths(@TempDir Path tempDir) throws Exception { + // create project/child and shared dirs, use ../shared from child's perspective + Path project = tempDir.resolve("project/child"); + Path shared = tempDir.resolve("shared"); + Files.createDirectories(project); + Files.createDirectories(shared); + + // use relative path from cwd — this will contain .. segments + Path relative = Path.of("").toAbsolutePath().relativize(shared); + Path result = Run.validateResourceDir(relative.toString()); + assertThat(result).isNotNull(); + } + + @Test + void walkShouldFindFilesRecursively(@TempDir Path tempDir) throws Exception { + Path dir = tempDir.resolve("soap"); + Path subDir = tempDir.resolve("soap/schemas"); + Files.createDirectories(subDir); + Files.writeString(dir.resolve("file.xsd"), "<xsd/>"); + Files.writeString(subDir.resolve("common.xsd"), "<xsd/>"); + + List<Path> files = Run.walkResourceDir(dir); + assertThat(files).hasSize(2); + assertThat(files).extracting(Path::getFileName).extracting(Path::toString) + .containsExactlyInAnyOrder("file.xsd", "common.xsd"); + } + + @Test + void walkShouldEnforceMaxFileLimit(@TempDir Path tempDir) throws Exception { + Path dir = tempDir.resolve("big"); + Files.createDirectories(dir); + + for (int i = 0; i < Run.MAX_RESOURCE_DIR_FILES + 1; i++) { + Files.writeString(dir.resolve("file" + i + ".txt"), "content"); + } + + assertThatThrownBy(() -> Run.walkResourceDir(dir)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("exceeds the limit"); + } + + @Test + void parentPathShouldMapToLastComponent(@TempDir Path tempDir) throws Exception { + // simulate ../shared/schemas structure where only the last dir name is used as target + Path shared = tempDir.resolve("shared/schemas"); + Files.createDirectories(shared); + Files.writeString(shared.resolve("common.xsd"), "<xsd/>"); + + Path dirPath = shared; + Path baseName = dirPath.getFileName(); + assertThat(baseName.toString()).isEqualTo("schemas"); + + // verify target path uses only the last component + Path srcResources = tempDir.resolve("export/src/main/resources"); + Files.createDirectories(srcResources); + + for (Path source : Run.walkResourceDir(dirPath)) { + Path relativePath = dirPath.relativize(source); + Path target = srcResources.resolve(baseName).resolve(relativePath); + Files.createDirectories(target.getParent()); + Files.copy(source, target); + } + + // ../shared/schemas/common.xsd -> src/main/resources/schemas/common.xsd + assertThat(srcResources.resolve("schemas/common.xsd")).exists(); + } + + @Test + void nestedParentPathShouldMapToLastComponent() { + // ../../mydata/foo -> last component is "foo" + Path path = Path.of("../../mydata/foo").normalize(); + assertThat(path.getFileName().toString()).isEqualTo("foo"); + } + + @Test + void deepSubdirectoryShouldPreserveStructure(@TempDir Path tempDir) throws Exception { + // create a deep structure: soap/types/common/base.xsd + Path dir = tempDir.resolve("soap"); + Path deep = tempDir.resolve("soap/types/common"); + Files.createDirectories(deep); + Files.writeString(dir.resolve("service.wsdl"), "<wsdl/>"); + Files.writeString(deep.resolve("base.xsd"), "<xsd/>"); + + Path baseName = dir.getFileName(); + Path srcResources = tempDir.resolve("export/src/main/resources"); + Files.createDirectories(srcResources); + + for (Path source : Run.walkResourceDir(dir)) { + Path relativePath = dir.relativize(source); + Path target = srcResources.resolve(baseName).resolve(relativePath); + Files.createDirectories(target.getParent()); + Files.copy(source, target); + } + + assertThat(srcResources.resolve("soap/service.wsdl")).exists(); + assertThat(srcResources.resolve("soap/types/common/base.xsd")).exists(); + } +} diff --git a/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/main/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/KubernetesExport.java b/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/main/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/KubernetesExport.java index 8baf5bc56aa1..57243c453ba6 100644 --- a/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/main/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/KubernetesExport.java +++ b/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/main/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/KubernetesExport.java @@ -185,6 +185,7 @@ public class KubernetesExport extends Export { logging = configurer.logging; loggingLevel = configurer.loggingLevel; verbose = configurer.verbose; + resourceDirs = configurer.resourceDirs; observe = true; // always include observability-services for kubernetes } @@ -662,6 +663,7 @@ public class KubernetesExport extends Export { String loggingLevel, boolean verbose, boolean skipPlugins, + List<String> resourceDirs, String camelQuarkusGroupId, String camelQuarkusArtifactId, String camelQuarkusVersion) implements QuarkusPlatformMixinSpec, MavenResolverMixinSpec { diff --git a/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/main/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/KubernetesRun.java b/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/main/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/KubernetesRun.java index 80b0ab78749b..d4aad60ce30c 100644 --- a/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/main/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/KubernetesRun.java +++ b/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/main/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/KubernetesRun.java @@ -207,6 +207,11 @@ public class KubernetesRun extends KubernetesBaseCommand { @CommandLine.Option(names = { "--exclude" }, description = "Exclude files by name or pattern") List<String> excludes = new ArrayList<>(); + @CommandLine.Option(names = { "--resource-dir", "--resource-dirs" }, + description = "Additional resource directories to include in src/main/resources (recursive, preserving structure)", + split = ",") + List<String> resourceDirs = new ArrayList<>(); + @CommandLine.Option(names = { "--package-scan-jars" }, defaultValue = "false", description = "Whether to automatic package scan JARs for custom Spring or Quarkus beans making them available for Camel CLI") boolean packageScanJars; @@ -482,6 +487,7 @@ public class KubernetesRun extends KubernetesBaseCommand { "info", verbose, skipPlugins, + resourceDirs, quarkusPlatformBoms.quarkusCamelBom().getGroupId(), quarkusPlatformBoms.quarkusCamelBom().getArtifactId(), quarkusPlatformBoms.quarkusCamelBom().getVersion());
