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


The following commit(s) were added to refs/heads/main by this push:
     new 1c980893d fix(cmd): read operator image from Pod
1c980893d is described below

commit 1c980893d9e38b6cb558fb63f7d2d671d1ed8e49
Author: Pasquale Congiusti <[email protected]>
AuthorDate: Wed Aug 12 08:45:51 2026 +0200

    fix(cmd): read operator image from Pod
    
    Instead of having a dedicated env var which may be difficult to fill in all 
installation methods.
    
    Closes #6730
---
 pkg/cmd/operator/operator.go                       | 40 +++++++++-
 pkg/cmd/operator/operator_test.go                  | 87 ++++++++++++++++++++--
 pkg/resources/config/manager/kustomization.yaml    | 10 ---
 .../config/manager/operator-deployment.yaml        |  3 -
 4 files changed, 117 insertions(+), 23 deletions(-)

diff --git a/pkg/cmd/operator/operator.go b/pkg/cmd/operator/operator.go
index 58d11ebbc..1ed9c5760 100644
--- a/pkg/cmd/operator/operator.go
+++ b/pkg/cmd/operator/operator.go
@@ -19,6 +19,7 @@ package operator
 
 import (
        "context"
+       "errors"
        "flag"
        "fmt"
        "os"
@@ -39,6 +40,7 @@ import (
        corev1 "k8s.io/api/core/v1"
        "k8s.io/apimachinery/pkg/labels"
        "k8s.io/apimachinery/pkg/selection"
+       "k8s.io/apimachinery/pkg/types"
        "k8s.io/client-go/tools/leaderelection/resourcelock"
        "sigs.k8s.io/controller-runtime/pkg/cache"
        ctrl "sigs.k8s.io/controller-runtime/pkg/client"
@@ -156,7 +158,10 @@ func Run(healthPort, monitoringPort int32, leaderElection 
bool, leaderElectionID
        }
 
        // Set the operator container image if it runs in-container
-       platform.OperatorImage = getOperatorImage()
+       platform.OperatorImage, err = getOperatorImage(ctx, bootstrapClient)
+       if err != nil {
+               log.Info("WARN: Camel K operator is running outside a 
container. Some features (eg, running build in pod mode) may be disabled!")
+       }
 
        if !leaderElection {
                log.Info("Leader election is disabled!")
@@ -270,8 +275,37 @@ func getWatchNamespace() (string, error) {
 }
 
 // getOperatorImage returns the image currently used by the running operator 
if present (when running out of cluster, it may be absent).
-func getOperatorImage() string {
-       return os.Getenv("CONTAINER_IMAGE")
+func getOperatorImage(ctx context.Context, kubeClient client.Client) (string, 
error) {
+       podName := os.Getenv("POD_NAME")
+       podNamespace := os.Getenv("NAMESPACE")
+
+       if podName == "" {
+               return "", errors.New("POD_NAME environment variable is not 
set")
+       }
+       if podNamespace == "" {
+               return "", errors.New("NAMESPACE environment variable is not 
set")
+       }
+
+       pod := &corev1.Pod{}
+       if err := kubeClient.Get(ctx, types.NamespacedName{
+               Name:      podName,
+               Namespace: podNamespace,
+       }, pod); err != nil {
+               return "", fmt.Errorf("failed to get operator pod %s/%s: %w",
+                       podNamespace, podName, err)
+       }
+
+       for _, container := range pod.Spec.Containers {
+               if container.Name == "camel-k-operator" {
+                       return container.Image, nil
+               }
+       }
+
+       return "", fmt.Errorf(
+               "camel-k-operator container not found in pod %s/%s",
+               podNamespace,
+               podName,
+       )
 }
 
 func exitOnError(err error, msg string) {
diff --git a/pkg/cmd/operator/operator_test.go 
b/pkg/cmd/operator/operator_test.go
index 00eac0784..364271ce6 100644
--- a/pkg/cmd/operator/operator_test.go
+++ b/pkg/cmd/operator/operator_test.go
@@ -18,11 +18,16 @@ limitations under the License.
 package operator
 
 import (
+       "context"
        "testing"
 
+       "github.com/apache/camel-k/v2/pkg/internal"
        "github.com/apache/camel-k/v2/pkg/platform"
        "github.com/stretchr/testify/assert"
        "github.com/stretchr/testify/require"
+       corev1 "k8s.io/api/core/v1"
+       metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+       "k8s.io/apimachinery/pkg/runtime"
        "sigs.k8s.io/controller-runtime/pkg/cache"
 )
 
@@ -132,19 +137,87 @@ func TestGetWatchNamespace(t *testing.T) {
 }
 
 func TestGetOperatorImage(t *testing.T) {
-       t.Run("env variable set", func(t *testing.T) {
-               t.Setenv("CONTAINER_IMAGE", "quay.io/example/operator:latest")
+       scheme := runtime.NewScheme()
+       require.NoError(t, corev1.AddToScheme(scheme))
+
+       t.Run("returns operator image", func(t *testing.T) {
+               t.Setenv("POD_NAME", "operator-123")
+               t.Setenv("NAMESPACE", "default")
+
+               pod := &corev1.Pod{
+                       ObjectMeta: metav1.ObjectMeta{
+                               Name:      "operator-123",
+                               Namespace: "default",
+                       },
+                       Spec: corev1.PodSpec{
+                               Containers: []corev1.Container{
+                                       {
+                                               Name:  "camel-k-operator",
+                                               Image: "my-operator:v1.2.3",
+                                       },
+                               },
+                       },
+               }
+
+               kubeClient, err := internal.NewFakeClient(pod)
+               require.NoError(t, err)
 
-               image := getOperatorImage()
+               image, err := getOperatorImage(context.Background(), kubeClient)
 
-               assert.Equal(t, "quay.io/example/operator:latest", image)
+               require.NoError(t, err)
+               assert.Equal(t, "my-operator:v1.2.3", image)
        })
 
-       t.Run("env variable not set", func(t *testing.T) {
-               t.Setenv("CONTAINER_IMAGE", "")
+       t.Run("returns error when pod does not exist", func(t *testing.T) {
+               t.Setenv("POD_NAME", "operator-123")
+               t.Setenv("NAMESPACE", "default")
+
+               kubeClient, err := internal.NewFakeClient()
+               require.NoError(t, err)
+
+               image, err := getOperatorImage(context.Background(), kubeClient)
+
+               require.Error(t, err)
+               assert.Empty(t, image)
+       })
+
+       t.Run("returns error when environment is missing", func(t *testing.T) {
+               t.Setenv("POD_NAME", "")
+               t.Setenv("NAMESPACE", "default")
+
+               kubeClient, err := internal.NewFakeClient()
+               require.NoError(t, err)
 
-               image := getOperatorImage()
+               image, err := getOperatorImage(context.Background(), kubeClient)
+
+               require.Error(t, err)
+               assert.Empty(t, image)
+       })
 
+       t.Run("returns error when operator container is missing", func(t 
*testing.T) {
+               t.Setenv("POD_NAME", "operator-123")
+               t.Setenv("NAMESPACE", "default")
+
+               pod := &corev1.Pod{
+                       ObjectMeta: metav1.ObjectMeta{
+                               Name:      "operator-123",
+                               Namespace: "default",
+                       },
+                       Spec: corev1.PodSpec{
+                               Containers: []corev1.Container{
+                                       {
+                                               Name:  "some-other-container",
+                                               Image: "other:v1",
+                                       },
+                               },
+                       },
+               }
+               kubeClient, err := internal.NewFakeClient(pod)
+               require.NoError(t, err)
+
+               image, err := getOperatorImage(context.Background(), kubeClient)
+
+               require.Error(t, err)
                assert.Empty(t, image)
        })
 }
diff --git a/pkg/resources/config/manager/kustomization.yaml 
b/pkg/resources/config/manager/kustomization.yaml
index b067e2c33..a4543333a 100644
--- a/pkg/resources/config/manager/kustomization.yaml
+++ b/pkg/resources/config/manager/kustomization.yaml
@@ -28,13 +28,3 @@ patches:
     target:
       kind: Deployment
       name: camel-k-operator
-
-replacements:
-  - source:
-      kind: Deployment
-      fieldPath: spec.template.spec.containers.[name=camel-k-operator].image
-    targets:
-      - select:
-          kind: Deployment
-        fieldPaths:
-          - 
spec.template.spec.containers.[name=camel-k-operator].env.[name=CONTAINER_IMAGE].value
diff --git a/pkg/resources/config/manager/operator-deployment.yaml 
b/pkg/resources/config/manager/operator-deployment.yaml
index 1331ea35d..70e329e9c 100644
--- a/pkg/resources/config/manager/operator-deployment.yaml
+++ b/pkg/resources/config/manager/operator-deployment.yaml
@@ -77,9 +77,6 @@ spec:
             # Note: remove the variable to disable the feature.
             - name: CAMEL_MONITOR_OPERATOR_LABEL
               value: "camel.apache.org/monitor"
-            # Used to query which is the image this operator is running
-            - name: CONTAINER_IMAGE
-              value: ""
             # You can provide a different SA for builder Pods
             - name: BUILDER_SA
               value: "camel-k-builder"

Reply via email to