Skip to content
This repository was archived by the owner on Sep 9, 2026. It is now read-only.

OSAC-1992: read tier definitions and backend credentials from AAP extra_vars - #455

Closed
wgordon17 wants to merge 22 commits into
osac-project:mainfrom
wgordon17:feat/OSAC-1992-aap-tier-extra-vars
Closed

wgordon17 wants to merge 22 commits into
osac-project:mainfrom
wgordon17:feat/OSAC-1992-aap-tier-extra-vars

Conversation

@wgordon17

@wgordon17 wgordon17 commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Replaces the STORAGE_TIERS env var and storage-operations-ig VAST admin credentials with ansible_eda.event.storage_tier_definitions/storage_backend_connections extra_vars populated by osac-operator's new Tier API integration, absorbing OSAC-1957's outstanding AAP-side AC
  • Centralizes qos_policy derivation in the storage_provider role so every caller gets consistent naming without duplicating the logic
  • Wraps AAP-discovered tier/backend capability-mismatch checks (unsupported protocol, ambiguous/unresolved/incomplete backend connections) in structured set_stats failure artifacts, additive scaffolding for a future osac-operator consumer to attribute job failures to a specific StorageTier/StorageBackend

Summary by CodeRabbit

  • New Features
    • Storage provisioning/teardown is now event-driven via storage_tier_definitions and per-backend_id storage_backend_connections.
    • Quotas use quota_bytes; QoS policy is always derived from the tier name.
    • Storage tier dispatch supports per-provider filtering, with stricter protocol validation and snapshot handling via live VolumeSnapshot CRD detection.
  • Bug Fixes
    • Improved fail-fast validation and structured failure reporting for invalid inputs and credential/backend issues.
  • Documentation
    • Updated provider docs, templates, and example payload/configs for the event-driven model.
  • Tests
    • Expanded dispatcher and integration coverage for new validation, filtering, and credential/snapshot scenarios.

wgordon17 added 14 commits July 29, 2026 10:34
…aybooks

Signed-off-by: Will Gordon <wgordon@redhat.com>
Assisted-by: Claude Code <noreply@anthropic.com>
…playbooks

Signed-off-by: Will Gordon <wgordon@redhat.com>
Assisted-by: Claude Code <noreply@anthropic.com>
Signed-off-by: Will Gordon <wgordon@redhat.com>
Assisted-by: Claude Code <noreply@anthropic.com>
…instance tier lookup

Signed-off-by: Will Gordon <wgordon@redhat.com>
Assisted-by: Claude Code <noreply@anthropic.com>
Signed-off-by: Will Gordon <wgordon@redhat.com>
Assisted-by: Claude Code <noreply@anthropic.com>
…rbing OSAC-1957

Signed-off-by: Will Gordon <wgordon@redhat.com>
Assisted-by: Claude Code <noreply@anthropic.com>
Signed-off-by: Will Gordon <wgordon@redhat.com>
Assisted-by: Claude Code <noreply@anthropic.com>
…key mismatch

Assisted-by: Claude Code <noreply@anthropic.com>
Signed-off-by: Will Gordon <wgordon@redhat.com>
Assisted-by: Claude Code <noreply@anthropic.com>
Signed-off-by: Will Gordon <wgordon@redhat.com>
… infra

Assisted-by: Claude Code <noreply@anthropic.com>
Signed-off-by: Will Gordon <wgordon@redhat.com>
…ig template

Assisted-by: Claude Code <noreply@anthropic.com>
Signed-off-by: Will Gordon <wgordon@redhat.com>
storage_provider_max_tiers has no consumer anywhere in tasks/main.yaml --
the validation it once guarded was deleted in 77cdf99 without updating
this test, leaving it asserting on nonexistent behavior since 2026-05-17.
No layer above AAP (fulfillment-service API, osac-operator) enforces a
tier-count ceiling either, so reintroducing an AAP-only check would be
an arbitrary, unbacked limit rather than a real product constraint.

Assisted-by: Claude Code <noreply@anthropic.com>
Signed-off-by: Will Gordon <wgordon@redhat.com>
qos_limits README description didn't mention that a tier with
qos_limits.static_limits present but both bandwidth fields zero (or
unset) also opts out of qos_policy defaulting -- same as omitting
qos_limits entirely. Clarified to match the actual condition in
storage_provider/tasks/main.yaml.

Assisted-by: Claude Code <noreply@anthropic.com>
Signed-off-by: Will Gordon <wgordon@redhat.com>
…backend misconfigurations

Wraps four fail-hard checks -- unsupported protocol in vast_storage/setup.yaml,
and three backend-connection-resolution checks in read_credentials.yaml
(ambiguous backend association, unresolved backend connection, incomplete
backend connection) -- in block/rescue so each also computes a structured
osac_storage_provider_failures list (reason, tiers, backend_ids, message) via
set_fact and emits it via ansible.builtin.set_stats before re-raising the
original human-readable message unchanged. Nothing reads these artifacts yet --
additive scaffolding for a future osac-operator consumer to parse AAP Job API
artifacts and attribute a job failure to a specific StorageTier/StorageBackend.

Assisted-by: Claude Code <noreply@anthropic.com>
Signed-off-by: Will Gordon <wgordon@redhat.com>
@openshift-ci-robot

openshift-ci-robot commented Jul 29, 2026

Copy link
Copy Markdown

@wgordon17: This pull request references OSAC-1992 which is a valid jira issue.

Warning: The referenced jira issue has an invalid target version for the target branch this PR targets: expected the story to target the "5.0.0" version, but no target version was set.

Details

In response to this:

Summary

  • Replaces the STORAGE_TIERS env var and storage-operations-ig VAST admin credentials with ansible_eda.event.storage_tier_definitions/storage_backend_connections extra_vars populated by osac-operator's new Tier API integration, absorbing OSAC-1957's outstanding AAP-side AC
  • Centralizes qos_policy derivation in the storage_provider role so every caller gets consistent naming without duplicating the logic
  • Wraps AAP-discovered tier/backend capability-mismatch checks (unsupported protocol, ambiguous/unresolved/incomplete backend connections) in structured set_stats failure artifacts, additive scaffolding for a future osac-operator consumer to attribute job failures to a specific StorageTier/StorageBackend

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the openshift-eng/jira-lifecycle-plugin repository.

@openshift-ci

openshift-ci Bot commented Jul 29, 2026

Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: wgordon17
Once this PR has been reviewed and has the lgtm label, please assign akshaynadkarni for approval. For more information see the Code Review Process.

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@coderabbitai

coderabbitai Bot commented Jul 29, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository: osac-project/coderabbit/.coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 45c92da1-32e4-408c-a823-c3d6b9fc5673

📥 Commits

Reviewing files that changed from the base of the PR and between f88bf3f and 4bcd144.

📒 Files selected for processing (1)
  • collections/ansible_collections/osac/service/roles/common/tasks/show_eda_event_metadata.yaml

Walkthrough

Storage provisioning now consumes event-supplied tier definitions and backend connections, derives QoS policies, resolves VAST credentials by backend ID, validates provider inputs, redacts EDA event logging, detects snapshot CRDs, and expands unit and integration coverage.

Changes

Storage provider event-driven provisioning

Layer / File(s) Summary
Event-supplied tier and backend inputs
playbook_osac_*.yml, config/base/*storage-operations-ig-example.yaml, samples/*, collections/.../storage_provider/meta/*, collections/.../templates/README.md, tests/integration/integration_config.yml.template, collections/.../roles/aap/templates/*.j2
Inputs now use event-supplied tier definitions and backend connection mappings instead of environment-sourced tiers and credentials.
Tier normalization and QoS derivation
collections/.../storage_provider/tasks/main.yaml, collections/.../storage_provider/tasks/_dispatch_provider.yaml
Caller-supplied QoS policies are discarded, derived policies are validated, and provider-specific tiers receive backend connections.
VAST backend credential resolution
collections/.../vast_storage/defaults/main.yaml, collections/.../vast_storage/tasks/read_credentials.yaml
Credentials are resolved and validated from backend IDs, with namespace fallback resolution updated.
VAST validation and execution
collections/.../vast_storage/tasks/*
Protocol validation is shared, quotas use quota_bytes, and snapshot creation uses live CRD detection with the enable flag.
Event validation and redacted logging
playbook_osac_*.yml, collections/.../common/tasks/show_eda_event_metadata.yaml, .claude/rules/playbook-patterns.md
Playbooks require valid event tier arrays and log allowlisted metadata instead of full payloads.
Test coverage
collections/.../storage_provider/tests/test.yml, tests/integration/*, tests/integration/targets/storage_provider_*/*
Tests cover validation, derived QoS, backend failures, event wiring, credential migration, dispatcher execution, and snapshot-disabled provisioning.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant EDAEvent
  participant StoragePlaybook
  participant StorageProviderRole
  participant DispatchedVASTRole
  participant BackendConnections
  EDAEvent->>StoragePlaybook: tier definitions and backend connections
  StoragePlaybook->>StorageProviderRole: provider tiers and connections
  StorageProviderRole->>DispatchedVASTRole: normalized tiers and backend mappings
  DispatchedVASTRole->>BackendConnections: resolve endpoint and credentials
  DispatchedVASTRole->>DispatchedVASTRole: validate protocols, quotas, and snapshots
Loading

Possibly related PRs

  • osac-project/osac-aap#296: Refactors the storage provider dispatcher and VAST backend credential-resolution implementation used by this change.
  • osac-project/osac-aap#377: Also modifies the storage provider dispatcher’s included-role invocation and variable forwarding.

Suggested labels: lgtm, approved

Suggested reviewers: akshaynadkarni, zszabo-rh

🚥 Pre-merge checks | ✅ 11
✅ Passed checks (11 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: sourcing tier definitions and backend credentials from AAP extra vars instead of environment variables.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
No-Hardcoded-Secrets ✅ Passed No hardcoded real secrets found: added values are env-var placeholders or mock/default test creds (incl. admin/admin examples); no embedded creds, keys, or long blobs.
No-Weak-Crypto ✅ Passed No MD5/SHA1/DES/RC4/3DES/Blowfish/ECB or custom crypto in changed files; only RSA 2048 test setup, which is exempt.
No-Injection-Vectors ✅ Passed Modified files add validation/redaction only; no shell/eval/os.system/yaml.load/pickle.loads/dangerous HTML sinks or SQL concat found.
Container-Privileges ✅ Passed No changed K8s/container manifests add privileged, hostPID/Network/IPC, allowPrivilegeEscalation:true, SYS_ADMIN, or root settings; existing hook securityContexts disable escalation and drop all caps.
No-Sensitive-Data-In-Logs ✅ Passed PASS: full-payload debug was replaced with metadata-only logging; credential facts use no_log, and no task logs passwords/tokens/hostnames.
Ai-Attribution ✅ Passed PR-only commits use Assisted-by: Claude Code trailers and contain no AI-related Co-Authored-By entries.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

- Add the missing closed-set protocol check to ensure_storage_class
  (the dominant cluster-storage action), factored into a shared
  _validate_tier_protocols.yaml so setup and ensure_storage_class
  can't drift out of sync again
- Replace the STORAGE_SNAPSHOTS_ENABLED env var with a set_fact
  computed unconditionally from the existing live VolumeSnapshot CRD
  check, removing the now-dead toggle from argument_specs, 3
  playbooks, the example ConfigMap, and 5 test fixtures
- Make qos_policy fully system-derived: any caller-supplied value is
  discarded and ignored (never validated or preserved), consistent
  with how every other field outside this role's schema is already
  treated
- Wrap the missing-backend_id check in the same block/rescue +
  set_stats structured-failure pattern as its three sibling
  backend-connection checks
- Delete the dead _requested_tiers filtering branch in
  _dispatch_provider.yaml -- no caller ever wired it up, and
  playbook_osac_create_compute_instance.yml already solves
  single-tier filtering its own way
- Remove OSAC_STORAGE_CONFIG_NAMESPACE's redundant, non-functional
  env var injection in favor of reading the standard Kubernetes
  service-account namespace file directly; the documented
  ConfigMap-based override can now actually take effect
- Add message field assertions to 3 structured-failure tests that
  were only checking reason/tiers/backend_ids, plus new tests for
  the missing-backend_id artifact, protocol validation via
  ensure_storage_class, and the real reachable empty-string/
  UNSPECIFIED protocol case
- Wire the storage_provider dispatcher unit tests into CI via
  run_tests.sh (previously only run manually)

Assisted-by: Claude Code <noreply@anthropic.com>
Signed-off-by: Will Gordon <wgordon@redhat.com>
Full-branch self-review (independent subagent, commit 51db654) found no
CRITICAL/HIGH findings. Fixes three LOW-severity items: removes now-inert
qos_policy example values from two integration fixtures (the role always
derives qos_policy from the tier name and discards any caller-supplied
value, so these were misleading), and disambiguates the duplicate "Validate
tier protocols are supported by VAST provider" task name shared between the
two include_tasks call sites and the shared _validate_tier_protocols.yaml
file itself.

Assisted-by: Claude Code <noreply@anthropic.com>
Signed-off-by: Will Gordon <wgordon@redhat.com>
@wgordon17
wgordon17 marked this pull request as ready for review July 30, 2026 01:42
Addresses the No-Sensitive-Data-In-Logs pre-merge check failure.

storage_provider_block_encryption_passphrase is read from
ansible_eda.event.payload.spec.blockEncryptionPassphrase in
playbook_osac_create_tenant_cluster_storage.yml,
playbook_osac_create_tenant_storage_backend.yml, and
playbook_osac_create_compute_instance.yml -- a real secret nested inside
.payload itself, unlike storage_tier_definitions/storage_backend_connections
which arrive as siblings of .payload. All three playbooks' "Show EDA Event"
pre-task unconditionally debugged the whole payload object, which prints
that passphrase in cleartext to the job log.

Replaced the blanket payload debug with an explicit metadata allowlist
(kind, name, namespace, uid, plus the tenant annotation or templateID each
playbook already relies on) in those three playbooks, and in the two
delete-side sibling playbooks for consistency, since they share the same
convention even though they don't currently read blockEncryptionPassphrase.

Verified: ansible-lint clean, and confirmed live (with a real secret string
injected via -e) that the new debug task prints only the allowlisted fields
in all three affected create playbooks -- the injected secret does not
appear anywhere in the log output, including in the ClusterOrder-payload
and ComputeInstance-payload variants which have different metadata shapes.

Assisted-by: Claude Code <noreply@anthropic.com>
Signed-off-by: Will Gordon <wgordon@redhat.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
playbook_osac_create_compute_instance.yml (1)

48-63: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Reject malformed optional tier definitions before filtering.

A defined string or mapping reaches selectattr before storage_provider can enforce its required-list contract, producing a misleading “tier not found” path or skipped provisioning. Validate that a defined value is a non-string, non-mapping sequence before Line 49.

Proposed fix
+    - name: Validate optional storage_tier_definitions type
+      ansible.builtin.fail:
+        msg: ansible_eda.event.storage_tier_definitions must be an array when provided.
+      when: >-
+        ansible_eda.event.storage_tier_definitions is defined and
+        (ansible_eda.event.storage_tier_definitions is not sequence or
+         ansible_eda.event.storage_tier_definitions is string or
+         ansible_eda.event.storage_tier_definitions is mapping)
+
     - name: Filter storage tier definitions to the requested tier for JIT storage
🤖 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 `@playbook_osac_create_compute_instance.yml` around lines 48 - 63, The JIT
storage tier filtering block must reject malformed storage_tier_definitions
before selectattr runs. Add validation before the block’s filtering task so any
defined value is a non-string, non-mapping sequence, preserving the existing
empty/default behavior and preventing invalid input from reaching
_jit_storage_tiers filtering.
🤖 Prompt for all review comments with 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.

Inline comments:
In `@playbook_osac_create_compute_instance.yml`:
- Around line 15-25: Centralize the EDA payload-redaction policy by introducing
or reusing a shared redacted event logger, then replace the local “Show EDA
Event” allowlists in playbook_osac_create_compute_instance.yml (lines 15-25),
playbook_osac_create_tenant_cluster_storage.yml (lines 27-37),
playbook_osac_create_tenant_storage_backend.yml (lines 12-21),
playbook_osac_delete_tenant_cluster_storage.yml (lines 25-35), and
playbook_osac_delete_tenant_storage_backend.yml (lines 11-20). Ensure the shared
sanitizer preserves required event metadata while excluding sensitive fields
such as storage_provider_block_encryption_passphrase, and apply the same logging
convention repo-wide rather than maintaining storage-specific policies.

---

Outside diff comments:
In `@playbook_osac_create_compute_instance.yml`:
- Around line 48-63: The JIT storage tier filtering block must reject malformed
storage_tier_definitions before selectattr runs. Add validation before the
block’s filtering task so any defined value is a non-string, non-mapping
sequence, preserving the existing empty/default behavior and preventing invalid
input from reaching _jit_storage_tiers filtering.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository: osac-project/coderabbit/.coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 6effbe6d-ed0b-4a99-baf4-86ca0c3cd26f

📥 Commits

Reviewing files that changed from the base of the PR and between 2331b3f and 70ca0dd.

📒 Files selected for processing (9)
  • playbook_osac_create_compute_instance.yml
  • playbook_osac_create_tenant_cluster_storage.yml
  • playbook_osac_create_tenant_storage_backend.yml
  • playbook_osac_delete_tenant_cluster_storage.yml
  • playbook_osac_delete_tenant_storage_backend.yml
  • samples/storage_tier_definitions_payload.json
  • tests/integration/integration_config.yml.template
  • tests/integration/targets/storage_provider_ensure_sc/tasks/main.yml
  • tests/integration/targets/storage_provider_teardown/tasks/main.yml

Comment thread playbook_osac_create_compute_instance.yml
Addresses the 2 remaining findings from CodeRabbit's round-4 review.

- Centralize the EDA payload-redaction policy: rather than 5 separate
  copy-pasted metadata allowlists, added
  osac.service.common/tasks/show_eda_event_metadata.yaml as the single
  shared implementation. It always logs kind/name/namespace/uid and
  accepts an optional eda_event_extra_fields dict for the one extra
  non-sensitive field each playbook needs (tenant_annotation or
  template_id). All 5 storage playbooks now call this shared task via
  include_role instead of inlining their own debug block. Documented
  the convention in .claude/rules/playbook-patterns.md so future
  playbooks reading a sensitive payload.spec field use the shared task
  from the start instead of the bare "debug: var: payload" example.
  A full repo-wide migration of every other playbook's existing debug
  task is a separate, larger initiative than this PR's scope -- this
  centralizes the actual redaction logic in one place and gives new
  playbooks the correct pattern by default.

- playbook_osac_create_compute_instance.yml treats
  storage_tier_definitions as optional (JIT-provisioning path only)
  and wasn't type-checked before selectattr, unlike the 4 other
  playbooks that require it and already validate. Added the same
  non-sequence/string/mapping rejection, gated on "is defined" since
  omitting the field entirely is valid here.

Verified: ansible-lint clean repo-wide, --syntax-check on all 5
playbooks, and live -e runs (with injected fake secrets) confirming:
the shared task renders the same redacted metadata as before with no
secret leakage in any of the Tenant/ClusterOrder/ComputeInstance
payload shapes; the new type-check rejects a malformed string value
with a clear message; and omitting storage_tier_definitions entirely
still skips cleanly with no regression to existing behavior.

Assisted-by: Claude Code <noreply@anthropic.com>
Signed-off-by: Will Gordon <wgordon@redhat.com>
@akshaynadkarni
akshaynadkarni requested review from akshaynadkarni and zszabo-rh and removed request for eliorerz and tzvatot July 30, 2026 18:08
@wgordon17

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 30, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
playbook_osac_delete_tenant_cluster_storage.yml (1)

81-86: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Pass backend connections into cluster teardown.

This call passes storage_provider_tiers but omits storage_provider_backend_connections, leaving the provider role without the event-supplied credentials needed to resolve each tier’s backend_id. VAST cluster cleanup can therefore fail when it attempts credential resolution.

Proposed fix
         storage_provider_action: teardown_cluster_storage
         storage_provider_tiers: "{{ ansible_eda.event.storage_tier_definitions }}"
+        storage_provider_backend_connections: "{{ ansible_eda.event.storage_backend_connections | default({}) }}"
🤖 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 `@playbook_osac_delete_tenant_cluster_storage.yml` around lines 81 - 86, Update
the “Clean up cluster-side tenant storage resources” include_role task to pass
ansible_eda.event.storage_provider_backend_connections through the
storage_provider_backend_connections variable alongside storage_provider_tiers,
so teardown_cluster_storage can resolve each tier’s backend_id using the
event-supplied credentials.
🤖 Prompt for all review comments with 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.

Inline comments:
In
`@collections/ansible_collections/osac/service/roles/common/tasks/show_eda_event_metadata.yaml`:
- Around line 15-25: Update the “Show EDA Event metadata” task to enforce an
explicit allowlist for eda_event_extra_fields, permitting only approved safe
fields and excluding arbitrary nested payload or credential data. Ensure the
fixed kind, name, namespace, and uid metadata is merged last so callers cannot
overwrite it; do not log the unfiltered dictionary.

---

Outside diff comments:
In `@playbook_osac_delete_tenant_cluster_storage.yml`:
- Around line 81-86: Update the “Clean up cluster-side tenant storage resources”
include_role task to pass ansible_eda.event.storage_provider_backend_connections
through the storage_provider_backend_connections variable alongside
storage_provider_tiers, so teardown_cluster_storage can resolve each tier’s
backend_id using the event-supplied credentials.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository: osac-project/coderabbit/.coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 6259dd45-7773-4c5b-80d0-34ae98741bdc

📥 Commits

Reviewing files that changed from the base of the PR and between 70ca0dd and f88bf3f.

📒 Files selected for processing (7)
  • .claude/rules/playbook-patterns.md
  • collections/ansible_collections/osac/service/roles/common/tasks/show_eda_event_metadata.yaml
  • playbook_osac_create_compute_instance.yml
  • playbook_osac_create_tenant_cluster_storage.yml
  • playbook_osac_create_tenant_storage_backend.yml
  • playbook_osac_delete_tenant_cluster_storage.yml
  • playbook_osac_delete_tenant_storage_backend.yml

…elds

Addresses the round-5 CodeRabbit finding on the shared redaction task itself.

combine(eda_event_extra_fields | default({})) merged the caller-supplied
dict on top of the fixed metadata with no restriction on its keys: a
careless future caller could overwrite kind/name/namespace/uid, or pass
something like the whole payload.spec as an "extra field" and defeat the
entire point of centralizing redaction in this task.

Added an explicit allowlist (tenant_annotation, template_id -- the only
two keys any current caller uses) that fails loudly if
eda_event_extra_fields contains anything else, and reversed the combine
order so the fixed metadata is merged last and always wins regardless.
Adding a new extra field now requires deliberately updating the allowlist
in this one file, keeping it the single actual enforcement point rather
than a convention callers could accidentally bypass.

Verified: ansible-lint clean, confirmed the normal cases still render
correctly (no extra fields, and the tenant_annotation/template_id cases
used by the 5 real playbooks), and confirmed both attack scenarios from
the review are now rejected with a clear error: a disallowed key
("leaked_secret") and an attempt to override a fixed key ("name") both
fail at the new validation task before anything is logged.

Assisted-by: Claude Code <noreply@anthropic.com>
Signed-off-by: Will Gordon <wgordon@redhat.com>
@wgordon17

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 30, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@zszabo-rh zszabo-rh 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.

One minor concern noted inline, otherwise the changes LGTM! (👍🏻ᴗ _ᴗ)👍🏻

STORAGE_TIERS env var contains invalid JSON.
Value: '{{ _storage_tiers_raw }}'.
Expected a JSON array of tier objects with name, protocol, and provider fields.
- name: Validate storage_tier_definitions is a non-empty array in the EDA event

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.

I'm not sure about this is really necessary here.. missing tier definitions on creation is definitely a real misconfiguration but for teardown this may be too strict.
Not asking for a full change, just consider whether this should be warn + skip rather than fail when storage_tier_definitions is absent on the delete path.

storage_provider_action: ensure_storage_class
storage_provider_tiers: "{{ _jit_storage_tiers }}"
storage_provider_backend_connections: "{{ ansible_eda.event.storage_backend_connections | default({}) }}"
storage_provider_provisioning_target: vmaas

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:
Is this being used? Are there plans to use this in the future for caas, bmaas etc.?

success_msg: "Role correctly rejected invalid input"

# ──────────────────────────────────────────────────────────────
# Test 9: Invalid DNS label tier name -- error path

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: Test comments jump from 7 to 9 to 11 (missing 8, 10). Likely from removed scenarios during iteration. Perhaps we can skip numbering.

# store. Tests that assert on the call log or pre-seed VMS resources cannot
# run in parallel without cross-contamination. Run all sequentially — each
# test takes ~7s so the total overhead is negligible.
STORAGE_TESTS=(

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: The STORAGE_TESTS targets (storage_provider_setup, storage_provider_ensure_sc, etc.) are VAST-specific end-to-end: they hardcode provider: vast, assert vast-* resource names, and require the mock VMS server. When a second provider lands (e.g. PURE, LVMS), these names will be ambiguous.

Should we add a prefix or a vast/ sub-directory?
WDYT?

block:
- name: "Include provider storage role"
ansible.builtin.include_role:
name: "osac.templates.{{ _current_provider }}_storage"

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: Today this dispatch loop is only exercised with a single provider (vast) in tests. Once LVMS lands (cc @zszabo-rh ), can we add a test with tiers spanning two providers? WDYT?

Comment on lines 323 to +326
- name: Create VolumeSnapshotClass per tier
when: >-
(storage_provider_snapshots_enabled | default(true)) and
(_vast_vsc_crd_check.resources | default([]) | length > 0)
when:
- _vast_snapshot_crd_available | bool
- storage_provider_snapshots_enabled | default(true) | bool

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.

question: storage_provider_snapshots_enabled defaults to true, meaning every ensure_storage_class call creates a VolumeSnapshotClass per tier alongside the StorageClass. Two questions:

  1. Are there side effects to creating VolumeSnapshotClasses by default?
    e.g., does the VAST CSI driver need additional RBAC or a specific version to handle snapshot operations, and what happens if a user tries to create a VolumeSnapshot on a cluster where the driver doesn't support it?

  2. This parameter isn't declared in storage_provider/meta/argument_specs.yaml, so consumers of the role won't know it exists unless they read the task file. Perhaps you can add it for completeness.

Comment on lines 32 to 33
- secretRef:
name: storage-operations-ig

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.

question: After this PR the Secret has no credential fields left, but the secretRef is still required (no optional: true). The compute-instance IG already marks it optional. Should this match the compute-instance IG?

I am not seeing a reason to keep it required, for now. WDYT?

@wgordon17

wgordon17 commented Aug 2, 2026

Copy link
Copy Markdown
Contributor Author

This PR has been migrated to the new osac mono-repo as osac-project/osac#99, following Elior Erez's guidance in #wg-osac-eng (2026-07-31) that open PR authors should port their work to osac-project/osac now that osac-aap has merged upstream (OSAC-1732).

This is a migration, not an abandonment — the full 22-commit history and review thread remain here for reference.

Review findings addressed in the new PR:

@akshaynadkarni @zszabo-rh — here is the status of each substantive item from round 6:

  1. argument_specs entry (storage_provider_snapshots_enabled) — Fixed. Added to storage_provider/meta/argument_specs.yaml (type bool, default true). The VolumeSnapshotClass CRD live-check already gates creation regardless of this flag, so no real side effect exists — this is a documentation-completeness fix only.

  2. secretRef optionality (storage-operations-ig.j2) — Fixed. Marked optional: true to match compute-instance-operations-ig.j2. The Secret has no credential fields remaining (credentials now sourced via storage_backend_connections extra_vars from osac-operator), no consumer reads from it, and no fallback to broader-access credentials exists. An inline comment in the template references the credential-isolation decision.

  3. Teardown warn-vs-fail (playbook_osac_delete_tenant_cluster_storage.yml) — Retained as-is after research. Warn+skip would let osac-operator mark cleanup as complete when the storage_provider dispatch never ran (absent tier data means no provider routing), orphaning cluster-side StorageClasses/VolumeSnapshotClasses/CSI Secrets. The hard fail forces reconciliation retry, which is correct since the only production case for absent tier data is a transient Tier API failure.

The 4 forward-looking nits (CaaS/BMaaS field usage, multi-provider test layout, multi-provider dispatch test, test-comment numbering) are carried into the new PR's description for continuity.

@wgordon17 wgordon17 closed this Aug 2, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants