Skip to content

HYPERFLEET-720 - fix: update adapter configs#40

Open
rh-amarin wants to merge 1 commit intoopenshift-hyperfleet:mainfrom
rh-amarin:align-adapter-config
Open

HYPERFLEET-720 - fix: update adapter configs#40
rh-amarin wants to merge 1 commit intoopenshift-hyperfleet:mainfrom
rh-amarin:align-adapter-config

Conversation

@rh-amarin
Copy link
Contributor

@rh-amarin rh-amarin commented Mar 6, 2026

https://issues.redhat.com/browse/HYPERFLEET-720

Updates the adapter configs for the e2e tests following the config standard

This should be merged only after merging openshift-hyperfleet/hyperfleet-adapter#67

Summary by CodeRabbit

  • Refactor
    • Converted many config keys from camelCase to snake_case and flattened configs to a unified adapter root with top-level params/payloads.
    • Reorganized broker, client, TLS, discovery, resources, manifestWork/manifest, post/status and post_actions into the new naming and structure; updated labels/annotations paths.
  • Refactor (scripts)
    • Simplified adapter discovery, install/uninstall flows with clearer logging, validation and aggregated status reporting.

@openshift-ci openshift-ci bot requested review from pnguyen44 and rafabene March 6, 2026 10:37
@openshift-ci
Copy link

openshift-ci bot commented Mar 6, 2026

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by:
Once this PR has been reviewed and has the lgtm label, please assign ciaranroche 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
Copy link

coderabbitai bot commented Mar 6, 2026

Note

Currently processing new changes in this PR. This may take a few minutes, please wait...

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: a00493a3-f6bf-45cd-9b4f-b0d1216d644c

📥 Commits

Reviewing files that changed from the base of the PR and between a2d479d and 4a2cc0f.

📒 Files selected for processing (16)
  • deploy-scripts/lib/adapter.sh
  • testdata/adapter-configs/cl-deployment/adapter-config.yaml
  • testdata/adapter-configs/cl-deployment/adapter-task-config.yaml
  • testdata/adapter-configs/cl-deployment/values.yaml
  • testdata/adapter-configs/cl-job/adapter-config.yaml
  • testdata/adapter-configs/cl-job/adapter-task-config.yaml
  • testdata/adapter-configs/cl-job/values.yaml
  • testdata/adapter-configs/cl-maestro/adapter-config.yaml
  • testdata/adapter-configs/cl-maestro/adapter-task-config.yaml
  • testdata/adapter-configs/cl-maestro/values.yaml
  • testdata/adapter-configs/cl-namespace/adapter-config.yaml
  • testdata/adapter-configs/cl-namespace/adapter-task-config.yaml
  • testdata/adapter-configs/cl-namespace/values.yaml
  • testdata/adapter-configs/np-configmap/adapter-config.yaml
  • testdata/adapter-configs/np-configmap/adapter-task-config.yaml
  • testdata/adapter-configs/np-configmap/values.yaml

Walkthrough

This pull request standardizes testdata adapter configs and task configs across many adapters by flattening CRD-like top-level structures (removing apiVersion/kind/metadata/spec), promoting params to top-level, and converting keys from camelCase to snake_case (e.g., apiCall → api_call, retryAttempts → retry_attempts, bySelectors → by_selectors, subscriptionId → subscription_id). Maestro/TLS, manifest/discovery, post/payloads, and delete options are reorganized into flatter, snake_case layouts. The deploy script (deploy-scripts/lib/adapter.sh) was refactored for clearer control flow, logging, validation, and Helm invocation handling.

Sequence Diagram(s)

mermaid
sequenceDiagram
actor Operator
participant AdapterScript as "deploy-scripts/adapter.sh"
participant Filesystem as "Filesystem (charts/config)"
participant Helm as "Helm CLI"
participant Kubernetes as "Kubernetes API"
Operator->>AdapterScript: discover_adapters()
AdapterScript->>Filesystem: scan adapter dirs
Filesystem-->>AdapterScript: adapter list
Operator->>AdapterScript: install_adapter_instance(adapter)
AdapterScript->>Filesystem: copy adapter config -> chart dir
AdapterScript->>Helm: helm upgrade --install (with values)
Helm-->>AdapterScript: helm result (success/failure)
AdapterScript->>Kubernetes: wait_for_pods_ready(namespace)
Kubernetes-->>AdapterScript: pod status
AdapterScript-->>Operator: report success/failure

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 60.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: updating adapter configuration files to follow project standards, with the JIRA reference providing context.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
📝 Coding Plan
  • Generate coding plan for human review comments

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

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@testdata/adapter-configs/nodepools-np-configmap/adapter-task-config.yaml`:
- Around line 59-60: The manifest.ref in adapter-task-config.yaml is pointing to
a developer's absolute local path; update the manifest.ref value to the
container-style path used by other adapter configs (replace the /Users/... path
with the container path pattern and filename, e.g. the in-container location of
adapter-task-resource-configmap.yaml) so the manifest references the resource
inside the container image; change the manifest.ref entry (in
adapter-task-config.yaml) to that container path.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: fe098303-7816-4831-916c-749a843de84e

📥 Commits

Reviewing files that changed from the base of the PR and between 0da91f3 and 0fcfc57.

📒 Files selected for processing (15)
  • testdata/adapter-configs/cl-maestro/adapter-config.yaml
  • testdata/adapter-configs/cl-maestro/adapter-task-config.yaml
  • testdata/adapter-configs/cl-maestro/values.yaml
  • testdata/adapter-configs/clusters-cl-deployment/adapter-config.yaml
  • testdata/adapter-configs/clusters-cl-deployment/adapter-task-config.yaml
  • testdata/adapter-configs/clusters-cl-deployment/values.yaml
  • testdata/adapter-configs/clusters-cl-job/adapter-config.yaml
  • testdata/adapter-configs/clusters-cl-job/adapter-task-config.yaml
  • testdata/adapter-configs/clusters-cl-job/values.yaml
  • testdata/adapter-configs/clusters-cl-namespace/adapter-config.yaml
  • testdata/adapter-configs/clusters-cl-namespace/adapter-task-config.yaml
  • testdata/adapter-configs/clusters-cl-namespace/values.yaml
  • testdata/adapter-configs/nodepools-np-configmap/adapter-config.yaml
  • testdata/adapter-configs/nodepools-np-configmap/adapter-task-config.yaml
  • testdata/adapter-configs/nodepools-np-configmap/values.yaml

spec:
adapter:
version: "0.1.0"
#version: "0.1.0"
Copy link
Contributor

Choose a reason for hiding this comment

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

Does this mean this version isn’t required in the configuration?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I aligned with the adapter examples making it "0.2.0"

&& resources.namespace0.statusFeedback.values.exists(v, has(v.name) && v.name == "phase" && has(v.fieldValue))
? resources.namespace0.statusFeedback.values.filter(v, v.name == "phase")[0].fieldValue.string
: "Unknown"
# Health: Adapter execution status — surfaces errors from any phase
Copy link
Contributor

Choose a reason for hiding this comment

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

Just noticed — this Health condition in cl-maestro uses the newer, richer pattern (checking executionStatus, resourcesSkipped, structured error messages with phase/step/message), but the other four adapters (cl-deployment, cl-job, cl-namespace, np-configmap) all still use the simpler version that just checks adapter.?errorReason / adapter.?errorMessage.

Is that intentional? Totally fine if cl-maestro is meant to be the reference and the others will catch up later — just want to make sure it's not an oversight since they're all being touched in the same PR anyway.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I will focus here in just the minimal changes for adapting to the new adapter config properties, we can deal with the semantics later if that is ok

@yingzhanredhat
Copy link
Contributor

As the fields format is changed, it requires to update the adapter deployment helm cmd :

helm upgrade --install

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

♻️ Duplicate comments (2)
testdata/adapter-configs/np-configmap/adapter-task-config.yaml (1)

59-60: ⚠️ Potential issue | 🔴 Critical

Replace the developer-local manifest path.

Line 60 has reverted to an absolute path from a local workstation. That will break in CI and inside the adapter container; use the in-container path pattern used by the other configs instead.

🐛 Proposed fix
     manifest:
-      ref: /Users/amarin/work/workspaces/github/hyperfleet/hyperfleet-e2e/ae2e/align-adapter-config/testdata/adapter-configs/nodepools-np-configmap/adapter-task-resource-configmap.yaml
+      ref: "/etc/adapter/configmap.yaml"
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@testdata/adapter-configs/np-configmap/adapter-task-config.yaml` around lines
59 - 60, The manifest.ref in adapter-task-config.yaml currently points to a
developer-local absolute path; change the value of manifest.ref to the
in-container relative path pattern used by other configs (e.g., the path under
the container workspace or testdata bundle) so the adapter can load the resource
in CI and inside the container; locate the manifest.ref entry in the file and
replace the absolute /Users/... path with the project-relative in-container path
used elsewhere in these configs.
testdata/adapter-configs/cl-maestro/adapter-config.yaml (1)

11-23: ⚠️ Potential issue | 🔴 Critical

Rename the Helm overrides alongside these client keys.

These settings moved to clients.hyperfleet_api.* and clients.broker.subscription_id. If deploy-scripts/lib/adapter.sh still writes the old camelCase paths, the adapter will boot with literal CHANGE_ME values for the API endpoint and broker subscription.

Verify that the deploy script now sets the snake_case keys. Expected: matches for clients.hyperfleet_api.* / clients.broker.subscription_id, and no matches for the old camelCase paths.

#!/bin/bash
set -euo pipefail

file="$(fd '^adapter\.sh$' deploy-scripts -tf | head -n1)"
[ -n "$file" ]

sed -n '150,220p' "$file"
rg -n 'clients\.hyperfleet_api\.base_url|clients\.hyperfleet_api\.retry_attempts|clients\.hyperfleet_api\.retry_backoff|clients\.broker\.subscription_id|hyperfleetApi|baseUrl|retryAttempts|retryBackoff|subscriptionId' "$file"
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@testdata/adapter-configs/cl-maestro/adapter-config.yaml` around lines 11 -
23, The deploy script deploy-scripts/lib/adapter.sh is still emitting old
camelCase config paths (e.g. hyperfleetApi, baseUrl, retryAttempts,
retryBackoff, subscriptionId); update it so the Helm/Env overrides it writes use
the new snake_case keys clients.hyperfleet_api.* and
clients.broker.subscription_id instead, removing any writes or matches for the
old camelCase names; search for occurrences of hyperfleetApi, baseUrl,
retryAttempts, retryBackoff, subscriptionId in adapter.sh and replace the output
keys/templating to emit clients.hyperfleet_api.base_url,
clients.hyperfleet_api.retry_attempts, clients.hyperfleet_api.retry_backoff and
clients.broker.subscription_id accordingly so the adapter-config.yaml receives
the correct values at deploy time.
🧹 Nitpick comments (1)
testdata/adapter-configs/cl-maestro/adapter-task-config.yaml (1)

11-14: Give the event and fetched generations different names.

generation is sourced twice from different places, so it is unclear whether observed_generation is tied to the incoming event or the fresh /clusters read. Renaming the captured field would make the intent explicit and avoid subtle drift if those values ever diverge.

♻️ Proposed refactor
-      - name: "generation"
+      - name: "clusterGeneration"
         field: "generation"

If the fetched cluster generation is the intended value, reference clusterGeneration explicitly where you need it.

Also applies to: 33-34, 291-292

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@testdata/adapter-configs/cl-maestro/adapter-task-config.yaml` around lines 11
- 14, The config currently defines a field named "generation" sourced from
event.generation which conflicts with another "generation" coming from the
fetched /clusters read; rename the event-sourced field to make intent explicit
(e.g., change name "generation" sourced from "event.generation" to
"event_generation" or "incoming_generation") and ensure the fetched cluster
value uses a distinct name (e.g., "clusterGeneration" or "observed_generation")
wherever referenced (also update the other occurrences noted at lines 33-34 and
291-292) so code that expects the fetched cluster generation can reference
clusterGeneration explicitly and avoid ambiguity.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@testdata/adapter-configs/cl-job/adapter-task-config.yaml`:
- Around line 139-157: The condition checks in the expressions are incorrectly
looking for condition.type == "Available" on resources.testJob; change these to
check for Job condition types "Complete" (for success) and "Failed" (for
failure) and update the ternary branches accordingly in the status, reason, and
message expressions (refer to resources.testJob, .status.conditions,
.filter(...) and .exists(...) usages). Specifically: replace the
existence/filter tests that use c.type == "Available" with c.type == "Complete"
for the success path, keep/ensure the failure path uses c.type == "Failed", and
adjust the reason/message text to reflect "testJobComplete"/"testJobFailed" (or
similar) and "testJob completed"/"testJob failed" while preserving the fallback
branches that use resources.?testJob.?status.hasValue() and pending defaults.

In `@testdata/adapter-configs/cl-job/values.yaml`:
- Around line 20-23: The deploy scripts pass camelCase Helm override keys that
no longer match the values file; update the Helm --set arguments in adapter.sh
and sentinel.sh to use the snake_case keys used in values.yaml (project_id,
subscription_id, topic, dead_letter_topic) instead of camelCase (e.g., change
broker.projectId -> broker.project_id, broker.subscriptionId ->
broker.subscription_id, broker.deadLetterTopic -> broker.dead_letter_topic) so
the broker config is properly injected during helm install/upgrade.

In `@testdata/adapter-configs/cl-maestro/adapter-task-config.yaml`:
- Around line 99-105: The hyperfleet.io/cluster-name annotation is using the
wrong template variable (.clusterId) causing incorrect values; update the
annotation under annotations (key hyperfleet.io/cluster-name) to use
.clusterName instead of .clusterId so it matches the captured clusterName value
used elsewhere.

---

Duplicate comments:
In `@testdata/adapter-configs/cl-maestro/adapter-config.yaml`:
- Around line 11-23: The deploy script deploy-scripts/lib/adapter.sh is still
emitting old camelCase config paths (e.g. hyperfleetApi, baseUrl, retryAttempts,
retryBackoff, subscriptionId); update it so the Helm/Env overrides it writes use
the new snake_case keys clients.hyperfleet_api.* and
clients.broker.subscription_id instead, removing any writes or matches for the
old camelCase names; search for occurrences of hyperfleetApi, baseUrl,
retryAttempts, retryBackoff, subscriptionId in adapter.sh and replace the output
keys/templating to emit clients.hyperfleet_api.base_url,
clients.hyperfleet_api.retry_attempts, clients.hyperfleet_api.retry_backoff and
clients.broker.subscription_id accordingly so the adapter-config.yaml receives
the correct values at deploy time.

In `@testdata/adapter-configs/np-configmap/adapter-task-config.yaml`:
- Around line 59-60: The manifest.ref in adapter-task-config.yaml currently
points to a developer-local absolute path; change the value of manifest.ref to
the in-container relative path pattern used by other configs (e.g., the path
under the container workspace or testdata bundle) so the adapter can load the
resource in CI and inside the container; locate the manifest.ref entry in the
file and replace the absolute /Users/... path with the project-relative
in-container path used elsewhere in these configs.

---

Nitpick comments:
In `@testdata/adapter-configs/cl-maestro/adapter-task-config.yaml`:
- Around line 11-14: The config currently defines a field named "generation"
sourced from event.generation which conflicts with another "generation" coming
from the fetched /clusters read; rename the event-sourced field to make intent
explicit (e.g., change name "generation" sourced from "event.generation" to
"event_generation" or "incoming_generation") and ensure the fetched cluster
value uses a distinct name (e.g., "clusterGeneration" or "observed_generation")
wherever referenced (also update the other occurrences noted at lines 33-34 and
291-292) so code that expects the fetched cluster generation can reference
clusterGeneration explicitly and avoid ambiguity.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 73d93cd9-a9b7-4d41-a075-9ff4b507d890

📥 Commits

Reviewing files that changed from the base of the PR and between 0fcfc57 and e696f32.

📒 Files selected for processing (15)
  • testdata/adapter-configs/cl-deployment/adapter-config.yaml
  • testdata/adapter-configs/cl-deployment/adapter-task-config.yaml
  • testdata/adapter-configs/cl-deployment/values.yaml
  • testdata/adapter-configs/cl-job/adapter-config.yaml
  • testdata/adapter-configs/cl-job/adapter-task-config.yaml
  • testdata/adapter-configs/cl-job/values.yaml
  • testdata/adapter-configs/cl-maestro/adapter-config.yaml
  • testdata/adapter-configs/cl-maestro/adapter-task-config.yaml
  • testdata/adapter-configs/cl-maestro/values.yaml
  • testdata/adapter-configs/cl-namespace/adapter-config.yaml
  • testdata/adapter-configs/cl-namespace/adapter-task-config.yaml
  • testdata/adapter-configs/cl-namespace/values.yaml
  • testdata/adapter-configs/np-configmap/adapter-config.yaml
  • testdata/adapter-configs/np-configmap/adapter-task-config.yaml
  • testdata/adapter-configs/np-configmap/values.yaml
🚧 Files skipped from review as they are similar to previous changes (1)
  • testdata/adapter-configs/cl-maestro/values.yaml

@rh-amarin rh-amarin force-pushed the align-adapter-config branch from e696f32 to beade25 Compare March 12, 2026 11:10
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

♻️ Duplicate comments (2)
testdata/adapter-configs/cl-maestro/adapter-task-config.yaml (1)

99-105: ⚠️ Potential issue | 🟡 Minor

Use clusterName for hyperfleet.io/cluster-name.

Line 104 writes the ID into the name annotation even though clusterName was captured above, so anything reading this annotation gets the wrong value.

💡 Proposed fix
-          hyperfleet.io/cluster-name: "{{ .clusterId }}"
+          hyperfleet.io/cluster-name: "{{ .clusterName }}"
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@testdata/adapter-configs/cl-maestro/adapter-task-config.yaml` around lines 99
- 105, The annotation hyperfleet.io/cluster-name currently uses "{{ .clusterId
}}" but should use the captured clusterName variable; update the annotations
block so hyperfleet.io/cluster-name is set to "{{ .clusterName }}" (replace
references to .clusterId with .clusterName) to ensure consumers read the actual
cluster name.
testdata/adapter-configs/cl-job/adapter-task-config.yaml (1)

139-157: ⚠️ Potential issue | 🔴 Critical

Derive Job availability from Complete/Failed, not Available.

Kubernetes Jobs do not publish an Available condition. This block stays "Unknown", and the downstream cl-deployment wait on cl-job availability never unblocks.

🐛 Proposed fix
           - type: "Available"
             status:
               expression: |
                 has(resources.testJob) ?
-                 ( resources.?testJob.?status.?conditions.orValue([]).exists(c, c.type == "Available")
-                  ? resources.testJob.status.conditions.filter(c, c.type == "Available")[0].status : "Unknown")
+                 ( resources.?testJob.?status.?conditions.orValue([]).exists(c, c.type == "Complete" && c.status == "True")
+                  ? "True"
+                  : resources.?testJob.?status.?conditions.orValue([]).exists(c, c.type == "Failed" && c.status == "True")
+                    ? "False"
+                    : "Unknown")
                  : "Unknown"
             reason:
               expression: |
-                resources.?testJob.?status.?conditions.orValue([]).exists(c, c.type == "Available")
-                  ? resources.testJob.status.conditions.filter(c, c.type == "Available")[0].reason
-                  : resources.?testJob.?status.?conditions.orValue([]).exists(c, c.type == "Failed") ? "testJobFailed"
-                       : resources.?testJob.?status.hasValue() ? "testJobInProgress" : "testJobPending"
+                resources.?testJob.?status.?conditions.orValue([]).exists(c, c.type == "Complete" && c.status == "True")
+                  ? "JobComplete"
+                  : resources.?testJob.?status.?conditions.orValue([]).exists(c, c.type == "Failed" && c.status == "True") ? "JobFailed"
+                       : resources.?testJob.?status.hasValue() ? "JobInProgress" : "JobPending"
             message:
               expression: |
-                resources.?testJob.?status.?conditions.orValue([]).exists(c, c.type == "Available")
-                  ? resources.testJob.status.conditions.filter(c, c.type == "Available")[0].message
-                  : resources.?testJob.?status.?conditions.orValue([]).exists(c, c.type == "Failed") ? "testJob failed"
-                       : resources.?testJob.?status.hasValue() ? "testJob in progress" : "testJob is pending"
+                resources.?testJob.?status.?conditions.orValue([]).exists(c, c.type == "Complete" && c.status == "True")
+                  ? "testJob completed successfully"
+                  : resources.?testJob.?status.?conditions.orValue([]).exists(c, c.type == "Failed" && c.status == "True") ? "testJob failed"
+                       : resources.?testJob.?status.hasValue() ? "testJob in progress" : "testJob is pending"
Does the Kubernetes Job status API expose an `Available` condition, or are the standard Job conditions `Complete` and `Failed`?
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@testdata/adapter-configs/cl-job/adapter-task-config.yaml` around lines 139 -
157, The current expressions look for a condition with type "Available" on
resources.testJob (e.g., resources.testJob.status.conditions.filter(..., c.type
== "Available")), but Kubernetes Jobs use "Complete" and "Failed"; update the
three expressions (status, reason, message) to derive availability from
conditions with type "Complete" and "Failed" instead: check for a "Complete"
condition first to return Success/complete status and message, then check for a
"Failed" condition to return failure status/reason/message (e.g., map to
"Failed"/"testJobFailed"), and otherwise fall back to an in-progress/pending
value using resources.?testJob.?status.hasValue(); keep existing use of
resources.testJob, status.conditions.orValue([]), exists(...) and filter(...)
helpers but replace comparisons to c.type == "Available" with c.type ==
"Complete" and add the analogous checks for c.type == "Failed".
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@testdata/adapter-configs/cl-deployment/values.yaml`:
- Around line 17-20: Replace all camelCase Helm keys with snake_case to match
the values.yaml: change occurrences of "projectId" to "project_id",
"subscriptionId" to "subscription_id" and "deadLetterTopic" to
"dead_letter_topic" wherever Helm --set is used in your deploy scripts (the
adapter.sh Helm --set args and the sentinel.sh Helm --set arg) and in the test
payload file that still contains camelCase; ensure the exact string replacements
are applied so Helm creates fields that match the values.yaml keys.

In `@testdata/adapter-configs/cl-maestro/adapter-task-config.yaml`:
- Around line 42-45: The fixture hardcodes placementClusterName expression to
"cluster1", which prevents routing tests from using the MAESTRO_CONSUMER
override; change the expression for the placementClusterName entry to reference
the test environment variable (e.g. use "${MAESTRO_CONSUMER}" or a parameter
placeholder) so test setup can control routing, updating the
placementClusterName mapping in the adapter-task-config.yaml (the
placementClusterName name/expression pair) accordingly.

In `@testdata/adapter-configs/np-configmap/values.yaml`:
- Around line 16-20: Update the Helm value key names used when rendering adapter
values: replace occurrences of broker.googlepubsub.projectId with
broker.googlepubsub.project_id, broker.googlepubsub.subscriptionId with
broker.googlepubsub.subscription_id, and broker.googlepubsub.deadLetterTopic
with broker.googlepubsub.dead_letter_topic so the script passes the renamed
snake_case keys from values.yaml (look for these exact key strings in
deploy-scripts/lib/adapter.sh).

---

Duplicate comments:
In `@testdata/adapter-configs/cl-job/adapter-task-config.yaml`:
- Around line 139-157: The current expressions look for a condition with type
"Available" on resources.testJob (e.g.,
resources.testJob.status.conditions.filter(..., c.type == "Available")), but
Kubernetes Jobs use "Complete" and "Failed"; update the three expressions
(status, reason, message) to derive availability from conditions with type
"Complete" and "Failed" instead: check for a "Complete" condition first to
return Success/complete status and message, then check for a "Failed" condition
to return failure status/reason/message (e.g., map to "Failed"/"testJobFailed"),
and otherwise fall back to an in-progress/pending value using
resources.?testJob.?status.hasValue(); keep existing use of resources.testJob,
status.conditions.orValue([]), exists(...) and filter(...) helpers but replace
comparisons to c.type == "Available" with c.type == "Complete" and add the
analogous checks for c.type == "Failed".

In `@testdata/adapter-configs/cl-maestro/adapter-task-config.yaml`:
- Around line 99-105: The annotation hyperfleet.io/cluster-name currently uses
"{{ .clusterId }}" but should use the captured clusterName variable; update the
annotations block so hyperfleet.io/cluster-name is set to "{{ .clusterName }}"
(replace references to .clusterId with .clusterName) to ensure consumers read
the actual cluster name.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: c6c88262-34cf-44a4-9396-f7692577e824

📥 Commits

Reviewing files that changed from the base of the PR and between e696f32 and beade25.

📒 Files selected for processing (15)
  • testdata/adapter-configs/cl-deployment/adapter-config.yaml
  • testdata/adapter-configs/cl-deployment/adapter-task-config.yaml
  • testdata/adapter-configs/cl-deployment/values.yaml
  • testdata/adapter-configs/cl-job/adapter-config.yaml
  • testdata/adapter-configs/cl-job/adapter-task-config.yaml
  • testdata/adapter-configs/cl-job/values.yaml
  • testdata/adapter-configs/cl-maestro/adapter-config.yaml
  • testdata/adapter-configs/cl-maestro/adapter-task-config.yaml
  • testdata/adapter-configs/cl-maestro/values.yaml
  • testdata/adapter-configs/cl-namespace/adapter-config.yaml
  • testdata/adapter-configs/cl-namespace/adapter-task-config.yaml
  • testdata/adapter-configs/cl-namespace/values.yaml
  • testdata/adapter-configs/np-configmap/adapter-config.yaml
  • testdata/adapter-configs/np-configmap/adapter-task-config.yaml
  • testdata/adapter-configs/np-configmap/values.yaml
🚧 Files skipped from review as they are similar to previous changes (5)
  • testdata/adapter-configs/cl-maestro/values.yaml
  • testdata/adapter-configs/cl-job/adapter-config.yaml
  • testdata/adapter-configs/cl-namespace/values.yaml
  • testdata/adapter-configs/cl-deployment/adapter-config.yaml
  • testdata/adapter-configs/np-configmap/adapter-config.yaml

@rh-amarin rh-amarin force-pushed the align-adapter-config branch from beade25 to a2d479d Compare March 13, 2026 12:59
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

♻️ Duplicate comments (2)
testdata/adapter-configs/cl-maestro/adapter-task-config.yaml (1)

42-44: ⚠️ Potential issue | 🟠 Major

Parameterize placementClusterName instead of hardcoding "cluster1"

Line 43 hardcodes the Maestro target, which makes routing behavior environment-insensitive and brittle for scenarios that expect dynamic consumer selection.

As per coding guidelines, "Focus on major issues impacting performance, readability, maintainability and security. Avoid nitpicks and avoid verbosity."

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@testdata/adapter-configs/cl-maestro/adapter-task-config.yaml` around lines 42
- 44, The placementClusterName parameter is hardcoded to "cluster1"; replace
that literal with a parameterized reference so the adapter can be configured
per-environment (update the expression for name: "placementClusterName" to read
from the template/variable/environment value rather than a fixed string), ensure
a sensible default or required flag is documented in the description, and adjust
any consuming code/templating that expects this field so it reads the new
variable-based value (look for occurrences of placementClusterName in templates
and adapter config readers to update usage).
testdata/adapter-configs/cl-job/adapter-task-config.yaml (1)

139-157: ⚠️ Potential issue | 🔴 Critical

Use Job Complete/Failed conditions; Available is invalid for Jobs

Lines 143, 148, and 154 check c.type == "Available" on a Job. That condition is not produced for Jobs, so this status can stay Unknown and block downstream adapters waiting on job readiness.

Proposed fix
           - type: "Available"
             status:
               expression: |
                 has(resources.testJob) ?
-                 ( resources.?testJob.?status.?conditions.orValue([]).exists(c, c.type == "Available")
-                  ? resources.testJob.status.conditions.filter(c, c.type == "Available")[0].status : "Unknown")
+                 ( resources.?testJob.?status.?conditions.orValue([]).exists(c, c.type == "Complete" && c.status == "True")
+                  ? "True"
+                  : resources.?testJob.?status.?conditions.orValue([]).exists(c, c.type == "Failed" && c.status == "True")
+                    ? "False"
+                    : "Unknown")
                  : "Unknown"
             reason:
               expression: |
-                resources.?testJob.?status.?conditions.orValue([]).exists(c, c.type == "Available")
-                  ? resources.testJob.status.conditions.filter(c, c.type == "Available")[0].reason
-                  : resources.?testJob.?status.?conditions.orValue([]).exists(c, c.type == "Failed") ? "testJobFailed"
-                       : resources.?testJob.?status.hasValue() ? "testJobInProgress" : "testJobPending"
+                resources.?testJob.?status.?conditions.orValue([]).exists(c, c.type == "Complete" && c.status == "True")
+                  ? "JobComplete"
+                  : resources.?testJob.?status.?conditions.orValue([]).exists(c, c.type == "Failed" && c.status == "True") ? "JobFailed"
+                       : resources.?testJob.?status.hasValue() ? "JobInProgress" : "JobPending"
             message:
               expression: |
-                resources.?testJob.?status.?conditions.orValue([]).exists(c, c.type == "Available")
-                  ? resources.testJob.status.conditions.filter(c, c.type == "Available")[0].message
-                  : resources.?testJob.?status.?conditions.orValue([]).exists(c, c.type == "Failed") ? "testJob failed"
-                       : resources.?testJob.?status.hasValue() ? "testJob in progress" : "testJob is pending"
+                resources.?testJob.?status.?conditions.orValue([]).exists(c, c.type == "Complete" && c.status == "True")
+                  ? "testJob completed successfully"
+                  : resources.?testJob.?status.?conditions.orValue([]).exists(c, c.type == "Failed" && c.status == "True") ? "testJob failed"
+                       : resources.?testJob.?status.hasValue() ? "testJob in progress" : "testJob is pending"

Verification (read-only): first command should return no Available checks for testJob after the fix.

#!/bin/bash
set -euo pipefail

# Verify cl-job no longer checks Job condition type "Available"
rg -n -C2 'testJob.*Available|c\.type == "Available"|filter\(c, c\.type == "Available"\)' testdata/adapter-configs/cl-job/adapter-task-config.yaml

# Show downstream dependency that consumes cl-job reported "Available" condition
rg -n -C2 "adapter=='cl-job'|type=='Available'" testdata/adapter-configs/cl-deployment/adapter-task-config.yaml

As per coding guidelines, "Focus on major issues impacting performance, readability, maintainability and security. Avoid nitpicks and avoid verbosity."

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@testdata/adapter-configs/cl-job/adapter-task-config.yaml` around lines 139 -
157, The YAML is incorrectly checking Job condition type "Available" for
resources.testJob (expressions using exists(c, c.type == "Available") and
filter(c, c.type == "Available")), which Jobs do not emit; update those checks
to use Job conditions "Complete" and "Failed" instead: replace exists(... ==
"Available") and filter(... == "Available") with the appropriate checks for
"Complete" (treat as success) and "Failed" (treat as failure), and adjust the
reason/message branches so the success branch returns the Complete condition's
reason/message, the failure branch returns Failed reason/message (or the
provided fallback strings), and keep the existing fallbacks that use
resources.?testJob.?status.hasValue() and "Unknown"/"testJobPending" as before.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@deploy-scripts/lib/adapter.sh`:
- Around line 218-221: The current conditional treats any failure of
discover_adapters as a successful no-op; change the control flow so you
distinguish a discovery error from a valid empty result: call discover_adapters
and check its exit status first (if non-zero) then log an error and return a
non-zero exit code, and only if it succeeds but yields an empty adapters list
log a warning and return 0. Update the block that uses discover_adapters (the
conditional around adapters=$(discover_adapters)) accordingly, and make the
identical fix for the second occurrence around lines 292-295 so discovery
failures are not masked as success.
- Around line 39-49: The adapter name is only checked for emptiness and can
contain path-traversal characters which may reach filesystem operations like rm
-rf "${dest_adapter_dir}"; add a strict character whitelist check for
adapter_name (allow only letters, digits and hyphens) and reject/log and return
non-zero when it fails, using the same validation wherever adapter_name is
parsed (references: variable adapter_name, adapter_configs_dir, adapter_dirs
array population, and the rm -rf call that uses dest_adapter_dir); ensure the
error message mentions invalid characters so callers know why it was rejected.
- Around line 266-267: The helm release check using grep -q "^${release_name}"
can match prefixes (e.g., adapter-x matching adapter-xy); update the condition
in the adapter release check to require an exact release name by anchoring the
match to either end-of-line or the following whitespace, e.g. replace the grep
with grep -E -q "^${release_name}([[:space:]]|$)" (or use grep -F -x if you
prefer exact-line matching) so the test for release_name is exact before calling
log_warning.

---

Duplicate comments:
In `@testdata/adapter-configs/cl-job/adapter-task-config.yaml`:
- Around line 139-157: The YAML is incorrectly checking Job condition type
"Available" for resources.testJob (expressions using exists(c, c.type ==
"Available") and filter(c, c.type == "Available")), which Jobs do not emit;
update those checks to use Job conditions "Complete" and "Failed" instead:
replace exists(... == "Available") and filter(... == "Available") with the
appropriate checks for "Complete" (treat as success) and "Failed" (treat as
failure), and adjust the reason/message branches so the success branch returns
the Complete condition's reason/message, the failure branch returns Failed
reason/message (or the provided fallback strings), and keep the existing
fallbacks that use resources.?testJob.?status.hasValue() and
"Unknown"/"testJobPending" as before.

In `@testdata/adapter-configs/cl-maestro/adapter-task-config.yaml`:
- Around line 42-44: The placementClusterName parameter is hardcoded to
"cluster1"; replace that literal with a parameterized reference so the adapter
can be configured per-environment (update the expression for name:
"placementClusterName" to read from the template/variable/environment value
rather than a fixed string), ensure a sensible default or required flag is
documented in the description, and adjust any consuming code/templating that
expects this field so it reads the new variable-based value (look for
occurrences of placementClusterName in templates and adapter config readers to
update usage).

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: ae951c1d-fc95-47c9-a3c4-e818a1947fcf

📥 Commits

Reviewing files that changed from the base of the PR and between beade25 and a2d479d.

📒 Files selected for processing (16)
  • deploy-scripts/lib/adapter.sh
  • testdata/adapter-configs/cl-deployment/adapter-config.yaml
  • testdata/adapter-configs/cl-deployment/adapter-task-config.yaml
  • testdata/adapter-configs/cl-deployment/values.yaml
  • testdata/adapter-configs/cl-job/adapter-config.yaml
  • testdata/adapter-configs/cl-job/adapter-task-config.yaml
  • testdata/adapter-configs/cl-job/values.yaml
  • testdata/adapter-configs/cl-maestro/adapter-config.yaml
  • testdata/adapter-configs/cl-maestro/adapter-task-config.yaml
  • testdata/adapter-configs/cl-maestro/values.yaml
  • testdata/adapter-configs/cl-namespace/adapter-config.yaml
  • testdata/adapter-configs/cl-namespace/adapter-task-config.yaml
  • testdata/adapter-configs/cl-namespace/values.yaml
  • testdata/adapter-configs/np-configmap/adapter-config.yaml
  • testdata/adapter-configs/np-configmap/adapter-task-config.yaml
  • testdata/adapter-configs/np-configmap/values.yaml
🚧 Files skipped from review as they are similar to previous changes (3)
  • testdata/adapter-configs/cl-deployment/adapter-config.yaml
  • testdata/adapter-configs/cl-deployment/values.yaml
  • testdata/adapter-configs/np-configmap/adapter-config.yaml

Comment on lines +39 to +49
# Validate adapter name is not empty (prevents issues from trailing commas)
if [[ -z "${adapter_name}" ]]; then
log_error "Empty adapter name in CLUSTER_TIER0_ADAPTERS_DEPLOYMENT (check for trailing commas)" >&2
return 1
fi
if [[ -d "${adapter_configs_dir}/${adapter_name}" ]]; then
adapter_dirs+=("clusters|${adapter_name}")
else
log_error "Cluster adapter directory not found: ${adapter_configs_dir}/${adapter_name}" >&2
return 1
fi
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# First, locate and examine the file
if [[ -f "deploy-scripts/lib/adapter.sh" ]]; then
  echo "=== File found. Checking file size ==="
  wc -l deploy-scripts/lib/adapter.sh
else
  echo "File not found at expected location. Searching..."
  find . -name "adapter.sh" -type f 2>/dev/null
fi

Repository: openshift-hyperfleet/hyperfleet-e2e

Length of output: 151


🏁 Script executed:

#!/bin/bash
# Read the relevant sections of the file with context
echo "=== Lines 35-75 (covering lines 39-49 and 60-69) ==="
sed -n '35,75p' deploy-scripts/lib/adapter.sh

echo -e "\n=== Lines 120-145 (covering line 136 rm -rf usage) ==="
sed -n '120,145p' deploy-scripts/lib/adapter.sh

echo -e "\n=== Lines 210-230 (covering lines 218-221) ==="
sed -n '210,230p' deploy-scripts/lib/adapter.sh

echo -e "\n=== Lines 260-275 (covering lines 266-267) ==="
sed -n '260,275p' deploy-scripts/lib/adapter.sh

echo -e "\n=== Lines 285-300 (covering lines 292-295) ==="
sed -n '285,300p' deploy-scripts/lib/adapter.sh

Repository: openshift-hyperfleet/hyperfleet-e2e

Length of output: 4367


🏁 Script executed:

#!/bin/bash
# Check if adapter names flow into filesystem operations
echo "=== Searching for rm -rf operations involving adapter_name ==="
grep -n "rm -rf" deploy-scripts/lib/adapter.sh

echo -e "\n=== Searching for dest_adapter_dir construction ==="
grep -n "dest_adapter_dir" deploy-scripts/lib/adapter.sh

echo -e "\n=== Searching for adapter name validation or sanitization ==="
grep -n "validate_adapter_name\|adapter_name.*=~\|adapter_name.*grep" deploy-scripts/lib/adapter.sh

Repository: openshift-hyperfleet/hyperfleet-e2e

Length of output: 1083


Harden adapter name validation to prevent path traversal in filesystem operations

Adapter names are only validated for emptiness but not character content. Names containing path traversal sequences (e.g., ../..) pass validation, and the substring safety check on line 131 is insufficient to block them. This allows unsafe paths to flow into rm -rf "${dest_adapter_dir}" on line 136.

Add character validation to restrict adapter names to safe characters (alphanumeric and hyphens):

Suggested fix
+validate_adapter_name() {
+  [[ "$1" =~ ^[a-z0-9]([a-z0-9-]*[a-z0-9])?$ ]]
+}
+
   if [[ -n "${cluster_adapters}" ]]; then
     IFS=',' read -ra cluster_adapter_array <<< "${cluster_adapters}"
     for adapter_name in "${cluster_adapter_array[@]}"; do
       adapter_name=$(echo "${adapter_name}" | xargs)
       if [[ -z "${adapter_name}" ]]; then
         log_error "Empty adapter name in CLUSTER_TIER0_ADAPTERS_DEPLOYMENT (check for trailing commas)" >&2
         return 1
       fi
+      if ! validate_adapter_name "${adapter_name}"; then
+        log_error "Invalid adapter name '${adapter_name}' in CLUSTER_TIER0_ADAPTERS_DEPLOYMENT"
+        return 1
+      fi
       if [[ -d "${adapter_configs_dir}/${adapter_name}" ]]; then
         adapter_dirs+=("clusters|${adapter_name}")
       else
         log_error "Cluster adapter directory not found: ${adapter_configs_dir}/${adapter_name}" >&2
         return 1
@@
   if [[ -n "${nodepool_adapters}" ]]; then
     IFS=',' read -ra nodepool_adapter_array <<< "${nodepool_adapters}"
     for adapter_name in "${nodepool_adapter_array[@]}"; do
       adapter_name=$(echo "${adapter_name}" | xargs)
       if [[ -z "${adapter_name}" ]]; then
         log_error "Empty adapter name in NODEPOOL_TIER0_ADAPTERS_DEPLOYMENT (check for trailing commas)" >&2
         return 1
       fi
+      if ! validate_adapter_name "${adapter_name}"; then
+        log_error "Invalid adapter name '${adapter_name}' in NODEPOOL_TIER0_ADAPTERS_DEPLOYMENT"
+        return 1
+      fi
       if [[ -d "${adapter_configs_dir}/${adapter_name}" ]]; then
         adapter_dirs+=("nodepools|${adapter_name}")
       else
         log_error "NodePool adapter directory not found: ${adapter_configs_dir}/${adapter_name}" >&2
         return 1

Also applies to: 60-69

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@deploy-scripts/lib/adapter.sh` around lines 39 - 49, The adapter name is only
checked for emptiness and can contain path-traversal characters which may reach
filesystem operations like rm -rf "${dest_adapter_dir}"; add a strict character
whitelist check for adapter_name (allow only letters, digits and hyphens) and
reject/log and return non-zero when it fails, using the same validation wherever
adapter_name is parsed (references: variable adapter_name, adapter_configs_dir,
adapter_dirs array population, and the rm -rf call that uses dest_adapter_dir);
ensure the error message mentions invalid characters so callers know why it was
rejected.

Comment on lines +218 to +221
if ! adapters=$(discover_adapters); then
log_warning "No adapters found to deploy"
return 0
fi
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Do not treat discovery errors as success/no-op

Both flows return success when discover_adapters fails, which hides real config errors (missing dirs, malformed adapter list) and can make CI pass with adapters silently skipped.

Suggested control-flow fix
-  if ! adapters=$(discover_adapters); then
-    log_warning "No adapters found to deploy"
-    return 0
-  fi
+  if ! adapters=$(discover_adapters); then
+    log_error "Adapter discovery failed; aborting deployment"
+    return 1
+  fi
@@
-  if ! adapters=$(discover_adapters); then
-    log_warning "No adapters found to uninstall"
-    return 0
-  fi
+  if ! adapters=$(discover_adapters); then
+    log_error "Adapter discovery failed; aborting uninstall"
+    return 1
+  fi

Also applies to: 292-295

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@deploy-scripts/lib/adapter.sh` around lines 218 - 221, The current
conditional treats any failure of discover_adapters as a successful no-op;
change the control flow so you distinguish a discovery error from a valid empty
result: call discover_adapters and check its exit status first (if non-zero)
then log an error and return a non-zero exit code, and only if it succeeds but
yields an empty adapters list log a warning and return 0. Update the block that
uses discover_adapters (the conditional around adapters=$(discover_adapters))
accordingly, and make the identical fix for the second occurrence around lines
292-295 so discovery failures are not masked as success.

Comment on lines +266 to +267
if ! helm list -n "${NAMESPACE}" 2>/dev/null | grep -q "^${release_name}"; then
log_warning "Release '${release_name}' not found in namespace '${NAMESPACE}'"
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

# First, let's locate and examine the adapter.sh file
find . -name "adapter.sh" -type f

Repository: openshift-hyperfleet/hyperfleet-e2e

Length of output: 110


🏁 Script executed:

# Now let's read the relevant section of the file, specifically around lines 266-267
wc -l ./deploy-scripts/lib/adapter.sh

Repository: openshift-hyperfleet/hyperfleet-e2e

Length of output: 114


🏁 Script executed:

# Read lines 260-280 to get context around the target lines
sed -n '260,280p' ./deploy-scripts/lib/adapter.sh

Repository: openshift-hyperfleet/hyperfleet-e2e

Length of output: 896


🏁 Script executed:

# Let's check if helm list -q is a valid flag and look for other helm list usages in the codebase
rg "helm list" ./deploy-scripts/ -A 1

Repository: openshift-hyperfleet/hyperfleet-e2e

Length of output: 975


🏁 Script executed:

# Let's check what helm list output looks like - examine the api.sh implementation more closely
sed -n '1,100p' ./deploy-scripts/lib/api.sh | grep -A 10 "helm list"

Repository: openshift-hyperfleet/hyperfleet-e2e

Length of output: 61


🏁 Script executed:

# Let's find the exact line in api.sh that uses helm list
rg "helm list" ./deploy-scripts/lib/api.sh -B 2 -A 3

Repository: openshift-hyperfleet/hyperfleet-e2e

Length of output: 300


🏁 Script executed:

# Let's also check the sentinel.sh file to see if it has the same pattern
rg "helm list" ./deploy-scripts/lib/sentinel.sh -B 2 -A 3

Repository: openshift-hyperfleet/hyperfleet-e2e

Length of output: 291


🏁 Script executed:

# Let's verify helm list -q is a valid flag by checking helm documentation or other usages
# First, let's see if there's any helm command documentation in the repo
find . -name "*.md" -type f -exec grep -l "helm list" {} \;

Repository: openshift-hyperfleet/hyperfleet-e2e

Length of output: 105


🏁 Script executed:

# Check the README for helm list documentation
grep -B 3 -A 3 "helm list" ./deploy-scripts/README.md

Repository: openshift-hyperfleet/hyperfleet-e2e

Length of output: 219


🏁 Script executed:

# Let's verify the exact helm list output format by checking if there are any test files or examples
find . -name "*.sh" -type f -exec grep -l "helm list" {} \; | head -5

Repository: openshift-hyperfleet/hyperfleet-e2e

Length of output: 202


🏁 Script executed:

# Let's read the entire context around the api.sh implementation to understand the pattern better
rg -B 10 "helm list" ./deploy-scripts/lib/api.sh | head -20

Repository: openshift-hyperfleet/hyperfleet-e2e

Length of output: 300


Use exact Helm release matching

grep -q "^${release_name}" lacks an end-of-line anchor, causing false positives. For example, release name adapter-x will match both adapter-x and adapter-xy. Use exact matching on the release name.

Suggested fix
-  if ! helm list -n "${NAMESPACE}" 2>/dev/null | grep -q "^${release_name}"; then
+  if ! helm list -n "${NAMESPACE}" -q 2>/dev/null | grep -Fxq -- "${release_name}"; then
     log_warning "Release '${release_name}' not found in namespace '${NAMESPACE}'"
     return 0
   fi
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if ! helm list -n "${NAMESPACE}" 2>/dev/null | grep -q "^${release_name}"; then
log_warning "Release '${release_name}' not found in namespace '${NAMESPACE}'"
if ! helm list -n "${NAMESPACE}" -q 2>/dev/null | grep -Fxq -- "${release_name}"; then
log_warning "Release '${release_name}' not found in namespace '${NAMESPACE}'"
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@deploy-scripts/lib/adapter.sh` around lines 266 - 267, The helm release check
using grep -q "^${release_name}" can match prefixes (e.g., adapter-x matching
adapter-xy); update the condition in the adapter release check to require an
exact release name by anchoring the match to either end-of-line or the following
whitespace, e.g. replace the grep with grep -E -q
"^${release_name}([[:space:]]|$)" (or use grep -F -x if you prefer exact-line
matching) so the test for release_name is exact before calling log_warning.

has(resources.testJob) ? "True" : "False"
reason:
expression: |
has(resources.testJob.spec)
Copy link
Contributor

Choose a reason for hiding this comment

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

Category: Bug

The reason expression on line 130 checks has(resources.testJob.spec) while the status
expression on line 127 checks has(resources.testJob). These would produce contradictory
results when the resource exists but .spec is not yet populated — status says "True", reason
says "JobPending".

All other adapters in this PR use has(resources.) consistently for both fields. Looks
like an accidental change — should this be has(resources.testJob) to match?

Suggested change
has(resources.testJob.spec)
has(resources.testJob)

@rh-amarin rh-amarin force-pushed the align-adapter-config branch from a2d479d to 4a2cc0f Compare March 13, 2026 14:38
@coderabbitai
Copy link

coderabbitai bot commented Mar 13, 2026

Caution

Failed to replace (edit) comment. This is likely due to insufficient permissions or the comment being deleted.

Error details
{"name":"HttpError","status":403,"request":{"method":"PATCH","url":"https://api.github.com/repos/openshift-hyperfleet/hyperfleet-e2e/issues/comments/4010957404","headers":{"accept":"application/vnd.github.v3+json","user-agent":"octokit.js/0.0.0-development octokit-core.js/7.0.6 Node.js/24","authorization":"token [REDACTED]","content-type":"application/json; charset=utf-8"},"body":{"body":"<!-- This is an auto-generated comment: summarize by coderabbit.ai -->\n<!-- This is an auto-generated comment: failure by coderabbit.ai -->\n\n> [!CAUTION]\n> ## Review failed\n> \n> Failed to post review comments\n\n<!-- end of auto-generated comment: failure by coderabbit.ai -->\n\n<!-- This is an auto-generated comment: review paused by coderabbit.ai -->\n\n> [!NOTE]\n> ## Reviews paused\n> \n> 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.\n> \n> Use the following commands to manage reviews:\n> - `@coderabbitai resume` to resume automatic reviews.\n> - `@coderabbitai review` to trigger a single review.\n> \n> Use the checkboxes below for quick actions:\n> - [ ] <!-- {\"checkboxId\": \"7f6cc2e2-2e4e-497a-8c31-c9e4573e93d1\"} --> ▶️ Resume reviews\n> - [ ] <!-- {\"checkboxId\": \"e9bb8d72-00e8-4f67-9cb2-caf3b22574fe\"} --> 🔍 Trigger review\n\n<!-- end of auto-generated comment: review paused by coderabbit.ai -->\n\n<!-- walkthrough_start -->\n\n## Walkthrough\n\nThis PR standardizes many testdata adapter configs and task configs: it removes CRD-like top-level apiVersion/kind/metadata/spec blocks, promotes params to top-level, and renames camelCase keys to snake_case across preconditions, resources, post/payloads, discovery, and ManifestWork definitions. Maestro/TLS fields were flattened and renamed. Broker googlepubsub keys (projectId, subscriptionId, deadLetterTopic) were renamed to snake_case. The deploy script (deploy-scripts/lib/adapter.sh) was refactored for clearer discovery, install, and uninstall flows, improved validation/error aggregation, and adjusted Helm invocation handling.\n\n## Sequence Diagram(s)\n\nmermaid\nsequenceDiagram\n    actor Operator\n    participant AdapterScript as \"deploy-scripts/adapter.sh\"\n    participant Filesystem as \"Filesystem (charts/config)\"\n    participant Helm as \"Helm CLI\"\n    participant Kubernetes as \"Kubernetes API\"\n    Operator->>AdapterScript: discover_adapters()\n    AdapterScript->>Filesystem: scan adapter dirs\n    Filesystem-->>AdapterScript: adapter list\n    Operator->>AdapterScript: install_adapter_instance(adapter)\n    AdapterScript->>Filesystem: validate & copy adapter config into chart dir\n    AdapterScript->>Helm: helm upgrade --install (with values)\n    Helm-->>AdapterScript: helm result (success/failure)\n    AdapterScript->>Kubernetes: wait_for_pods_ready(namespace)\n    Kubernetes-->>AdapterScript: pod statuses\n    AdapterScript-->>Operator: report success/failure\n\n## Estimated code review effort\n\n🎯 5 (Critical) | ⏱️ ~120 minutes\n\n<!-- walkthrough_end -->\n\n\n<!-- pre_merge_checks_walkthrough_start -->\n\n<details>\n<summary>🚥 Pre-merge checks | ✅ 2 | ❌ 1</summary>\n\n### ❌ Failed checks (1 warning)\n\n|     Check name     | Status     | Explanation                                                                           | Resolution                                                                         |\n| :----------------: | :--------- | :------------------------------------------------------------------------------------ | :--------------------------------------------------------------------------------- |\n| Docstring Coverage | ⚠️ Warning | Docstring coverage is 60.00% which is insufficient. The required threshold is 80.00%. | Write docstrings for the functions missing them to satisfy the coverage threshold. |\n\n<details>\n<summary>✅ Passed checks (2 passed)</summary>\n\n|     Check name    | Status   | Explanation                                                                                                                                                                                                                            |\n| :---------------: | :------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| Description Check | ✅ Passed | Check skipped - CodeRabbit’s high-level summary is enabled.                                                                                                                                                                            |\n|    Title check    | ✅ Passed | The title references a ticket ([HYPERFLEET-720](https://issues.redhat.com/browse/HYPERFLEET-720)) and summarizes the main change as updating adapter configs to follow project standards, which accurately reflects the extensive config file updates across all adapter test data files. |\n\n</details>\n\n<sub>✏️ Tip: You can configure your own custom pre-merge checks in the settings.</sub>\n\n</details>\n\n<!-- pre_merge_checks_walkthrough_end -->\n\n<!-- finishing_touch_checkbox_start -->\n\n<details>\n<summary>✨ Finishing Touches</summary>\n\n<details>\n<summary>🧪 Generate unit tests (beta)</summary>\n\n- [ ] <!-- {\"checkboxId\": \"f47ac10b-58cc-4372-a567-0e02b2c3d479\", \"radioGroupId\": \"utg-output-choice-group-unknown_comment_id\"} -->   Create PR with unit tests\n- [ ] <!-- {\"checkboxId\": \"07f1e7d6-8a8e-4e23-9900-8731c2c87f58\", \"radioGroupId\": \"utg-output-choice-group-unknown_comment_id\"} -->   Post copyable unit tests in a comment\n\n</details>\n\n</details>\n\n<!-- finishing_touch_checkbox_end -->\n\n<!-- pr_review_plan_action_start -->\n\n<details>\n<summary>📝 Coding Plan</summary>\n\n- [ ] <!-- {\"checkboxId\": \"6ad8a4e1-0b3a-4ea2-9b5b-d82c1f47d1f2\"} --> Generate coding plan for human review comments\n\n</details>\n\n<!-- pr_review_plan_action_end -->\n\n<!-- tips_start -->\n\n---\n\n\n\n<sub>Comment `@coderabbitai help` to get the list of available commands and usage tips.</sub>\n\n<!-- tips_end -->\n\n<!-- internal state start -->\n\n\n<!-- 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= -->\n\n<!-- internal state end -->"},"request":{"retryCount":0}},"response":{"url":"https://api.github.com/repos/openshift-hyperfleet/hyperfleet-e2e/issues/comments/4010957404","status":403,"headers":{"access-control-allow-origin":"*","access-control-expose-headers":"ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, X-GitHub-Request-Id, Deprecation, Sunset","content-encoding":"gzip","content-security-policy":"default-src 'none'","content-type":"application/json; charset=utf-8","date":"Fri, 13 Mar 2026 14:45:56 GMT","referrer-policy":"origin-when-cross-origin, strict-origin-when-cross-origin","server":"github.com","strict-transport-security":"max-age=31536000; includeSubdomains; preload","transfer-encoding":"chunked","vary":"Accept-Encoding, Accept, X-Requested-With","x-accepted-github-permissions":"issues=write; pull_requests=write","x-content-type-options":"nosniff","x-frame-options":"deny","x-github-api-version-selected":"2022-11-28","x-github-media-type":"github.v3; format=json","x-github-request-id":"D8AC:387C69:60DA67:1957176:69B42324","x-ratelimit-limit":"15000","x-ratelimit-remaining":"14797","x-ratelimit-reset":"1773413457","x-ratelimit-resource":"core","x-ratelimit-used":"203","x-xss-protection":"0"},"data":{"message":"Resource not accessible by integration","documentation_url":"https://docs.github.com/rest/issues/comments#update-an-issue-comment","status":"403"}}}

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.

6 participants