From 1abb6c1368ff9cea9c61c749d9266c66a8bb9843 Mon Sep 17 00:00:00 2001 From: Christoph Deppisch Date: Sun, 24 Mar 2024 11:49:04 +0100 Subject: [PATCH] CAMEL-20606: Create pipe on cluster with bind command - By default create pipe on the cluster with Camel K JBang plugin - Add wait and logs option to align with Camel K integration run command - Improve unit tests - Add bind command documentation --- .../modules/ROOT/pages/camel-jbang-k.adoc | 321 +++++++++++++++++- .../modules/ROOT/pages/camel-jbang.adoc | 124 ++++++- .../camel/dsl/jbang/core/commands/Bind.java | 2 +- .../dsl/jbang/core/commands/BindTest.java | 181 ++++------ .../camel/dsl/jbang/core/commands/k/Bind.java | 53 ++- .../core/commands/k/IntegrationLogs.java | 8 +- .../jbang/core/commands/k/IntegrationRun.java | 9 +- .../dsl/jbang/core/commands/k/BindTest.java | 103 ++++-- .../core/commands/k/IntegrationRunTest.java | 12 + .../jbang/core/commands/k/KubeBaseTest.java | 25 ++ .../camel/dsl/jbang/core/commands/k/pipe.yaml | 38 +++ 11 files changed, 691 insertions(+), 185 deletions(-) create mode 100644 dsl/camel-jbang/camel-jbang-plugin-k/src/test/resources/org/apache/camel/dsl/jbang/core/commands/k/pipe.yaml diff --git a/docs/user-manual/modules/ROOT/pages/camel-jbang-k.adoc b/docs/user-manual/modules/ROOT/pages/camel-jbang-k.adoc index 4cca0a82c0f5f..2eeff9fc6b741 100644 --- a/docs/user-manual/modules/ROOT/pages/camel-jbang-k.adoc +++ b/docs/user-manual/modules/ROOT/pages/camel-jbang-k.adoc @@ -24,6 +24,9 @@ camel plugin get ---- Now Camel JBang is able to run the subcommands offered by the plugin. + +== Run integrations + Simply run the integration using the `k` subcommand in Camel JBang. [source,bash] @@ -110,7 +113,7 @@ The run command offers a lot more options that you may use to configure the Came |Add a label to the integration. Use name values pairs like "--label my.company=hello". |--traits, -t -|Add a label to the integration. Use name values pairs like "--label my.company=hello". +|Add a trait configuration to the integration. Use name values pairs like "--trait trait.name.config=hello". |--use-flows |Write yaml sources as Flow objects in the integration custom resource (default=true). @@ -128,6 +131,8 @@ The run command offers a lot more options that you may use to configure the Came |Just output the generated integration custom resource (supports: yaml or json). |======================================================================= +== List integrations + You can list the available integration resources with the following command. [source,bash] @@ -139,6 +144,8 @@ my-route Running kit-123456789 1/1 This looks for all integrations in the current namespace and lists their individual status. +== Show integration logs + To inspect the log output of a running integration call: [source,bash] @@ -149,6 +156,8 @@ camel k logs my-route The command connects to the running integration Pod and prints the log output. Just terminate the process to stop printing the logs. +== Delete integrations + Of course, you may also delete an integration resource from the cluster. [source,bash] @@ -162,3 +171,313 @@ To remove all available integrations on the current namespace use the `--all` op ---- camel k delete --all ---- + +== Create integration pipes + +In some contexts (for example **"serverless"**) users often want to leverage the power of Apache Camel to be able to connect to various sources/sinks, with focus on connectivity to 3rd party technologies and services and less focus on doing complex processing (such as transformations or other enterprise integration patterns). + +Pipe resources represent a special form of Camel integrations where a source gets bound to a sink. +The operation to create such a Pipe resource is often related to as the process of binding a source to a sink. + +You can use the Camel JBang subcommand `bind` to create Pipe resources. +The result of this Pipe resource being created on a Kubernetes cluster is a running Camel integration. + +The Camel K bind command supports the following options: + +[width="100%",cols="1m,3",options="header",] +|======================================================================= +|Option |Description + +|--operator-id +|Operator id selected to manage this integration. (default=camel-k) + +|--source +|Source (from) such as a Kamelet or Camel endpoint uri that provides data.. + +|--sink +|Sink (to) such as a Kamelet or Camel endpoint uri where data should be sent to. + +|--step +|Add optional 1-n steps to the pipe processing. Each step represents a reference to a Kamelet of type action. + +|--property +|Add a pipe property in the form of [source,sink,error-handler,step-].= where is the step number starting from 1. + +|--error-handler +|Add error handler (none,log,sink:). Sink endpoints are expected in the format [[apigroup/]version:]kind:[namespace/]name, plain Camel URIs or Kamelet name. + +|--annotation +|Add an annotation to the integration. Use name values pairs like "--annotation my.company=hello". + +|--connect +|A Service that the integration should bind to, specified as [[apigroup/]version:]kind:[namespace/]name. + +|--traits +|Add a trait configuration to the integration. Use name values pairs like "--trait trait.name.config=hello". + +|--wait +|Wait for the integration to become ready. + +|--logs +|Print logs after integration has been started. + +|--output +|Just output the generated pipe custom resource (supports: file, yaml or json). +|======================================================================= + +Sources and sinks in a pipe may be Camel endpoint URIs, a Kamelet or a references to a Kubernetes resource (e.g. Knative brokers, Kafka topics). + +=== Binding Kamelets + +In a typical use case a Pipe connects Kamelets of type source and sink. +Usually a Kamelet gets identified by its name (e.g. timer-source, log-sink). + +[source,bash] +---- +camel k bind my-pipe --source timer-source --sink log-sink --property source.message="Camel rocks!" --property sink.showHeaders=true +---- + +The bind command receives the name of the pipe as a command argument and uses several options to specify the source and the sink. +In addition to that the user is able to specify properties on the individual source and sink (e.g. the message property on the timer-source Kamelet). + +The result of this command is a Pipe custom resource that you can apply to a Kubernetes cluster. + +[source,yaml] +---- +apiVersion: camel.apache.org/v1 +kind: Pipe +metadata: + name: my-pipe + annotations: + camel.apache.org/operator.id: camel-k +spec: + source: # <1> + ref: + kind: Kamelet + apiVersion: camel.apache.org/v1 + name: timer-source + properties: + message: "Camel rocks!" + sink: # <2> + ref: + kind: Kamelet + apiVersion: camel.apache.org/v1 + name: log-sink + properties: + showHeaders: true +---- +<1> Reference to the source that provides data +<2> Reference to the sink where data should be sent to + +Each Pipe resource uses an operator id annotation to specify which operator on the cluster should handle the resource. + +NOTE: The bind command is able to inspect the properties defined in the Kamelet specification in order to set default values. In case the Kamelet defines a required property that is not explicitly set by the user the bind command automatically creates a property placeholder with an example value. + +=== Add binding steps + +You can specify 1-n additional steps that get executed between the source and sink. + +[source,bash] +---- +camel k bind my-pipe --source timer-source --sink log-sink --step set-body-action --property step-1.value="Camel rocks!" +---- + +[source,yaml] +---- +apiVersion: camel.apache.org/v1 +kind: Pipe +metadata: + name: my-pipe +spec: + source: +# ... + steps: + - ref: + kind: Kamelet + apiVersion: camel.apache.org/v1 + name: set-body-action + properties: + value: "Camel rocks!" + sink: +# ... +---- + +NOTE: Each step should reverence a Kamelet of type `action`. +The properties for a step can be set with the respective `step-` prefix where `n` is the step number beginning with 1. + +=== Binding Camel endpoint URIs + +Instead of referencing a Kamelet or Kubernetes resource you can also configure the source/sink to be an explicit Camel URI. +For example, the following bind command is allowed: + +[source,bash] +---- +camel k bind my-pipe --source timer:tick --sink https://mycompany.com/the-service --property source.period=5000 +---- + +This will use the Camel endpoint URIs `timer:tick` and `log:info` as source and sink in the Pipe. +The properties are set as endpoint parameters. + +[source,yaml] +---- +apiVersion: camel.apache.org/v1 +kind: Pipe +metadata: + name: my-pipe +spec: + source: + uri: timer:tick # <1> + properties: + period: 5000 + sink: + uri: https://mycompany.com/the-service # <2> +---- +<1> Pipe with explicit Camel endpoint URI as source +<2> Pipe with explicit Camel endpoint URI as sink where the data gets pushed to + +This Pipe explicitly defines Camel endpoint URIs that act as a source and sink. + +NOTE: You can also specify endpoint parameters directly on the source/sink like `--source timer:tick?period=5000` + +=== Error handling + +You can configure an error handler in order to specify what to do when some event ends up with failure. +Pipes offer a mechanism to specify an error policy to adopt in case an event processing fails. + +In case of an exception thrown during the pipe processing the respective error handler will perform its actions. + +The Pipe knows different types of error handlers `none`, `log` and `sink`: + +* none -> Explicit `noErrorHandler` is set and the error is ignored. +* log -> Errors get logged to the output. +* sink -> Errors get pushed to a specified endpoint in the form of dead letter queue. + +The error handler may be configured with special properties that allow you to define the error handling behavior such as redelivery or delay policy. + +==== No error handler + +There may be certain cases where you want to just ignore any failure happening on your integration. +In this situation just use a `none` error handler. + +[source,bash] +---- +camel k bind my-pipe --source timer-source --sink log-sink --error-handler none +---- + +This results in following error handler configuration on the pipe: + +[source,yaml] +---- +apiVersion: camel.apache.org/v1 +kind: Pipe +metadata: + name: my-pipe +spec: + source: +# ... + sink: +# ... + errorHandler: + none: {} +---- + +==== Log error handler + +Apache Camel offers a default behavior for handling failure: log to standard output. +However, you can use the `log` error handler to specify other behaviors such as redelivery or delay policy. + +[source,bash] +---- +camel k bind my-pipe --source timer-source --sink log-sink --error-handler log --property error-handler.maximumRedeliveries=3 --property error-handler.redeliveryDelay=2000 +---- + +This results in the error handler configuration on the Pipe: + +[source,yaml] +---- +apiVersion: camel.apache.org/v1 +kind: Pipe +metadata: + name: my-pipe +spec: + source: +# ... + sink: +# ... + errorHandler: + log: + parameters: # <1> + redeliveryDelay: 2000 + maximumRedeliveries: 3 +---- +<1> Parameters belonging to the `log` error handler type + +==== Sink error handler + +The `sink` error handler is probably the most interesting error handler type as it allows you to redirect failing events to other components, such as a third party URI, a queue or topic or even another `Kamelet` which will be performing certain logic with the failing event. + +The sink error handler expects a proper endpoint URI which may be a reference to another Kamelet, a fully qualified custom resource reference or an arbitrary Camel endpoint URI. + +[source,bash] +---- +camel k bind my-pipe --source timer-source --sink log-sink --error-handler sink:my-error-handler --property error-handler.sink.message=ERROR! --property error-handler.maximumRedeliveries=1 +---- + +[source,yaml] +---- +apiVersion: camel.apache.org/v1 +kind: Pipe +metadata: + name: my-pipe +spec: + source: +# ... + sink: +# ... + errorHandler: + sink: + endpoint: + ref: # <1> + kind: Kamelet + apiVersion: camel.apache.org/v1 + name: my-error-handler + properties: + message: "ERROR!" # <2> + # ... + parameters: + maximumRedeliveries: 1 # <3> + # ... +---- +<1> You can use `ref` or `uri`. `ref` will be interpreted by the operator according the `kind`, `apiVersion` and `name`. You can use any `Kamelet`, `KafkaTopic` channel or `Knative` destination. +<2> Properties targeting the sink endpoint (in this example a property on the `Kamelet` named `my-error-handler`). Properties targeting the sink endpoint need to use the `error-handler.sink.*` prefix. +<3> Parameters for the error handler (such as redelivery or delay policy). Error handler parameters need to use the `error-handler.*` prefix. + +NOTE: The error handler properties are divided into properties that target the error handler sink endpoint and properties that should be set on the Camel error handler component (e.g. maximumRedeliveries). You need to specify the respective property prefix (`error-handler.` or `error-handler.sink.`) to decide where the property should be set. + +As an alternative to referencing a Kamelet as an error handler sink you may also use an arbitrary Camel endpoint URI. + +[source,bash] +---- +camel k bind my-pipe --source timer-source --sink log-sink --error-handler sink:log:error --property error-handler.sink.showHeaders=true +---- + +It creates the error handler specification as follows: + +[source,yaml] +---- +apiVersion: camel.apache.org/v1 +kind: Pipe +metadata: + name: my-pipe +spec: + source: +# ... + sink: +# ... + errorHandler: + sink: + endpoint: + uri: log:error + properties: + showHeaders: true +---- diff --git a/docs/user-manual/modules/ROOT/pages/camel-jbang.adoc b/docs/user-manual/modules/ROOT/pages/camel-jbang.adoc index 4c61e011c9882..cb9340b271ff2 100644 --- a/docs/user-manual/modules/ROOT/pages/camel-jbang.adoc +++ b/docs/user-manual/modules/ROOT/pages/camel-jbang.adoc @@ -1045,7 +1045,7 @@ camel plugin delete === Running Camel K integrations or pipes -Camel also supports running Camel K integrations and binding files, which are in CRD format (Kubernetes Custom Resource Definitions). +Camel also supports running Camel K integrations and pipes, which represent Kubernetes custom resources following a specific CRD format (Kubernetes Custom Resource Definitions). For example a pipe file named `joke.yaml`: @@ -1080,6 +1080,102 @@ Can be run with camel: camel run joke.yaml ---- +==== Binding Kamelets in a pipe + +Camel JBang is able to create the Pipe custom resource for you. +You can use the `bind` command to specify a source and a sink that should be set in the pipe. +As a result Camel JBang will create a proper Pipe custom resource for you. + +The command expects a file name as command argument and provides several options to define the source and the sink that should be used in the pipe. + +[source,bash] +---- +camel bind joke.yaml --source chuck-norris-source --sink log-sink +---- + +This creates the `joke.yaml` file that represents the Pipe resource. + +[source,yaml] +---- +apiVersion: camel.apache.org/v1 +kind: Pipe +metadata: + name: joke +spec: + source: + ref: + kind: Kamelet + apiVersion: camel.apache.org/v1 + name: chuck-norris-source + properties: + period: 5000 + sink: + ref: + kind: Kamelet + apiVersion: camel.apache.org/v1 + name: log-sink +---- + +NOTE: The bind command is able to inspect the Kamelets being used as a source and sink in order to automatically set all required properties. +In case the Kamelet defines a required property and the user has not specified such the command will automatically set this property with an example value. +Once the pipe resource file is generated you can review and set the properties as you wish. + +The bind command supports the following options: + +[width="100%",cols="1m,3",options="header",] +|======================================================================= +|Option |Description + +|--source +|Source (from) such as a Kamelet or Camel endpoint uri that provides data.. + +|--sink +|Sink (to) such as a Kamelet or Camel endpoint uri where data should be sent to. + +|--step +|Add optional 1-n steps to the pipe processing. Each step represents a reference to a Kamelet of type action. + +|--property +|Add a pipe property in the form of [source,sink,error-handler,step-].= where is the step number starting from 1. + +|--error-handler +|Add error handler (none,log,sink:). Sink endpoints are expected in the format [[apigroup/]version:]kind:[namespace/]name, plain Camel URIs or Kamelet name. + +|--output +|Output format generated by this command (supports: file, yaml or json). Default is "file". +|======================================================================= + +==== Binding explicit Camel URIs + +Usually, the source and sink reference a Kamelet by its name as shown in the previous section. +As an alternative, you can also just use an arbitrary Camel endpoint URI that acts as a source or sink in the pipe. + +[source,bash] +---- +camel bind joke.yaml --source chuck-norris-source --sink https://mycompany.com/the-service +---- + +As a result the Pipe resource uses the Camel endpoints as source and sink. + +[source,yaml] +---- +apiVersion: camel.apache.org/v1 +kind: Pipe +metadata: + name: my-pipe +spec: + source: +# ... + sink: + uri: https://mycompany.com/the-service # <1> +---- +<1> Pipe with explicit Camel endpoint URI as sink where the data gets pushed to + +==== Advanced binding options + +The Camel K JBang plugin also provides the bind command. It enhances the arbitrary bind command with the option to directly create this resource on the +Kubernetes cluster. Please refer to the plugin documentation for more complex examples and a full description on how to use the bind command options. + === Run from clipboard You can also run Camel routes directly from the OS clipboard. This allows to copy some code, @@ -1205,7 +1301,6 @@ TIP: See more options with `camel cmd send --help`. The source for this example is provided on GitHub at https://github.com/apache/camel-kamelets-examples/tree/main/jbang/mqtt)[camel-jbang MQTT example]. - === Controlling local Camel integrations To list the currently running Camel integrations you use the `ps` command: @@ -1213,9 +1308,9 @@ To list the currently running Camel integrations you use the `ps` command: [source,bash] ---- camel ps - PID NAME READY STATUS AGE - 61818 sample.camel.MyCamelApplica… 1/1 Running 26m38s - 62506 dude 1/1 Running 4m34s + PID NAME READY STATUS AGE + 61818 sample.camel.MyCamelApplica... 1/1 Running 26m38s + 62506 dude 1/1 Running 4m34s ---- This lists the PID, the name and age of the integration. @@ -1258,9 +1353,9 @@ This is done using the `--watch` parameter as follows: [source,bash] ---- camel ps --watch - PID NAME READY STATUS AGE - 61818 sample.camel.MyCamelApplica… 1/1 Running 26m38s - 62506 dude 1/1 Running 4m34s + PID NAME READY STATUS AGE + 61818 sample.camel.MyCamelApplica... 1/1 Running 26m38s + 62506 dude 1/1 Running 4m34s ---- ==== Controlling Spring Boot and Quarkus integrations @@ -1637,9 +1732,9 @@ must be installed in the running integration, this can be done, either explicit [source,bash] ---- camel ps - PID NAME READY STATUS AGE - 61818 sample.camel.MyCamelApplica… 1/1 Running 26m38s - 62506 dude.java 1/1 Running 4m34s + PID NAME READY STATUS AGE + 61818 sample.camel.MyCamelApplica... 1/1 Running 26m38s + 62506 dude.java 1/1 Running 4m34s ---- With the PID you can then attach Jolokia: @@ -2256,9 +2351,9 @@ A health check may often be failed due to an exception was thrown which can be s [source,bash] ---- camel get health --trace - PID NAME AGE ID RL STATE RATE SINCE MESSAGE - 61038 mykafka 6m19s camel/context R UP 187/187/- 1s/6m16s/- - 61038 mykafka 6m19s camel/kafka-consumer-kafka-not-secure… R DOWN 187/-/187 1s/-/6m16s KafkaConsumer is not ready - Error: Invalid url in bootstrap.servers: value + PID NAME AGE ID RL STATE RATE SINCE MESSAGE + 61038 mykafka 6m19s camel/context R UP 187/187/- 1s/6m16s/- + 61038 mykafka 6m19s camel/kafka-consumer-kafka-not-secure... R DOWN 187/-/187 1s/-/6m16s KafkaConsumer is not ready - Error: Invalid url in bootstrap.servers: value ------------------------------------------------------------------------------------------------------------------------ @@ -2591,7 +2686,6 @@ This can be suppressed by setting the option `suppressExceptions` to `true` as s [Body is null] ---- - === Transforming message using Components Some components can also be used for message transformation such as FlatPack, Velocity, FreeMarker, Thymeleaf, and good old XSLT. diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Bind.java b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Bind.java index 3a00564534270..61ab92c85acf4 100644 --- a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Bind.java +++ b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Bind.java @@ -75,7 +75,7 @@ public class Bind extends CamelCommand { String errorHandler; @CommandLine.Option(names = { "--property" }, - description = "Adds a pipe property in the form of [source|sink|step-].= where is the step number starting from 1", + description = "Adds a pipe property in the form of [source|sink|error-handler|step-].= where is the step number starting from 1", arity = "0") String[] properties; diff --git a/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/BindTest.java b/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/BindTest.java index 02cdc70e6e6e6..bdde0d78c43db 100644 --- a/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/BindTest.java +++ b/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/BindTest.java @@ -17,6 +17,7 @@ package org.apache.camel.dsl.jbang.core.commands; +import org.apache.camel.util.StringHelper; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; @@ -24,12 +25,7 @@ class BindTest extends CamelCommandBaseTest { @Test public void shouldBindKameletSourceToKameletSink() throws Exception { - Bind command = new Bind(new CamelJBangMain().withPrinter(printer)); - command.file = "timer-to-log"; - command.source = "timer-source"; - command.sink = "log-sink"; - command.output = "yaml"; - + Bind command = createCommand("timer", "log"); command.doCall(); String output = printer.getOutput(); @@ -58,11 +54,7 @@ public void shouldBindKameletSourceToKameletSink() throws Exception { @Test public void shouldBindKameletSourceToKameletSinkWithProperties() throws Exception { - Bind command = new Bind(new CamelJBangMain().withPrinter(printer)); - command.file = "timer-to-log"; - command.source = "timer-source"; - command.sink = "log-sink"; - command.output = "yaml"; + Bind command = createCommand("timer", "log"); command.properties = new String[] { "source.message=Hello", @@ -99,11 +91,7 @@ public void shouldBindKameletSourceToKameletSinkWithProperties() throws Exceptio @Test public void shouldBindWithSteps() throws Exception { - Bind command = new Bind(new CamelJBangMain().withPrinter(printer)); - command.file = "timer-to-http"; - command.source = "timer-source"; - command.sink = "http-sink"; - command.output = "yaml"; + Bind command = createCommand("timer", "http"); command.steps = new String[] { "set-body-action", @@ -151,11 +139,7 @@ public void shouldBindWithSteps() throws Exception { @Test public void shouldBindWithUriSteps() throws Exception { - Bind command = new Bind(new CamelJBangMain().withPrinter(printer)); - command.file = "timer-to-http"; - command.source = "timer-source"; - command.sink = "http-sink"; - command.output = "yaml"; + Bind command = createCommand("timer", "http"); command.steps = new String[] { "set-body-action", @@ -200,11 +184,7 @@ public void shouldBindWithUriSteps() throws Exception { @Test public void shouldBindWithStepsAndProperties() throws Exception { - Bind command = new Bind(new CamelJBangMain().withPrinter(printer)); - command.file = "timer-to-http"; - command.source = "timer-source"; - command.sink = "http-sink"; - command.output = "yaml"; + Bind command = createCommand("timer", "http"); command.steps = new String[] { "set-body-action", @@ -259,11 +239,7 @@ public void shouldBindWithStepsAndProperties() throws Exception { @Test public void shouldBindWithUriStepsAndProperties() throws Exception { - Bind command = new Bind(new CamelJBangMain().withPrinter(printer)); - command.file = "timer-to-http"; - command.source = "timer-source"; - command.sink = "http-sink"; - command.output = "yaml"; + Bind command = createCommand("timer", "http"); command.steps = new String[] { "set-body-action", @@ -313,11 +289,7 @@ public void shouldBindWithUriStepsAndProperties() throws Exception { @Test public void shouldBindWithUriStepsAndUriProperties() throws Exception { - Bind command = new Bind(new CamelJBangMain().withPrinter(printer)); - command.file = "timer-to-http"; - command.source = "timer-source"; - command.sink = "http-sink"; - command.output = "yaml"; + Bind command = createCommand("timer", "http"); command.steps = new String[] { "set-body-action", @@ -369,11 +341,7 @@ public void shouldBindWithUriStepsAndUriProperties() throws Exception { @Test public void shouldBindKameletSourceToUri() throws Exception { - Bind command = new Bind(new CamelJBangMain().withPrinter(printer)); - command.file = "timer-to-log"; - command.source = "timer-source"; - command.sink = "log:info"; - command.output = "yaml"; + Bind command = createCommand("timer", "log:info"); command.doCall(); @@ -400,11 +368,7 @@ public void shouldBindKameletSourceToUri() throws Exception { @Test public void shouldBindKameletSourceToUriWithProperties() throws Exception { - Bind command = new Bind(new CamelJBangMain().withPrinter(printer)); - command.file = "timer-to-log"; - command.source = "timer-source"; - command.sink = "log:info"; - command.output = "yaml"; + Bind command = createCommand("timer", "log:info"); command.properties = new String[] { "source.message=Hello", @@ -436,11 +400,7 @@ public void shouldBindKameletSourceToUriWithProperties() throws Exception { @Test public void shouldBindKameletSourceToUriWithUriProperties() throws Exception { - Bind command = new Bind(new CamelJBangMain().withPrinter(printer)); - command.file = "timer-to-log"; - command.source = "timer-source"; - command.sink = "log:info?showStreams=false"; - command.output = "yaml"; + Bind command = createCommand("timer", "log:info?showStreams=false"); command.properties = new String[] { "source.message=Hello", @@ -473,11 +433,7 @@ public void shouldBindKameletSourceToUriWithUriProperties() throws Exception { @Test public void shouldBindUriToUri() throws Exception { - Bind command = new Bind(new CamelJBangMain().withPrinter(printer)); - command.file = "timer-to-log"; - command.source = "timer:tick"; - command.sink = "log:info"; - command.output = "yaml"; + Bind command = createCommand("timer:tick", "log:info"); command.doCall(); @@ -501,11 +457,7 @@ public void shouldBindUriToUri() throws Exception { @Test public void shouldBindUriToUriWithProperties() throws Exception { - Bind command = new Bind(new CamelJBangMain().withPrinter(printer)); - command.file = "timer-to-log"; - command.source = "timer:tick"; - command.sink = "log:info"; - command.output = "yaml"; + Bind command = createCommand("timer:tick", "log:info"); command.properties = new String[] { "source.message=Hello", @@ -534,11 +486,7 @@ public void shouldBindUriToUriWithProperties() throws Exception { @Test public void shouldBindUriToUriWithUriProperties() throws Exception { - Bind command = new Bind(new CamelJBangMain().withPrinter(printer)); - command.file = "timer-to-log"; - command.source = "timer:tick?period=10000"; - command.sink = "log:info?showStreams=false"; - command.output = "yaml"; + Bind command = createCommand("timer:tick?period=10000", "log:info?showStreams=false"); command.properties = new String[] { "source.message=Hello", @@ -569,11 +517,7 @@ public void shouldBindUriToUriWithUriProperties() throws Exception { @Test public void shouldBindKameletSinkErrorHandler() throws Exception { - Bind command = new Bind(new CamelJBangMain().withPrinter(printer)); - command.file = "timer-to-log"; - command.source = "timer-source"; - command.sink = "log-sink"; - command.output = "yaml"; + Bind command = createCommand("timer", "log"); command.errorHandler = "sink:log-sink"; @@ -615,11 +559,7 @@ public void shouldBindKameletSinkErrorHandler() throws Exception { @Test public void shouldBindKameletSinkErrorHandlerWithParameters() throws Exception { - Bind command = new Bind(new CamelJBangMain().withPrinter(printer)); - command.file = "timer-to-log"; - command.source = "timer-source"; - command.sink = "log-sink"; - command.output = "yaml"; + Bind command = createCommand("timer", "log"); command.errorHandler = "sink:log-sink"; @@ -668,11 +608,7 @@ public void shouldBindKameletSinkErrorHandlerWithParameters() throws Exception { @Test public void shouldBindKameletSinkErrorHandlerAndSinkProperties() throws Exception { - Bind command = new Bind(new CamelJBangMain().withPrinter(printer)); - command.file = "timer-to-log"; - command.source = "timer-source"; - command.sink = "log-sink"; - command.output = "yaml"; + Bind command = createCommand("timer", "log"); command.errorHandler = "sink:log-sink"; @@ -722,11 +658,7 @@ public void shouldBindKameletSinkErrorHandlerAndSinkProperties() throws Exceptio @Test public void shouldBindEndpointUriSinkErrorHandler() throws Exception { - Bind command = new Bind(new CamelJBangMain().withPrinter(printer)); - command.file = "timer-to-log"; - command.source = "timer-source"; - command.sink = "log-sink"; - command.output = "yaml"; + Bind command = createCommand("timer", "log"); command.errorHandler = "sink:log:error"; @@ -765,11 +697,7 @@ public void shouldBindEndpointUriSinkErrorHandler() throws Exception { @Test public void shouldBindEndpointUriSinkErrorHandlerWithParameters() throws Exception { - Bind command = new Bind(new CamelJBangMain().withPrinter(printer)); - command.file = "timer-to-log"; - command.source = "timer-source"; - command.sink = "log-sink"; - command.output = "yaml"; + Bind command = createCommand("timer", "log"); command.errorHandler = "sink:log:error"; @@ -815,11 +743,7 @@ public void shouldBindEndpointUriSinkErrorHandlerWithParameters() throws Excepti @Test public void shouldBindEndpointUriSinkErrorHandlerAndSinkProperties() throws Exception { - Bind command = new Bind(new CamelJBangMain().withPrinter(printer)); - command.file = "timer-to-log"; - command.source = "timer-source"; - command.sink = "log-sink"; - command.output = "yaml"; + Bind command = createCommand("timer", "log"); command.errorHandler = "sink:log:error"; @@ -866,11 +790,7 @@ public void shouldBindEndpointUriSinkErrorHandlerAndSinkProperties() throws Exce @Test public void shouldBindEndpointUriSinkErrorHandlerAndUriProperties() throws Exception { - Bind command = new Bind(new CamelJBangMain().withPrinter(printer)); - command.file = "timer-to-log"; - command.source = "timer-source"; - command.sink = "log-sink"; - command.output = "yaml"; + Bind command = createCommand("timer", "log"); command.errorHandler = "sink:log:error?showStreams=false"; @@ -918,11 +838,7 @@ public void shouldBindEndpointUriSinkErrorHandlerAndUriProperties() throws Excep @Test public void shouldBindWithLogErrorHandler() throws Exception { - Bind command = new Bind(new CamelJBangMain().withPrinter(printer)); - command.file = "timer-to-log"; - command.source = "timer-source"; - command.sink = "log-sink"; - command.output = "yaml"; + Bind command = createCommand("timer", "log"); command.errorHandler = "log"; @@ -957,11 +873,7 @@ public void shouldBindWithLogErrorHandler() throws Exception { @Test public void shouldBindWithLogErrorHandlerWithParameters() throws Exception { - Bind command = new Bind(new CamelJBangMain().withPrinter(printer)); - command.file = "timer-to-log"; - command.source = "timer-source"; - command.sink = "log-sink"; - command.output = "yaml"; + Bind command = createCommand("timer", "log"); command.errorHandler = "log"; @@ -1003,11 +915,7 @@ public void shouldBindWithLogErrorHandlerWithParameters() throws Exception { @Test public void shouldBindWithNoErrorHandler() throws Exception { - Bind command = new Bind(new CamelJBangMain().withPrinter(printer)); - command.file = "timer-to-log"; - command.source = "timer-source"; - command.sink = "log-sink"; - command.output = "yaml"; + Bind command = createCommand("timer", "log"); command.errorHandler = "none"; @@ -1041,10 +949,7 @@ public void shouldBindWithNoErrorHandler() throws Exception { @Test public void shouldSupportJsonOutput() throws Exception { - Bind command = new Bind(new CamelJBangMain().withPrinter(printer)); - command.file = "timer-to-log"; - command.source = "timer-source"; - command.sink = "log-sink"; + Bind command = createCommand("timer", "log"); command.output = "json"; command.doCall(); @@ -1082,14 +987,42 @@ public void shouldSupportJsonOutput() throws Exception { @Test public void shouldHandleUnsupportedOutputFormat() throws Exception { - Bind command = new Bind(new CamelJBangMain().withPrinter(printer)); - command.file = "timer-to-log"; - command.source = "timer-source"; - command.sink = "log-sink"; + Bind command = createCommand("timer", "log"); command.output = "wrong"; Assertions.assertEquals(-1, command.doCall()); Assertions.assertEquals("Unsupported output format 'wrong' (supported: file, yaml, json)", printer.getOutput()); } + + private Bind createCommand(String source, String sink) { + Bind command = new Bind(new CamelJBangMain().withPrinter(printer)); + + String sourceName; + String sourceUri; + if (source.contains(":")) { + sourceName = StringHelper.before(source, ":"); + sourceUri = source; + } else { + sourceName = source; + sourceUri = source + "-source"; + } + + String sinkName; + String sinkUri; + if (sink.contains(":")) { + sinkName = StringHelper.before(sink, ":"); + sinkUri = sink; + } else { + sinkName = sink; + sinkUri = sink + "-sink"; + } + + command.file = sourceName + "-to-" + sinkName + ".yaml"; + command.source = sourceUri; + command.sink = sinkUri; + command.output = "yaml"; + + return command; + } } diff --git a/dsl/camel-jbang/camel-jbang-plugin-k/src/main/java/org/apache/camel/dsl/jbang/core/commands/k/Bind.java b/dsl/camel-jbang/camel-jbang-plugin-k/src/main/java/org/apache/camel/dsl/jbang/core/commands/k/Bind.java index c536045c68fa4..c5531d1add460 100644 --- a/dsl/camel-jbang/camel-jbang-plugin-k/src/main/java/org/apache/camel/dsl/jbang/core/commands/k/Bind.java +++ b/dsl/camel-jbang/camel-jbang-plugin-k/src/main/java/org/apache/camel/dsl/jbang/core/commands/k/Bind.java @@ -21,9 +21,12 @@ import java.util.Arrays; import java.util.List; import java.util.Stack; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicBoolean; import org.apache.camel.dsl.jbang.core.commands.CamelJBangMain; import org.apache.camel.util.ObjectHelper; +import org.apache.camel.v1.Pipe; import org.apache.camel.v1.integrationspec.Traits; import org.apache.camel.v1.integrationspec.traits.ServiceBinding; import picocli.CommandLine; @@ -36,19 +39,22 @@ public class Bind extends KubeBaseCommand { private final org.apache.camel.dsl.jbang.core.commands.Bind delegate; - @CommandLine.Parameters(description = "Name of pipe", arity = "1", + @CommandLine.Parameters(description = "The name of the Pipe resource created on the cluster.", arity = "1", paramLabel = "", parameterConsumer = NameConsumer.class) Path pipeName; // Defined only for code completion; the field never used String name; - @CommandLine.Option(names = { "--source" }, description = "Source (from) such as a Kamelet or Camel endpoint uri", + @CommandLine.Option(names = { "--source" }, + description = "Source (from) such as a Kamelet or Camel endpoint uri that provides data.", required = true) String source; - @CommandLine.Option(names = { "--step" }, description = "Optional steps such as a Kamelet or Camel endpoint uri") + @CommandLine.Option(names = { "--step" }, + description = "Add optional 1-n steps to the pipe processing. Each step represents a reference to a Kamelet of type action.") String[] steps; - @CommandLine.Option(names = { "--sink" }, description = "Sink (to) such as a Kamelet or Camel endpoint uri", + @CommandLine.Option(names = { "--sink" }, + description = "Sink (to) such as a Kamelet or Camel endpoint uri where data should be sent to.", required = true) String sink; @@ -57,12 +63,11 @@ public class Bind extends KubeBaseCommand { String errorHandler; @CommandLine.Option(names = { "--property" }, - description = "Adds a pipe property in the form of [source|sink|step-].= where is the step number starting from 1", + description = "Add a pipe property in the form of [source|sink|error-handler|step-].= where is the step number starting from 1.", arity = "0") String[] properties; @CommandLine.Option(names = { "--output" }, - defaultValue = "file", description = "Output format generated by this command (supports: file, yaml or json).") String output; @@ -83,6 +88,12 @@ public class Bind extends KubeBaseCommand { description = "Add a label to the integration. Use name values pairs like \"--label my.company=hello\".") String[] traits; + @CommandLine.Option(names = { "--wait" }, description = "Wait for the pipe to become ready.") + boolean wait; + + @CommandLine.Option(names = { "--logs" }, description = "Print logs after pipe has been started.") + boolean logs; + public Bind(CamelJBangMain main) { super(main); delegate = new org.apache.camel.dsl.jbang.core.commands.Bind( @@ -109,7 +120,6 @@ public Integer doCall() throws Exception { delegate.setSteps(steps); delegate.setErrorHandler(errorHandler); delegate.setProperties(properties); - delegate.setOutput(output); String pipe = delegate.constructPipe(); @@ -171,7 +181,34 @@ public Integer doCall() throws Exception { pipe = pipe.replaceFirst("\\{\\{ \\.IntegrationSpec }}\n", integrationSpec); - return delegate.dumpPipe(pipe); + if (output != null) { + delegate.setOutput(output); + return delegate.dumpPipe(pipe); + } + + Pipe pipeResource = KubernetesHelper.yaml().loadAs(pipe, Pipe.class); + final AtomicBoolean updated = new AtomicBoolean(false); + client(Pipe.class).resource(pipeResource).createOr(it -> { + updated.set(true); + return it.update(); + }); + + if (updated.get()) { + printer().printf("Pipe %s updated%n", pipeResource.getMetadata().getName()); + } else { + printer().printf("Pipe %s created%n", pipeResource.getMetadata().getName()); + } + + if (wait || logs) { + client(Pipe.class).withName(pipeResource.getMetadata().getName()) + .waitUntilCondition(it -> "Running".equals(it.getStatus().getPhase()), 10, TimeUnit.MINUTES); + } + + if (logs) { + new IntegrationLogs(getMain()).watchLogs(pipeResource.getMetadata().getName()); + } + + return 0; } static class NameConsumer extends ParameterConsumer { diff --git a/dsl/camel-jbang/camel-jbang-plugin-k/src/main/java/org/apache/camel/dsl/jbang/core/commands/k/IntegrationLogs.java b/dsl/camel-jbang/camel-jbang-plugin-k/src/main/java/org/apache/camel/dsl/jbang/core/commands/k/IntegrationLogs.java index faf96f0c27c5a..a9d5919083f97 100644 --- a/dsl/camel-jbang/camel-jbang-plugin-k/src/main/java/org/apache/camel/dsl/jbang/core/commands/k/IntegrationLogs.java +++ b/dsl/camel-jbang/camel-jbang-plugin-k/src/main/java/org/apache/camel/dsl/jbang/core/commands/k/IntegrationLogs.java @@ -55,13 +55,13 @@ public Integer doCall() throws Exception { return 0; } - watchLogs(integration); + watchLogs(integration.getMetadata().getName()); return 0; } - void watchLogs(Integration integration) { - PodList pods = pods().withLabel(KubeCommand.INTEGRATION_LABEL, integration.getMetadata().getName()).list(); + void watchLogs(String integrationName) { + PodList pods = pods().withLabel(KubeCommand.INTEGRATION_LABEL, integrationName).list(); Pod pod = pods.getItems().stream() .filter(p -> p.getStatus().getPhase() != null && !"Terminated".equals(p.getStatus().getPhase())) @@ -73,7 +73,7 @@ void watchLogs(Integration integration) { if (pod.getSpec().getContainers().stream() .anyMatch(container -> KubeCommand.INTEGRATION_CONTAINER_NAME.equals(container.getName()))) { containerName = KubeCommand.INTEGRATION_CONTAINER_NAME; - } else if (pod.getSpec().getContainers().size() > 0) { + } else if (!pod.getSpec().getContainers().isEmpty()) { containerName = pod.getSpec().getContainers().get(0).getName(); } } diff --git a/dsl/camel-jbang/camel-jbang-plugin-k/src/main/java/org/apache/camel/dsl/jbang/core/commands/k/IntegrationRun.java b/dsl/camel-jbang/camel-jbang-plugin-k/src/main/java/org/apache/camel/dsl/jbang/core/commands/k/IntegrationRun.java index a435ad67b147c..4acc18ed8c2f3 100644 --- a/dsl/camel-jbang/camel-jbang-plugin-k/src/main/java/org/apache/camel/dsl/jbang/core/commands/k/IntegrationRun.java +++ b/dsl/camel-jbang/camel-jbang-plugin-k/src/main/java/org/apache/camel/dsl/jbang/core/commands/k/IntegrationRun.java @@ -147,7 +147,7 @@ public class IntegrationRun extends KubeBaseCommand { String[] labels; @CommandLine.Option(names = { "--traits", "-t" }, - description = "Add a label to the integration. Use name values pairs like \"--label my.company=hello\".") + description = "Add a trait configuration to the integration. Use name values pairs like \"--trait trait.name.config=hello\".") String[] traits; @CommandLine.Option(names = { "--use-flows" }, defaultValue = "true", @@ -313,7 +313,10 @@ public Integer doCall() throws Exception { case "yaml" -> printer().println(KubernetesHelper.yaml().dumpAsMap(integration)); case "json" -> printer().println( JSonHelper.prettyPrint(KubernetesHelper.json().writer().writeValueAsString(integration), 2)); - default -> printer().printf("Unsupported output format %s%n", output); + default -> { + printer().printf("Unsupported output format '%s' (supported: yaml, json)%n", output); + return -1; + } } return 0; @@ -337,7 +340,7 @@ public Integer doCall() throws Exception { } if (logs) { - new IntegrationLogs(getMain()).watchLogs(integration); + new IntegrationLogs(getMain()).watchLogs(integration.getMetadata().getName()); } return 0; diff --git a/dsl/camel-jbang/camel-jbang-plugin-k/src/test/java/org/apache/camel/dsl/jbang/core/commands/k/BindTest.java b/dsl/camel-jbang/camel-jbang-plugin-k/src/test/java/org/apache/camel/dsl/jbang/core/commands/k/BindTest.java index 9809bf44ee761..eafc0c209ded0 100644 --- a/dsl/camel-jbang/camel-jbang-plugin-k/src/test/java/org/apache/camel/dsl/jbang/core/commands/k/BindTest.java +++ b/dsl/camel-jbang/camel-jbang-plugin-k/src/test/java/org/apache/camel/dsl/jbang/core/commands/k/BindTest.java @@ -18,18 +18,47 @@ package org.apache.camel.dsl.jbang.core.commands.k; import org.apache.camel.dsl.jbang.core.commands.CamelJBangMain; +import org.apache.camel.util.StringHelper; +import org.apache.camel.v1.Pipe; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; class BindTest extends KubeBaseTest { + @Test + public void shouldCreatePipe() throws Exception { + Bind command = createCommand("timer", "http"); + command.output = null; + command.doCall(); + + Assertions.assertEquals("Pipe timer-to-http created", printer.getOutput()); + + Pipe created = kubernetesClient.resources(Pipe.class).withName("timer-to-http").get(); + Assertions.assertEquals("camel-k", created.getMetadata().getAnnotations().get(KubeCommand.OPERATOR_ID_LABEL)); + } + + @Test + public void shouldUpdatePipe() throws Exception { + Pipe pipe = createPipe("timer-to-log"); + kubernetesClient.resources(Pipe.class).resource(pipe).create(); + + Bind command = createCommand("timer", "log"); + command.output = null; + + command.properties = new String[] { + "sink.showHeaders=true" + }; + command.doCall(); + + Assertions.assertEquals("Pipe timer-to-log updated", printer.getOutput()); + + Pipe created = kubernetesClient.resources(Pipe.class).withName("timer-to-log").get(); + Assertions.assertEquals("camel-k", created.getMetadata().getAnnotations().get(KubeCommand.OPERATOR_ID_LABEL)); + } + @Test public void shouldBindWithDefaultOperatorId() throws Exception { - Bind command = new Bind(new CamelJBangMain().withPrinter(printer)); - command.name = "timer-to-log"; - command.source = "timer-source"; - command.sink = "log-sink"; - command.output = "yaml"; + Bind command = createCommand("timer", "log"); command.doCall(); @@ -61,11 +90,7 @@ public void shouldBindWithDefaultOperatorId() throws Exception { @Test public void shouldBindWithAnnotations() throws Exception { - Bind command = new Bind(new CamelJBangMain().withPrinter(printer)); - command.name = "timer-to-log"; - command.source = "timer-source"; - command.sink = "log-sink"; - command.output = "yaml"; + Bind command = createCommand("timer", "log"); command.annotations = new String[] { "app=camel-k" @@ -102,11 +127,7 @@ public void shouldBindWithAnnotations() throws Exception { @Test public void shouldBindWithTraits() throws Exception { - Bind command = new Bind(new CamelJBangMain().withPrinter(printer)); - command.name = "timer-to-log"; - command.source = "timer-source"; - command.sink = "log-sink"; - command.output = "yaml"; + Bind command = createCommand("timer", "log"); command.traits = new String[] { "mount.configs=configmap:my-cm", @@ -154,11 +175,7 @@ public void shouldBindWithTraits() throws Exception { @Test public void shouldBindWithServiceBindings() throws Exception { - Bind command = new Bind(new CamelJBangMain().withPrinter(printer)); - command.name = "timer-to-log"; - command.source = "timer-source"; - command.sink = "log-sink"; - command.output = "yaml"; + Bind command = createCommand("timer", "http"); command.connects = new String[] { "serving.knative.dev/v1:Service:my-service" @@ -171,7 +188,7 @@ public void shouldBindWithServiceBindings() throws Exception { apiVersion: camel.apache.org/v1 kind: Pipe metadata: - name: timer-to-log + name: timer-to-http annotations: camel.apache.org/operator.id: camel-k spec: @@ -192,19 +209,15 @@ public void shouldBindWithServiceBindings() throws Exception { ref: kind: Kamelet apiVersion: camel.apache.org/v1 - name: log-sink - #properties: - #key: "value" + name: http-sink + properties: + url: "https://my-service/path" """.trim(), output); } @Test public void shouldFailWithMissingOperatorId() throws Exception { - Bind command = new Bind(new CamelJBangMain().withPrinter(printer)); - command.name = "timer-to-log"; - command.source = "timer-source"; - command.sink = "log-sink"; - command.output = "yaml"; + Bind command = createCommand("timer:tick", "log"); command.operatorId = ""; @@ -212,4 +225,36 @@ public void shouldFailWithMissingOperatorId() throws Exception { Assertions.assertEquals("Operator id must be set", printer.getOutput()); } + + private Bind createCommand(String source, String sink) { + Bind command = new Bind(new CamelJBangMain().withPrinter(printer)); + command.withClient(kubernetesClient); + + String sourceName; + String sourceUri; + if (source.contains(":")) { + sourceName = StringHelper.before(source, ":"); + sourceUri = source; + } else { + sourceName = source; + sourceUri = source + "-source"; + } + + String sinkName; + String sinkUri; + if (sink.contains(":")) { + sinkName = StringHelper.before(sink, ":"); + sinkUri = sink; + } else { + sinkName = sink; + sinkUri = sink + "-sink"; + } + + command.name = sourceName + "-to-" + sinkName + ".yaml"; + command.source = sourceUri; + command.sink = sinkUri; + command.output = "yaml"; + + return command; + } } diff --git a/dsl/camel-jbang/camel-jbang-plugin-k/src/test/java/org/apache/camel/dsl/jbang/core/commands/k/IntegrationRunTest.java b/dsl/camel-jbang/camel-jbang-plugin-k/src/test/java/org/apache/camel/dsl/jbang/core/commands/k/IntegrationRunTest.java index 0a6a0e3df7c3b..318bae746215d 100644 --- a/dsl/camel-jbang/camel-jbang-plugin-k/src/test/java/org/apache/camel/dsl/jbang/core/commands/k/IntegrationRunTest.java +++ b/dsl/camel-jbang/camel-jbang-plugin-k/src/test/java/org/apache/camel/dsl/jbang/core/commands/k/IntegrationRunTest.java @@ -656,6 +656,18 @@ public void shouldFailWithMissingOperatorId() throws Exception { Assertions.assertEquals("Operator id must be set", printer.getOutput()); } + @Test + public void shouldHandleUnsupportedOutputFormat() throws Exception { + IntegrationRun command = createCommand(); + command.filePaths = new String[] { "classpath:route.yaml" }; + command.useFlows = false; + command.output = "wrong"; + + Assertions.assertEquals(-1, command.doCall()); + + Assertions.assertEquals("Unsupported output format 'wrong' (supported: yaml, json)", printer.getOutput()); + } + private IntegrationRun createCommand() { IntegrationRun command = new IntegrationRun(new CamelJBangMain().withPrinter(printer)); command.withClient(kubernetesClient); diff --git a/dsl/camel-jbang/camel-jbang-plugin-k/src/test/java/org/apache/camel/dsl/jbang/core/commands/k/KubeBaseTest.java b/dsl/camel-jbang/camel-jbang-plugin-k/src/test/java/org/apache/camel/dsl/jbang/core/commands/k/KubeBaseTest.java index ab3dde9278fe7..c4df9d8ec17b1 100644 --- a/dsl/camel-jbang/camel-jbang-plugin-k/src/test/java/org/apache/camel/dsl/jbang/core/commands/k/KubeBaseTest.java +++ b/dsl/camel-jbang/camel-jbang-plugin-k/src/test/java/org/apache/camel/dsl/jbang/core/commands/k/KubeBaseTest.java @@ -32,6 +32,8 @@ import org.apache.camel.util.IOHelper; import org.apache.camel.v1.Integration; import org.apache.camel.v1.IntegrationSpec; +import org.apache.camel.v1.Pipe; +import org.apache.camel.v1.PipeSpec; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; @@ -41,6 +43,7 @@ public class KubeBaseTest { protected static Integration integration; + protected static Pipe pipe; private KubernetesMockServer k8sServer; @@ -90,4 +93,26 @@ protected Integration createIntegration(String name) throws IOException { return created; } + protected Pipe createPipe() throws IOException { + return createPipe("pipe"); + } + + protected Pipe createPipe(String name) throws IOException { + if (pipe == null) { + pipe = KubernetesHelper.yaml().loadAs( + IOHelper.loadText(KubeBaseTest.class.getResourceAsStream("pipe.yaml")), Pipe.class); + } + + Pipe created = new Pipe(); + created.getMetadata().setName(name); + created.setSpec(new PipeSpec()); + created.getSpec().setSource(pipe.getSpec().getSource()); + created.getSpec().setSink(pipe.getSpec().getSink()); + created.getSpec().setSteps(pipe.getSpec().getSteps()); + created.getSpec().setErrorHandler(pipe.getSpec().getErrorHandler()); + created.getSpec().setIntegration(pipe.getSpec().getIntegration()); + + return created; + } + } diff --git a/dsl/camel-jbang/camel-jbang-plugin-k/src/test/resources/org/apache/camel/dsl/jbang/core/commands/k/pipe.yaml b/dsl/camel-jbang/camel-jbang-plugin-k/src/test/resources/org/apache/camel/dsl/jbang/core/commands/k/pipe.yaml new file mode 100644 index 0000000000000..5ad3d12a25512 --- /dev/null +++ b/dsl/camel-jbang/camel-jbang-plugin-k/src/test/resources/org/apache/camel/dsl/jbang/core/commands/k/pipe.yaml @@ -0,0 +1,38 @@ +# +# 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. +# + +apiVersion: camel.apache.org/v1 +kind: Pipe +metadata: + name: timer-to-log + annotations: + camel.apache.org/operator.id: camel-k +spec: + source: + ref: + kind: Kamelet + apiVersion: camel.apache.org/v1 + name: timer-source + properties: + message: "hello world" + sink: + ref: + kind: Kamelet + apiVersion: camel.apache.org/v1 + name: log-sink + properties: + showHeaders: true