Skip to content

test: EKS add-on support - #601

Open
ThirdEyeSqueegee wants to merge 5 commits into
mainfrom
addon-test
Open

test: EKS add-on support#601
ThirdEyeSqueegee wants to merge 5 commits into
mainfrom
addon-test

Conversation

@ThirdEyeSqueegee

@ThirdEyeSqueegee ThirdEyeSqueegee commented Apr 13, 2026

Copy link
Copy Markdown
Member

Description

Why is this change being made?

  1. Add support for testing the EKS add-on by passing --addon and --addon-version flags to run-tests.sh

What is changing?

  1. Add a new integ test install method for the provider governed by the --addon flag in run-tests.sh
    i. --addon-version can be used to specify an add-on version to test
  2. Update README.md with add-on testing instructions
  3. Add addon_config_values.yaml to pass config options to add-on for integ tests
  4. Add check to fail fast if POD_IDENTITY_ROLE_ARN is undefined when Pod Identity configs are selected for test runs
  5. Dynamically fetch cluster role for RBAC validation test case

Related Links

  • Issue #, if available:
    N/A

Testing

How was this tested?

  1. Ran integ tests locally: ./run-tests --addon x64 and ./run-tests.sh x64 --addon --addon-version v3.0.0-eksbuild.1
    i. All tests pass

When testing locally, provide testing artifact(s):

  1. N/A

Reviewee Checklist

Update the checklist after submitting the PR

  • I have reviewed, tested and understand all changes
    If not, why:
  • I have filled out the Description and Testing sections above
    If not, why:
  • Build and Unit tests are passing
    If not, why:
  • Unit test coverage check is passing
    If not, why:
  • Integration tests pass locally
    If not, why:
  • I have updated integration tests (if needed)
    If not, why:
  • I have ensured no sensitive information is leaking (i.e., no logging of sensitive fields, or otherwise)
    If not, why:
  • I have added explanatory comments for complex logic, new classes/methods and new tests
    If not, why:
  • I have updated README/documentation (if needed)
    If not, why:
  • I have clearly called out breaking changes (if any)
    If not, why:

Reviewer Checklist

All reviewers please ensure the following are true before reviewing:

  • Reviewee checklist has been accurately filled out
  • Code changes align with stated purpose in description
  • Test coverage adequately validates the changes

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.

@ThirdEyeSqueegee
ThirdEyeSqueegee requested a review from a team as a code owner April 13, 2026 00:20
@codecov

codecov Bot commented Apr 13, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 61.62%. Comparing base (51c23b1) to head (24c4458).

Additional details and impacted files
@@           Coverage Diff           @@
##             main     #601   +/-   ##
=======================================
  Coverage   61.62%   61.62%           
=======================================
  Files          11       11           
  Lines         740      740           
=======================================
  Hits          456      456           
  Misses        265      265           
  Partials       19       19           

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@ThirdEyeSqueegee ThirdEyeSqueegee added the safe-to-test Pull Request has been manually reviewed and deemed to be safe to run integration tests on. label Apr 13, 2026
@ThirdEyeSqueegee
ThirdEyeSqueegee requested review from a team and simonmarty and removed request for a team April 13, 2026 00:32
Comment thread tests/run-tests.sh
Comment thread tests/integration.bats.template Outdated
log "Installing secrets-store-csi-driver via Helm"
KUBECONFIG=${{KUBECONFIG_VAR}} helm --namespace=$NAMESPACE install --wait --wait-for-jobs --timeout=30s csi-secrets-store secrets-store-csi-driver/secrets-store-csi-driver --set enableSecretRotation=true --set rotationPollInterval=15s --set syncSecret.enabled=true --set tokenRequests[0].audience=sts.amazonaws.com --set tokenRequests[1].audience=pods.eks.amazonaws.com
log "Installing secrets-store-csi-driver via Helm"
KUBECONFIG=${{KUBECONFIG_VAR}} helm --namespace=$NAMESPACE install --wait --wait-for-jobs --timeout=30s csi-secrets-store secrets-store-csi-driver/secrets-store-csi-driver --set enableSecretRotation=true --set rotationPollInterval=15s --set syncSecret.enabled=true --set tokenRequests[0].audience=sts.amazonaws.com --set tokenRequests[1].audience=pods.eks.amazonaws.com

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.

Nit, for a followup, (you don't have to do it in this PR, and you don't have to be the one to do it):

We might as well install the provider here through the helm chart and install the driver as a Helm dependency instead of in two separate steps. We just have to pass the config options we're passing here to the underlying driver chart. That way the addon and the provider flows are more similar.

@github-actions github-actions Bot removed the safe-to-test Pull Request has been manually reviewed and deemed to be safe to run integration tests on. label Apr 13, 2026
@ThirdEyeSqueegee ThirdEyeSqueegee added the safe-to-test Pull Request has been manually reviewed and deemed to be safe to run integration tests on. label Apr 13, 2026
@github-actions github-actions Bot removed the safe-to-test Pull Request has been manually reviewed and deemed to be safe to run integration tests on. label Apr 13, 2026
@ThirdEyeSqueegee ThirdEyeSqueegee added the safe-to-test Pull Request has been manually reviewed and deemed to be safe to run integration tests on. label May 8, 2026
@github-actions github-actions Bot removed the safe-to-test Pull Request has been manually reviewed and deemed to be safe to run integration tests on. label Jun 5, 2026
@ThirdEyeSqueegee ThirdEyeSqueegee added the safe-to-test Pull Request has been manually reviewed and deemed to be safe to run integration tests on. label Jun 5, 2026
@github-actions github-actions Bot removed the safe-to-test Pull Request has been manually reviewed and deemed to be safe to run integration tests on. label Jul 28, 2026
@secrets-manager-ai-code-review

secrets-manager-ai-code-review Bot commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

Claude finished @simonmarty's task in 2m 16s —— View job


Review: EKS add-on test support

  • Gather context (diff vs origin/main)
  • Review run-tests.sh flag parsing
  • Review integration.bats.template changes
  • Review generate-test-files.py and config/docs
  • Post review feedback

I've reviewed the changes and left a couple of inline comments. Overall this is a clean, well-scoped addition and the flag-parsing rework nicely addresses the earlier out-of-order-args feedback. One likely bug worth confirming before merge.

🔴 Likely bug: driverWritesSecrets test fails in addon mode

tests/integration.bats.template:343 — the @test "CSI inline volume test with driverWritesSecrets enabled" case runs helm upgrade csi-secrets-store-provider-aws ... unconditionally. In --addon mode the provider is installed as an EKS add-on, so there is no Helm release by that name and the upgrade fails with:

Error: UPGRADE FAILED: "csi-secrets-store-provider-aws" has no deployed releases

The @test "Install aws provider" case (line 133) was correctly guarded with skip when INSTALL_METHOD == addon, but this test — and its teardown() at line 391, which repeats the same helm upgrade — were not. Two options:

  • Add a matching skip guard when INSTALL_METHOD == addon, or
  • Toggle driverWritesSecrets via the add-on configuration values (addon_config_values.yaml + aws eks update-addon) so add-on coverage is preserved.

Since the description says all tests passed locally, I suspect the addon run didn't actually reach this case. Worth verifying an end-to-end --addon run gets past it.

(This line is unchanged context and outside the diff, so I couldn't attach an inline comment there.) Fix this →

🟡 Minor: ClusterRole lookup robustness

tests/integration.bats.template:167 — if the jq select(test("provider.*cluster-role")) matches nothing, PROVIDER_CLUSTER_ROLE is empty and the subsequent kubectl get clusterrole lists all roles, whose shape ({items:[...]}) then breaks the jq '.rules[]'. It fails safe, but with a misleading error. Suggested a [[ -n "$PROVIDER_CLUSTER_ROLE" ]] || fail ... guard inline.

🟢 Looks good

  • run-tests.sh flag parsing — from-any-position parsing plus the --addon-version requires --addon check correctly handles the out-of-order case (--addon-version X --addon) that @simonmarty flagged. --addon-version also validates a value is present.
  • generate-test-files.py — the POD_IDENTITY_ROLE_ARN fail-fast guard is a good addition; fails cleanly before creating a cluster.
  • Guarded env-var checks — moving PRIVREPO/GHCR checks behind INSTALL_METHOD != addon is correct; the addon path genuinely doesn't need them.
  • README + addon_config_values.yaml — clear docs, and the config values mirror the Helm --set flags.

Nits

  • addon_config_values.yaml duplicates the driver settings currently passed via Helm --set in the non-addon path. @simonmarty's earlier suggestion (install the driver as a Helm dependency of the provider chart so both flows share one config source) would remove that drift — reasonable as the noted follow-up, not this PR.

Comment thread tests/run-tests.sh
done
set -- "${REMAINING_ARGS[@]}"

if [[ -n "$ADDON_VERSION" && "$INSTALL_METHOD" != "addon" ]]; then

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.

👍 This correctly resolves @simonmarty's earlier note — flags are now parsed from any position and --addon-version ... --addon (out of order) is accepted before the --addon-version requires --addon check runs. Nice.

One small note: INSTALL_METHOD and ADDON_VERSION are exported here so the generated .bats files inherit them. That works because bats is invoked as a child process later in this same script, but it does mean these leak into the caller's environment if the script is ever sourced. Given it's #!/bin/bash and always run as a subprocess, this is fine as-is.

log "Verifying provider ClusterRole does not grant serviceaccounts/token create permission"

# Find the provider ClusterRole (name varies between Helm and addon installs)
PROVIDER_CLUSTER_ROLE=$(kubectl --kubeconfig=${{KUBECONFIG_VAR}} get clusterrole -o json | jq -r '.items[].metadata.name | select(test("provider.*cluster-role"))' | head -1)

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.

Minor robustness: if the select(test("provider.*cluster-role")) filter matches nothing, PROVIDER_CLUSTER_ROLE is empty and the next command degrades to kubectl get clusterrole -o json (all roles). That output is {items: [...]} rather than {rules: [...]}, so the jq '.rules[]' errors and the test fails — fail-safe, but with a confusing message. Consider asserting the role was found first:

[[ -n "$PROVIDER_CLUSTER_ROLE" ]] || fail "Could not locate provider ClusterRole"

log "Verifying provider ClusterRole does not grant serviceaccounts/token create permission"

# Find the provider ClusterRole (name varies between Helm and addon installs)
PROVIDER_CLUSTER_ROLE=$(kubectl --kubeconfig=${{KUBECONFIG_VAR}} get clusterrole -o json | jq -r '.items[].metadata.name | select(test("provider.*cluster-role"))' | head -1)

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.

Minor robustness: if the select(test("provider.*cluster-role")) filter matches nothing, PROVIDER_CLUSTER_ROLE is empty and the next command becomes kubectl get clusterrole -o json (all roles), whose top-level shape is {items: [...]} rather than {rules: [...]} — so the jq '.rules[]' will error and the test fails rather than silently passing. That's fail-safe, but the failure message won't point at the root cause. Consider asserting the role was found first, e.g.:

[[ -n "$PROVIDER_CLUSTER_ROLE" ]] || fail "Could not locate provider ClusterRole"

@simonmarty simonmarty left a comment

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.

Could you address the AI code review comments?

@secrets-manager-ai-code-review

secrets-manager-ai-code-review Bot commented Aug 19, 2026

Copy link
Copy Markdown
Contributor

Claude finished @ThirdEyeSqueegee's task in 45m 17s —— View job


Review: EKS add-on test support

  • Gather context (diff vs origin/main, chart RBAC/dependency structure, integ.yml call sites)
  • Review run-tests.sh flag parsing and dispatch
  • Review integration.bats.template install-path parity
  • Review generate-test-files.py, addon_config_values.yaml, README
  • Post inline comments (8 posted)

@simonmarty asked for the earlier AI review comments to be addressed. Checking the current head (24c4458): the two flagged issues are still open — the driverWritesSecrets helm upgrade has no addon guard, and the ClusterRole lookup still has no non-empty check. The --addon-version out-of-order concern was fixed. Full detail is inline; summary below.

🔴 Blocking

Addon mode cannot reach a green run. integration.bats.template:343-352 and teardown() at L391-402 both run helm upgrade -n $NAMESPACE csi-secrets-store-provider-aws ... unconditionally. @test "Install aws provider" is the only test that got the skip, so under --addon there is no such release, the chart's secrets-store-csi-driver dependency was never fetched (helm package --dependency-update lives in the skipped test, and charts/*/charts/ is not vendored — verified), $PRIVREPO/$PRIVTAG are empty by design, and ghcr-secret is never created. Four independent failures on one command. Suggested a skip_if_addon helper in helpers.bash so the next Helm-only test can't repeat the omission. Since the description reports a passing --addon x64 run, that run likely didn't reach L343 — worth re-verifying end to end.

The RBAC security assertion can pass vacuously. integration.bats.template:167 — with multiple regex matches, head -1 picks arbitrarily and the serviceaccounts/token check runs against the wrong ClusterRole and reports green; with zero matches it dies on an opaque jq: Cannot iterate over null. The assignment is also a pipeline ending in head, so a kubectl failure never trips errexit. The chart labels the ClusterRole (rbac.yaml:20-22provider.labels), so -l app=secrets-store-csi-driver-provider-aws — the idiom already used 11 lines up at L156 — plus a || fail guard replaces the regex and head -1 entirely. Suggestion diff is inline.

🟡 Worth addressing

Where Issue
run-tests.sh:57 Unknown flags fall through to positional args and the dispatch chain has no else → a flag typo runs zero tests and exits 0. A green CI check on a build the suite never touched.
run-tests.sh:65 Validation reads ADDON_VERSION/INSTALL_METHOD from the ambient env, not the parsed flags, and sits before the clean branch. An inherited ADDON_VERSION breaks run-tests.sh clean — the if: always() cleanup step — leaking a 3-node cluster and secrets in two regions. Inherited INSTALL_METHOD=addon silently switches CI into addon mode.
integration.bats.template:71-75 Nothing installs or verifies the CSI driver in addon mode (depends on the published add-on's default for secrets-store-csi-driver.install); wait addon-active is control-plane status, not DaemonSet readiness, and the only provider-pod assertion is in the skipped test; create-addon isn't re-entrant (ResourceInUseException on re-run).
generate-test-files.py:235 The POD_IDENTITY_ROLE_ARN guard is a good addition but lands inside setup_file after eksctl create cluster, so it fails ~15-20 min and one paid cluster late. Every other env guard is at file scope for exactly this reason.
addon_config_values.yaml Set secrets-store-csi-driver.install: true explicitly. Also worth running aws eks describe-addon-configuration once to confirm the add-on's schema actually accepts the nested secrets-store-csi-driver.* keys — if it doesn't, create-addon fails after the cluster is up.
README.md:51 "does not require PRIVREPO" is false while L346 is unguarded; omits that --addon x64-pod-identity still needs POD_IDENTITY_ROLE_ARN; and doesn't say that --addon tests the published add-on image, not the branch build.

Notes, not blockers

  • Pre-existing bug in a file you're touching: teardown() at L393 compares $BATS_TEST_NAME (which bats sets to the mangled function name test_CSI_inline_volume_test_with_driverWritesSecrets_enabled) against the human-readable description. It never matches, so driverWritesSecrets=false is never restored and L416 runs against a provider the suite believes it reset. $BATS_TEST_DESCRIPTION is the right variable — but note that fixing it makes a second unguarded helm upgrade live, and because teardown runs after every test, a failure there marks every test in the file as failed. Fix it together with the addon guard.
  • No CI coverage. integ.yml:123 still calls ./run-tests.sh <arch>-<auth> with no --addon and no matrix dimension for it, so nothing above is caught by any pipeline and the addon path will rot silently. Either wire in an addon leg or note in the README that --addon is manual-only.
  • Config duplication — agreed with @simonmarty's earlier suggestion (driver as a Helm dependency of the provider chart so both flows share one config source) as a follow-up.

🟢 Looks good

  • Flag parsing from any position correctly resolves @simonmarty's out-of-order case; --addon-version X --addon is accepted before the consistency check runs, and a missing value is caught.
  • Guarded env checks — moving the PRIVREPO/GHCR checks behind INSTALL_METHOD != addon is right; the addon path genuinely doesn't need them. Same for scoping the GHCR secret to the else branch.
  • addon_config_values.yaml's tokenRequests shape is an exact match for what the --set tokenRequests[0..1].audience chain produced.
  • f-string escaping in get_auth_setup is correct (${{POD_IDENTITY_ROLE_ARN}}${POD_IDENTITY_ROLE_ARN}), and the {{AUTH_SETUP}}-after-{{KEY}} substitution order is safe.

Caveat on method: this is a static review. I couldn't run shellcheck/bash -n or an actual --addon run in this environment, so the addon-schema and driver-subchart questions above are stated as things to verify, not as confirmed failures. The L343 breakage and the run-tests.sh exit-0-on-typo hole are structural and don't need a cluster to confirm.
addon-test

Comment on lines +134 to +136
if [[ "${INSTALL_METHOD}" == "addon" ]]; then
skip "Provider installed as EKS addon"
fi

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.

🔴 Blocking: this is the only Helm-dependent test that got the guard — addon mode can't pass.

Two other Helm-only blocks were missed (both outside the diff, so I can't anchor there):

  • L343-352, @test "CSI inline volume test with driverWritesSecrets enabled" — runs helm upgrade -n $NAMESPACE csi-secrets-store-provider-aws ... unconditionally.
  • L391-402, teardown() — repeats the same helm upgrade to restore driverWritesSecrets=false.

In --addon mode all four things they depend on are absent:

  1. No csi-secrets-store-provider-aws Helm release exists (this test is skipped) → Error: UPGRADE FAILED: "csi-secrets-store-provider-aws" has no deployed releases.
  2. helm package --dependency-update at L140 never ran, and charts/secrets-store-csi-driver-provider-aws/charts/ is not vendored (I checked — only Chart.lock, Chart.yaml, templates, values.yaml), so helm also fails dependency resolution: found in Chart.yaml, but missing in charts/ directory: secrets-store-csi-driver.
  3. $PRIVREPO/$PRIVTAG are empty — the new guard at L24 stops enforcing PRIVREPO, and tests/README.md:51 says it isn't needed. --set image.tag= renders image: <repo>:, exactly the footgun the comment at L148-152 guards against for the Helm path.
  4. ghcr-secret is only created inside the else at L78-81, but L351 attaches it unconditionally.

Given the PR description says all tests passed under ./run-tests.sh --addon x64, this run very likely didn't reach L343 — worth re-verifying end-to-end.

Rather than a third copy of the inline if, a shared guard in tests/helpers.bash (already loaded at L3) makes the omission visible and gives the next Helm-only test something to copy:

skip_if_addon() {
	[[ "${INSTALL_METHOD}" == "addon" ]] && skip "provider installed as EKS addon"
}

Alternatively, toggle driverWritesSecrets through addon_config_values.yaml + aws eks update-addon so addon mode keeps that coverage instead of losing it.

Separately: skipping this test also drops the only assertion that the provider actually rolled out (L156-158) — see my comment on L71.

log "Verifying provider ClusterRole does not grant serviceaccounts/token create permission"

# Find the provider ClusterRole (name varies between Helm and addon installs)
PROVIDER_CLUSTER_ROLE=$(kubectl --kubeconfig=${{KUBECONFIG_VAR}} get clusterrole -o json | jq -r '.items[].metadata.name | select(test("provider.*cluster-role"))' | head -1)

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.

🔴 The lookup can silently make this security assertion vacuous. (Re-raising @simonmarty's jq note and the earlier bot comment — the guard still isn't there.)

Three failure modes, none of which report the real cause:

  1. No matchPROVIDER_CLUSTER_ROLE is empty. L170 degrades to kubectl get clusterrole -o json, which returns a kind: List whose .rules is null, so jq -e '.rules[]' aborts with Cannot iterate over null (exit 5). Fails safe, but the message points at jq rather than at a missing role.
  2. Multiple matcheshead -1 silently picks the first in API order. If any other ClusterRole matches provider.*cluster-role (a stale release, a second provider) the serviceaccounts/token check runs against the wrong object and passes green while the real provider role grants the permission. That's a false pass on a privilege-escalation regression test.
  3. The assignment is a pipeline ending in head, so exit status is head's — a kubectl failure never trips bats' errexit; the variable just comes back empty and you land in case 1.

The chart already gives you a name-independent handle: provider.labels (_helpers.tpl) stamps app: secrets-store-csi-driver-provider-aws and app.kubernetes.io/name onto the ClusterRole via rbac.yaml:20-22, and this file already uses that selector idiom at L156/L355. That replaces both the regex and head -1:

Suggested change
PROVIDER_CLUSTER_ROLE=$(kubectl --kubeconfig=${{KUBECONFIG_VAR}} get clusterrole -o json | jq -r '.items[].metadata.name | select(test("provider.*cluster-role"))' | head -1)
# Find the provider ClusterRole (name varies between Helm and addon installs)
PROVIDER_CLUSTER_ROLE=$(kubectl --kubeconfig=${{KUBECONFIG_VAR}} get clusterrole -l app=secrets-store-csi-driver-provider-aws -o jsonpath="{.items[0].metadata.name}")
[[ -n "$PROVIDER_CLUSTER_ROLE" ]] || fail "Could not locate provider ClusterRole"

If you'd rather keep the regex, the [[ -n ... ]] || fail ... line alone fixes case 1 and 3; case 2 still needs a uniqueness check.

Nit while you're here: the -n $NAMESPACE retained on L170 is a no-op — ClusterRole is cluster-scoped, and the new L167 correctly omits it.

Comment on lines +71 to +75
if [[ "${INSTALL_METHOD}" == "addon" ]]; then
log "Installing aws-secrets-store-csi-driver-provider as EKS addon"
aws eks create-addon --cluster-name $CLUSTER_NAME --addon-name aws-secrets-store-csi-driver-provider \
--configuration-values file://addon_config_values.yaml ${ADDON_VERSION:+--addon-version $ADDON_VERSION} --region $REGION
aws eks wait addon-active --cluster-name $CLUSTER_NAME --addon-name aws-secrets-store-csi-driver-provider --region $REGION

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.

🟡 Three gaps in the addon install branch relative to the Helm branch it replaces.

1. Nothing installs or verifies the CSI driver. The else branch at L87 is the only thing that installs secrets-store-csi-driver, and it's skipped here. Addon mode relies entirely on the published add-on vendoring the driver as a subchart and leaving secrets-store-csi-driver.install at its default true (Chart.yaml gates the dep on that condition). If the EKS build strips or flips it — plausible, since EKS ships the driver as its own add-on — nothing installs the driver and the first symptom is @test "secretproviderclasses crd is established" (L179) timing out at 60s, followed by every mount/rotation/sync test failing with no pointer at the root cause. Worth setting secrets-store-csi-driver.install: true explicitly in addon_config_values.yaml so the intent is asserted rather than inherited.

2. No readiness gate. The Helm path had helm install --wait --wait-for-jobs plus the explicit provider-pod assertion at L156-158 — and that assertion is inside the test you just skipped. aws eks wait addon-active reflects EKS control-plane add-on status, not that the provider DaemonSet is Ready on all 3 nodes. The next assertions have hard 60s budgets (L179, L201), so a slow rollout on a fresh 3-node cluster surfaces as an intermittent mount timeout. Mirroring what the skipped test provided would fix it:

kubectl --kubeconfig=${{KUBECONFIG_VAR}} -n $NAMESPACE rollout status daemonset -l app=secrets-store-csi-driver-provider-aws --timeout=120s

3. create-addon isn't re-entrant. No --resolve-conflicts, so a re-run against a cluster whose teardown_file didn't complete gets ResourceInUseException and aborts setup_file, failing all tests with a confusing error. And if the add-on lands in a stuck CREATING/DEGRADED, the waiter blocks for its full default (60 × 10s = 10 min) on a live billing cluster and then reports a bare Max attempts exceeded — echoing aws eks describe-addon on failure would make that diagnosable.

Also note (not a defect, but worth stating in the README — see my comment there): create-addon has no image override, so --addon validates the published add-on image, not $PRIVREPO:$PRIVTAG from the branch under test.

Comment thread tests/run-tests.sh
Comment on lines +57 to +60
*)
REMAINING_ARGS+=("$1")
shift
;;

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.

🟡 The catch-all makes a typo'd flag a silent green run.

Unrecognized flags fall into REMAINING_ARGS and become $1. The dispatch chain at L96-137 has no else, so nothing matches, bats is never invoked, bats_exit_code stays at its initialized 0, and L141 exits 0 having run zero tests:

$ ./run-tests.sh --addon-verison v1 x64-irsa   # or --addons, or --addon=true
Generating test files...
Test files generated successfully
Cleaning up...
$ echo $?
0

In CI that's a green integration-tests check on a build where the suite never ran. The =-joined form (--addon-version=v1) hits this too, since the case only handles the space-separated form.

This state was unreachable before — adding flags is what makes it easy to hit. Rejecting unknown options here is half the fix:

Suggested change
*)
REMAINING_ARGS+=("$1")
shift
;;
-*)
echo "Error: unknown option: $1" >&2
exit 1
;;
*)
REMAINING_ARGS+=("$1")
shift
;;

The other half is an else on the dispatch chain (L137) that errors on an unrecognized target, e.g. else echo "Error: unknown target: $1" >&2; exit 1; fi.

Comment thread tests/run-tests.sh
Comment on lines +65 to +68
if [[ -n "$ADDON_VERSION" && "$INSTALL_METHOD" != "addon" ]]; then
echo "Error: --addon-version requires --addon" >&2
exit 1
fi

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.

🟡 This reads the ambient environment, not just the flags parsed above.

Neither variable is initialized before the loop, so inherited values are indistinguishable from flags:

  • ADDON_VERSION exported in the caller's shell, no --addon → this block exit 1s. Because it sits before the clean branch at L70, that kills ./run-tests.sh clean x64-irsa — i.e. .github/workflows/integ.yml:135, the if: always() step whose only job is deleting the EKS cluster and the secrets/parameters after a failed run. A stray env var turns an ordinary test failure into a leaked 3-node cluster plus secrets in two regions.
  • INSTALL_METHOD=addon inherited → the untouched CI invocation ./run-tests.sh x64-irsa silently takes the addon path with no flag and no log line.

Fix is to parse into locals and export only what the flags actually set:

Suggested change
if [[ -n "$ADDON_VERSION" && "$INSTALL_METHOD" != "addon" ]]; then
echo "Error: --addon-version requires --addon" >&2
exit 1
fi
if [[ -n "$addon_version" && "$install_method" != "addon" ]]; then
echo "Error: --addon-version requires --addon" >&2
exit 1
fi
export INSTALL_METHOD="$install_method"
[[ -n "$addon_version" ]] && export ADDON_VERSION="$addon_version"

(with install_method= / addon_version= initialized before the loop and the case arms assigning those instead of exporting). Moving the check after the clean branch would also keep cleanup reachable regardless.

Minor, optional: --addon-version X has exactly one meaning, so having that arm also set addon mode would let this validation block go away entirely.

Comment on lines +235 to +238
return f""" if [[ -z "${{POD_IDENTITY_ROLE_ARN}}" ]]; then
echo "Error: POD_IDENTITY_ROLE_ARN is not set" >&2
return 1
fi

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.

🟡 Good check, but it fires ~15-20 minutes and one EKS cluster too late.

This lands at the {{AUTH_SETUP}} substitution point, which is integration.bats.template:69inside setup_file, after create-secrets (L54) and after eksctl create cluster --nodes 3 (L62-67). Every other required-env guard (PRIVREPO, GITHUB_ACTOR, GITHUB_TOKEN, template L24-44) is deliberately at file scope so it aborts before any AWS call.

So ./run-tests.sh x64-pod-identity with the var unset (local run, or a fork where secrets.POD_IDENTITY_ROLE_ARN is empty) first creates the secrets/parameters in two regions, then waits out a full 3-node cluster build, and only then prints the error. Cluster reclamation then depends on teardown_file running after a failed setup_file; in CI the if: always() cleanup step covers it, locally nothing does.

Since auth_type is already known at generation time, this belongs in the template's guard block instead — e.g. a {{REQUIRED_ENV_GUARD}} substitution alongside {{AUTH_SETUP}}, or a plain gate in the template:

if [[ "{{AUTH_TYPE}}" == "pod-identity" && -z "${POD_IDENTITY_ROLE_ARN}" ]]; then
	echo "Error: POD_IDENTITY_ROLE_ARN is not specified" >&2
	return 1
fi

That also gets the shell out of the f-string (no ${{...}} brace-doubling to reason about) and keeps all env validation in one greppable place. Two nits if it stays here: the new block is tab-indented while the adjacent generated eksctl lines use 4 spaces, and the message says "is not set" where the existing guards say "is not specified".

Comment on lines +1 to +8
secrets-store-csi-driver:
enableSecretRotation: true
rotationPollInterval: "15s"
syncSecret:
enabled: true
tokenRequests:
- audience: "sts.amazonaws.com"
- audience: "pods.eks.amazonaws.com"

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.

🟡 Two things worth pinning down here.

1. Add install: true explicitly. This file is the only thing configuring the driver in addon mode, but it never asserts the driver is installed at all — that depends on the published add-on's baked-in default for the secrets-store-csi-driver.install condition (charts/.../Chart.yaml:11-15). Making it explicit costs nothing and turns an inherited assumption into a stated one:

Suggested change
secrets-store-csi-driver:
enableSecretRotation: true
rotationPollInterval: "15s"
syncSecret:
enabled: true
tokenRequests:
- audience: "sts.amazonaws.com"
- audience: "pods.eks.amazonaws.com"
secrets-store-csi-driver:
install: true
enableSecretRotation: true
rotationPollInterval: "15s"
syncSecret:
enabled: true
tokenRequests:
- audience: "sts.amazonaws.com"
- audience: "pods.eks.amazonaws.com"

Related: EKS validates --configuration-values against the schema from DescribeAddonConfiguration and rejects unknown keys, so if the published add-on doesn't expose secrets-store-csi-driver.*, create-addon fails with InvalidParameterException after the cluster is already up. A quick aws eks describe-addon-configuration --addon-name aws-secrets-store-csi-driver-provider --addon-version <v> would confirm this file's shape against the real schema — cheap to check, and it's the assumption the whole addon path rests on.

2. Drift risk (follow-up, not this PR). All five settings now exist in two syntaxes with nothing linking them: this YAML and the --set chain at integration.bats.template:87. The tokenRequests pair is also already declared verbatim in charts/secrets-store-csi-driver-provider-aws/values.yaml. The rotation tests hard-wire wait_for_process 240 5 against the 15s poll interval, so bumping it in one place and not the other makes the two lanes exercise different driver configs — a rotation test that passes in one mode and fails in the other for a config reason that looks like a product regression. This is @simonmarty's earlier suggestion (install the driver as a Helm dependency of the provider chart so both flows share one config source); agreed it's a follow-up.

The tokenRequests shape itself is correct — a list of two single-key maps is exactly what --set tokenRequests[0].audience=... tokenRequests[1].audience=... produces.

Comment thread tests/README.md
Comment on lines +51 to +54
To install the provider as an EKS managed addon instead of via Helm, use the `--addon` flag. This does not require `PRIVREPO`, `GITHUB_ACTOR`, or `GITHUB_TOKEN`.

- `./run-tests.sh --addon x64-irsa` will install the provider as an EKS addon and run x64 IRSA tests
- `./run-tests.sh --addon --addon-version v2.2.2-eksbuild.2 x64-irsa` will install a specific addon version

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.

🟡 Three doc accuracy issues.

  1. "does not require PRIVREPO" is not true as shipped — integration.bats.template:346-351 (and teardown() at L396-401) still consume $PRIVREPO, $PRIVTAG and ghcr-secret with no addon guard. Someone following these instructions gets a failed run. Accurate once the guards from my comment on L134 are added.

  2. --addon x64-pod-identity still needs POD_IDENTITY_ROLE_ARN, and as of this PR that's a hard failure rather than a downstream error (generate-test-files.py:236). Worth saying so here, since the section reads as "addon mode needs fewer env vars".

  3. Worth stating what --addon does and doesn't validate. aws eks create-addon has no image override, so this path exercises whatever provider image the published add-on ships — not the build from the branch under test. That makes it a release/packaging test, and it can't substitute for the Helm job. Without that caveat a reader could reasonably assume a green --addon run validated their change.

Also, the example pins v2.2.2-eksbuild.2 while the chart is at 3.1.2; a current version (or a note that --addon-version is optional and defaults to whatever EKS resolves) would age better.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants