This is an automated email from the ASF dual-hosted git repository.

squakez pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel-k.git

commit ad5bbf162748acc0ca0184cc270fd350961a4d8e
Author: Keerthan <[email protected]>
AuthorDate: Wed Sep 23 19:48:21 2026 +0530

    Fix #5935: Add ArkMQ operator queue Pipe binding
---
 .github/workflows/arkmq.yml                        |  91 ++++++
 docs/modules/ROOT/pages/pipes/pipes.adoc           |  33 ++-
 e2e/arkmq/arkmq_binding_test.go                    |  50 ++++
 .../arkmq/files/arkmq-to-log.yaml                  |  39 +--
 .../arkmq/files/timer-to-arkmq.yaml                |  39 +--
 .../arkmq/setup/broker.yaml                        |  32 +-
 .../arkmq/setup/queue.yaml                         |  34 +--
 e2e/arkmq/setup/setup.sh                           |  41 +++
 pkg/apis/addtoscheme_arkmq_duck_v1beta1.go         |  27 ++
 pkg/apis/duck/arkmq/v1beta1/doc.go                 |  21 ++
 pkg/apis/duck/arkmq/v1beta1/duck_types.go          | 105 +++++++
 pkg/apis/duck/arkmq/v1beta1/register.go            |  47 +++
 .../duck/arkmq/v1beta1/zz_generated.deepcopy.go    | 207 +++++++++++++
 .../arkmq/clientset/internalclientset/clientset.go | 121 ++++++++
 .../internalclientset/fake/clientset_generated.go  | 102 +++++++
 .../arkmq/clientset/internalclientset/fake/doc.go  |  21 ++
 .../clientset/internalclientset/fake/register.go   |  57 ++++
 .../clientset/internalclientset/scheme/doc.go      |  21 ++
 .../clientset/internalclientset/scheme/register.go |  57 ++++
 .../typed/arkmq/v1beta1/activemqartemis.go         |  63 ++++
 .../typed/arkmq/v1beta1/activemqartemisaddress.go  |  63 ++++
 .../typed/arkmq/v1beta1/arkmq_client.go            | 107 +++++++
 .../internalclientset/typed/arkmq/v1beta1/doc.go   |  21 ++
 .../typed/arkmq/v1beta1/fake/doc.go                |  21 ++
 .../arkmq/v1beta1/fake/fake_activemqartemis.go     |  53 ++++
 .../v1beta1/fake/fake_activemqartemisaddress.go    |  53 ++++
 .../typed/arkmq/v1beta1/fake/fake_arkmq_client.go  |  45 +++
 .../typed/arkmq/v1beta1/generated_expansion.go     |  24 ++
 pkg/controller/pipe/initialize_test.go             | 106 ++++++-
 .../config/rbac/descoped/kustomization.yaml        |   2 +
 .../operator-cluster-role-arkmq.yaml}              |  40 +--
 .../operator-cluster-role-binding-arkmq.yaml}      |  38 +--
 .../config/rbac/namespaced/kustomization.yaml      |   2 +
 ...kustomization.yaml => operator-role-arkmq.yaml} |  40 +--
 ...ation.yaml => operator-role-binding-arkmq.yaml} |  38 +--
 pkg/util/bindings/arkmq.go                         | 217 ++++++++++++++
 pkg/util/bindings/arkmq_test.go                    | 327 +++++++++++++++++++++
 script/Makefile                                    |   8 +
 script/gen_client.sh                               |   8 +
 39 files changed, 2216 insertions(+), 205 deletions(-)

diff --git a/.github/workflows/arkmq.yml b/.github/workflows/arkmq.yml
new file mode 100644
index 000000000..3ea57f8d8
--- /dev/null
+++ b/.github/workflows/arkmq.yml
@@ -0,0 +1,91 @@
+# ---------------------------------------------------------------------------
+# 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.
+# ---------------------------------------------------------------------------
+
+name: arkmq
+
+env:
+  GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+
+on:
+  pull_request:
+    branches:
+      - main
+      - "release-*"
+    paths-ignore:
+      - 'docs/**'
+      - 'java/**'
+      - 'proposals/**'
+      - '**.adoc'
+      - '**.md'
+      - 'KEYS'
+      - 'LICENSE'
+      - 'NOTICE'
+  push:
+    branches:
+      - main
+      - "release-*"
+    paths-ignore:
+      - 'docs/**'
+      - 'java/**'
+      - 'proposals/**'
+      - '**.adoc'
+      - '**.md'
+      - 'KEYS'
+      - 'LICENSE'
+      - 'NOTICE'
+  workflow_dispatch:
+
+concurrency:
+  group: ${{ github.workflow }}-${{ github.event.pull_request.number || 
github.sha }}
+  cancel-in-progress: true
+
+jobs:
+  arkmq-test:
+    runs-on: ubuntu-latest
+    steps:
+
+    - name: Checkout code
+      uses: actions/checkout@v7
+      with:
+        persist-credentials: false
+        submodules: recursive
+
+    - name: Infra setting
+      uses: ./.github/actions/infra-setting
+
+    - name: Install ArkMQ
+      shell: bash
+      run: |
+        ./e2e/arkmq/setup/setup.sh
+
+    - name: Create operator namespace
+      shell: bash
+      run: |
+        kubectl create ns camel-k
+
+    - name: Registry setting
+      uses: ./.github/actions/registry-setting
+
+    - name: Install operator
+      shell: bash
+      run: |
+        make install-k8s-global
+
+    - name: Run test
+      shell: bash
+      run: |
+        DO_TEST_PREBUILD=false GOTESTFMT="-json 2>&1 | gotestfmt" make 
test-arkmq
diff --git a/docs/modules/ROOT/pages/pipes/pipes.adoc 
b/docs/modules/ROOT/pages/pipes/pipes.adoc
index 25d145f1b..d05008d2f 100644
--- a/docs/modules/ROOT/pages/pipes/pipes.adoc
+++ b/docs/modules/ROOT/pages/pipes/pipes.adoc
@@ -1,6 +1,6 @@
 = Running a Pipe
 
-The Pipe is a concept that allows you to create a "composable" Event Driven 
Architecture design. The Pipe can bind **source** and **sink** endpoints where 
an endpoint represents a source/sink external entity (could be any Camel URI or 
a Kubernetes resource such as xref:kamelets/kamelets.adoc[Kamelets], Kafka 
(https://strimzi.io/[Strimzi]) or https://knative.dev[Knative] resources).
+The Pipe is a concept that allows you to create a "composable" Event Driven 
Architecture design. The Pipe can bind **source** and **sink** endpoints where 
an endpoint represents a source/sink external entity (could be any Camel URI or 
a Kubernetes resource such as xref:kamelets/kamelets.adoc[Kamelets], Kafka 
(https://strimzi.io/[Strimzi]), ArkMQ (https://arkmq.org/[ActiveMQ Artemis]) or 
https://knative.dev[Knative] resources).
 
 [NOTE]
 ====
@@ -177,6 +177,37 @@ spec:
 KafkaTopics require the Strimzi operator and a configured KafkaTopic`.
 ====
 
+=== Binding to ArkMQ queues
+
+Another typical use case is consume/produce events directly from an 
ActiveMQArtemisAddress custom resource (managed by https://arkmq.org/[ArkMQ] / 
ActiveMQ Artemis operator):
+
+.beer-event-to-queue.yaml
+[source,yaml,subs="attributes+"]
+----
+apiVersion: camel.apache.org/v1
+kind: Pipe
+metadata:
+  name: beer-event-to-queue
+spec:
+  source:
+    ref:
+      kind: Kamelet
+      apiVersion: camel.apache.org/v1alpha1
+      name: beer-source
+    properties:
+      period: 5000
+  sink:
+    ref:
+      kind: ActiveMQArtemisAddress
+      apiVersion: broker.amq.io/v1beta1
+      name: beer-events
+----
+
+[NOTE]
+====
+ActiveMQArtemisAddress requires the ActiveMQ Artemis / ArkMQ operator and an 
existing broker cluster.
+====
+
 === Binding to Knative resources
 
 A Pipe allows to move data from a system described by a Kamelet towards a 
https://knative.dev[Knative] destination, or from a Knative channel/broker to 
another external system described by a Kamelet. This means Pipes may act as 
event sources and sinks for the Knative eventing broker in a declarative way.
diff --git a/e2e/arkmq/arkmq_binding_test.go b/e2e/arkmq/arkmq_binding_test.go
new file mode 100644
index 000000000..1875d10cb
--- /dev/null
+++ b/e2e/arkmq/arkmq_binding_test.go
@@ -0,0 +1,50 @@
+//go:build integration
+// +build integration
+
+/*
+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 arkmq
+
+import (
+       "context"
+       "testing"
+
+       . "github.com/onsi/gomega"
+       corev1 "k8s.io/api/core/v1"
+
+       . "github.com/apache/camel-k/v2/e2e/support"
+       v1 "github.com/apache/camel-k/v2/pkg/apis/camel/v1"
+)
+
+func TestArkMQ(t *testing.T) {
+       WithExistingNamedTestNamespace(t, func(ctx context.Context, g *WithT, 
arkmqNs string) {
+               t.Run("ArkMQ ActiveMQArtemisAddress resource", func(t 
*testing.T) {
+                       ExpectExecSucceed(t, g, Kubectl("apply", "-f", 
"files/timer-to-arkmq.yaml"))
+                       // Wait for the readiness of the Integration
+                       g.Eventually(IntegrationConditionStatus(t, ctx, 
arkmqNs, "timer-to-arkmq", v1.IntegrationConditionReady), TestTimeoutMedium).
+                               Should(Equal(corev1.ConditionTrue))
+                       ExpectExecSucceed(t, g, Kubectl("apply", "-f", 
"files/arkmq-to-log.yaml"))
+                       g.Eventually(IntegrationConditionStatus(t, ctx, 
arkmqNs, "arkmq-to-log", v1.IntegrationConditionReady), TestTimeoutMedium).
+                               Should(Equal(corev1.ConditionTrue))
+                       // Verify we are consuming records from the queue
+                       g.Eventually(IntegrationLogs(t, ctx, arkmqNs, 
"arkmq-to-log")).Should(ContainSubstring("Body is null"))
+
+                       g.Expect(Kamel(t, ctx, "delete", "--all", "-n", 
arkmqNs).Execute()).To(Succeed())
+               })
+       }, "arkmq")
+}
diff --git a/pkg/resources/config/rbac/namespaced/kustomization.yaml 
b/e2e/arkmq/files/arkmq-to-log.yaml
similarity index 55%
copy from pkg/resources/config/rbac/namespaced/kustomization.yaml
copy to e2e/arkmq/files/arkmq-to-log.yaml
index e50bc5c5a..6ff45213c 100644
--- a/pkg/resources/config/rbac/namespaced/kustomization.yaml
+++ b/e2e/arkmq/files/arkmq-to-log.yaml
@@ -14,29 +14,16 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 # ---------------------------------------------------------------------------
-
-#
-# rbac resources applicable for all kubernetes platforms - namespaced operator
-#
-apiVersion: kustomize.config.k8s.io/v1beta1
-kind: Kustomization
-
-resources:
-- operator-role-certmanager.yaml
-- operator-role-events.yaml
-- operator-role.yaml
-- operator-role-keda.yaml
-- operator-role-knative.yaml
-- operator-role-leases.yaml
-- operator-role-openshift.yaml
-- operator-role-podmonitors.yaml
-- operator-role-strimzi.yaml
-- operator-role-binding.yaml
-- operator-role-binding-certmanager.yaml
-- operator-role-binding-events.yaml
-- operator-role-binding-keda.yaml
-- operator-role-binding-knative.yaml
-- operator-role-binding-leases.yaml
-- operator-role-binding-openshift.yaml
-- operator-role-binding-podmonitors.yaml
-- operator-role-binding-strimzi.yaml
+apiVersion: camel.apache.org/v1
+kind: Pipe
+metadata:
+  name: arkmq-to-log
+  namespace: arkmq
+spec:
+  sink:
+    uri: log:info
+  source:
+    ref:
+      kind: ActiveMQArtemisAddress
+      apiVersion: broker.amq.io/v1beta1
+      name: my-queue
diff --git a/pkg/resources/config/rbac/namespaced/kustomization.yaml 
b/e2e/arkmq/files/timer-to-arkmq.yaml
similarity index 55%
copy from pkg/resources/config/rbac/namespaced/kustomization.yaml
copy to e2e/arkmq/files/timer-to-arkmq.yaml
index e50bc5c5a..73fb51043 100644
--- a/pkg/resources/config/rbac/namespaced/kustomization.yaml
+++ b/e2e/arkmq/files/timer-to-arkmq.yaml
@@ -14,29 +14,16 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 # ---------------------------------------------------------------------------
-
-#
-# rbac resources applicable for all kubernetes platforms - namespaced operator
-#
-apiVersion: kustomize.config.k8s.io/v1beta1
-kind: Kustomization
-
-resources:
-- operator-role-certmanager.yaml
-- operator-role-events.yaml
-- operator-role.yaml
-- operator-role-keda.yaml
-- operator-role-knative.yaml
-- operator-role-leases.yaml
-- operator-role-openshift.yaml
-- operator-role-podmonitors.yaml
-- operator-role-strimzi.yaml
-- operator-role-binding.yaml
-- operator-role-binding-certmanager.yaml
-- operator-role-binding-events.yaml
-- operator-role-binding-keda.yaml
-- operator-role-binding-knative.yaml
-- operator-role-binding-leases.yaml
-- operator-role-binding-openshift.yaml
-- operator-role-binding-podmonitors.yaml
-- operator-role-binding-strimzi.yaml
+apiVersion: camel.apache.org/v1
+kind: Pipe
+metadata:
+  name: timer-to-arkmq
+  namespace: arkmq
+spec:
+  source:
+    uri: timer:foo
+  sink:
+    ref:
+      kind: ActiveMQArtemisAddress
+      apiVersion: broker.amq.io/v1beta1
+      name: my-queue
diff --git a/pkg/resources/config/rbac/namespaced/kustomization.yaml 
b/e2e/arkmq/setup/broker.yaml
similarity index 55%
copy from pkg/resources/config/rbac/namespaced/kustomization.yaml
copy to e2e/arkmq/setup/broker.yaml
index e50bc5c5a..560e09954 100644
--- a/pkg/resources/config/rbac/namespaced/kustomization.yaml
+++ b/e2e/arkmq/setup/broker.yaml
@@ -15,28 +15,10 @@
 # limitations under the License.
 # ---------------------------------------------------------------------------
 
-#
-# rbac resources applicable for all kubernetes platforms - namespaced operator
-#
-apiVersion: kustomize.config.k8s.io/v1beta1
-kind: Kustomization
-
-resources:
-- operator-role-certmanager.yaml
-- operator-role-events.yaml
-- operator-role.yaml
-- operator-role-keda.yaml
-- operator-role-knative.yaml
-- operator-role-leases.yaml
-- operator-role-openshift.yaml
-- operator-role-podmonitors.yaml
-- operator-role-strimzi.yaml
-- operator-role-binding.yaml
-- operator-role-binding-certmanager.yaml
-- operator-role-binding-events.yaml
-- operator-role-binding-keda.yaml
-- operator-role-binding-knative.yaml
-- operator-role-binding-leases.yaml
-- operator-role-binding-openshift.yaml
-- operator-role-binding-podmonitors.yaml
-- operator-role-binding-strimzi.yaml
+apiVersion: broker.amq.io/v1beta1
+kind: ActiveMQArtemis
+metadata:
+  name: my-broker
+spec:
+  deploymentPlan:
+    size: 1
diff --git a/pkg/resources/config/rbac/namespaced/kustomization.yaml 
b/e2e/arkmq/setup/queue.yaml
similarity index 55%
copy from pkg/resources/config/rbac/namespaced/kustomization.yaml
copy to e2e/arkmq/setup/queue.yaml
index e50bc5c5a..1c7852235 100644
--- a/pkg/resources/config/rbac/namespaced/kustomization.yaml
+++ b/e2e/arkmq/setup/queue.yaml
@@ -15,28 +15,12 @@
 # limitations under the License.
 # ---------------------------------------------------------------------------
 
-#
-# rbac resources applicable for all kubernetes platforms - namespaced operator
-#
-apiVersion: kustomize.config.k8s.io/v1beta1
-kind: Kustomization
-
-resources:
-- operator-role-certmanager.yaml
-- operator-role-events.yaml
-- operator-role.yaml
-- operator-role-keda.yaml
-- operator-role-knative.yaml
-- operator-role-leases.yaml
-- operator-role-openshift.yaml
-- operator-role-podmonitors.yaml
-- operator-role-strimzi.yaml
-- operator-role-binding.yaml
-- operator-role-binding-certmanager.yaml
-- operator-role-binding-events.yaml
-- operator-role-binding-keda.yaml
-- operator-role-binding-knative.yaml
-- operator-role-binding-leases.yaml
-- operator-role-binding-openshift.yaml
-- operator-role-binding-podmonitors.yaml
-- operator-role-binding-strimzi.yaml
+apiVersion: broker.amq.io/v1beta1
+kind: ActiveMQArtemisAddress
+metadata:
+  name: my-queue
+spec:
+  addressName: my-queue
+  queueName: my-queue
+  routingType: anycast
+  applyTo: my-broker
diff --git a/e2e/arkmq/setup/setup.sh b/e2e/arkmq/setup/setup.sh
new file mode 100644
index 000000000..59afa39f7
--- /dev/null
+++ b/e2e/arkmq/setup/setup.sh
@@ -0,0 +1,41 @@
+#!/bin/bash
+
+# ---------------------------------------------------------------------------
+# 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.
+# ---------------------------------------------------------------------------
+
+####
+#
+# This script takes care of ArkMQ operator setup for e2e tests
+#
+####
+
+SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
+
+kubectl create namespace arkmq --dry-run=client -o yaml | kubectl apply -f -
+kubectl apply --server-side -f 
https://github.com/arkmq-org/arkmq-org-broker-operator/releases/latest/download/arkmq-org-broker-operator.yaml
 -n arkmq
+kubectl rollout status deployment arkmq-org-broker-operator -n arkmq 
--timeout=180s
+
+# Wait for CRDs to be established
+kubectl wait --for=condition=established crd/activemqartemises.broker.amq.io 
--timeout=60s
+kubectl wait --for=condition=established 
crd/activemqartemisaddresses.broker.amq.io --timeout=60s
+
+#### Setup an ActiveMQ Artemis broker
+kubectl apply -f $SCRIPT_DIR/broker.yaml -n arkmq
+kubectl wait activemqartemis/my-broker --for=condition=Ready --timeout=300s -n 
arkmq
+
+#### Setup an ActiveMQ Artemis queue address
+kubectl apply -f $SCRIPT_DIR/queue.yaml -n arkmq
diff --git a/pkg/apis/addtoscheme_arkmq_duck_v1beta1.go 
b/pkg/apis/addtoscheme_arkmq_duck_v1beta1.go
new file mode 100644
index 000000000..c56a10fb5
--- /dev/null
+++ b/pkg/apis/addtoscheme_arkmq_duck_v1beta1.go
@@ -0,0 +1,27 @@
+/*
+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 apis
+
+import (
+       v1beta1 "github.com/apache/camel-k/v2/pkg/apis/duck/arkmq/v1beta1"
+)
+
+func init() {
+       // Register the types with the Scheme so the components can map objects 
to GroupVersionKinds and back
+       AddToSchemes = append(AddToSchemes, v1beta1.SchemeBuilder.AddToScheme)
+}
diff --git a/pkg/apis/duck/arkmq/v1beta1/doc.go 
b/pkg/apis/duck/arkmq/v1beta1/doc.go
new file mode 100644
index 000000000..b7bc47f1c
--- /dev/null
+++ b/pkg/apis/duck/arkmq/v1beta1/doc.go
@@ -0,0 +1,21 @@
+/*
+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 v1beta1 contains a partial schema of the ArkMQ APIs
+// +kubebuilder:object:generate=true
+// +groupName=broker.amq.io
+package v1beta1
diff --git a/pkg/apis/duck/arkmq/v1beta1/duck_types.go 
b/pkg/apis/duck/arkmq/v1beta1/duck_types.go
new file mode 100644
index 000000000..c8ac3fa8a
--- /dev/null
+++ b/pkg/apis/duck/arkmq/v1beta1/duck_types.go
@@ -0,0 +1,105 @@
+/*
+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 v1beta1
+
+import metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+
+const (
+       ArkMQGroup       = "broker.amq.io"
+       ArkMQVersion     = "v1beta1"
+       ArkMQKindAddress = "ActiveMQArtemisAddress"
+       ArkMQKindBroker  = "ActiveMQArtemis"
+
+       ArkMQBrokerLabel = "ActiveMQArtemis"
+)
+
+// +genclient
+// +genclient:onlyVerbs=get,list,watch
+// +genclient:noStatus
+// +kubebuilder:object:root=true
+
+// ActiveMQArtemisAddress is the duck of an ActiveMQArtemisAddress.
+type ActiveMQArtemisAddress struct {
+       metav1.TypeMeta   `json:",inline"`
+       metav1.ObjectMeta `json:"metadata,omitempty"`
+
+       Spec ActiveMQArtemisAddressSpec `json:"spec,omitempty"`
+}
+
+// ActiveMQArtemisAddressSpec is the duck of an ActiveMQArtemisAddress spec.
+type ActiveMQArtemisAddressSpec struct {
+       AddressName string `json:"addressName,omitempty"`
+       QueueName   string `json:"queueName,omitempty"`
+       RoutingType string `json:"routingType,omitempty"`
+       ApplyTo     string `json:"applyTo,omitempty"`
+}
+
+// +kubebuilder:object:root=true
+
+// ActiveMQArtemisAddressList contains a list of ActiveMQArtemisAddress.
+type ActiveMQArtemisAddressList struct {
+       metav1.TypeMeta `json:",inline"`
+       metav1.ListMeta `json:"metadata,omitempty"`
+
+       Items []ActiveMQArtemisAddress `json:"items"`
+}
+
+// +genclient
+// +genclient:onlyVerbs=get,list,watch
+// +genclient:noStatus
+// +kubebuilder:object:root=true
+
+// ActiveMQArtemis is the duck of an ActiveMQArtemis broker.
+type ActiveMQArtemis struct {
+       metav1.TypeMeta   `json:",inline"`
+       metav1.ObjectMeta `json:"metadata,omitempty"`
+
+       Spec   ActiveMQArtemisSpec   `json:"spec,omitempty"`
+       Status ActiveMQArtemisStatus `json:"status,omitempty"`
+}
+
+// ActiveMQArtemisSpec contains relevant spec of the ActiveMQArtemis.
+type ActiveMQArtemisSpec struct {
+       DeploymentPlan ActiveMQArtemisDeploymentPlan 
`json:"deploymentPlan,omitempty"`
+}
+
+// ActiveMQArtemisDeploymentPlan contains deployment plan.
+type ActiveMQArtemisDeploymentPlan struct {
+       Size int32 `json:"size,omitempty"`
+}
+
+// ActiveMQArtemisStatus contains the relevant info of the ActiveMQArtemis 
status.
+type ActiveMQArtemisStatus struct {
+       PortStatus []ActiveMQArtemisPortStatus `json:"portStatus,omitempty"`
+}
+
+// ActiveMQArtemisPortStatus contains port information.
+type ActiveMQArtemisPortStatus struct {
+       Name string `json:"name,omitempty"`
+       Port int32  `json:"port,omitempty"`
+}
+
+// +kubebuilder:object:root=true
+
+// ActiveMQArtemisList contains a list of ActiveMQArtemis.
+type ActiveMQArtemisList struct {
+       metav1.TypeMeta `json:",inline"`
+       metav1.ListMeta `json:"metadata,omitempty"`
+
+       Items []ActiveMQArtemis `json:"items"`
+}
diff --git a/pkg/apis/duck/arkmq/v1beta1/register.go 
b/pkg/apis/duck/arkmq/v1beta1/register.go
new file mode 100644
index 000000000..deb21a2d8
--- /dev/null
+++ b/pkg/apis/duck/arkmq/v1beta1/register.go
@@ -0,0 +1,47 @@
+/*
+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 v1beta1
+
+import (
+       metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+       "k8s.io/apimachinery/pkg/runtime"
+       "k8s.io/apimachinery/pkg/runtime/schema"
+)
+
+var (
+       // SchemeGroupVersion is group version used to register these objects.
+       SchemeGroupVersion = schema.GroupVersion{Group: ArkMQGroup, Version: 
ArkMQVersion}
+
+       // SchemeBuilder is used to add go types to the GroupVersionKind scheme.
+       SchemeBuilder = runtime.NewSchemeBuilder(addKnownTypes)
+
+       // AddToScheme adds the types in this group-version to the given scheme.
+       AddToScheme = SchemeBuilder.AddToScheme
+)
+
+func addKnownTypes(scheme *runtime.Scheme) error {
+       scheme.AddKnownTypes(SchemeGroupVersion,
+               &ActiveMQArtemis{},
+               &ActiveMQArtemisList{},
+               &ActiveMQArtemisAddress{},
+               &ActiveMQArtemisAddressList{},
+       )
+       metav1.AddToGroupVersion(scheme, SchemeGroupVersion)
+
+       return nil
+}
diff --git a/pkg/apis/duck/arkmq/v1beta1/zz_generated.deepcopy.go 
b/pkg/apis/duck/arkmq/v1beta1/zz_generated.deepcopy.go
new file mode 100644
index 000000000..5003285b0
--- /dev/null
+++ b/pkg/apis/duck/arkmq/v1beta1/zz_generated.deepcopy.go
@@ -0,0 +1,207 @@
+//go:build !ignore_autogenerated
+
+// Code generated by controller-gen. DO NOT EDIT.
+
+package v1beta1
+
+import (
+       "k8s.io/apimachinery/pkg/runtime"
+)
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, 
writing into out. in must be non-nil.
+func (in *ActiveMQArtemis) DeepCopyInto(out *ActiveMQArtemis) {
+       *out = *in
+       out.TypeMeta = in.TypeMeta
+       in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
+       out.Spec = in.Spec
+       in.Status.DeepCopyInto(&out.Status)
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, 
creating a new ActiveMQArtemis.
+func (in *ActiveMQArtemis) DeepCopy() *ActiveMQArtemis {
+       if in == nil {
+               return nil
+       }
+       out := new(ActiveMQArtemis)
+       in.DeepCopyInto(out)
+       return out
+}
+
+// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, 
creating a new runtime.Object.
+func (in *ActiveMQArtemis) DeepCopyObject() runtime.Object {
+       if c := in.DeepCopy(); c != nil {
+               return c
+       }
+       return nil
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, 
writing into out. in must be non-nil.
+func (in *ActiveMQArtemisAddress) DeepCopyInto(out *ActiveMQArtemisAddress) {
+       *out = *in
+       out.TypeMeta = in.TypeMeta
+       in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
+       out.Spec = in.Spec
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, 
creating a new ActiveMQArtemisAddress.
+func (in *ActiveMQArtemisAddress) DeepCopy() *ActiveMQArtemisAddress {
+       if in == nil {
+               return nil
+       }
+       out := new(ActiveMQArtemisAddress)
+       in.DeepCopyInto(out)
+       return out
+}
+
+// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, 
creating a new runtime.Object.
+func (in *ActiveMQArtemisAddress) DeepCopyObject() runtime.Object {
+       if c := in.DeepCopy(); c != nil {
+               return c
+       }
+       return nil
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, 
writing into out. in must be non-nil.
+func (in *ActiveMQArtemisAddressList) DeepCopyInto(out 
*ActiveMQArtemisAddressList) {
+       *out = *in
+       out.TypeMeta = in.TypeMeta
+       in.ListMeta.DeepCopyInto(&out.ListMeta)
+       if in.Items != nil {
+               in, out := &in.Items, &out.Items
+               *out = make([]ActiveMQArtemisAddress, len(*in))
+               for i := range *in {
+                       (*in)[i].DeepCopyInto(&(*out)[i])
+               }
+       }
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, 
creating a new ActiveMQArtemisAddressList.
+func (in *ActiveMQArtemisAddressList) DeepCopy() *ActiveMQArtemisAddressList {
+       if in == nil {
+               return nil
+       }
+       out := new(ActiveMQArtemisAddressList)
+       in.DeepCopyInto(out)
+       return out
+}
+
+// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, 
creating a new runtime.Object.
+func (in *ActiveMQArtemisAddressList) DeepCopyObject() runtime.Object {
+       if c := in.DeepCopy(); c != nil {
+               return c
+       }
+       return nil
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, 
writing into out. in must be non-nil.
+func (in *ActiveMQArtemisAddressSpec) DeepCopyInto(out 
*ActiveMQArtemisAddressSpec) {
+       *out = *in
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, 
creating a new ActiveMQArtemisAddressSpec.
+func (in *ActiveMQArtemisAddressSpec) DeepCopy() *ActiveMQArtemisAddressSpec {
+       if in == nil {
+               return nil
+       }
+       out := new(ActiveMQArtemisAddressSpec)
+       in.DeepCopyInto(out)
+       return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, 
writing into out. in must be non-nil.
+func (in *ActiveMQArtemisDeploymentPlan) DeepCopyInto(out 
*ActiveMQArtemisDeploymentPlan) {
+       *out = *in
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, 
creating a new ActiveMQArtemisDeploymentPlan.
+func (in *ActiveMQArtemisDeploymentPlan) DeepCopy() 
*ActiveMQArtemisDeploymentPlan {
+       if in == nil {
+               return nil
+       }
+       out := new(ActiveMQArtemisDeploymentPlan)
+       in.DeepCopyInto(out)
+       return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, 
writing into out. in must be non-nil.
+func (in *ActiveMQArtemisList) DeepCopyInto(out *ActiveMQArtemisList) {
+       *out = *in
+       out.TypeMeta = in.TypeMeta
+       in.ListMeta.DeepCopyInto(&out.ListMeta)
+       if in.Items != nil {
+               in, out := &in.Items, &out.Items
+               *out = make([]ActiveMQArtemis, len(*in))
+               for i := range *in {
+                       (*in)[i].DeepCopyInto(&(*out)[i])
+               }
+       }
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, 
creating a new ActiveMQArtemisList.
+func (in *ActiveMQArtemisList) DeepCopy() *ActiveMQArtemisList {
+       if in == nil {
+               return nil
+       }
+       out := new(ActiveMQArtemisList)
+       in.DeepCopyInto(out)
+       return out
+}
+
+// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, 
creating a new runtime.Object.
+func (in *ActiveMQArtemisList) DeepCopyObject() runtime.Object {
+       if c := in.DeepCopy(); c != nil {
+               return c
+       }
+       return nil
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, 
writing into out. in must be non-nil.
+func (in *ActiveMQArtemisPortStatus) DeepCopyInto(out 
*ActiveMQArtemisPortStatus) {
+       *out = *in
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, 
creating a new ActiveMQArtemisPortStatus.
+func (in *ActiveMQArtemisPortStatus) DeepCopy() *ActiveMQArtemisPortStatus {
+       if in == nil {
+               return nil
+       }
+       out := new(ActiveMQArtemisPortStatus)
+       in.DeepCopyInto(out)
+       return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, 
writing into out. in must be non-nil.
+func (in *ActiveMQArtemisSpec) DeepCopyInto(out *ActiveMQArtemisSpec) {
+       *out = *in
+       out.DeploymentPlan = in.DeploymentPlan
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, 
creating a new ActiveMQArtemisSpec.
+func (in *ActiveMQArtemisSpec) DeepCopy() *ActiveMQArtemisSpec {
+       if in == nil {
+               return nil
+       }
+       out := new(ActiveMQArtemisSpec)
+       in.DeepCopyInto(out)
+       return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, 
writing into out. in must be non-nil.
+func (in *ActiveMQArtemisStatus) DeepCopyInto(out *ActiveMQArtemisStatus) {
+       *out = *in
+       if in.PortStatus != nil {
+               in, out := &in.PortStatus, &out.PortStatus
+               *out = make([]ActiveMQArtemisPortStatus, len(*in))
+               copy(*out, *in)
+       }
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, 
creating a new ActiveMQArtemisStatus.
+func (in *ActiveMQArtemisStatus) DeepCopy() *ActiveMQArtemisStatus {
+       if in == nil {
+               return nil
+       }
+       out := new(ActiveMQArtemisStatus)
+       in.DeepCopyInto(out)
+       return out
+}
diff --git a/pkg/client/arkmq/clientset/internalclientset/clientset.go 
b/pkg/client/arkmq/clientset/internalclientset/clientset.go
new file mode 100644
index 000000000..6bfbf6fed
--- /dev/null
+++ b/pkg/client/arkmq/clientset/internalclientset/clientset.go
@@ -0,0 +1,121 @@
+/*
+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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package internalclientset
+
+import (
+       fmt "fmt"
+       http "net/http"
+
+       brokerv1beta1 
"github.com/apache/camel-k/v2/pkg/client/arkmq/clientset/internalclientset/typed/arkmq/v1beta1"
+       discovery "k8s.io/client-go/discovery"
+       rest "k8s.io/client-go/rest"
+       flowcontrol "k8s.io/client-go/util/flowcontrol"
+)
+
+type Interface interface {
+       Discovery() discovery.DiscoveryInterfaces
+       BrokerV1beta1() brokerv1beta1.BrokerV1beta1Interface
+}
+
+// Clientset contains the clients for groups.
+type Clientset struct {
+       *discovery.DiscoveryClient
+       brokerV1beta1 *brokerv1beta1.BrokerV1beta1Client
+}
+
+// BrokerV1beta1 retrieves the BrokerV1beta1Client
+func (c *Clientset) BrokerV1beta1() brokerv1beta1.BrokerV1beta1Interface {
+       return c.brokerV1beta1
+}
+
+// Discovery retrieves the DiscoveryClient
+func (c *Clientset) Discovery() discovery.DiscoveryInterfaces {
+       if c == nil {
+               return nil
+       }
+       return c.DiscoveryClient
+}
+
+// NewForConfig creates a new Clientset for the given config.
+// If config's RateLimiter is not set and QPS and Burst are acceptable,
+// NewForConfig will generate a rate-limiter in configShallowCopy.
+// NewForConfig is equivalent to NewForConfigAndClient(c, httpClient),
+// where httpClient was generated with rest.HTTPClientFor(c).
+func NewForConfig(c *rest.Config) (*Clientset, error) {
+       configShallowCopy := *c
+
+       if configShallowCopy.UserAgent == "" {
+               configShallowCopy.UserAgent = rest.DefaultKubernetesUserAgent()
+       }
+
+       // share the transport between all clients
+       httpClient, err := rest.HTTPClientFor(&configShallowCopy)
+       if err != nil {
+               return nil, err
+       }
+
+       return NewForConfigAndClient(&configShallowCopy, httpClient)
+}
+
+// NewForConfigAndClient creates a new Clientset for the given config and http 
client.
+// Note the http client provided takes precedence over the configured 
transport values.
+// If config's RateLimiter is not set and QPS and Burst are acceptable,
+// NewForConfigAndClient will generate a rate-limiter in configShallowCopy.
+func NewForConfigAndClient(c *rest.Config, httpClient *http.Client) 
(*Clientset, error) {
+       configShallowCopy := *c
+       if configShallowCopy.RateLimiter == nil && configShallowCopy.QPS > 0 {
+               if configShallowCopy.Burst <= 0 {
+                       return nil, fmt.Errorf("burst is required to be greater 
than 0 when RateLimiter is not set and QPS is set to greater than 0")
+               }
+               configShallowCopy.RateLimiter = 
flowcontrol.NewTokenBucketRateLimiter(configShallowCopy.QPS, 
configShallowCopy.Burst)
+       }
+
+       var cs Clientset
+       var err error
+       cs.brokerV1beta1, err = 
brokerv1beta1.NewForConfigAndClient(&configShallowCopy, httpClient)
+       if err != nil {
+               return nil, err
+       }
+
+       cs.DiscoveryClient, err = 
discovery.NewDiscoveryClientForConfigAndClient(&configShallowCopy, httpClient)
+       if err != nil {
+               return nil, err
+       }
+       return &cs, nil
+}
+
+// NewForConfigOrDie creates a new Clientset for the given config and
+// panics if there is an error in the config.
+func NewForConfigOrDie(c *rest.Config) *Clientset {
+       cs, err := NewForConfig(c)
+       if err != nil {
+               panic(err)
+       }
+       return cs
+}
+
+// New creates a new Clientset for the given RESTClient.
+func New(c rest.Interface) *Clientset {
+       var cs Clientset
+       cs.brokerV1beta1 = brokerv1beta1.New(c)
+
+       cs.DiscoveryClient = discovery.NewDiscoveryClient(c)
+       return &cs
+}
diff --git 
a/pkg/client/arkmq/clientset/internalclientset/fake/clientset_generated.go 
b/pkg/client/arkmq/clientset/internalclientset/fake/clientset_generated.go
new file mode 100644
index 000000000..2406b49b0
--- /dev/null
+++ b/pkg/client/arkmq/clientset/internalclientset/fake/clientset_generated.go
@@ -0,0 +1,102 @@
+/*
+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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+import (
+       clientset 
"github.com/apache/camel-k/v2/pkg/client/arkmq/clientset/internalclientset"
+       brokerv1beta1 
"github.com/apache/camel-k/v2/pkg/client/arkmq/clientset/internalclientset/typed/arkmq/v1beta1"
+       fakebrokerv1beta1 
"github.com/apache/camel-k/v2/pkg/client/arkmq/clientset/internalclientset/typed/arkmq/v1beta1/fake"
+       metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+       "k8s.io/apimachinery/pkg/runtime"
+       "k8s.io/apimachinery/pkg/watch"
+       "k8s.io/client-go/discovery"
+       fakediscovery "k8s.io/client-go/discovery/fake"
+       "k8s.io/client-go/testing"
+)
+
+// NewSimpleClientset returns a clientset that will respond with the provided 
objects.
+// It's backed by a very simple object tracker that processes creates, updates 
and deletions as-is,
+// without applying any field management, validations and/or defaults. It 
shouldn't be considered a replacement
+// for a real clientset and is mostly useful in simple unit tests.
+func NewSimpleClientset(objects ...runtime.Object) *Clientset {
+       o := testing.NewObjectTracker(scheme, codecs.UniversalDecoder())
+       for _, obj := range objects {
+               if err := o.Add(obj); err != nil {
+                       panic(err)
+               }
+       }
+
+       cs := &Clientset{tracker: o}
+       cs.discovery = &fakediscovery.FakeDiscovery{Fake: &cs.Fake}
+       cs.AddReactor("*", "*", testing.ObjectReaction(o))
+       cs.AddWatchReactor("*", func(action testing.Action) (handled bool, ret 
watch.Interface, err error) {
+               var opts metav1.ListOptions
+               if watchAction, ok := action.(testing.WatchActionImpl); ok {
+                       opts = watchAction.ListOptions
+               }
+               gvr := action.GetResource()
+               ns := action.GetNamespace()
+               watch, err := o.Watch(gvr, ns, opts)
+               if err != nil {
+                       return false, nil, err
+               }
+               return true, watch, nil
+       })
+
+       return cs
+}
+
+// Clientset implements clientset.Interface. Meant to be embedded into a
+// struct to get a default implementation. This makes faking out just the 
method
+// you want to test easier.
+type Clientset struct {
+       testing.Fake
+       discovery *fakediscovery.FakeDiscovery
+       tracker   testing.ObjectTracker
+}
+
+func (c *Clientset) Discovery() discovery.DiscoveryInterfaces {
+       return c.discovery
+}
+
+func (c *Clientset) Tracker() testing.ObjectTracker {
+       return c.tracker
+}
+
+// IsWatchListSemanticsUnSupported informs the reflector that this client
+// doesn't support WatchList semantics.
+//
+// This is a synthetic method whose sole purpose is to satisfy the optional
+// interface check performed by the reflector.
+// Returning true signals that WatchList can NOT be used.
+// No additional logic is implemented here.
+func (c *Clientset) IsWatchListSemanticsUnSupported() bool {
+       return true
+}
+
+var (
+       _ clientset.Interface = &Clientset{}
+       _ testing.FakeClient  = &Clientset{}
+)
+
+// BrokerV1beta1 retrieves the BrokerV1beta1Client
+func (c *Clientset) BrokerV1beta1() brokerv1beta1.BrokerV1beta1Interface {
+       return &fakebrokerv1beta1.FakeBrokerV1beta1{Fake: &c.Fake}
+}
diff --git a/pkg/client/arkmq/clientset/internalclientset/fake/doc.go 
b/pkg/client/arkmq/clientset/internalclientset/fake/doc.go
new file mode 100644
index 000000000..9c6a5fa07
--- /dev/null
+++ b/pkg/client/arkmq/clientset/internalclientset/fake/doc.go
@@ -0,0 +1,21 @@
+/*
+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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+// This package has the automatically generated fake clientset.
+package fake
diff --git a/pkg/client/arkmq/clientset/internalclientset/fake/register.go 
b/pkg/client/arkmq/clientset/internalclientset/fake/register.go
new file mode 100644
index 000000000..6626d0c24
--- /dev/null
+++ b/pkg/client/arkmq/clientset/internalclientset/fake/register.go
@@ -0,0 +1,57 @@
+/*
+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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+import (
+       brokerv1beta1 "github.com/apache/camel-k/v2/pkg/apis/duck/arkmq/v1beta1"
+       v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+       runtime "k8s.io/apimachinery/pkg/runtime"
+       schema "k8s.io/apimachinery/pkg/runtime/schema"
+       serializer "k8s.io/apimachinery/pkg/runtime/serializer"
+       utilruntime "k8s.io/apimachinery/pkg/util/runtime"
+)
+
+var scheme = runtime.NewScheme()
+var codecs = serializer.NewCodecFactory(scheme)
+
+var localSchemeBuilder = runtime.SchemeBuilder{
+       brokerv1beta1.AddToScheme,
+}
+
+// AddToScheme adds all types of this clientset into the given scheme. This 
allows composition
+// of clientsets, like in:
+//
+//     import (
+//       "k8s.io/client-go/kubernetes"
+//       clientsetscheme "k8s.io/client-go/kubernetes/scheme"
+//       aggregatorclientsetscheme 
"k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/scheme"
+//     )
+//
+//     kclientset, _ := kubernetes.NewForConfig(c)
+//     _ = aggregatorclientsetscheme.AddToScheme(clientsetscheme.Scheme)
+//
+// After this, RawExtensions in Kubernetes types will serialize 
kube-aggregator types
+// correctly.
+var AddToScheme = localSchemeBuilder.AddToScheme
+
+func init() {
+       v1.AddToGroupVersion(scheme, schema.GroupVersion{Version: "v1"})
+       utilruntime.Must(AddToScheme(scheme))
+}
diff --git a/pkg/client/arkmq/clientset/internalclientset/scheme/doc.go 
b/pkg/client/arkmq/clientset/internalclientset/scheme/doc.go
new file mode 100644
index 000000000..dd7d3b588
--- /dev/null
+++ b/pkg/client/arkmq/clientset/internalclientset/scheme/doc.go
@@ -0,0 +1,21 @@
+/*
+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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+// This package contains the scheme of the automatically generated clientset.
+package scheme
diff --git a/pkg/client/arkmq/clientset/internalclientset/scheme/register.go 
b/pkg/client/arkmq/clientset/internalclientset/scheme/register.go
new file mode 100644
index 000000000..4d0cfde87
--- /dev/null
+++ b/pkg/client/arkmq/clientset/internalclientset/scheme/register.go
@@ -0,0 +1,57 @@
+/*
+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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package scheme
+
+import (
+       brokerv1beta1 "github.com/apache/camel-k/v2/pkg/apis/duck/arkmq/v1beta1"
+       v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+       runtime "k8s.io/apimachinery/pkg/runtime"
+       schema "k8s.io/apimachinery/pkg/runtime/schema"
+       serializer "k8s.io/apimachinery/pkg/runtime/serializer"
+       utilruntime "k8s.io/apimachinery/pkg/util/runtime"
+)
+
+var Scheme = runtime.NewScheme()
+var Codecs = serializer.NewCodecFactory(Scheme)
+var ParameterCodec = runtime.NewParameterCodec(Scheme)
+var localSchemeBuilder = runtime.SchemeBuilder{
+       brokerv1beta1.AddToScheme,
+}
+
+// AddToScheme adds all types of this clientset into the given scheme. This 
allows composition
+// of clientsets, like in:
+//
+//     import (
+//       "k8s.io/client-go/kubernetes"
+//       clientsetscheme "k8s.io/client-go/kubernetes/scheme"
+//       aggregatorclientsetscheme 
"k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/scheme"
+//     )
+//
+//     kclientset, _ := kubernetes.NewForConfig(c)
+//     _ = aggregatorclientsetscheme.AddToScheme(clientsetscheme.Scheme)
+//
+// After this, RawExtensions in Kubernetes types will serialize 
kube-aggregator types
+// correctly.
+var AddToScheme = localSchemeBuilder.AddToScheme
+
+func init() {
+       v1.AddToGroupVersion(Scheme, schema.GroupVersion{Version: "v1"})
+       utilruntime.Must(AddToScheme(Scheme))
+}
diff --git 
a/pkg/client/arkmq/clientset/internalclientset/typed/arkmq/v1beta1/activemqartemis.go
 
b/pkg/client/arkmq/clientset/internalclientset/typed/arkmq/v1beta1/activemqartemis.go
new file mode 100644
index 000000000..b4c09a538
--- /dev/null
+++ 
b/pkg/client/arkmq/clientset/internalclientset/typed/arkmq/v1beta1/activemqartemis.go
@@ -0,0 +1,63 @@
+/*
+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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package v1beta1
+
+import (
+       context "context"
+
+       arkmqv1beta1 "github.com/apache/camel-k/v2/pkg/apis/duck/arkmq/v1beta1"
+       scheme 
"github.com/apache/camel-k/v2/pkg/client/arkmq/clientset/internalclientset/scheme"
+       v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+       watch "k8s.io/apimachinery/pkg/watch"
+       gentype "k8s.io/client-go/gentype"
+)
+
+// ActiveMQArtemisesGetter has a method to return a ActiveMQArtemisInterface.
+// A group's client should implement this interface.
+type ActiveMQArtemisesGetter interface {
+       ActiveMQArtemises(namespace string) ActiveMQArtemisInterface
+}
+
+// ActiveMQArtemisInterface has methods to work with ActiveMQArtemis resources.
+type ActiveMQArtemisInterface interface {
+       Get(ctx context.Context, name string, opts v1.GetOptions) 
(*arkmqv1beta1.ActiveMQArtemis, error)
+       List(ctx context.Context, opts v1.ListOptions) 
(*arkmqv1beta1.ActiveMQArtemisList, error)
+       Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error)
+       ActiveMQArtemisExpansion
+}
+
+// activeMQArtemises implements ActiveMQArtemisInterface
+type activeMQArtemises struct {
+       *gentype.ClientWithList[*arkmqv1beta1.ActiveMQArtemis, 
*arkmqv1beta1.ActiveMQArtemisList]
+}
+
+// newActiveMQArtemises returns a ActiveMQArtemises
+func newActiveMQArtemises(c *BrokerV1beta1Client, namespace string) 
*activeMQArtemises {
+       return &activeMQArtemises{
+               gentype.NewClientWithList[*arkmqv1beta1.ActiveMQArtemis, 
*arkmqv1beta1.ActiveMQArtemisList](
+                       "activemqartemises",
+                       c.RESTClient(),
+                       scheme.ParameterCodec,
+                       namespace,
+                       func() *arkmqv1beta1.ActiveMQArtemis { return 
&arkmqv1beta1.ActiveMQArtemis{} },
+                       func() *arkmqv1beta1.ActiveMQArtemisList { return 
&arkmqv1beta1.ActiveMQArtemisList{} },
+               ),
+       }
+}
diff --git 
a/pkg/client/arkmq/clientset/internalclientset/typed/arkmq/v1beta1/activemqartemisaddress.go
 
b/pkg/client/arkmq/clientset/internalclientset/typed/arkmq/v1beta1/activemqartemisaddress.go
new file mode 100644
index 000000000..f8d753cac
--- /dev/null
+++ 
b/pkg/client/arkmq/clientset/internalclientset/typed/arkmq/v1beta1/activemqartemisaddress.go
@@ -0,0 +1,63 @@
+/*
+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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package v1beta1
+
+import (
+       context "context"
+
+       arkmqv1beta1 "github.com/apache/camel-k/v2/pkg/apis/duck/arkmq/v1beta1"
+       scheme 
"github.com/apache/camel-k/v2/pkg/client/arkmq/clientset/internalclientset/scheme"
+       v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+       watch "k8s.io/apimachinery/pkg/watch"
+       gentype "k8s.io/client-go/gentype"
+)
+
+// ActiveMQArtemisAddressesGetter has a method to return a 
ActiveMQArtemisAddressInterface.
+// A group's client should implement this interface.
+type ActiveMQArtemisAddressesGetter interface {
+       ActiveMQArtemisAddresses(namespace string) 
ActiveMQArtemisAddressInterface
+}
+
+// ActiveMQArtemisAddressInterface has methods to work with 
ActiveMQArtemisAddress resources.
+type ActiveMQArtemisAddressInterface interface {
+       Get(ctx context.Context, name string, opts v1.GetOptions) 
(*arkmqv1beta1.ActiveMQArtemisAddress, error)
+       List(ctx context.Context, opts v1.ListOptions) 
(*arkmqv1beta1.ActiveMQArtemisAddressList, error)
+       Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error)
+       ActiveMQArtemisAddressExpansion
+}
+
+// activeMQArtemisAddresses implements ActiveMQArtemisAddressInterface
+type activeMQArtemisAddresses struct {
+       *gentype.ClientWithList[*arkmqv1beta1.ActiveMQArtemisAddress, 
*arkmqv1beta1.ActiveMQArtemisAddressList]
+}
+
+// newActiveMQArtemisAddresses returns a ActiveMQArtemisAddresses
+func newActiveMQArtemisAddresses(c *BrokerV1beta1Client, namespace string) 
*activeMQArtemisAddresses {
+       return &activeMQArtemisAddresses{
+               gentype.NewClientWithList[*arkmqv1beta1.ActiveMQArtemisAddress, 
*arkmqv1beta1.ActiveMQArtemisAddressList](
+                       "activemqartemisaddresses",
+                       c.RESTClient(),
+                       scheme.ParameterCodec,
+                       namespace,
+                       func() *arkmqv1beta1.ActiveMQArtemisAddress { return 
&arkmqv1beta1.ActiveMQArtemisAddress{} },
+                       func() *arkmqv1beta1.ActiveMQArtemisAddressList { 
return &arkmqv1beta1.ActiveMQArtemisAddressList{} },
+               ),
+       }
+}
diff --git 
a/pkg/client/arkmq/clientset/internalclientset/typed/arkmq/v1beta1/arkmq_client.go
 
b/pkg/client/arkmq/clientset/internalclientset/typed/arkmq/v1beta1/arkmq_client.go
new file mode 100644
index 000000000..881d6e2cf
--- /dev/null
+++ 
b/pkg/client/arkmq/clientset/internalclientset/typed/arkmq/v1beta1/arkmq_client.go
@@ -0,0 +1,107 @@
+/*
+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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package v1beta1
+
+import (
+       http "net/http"
+
+       arkmqv1beta1 "github.com/apache/camel-k/v2/pkg/apis/duck/arkmq/v1beta1"
+       scheme 
"github.com/apache/camel-k/v2/pkg/client/arkmq/clientset/internalclientset/scheme"
+       rest "k8s.io/client-go/rest"
+)
+
+type BrokerV1beta1Interface interface {
+       RESTClient() rest.Interface
+       ActiveMQArtemisesGetter
+       ActiveMQArtemisAddressesGetter
+}
+
+// BrokerV1beta1Client is used to interact with features provided by the 
broker.amq.io group.
+type BrokerV1beta1Client struct {
+       restClient rest.Interface
+}
+
+func (c *BrokerV1beta1Client) ActiveMQArtemises(namespace string) 
ActiveMQArtemisInterface {
+       return newActiveMQArtemises(c, namespace)
+}
+
+func (c *BrokerV1beta1Client) ActiveMQArtemisAddresses(namespace string) 
ActiveMQArtemisAddressInterface {
+       return newActiveMQArtemisAddresses(c, namespace)
+}
+
+// NewForConfig creates a new BrokerV1beta1Client for the given config.
+// NewForConfig is equivalent to NewForConfigAndClient(c, httpClient),
+// where httpClient was generated with rest.HTTPClientFor(c).
+func NewForConfig(c *rest.Config) (*BrokerV1beta1Client, error) {
+       config := *c
+       setConfigDefaults(&config)
+       httpClient, err := rest.HTTPClientFor(&config)
+       if err != nil {
+               return nil, err
+       }
+       return NewForConfigAndClient(&config, httpClient)
+}
+
+// NewForConfigAndClient creates a new BrokerV1beta1Client for the given 
config and http client.
+// Note the http client provided takes precedence over the configured 
transport values.
+func NewForConfigAndClient(c *rest.Config, h *http.Client) 
(*BrokerV1beta1Client, error) {
+       config := *c
+       setConfigDefaults(&config)
+       client, err := rest.RESTClientForConfigAndClient(&config, h)
+       if err != nil {
+               return nil, err
+       }
+       return &BrokerV1beta1Client{client}, nil
+}
+
+// NewForConfigOrDie creates a new BrokerV1beta1Client for the given config and
+// panics if there is an error in the config.
+func NewForConfigOrDie(c *rest.Config) *BrokerV1beta1Client {
+       client, err := NewForConfig(c)
+       if err != nil {
+               panic(err)
+       }
+       return client
+}
+
+// New creates a new BrokerV1beta1Client for the given RESTClient.
+func New(c rest.Interface) *BrokerV1beta1Client {
+       return &BrokerV1beta1Client{c}
+}
+
+func setConfigDefaults(config *rest.Config) {
+       gv := arkmqv1beta1.SchemeGroupVersion
+       config.GroupVersion = &gv
+       config.APIPath = "/apis"
+       config.NegotiatedSerializer = 
rest.CodecFactoryForGeneratedClient(scheme.Scheme, 
scheme.Codecs).WithoutConversion()
+
+       if config.UserAgent == "" {
+               config.UserAgent = rest.DefaultKubernetesUserAgent()
+       }
+}
+
+// RESTClient returns a RESTClient that is used to communicate
+// with API server by this client implementation.
+func (c *BrokerV1beta1Client) RESTClient() rest.Interface {
+       if c == nil {
+               return nil
+       }
+       return c.restClient
+}
diff --git 
a/pkg/client/arkmq/clientset/internalclientset/typed/arkmq/v1beta1/doc.go 
b/pkg/client/arkmq/clientset/internalclientset/typed/arkmq/v1beta1/doc.go
new file mode 100644
index 000000000..69b5e249c
--- /dev/null
+++ b/pkg/client/arkmq/clientset/internalclientset/typed/arkmq/v1beta1/doc.go
@@ -0,0 +1,21 @@
+/*
+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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+// This package has the automatically generated typed clients.
+package v1beta1
diff --git 
a/pkg/client/arkmq/clientset/internalclientset/typed/arkmq/v1beta1/fake/doc.go 
b/pkg/client/arkmq/clientset/internalclientset/typed/arkmq/v1beta1/fake/doc.go
new file mode 100644
index 000000000..5d1c76cc9
--- /dev/null
+++ 
b/pkg/client/arkmq/clientset/internalclientset/typed/arkmq/v1beta1/fake/doc.go
@@ -0,0 +1,21 @@
+/*
+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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+// Package fake has the automatically generated clients.
+package fake
diff --git 
a/pkg/client/arkmq/clientset/internalclientset/typed/arkmq/v1beta1/fake/fake_activemqartemis.go
 
b/pkg/client/arkmq/clientset/internalclientset/typed/arkmq/v1beta1/fake/fake_activemqartemis.go
new file mode 100644
index 000000000..5c4620f05
--- /dev/null
+++ 
b/pkg/client/arkmq/clientset/internalclientset/typed/arkmq/v1beta1/fake/fake_activemqartemis.go
@@ -0,0 +1,53 @@
+/*
+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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+import (
+       v1beta1 "github.com/apache/camel-k/v2/pkg/apis/duck/arkmq/v1beta1"
+       arkmqv1beta1 
"github.com/apache/camel-k/v2/pkg/client/arkmq/clientset/internalclientset/typed/arkmq/v1beta1"
+       gentype "k8s.io/client-go/gentype"
+)
+
+// fakeActiveMQArtemises implements ActiveMQArtemisInterface
+type fakeActiveMQArtemises struct {
+       *gentype.FakeClientWithList[*v1beta1.ActiveMQArtemis, 
*v1beta1.ActiveMQArtemisList]
+       Fake *FakeBrokerV1beta1
+}
+
+func newFakeActiveMQArtemises(fake *FakeBrokerV1beta1, namespace string) 
arkmqv1beta1.ActiveMQArtemisInterface {
+       return &fakeActiveMQArtemises{
+               gentype.NewFakeClientWithList[*v1beta1.ActiveMQArtemis, 
*v1beta1.ActiveMQArtemisList](
+                       fake.Fake,
+                       namespace,
+                       
v1beta1.SchemeGroupVersion.WithResource("activemqartemises"),
+                       v1beta1.SchemeGroupVersion.WithKind("ActiveMQArtemis"),
+                       func() *v1beta1.ActiveMQArtemis { return 
&v1beta1.ActiveMQArtemis{} },
+                       func() *v1beta1.ActiveMQArtemisList { return 
&v1beta1.ActiveMQArtemisList{} },
+                       func(dst, src *v1beta1.ActiveMQArtemisList) { 
dst.ListMeta = src.ListMeta },
+                       func(list *v1beta1.ActiveMQArtemisList) 
[]*v1beta1.ActiveMQArtemis {
+                               return gentype.ToPointerSlice(list.Items)
+                       },
+                       func(list *v1beta1.ActiveMQArtemisList, items 
[]*v1beta1.ActiveMQArtemis) {
+                               list.Items = gentype.FromPointerSlice(items)
+                       },
+               ),
+               fake,
+       }
+}
diff --git 
a/pkg/client/arkmq/clientset/internalclientset/typed/arkmq/v1beta1/fake/fake_activemqartemisaddress.go
 
b/pkg/client/arkmq/clientset/internalclientset/typed/arkmq/v1beta1/fake/fake_activemqartemisaddress.go
new file mode 100644
index 000000000..2f6681b77
--- /dev/null
+++ 
b/pkg/client/arkmq/clientset/internalclientset/typed/arkmq/v1beta1/fake/fake_activemqartemisaddress.go
@@ -0,0 +1,53 @@
+/*
+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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+import (
+       v1beta1 "github.com/apache/camel-k/v2/pkg/apis/duck/arkmq/v1beta1"
+       arkmqv1beta1 
"github.com/apache/camel-k/v2/pkg/client/arkmq/clientset/internalclientset/typed/arkmq/v1beta1"
+       gentype "k8s.io/client-go/gentype"
+)
+
+// fakeActiveMQArtemisAddresses implements ActiveMQArtemisAddressInterface
+type fakeActiveMQArtemisAddresses struct {
+       *gentype.FakeClientWithList[*v1beta1.ActiveMQArtemisAddress, 
*v1beta1.ActiveMQArtemisAddressList]
+       Fake *FakeBrokerV1beta1
+}
+
+func newFakeActiveMQArtemisAddresses(fake *FakeBrokerV1beta1, namespace 
string) arkmqv1beta1.ActiveMQArtemisAddressInterface {
+       return &fakeActiveMQArtemisAddresses{
+               gentype.NewFakeClientWithList[*v1beta1.ActiveMQArtemisAddress, 
*v1beta1.ActiveMQArtemisAddressList](
+                       fake.Fake,
+                       namespace,
+                       
v1beta1.SchemeGroupVersion.WithResource("activemqartemisaddresses"),
+                       
v1beta1.SchemeGroupVersion.WithKind("ActiveMQArtemisAddress"),
+                       func() *v1beta1.ActiveMQArtemisAddress { return 
&v1beta1.ActiveMQArtemisAddress{} },
+                       func() *v1beta1.ActiveMQArtemisAddressList { return 
&v1beta1.ActiveMQArtemisAddressList{} },
+                       func(dst, src *v1beta1.ActiveMQArtemisAddressList) { 
dst.ListMeta = src.ListMeta },
+                       func(list *v1beta1.ActiveMQArtemisAddressList) 
[]*v1beta1.ActiveMQArtemisAddress {
+                               return gentype.ToPointerSlice(list.Items)
+                       },
+                       func(list *v1beta1.ActiveMQArtemisAddressList, items 
[]*v1beta1.ActiveMQArtemisAddress) {
+                               list.Items = gentype.FromPointerSlice(items)
+                       },
+               ),
+               fake,
+       }
+}
diff --git 
a/pkg/client/arkmq/clientset/internalclientset/typed/arkmq/v1beta1/fake/fake_arkmq_client.go
 
b/pkg/client/arkmq/clientset/internalclientset/typed/arkmq/v1beta1/fake/fake_arkmq_client.go
new file mode 100644
index 000000000..be83e82fc
--- /dev/null
+++ 
b/pkg/client/arkmq/clientset/internalclientset/typed/arkmq/v1beta1/fake/fake_arkmq_client.go
@@ -0,0 +1,45 @@
+/*
+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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+import (
+       v1beta1 
"github.com/apache/camel-k/v2/pkg/client/arkmq/clientset/internalclientset/typed/arkmq/v1beta1"
+       rest "k8s.io/client-go/rest"
+       testing "k8s.io/client-go/testing"
+)
+
+type FakeBrokerV1beta1 struct {
+       *testing.Fake
+}
+
+func (c *FakeBrokerV1beta1) ActiveMQArtemises(namespace string) 
v1beta1.ActiveMQArtemisInterface {
+       return newFakeActiveMQArtemises(c, namespace)
+}
+
+func (c *FakeBrokerV1beta1) ActiveMQArtemisAddresses(namespace string) 
v1beta1.ActiveMQArtemisAddressInterface {
+       return newFakeActiveMQArtemisAddresses(c, namespace)
+}
+
+// RESTClient returns a RESTClient that is used to communicate
+// with API server by this client implementation.
+func (c *FakeBrokerV1beta1) RESTClient() rest.Interface {
+       var ret *rest.RESTClient
+       return ret
+}
diff --git 
a/pkg/client/arkmq/clientset/internalclientset/typed/arkmq/v1beta1/generated_expansion.go
 
b/pkg/client/arkmq/clientset/internalclientset/typed/arkmq/v1beta1/generated_expansion.go
new file mode 100644
index 000000000..50d18cb0c
--- /dev/null
+++ 
b/pkg/client/arkmq/clientset/internalclientset/typed/arkmq/v1beta1/generated_expansion.go
@@ -0,0 +1,24 @@
+/*
+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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package v1beta1
+
+type ActiveMQArtemisExpansion interface{}
+
+type ActiveMQArtemisAddressExpansion interface{}
diff --git a/pkg/controller/pipe/initialize_test.go 
b/pkg/controller/pipe/initialize_test.go
index 29b092880..d0d9baa8b 100644
--- a/pkg/controller/pipe/initialize_test.go
+++ b/pkg/controller/pipe/initialize_test.go
@@ -262,14 +262,14 @@ func TestNewPipeUnsupportedRef(t *testing.T) {
        handledPipe, err := a.Handle(context.TODO(), pipe)
        require.Error(t, err)
        assert.Equal(t, "could not find any suitable binding provider for 
my-api-version/my-kind my-kind-name in namespace ns. "+
-               "Bindings available: [\"kamelet\" \"knative-uri\" \"strimzi\" 
\"service-ref\" \"camel-uri\" \"knative-ref\"]", err.Error())
+               "Bindings available: [\"arkmq\" \"kamelet\" \"knative-uri\" 
\"strimzi\" \"service-ref\" \"camel-uri\" \"knative-ref\"]", err.Error())
        assert.Equal(t, v1.PipePhaseError, handledPipe.Status.Phase)
        cond := handledPipe.Status.GetCondition(v1.PipeConditionReady)
        assert.NotNil(t, cond)
        assert.Equal(t, corev1.ConditionFalse, cond.Status)
        assert.Equal(t, "IntegrationError", cond.Reason)
        assert.Equal(t, "could not find any suitable binding provider for 
my-api-version/my-kind my-kind-name in namespace ns. "+
-               "Bindings available: [\"kamelet\" \"knative-uri\" \"strimzi\" 
\"service-ref\" \"camel-uri\" \"knative-ref\"]", cond.Message)
+               "Bindings available: [\"arkmq\" \"kamelet\" \"knative-uri\" 
\"strimzi\" \"service-ref\" \"camel-uri\" \"knative-ref\"]", cond.Message)
 }
 
 func TestNewPipeKnativeURIBinding(t *testing.T) {
@@ -472,6 +472,108 @@ func TestNewPipeStrimziKafkaBinding(t *testing.T) {
                "\"uri\":\"direct:something\"},\"id\":\"binding\"}}", 
string(flow))
 }
 
+func TestNewPipeArkMQBinding(t *testing.T) {
+       pipe := &v1.Pipe{
+               TypeMeta: metav1.TypeMeta{
+                       APIVersion: v1.SchemeGroupVersion.String(),
+                       Kind:       v1.PipeKind,
+               },
+               ObjectMeta: metav1.ObjectMeta{
+                       Namespace: "ns",
+                       Name:      "my-pipe",
+               },
+               Spec: v1.PipeSpec{
+                       Sink: v1.Endpoint{
+                               Ref: &corev1.ObjectReference{
+                                       Kind:       "ActiveMQArtemisAddress",
+                                       Name:       "my-queue",
+                                       APIVersion: "broker.amq.io/v1beta1",
+                               },
+                               Properties: 
asEndpointProperties(map[string]string{
+                                       "brokerURL": 
"tcp://my-broker-hdls-svc:61616",
+                               }),
+                       },
+                       Source: v1.Endpoint{
+                               URI: ptr.To("direct:something"),
+                       },
+               },
+       }
+       c, err := internal.NewFakeClient(pipe)
+       require.NoError(t, err)
+
+       a := NewInitializeAction()
+       a.InjectLogger(log.Log)
+       a.InjectClient(c)
+       assert.Equal(t, "initialize", a.Name())
+       assert.True(t, a.CanHandle(pipe))
+       handledPipe, err := a.Handle(context.TODO(), pipe)
+       require.NoError(t, err)
+       assert.Equal(t, v1.PipePhaseCreating, handledPipe.Status.Phase)
+       // Check integration which should have been created
+       expectedIT := v1.NewIntegration(pipe.Namespace, pipe.Name)
+       err = c.Get(context.Background(), 
ctrl.ObjectKeyFromObject(&expectedIT), &expectedIT)
+       require.NoError(t, err)
+       assert.Equal(t, pipe.Name, expectedIT.Name)
+       assert.Equal(t, v1.IntegrationPhaseNone, expectedIT.Status.Phase)
+       assert.Equal(t, "Pipe", 
expectedIT.Labels[kubernetes.CamelCreatorLabelKind])
+       assert.Equal(t, "my-pipe", 
expectedIT.Labels[kubernetes.CamelCreatorLabelName])
+       flow, err := json.Marshal(expectedIT.Spec.Flows[0].RawMessage)
+       require.NoError(t, err)
+       assert.Equal(t, 
"{\"route\":{\"from\":{\"steps\":[{\"to\":\"jms:queue:my-queue?brokerURL=tcp%3A%2F%2Fmy-broker-hdls-svc%3A61616\"}],"+
+               "\"uri\":\"direct:something\"},\"id\":\"binding\"}}", 
string(flow))
+}
+
+func TestNewPipeArkMQSourceBinding(t *testing.T) {
+       pipe := &v1.Pipe{
+               TypeMeta: metav1.TypeMeta{
+                       APIVersion: v1.SchemeGroupVersion.String(),
+                       Kind:       v1.PipeKind,
+               },
+               ObjectMeta: metav1.ObjectMeta{
+                       Namespace: "ns",
+                       Name:      "my-pipe-source",
+               },
+               Spec: v1.PipeSpec{
+                       Source: v1.Endpoint{
+                               Ref: &corev1.ObjectReference{
+                                       Kind:       "ActiveMQArtemisAddress",
+                                       Name:       "my-queue",
+                                       APIVersion: "broker.amq.io/v1beta1",
+                               },
+                               Properties: 
asEndpointProperties(map[string]string{
+                                       "brokerURL": 
"tcp://my-broker-hdls-svc:61616",
+                               }),
+                       },
+                       Sink: v1.Endpoint{
+                               URI: ptr.To("log:info"),
+                       },
+               },
+       }
+       c, err := internal.NewFakeClient(pipe)
+       require.NoError(t, err)
+
+       a := NewInitializeAction()
+       a.InjectLogger(log.Log)
+       a.InjectClient(c)
+       assert.Equal(t, "initialize", a.Name())
+       assert.True(t, a.CanHandle(pipe))
+       handledPipe, err := a.Handle(context.TODO(), pipe)
+       require.NoError(t, err)
+       assert.Equal(t, v1.PipePhaseCreating, handledPipe.Status.Phase)
+       // Check integration which should have been created
+       expectedIT := v1.NewIntegration(pipe.Namespace, pipe.Name)
+       err = c.Get(context.Background(), 
ctrl.ObjectKeyFromObject(&expectedIT), &expectedIT)
+       require.NoError(t, err)
+       assert.Equal(t, pipe.Name, expectedIT.Name)
+       assert.Equal(t, v1.IntegrationPhaseNone, expectedIT.Status.Phase)
+       assert.Equal(t, "Pipe", 
expectedIT.Labels[kubernetes.CamelCreatorLabelKind])
+       assert.Equal(t, "my-pipe-source", 
expectedIT.Labels[kubernetes.CamelCreatorLabelName])
+       flow, err := json.Marshal(expectedIT.Spec.Flows[0].RawMessage)
+       require.NoError(t, err)
+       assert.Equal(t, 
"{\"route\":{\"from\":{\"steps\":[{\"to\":\"log:info\"}],"+
+               
"\"uri\":\"jms:queue:my-queue?brokerURL=tcp%3A%2F%2Fmy-broker-hdls-svc%3A61616\"},\"id\":\"binding\"}}",
 string(flow))
+}
+
 func asEndpointProperties(props map[string]string) *v1.EndpointProperties {
        serialized, err := json.Marshal(props)
        if err != nil {
diff --git a/pkg/resources/config/rbac/descoped/kustomization.yaml 
b/pkg/resources/config/rbac/descoped/kustomization.yaml
index 54c7ebb7e..5dc488bed 100644
--- a/pkg/resources/config/rbac/descoped/kustomization.yaml
+++ b/pkg/resources/config/rbac/descoped/kustomization.yaml
@@ -31,6 +31,7 @@ resources:
 - operator-cluster-role-openshift.yaml
 - operator-cluster-role-podmonitors.yaml
 - operator-cluster-role-strimzi.yaml
+- operator-cluster-role-arkmq.yaml
 - operator-cluster-role-binding-certmanager.yaml
 - operator-cluster-role-binding-events.yaml
 - operator-cluster-role-binding-keda.yaml
@@ -39,4 +40,5 @@ resources:
 - operator-cluster-role-binding-openshift.yaml
 - operator-cluster-role-binding-podmonitors.yaml
 - operator-cluster-role-binding-strimzi.yaml
+- operator-cluster-role-binding-arkmq.yaml
 - operator-cluster-role-binding.yaml
diff --git a/pkg/resources/config/rbac/namespaced/kustomization.yaml 
b/pkg/resources/config/rbac/descoped/operator-cluster-role-arkmq.yaml
similarity index 55%
copy from pkg/resources/config/rbac/namespaced/kustomization.yaml
copy to pkg/resources/config/rbac/descoped/operator-cluster-role-arkmq.yaml
index e50bc5c5a..4fa6b9335 100644
--- a/pkg/resources/config/rbac/namespaced/kustomization.yaml
+++ b/pkg/resources/config/rbac/descoped/operator-cluster-role-arkmq.yaml
@@ -15,28 +15,18 @@
 # limitations under the License.
 # ---------------------------------------------------------------------------
 
-#
-# rbac resources applicable for all kubernetes platforms - namespaced operator
-#
-apiVersion: kustomize.config.k8s.io/v1beta1
-kind: Kustomization
-
-resources:
-- operator-role-certmanager.yaml
-- operator-role-events.yaml
-- operator-role.yaml
-- operator-role-keda.yaml
-- operator-role-knative.yaml
-- operator-role-leases.yaml
-- operator-role-openshift.yaml
-- operator-role-podmonitors.yaml
-- operator-role-strimzi.yaml
-- operator-role-binding.yaml
-- operator-role-binding-certmanager.yaml
-- operator-role-binding-events.yaml
-- operator-role-binding-keda.yaml
-- operator-role-binding-knative.yaml
-- operator-role-binding-leases.yaml
-- operator-role-binding-openshift.yaml
-- operator-role-binding-podmonitors.yaml
-- operator-role-binding-strimzi.yaml
+kind: ClusterRole
+apiVersion: rbac.authorization.k8s.io/v1
+metadata:
+  name: camel-k-operator-arkmq
+  labels:
+    app: "camel-k"
+rules:
+- apiGroups:
+  - "broker.amq.io"
+  resources:
+  - activemqartemises
+  - activemqartemisaddresses
+  verbs:
+  - get
+  - list
diff --git a/pkg/resources/config/rbac/namespaced/kustomization.yaml 
b/pkg/resources/config/rbac/descoped/operator-cluster-role-binding-arkmq.yaml
similarity index 55%
copy from pkg/resources/config/rbac/namespaced/kustomization.yaml
copy to 
pkg/resources/config/rbac/descoped/operator-cluster-role-binding-arkmq.yaml
index e50bc5c5a..246ce2b31 100644
--- a/pkg/resources/config/rbac/namespaced/kustomization.yaml
+++ 
b/pkg/resources/config/rbac/descoped/operator-cluster-role-binding-arkmq.yaml
@@ -15,28 +15,16 @@
 # limitations under the License.
 # ---------------------------------------------------------------------------
 
-#
-# rbac resources applicable for all kubernetes platforms - namespaced operator
-#
-apiVersion: kustomize.config.k8s.io/v1beta1
-kind: Kustomization
-
-resources:
-- operator-role-certmanager.yaml
-- operator-role-events.yaml
-- operator-role.yaml
-- operator-role-keda.yaml
-- operator-role-knative.yaml
-- operator-role-leases.yaml
-- operator-role-openshift.yaml
-- operator-role-podmonitors.yaml
-- operator-role-strimzi.yaml
-- operator-role-binding.yaml
-- operator-role-binding-certmanager.yaml
-- operator-role-binding-events.yaml
-- operator-role-binding-keda.yaml
-- operator-role-binding-knative.yaml
-- operator-role-binding-leases.yaml
-- operator-role-binding-openshift.yaml
-- operator-role-binding-podmonitors.yaml
-- operator-role-binding-strimzi.yaml
+kind: ClusterRoleBinding
+apiVersion: rbac.authorization.k8s.io/v1
+metadata:
+  name: camel-k-operator-arkmq
+  labels:
+    app: "camel-k"
+subjects:
+- kind: ServiceAccount
+  name: camel-k-operator
+roleRef:
+  kind: ClusterRole
+  name: camel-k-operator-arkmq
+  apiGroup: rbac.authorization.k8s.io
diff --git a/pkg/resources/config/rbac/namespaced/kustomization.yaml 
b/pkg/resources/config/rbac/namespaced/kustomization.yaml
index e50bc5c5a..bc20eb79b 100644
--- a/pkg/resources/config/rbac/namespaced/kustomization.yaml
+++ b/pkg/resources/config/rbac/namespaced/kustomization.yaml
@@ -31,6 +31,7 @@ resources:
 - operator-role-openshift.yaml
 - operator-role-podmonitors.yaml
 - operator-role-strimzi.yaml
+- operator-role-arkmq.yaml
 - operator-role-binding.yaml
 - operator-role-binding-certmanager.yaml
 - operator-role-binding-events.yaml
@@ -40,3 +41,4 @@ resources:
 - operator-role-binding-openshift.yaml
 - operator-role-binding-podmonitors.yaml
 - operator-role-binding-strimzi.yaml
+- operator-role-binding-arkmq.yaml
diff --git a/pkg/resources/config/rbac/namespaced/kustomization.yaml 
b/pkg/resources/config/rbac/namespaced/operator-role-arkmq.yaml
similarity index 55%
copy from pkg/resources/config/rbac/namespaced/kustomization.yaml
copy to pkg/resources/config/rbac/namespaced/operator-role-arkmq.yaml
index e50bc5c5a..62c13b356 100644
--- a/pkg/resources/config/rbac/namespaced/kustomization.yaml
+++ b/pkg/resources/config/rbac/namespaced/operator-role-arkmq.yaml
@@ -15,28 +15,18 @@
 # limitations under the License.
 # ---------------------------------------------------------------------------
 
-#
-# rbac resources applicable for all kubernetes platforms - namespaced operator
-#
-apiVersion: kustomize.config.k8s.io/v1beta1
-kind: Kustomization
-
-resources:
-- operator-role-certmanager.yaml
-- operator-role-events.yaml
-- operator-role.yaml
-- operator-role-keda.yaml
-- operator-role-knative.yaml
-- operator-role-leases.yaml
-- operator-role-openshift.yaml
-- operator-role-podmonitors.yaml
-- operator-role-strimzi.yaml
-- operator-role-binding.yaml
-- operator-role-binding-certmanager.yaml
-- operator-role-binding-events.yaml
-- operator-role-binding-keda.yaml
-- operator-role-binding-knative.yaml
-- operator-role-binding-leases.yaml
-- operator-role-binding-openshift.yaml
-- operator-role-binding-podmonitors.yaml
-- operator-role-binding-strimzi.yaml
+kind: Role
+apiVersion: rbac.authorization.k8s.io/v1
+metadata:
+  name: camel-k-operator-arkmq
+  labels:
+    app: "camel-k"
+rules:
+- apiGroups:
+  - "broker.amq.io"
+  resources:
+  - activemqartemises
+  - activemqartemisaddresses
+  verbs:
+  - get
+  - list
diff --git a/pkg/resources/config/rbac/namespaced/kustomization.yaml 
b/pkg/resources/config/rbac/namespaced/operator-role-binding-arkmq.yaml
similarity index 55%
copy from pkg/resources/config/rbac/namespaced/kustomization.yaml
copy to pkg/resources/config/rbac/namespaced/operator-role-binding-arkmq.yaml
index e50bc5c5a..dd85c814a 100644
--- a/pkg/resources/config/rbac/namespaced/kustomization.yaml
+++ b/pkg/resources/config/rbac/namespaced/operator-role-binding-arkmq.yaml
@@ -15,28 +15,16 @@
 # limitations under the License.
 # ---------------------------------------------------------------------------
 
-#
-# rbac resources applicable for all kubernetes platforms - namespaced operator
-#
-apiVersion: kustomize.config.k8s.io/v1beta1
-kind: Kustomization
-
-resources:
-- operator-role-certmanager.yaml
-- operator-role-events.yaml
-- operator-role.yaml
-- operator-role-keda.yaml
-- operator-role-knative.yaml
-- operator-role-leases.yaml
-- operator-role-openshift.yaml
-- operator-role-podmonitors.yaml
-- operator-role-strimzi.yaml
-- operator-role-binding.yaml
-- operator-role-binding-certmanager.yaml
-- operator-role-binding-events.yaml
-- operator-role-binding-keda.yaml
-- operator-role-binding-knative.yaml
-- operator-role-binding-leases.yaml
-- operator-role-binding-openshift.yaml
-- operator-role-binding-podmonitors.yaml
-- operator-role-binding-strimzi.yaml
+kind: RoleBinding
+apiVersion: rbac.authorization.k8s.io/v1
+metadata:
+  name: camel-k-operator-arkmq
+  labels:
+    app: "camel-k"
+subjects:
+- kind: ServiceAccount
+  name: camel-k-operator
+roleRef:
+  kind: Role
+  name: camel-k-operator-arkmq
+  apiGroup: rbac.authorization.k8s.io
diff --git a/pkg/util/bindings/arkmq.go b/pkg/util/bindings/arkmq.go
new file mode 100644
index 000000000..94b1da06e
--- /dev/null
+++ b/pkg/util/bindings/arkmq.go
@@ -0,0 +1,217 @@
+/*
+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 bindings
+
+import (
+       "fmt"
+
+       camelv1 "github.com/apache/camel-k/v2/pkg/apis/camel/v1"
+       arkmqv1beta1 "github.com/apache/camel-k/v2/pkg/apis/duck/arkmq/v1beta1"
+       
"github.com/apache/camel-k/v2/pkg/client/arkmq/clientset/internalclientset"
+       "github.com/apache/camel-k/v2/pkg/util/uri"
+       k8serrors "k8s.io/apimachinery/pkg/api/errors"
+       v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+       "k8s.io/apimachinery/pkg/runtime/schema"
+)
+
+func init() {
+       RegisterBindingProvider(ArkMQBindingProvider{})
+}
+
+// camelArkMQ represents the configuration required by Camel JMS component for 
ArkMQ.
+type camelArkMQ struct {
+       queueName  string
+       properties map[string]string
+}
+
+// ArkMQBindingProvider allows connecting to an ArkMQ queue via Binding.
+type ArkMQBindingProvider struct {
+       Client internalclientset.Interface
+}
+
+func (a ArkMQBindingProvider) ID() string {
+       return "arkmq"
+}
+
+func (a ArkMQBindingProvider) Translate(ctx BindingContext, _ EndpointContext, 
endpoint camelv1.Endpoint) (*Binding, error) {
+       if endpoint.Ref == nil {
+               // IMPORTANT: just pass through if this provider cannot manage 
the binding. Another provider in the chain may take care of it.
+               return nil, nil
+       }
+       gv, err := schema.ParseGroupVersion(endpoint.Ref.APIVersion)
+       if err != nil {
+               return nil, err
+       }
+       if gv.Group != arkmqv1beta1.ArkMQGroup {
+               // IMPORTANT: just pass through if this provider cannot manage 
the binding. Another provider in the chain may take care of it.
+               return nil, nil
+       }
+
+       camelArkMQ, err := a.toCamelArkMQ(ctx, endpoint)
+       if err != nil {
+               return nil, err
+       }
+       arkmqURI := "jms:queue:" + camelArkMQ.queueName
+       arkmqURI = uri.AppendParameters(arkmqURI, camelArkMQ.properties)
+
+       return &Binding{
+               URI: arkmqURI,
+       }, nil
+}
+
+// toCamelArkMQ serializes an endpoint to a camelArkMQ struct.
+func (a ArkMQBindingProvider) toCamelArkMQ(ctx BindingContext, endpoint 
camelv1.Endpoint) (*camelArkMQ, error) {
+       if endpoint.Ref.Kind != arkmqv1beta1.ArkMQKindAddress {
+               return nil, fmt.Errorf("invalid endpoint kind %q. Can only work 
with %s kind",
+                       endpoint.Ref.Kind, arkmqv1beta1.ArkMQKindAddress)
+       }
+
+       return a.fromAddressToCamel(ctx, endpoint)
+}
+
+// Verify and transform an ActiveMQArtemisAddress resource to Camel JMS queue 
endpoint parameters.
+func (a ArkMQBindingProvider) fromAddressToCamel(ctx BindingContext, endpoint 
camelv1.Endpoint) (*camelArkMQ, error) {
+       props, err := endpoint.Properties.GetPropertyMap()
+       if err != nil {
+               return nil, err
+       }
+       if props == nil {
+               props = make(map[string]string)
+       }
+
+       queueName := endpoint.Ref.Name
+       if props["brokerURL"] == "" {
+               address, err := a.lookupAddress(ctx, endpoint)
+               if err != nil {
+                       return nil, err
+               }
+
+               if address.Spec.RoutingType == "multicast" {
+                       return nil, fmt.Errorf("multicast addresses (topics) 
are not supported on queue binding %s", endpoint.Ref.Name)
+               }
+
+               if address.Spec.QueueName != "" {
+                       queueName = address.Spec.QueueName
+               } else if address.Spec.AddressName != "" {
+                       queueName = address.Spec.AddressName
+               }
+
+               brokerURL, err := a.lookupBrokerURL(ctx, address, endpoint)
+               if err != nil {
+                       return nil, err
+               }
+
+               props["brokerURL"] = brokerURL
+       }
+
+       return &camelArkMQ{
+               queueName:  queueName,
+               properties: props,
+       }, nil
+}
+
+func (a ArkMQBindingProvider) lookupBrokerURL(ctx BindingContext, address 
*arkmqv1beta1.ActiveMQArtemisAddress, endpoint camelv1.Endpoint) (string, 
error) {
+       clusterName := address.Spec.ApplyTo
+       if clusterName == "" && address.Labels != nil {
+               clusterName = address.Labels[arkmqv1beta1.ArkMQBrokerLabel]
+       }
+       if clusterName == "" {
+               return "", fmt.Errorf("no %q label or applyTo defined on 
address %s", arkmqv1beta1.ArkMQBrokerLabel, endpoint.Ref.Name)
+       }
+
+       namespace := endpoint.Ref.Namespace
+       if namespace == "" {
+               namespace = ctx.Namespace
+       }
+
+       return a.getBrokerURL(ctx, clusterName, namespace)
+}
+
+func (a ArkMQBindingProvider) getBrokerURL(ctx BindingContext, clusterName, 
namespace string) (string, error) {
+       client := a.Client
+       if client == nil {
+               arkmqClient, err := 
internalclientset.NewForConfig(ctx.Client.GetConfig())
+               if err != nil {
+                       return "", err
+               }
+               client = arkmqClient
+       }
+
+       broker, err := 
client.BrokerV1beta1().ActiveMQArtemises(namespace).Get(ctx.Ctx, clusterName, 
v1.GetOptions{})
+       if err != nil {
+               return "", err
+       }
+
+       port := int32(61616)
+       for _, p := range broker.Status.PortStatus {
+               if p.Name == "core" || p.Name == "all" || p.Name == "openwire" {
+                       if p.Port > 0 {
+                               port = p.Port
+                               break
+                       }
+               }
+       }
+
+       if namespace != "" {
+               return fmt.Sprintf("tcp://%s-hdls-svc.%s.svc:%d", clusterName, 
namespace, port), nil
+       }
+       return fmt.Sprintf("tcp://%s-hdls-svc:%d", clusterName, port), nil
+}
+
+func (a ArkMQBindingProvider) lookupAddress(ctx BindingContext, endpoint 
camelv1.Endpoint) (*arkmqv1beta1.ActiveMQArtemisAddress, error) {
+       client := a.Client
+       if client == nil {
+               arkmqClient, err := 
internalclientset.NewForConfig(ctx.Client.GetConfig())
+               if err != nil {
+                       return nil, err
+               }
+               client = arkmqClient
+       }
+
+       namespace := endpoint.Ref.Namespace
+       if namespace == "" {
+               namespace = ctx.Namespace
+       }
+
+       // first check by ActiveMQArtemisAddress name
+       address, err := 
client.BrokerV1beta1().ActiveMQArtemisAddresses(namespace).Get(ctx.Ctx, 
endpoint.Ref.Name, v1.GetOptions{})
+       if err != nil && !k8serrors.IsNotFound(err) {
+               return nil, err
+       }
+       if err == nil {
+               return address, nil
+       }
+
+       // if not found, then look at spec.queueName or spec.addressName
+       addresses, err := 
client.BrokerV1beta1().ActiveMQArtemisAddresses(namespace).List(ctx.Ctx, 
v1.ListOptions{})
+       if err != nil {
+               return nil, fmt.Errorf("couldn't find any 
ActiveMQArtemisAddress with either name, queueName or addressName %s; error 
%w", endpoint.Ref.Name, err)
+       }
+       for i := range addresses.Items {
+               item := &addresses.Items[i]
+               if item.Spec.AddressName == endpoint.Ref.Name || 
item.Spec.QueueName == endpoint.Ref.Name {
+                       return item, nil
+               }
+       }
+
+       return nil, fmt.Errorf("couldn't find any ActiveMQArtemisAddress with 
either name, queueName or addressName %s", endpoint.Ref.Name)
+}
+
+func (a ArkMQBindingProvider) Order() int {
+       return OrderStandard
+}
diff --git a/pkg/util/bindings/arkmq_test.go b/pkg/util/bindings/arkmq_test.go
new file mode 100644
index 000000000..75289ed4c
--- /dev/null
+++ b/pkg/util/bindings/arkmq_test.go
@@ -0,0 +1,327 @@
+/*
+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 bindings
+
+import (
+       "context"
+       "testing"
+
+       camelv1 "github.com/apache/camel-k/v2/pkg/apis/camel/v1"
+       arkmqv1beta1 "github.com/apache/camel-k/v2/pkg/apis/duck/arkmq/v1beta1"
+       
"github.com/apache/camel-k/v2/pkg/client/arkmq/clientset/internalclientset/fake"
+       "github.com/apache/camel-k/v2/pkg/internal"
+
+       "github.com/stretchr/testify/assert"
+       "github.com/stretchr/testify/require"
+       corev1 "k8s.io/api/core/v1"
+       metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+)
+
+func TestArkMQDirect(t *testing.T) {
+       ctx, cancel := context.WithCancel(context.Background())
+       defer cancel()
+
+       client, err := internal.NewFakeClient()
+       require.NoError(t, err)
+
+       bindingContext := BindingContext{
+               Ctx:       ctx,
+               Client:    client,
+               Namespace: "test",
+               Profile:   camelv1.TraitProfileKubernetes,
+       }
+
+       endpoint := camelv1.Endpoint{
+               Ref: &corev1.ObjectReference{
+                       Kind:       "ActiveMQArtemisAddress",
+                       Name:       "myqueue",
+                       APIVersion: "broker.amq.io/v1beta1",
+               },
+               Properties: asEndpointProperties(map[string]string{
+                       "brokerURL": "tcp://custom-broker:61616",
+               }),
+       }
+
+       binding, err := ArkMQBindingProvider{}.Translate(bindingContext, 
EndpointContext{
+               Type: camelv1.EndpointTypeSink,
+       }, endpoint)
+       require.NoError(t, err)
+       assert.NotNil(t, binding)
+       assert.Equal(t, 
"jms:queue:myqueue?brokerURL=tcp%3A%2F%2Fcustom-broker%3A61616", binding.URI)
+}
+
+func TestArkMQLookupAddress(t *testing.T) {
+       ctx, cancel := context.WithCancel(context.Background())
+       defer cancel()
+
+       broker := &arkmqv1beta1.ActiveMQArtemis{
+               ObjectMeta: metav1.ObjectMeta{
+                       Namespace: "test",
+                       Name:      "mybroker",
+               },
+               Status: arkmqv1beta1.ActiveMQArtemisStatus{
+                       PortStatus: []arkmqv1beta1.ActiveMQArtemisPortStatus{
+                               {
+                                       Name: "core",
+                                       Port: 61616,
+                               },
+                       },
+               },
+       }
+
+       address := &arkmqv1beta1.ActiveMQArtemisAddress{
+               ObjectMeta: metav1.ObjectMeta{
+                       Namespace: "test",
+                       Name:      "myaddress",
+               },
+               Spec: arkmqv1beta1.ActiveMQArtemisAddressSpec{
+                       QueueName: "resolved-queue",
+                       ApplyTo:   "mybroker",
+               },
+       }
+
+       client, err := internal.NewFakeClient()
+       require.NoError(t, err)
+
+       bindingContext := BindingContext{
+               Ctx:       ctx,
+               Client:    client,
+               Namespace: "test",
+               Profile:   camelv1.TraitProfileKubernetes,
+       }
+
+       endpoint := camelv1.Endpoint{
+               Ref: &corev1.ObjectReference{
+                       Kind:       "ActiveMQArtemisAddress",
+                       Name:       "myaddress",
+                       APIVersion: "broker.amq.io/v1beta1",
+               },
+       }
+
+       provider := ArkMQBindingProvider{
+               Client: fake.NewSimpleClientset(broker, address),
+       }
+
+       binding, err := provider.Translate(bindingContext, EndpointContext{
+               Type: camelv1.EndpointTypeSink,
+       }, endpoint)
+       require.NoError(t, err)
+       assert.NotNil(t, binding)
+       assert.Equal(t, 
"jms:queue:resolved-queue?brokerURL=tcp%3A%2F%2Fmybroker-hdls-svc.test.svc%3A61616",
 binding.URI)
+}
+
+func TestArkMQMulticastUnsupported(t *testing.T) {
+       ctx, cancel := context.WithCancel(context.Background())
+       defer cancel()
+
+       address := &arkmqv1beta1.ActiveMQArtemisAddress{
+               ObjectMeta: metav1.ObjectMeta{
+                       Namespace: "test",
+                       Name:      "mytopic",
+               },
+               Spec: arkmqv1beta1.ActiveMQArtemisAddressSpec{
+                       RoutingType: "multicast",
+                       ApplyTo:     "mybroker",
+               },
+       }
+
+       client, err := internal.NewFakeClient()
+       require.NoError(t, err)
+
+       bindingContext := BindingContext{
+               Ctx:       ctx,
+               Client:    client,
+               Namespace: "test",
+               Profile:   camelv1.TraitProfileKubernetes,
+       }
+
+       endpoint := camelv1.Endpoint{
+               Ref: &corev1.ObjectReference{
+                       Kind:       "ActiveMQArtemisAddress",
+                       Name:       "mytopic",
+                       APIVersion: "broker.amq.io/v1beta1",
+               },
+       }
+
+       provider := ArkMQBindingProvider{
+               Client: fake.NewSimpleClientset(address),
+       }
+
+       _, err = provider.Translate(bindingContext, EndpointContext{
+               Type: camelv1.EndpointTypeSink,
+       }, endpoint)
+       require.Error(t, err)
+       assert.Contains(t, err.Error(), "multicast addresses (topics) are not 
supported on queue binding mytopic")
+}
+
+func TestArkMQLookupAddressByName(t *testing.T) {
+       ctx, cancel := context.WithCancel(context.Background())
+       defer cancel()
+
+       broker := &arkmqv1beta1.ActiveMQArtemis{
+               ObjectMeta: metav1.ObjectMeta{
+                       Namespace: "test",
+                       Name:      "mybroker",
+               },
+       }
+
+       address := &arkmqv1beta1.ActiveMQArtemisAddress{
+               ObjectMeta: metav1.ObjectMeta{
+                       Namespace: "test",
+                       Name:      "myevents",
+                       Labels: map[string]string{
+                               arkmqv1beta1.ArkMQBrokerLabel: "mybroker",
+                       },
+               },
+               Spec: arkmqv1beta1.ActiveMQArtemisAddressSpec{
+                       AddressName: "events-queue",
+               },
+       }
+
+       client, err := internal.NewFakeClient()
+       require.NoError(t, err)
+
+       bindingContext := BindingContext{
+               Ctx:       ctx,
+               Client:    client,
+               Namespace: "test",
+               Profile:   camelv1.TraitProfileKubernetes,
+       }
+
+       endpoint := camelv1.Endpoint{
+               Ref: &corev1.ObjectReference{
+                       Kind:       "ActiveMQArtemisAddress",
+                       Name:       "myevents",
+                       APIVersion: "broker.amq.io/v1beta1",
+               },
+       }
+
+       provider := ArkMQBindingProvider{
+               Client: fake.NewSimpleClientset(broker, address),
+       }
+
+       binding, err := provider.Translate(bindingContext, EndpointContext{
+               Type: camelv1.EndpointTypeSink,
+       }, endpoint)
+       require.NoError(t, err)
+       assert.NotNil(t, binding)
+       assert.Equal(t, 
"jms:queue:events-queue?brokerURL=tcp%3A%2F%2Fmybroker-hdls-svc.test.svc%3A61616",
 binding.URI)
+}
+
+func TestArkMQUnsupportedKind(t *testing.T) {
+       ctx, cancel := context.WithCancel(context.Background())
+       defer cancel()
+
+       client, err := internal.NewFakeClient()
+       require.NoError(t, err)
+
+       bindingContext := BindingContext{
+               Ctx:       ctx,
+               Client:    client,
+               Namespace: "test",
+               Profile:   camelv1.TraitProfileKubernetes,
+       }
+
+       for _, kind := range []string{"ActiveMQArtemisQueue", 
"ActiveMQArtemis", "UnknownKind"} {
+               endpoint := camelv1.Endpoint{
+                       Ref: &corev1.ObjectReference{
+                               Kind:       kind,
+                               Name:       "myresource",
+                               APIVersion: "broker.amq.io/v1beta1",
+                       },
+               }
+
+               _, err := ArkMQBindingProvider{}.Translate(bindingContext, 
EndpointContext{
+                       Type: camelv1.EndpointTypeSink,
+               }, endpoint)
+               require.Error(t, err)
+               assert.Contains(t, err.Error(), "Can only work with 
ActiveMQArtemisAddress kind")
+       }
+}
+
+func TestArkMQMissingBrokerLabel(t *testing.T) {
+       ctx, cancel := context.WithCancel(context.Background())
+       defer cancel()
+
+       address := &arkmqv1beta1.ActiveMQArtemisAddress{
+               ObjectMeta: metav1.ObjectMeta{
+                       Namespace: "test",
+                       Name:      "unattached-address",
+               },
+       }
+
+       client, err := internal.NewFakeClient()
+       require.NoError(t, err)
+
+       bindingContext := BindingContext{
+               Ctx:       ctx,
+               Client:    client,
+               Namespace: "test",
+               Profile:   camelv1.TraitProfileKubernetes,
+       }
+
+       endpoint := camelv1.Endpoint{
+               Ref: &corev1.ObjectReference{
+                       Kind:       "ActiveMQArtemisAddress",
+                       Name:       "unattached-address",
+                       APIVersion: "broker.amq.io/v1beta1",
+               },
+       }
+
+       provider := ArkMQBindingProvider{
+               Client: fake.NewSimpleClientset(address),
+       }
+
+       _, err = provider.Translate(bindingContext, EndpointContext{
+               Type: camelv1.EndpointTypeSink,
+       }, endpoint)
+       require.Error(t, err)
+       assert.Contains(t, err.Error(), "no \"ActiveMQArtemis\" label or 
applyTo defined on address")
+}
+
+func TestArkMQPassThrough(t *testing.T) {
+       ctx, cancel := context.WithCancel(context.Background())
+       defer cancel()
+
+       client, err := internal.NewFakeClient()
+       require.NoError(t, err)
+
+       bindingContext := BindingContext{
+               Ctx:       ctx,
+               Client:    client,
+               Namespace: "test",
+               Profile:   camelv1.TraitProfileKubernetes,
+       }
+
+       // Nil Ref
+       binding, err := ArkMQBindingProvider{}.Translate(bindingContext, 
EndpointContext{}, camelv1.Endpoint{})
+       require.NoError(t, err)
+       assert.Nil(t, binding)
+
+       // Different API group
+       endpoint := camelv1.Endpoint{
+               Ref: &corev1.ObjectReference{
+                       Kind:       "KafkaTopic",
+                       Name:       "mytopic",
+                       APIVersion: "kafka.strimzi.io/v1beta2",
+               },
+       }
+       binding, err = ArkMQBindingProvider{}.Translate(bindingContext, 
EndpointContext{}, endpoint)
+       require.NoError(t, err)
+       assert.Nil(t, binding)
+}
diff --git a/script/Makefile b/script/Makefile
index a4b154f40..19656cd0e 100644
--- a/script/Makefile
+++ b/script/Makefile
@@ -338,6 +338,14 @@ test-kafka: gotestfmt-install
        go test -timeout 20m -v ./e2e/kafka -tags=integration $(GOTESTFMT) || 
((FAILED++)); \
        exit $${FAILED}
 
+#
+# ArkMQ tests that require the presence of ArkMQ operator configuration
+#
+test-arkmq: gotestfmt-install
+       FAILED=0; \
+       go test -timeout 20m -v ./e2e/arkmq -tags=integration $(GOTESTFMT) || 
((FAILED++)); \
+       exit $${FAILED}
+
 #
 # Telemetry tests that require the configuration of telemetry endpoints
 #
diff --git a/script/gen_client.sh b/script/gen_client.sh
index 14c4f40bd..d3a56ca82 100755
--- a/script/gen_client.sh
+++ b/script/gen_client.sh
@@ -25,6 +25,7 @@ cd $location/../pkg/client
 rm -rf camel
 rm -rf strimzi
 rm -rf keda
+rm -rf arkmq
 
 echo "Generating Go client code..."
 
@@ -58,6 +59,13 @@ $(go env GOPATH)/bin/client-gen \
   --output-dir=./keda/clientset/ \
   --output-pkg=github.com/apache/camel-k/v2/pkg/client/keda/clientset
 
+$(go env GOPATH)/bin/client-gen \
+  --input arkmq/v1beta1 \
+  --go-header-file=../../script/headers/default.txt \
+  --input-base=github.com/apache/camel-k/v2/pkg/apis/duck \
+  --output-dir=./arkmq/clientset/ \
+  --output-pkg=github.com/apache/camel-k/v2/pkg/client/arkmq/clientset
+
 $(go env GOPATH)/bin/lister-gen \
        "github.com/apache/camel-k/v2/pkg/apis/camel/v1" \
        --go-header-file=../../script/headers/default.txt \

Reply via email to