Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions internal/controller/kubevirt_datamover_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (

oadpv1alpha1 "github.com/openshift/oadp-operator/api/v1alpha1"
"github.com/openshift/oadp-operator/pkg/common"
"github.com/openshift/oadp-operator/pkg/credentials/stsflow"
)

const (
Expand Down Expand Up @@ -179,6 +180,20 @@ func ensureKubevirtDatamoverRequiredSpecs(
})
}

// Add Azure workload identity environment variables if configured
var envFrom []corev1.EnvFromSource
azureClientID := os.Getenv(stsflow.ClientIDEnvKey)
if azureClientID != "" && os.Getenv(stsflow.TenantIDEnvKey) != "" && os.Getenv(stsflow.SubscriptionIDEnvKey) != "" {
envFrom = append(envFrom, corev1.EnvFromSource{
SecretRef: &corev1.SecretEnvSource{
LocalObjectReference: corev1.LocalObjectReference{
Name: stsflow.AzureWorkloadIdentitySecretName,
},
},
})
r.Log.Info("Added Azure workload identity secret reference to KubeVirt DataMover container")
}

Comment on lines +183 to +196

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟠 Major | 🏗️ Heavy lift

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

rg -n -C 8 \
  'ReconcileAzureWorkloadIdentitySecret|AzureWorkloadIdentitySecretName|AZURE_(CLIENT_ID|TENANT_ID|FEDERATED_TOKEN_FILE)|EnvFrom|ResourceVersion|resource-version|revision|sha256' \
  --glob '*.go' .

Repository: openshift/oadp-operator

Length of output: 50380


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '--- target controller outline ---'
ast-grep outline internal/controller/kubevirt_datamover_controller.go
echo '--- target controller relevant symbols ---'
rg -n -C 12 'AzureWorkloadIdentitySecretName|ClientIDEnvKey|TenantIDEnvKey|SubscriptionIDEnvKey|EnvFrom|DataMover|Deployment|Reconcile' internal/controller/kubevirt_datamover_controller.go
echo '--- STS reconciler symbols and secret updates ---'
rg -n -C 14 'ReconcileAzureWorkloadIdentitySecret|CreateOrUpdateSTSSecretWithClientsAndWait|AzureWorkloadIdentitySecretName|ClientIDEnvKey|TenantIDEnvKey|SubscriptionIDEnvKey|FEDERATED_TOKEN' pkg/credentials/stsflow internal/controller
echo '--- target controller tests and callers ---'
rg -n -C 10 'KubeVirt|DataMover|AzureWorkloadIdentity|EnvFrom|SecretRef' internal/controller/*test.go

Repository: openshift/oadp-operator

Length of output: 50380


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '--- target deployment construction ---'
sed -n '183,220p' internal/controller/kubevirt_datamover_controller.go
sed -n '260,340p' internal/controller/kubevirt_datamover_controller.go

echo '--- Azure STS controller ---'
wc -l internal/controller/stsflow.go
cat -n internal/controller/stsflow.go

echo '--- STS secret update implementation ---'
sed -n '85,145p' pkg/credentials/stsflow/stsflow.go
sed -n '224,330p' pkg/credentials/stsflow/stsflow.go

echo '--- all call sites for Azure STS reconciliation and KubeVirt reconciliation ---'
rg -n -C 8 'ReconcileAzureWorkloadIdentitySecret|STSStandardizedFlow|CreateOrUpdateSTSSecretWithClients|ReconcileKubevirtDatamoverController' --glob '*.go' .

Repository: openshift/oadp-operator

Length of output: 50379


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '--- controller setup and owned-resource watches ---'
sed -n '55,135p' internal/controller/dataprotectionapplication_controller.go
rg -n -C 8 'Owns\(|For\(|Complete\(|SetupWithManager|Secret' internal/controller/dataprotectionapplication_controller.go

echo '--- KubeVirt controller tests for Azure envFrom and template changes ---'
rg -n -C 12 'CLIENTID|TENANTID|SUBSCRIPTIONID|AZURE|EnvFrom|Annotations|PodTemplate|ResourceVersion' internal/controller/kubevirt_datamover_controller_test.go

echo '--- source-level invariant probe ---'
python3 - <<'PY'
from pathlib import Path
p = Path("internal/controller/kubevirt_datamover_controller.go").read_text()
start = p.index("func ensureKubevirtDatamoverRequiredSpecs")
end = p.index("\nfunc ", start + 5)
fn = p[start:end]
checks = {
    "reads operator Azure environment": 'os.Getenv(stsflow.ClientIDEnvKey)' in fn,
    "references Azure Secret through EnvFrom": 'Name: stsflow.AzureWorkloadIdentitySecretName' in fn,
    "assigns EnvFrom to manager": 'kubevirtDatamoverContainer.EnvFrom = envFrom' in fn,
    "reads Secret resource version": '.ResourceVersion' in fn,
    "gets Secret from Kubernetes API": 'r.Get(' in fn,
    "adds Secret content revision": 'sha256' in fn or 'revision' in fn,
}
for name, value in checks.items():
    print(f"{name}: {value}")
PY

Repository: openshift/oadp-operator

Length of output: 25295


🌐 Web query:

Kubernetes official documentation Secret environment variables not updated automatically running container

💡 Result:

In Kubernetes, environment variables injected into a container from a Secret (or ConfigMap) are not updated automatically when the underlying Secret is modified [1][2]. These environment variables are only set when the Pod is created [1][3]. Because they are part of the process environment, they cannot be changed without terminating and recreating the container or the Pod [1][4]. If you need to update the values used by your application, you have the following options: 1. Perform a rolling update: The standard way to propagate changes is to trigger a rollout of the Deployment [1][4]. This can be done by running: kubectl rollout restart deployment This command replaces existing Pods with new ones that will pull the updated Secret values [1][5]. 2. Use Volumes instead of environment variables: If your application can be configured to read values from files, mounting the Secret as a volume is an alternative [6][2]. When a Secret is mounted as a volume, Kubernetes automatically updates the projected files (after a brief delay for kubelet synchronization), which allows many applications to detect the change and reload the configuration without requiring a Pod restart [4][2]. Note: Simply updating the Secret does not affect running Pods [1][4]. If you do not perform a rollout or recreate the Pods, the containers will continue to use the stale environment variable values from their initial startup [1][5].

Citations:


Add a rollout trigger for Azure Secret changes.

envFrom values are set only when the Pod starts. Secret updates enqueue DPA reconciliation, but the Deployment template keeps the same SecretRef, so existing KubeVirt DataMover Pods retain stale Azure identity values. Add a Secret resource-version or content-hash annotation to the Pod template and test Azure identity rotation.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/controller/kubevirt_datamover_controller.go` around lines 183 - 196,
Update the KubeVirt DataMover Pod template construction alongside the Azure
workload identity envFrom setup to include an annotation derived from the
referenced Azure Secret’s resource version or content hash. Ensure this
annotation changes whenever the Secret changes, triggering Deployment rollout
and fresh environment values in existing Pods; add coverage for Azure identity
rotation.

Source: MCP tools

// Track DPA resource version for change detection
currentKubevirtDatamoverEnabled := r.checkKubevirtDatamoverEnabled()
if len(kdmDpaResourceVersion) == 0 ||
Expand Down Expand Up @@ -251,6 +266,7 @@ func ensureKubevirtDatamoverRequiredSpecs(
Command: []string{"/manager"},
Args: args,
Env: envVars,
EnvFrom: envFrom,
Ports: []corev1.ContainerPort{
{
Name: "https",
Expand Down Expand Up @@ -315,6 +331,7 @@ func ensureKubevirtDatamoverRequiredSpecs(
kubevirtDatamoverContainer.ImagePullPolicy = imagePullPolicy
kubevirtDatamoverContainer.Args = args
kubevirtDatamoverContainer.Env = envVars
kubevirtDatamoverContainer.EnvFrom = envFrom
kubevirtDatamoverContainer.Resources = resources
kubevirtDatamoverContainer.TerminationMessagePolicy = corev1.TerminationMessageFallbackToLogsOnError
kubevirtDatamoverContainerFound = true
Expand Down