refactoring

This commit is contained in:
Safwan
2026-06-22 20:34:40 +05:00
parent 73729c951e
commit 3ace65a9ad
14 changed files with 535 additions and 167 deletions
+15
View File
@@ -968,4 +968,19 @@ func TestSecretProviderClassPodStatusPredicates(t *testing.T) {
if p.Update(event.UpdateEvent{ObjectOld: oldObj, ObjectNew: newObjSame}) {
t.Fatal("UpdateFunc should return false on unchanged status")
}
// A metadata/label-only change (same Status) must NOT trigger a reload,
// since the predicate hashes only the status. (Master tested this via
// UpdateSecretProviderClassPodStatusLabels.)
labelOnly := oldObj.DeepCopy()
labelOnly.Labels = map[string]string{"unrelated": "changed"}
labelOnly.Annotations = map[string]string{"note": "touched"}
if p.Update(event.UpdateEvent{ObjectOld: oldObj, ObjectNew: labelOnly}) {
t.Fatal("UpdateFunc should return false on a label/metadata-only change")
}
// Type-assertion failure (wrong object type) must be rejected, not panic.
if p.Update(event.UpdateEvent{ObjectOld: &corev1.ConfigMap{}, ObjectNew: &corev1.ConfigMap{}}) {
t.Fatal("UpdateFunc should return false when objects are not SPCPS")
}
}
+5
View File
@@ -268,6 +268,11 @@ func (s *Service) findVolumeUsingResource(volumes []corev1.Volume, resourceName
}
}
}
case ResourceTypeSecretProviderClass:
// Match the CSI volume that references this SPC.
if vol.CSI != nil && vol.CSI.VolumeAttributes["secretProviderClass"] == resourceName {
return vol.Name
}
}
}
return ""
+86
View File
@@ -5,6 +5,7 @@ import (
"testing"
"github.com/go-logr/logr/testr"
appsv1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
csiv1 "sigs.k8s.io/secrets-store-csi-driver/apis/v1"
@@ -1385,3 +1386,88 @@ func TestService_ProcessCreateEventDisabled(t *testing.T) {
t.Errorf("Expected nil decisions when create events disabled, got %v", decisions)
}
}
func TestService_ApplyReload_SPC_TargetsMountingContainer(t *testing.T) {
cfg := config.NewDefault()
cfg.ReloadStrategy = config.ReloadStrategyEnvVars
svc := NewService(cfg, testr.New(t))
// Two containers; only the second mounts the CSI volume that references the SPC.
dep := &appsv1.Deployment{
ObjectMeta: metav1.ObjectMeta{Name: "multi", Namespace: "default"},
Spec: appsv1.DeploymentSpec{
Template: corev1.PodTemplateSpec{
Spec: corev1.PodSpec{
Containers: []corev1.Container{
{Name: "c0"},
{Name: "c1", VolumeMounts: []corev1.VolumeMount{{Name: "spc-vol", MountPath: "/mnt/secrets-store"}}},
},
Volumes: []corev1.Volume{
{
Name: "spc-vol",
VolumeSource: corev1.VolumeSource{
CSI: &corev1.CSIVolumeSource{
Driver: "secrets-store.csi.k8s.io",
VolumeAttributes: map[string]string{"secretProviderClass": "my-spc"},
},
},
},
},
},
},
},
}
accessor := workload.NewDeploymentWorkload(dep)
// autoReload=true exercises volume-based container targeting.
updated, err := svc.ApplyReload(context.Background(), accessor, "my-spc", ResourceTypeSecretProviderClass, "default", "spchash", true)
if err != nil {
t.Fatalf("ApplyReload failed: %v", err)
}
if !updated {
t.Fatal("expected updated=true")
}
containers := accessor.GetContainers()
const envName = "STAKATER_MY_SPC_SECRETPROVIDERCLASS"
hasEnv := func(c corev1.Container) bool {
for _, e := range c.Env {
if e.Name == envName {
return true
}
}
return false
}
if hasEnv(containers[0]) {
t.Error("env var must NOT land on container[0] (it does not mount the SPC volume)")
}
if !hasEnv(containers[1]) {
t.Error("env var must land on container[1], which mounts the SPC CSI volume")
}
}
func TestService_ProcessSecretProviderClass_GenericAuto(t *testing.T) {
cfg := config.NewDefault()
svc := NewService(cfg, testr.New(t))
// Generic auto annotation (not the typed SPC one) must also trigger an SPC reload.
deploy := testutil.NewDeployment("test-deploy", "default", map[string]string{
"reloader.stakater.com/auto": "true",
})
workloads := []workload.Workload{workload.NewDeploymentWorkload(deploy)}
change := SecretProviderClassChange{
Name: "my-spc",
Namespace: "default",
Status: csiv1.SecretProviderClassPodStatusStatus{
SecretProviderClassName: "my-spc",
Objects: []csiv1.SecretProviderClassObject{{ID: "a", Version: "1"}},
},
EventType: EventTypeUpdate,
}
decisions := svc.Process(change, workloads)
if len(decisions) != 1 || !decisions[0].ShouldReload {
t.Fatalf("expected generic-auto SPC reload, got %+v", decisions)
}
}
+9 -2
View File
@@ -179,8 +179,15 @@ func (s *AnnotationStrategy) Apply(input StrategyInput) (bool, error) {
annotationKey := s.cfg.Annotations.LastReloadedFrom
existingValue := input.PodAnnotations[annotationKey]
if existingValue == string(sourceJSON) {
return false, nil
// Idempotent on kind+name+hash, ignoring ReloadedAt: a timestamped compare
// would force a rollout every reconcile (one CSI rotation fans out to N
// SecretProviderClassPodStatus updates → N rollouts).
if existingValue != "" {
var prev ReloadSource
if err := json.Unmarshal([]byte(existingValue), &prev); err == nil &&
prev.Kind == source.Kind && prev.Name == source.Name && prev.Hash == source.Hash {
return false, nil
}
}
input.PodAnnotations[annotationKey] = string(sourceJSON)
+44
View File
@@ -255,6 +255,50 @@ func TestAnnotationStrategy_Apply(t *testing.T) {
}
})
t.Run("idempotent for same resource and hash (ignores timestamp)", func(t *testing.T) {
annotations := make(map[string]string)
input := StrategyInput{
ResourceName: "my-config",
ResourceType: ResourceTypeConfigMap,
Namespace: "default",
Hash: "abc123",
Container: &corev1.Container{Name: "c"},
PodAnnotations: annotations,
}
changed, err := strategy.Apply(input)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if !changed {
t.Fatal("expected changed=true on first apply")
}
firstValue := annotations[cfg.Annotations.LastReloadedFrom]
// Re-applying the identical change must NOT report a change, even though
// a fresh ReloadedAt timestamp would make the serialized value differ.
changed, err = strategy.Apply(input)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if changed {
t.Error("expected changed=false when re-applying the same resource+hash")
}
if annotations[cfg.Annotations.LastReloadedFrom] != firstValue {
t.Error("annotation value must not change on an idempotent re-apply")
}
// A different hash (real content change) must trigger an update.
input.Hash = "def456"
changed, err = strategy.Apply(input)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if !changed {
t.Error("expected changed=true when the hash changes")
}
})
t.Run("error when annotations map is nil", func(t *testing.T) {
input := StrategyInput{
ResourceName: "my-config",