Repository: apache/camel-k
Pull request #4630 (2023-07-31 20:53:46)

Fix missing role in helm chart
Fix https://github.com/apache/camel-k/issues/4629

- Also improve doc about helm and minikube installation

<!-- Description -->




<!--
Enter your extended release note in the below block. If the PR requires
additional action from users switching to the new release, include the string
"action required". If no release note is required, write "NONE". 

You can (optionally) mark this PR with labels "kind/bug" or "kind/feature" to make sure
the text is added to the right section of the release notes. 
-->

**Release Note**
```release-note
NONE
```



Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index b2ba5d722..f1b4e5bce 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,9 +6,10 @@
 
 **Closed issues:**
 
+- Include Camel release subproject in the release process [\#4627](https://github.com/apache/camel-k/issues/4627)
+- Bot updating docs/antora.yaml causes camel-website build to fail [\#4624](https://github.com/apache/camel-k/issues/4624)
 - Upgrade to Go 1.19.x or 1.20.x [\#4613](https://github.com/apache/camel-k/issues/4613)
 - Cannot build with Camel Quarkus 3.0.0 RC1 [\#4609](https://github.com/apache/camel-k/issues/4609)
-- Changelog action is hitting github API rate limit [\#4596](https://github.com/apache/camel-k/issues/4596)
 - \[Openshift\] Repeated install/uninstall and removal of CamelCatalog leads to re-creation of builder image [\#4569](https://github.com/apache/camel-k/issues/4569)
 - Give the possibility to add a maven profile to an Integration project [\#4560](https://github.com/apache/camel-k/issues/4560)
 - Upload local dependencies as maven artifact [\#4244](https://github.com/apache/camel-k/issues/4244)
diff --git a/camel-k-sbom/camel-k-sbom.json b/camel-k-sbom/camel-k-sbom.json
index 9951758b4..d33bfdb99 100644
--- a/camel-k-sbom/camel-k-sbom.json
+++ b/camel-k-sbom/camel-k-sbom.json
@@ -2,10 +2,10 @@
   "$schema": "http://cyclonedx.org/schema/bom-1.4.schema.json",
   "bomFormat": "CycloneDX",
   "specVersion": "1.4",
-  "serialNumber": "urn:uuid:6ea1b540-034b-46b1-97d9-6f8ff5f3f0ae",
+  "serialNumber": "urn:uuid:2a6f2ffe-5ffe-4a3c-be47-346e0b679318",
   "version": 1,
   "metadata": {
-    "timestamp": "2023-07-31T10:06:45Z",
+    "timestamp": "2023-07-31T23:46:44Z",
     "tools": [
       {
         "vendor": "CycloneDX",
@@ -46,11 +46,11 @@
       }
     ],
     "component": {
-      "bom-ref": "pkg:golang/github.com/apache/camel-k/v2@v0.0.0-20230731100335-6a038a4a3114?type=module",
+      "bom-ref": "pkg:golang/github.com/apache/camel-k/v2@v0.0.0-20230731234318-2c6cdcd6e2a6?type=module",
       "type": "application",
       "name": "github.com/apache/camel-k/v2",
-      "version": "v0.0.0-20230731100335-6a038a4a3114",
-      "purl": "pkg:golang/github.com/apache/camel-k/v2@v0.0.0-20230731100335-6a038a4a3114?type=module\u0026goos=linux\u0026goarch=amd64",
+      "version": "v0.0.0-20230731234318-2c6cdcd6e2a6",
+      "purl": "pkg:golang/github.com/apache/camel-k/v2@v0.0.0-20230731234318-2c6cdcd6e2a6?type=module\u0026goos=linux\u0026goarch=amd64",
       "externalReferences": [
         {
           "url": "https://github.com/apache/camel-k",
@@ -423,18 +423,18 @@
       }
     },
     {
-      "bom-ref": "pkg:golang/github.com/apache/camel-k/v2/pkg/apis/camel@v0.0.0-20230731100335-6a038a4a3114?type=module",
+      "bom-ref": "pkg:golang/github.com/apache/camel-k/v2/pkg/apis/camel@v0.0.0-20230731234318-2c6cdcd6e2a6?type=module",
       "type": "library",
       "name": "github.com/apache/camel-k/v2/pkg/apis/camel",
-      "version": "v0.0.0-20230731100335-6a038a4a3114",
+      "version": "v0.0.0-20230731234318-2c6cdcd6e2a6",
       "scope": "required",
       "hashes": [
         {
           "alg": "SHA-256",
-          "content": "a28ff76a89ac9fab17461b9801698764882574e58c962a80a608017fa7884a9c"
+          "content": "0d124e8c3cd74cadd7a83607399dd00be23d88ee102623bc00e713cf1d0812b6"
         }
       ],
-      "purl": "pkg:golang/github.com/apache/camel-k/v2/pkg/apis/camel@v0.0.0-20230731100335-6a038a4a3114?type=module\u0026goos=linux\u0026goarch=amd64",
+      "purl": "pkg:golang/github.com/apache/camel-k/v2/pkg/apis/camel@v0.0.0-20230731234318-2c6cdcd6e2a6?type=module\u0026goos=linux\u0026goarch=amd64",
       "externalReferences": [
         {
           "url": "https://github.com/apache/camel-k/v2/pkg/apis/camel",
@@ -443,18 +443,18 @@
       ]
     },
     {
-      "bom-ref": "pkg:golang/github.com/apache/camel-k/v2/pkg/client/camel@v0.0.0-20230731100335-6a038a4a3114?type=module",
+      "bom-ref": "pkg:golang/github.com/apache/camel-k/v2/pkg/client/camel@v0.0.0-20230731234318-2c6cdcd6e2a6?type=module",
       "type": "library",
       "name": "github.com/apache/camel-k/v2/pkg/client/camel",
-      "version": "v0.0.0-20230731100335-6a038a4a3114",
+      "version": "v0.0.0-20230731234318-2c6cdcd6e2a6",
       "scope": "required",
       "hashes": [
         {
           "alg": "SHA-256",
-          "content": "d673aaf7c6fff37dfb95b5b20cccdc6e050ee1c269127b3553e20520c6e4942c"
+          "content": "97d04a5a092c876faebe97160dd16ea57d6e89b512fdedf91f0267f3ac50e80e"
         }
       ],
-      "purl": "pkg:golang/github.com/apache/camel-k/v2/pkg/client/camel@v0.0.0-20230731100335-6a038a4a3114?type=module\u0026goos=linux\u0026goarch=amd64",
+      "purl": "pkg:golang/github.com/apache/camel-k/v2/pkg/client/camel@v0.0.0-20230731234318-2c6cdcd6e2a6?type=module\u0026goos=linux\u0026goarch=amd64",
       "externalReferences": [
         {
           "url": "https://github.com/apache/camel-k/v2/pkg/client/camel",
@@ -463,18 +463,18 @@
       ]
     },
     {
-      "bom-ref": "pkg:golang/github.com/apache/camel-k/v2/pkg/kamelet/repository@v0.0.0-20230731100335-6a038a4a3114?type=module",
+      "bom-ref": "pkg:golang/github.com/apache/camel-k/v2/pkg/kamelet/repository@v0.0.0-20230731234318-2c6cdcd6e2a6?type=module",
       "type": "library",
       "name": "github.com/apache/camel-k/v2/pkg/kamelet/repository",
-      "version": "v0.0.0-20230731100335-6a038a4a3114",
+      "version": "v0.0.0-20230731234318-2c6cdcd6e2a6",
       "scope": "required",
       "hashes": [
         {
           "alg": "SHA-256",
-          "content": "19d99ed5ab6f9a43077633d835f26c9c24a12ac9f4a0543b592e174d233f374a"
+          "content": "0c6a31d5ca8c925ac2300aecf55c42ac54781b6b6806a0fe45f1bde90fc5cf81"
         }
       ],
-      "purl": "pkg:golang/github.com/apache/camel-k/v2/pkg/kamelet/repository@v0.0.0-20230731100335-6a038a4a3114?type=module\u0026goos=linux\u0026goarch=amd64",
+      "purl": "pkg:golang/github.com/apache/camel-k/v2/pkg/kamelet/repository@v0.0.0-20230731234318-2c6cdcd6e2a6?type=module\u0026goos=linux\u0026goarch=amd64",
       "externalReferences": [
         {
           "url": "https://github.com/apache/camel-k/v2/pkg/kamelet/repository",
@@ -4081,12 +4081,12 @@
   ],
   "dependencies": [
     {
-      "ref": "pkg:golang/github.com/apache/camel-k/v2@v0.0.0-20230731100335-6a038a4a3114?type=module",
+      "ref": "pkg:golang/github.com/apache/camel-k/v2@v0.0.0-20230731234318-2c6cdcd6e2a6?type=module",
       "dependsOn": [
         "pkg:golang/github.com/Masterminds/semver@v1.5.0?type=module",
-        "pkg:golang/github.com/apache/camel-k/v2/pkg/apis/camel@v0.0.0-20230731100335-6a038a4a3114?type=module",
-        "pkg:golang/github.com/apache/camel-k/v2/pkg/client/camel@v0.0.0-20230731100335-6a038a4a3114?type=module",
-        "pkg:golang/github.com/apache/camel-k/v2/pkg/kamelet/repository@v0.0.0-20230731100335-6a038a4a3114?type=module",
+        "pkg:golang/github.com/apache/camel-k/v2/pkg/apis/camel@v0.0.0-20230731234318-2c6cdcd6e2a6?type=module",
+        "pkg:golang/github.com/apache/camel-k/v2/pkg/client/camel@v0.0.0-20230731234318-2c6cdcd6e2a6?type=module",
+        "pkg:golang/github.com/apache/camel-k/v2/pkg/kamelet/repository@v0.0.0-20230731234318-2c6cdcd6e2a6?type=module",
         "pkg:golang/github.com/container-tools/spectrum@v0.6.32?type=module",
         "pkg:golang/github.com/evanphx/json-patch@v5.6.0+incompatible?type=module",
         "pkg:golang/github.com/fsnotify/fsnotify@v1.6.0?type=module",
@@ -4245,7 +4245,7 @@
       "ref": "pkg:golang/github.com/antlr/antlr4/runtime/Go/antlr@v1.4.10?type=module"
     },
     {
-      "ref": "pkg:golang/github.com/apache/camel-k/v2/pkg/apis/camel@v0.0.0-20230731100335-6a038a4a3114?type=module",
+      "ref": "pkg:golang/github.com/apache/camel-k/v2/pkg/apis/camel@v0.0.0-20230731234318-2c6cdcd6e2a6?type=module",
       "dependsOn": [
         "pkg:golang/github.com/imdario/mergo@v0.3.13?type=module",
         "pkg:golang/github.com/stretchr/testify@v1.8.4?type=module",
@@ -4271,9 +4271,9 @@
       ]
     },
     {
-      "ref": "pkg:golang/github.com/apache/camel-k/v2/pkg/client/camel@v0.0.0-20230731100335-6a038a4a3114?type=module",
+      "ref": "pkg:golang/github.com/apache/camel-k/v2/pkg/client/camel@v0.0.0-20230731234318-2c6cdcd6e2a6?type=module",
       "dependsOn": [
-        "pkg:golang/github.com/apache/camel-k/v2/pkg/apis/camel@v0.0.0-20230731100335-6a038a4a3114?type=module",
+        "pkg:golang/github.com/apache/camel-k/v2/pkg/apis/camel@v0.0.0-20230731234318-2c6cdcd6e2a6?type=module",
         "pkg:golang/k8s.io/api@v0.25.6?type=module",
         "pkg:golang/k8s.io/apimachinery@v0.25.6?type=module",
         "pkg:golang/k8s.io/client-go@v0.25.6?type=module",
@@ -4317,10 +4317,10 @@
       ]
     },
     {
-      "ref": "pkg:golang/github.com/apache/camel-k/v2/pkg/kamelet/repository@v0.0.0-20230731100335-6a038a4a3114?type=module",
+      "ref": "pkg:golang/github.com/apache/camel-k/v2/pkg/kamelet/repository@v0.0.0-20230731234318-2c6cdcd6e2a6?type=module",
       "dependsOn": [
-        "pkg:golang/github.com/apache/camel-k/v2/pkg/apis/camel@v0.0.0-20230731100335-6a038a4a3114?type=module",
-        "pkg:golang/github.com/apache/camel-k/v2/pkg/client/camel@v0.0.0-20230731100335-6a038a4a3114?type=module",
+        "pkg:golang/github.com/apache/camel-k/v2/pkg/apis/camel@v0.0.0-20230731234318-2c6cdcd6e2a6?type=module",
+        "pkg:golang/github.com/apache/camel-k/v2/pkg/client/camel@v0.0.0-20230731234318-2c6cdcd6e2a6?type=module",
         "pkg:golang/github.com/stretchr/testify@v1.8.4?type=module",
         "pkg:golang/golang.org/x/oauth2@v0.10.0?type=module",
         "pkg:golang/k8s.io/apimachinery@v0.25.6?type=module",
diff --git a/cicd/tekton/kamel-run/0.1/kamel-run.yaml b/cicd/tekton/kamel-run/0.1/kamel-run.yaml
index 1c6c148da..2853565a2 100644
--- a/cicd/tekton/kamel-run/0.1/kamel-run.yaml
+++ b/cicd/tekton/kamel-run/0.1/kamel-run.yaml
@@ -1,3 +1,20 @@
+# ---------------------------------------------------------------------------
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+# ---------------------------------------------------------------------------
+
 apiVersion: tekton.dev/v1beta1
 kind: Task
 metadata:
diff --git a/cicd/tekton/kamel-run/0.1/samples/run-external-build.yaml b/cicd/tekton/kamel-run/0.1/samples/run-external-build.yaml
index 14543a623..f62b5ba36 100644
--- a/cicd/tekton/kamel-run/0.1/samples/run-external-build.yaml
+++ b/cicd/tekton/kamel-run/0.1/samples/run-external-build.yaml
@@ -1,3 +1,20 @@
+# ---------------------------------------------------------------------------
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+# ---------------------------------------------------------------------------
+
 ---
 apiVersion: tekton.dev/v1beta1
 kind: Pipeline
diff --git a/cicd/tekton/kamel-run/0.1/samples/run-operator-build.yaml b/cicd/tekton/kamel-run/0.1/samples/run-operator-build.yaml
index 57dd95817..8f7b2a0f7 100644
--- a/cicd/tekton/kamel-run/0.1/samples/run-operator-build.yaml
+++ b/cicd/tekton/kamel-run/0.1/samples/run-operator-build.yaml
@@ -1,3 +1,20 @@
+# ---------------------------------------------------------------------------
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+# ---------------------------------------------------------------------------
+
 ---
 apiVersion: tekton.dev/v1beta1
 kind: Pipeline
diff --git a/cicd/tekton/kamel-run/0.1/support/camel-k-tekton.yaml b/cicd/tekton/kamel-run/0.1/support/camel-k-tekton.yaml
index 5aa8c6525..188a81213 100644
--- a/cicd/tekton/kamel-run/0.1/support/camel-k-tekton.yaml
+++ b/cicd/tekton/kamel-run/0.1/support/camel-k-tekton.yaml
@@ -1,3 +1,20 @@
+# ---------------------------------------------------------------------------
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+# ---------------------------------------------------------------------------
+
 ---
 apiVersion: v1
 kind: ServiceAccount
diff --git a/docs/modules/ROOT/pages/contributing/developers.adoc b/docs/modules/ROOT/pages/contributing/developers.adoc
index fcd57bdaf..5629b98ce 100644
--- a/docs/modules/ROOT/pages/contributing/developers.adoc
+++ b/docs/modules/ROOT/pages/contributing/developers.adoc
@@ -83,8 +83,8 @@ This executes a full build of the Go code. If you need to build the components s
 
 Currently the build is not entirely supported on Windows. If you're building on a Windows system, here's a temporary workaround:
 
-    1. Copy the `script/Makefile` to the root of the project. 
-    2. Run `make -f script/Makefile`. 
+    1. Copy the `script/Makefile` to the root of the project.
+    2. Run `make -f script/Makefile`.
     3. If the above command fails, run `make build-kamel`.
     4. Rename the `kamel` binary in the root to `kamel.exe`.
 
@@ -135,9 +135,12 @@ The commands assume you have an already running CRC instance and logged in corre
 
 === For Minikube
 
-* Run `make install-minikube`: to build the project and install it in the current namespace on Minikube
+First remove any camel k operator you may have installed, otherwise it will conflict with the new one we will build and install.
 
-This command assumes you have an already running Minikube instance with registry enabled (can be enabled with `minikube addons enable registry`) and no previous Camel K instance installed.
+* Enable the `registry` minikube addon: `minikube addons enable registry`
+* Set the access to the internal minikube registry: `eval $(minikube docker-env)`
+* Run `make images`: to build the project and install the image in the internal minikube registry
+* Install camel-k-operator: `./kamel install`
 
 === For remote Kubernetes/OpenShift clusters
 
@@ -150,6 +153,20 @@ kamel install --operator-image=docker.io/myrepo/camel-k:1.5.0-SNAPSHOT --operato
 
 Note `--olm=false` is necessary as otherwise the OLM bundle version is preferred.
 
+=== Local Helm installation
+
+If you want to test Helm installation
+
+* Build the Helm chart `make release-helm`
+* Build the project and the image: `make images`
+* Set the internal registry `export REGISTRY_ADDRESS=$(kubectl -n kube-system get service registry -o jsonpath='{.spec.clusterIP}')`
+* Install with Helm (look at the latest version produced by `make release-helm`)
+```
+ helm install camel-k-dev docs/charts/camel-k-2.1.0-SNAPSHOT.tgz --set platform.build.registry.address=${REGISTRY_ADDRESS} --set platform.build.registry.insecure=true --set operator.image=apache/camel-k:2.1.0-SNAPSHOT
+```
+
+To uninstall: `helm uninstall camel-k-dev`
+
 === Use
 
 Now you can play with Camel K:
diff --git a/helm/camel-k/templates/operator-role.yaml b/helm/camel-k/templates/operator-role.yaml
index 0c52d01d0..e84757173 100644
--- a/helm/camel-k/templates/operator-role.yaml
+++ b/helm/camel-k/templates/operator-role.yaml
@@ -32,7 +32,9 @@ rules:
   - integrationkits
   - integrationplatforms
   - integrations
-  - bindings
+  - pipes
+  - kameletbindings
+  # Deprecated: kameletbindings CR
   - kamelets
   verbs:
   - create
@@ -56,8 +58,11 @@ rules:
   - integrationplatforms/status
   - integrations/scale
   - integrations/status
-  - bindings/status
-  - bindings/scale
+  - pipes/status
+  - pipes/scale
+  # Deprecated: kameletbindings CR
+  - kameletbindings/status
+  - kameletbindings/scale
   - kamelets/status
   verbs:
   - get
@@ -92,6 +97,7 @@ rules:
   - ""
   resources:
   - pods/proxy
+  - pods/log
   verbs:
   - get
 - apiGroups:
@@ -111,6 +117,7 @@ rules:
   resources:
   - roles
   - rolebindings
+  - clusterrolebindings
   verbs:
   - create
   - delete
@@ -167,6 +174,13 @@ rules:
   - patch
   - update
   - watch
+- apiGroups:
+  - storage.k8s.io
+  resources:
+  - storageclasses
+  verbs:
+  - get
+  - list
 - apiGroups:
   - ""
   resources:
diff --git a/pkg/cmd/promote.go b/pkg/cmd/promote.go
index b87170f73..b15cc0838 100644
--- a/pkg/cmd/promote.go
+++ b/pkg/cmd/promote.go
@@ -49,15 +49,17 @@ func newCmdPromote(rootCmdOptions *RootCmdOptions) (*cobra.Command, *promoteCmdO
 		RootCmdOptions: rootCmdOptions,
 	}
 	cmd := cobra.Command{
-		Use:     "promote my-it --to [namespace]",
+		Use:     "promote my-it [--to <namespace>] [-x <promoted-operator-id>]",
 		Short:   "Promote an Integration/Pipe from an environment to another",
 		Long:    "Promote an Integration/Pipe from an environment to another, for example from a Development environment to a Production environment",
 		PreRunE: decode(&options),
 		RunE:    options.run,
 	}
 
-	cmd.Flags().String("to", "", "The namespace where to promote the Integration")
+	cmd.Flags().String("to", "", "The namespace where to promote the Integration/Pipe")
+	cmd.Flags().StringP("to-operator", "x", "", "The operator id which will reconcile the promoted Integration/Pipe")
 	cmd.Flags().StringP("output", "o", "", "Output format. One of: json|yaml")
+	cmd.Flags().BoolP("image", "i", false, "Output the container image only")
 
 	return &cmd, &options
 }
@@ -65,15 +67,20 @@ func newCmdPromote(rootCmdOptions *RootCmdOptions) (*cobra.Command, *promoteCmdO
 type promoteCmdOptions struct {
 	*RootCmdOptions
 	To           string `mapstructure:"to" yaml:",omitempty"`
+	ToOperator   string `mapstructure:"to-operator" yaml:",omitempty"`
 	OutputFormat string `mapstructure:"output" yaml:",omitempty"`
+	Image        bool   `mapstructure:"image" yaml:",omitempty"`
 }
 
 func (o *promoteCmdOptions) validate(_ *cobra.Command, args []string) error {
 	if len(args) != 1 {
-		return errors.New("promote expects an Integration/Pipe name argument")
+		return errors.New("promote requires an Integration/Pipe name argument")
 	}
 	if o.To == "" {
-		return errors.New("promote expects a destination namespace as --to argument")
+		return errors.New("promote requires a destination namespace as --to argument")
+	}
+	if o.To == o.Namespace {
+		return errors.New("source and destination namespaces must be different in order to avoid promoted Integration/Pipe clashes with the source Integration/Pipe")
 	}
 	return nil
 }
@@ -88,19 +95,23 @@ func (o *promoteCmdOptions) run(cmd *cobra.Command, args []string) error {
 	if err != nil {
 		return fmt.Errorf("could not retrieve cluster client: %w", err)
 	}
-	opSource, err := operatorInfo(o.Context, c, o.Namespace)
-	if err != nil {
-		return fmt.Errorf("could not retrieve info for Camel K operator source: %w", err)
-	}
-	opDest, err := operatorInfo(o.Context, c, o.To)
-	if err != nil {
-		return fmt.Errorf("could not retrieve info for Camel K operator destination: %w", err)
-	}
+	if !o.isDryRun() {
+		// Skip these checks if in dry mode
+		opSource, err := operatorInfo(o.Context, c, o.Namespace)
+		if err != nil {
+			return fmt.Errorf("could not retrieve info for Camel K operator source: %w", err)
+		}
+		opDest, err := operatorInfo(o.Context, c, o.To)
+		if err != nil {
+			return fmt.Errorf("could not retrieve info for Camel K operator destination: %w", err)
+		}
 
-	err = checkOpsCompatibility(cmd, opSource, opDest)
-	if err != nil {
-		return fmt.Errorf("could not verify operators compatibility: %w", err)
+		err = checkOpsCompatibility(cmd, opSource, opDest)
+		if err != nil {
+			return fmt.Errorf("could not verify operators compatibility: %w", err)
+		}
 	}
+
 	promotePipe := false
 	var sourceIntegration *v1.Integration
 	// We first look if a Pipe with the name exists
@@ -118,41 +129,51 @@ func (o *promoteCmdOptions) run(cmd *cobra.Command, args []string) error {
 	if sourceIntegration.Status.Phase != v1.IntegrationPhaseRunning {
 		return fmt.Errorf("could not promote an Integration in %s status", sourceIntegration.Status.Phase)
 	}
-	err = o.validateDestResources(c, sourceIntegration)
-	if err != nil {
-		return fmt.Errorf("could not validate destination resources: %w", err)
+
+	// Image only mode
+	if o.Image {
+		showImageOnly(cmd, sourceIntegration)
+		return nil
+	}
+
+	if !o.isDryRun() {
+		// Skip these checks if in dry mode
+		err = o.validateDestResources(c, sourceIntegration)
+		if err != nil {
+			return fmt.Errorf("could not validate destination resources: %w", err)
+		}
 	}
 
 	// Pipe promotion
 	if promotePipe {
 		destPipe := o.editPipe(sourcePipe, sourceIntegration)
+		if o.OutputFormat != "" {
+			return showPipeOutput(cmd, destPipe, o.OutputFormat, c.GetScheme())
+		}
 		// Ensure the destination namespace has access to the source namespace images
 		err = addSystemPullerRoleBinding(o.Context, c, sourceIntegration.Namespace, destPipe.Namespace)
 		if err != nil {
 			return err
 		}
 		replaced, err := o.replaceResource(destPipe)
-		if o.OutputFormat != "" {
-			return showPipeOutput(cmd, destPipe, o.OutputFormat, c.GetScheme())
-		}
 		if !replaced {
-			fmt.Fprintln(cmd.OutOrStdout(), `Promoted Integration "`+name+`" created`)
+			fmt.Fprintln(cmd.OutOrStdout(), `Promoted Pipe "`+name+`" created`)
 		} else {
-			fmt.Fprintln(cmd.OutOrStdout(), `Promoted Integration "`+name+`" updated`)
+			fmt.Fprintln(cmd.OutOrStdout(), `Promoted Pipe "`+name+`" updated`)
 		}
 		return err
 	}
 
 	// Plain Integration promotion
 	destIntegration := o.editIntegration(sourceIntegration)
+	if o.OutputFormat != "" {
+		return showIntegrationOutput(cmd, destIntegration, o.OutputFormat)
+	}
 	// Ensure the destination namespace has access to the source namespace images
 	err = addSystemPullerRoleBinding(o.Context, c, sourceIntegration.Namespace, destIntegration.Namespace)
 	if err != nil {
 		return err
 	}
-	if o.OutputFormat != "" {
-		return showIntegrationOutput(cmd, destIntegration, o.OutputFormat)
-	}
 	replaced, err := o.replaceResource(destIntegration)
 	if !replaced {
 		fmt.Fprintln(cmd.OutOrStdout(), `Promoted Integration "`+name+`" created`)
@@ -441,7 +462,7 @@ func (o *promoteCmdOptions) editIntegration(it *v1.Integration) *v1.Integration
 	dst := v1.NewIntegration(o.To, it.Name)
 	contImage := it.Status.Image
 	dst.Spec = *it.Spec.DeepCopy()
-	dst.Annotations = cloneAnnotations(it.Annotations)
+	dst.Annotations = cloneAnnotations(it.Annotations, o.ToOperator)
 	dst.Labels = cloneLabels(it.Labels)
 	if dst.Spec.Traits.Container == nil {
 		dst.Spec.Traits.Container = &traitv1.ContainerTrait{}
@@ -450,14 +471,23 @@ func (o *promoteCmdOptions) editIntegration(it *v1.Integration) *v1.Integration
 	return &dst
 }
 
-// Return all annotations but the ones specific to source (ie, the operator).
-func cloneAnnotations(ann map[string]string) map[string]string {
+// Return all annotations overriding the operator Id if provided.
+func cloneAnnotations(ann map[string]string, operatorID string) map[string]string {
+	operatorIDAnnotationSet := false
 	newMap := make(map[string]string)
 	for k, v := range ann {
-		if k != v1.OperatorIDAnnotation {
+		if k == v1.OperatorIDAnnotation {
+			if operatorID != "" {
+				newMap[v1.OperatorIDAnnotation] = operatorID
+				operatorIDAnnotationSet = true
+			}
+		} else {
 			newMap[k] = v
 		}
 	}
+	if !operatorIDAnnotationSet && operatorID != "" {
+		newMap[v1.OperatorIDAnnotation] = operatorID
+	}
 	return newMap
 }
 
@@ -473,7 +503,7 @@ func cloneLabels(lbs map[string]string) map[string]string {
 func (o *promoteCmdOptions) editPipe(kb *v1.Pipe, it *v1.Integration) *v1.Pipe {
 	dst := v1.NewPipe(o.To, kb.Name)
 	dst.Spec = *kb.Spec.DeepCopy()
-	dst.Annotations = cloneAnnotations(kb.Annotations)
+	dst.Annotations = cloneAnnotations(kb.Annotations, o.ToOperator)
 	dst.Labels = cloneLabels(kb.Labels)
 	contImage := it.Status.Image
 	if dst.Spec.Integration == nil {
@@ -503,6 +533,10 @@ func (o *promoteCmdOptions) replaceResource(res k8sclient.Object) (bool, error)
 	return kubernetes.ReplaceResource(o.Context, o._client, res)
 }
 
+func (o *promoteCmdOptions) isDryRun() bool {
+	return o.OutputFormat != "" || o.Image
+}
+
 // RoleBinding is required to allow access to images in one namespace
 // by another namespace. Without this on rbac-enabled clusters, the
 // image cannot be pulled.
@@ -533,3 +567,7 @@ func addSystemPullerRoleBinding(ctx context.Context, c client.Client, sourceNS s
 
 	return err
 }
+
+func showImageOnly(cmd *cobra.Command, integration *v1.Integration) {
+	fmt.Fprintln(cmd.OutOrStdout(), integration.Status.Image)
+}
diff --git a/resources/traits.yaml b/resources/traits.yaml
index ed03494e6..dae6f5aa0 100755
--- a/resources/traits.yaml
+++ b/resources/traits.yaml
@@ -1,3 +1,20 @@
+# ---------------------------------------------------------------------------
+# 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.
+# ---------------------------------------------------------------------------
+
 traits:
 - name: 3scale
   platform: false
diff --git a/script/release-branch.sh b/script/release-branch.sh
index 884ca0ce4..ab40c44c3 100755
--- a/script/release-branch.sh
+++ b/script/release-branch.sh
@@ -1,5 +1,20 @@
 #!/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.
+
 set -e
 
 display_usage() {


Test patch:
diff --git a/cicd/tekton/kamel-run/0.1/tests/resources.yaml b/cicd/tekton/kamel-run/0.1/tests/resources.yaml
index 8c66baefb..b100913ca 100644
--- a/cicd/tekton/kamel-run/0.1/tests/resources.yaml
+++ b/cicd/tekton/kamel-run/0.1/tests/resources.yaml
@@ -1,3 +1,20 @@
+# ---------------------------------------------------------------------------
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+# ---------------------------------------------------------------------------
+
 ---
 apiVersion: v1
 kind: ServiceAccount
diff --git a/cicd/tekton/kamel-run/0.1/tests/run.yaml b/cicd/tekton/kamel-run/0.1/tests/run.yaml
index b255be62b..2ff6cc9a6 100644
--- a/cicd/tekton/kamel-run/0.1/tests/run.yaml
+++ b/cicd/tekton/kamel-run/0.1/tests/run.yaml
@@ -1,3 +1,20 @@
+# ---------------------------------------------------------------------------
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+# ---------------------------------------------------------------------------
+
 ---
 apiVersion: tekton.dev/v1beta1
 kind: Pipeline
diff --git a/e2e/common/misc/files/registry/src/main/java/camelk/DeterministicDecryption.java b/e2e/common/misc/files/registry/src/main/java/camelk/DeterministicDecryption.java
index deac67e5b..9822a4840 100644
--- a/e2e/common/misc/files/registry/src/main/java/camelk/DeterministicDecryption.java
+++ b/e2e/common/misc/files/registry/src/main/java/camelk/DeterministicDecryption.java
@@ -1,19 +1,20 @@
 /*
-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.
-*/
+ * 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 camelk;
 
 import java.io.IOException;
diff --git a/e2e/yaks/common/kamelet-binding-broker/sample-broker.yaml b/e2e/yaks/common/kamelet-binding-broker/sample-broker.yaml
index 1e04f0d47..da54b7928 100644
--- a/e2e/yaks/common/kamelet-binding-broker/sample-broker.yaml
+++ b/e2e/yaks/common/kamelet-binding-broker/sample-broker.yaml
@@ -1,3 +1,20 @@
+# ---------------------------------------------------------------------------
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+# ---------------------------------------------------------------------------
+
 apiVersion: eventing.knative.dev/v1
 kind: Broker
 metadata:
diff --git a/pkg/cmd/promote_test.go b/pkg/cmd/promote_test.go
index de35de413..bc39d63de 100644
--- a/pkg/cmd/promote_test.go
+++ b/pkg/cmd/promote_test.go
@@ -65,9 +65,8 @@ func TestIntegrationNotCompatible(t *testing.T) {
 	srcCatalog := createTestCamelCatalog(srcPlatform)
 	dstCatalog := createTestCamelCatalog(dstPlatform)
 
-	promoteCmdOptions, promoteCmd, _ := initializePromoteCmdOptions(t, &srcPlatform, &dstPlatform, &defaultIntegration, &srcCatalog, &dstCatalog)
-	_, err := test.ExecuteCommand(promoteCmd, cmdPromote, "my-it-test", "--to", "prod-namespace", "-o", "yaml", "-n", "default")
-	assert.Equal(t, "yaml", promoteCmdOptions.OutputFormat)
+	_, promoteCmd, _ := initializePromoteCmdOptions(t, &srcPlatform, &dstPlatform, &defaultIntegration, &srcCatalog, &dstCatalog)
+	_, err := test.ExecuteCommand(promoteCmd, cmdPromote, "my-it-test", "--to", "prod-namespace", "-n", "default")
 	assert.NotNil(t, err)
 	assert.Equal(t,
 		fmt.Sprintf("could not verify operators compatibility: source (%s) and destination (0.0.1) Camel K operator versions are not compatible", defaults.Version),
@@ -137,7 +136,6 @@ metadata:
   creationTimestamp: null
   name: my-kb-test
   namespace: prod-namespace
-  resourceVersion: "1"
 spec:
   integration:
     traits:
@@ -238,7 +236,6 @@ metadata:
     my-label: my-value
   name: my-kb-test
   namespace: prod-namespace
-  resourceVersion: "1"
 spec:
   integration:
     traits:
@@ -249,3 +246,98 @@ spec:
 status: {}
 `, output)
 }
+
+func TestItImageOnly(t *testing.T) {
+	srcPlatform := v1.NewIntegrationPlatform("default", platform.DefaultPlatformName)
+	srcPlatform.Status.Version = defaults.Version
+	srcPlatform.Status.Build.RuntimeVersion = defaults.DefaultRuntimeVersion
+	srcPlatform.Status.Phase = v1.IntegrationPlatformPhaseReady
+	dstPlatform := v1.NewIntegrationPlatform("prod-namespace", platform.DefaultPlatformName)
+	dstPlatform.Status.Version = defaults.Version
+	dstPlatform.Status.Build.RuntimeVersion = defaults.DefaultRuntimeVersion
+	dstPlatform.Status.Phase = v1.IntegrationPlatformPhaseReady
+	defaultIntegration := nominalIntegration("my-it-test")
+	srcCatalog := createTestCamelCatalog(srcPlatform)
+	dstCatalog := createTestCamelCatalog(dstPlatform)
+
+	_, promoteCmd, _ := initializePromoteCmdOptions(t, &srcPlatform, &dstPlatform, &defaultIntegration, &srcCatalog, &dstCatalog)
+	output, err := test.ExecuteCommand(promoteCmd, cmdPromote, "my-it-test", "--to", "prod-namespace", "-i", "-n", "default")
+	assert.Nil(t, err)
+	assert.Equal(t, "my-special-image\n", output)
+}
+
+func TestPipeImageOnly(t *testing.T) {
+	srcPlatform := v1.NewIntegrationPlatform("default", platform.DefaultPlatformName)
+	srcPlatform.Status.Version = defaults.Version
+	srcPlatform.Status.Build.RuntimeVersion = defaults.DefaultRuntimeVersion
+	srcPlatform.Status.Phase = v1.IntegrationPlatformPhaseReady
+	dstPlatform := v1.NewIntegrationPlatform("prod-namespace", platform.DefaultPlatformName)
+	dstPlatform.Status.Version = defaults.Version
+	dstPlatform.Status.Build.RuntimeVersion = defaults.DefaultRuntimeVersion
+	dstPlatform.Status.Phase = v1.IntegrationPlatformPhaseReady
+	defaultKB := nominalPipe("my-kb-test")
+	defaultIntegration := nominalIntegration("my-kb-test")
+	srcCatalog := createTestCamelCatalog(srcPlatform)
+	dstCatalog := createTestCamelCatalog(dstPlatform)
+
+	_, promoteCmd, _ := initializePromoteCmdOptions(t, &srcPlatform, &dstPlatform, &defaultKB, &defaultIntegration, &srcCatalog, &dstCatalog)
+	output, err := test.ExecuteCommand(promoteCmd, cmdPromote, "my-kb-test", "--to", "prod-namespace", "-i", "-n", "default")
+	assert.Nil(t, err)
+	assert.Equal(t, "my-special-image\n", output)
+}
+
+func TestIntegrationToOperatorId(t *testing.T) {
+	srcPlatform := v1.NewIntegrationPlatform("default", platform.DefaultPlatformName)
+	srcPlatform.Status.Version = defaults.Version
+	srcPlatform.Status.Build.RuntimeVersion = defaults.DefaultRuntimeVersion
+	srcPlatform.Status.Phase = v1.IntegrationPlatformPhaseReady
+	dstPlatform := v1.NewIntegrationPlatform("prod-namespace", platform.DefaultPlatformName)
+	dstPlatform.Status.Version = defaults.Version
+	dstPlatform.Status.Build.RuntimeVersion = defaults.DefaultRuntimeVersion
+	dstPlatform.Status.Phase = v1.IntegrationPlatformPhaseReady
+	defaultIntegration := nominalIntegration("my-it-test")
+	srcCatalog := createTestCamelCatalog(srcPlatform)
+	dstCatalog := createTestCamelCatalog(dstPlatform)
+
+	// Verify default (missing) operator Id
+	promoteCmdOptions, promoteCmd, _ := initializePromoteCmdOptions(t, &srcPlatform, &dstPlatform, &defaultIntegration, &srcCatalog, &dstCatalog)
+	output, err := test.ExecuteCommand(promoteCmd, cmdPromote, "my-it-test", "-x", "my-prod-operator", "-o", "yaml", "--to", "prod")
+	assert.Equal(t, "yaml", promoteCmdOptions.OutputFormat)
+	assert.Nil(t, err)
+	assert.Equal(t, `apiVersion: camel.apache.org/v1
+kind: Integration
+metadata:
+  annotations:
+    camel.apache.org/operator.id: my-prod-operator
+  creationTimestamp: null
+  name: my-it-test
+  namespace: prod
+spec:
+  traits:
+    container:
+      image: my-special-image
+status: {}
+`, output)
+	// Verify also when the operator Id is set in the integration
+	defaultIntegration.Annotations = map[string]string{
+		"camel.apache.org/operator.id": "camel-k",
+	}
+	promoteCmdOptions, promoteCmd, _ = initializePromoteCmdOptions(t, &srcPlatform, &dstPlatform, &defaultIntegration, &srcCatalog, &dstCatalog)
+	output, err = test.ExecuteCommand(promoteCmd, cmdPromote, "my-it-test", "-x", "my-prod-operator", "-o", "yaml", "--to", "prod")
+	assert.Equal(t, "yaml", promoteCmdOptions.OutputFormat)
+	assert.Nil(t, err)
+	assert.Equal(t, `apiVersion: camel.apache.org/v1
+kind: Integration
+metadata:
+  annotations:
+    camel.apache.org/operator.id: my-prod-operator
+  creationTimestamp: null
+  name: my-it-test
+  namespace: prod
+spec:
+  traits:
+    container:
+      image: my-special-image
+status: {}
+`, output)
+}