test(e2e): fix TOCTOU race in CSI reload waits

The CSI e2e tests wait for the SPCPS version change before calling
WaitReloaded/WaitEnvVar, but Reloader reacts to that same SPCPS update.
When Reloader won the race, WaitReloaded captured the already-reloaded
annotation as its baseline and then timed out waiting for a further
change (seen in CI: "Init container with CSI volume should reload...").

Add WaitReloadedFrom/WaitEnvVarFrom adapter variants that take a
caller-supplied baseline, and have the CSI tests capture that baseline
before updating the Vault secret. Negative tests also benefit: an
erroneous reload that lands during the CSI sync wait is now detected
instead of silently absorbed into the baseline.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Michał Marszałek
2026-07-06 14:10:38 +02:00
co-authored by Claude Fable 5
parent 53ae379242
commit 0e45c6b24d
13 changed files with 201 additions and 34 deletions
+20 -6
View File
@@ -72,6 +72,11 @@ var _ = Describe("CSI SecretProviderClass Tests", Label("csi"), Serial, func() {
Expect(err).NotTo(HaveOccurred())
GinkgoWriter.Printf("Initial SPCPS version: %s\n", initialVersion)
// Capture the reload-annotation baseline before the trigger: Reloader reacts to the
// same SPCPS update the test waits on below, so it may reload before WaitReloaded runs.
priorReload, err := adapter.GetPodTemplateAnnotation(ctx, testNamespace, deploymentName, utils.AnnotationLastReloadedFrom)
Expect(err).NotTo(HaveOccurred())
By("Updating the Vault secret")
err = utils.UpdateVaultSecret(
ctx, kubeClient, restConfig, vaultSecretPath, map[string]string{"api_key": "updated-value-v2"})
@@ -83,9 +88,9 @@ var _ = Describe("CSI SecretProviderClass Tests", Label("csi"), Serial, func() {
GinkgoWriter.Println("CSI driver synced new secret version")
By("Waiting for Deployment to be reloaded by Reloader")
reloaded, err := adapter.WaitReloaded(
reloaded, err := adapter.WaitReloadedFrom(
ctx, testNamespace, deploymentName,
utils.AnnotationLastReloadedFrom, utils.ReloadTimeout,
utils.AnnotationLastReloadedFrom, priorReload, utils.ReloadTimeout,
)
Expect(err).NotTo(HaveOccurred())
Expect(reloaded).To(BeTrue(), "Deployment should have been reloaded after Vault secret change")
@@ -124,6 +129,10 @@ var _ = Describe("CSI SecretProviderClass Tests", Label("csi"), Serial, func() {
By("First update to Vault secret")
initialVersion, _ := utils.GetSPCPSVersion(ctx, csiClient, testNamespace, spcpsName)
// Capture the baseline before the trigger to avoid racing Reloader's own reaction
// to the SPCPS update below.
priorReload, err := adapter.GetPodTemplateAnnotation(ctx, testNamespace, deploymentName, utils.AnnotationLastReloadedFrom)
Expect(err).NotTo(HaveOccurred())
err = utils.UpdateVaultSecret(
ctx, kubeClient, restConfig, vaultSecretPath, map[string]string{"password": "pass-v2"})
Expect(err).NotTo(HaveOccurred())
@@ -133,9 +142,9 @@ var _ = Describe("CSI SecretProviderClass Tests", Label("csi"), Serial, func() {
Expect(err).NotTo(HaveOccurred())
By("Waiting for first reload")
reloaded, err := adapter.WaitReloaded(
reloaded, err := adapter.WaitReloadedFrom(
ctx, testNamespace, deploymentName,
utils.AnnotationLastReloadedFrom, utils.ReloadTimeout,
utils.AnnotationLastReloadedFrom, priorReload, utils.ReloadTimeout,
)
Expect(err).NotTo(HaveOccurred())
Expect(reloaded).To(BeTrue())
@@ -230,6 +239,11 @@ var _ = Describe("CSI SecretProviderClass Tests", Label("csi"), Serial, func() {
By("Getting SPCPS version before Vault update")
initialVersion, _ := utils.GetSPCPSVersion(ctx, csiClient, testNamespace, spcpsName)
// Capture the baseline before the trigger to avoid racing Reloader's own reaction
// to the SPCPS update below.
priorReload, err := adapter.GetPodTemplateAnnotation(ctx, testNamespace, deploymentName, utils.AnnotationLastReloadedFrom)
Expect(err).NotTo(HaveOccurred())
By("Updating the Vault secret (should trigger reload)")
err = utils.UpdateVaultSecret(
ctx, kubeClient, restConfig, vaultSecretPath, map[string]string{"token": "token-v2"})
@@ -240,9 +254,9 @@ var _ = Describe("CSI SecretProviderClass Tests", Label("csi"), Serial, func() {
Expect(err).NotTo(HaveOccurred())
By("Verifying Deployment WAS reloaded for Vault secret change")
reloaded, err = adapter.WaitReloaded(
reloaded, err = adapter.WaitReloadedFrom(
ctx, testNamespace, deploymentName,
utils.AnnotationLastReloadedFrom, utils.ReloadTimeout,
utils.AnnotationLastReloadedFrom, priorReload, utils.ReloadTimeout,
)
Expect(err).NotTo(HaveOccurred())
Expect(reloaded).To(BeTrue(), "SPC auto annotation should trigger reload for Vault secret changes")