-
Notifications
You must be signed in to change notification settings - Fork 149
Add federation to skmo #3766
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
openshift-merge-bot
merged 16 commits into
openstack-k8s-operators:main
from
vakwetu:add-federation-to-skmo
Mar 27, 2026
+1,241
−56
Merged
Add federation to skmo #3766
Changes from all commits
Commits
Show all changes
16 commits
Select commit
Hold shift + click to select a range
b108d23
[ci_gen_kustomize_values] Add multi-namespace SKMO scenario and playb…
vakwetu e556836
[ci_gen_kustomize_values] Add Cinder LVM backend support for multi-na…
vakwetu 3802ea3
[federation] Support merging Keycloak CA into an existing CA bundle s…
vakwetu 1626349
[federation] Fix broken 'until' condition waiting for RHSSO InstallPlan
vakwetu 18926eb
[federation] Ensure kustomizations/controlplane directory exists befo…
vakwetu b573e86
[federation] Wait for Keystone Ready before running post-deploy auth …
vakwetu 8af7be1
[federation] Directly patch OSCP with Keystone federation config
vakwetu f139f6f
[federation] Make OpenStack resource creation idempotent
vakwetu fc20382
[ci_gen_kustomize_values] Fix 3-run death spiral in edpm-nodeset2-val…
vakwetu 7b45647
[multiple] Uniquify OSDPD names per deployment run
vakwetu 48d4dc6
[multiple] Fix MCO stuck-uncordon deadlock
vakwetu f4a6aef
[multiple] Fix SKMO federation CA bundle handling and SSL trust
vakwetu 587f9e5
[federation] Fix CA bundle secret name resolving to empty string
vakwetu 12f2734
[multiple] Handle already-unlocked state in usroverlay task
vakwetu 6767ae6
[multiple] Refactor inline Python/shell patterns to cleaner alternatives
vakwetu 49572b5
[multiple] Use strategic merge patch in Keystone federation kustomiza…
vakwetu File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,36 @@ | ||
| --- | ||
| - name: Patch leaf control plane with barbican-keystone-listener transport URL | ||
| hosts: localhost | ||
| gather_facts: false | ||
| vars: | ||
| central_namespace: openstack | ||
| leaf_namespace: openstack2 | ||
| leaf_transport_url_name: rabbitmq-transport-url-barbican-keystone-listener-regiontwo | ||
| tasks: | ||
| - name: Get transport URL secret from central namespace | ||
| kubernetes.core.k8s_info: | ||
| api_version: v1 | ||
| kind: Secret | ||
| namespace: "{{ central_namespace }}" | ||
| name: "{{ leaf_transport_url_name }}" | ||
| register: _transport_secret | ||
|
|
||
| - name: Patch OpenStackControlPlane in leaf region with notifications transport_url | ||
| vars: | ||
| _transport_url: "{{ _transport_secret.resources[0].data['transport_url'] | b64decode }}" | ||
| kubernetes.core.k8s: | ||
| state: patched | ||
| api_version: core.openstack.org/v1beta1 | ||
| kind: OpenStackControlPlane | ||
| name: controlplane | ||
| namespace: "{{ leaf_namespace }}" | ||
| definition: | ||
| spec: | ||
| barbican: | ||
| template: | ||
| barbicanKeystoneListener: | ||
| customServiceConfig: | | ||
| [DEFAULT] | ||
| transport_url = {{ _transport_url }} | ||
| [keystone_notifications] | ||
| pool_name = barbican-listener-regionTwo |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,209 @@ | ||
| --- | ||
| - name: Prepare SKMO leaf prerequisites in regionZero | ||
| hosts: localhost | ||
| gather_facts: false | ||
| vars: | ||
| skmo_values_file: "{{ cifmw_architecture_repo }}/examples/va/multi-namespace-skmo/control-plane2/skmo-values.yaml" | ||
| osp_secrets_env_file: "{{ cifmw_architecture_repo }}/lib/control-plane/base/osp-secrets.env" | ||
| central_namespace: openstack | ||
| leaf_namespace: openstack2 | ||
| leaf_secret_name: osp-secret | ||
| central_rootca_secret: rootca-public | ||
| central_rootca_internal_secret: rootca-internal | ||
| leaf_transport_url_name: barbican-keystone-listener-regiontwo | ||
| leaf_transport_url_name_secret: rabbitmq-transport-url-barbican-keystone-listener-regiontwo | ||
| leaf_transport_url_secret_copy: barbican-keystone-listener-regiontwo-transport | ||
| tasks: | ||
| - name: Wait for central Keystone API to be ready | ||
| kubernetes.core.k8s_info: | ||
| api_version: keystone.openstack.org/v1beta1 | ||
| kind: KeystoneAPI | ||
| namespace: "{{ central_namespace }}" | ||
| register: _keystoneapi_info | ||
| retries: 60 | ||
| delay: 10 | ||
| until: | ||
| - _keystoneapi_info.resources | length > 0 | ||
| - _keystoneapi_info.resources[0].status.conditions is defined | ||
| - _keystoneapi_info.resources[0].status.conditions | | ||
| selectattr('type', 'equalto', 'Ready') | | ||
| selectattr('status', 'equalto', 'True') | list | length > 0 | ||
|
|
||
| - name: Wait for openstackclient pod to be ready in central region | ||
| kubernetes.core.k8s_info: | ||
| api_version: v1 | ||
| kind: Pod | ||
| namespace: "{{ central_namespace }}" | ||
| name: openstackclient | ||
| register: _osc_pod_info | ||
| retries: 30 | ||
| delay: 10 | ||
| until: | ||
| - _osc_pod_info.resources | length > 0 | ||
| - _osc_pod_info.resources[0].status.conditions is defined | ||
| - _osc_pod_info.resources[0].status.conditions | | ||
| selectattr('type', 'equalto', 'Ready') | | ||
| selectattr('status', 'equalto', 'True') | list | length > 0 | ||
|
|
||
| - name: Load SKMO values | ||
| ansible.builtin.set_fact: | ||
| skmo_values: "{{ lookup('file', skmo_values_file) | from_yaml }}" | ||
|
|
||
| - name: Set SKMO leaf facts | ||
| ansible.builtin.set_fact: | ||
| leaf_region: "{{ skmo_values.data.leafRegion }}" | ||
| leaf_admin_user: "{{ skmo_values.data.leafAdminUser }}" | ||
| leaf_admin_project: "{{ skmo_values.data.leafAdminProject }}" | ||
| leaf_admin_password_key: "{{ skmo_values.data.leafAdminPasswordKey }}" | ||
| keystone_internal_url: "{{ skmo_values.data.keystoneInternalURL }}" | ||
| keystone_public_url: "{{ skmo_values.data.keystonePublicURL }}" | ||
| ca_bundle_secret_name: "{{ skmo_values.data.leafCaBundleSecretName }}" | ||
|
|
||
| - name: Ensure leaf osp-secret exists (pre-create from env file) | ||
| ansible.builtin.shell: | | ||
| set -euo pipefail | ||
| if ! oc -n {{ leaf_namespace }} get secret {{ leaf_secret_name }} >/dev/null 2>&1; then | ||
| oc -n {{ leaf_namespace }} create secret generic {{ leaf_secret_name }} \ | ||
| --from-env-file="{{ osp_secrets_env_file }}" \ | ||
| --dry-run=client -o yaml | oc apply -f - | ||
| fi | ||
| args: | ||
| executable: /bin/bash | ||
|
|
||
| - name: Read leaf admin password from leaf secret | ||
| ansible.builtin.shell: | | ||
| set -euo pipefail | ||
vakwetu marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| oc -n {{ leaf_namespace }} get secret {{ leaf_secret_name }} \ | ||
| -o jsonpath='{.data.{{ leaf_admin_password_key }}}' | base64 -d | ||
| args: | ||
| executable: /bin/bash | ||
| register: leaf_admin_password | ||
| changed_when: false | ||
|
|
||
| - name: Ensure leaf region exists in central Keystone | ||
| ansible.builtin.shell: | | ||
| set -euo pipefail | ||
| oc -n {{ central_namespace }} rsh openstackclient \ | ||
| openstack region show {{ leaf_region }} >/dev/null 2>&1 || \ | ||
| oc -n {{ central_namespace }} rsh openstackclient \ | ||
| openstack region create {{ leaf_region }} | ||
| args: | ||
| executable: /bin/bash | ||
|
|
||
| - name: Ensure keystone catalog endpoints exist for leaf region | ||
| ansible.builtin.shell: | | ||
| set -euo pipefail | ||
| if ! oc -n {{ central_namespace }} rsh openstackclient \ | ||
| openstack endpoint list --service keystone --interface public --region {{ leaf_region }} \ | ||
| -f value -c ID | head -1 | grep -q .; then | ||
| oc -n {{ central_namespace }} rsh openstackclient \ | ||
| openstack endpoint create --region {{ leaf_region }} identity public "{{ keystone_public_url }}" | ||
| fi | ||
| if ! oc -n {{ central_namespace }} rsh openstackclient \ | ||
| openstack endpoint list --service keystone --interface internal --region {{ leaf_region }} \ | ||
| -f value -c ID | head -1 | grep -q .; then | ||
| oc -n {{ central_namespace }} rsh openstackclient \ | ||
| openstack endpoint create --region {{ leaf_region }} identity internal "{{ keystone_internal_url }}" | ||
| fi | ||
| args: | ||
| executable: /bin/bash | ||
|
|
||
| - name: Ensure leaf admin project exists in central Keystone | ||
| ansible.builtin.shell: | | ||
| set -euo pipefail | ||
| oc -n {{ central_namespace }} rsh openstackclient \ | ||
| openstack project show {{ leaf_admin_project }} >/dev/null 2>&1 || \ | ||
| oc -n {{ central_namespace }} rsh openstackclient \ | ||
| openstack project create {{ leaf_admin_project }} | ||
| args: | ||
| executable: /bin/bash | ||
|
|
||
| - name: Ensure leaf admin user exists and has admin role | ||
| ansible.builtin.shell: | | ||
| set -euo pipefail | ||
| if ! oc -n {{ central_namespace }} rsh openstackclient \ | ||
| openstack user show {{ leaf_admin_user }} >/dev/null 2>&1; then | ||
| oc -n {{ central_namespace }} rsh openstackclient \ | ||
| openstack user create --domain Default --password "{{ leaf_admin_password.stdout | trim }}" {{ leaf_admin_user }} | ||
| fi | ||
| oc -n {{ central_namespace }} rsh openstackclient \ | ||
| openstack role add --project {{ leaf_admin_project }} --user {{ leaf_admin_user }} admin | ||
| args: | ||
| executable: /bin/bash | ||
|
|
||
| - name: Get existing leaf CA bundle secret if present | ||
| kubernetes.core.k8s_info: | ||
| api_version: v1 | ||
| kind: Secret | ||
| namespace: "{{ leaf_namespace }}" | ||
| name: "{{ ca_bundle_secret_name }}" | ||
| register: _existing_bundle | ||
|
|
||
| - name: Get central rootca certs | ||
| kubernetes.core.k8s_info: | ||
| api_version: v1 | ||
| kind: Secret | ||
| namespace: "{{ central_namespace }}" | ||
| name: "{{ item }}" | ||
| register: _central_certs | ||
| loop: | ||
| - "{{ central_rootca_secret }}" | ||
| - "{{ central_rootca_internal_secret }}" | ||
|
|
||
| - name: Create or update leaf CA bundle secret | ||
| kubernetes.core.k8s: | ||
| state: present | ||
| definition: | ||
| apiVersion: v1 | ||
| kind: Secret | ||
| metadata: | ||
| name: "{{ ca_bundle_secret_name }}" | ||
| namespace: "{{ leaf_namespace }}" | ||
| data: "{{ (_existing_bundle.resources[0].data | default({})) | combine({ | ||
| 'skmo-central-rootca.crt': _central_certs.results[0].resources[0].data['tls.crt'], | ||
| 'skmo-central-rootca-internal.crt': _central_certs.results[1].resources[0].data['tls.crt'] | ||
| }) }}" | ||
|
|
||
| - name: Create TransportURL CR in central region for leaf listener | ||
| ansible.builtin.shell: | | ||
| set -euo pipefail | ||
| oc apply -f - <<EOF | ||
| apiVersion: rabbitmq.openstack.org/v1beta1 | ||
| kind: TransportURL | ||
| metadata: | ||
| name: {{ leaf_transport_url_name }} | ||
| namespace: {{ central_namespace }} | ||
| spec: | ||
| rabbitmqClusterName: rabbitmq | ||
| EOF | ||
| args: | ||
| executable: /bin/bash | ||
|
|
||
| - name: Wait for TransportURL to be ready | ||
vakwetu marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| ansible.builtin.shell: | | ||
| set -euo pipefail | ||
| oc wait transporturl {{ leaf_transport_url_name }} \ | ||
| -n {{ central_namespace }} \ | ||
| --for=condition=Ready --timeout=120s | ||
| args: | ||
| executable: /bin/bash | ||
|
|
||
| - name: Get transport URL secret from central namespace | ||
| kubernetes.core.k8s_info: | ||
| api_version: v1 | ||
| kind: Secret | ||
| namespace: "{{ central_namespace }}" | ||
| name: "{{ leaf_transport_url_name_secret }}" | ||
| register: _transport_secret | ||
|
|
||
| - name: Copy transport URL secret to leaf namespace | ||
| kubernetes.core.k8s: | ||
| state: present | ||
| definition: | ||
| apiVersion: v1 | ||
| kind: Secret | ||
| metadata: | ||
| name: "{{ leaf_transport_url_secret_copy }}" | ||
| namespace: "{{ leaf_namespace }}" | ||
| type: "{{ _transport_secret.resources[0].type }}" | ||
| data: "{{ _transport_secret.resources[0].data }}" | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,139 @@ | ||
| --- | ||
| - name: Update central CA bundle with leaf region CAs and wait for reconciliation | ||
| hosts: localhost | ||
| gather_facts: false | ||
| vars: | ||
| central_namespace: openstack | ||
| leaf_namespace: openstack2 | ||
| controlplane_name: controlplane | ||
| leaf_rootca_secret: rootca-public | ||
| leaf_rootca_internal_secret: rootca-internal | ||
| tasks: | ||
| # ------------------------------------------------------------------------- | ||
| # Step 1 - determine which secret holds the central CA bundle. | ||
| # | ||
| # Priority: | ||
| # 1. spec.tls.caBundleSecretName already set on the OSCP. | ||
| # 2. cifmw_custom_ca_certs_secret_name variable (if set by caller). | ||
| # 3. Hard default: "custom-ca-certs". | ||
| # ------------------------------------------------------------------------- | ||
| - name: Read current OpenStackControlPlane state | ||
| kubernetes.core.k8s_info: | ||
| api_version: core.openstack.org/v1beta1 | ||
| kind: OpenStackControlPlane | ||
| name: "{{ controlplane_name }}" | ||
| namespace: "{{ central_namespace }}" | ||
| register: _central_oscp_info | ||
|
|
||
| - name: Resolve CA bundle secret name | ||
| ansible.builtin.set_fact: | ||
| _ca_bundle_secret_name: >- | ||
| {{ | ||
| ((_central_oscp_info.resources | first).spec.tls | default({})).caBundleSecretName | ||
| | default(cifmw_custom_ca_certs_secret_name | default('custom-ca-certs', true), true) | ||
| | default('custom-ca-certs', true) | ||
| }} | ||
| _oscp_has_ca_bundle: >- | ||
| {{ | ||
| ( | ||
| ((_central_oscp_info.resources | first).spec.tls | default({})).caBundleSecretName | ||
| | default('') | ||
| ) | length > 0 | ||
| }} | ||
|
|
||
| # ------------------------------------------------------------------------- | ||
| # Step 2 - fetch the leaf region CA certs | ||
| # ------------------------------------------------------------------------- | ||
| - name: Get leaf region rootca certs | ||
| kubernetes.core.k8s_info: | ||
| api_version: v1 | ||
| kind: Secret | ||
| namespace: "{{ leaf_namespace }}" | ||
| name: "{{ item }}" | ||
| register: _leaf_certs | ||
| loop: | ||
| - "{{ leaf_rootca_secret }}" | ||
| - "{{ leaf_rootca_internal_secret }}" | ||
|
|
||
| # ------------------------------------------------------------------------- | ||
| # Step 3 - get existing central CA bundle data (if secret already exists) | ||
| # ------------------------------------------------------------------------- | ||
| - name: Look up existing central CA bundle secret | ||
| kubernetes.core.k8s_info: | ||
| api_version: v1 | ||
| kind: Secret | ||
| namespace: "{{ central_namespace }}" | ||
| name: "{{ _ca_bundle_secret_name }}" | ||
| register: _existing_bundle | ||
|
|
||
| - name: Capture existing CA bundle secret data | ||
| ansible.builtin.set_fact: | ||
| _existing_bundle_data: >- | ||
| {{ | ||
| (_existing_bundle.resources | first).data | ||
| if _existing_bundle.resources | length > 0 | ||
| else {} | ||
| }} | ||
|
|
||
| # ------------------------------------------------------------------------- | ||
| # Step 4 - create or update the secret, merging in the leaf CAs | ||
| # ------------------------------------------------------------------------- | ||
| - name: Create or update central CA bundle secret with leaf region CAs | ||
| kubernetes.core.k8s: | ||
| state: present | ||
| definition: | ||
| apiVersion: v1 | ||
| kind: Secret | ||
| metadata: | ||
| name: "{{ _ca_bundle_secret_name }}" | ||
| namespace: "{{ central_namespace }}" | ||
| data: >- | ||
| {{ | ||
| _existing_bundle_data | combine({ | ||
| 'skmo-leaf-rootca.crt': | ||
| _leaf_certs.results[0].resources[0].data['tls.crt'], | ||
| 'skmo-leaf-rootca-internal.crt': | ||
| _leaf_certs.results[1].resources[0].data['tls.crt'] | ||
| }) | ||
| }} | ||
|
|
||
| # ------------------------------------------------------------------------- | ||
| # Step 5 - patch the OSCP to reference the secret when not already set | ||
| # ------------------------------------------------------------------------- | ||
| - name: Patch OpenStackControlPlane to set caBundleSecretName (when unset) | ||
| when: not _oscp_has_ca_bundle | bool | ||
| kubernetes.core.k8s: | ||
| state: patched | ||
| definition: | ||
| apiVersion: core.openstack.org/v1beta1 | ||
| kind: OpenStackControlPlane | ||
| metadata: | ||
| name: "{{ controlplane_name }}" | ||
| namespace: "{{ central_namespace }}" | ||
| spec: | ||
| tls: | ||
| caBundleSecretName: "{{ _ca_bundle_secret_name }}" | ||
|
|
||
| # ------------------------------------------------------------------------- | ||
| # Step 6 - wait for RHOSO to reconcile combined-ca-bundle. | ||
| # | ||
| # We compare the fingerprint of the leaf rootca cert we just added against | ||
| # every cert in combined-ca-bundle, retrying until it appears. | ||
| # ------------------------------------------------------------------------- | ||
| - name: Wait for leaf region CA to appear in combined-ca-bundle | ||
| kubernetes.core.k8s_info: | ||
| api_version: v1 | ||
| kind: Secret | ||
| namespace: "{{ central_namespace }}" | ||
| name: combined-ca-bundle | ||
| register: _combined_bundle | ||
| until: >- | ||
| (_combined_bundle.resources | length > 0) and | ||
| ( | ||
| _leaf_certs.results[0].resources[0].data['tls.crt'] | b64decode | ||
| in | ||
| (_combined_bundle.resources | first).data['tls-ca-bundle.pem'] | b64decode | ||
| ) | ||
| retries: 30 | ||
| delay: 10 | ||
| changed_when: false |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| multi-namespace |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.