diff --git a/task/camel-run/0.1/README.md b/task/camel-run/0.1/README.md new file mode 100644 index 0000000000..8d263db2eb --- /dev/null +++ b/task/camel-run/0.1/README.md @@ -0,0 +1,181 @@ +# Camel run + +This Task runs [Apache Camel](https://camel.apache.org/) integrations using [Camel JBang](https://camel.apache.org/manual/camel-jbang.html). + +Camel JBang is a lightweight tool for running Camel routes without requiring complex setup or operators. It supports multiple runtimes (Camel Main, Spring Boot, Quarkus) and provides features like live reload, developer console, and observability. + +## Install the Task + +```shell +kubectl apply -f https://github.com/tektoncd/catalog/raw/main/task/camel-run/0.1/camel-run.yaml +``` + +## Prerequisites + +When using this task in a pipeline with `git-clone` task (as shown in the samples), you need to install the git-clone task first, if it is not already available: + +```shell +kubectl apply -f https://github.com/tektoncd/catalog/raw/main/task/git-clone/0.10/git-clone.yaml +``` + +## Parameters + +- **camel-jbang-image**: The name of the image containing the Camel JBang CLI (_default:_ docker.io/apache/camel-jbang:4.17.0). For production use, consider using a digest reference like `docker.io/apache/camel-jbang@sha256:7979e8c9e25d6ff136372f60ad7be74af3e1cee2e279d95b666bdae40d3b64e4` +- **filename**: The Camel file(s) to run. Multiple files separated by space (_default:_ empty, will use application.properties). _Format:_ `"file1.yaml file2.yaml"` or `"route.yaml"` +- **runtime**: Runtime to use. Valid values: `camel-main`, `spring-boot`, `quarkus` (_default:_ camel-main). +- **dependencies**: Additional dependencies to add. Comma-separated list (_default:_ empty). _Format:_ `"org.apache.camel:camel-http,org.apache.camel:camel-jackson"` +- **properties**: Comma separated list of properties files (_default:_ empty). _Format:_ `"application.properties,custom.properties"` +- **property**: Additional properties in key=value format. Multiple properties separated by space (_default:_ empty). _Format:_ `"key1=value1 key2=value2"` +- **port**: Port for embedded HTTP server. Use 0 for dynamic port, -1 to disable (_default:_ "-1"). +- **max-seconds**: Maximum seconds to run before stopping. Use 0 for unlimited (_default:_ "0"). +- **logging-level**: Logging level: ERROR, WARN, INFO, DEBUG, or TRACE (_default:_ info). +- **dev**: Enable dev mode with live reload when source files are updated (_default:_ "false"). +- **console**: Enable developer console at /q/dev (_default:_ "false"). +- **observe**: Enable observability services including health and metrics endpoints (_default:_ "false"). +- **extra-args**: Additional arguments to pass to camel run command (_default:_ empty). +- **output-log**: Path to save camel run output log. If empty, no log file will be generated (_default:_ "$(workspaces.source.path)/camel-run.log"). + +## Workspaces + +* **source**: A [Workspace](https://github.com/tektoncd/pipeline/blob/main/docs/workspaces.md) containing the Camel source files to run. + +## Results + +- **exit-code**: The exit code from the camel run command. + +## Platforms + +The Task can be run on `linux/amd64` platform. + +## Security + +This task runs as a non-root user (UID 1000) for security. The task uses environment variables to pass parameters to the script, preventing script injection vulnerabilities. + +## Usage + +### Basic Usage + +Run a simple Camel route: + +```yaml +apiVersion: tekton.dev/v1beta1 +kind: TaskRun +metadata: + name: camel-run-example +spec: + taskRef: + name: camel-run + params: + - name: filename + value: route.yaml + workspaces: + - name: source + persistentVolumeClaim: + claimName: camel-source-pvc +``` + +### With Properties and Dependencies + +Run a Camel route with external dependencies and properties: + +```yaml +apiVersion: tekton.dev/v1beta1 +kind: TaskRun +metadata: + name: camel-run-advanced +spec: + taskRef: + name: camel-run + params: + - name: filename + value: route.yaml + - name: dependencies + value: "org.apache.camel:camel-http,org.apache.camel:camel-opentelemetry2" + - name: properties + value: "application.properties" + - name: property + value: "camel.component.http.timeout=5000" + - name: port + value: "8080" + - name: logging-level + value: "DEBUG" + workspaces: + - name: source + persistentVolumeClaim: + claimName: camel-source-pvc +``` + +### Dev Mode with Console + +Run in development mode with live reload and developer console: + +```yaml +apiVersion: tekton.dev/v1beta1 +kind: TaskRun +metadata: + name: camel-run-dev +spec: + taskRef: + name: camel-run + params: + - name: filename + value: route.yaml + - name: dev + value: "true" + - name: console + value: "true" + - name: port + value: "8080" + workspaces: + - name: source + persistentVolumeClaim: + claimName: camel-source-pvc +``` + +### Using Different Runtime + +Run with Quarkus runtime: + +```yaml +apiVersion: tekton.dev/v1beta1 +kind: TaskRun +metadata: + name: camel-run-quarkus +spec: + taskRef: + name: camel-run + params: + - name: filename + value: route.yaml + - name: runtime + value: "quarkus" + workspaces: + - name: source + persistentVolumeClaim: + claimName: camel-source-pvc +``` + +## Integration with Pipelines + +Use the [sample pipeline](../0.1/samples/run-basic.yaml) as a reference for integrating camel-run into a complete CI/CD pipeline that fetches code from Git and runs the Camel integration. + +### Circuit Breaker Example + +The sample pipeline demonstrates running the [circuit-breaker example](https://github.com/apache/camel-jbang-examples/tree/main/circuit-breaker) from the Apache Camel JBang examples repository. This example shows how to use the Circuit Breaker Enterprise Integration Pattern (EIP) with Camel JBang. The pipeline: + +1. Fetches the camel-jbang-examples repository using the git-clone task +2. Runs the circuit-breaker route for 30 seconds +3. Demonstrates how the circuit breaker state changes from closed to open when failures occur + +The circuit-breaker example is ideal for demonstrating Camel's resilience patterns and can be monitored to observe state transitions during execution. + +To run the sample pipeline: + +```shell +# Install required tasks +kubectl apply -f https://github.com/tektoncd/catalog/raw/main/task/git-clone/0.10/git-clone.yaml +kubectl apply -f https://github.com/tektoncd/catalog/raw/main/task/camel-run/0.1/camel-run.yaml + +# Run the sample pipeline +kubectl apply -f https://github.com/tektoncd/catalog/raw/main/task/camel-run/0.1/samples/run-basic.yaml +``` diff --git a/task/camel-run/0.1/camel-run.yaml b/task/camel-run/0.1/camel-run.yaml new file mode 100644 index 0000000000..1ee904a3cb --- /dev/null +++ b/task/camel-run/0.1/camel-run.yaml @@ -0,0 +1,174 @@ +apiVersion: tekton.dev/v1beta1 +kind: Task +metadata: + name: camel-run + labels: + app.kubernetes.io/version: "0.1" + annotations: + tekton.dev/categories: Deployment + tekton.dev/pipelines.minVersion: "0.17.0" + tekton.dev/tags: cli + tekton.dev/platforms: "linux/amd64" + tekton.dev/displayName: "camel run" +spec: + description: >- + Run a Camel Integration using Camel JBang + + Camel-run task executes Camel routes using Camel JBang, which provides a lightweight way to run Camel integrations + without requiring any operator installation. This task supports running Camel routes with various runtimes + (camel-main, spring-boot, quarkus) and configuration options. + params: + - name: camel-jbang-image + description: The location of Camel JBang image. + default: docker.io/apache/camel-jbang:4.17.0 + - name: filename + description: | + The Camel file(s) to run. Can be multiple files separated by space. + Format: "file1.yaml file2.yaml" or "route.yaml" + default: "" + - name: runtime + description: | + Runtime to use. Valid values: camel-main, spring-boot, quarkus + default: camel-main + - name: dependencies + description: | + Additional dependencies to add. Comma-separated list. + Format: "org.apache.camel:camel-http,org.apache.camel:camel-jackson" + default: "" + - name: properties + description: | + Comma separated list of properties files. + Format: "application.properties,custom.properties" + default: "" + - name: property + description: | + Additional properties in key=value format. Multiple properties separated by space. + Format: "key1=value1 key2=value2" + default: "" + - name: port + description: Embeds a local HTTP server on this port (0 to dynamic assign, -1 to disable) + default: "-1" + - name: max-seconds + description: Max seconds to run before stopping (0 for unlimited) + default: "0" + - name: logging-level + description: Logging level (ERROR, WARN, INFO, DEBUG, TRACE) + default: info + - name: dev + description: Enables dev mode (live reload when source files are updated) + default: "false" + - name: console + description: Enable developer console at /q/dev + default: "false" + - name: observe + description: Enable observability services (health, metrics) + default: "false" + - name: extra-args + description: | + Additional camel run arguments. Space-separated list. + Format: "--flag1 value1 --flag2" + default: "" + - name: output-log + description: | + Path to save camel run output log. If empty, no log file will be generated. + Format: Absolute or workspace-relative path + default: "$(workspaces.source.path)/camel-run.log" + results: + - name: exit-code + description: The exit code of the camel run command + workspaces: + - name: source + steps: + - name: execute + image: $(params.camel-jbang-image) + workingDir: $(workspaces.source.path) + securityContext: + runAsNonRoot: true + runAsUser: 1000 + env: + - name: PARAM_FILENAME + value: $(params.filename) + - name: PARAM_RUNTIME + value: $(params.runtime) + - name: PARAM_DEPENDENCIES + value: $(params.dependencies) + - name: PARAM_PROPERTIES + value: $(params.properties) + - name: PARAM_PROPERTY + value: $(params.property) + - name: PARAM_PORT + value: $(params.port) + - name: PARAM_MAX_SECONDS + value: $(params.max-seconds) + - name: PARAM_LOGGING_LEVEL + value: $(params.logging-level) + - name: PARAM_DEV + value: $(params.dev) + - name: PARAM_CONSOLE + value: $(params.console) + - name: PARAM_OBSERVE + value: $(params.observe) + - name: PARAM_EXTRA_ARGS + value: $(params.extra-args) + - name: PARAM_OUTPUT_LOG + value: $(params.output-log) + script: | + #!/usr/bin/env bash + set -e + + CAMEL_RUN_ARGS=() + + # Add files to run + [[ ! "$PARAM_FILENAME" == "" ]] && CAMEL_RUN_ARGS+=($PARAM_FILENAME) + + # Add runtime + [[ ! "$PARAM_RUNTIME" == "camel-main" ]] && CAMEL_RUN_ARGS+=(--runtime "$PARAM_RUNTIME") + + # Add dependencies + [[ ! "$PARAM_DEPENDENCIES" == "" ]] && CAMEL_RUN_ARGS+=(--dep "$PARAM_DEPENDENCIES") + + # Add properties files + [[ ! "$PARAM_PROPERTIES" == "" ]] && CAMEL_RUN_ARGS+=(--properties "$PARAM_PROPERTIES") + + # Add individual properties + if [[ ! "$PARAM_PROPERTY" == "" ]]; then + for prop in $PARAM_PROPERTY; do + CAMEL_RUN_ARGS+=(--prop "$prop") + done + fi + + # Add port + [[ ! "$PARAM_PORT" == "-1" ]] && CAMEL_RUN_ARGS+=(--port "$PARAM_PORT") + + # Add max-seconds + [[ ! "$PARAM_MAX_SECONDS" == "0" ]] && CAMEL_RUN_ARGS+=(--max-seconds "$PARAM_MAX_SECONDS") + + # Add logging level + CAMEL_RUN_ARGS+=(--logging-level "$PARAM_LOGGING_LEVEL") + + # Add dev mode + [[ "$PARAM_DEV" == "true" ]] && CAMEL_RUN_ARGS+=(--dev) + + # Add console + [[ "$PARAM_CONSOLE" == "true" ]] && CAMEL_RUN_ARGS+=(--console) + + # Add observe + [[ "$PARAM_OBSERVE" == "true" ]] && CAMEL_RUN_ARGS+=(--observe) + + # Add extra args + [[ ! "$PARAM_EXTRA_ARGS" == "" ]] && CAMEL_RUN_ARGS+=($PARAM_EXTRA_ARGS) + + echo "Running: camel run ${CAMEL_RUN_ARGS[@]}" + + # Execute camel run and conditionally capture output + if [[ ! "$PARAM_OUTPUT_LOG" == "" ]]; then + echo "Logging output to: $PARAM_OUTPUT_LOG" + camel run "${CAMEL_RUN_ARGS[@]}" 2>&1 | tee "$PARAM_OUTPUT_LOG" + exit_code=$? + else + camel run "${CAMEL_RUN_ARGS[@]}" + exit_code=$? + fi + + echo "$exit_code" | tr -d '\n' | tee "$(results.exit-code.path)" + exit $exit_code diff --git a/task/camel-run/0.1/samples/run-basic.yaml b/task/camel-run/0.1/samples/run-basic.yaml new file mode 100644 index 0000000000..30f93e05e0 --- /dev/null +++ b/task/camel-run/0.1/samples/run-basic.yaml @@ -0,0 +1,51 @@ +--- +apiVersion: tekton.dev/v1beta1 +kind: Pipeline +metadata: + name: camel-run-basic +spec: + workspaces: + - name: shared-workspace + tasks: + - name: fetch-repository + taskRef: + name: git-clone + workspaces: + - name: output + workspace: shared-workspace + params: + - name: url + value: https://github.com/apache/camel-jbang-examples/ + - name: camel-run + taskRef: + name: camel-run + runAfter: + - fetch-repository + workspaces: + - name: source + workspace: shared-workspace + params: + - name: filename + value: circuit-breaker/route.camel.yaml + - name: max-seconds + value: "30" + - name: logging-level + value: "INFO" + +--- +apiVersion: tekton.dev/v1beta1 +kind: PipelineRun +metadata: + name: camel-run-basic-run +spec: + pipelineRef: + name: camel-run-basic + workspaces: + - name: shared-workspace + volumeClaimTemplate: + spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 1Gi diff --git a/task/camel-run/0.1/tests/pre-apply-task-hook.sh b/task/camel-run/0.1/tests/pre-apply-task-hook.sh new file mode 100755 index 0000000000..a0aa212374 --- /dev/null +++ b/task/camel-run/0.1/tests/pre-apply-task-hook.sh @@ -0,0 +1,2 @@ +#!/bin/bash +add_task git-clone latest diff --git a/task/camel-run/0.1/tests/run.yaml b/task/camel-run/0.1/tests/run.yaml new file mode 100644 index 0000000000..ce3172fc57 --- /dev/null +++ b/task/camel-run/0.1/tests/run.yaml @@ -0,0 +1,97 @@ +--- +apiVersion: tekton.dev/v1beta1 +kind: Pipeline +metadata: + name: camel-run-basic-test +spec: + workspaces: + - name: shared-workspace + tasks: + - name: fetch-repository + taskRef: + name: git-clone + workspaces: + - name: output + workspace: shared-workspace + params: + - name: url + value: https://github.com/apache/camel-jbang-examples/ + - name: camel-run + taskRef: + name: camel-run + runAfter: + - fetch-repository + workspaces: + - name: source + workspace: shared-workspace + params: + - name: filename + value: circuit-breaker/route.camel.yaml + - name: max-seconds + value: "30" + - name: logging-level + value: "INFO" + - name: verify-logs + runAfter: + - camel-run + workspaces: + - name: source + workspace: shared-workspace + params: + - name: exit-code + value: "$(tasks.camel-run.results.exit-code)" + taskSpec: + params: + - name: exit-code + workspaces: + - name: source + steps: + - name: verify + image: fedora + workingDir: $(workspaces.source.path) + script: | + #!/usr/bin/env bash + set -e + + exit_code=$(echo "$(params.exit-code)" | tr -d '[:space:]') + if [ "$exit_code" != "0" ]; then + echo "Expected exit code 0 (was $exit_code)" + exit 1 + fi + + if [ ! -f camel-run.log ]; then + echo "Log file not found: camel-run.log" + exit 1 + fi + + if ! grep -q "Forced error" camel-run.log; then + echo "Expected 'Forced error' in logs" + cat camel-run.log + exit 1 + fi + + if ! grep -q "CircuitBreaker is open: true" camel-run.log; then + echo "Expected 'CircuitBreaker is open: true' in logs" + cat camel-run.log + exit 1 + fi + + exit 0 + +--- +apiVersion: tekton.dev/v1beta1 +kind: PipelineRun +metadata: + name: camel-run-basic-test-run +spec: + pipelineRef: + name: camel-run-basic-test + workspaces: + - name: shared-workspace + volumeClaimTemplate: + spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 1Gi diff --git a/task/camel-run/OWNERS b/task/camel-run/OWNERS new file mode 100644 index 0000000000..71f3a07e8c --- /dev/null +++ b/task/camel-run/OWNERS @@ -0,0 +1,4 @@ +approvers: +- mcarlett +reviewers: +- mcarlett