Skip to content

Fix rotate_app_creds YAML parsing when from_yaml returns a list#19

Open
tusharjadhav3302 wants to merge 2 commits into
mainfrom
fix-ocp-creds-yaml-parsing
Open

Fix rotate_app_creds YAML parsing when from_yaml returns a list#19
tusharjadhav3302 wants to merge 2 commits into
mainfrom
fix-ocp-creds-yaml-parsing

Conversation

@tusharjadhav3302

@tusharjadhav3302 tusharjadhav3302 commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

Summary

Fix the rotate_app_creds day2ops procedure failing at the credential verification step with:
'list object' has no attribute 'clouds'

Why

The to_nice_yaml(indent=4) filter prepends ---\n to the clouds.yaml content. When this content is piped into the OCP openstack-credentials secret via oc set data, the secret stores the YAML document separator. On readback, Ansible's from_yaml interprets the ----prefixed content as a multi-document YAML and returns a list (with one element) instead of a dict.
The verification assert then fails because it expects ocp_creds.clouds.openstack.auth_type but ocp_creds is a list, not a mapping.

What failed

Task: Verify credentials rotated to application credentials
Error from Zuul job (shiftstack-rhel9-rhoso18.0-ocp421, Jun 30):
The conditional check 'ocp_creds.clouds.openstack.auth_type == 'v3applicationcredential'' failed. The error was: error while evaluating conditional (ocp_creds.clouds.openstack.auth_type == 'v3applicationcredential'): 'list object' has no attribute 'clouds'. 'list object' has no attribute 'clouds'

Note: The credential rotation itself succeeds — the secret IS correctly updated. Only the verification readback parsing fails.

How

Two fixes applied to rotate_app_creds.yml:

1. Prevention — strip --- before writing to the secret:

# Before (buggy):
cat {{ clouds_yaml_file_path }} | sed 's/{{ user_cloud }}:/openstack:/' | \
oc set data -n kube-system secret/openstack-credentials clouds.yaml=-

# After (fixed):
cat {{ clouds_yaml_file_path }} | sed '/^---$/d' | sed 's/{{ user_cloud }}:/openstack:/' | \
oc set data -n kube-system secret/openstack-credentials clouds.yaml=-

2. Defensive parsing — handle both list and dict from from_yaml:

# Before (buggy):
- name: Parse OCP credentials
  ansible.builtin.set_fact:
    ocp_creds: "{{ ocp_creds_output.stdout | from_yaml }}"

# After (fixed):
- name: Parse OCP credentials
  vars:
    parsed_yaml: "{{ ocp_creds_output.stdout | from_yaml }}"
  ansible.builtin.set_fact:
    ocp_creds: "{{ (parsed_yaml is mapping) | ternary(parsed_yaml, parsed_yaml[0]) }}"

Test Plan

  • ansible-lint passes (production profile)
  • Day2ops rotation passes on a running OCP cluster
  • oc get secret -n kube-system openstack-credentials content has no leading ---
  • ocp_creds correctly parsed as dict with auth_type: v3applicationcredential

References

Bug: https://redhat.atlassian.net/browse/OCPBUGS-95045
Parent feature: https://redhat.atlassian.net/browse/OSPRH-6485
Failing job: shiftstack-rhel9-rhoso18.0-ocp421 periodic run (Jun 30, 2026)

@tusharjadhav3302 tusharjadhav3302 added the ready-for-review PR is ready for code review label Jul 1, 2026

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

lgtm. Two things, please:

  1. Rebase on main - #20 is merged, so the cherry-picked install-config commit is already on main. A rebase should drop it cleanly.

  2. Testing - could you check the test plan boxes or link a CI run showing the rotation succeeds with the fix?

@tusharjadhav3302 tusharjadhav3302 force-pushed the fix-ocp-creds-yaml-parsing branch from a04c57b to 9d8bbb0 Compare July 2, 2026 05:46
@tusharjadhav3302

Copy link
Copy Markdown
Contributor Author

On running the ansible playbook manually on a healthy shiftstack cluster over serval71 using the following command :
sh-5.2$ ansible-navigator run playbooks/ocp_testing.yaml \ --extra-vars '{"stages": ["day2ops"], "day2ops_procedures": ["rotate_app_creds"], "installation_type": "ipi"}' \ -m stdout

The execution passes :
PLAY RECAP ********************************************************************* localhost : ok=191 changed=40 unreachable=0 failed=0 skipped=65 rescued=0 ignored=0

The failing ansible task now shows passing :
TASK [shiftstack.stages.day2ops : Verify credentials rotated to application credentials] *** ok: [localhost] => { "changed": false, "msg": "Credential rotation verified — auth_type is v3applicationcredential" }

A zuul ci re-run is triggered for the ci-framework-testproject

@tusharjadhav3302

Copy link
Copy Markdown
Contributor Author

tusharjadhav3302 and others added 2 commits July 2, 2026 20:24
The clouds.yaml stored in the OCP secret starts with '---' (from
to_nice_yaml), causing from_yaml to return a list instead of a dict.
Strip the document separator before piping to the secret and handle
both list/dict cases when parsing the verification readback.

OSPRH-6485

Co-authored-by: Cursor <cursoragent@cursor.com>
…sibility

The previous from_yaml fix handled the list case but not the string
case. The root cause is the jq + base64 pipeline returning unexpected
content. Switch to oc get -o jsonpath for reliable raw value extraction,
add debug output to diagnose future parsing issues, and improve the
assert to show actual values on failure.

OCPBUGS-95045

Co-authored-by: Cursor <cursoragent@cursor.com>

@dlaw4608 dlaw4608 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.

LGTM!!

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

Labels

ready-for-review PR is ready for code review

Development

Successfully merging this pull request may close these issues.

3 participants