|
| 1 | +--- |
| 2 | +# Disclaimer: |
| 3 | +# This playbook is not officially supported and comes with no guarantees. |
| 4 | +# Use it at your own risk. Ensure you test thoroughly in your environment |
| 5 | +# before deploying to production. |
| 6 | + |
| 7 | +# ----------------------------------------------------------------------------- |
| 8 | +# Playbook Name: Deploy RAN PTP GM tests script |
| 9 | +# Description : Prepares a bastion host to run RAN PTP GM eco-gotests. |
| 10 | +# Optionally discovers the spoke kubeconfig and BMC IP from the |
| 11 | +# hub ACM cluster. Mirrors required images, pulls the eco-gotests |
| 12 | +# container, and generates a single test script that runs: |
| 13 | +# 1. containernshide, powermanagement, deploymenttypes |
| 14 | +# (with existing ZTP PtpConfigs) |
| 15 | +# 2. For each ptp_cycle_config: switches PTP config, waits 5m, |
| 16 | +# runs ptp eco-gotests |
| 17 | +# |
| 18 | +# Prerequisites: |
| 19 | +# - Either kubeconfig is provided directly, or hub_kubeconfig + |
| 20 | +# spoke_cluster_label_selector are provided for spoke discovery. |
| 21 | +# - hub_kubeconfig must be the path to the hub kubeconfig file on the bastion |
| 22 | +# (used for spoke discovery and mounted into the eco-gotests container). |
| 23 | +# - ptp_cycle_configs must be a list of {name, urls[]} dicts. |
| 24 | +# - bmc_user and bmc_password must be defined for power management tests. |
| 25 | +# |
| 26 | +# Key Tasks: |
| 27 | +# - Optionally discover spoke kubeconfig and BMC IP from hub ManagedCluster |
| 28 | +# - Gather cluster version from OpenShift |
| 29 | +# - Pull the eco-gotests container (mirror to disconnected registry if needed) |
| 30 | +# - Generate a unified test script covering all eco_gotests_features and |
| 31 | +# ptp_cycle_configs |
| 32 | + |
| 33 | +# Usage (hub/spoke ACM discovery mode): |
| 34 | +# ansible-playbook ./playbooks/ran/deploy-ptp-gm-tests-script.yaml \ |
| 35 | +# -i ./inventories/ocp-deployment/build-inventory.py \ |
| 36 | +# --extra-vars "hub_kubeconfig=/home/telcov10n/project/generated/kni-qe-111/auth/kubeconfig \ |
| 37 | +# hub_clusterconfigs_path=/home/telcov10n/project/generated/kni-qe-111 \ |
| 38 | +# spoke_cluster_label_selector=sites=helix48 \ |
| 39 | +# bmc_user=<user> bmc_password=<pass> \ |
| 40 | +# labels='!no-container' \ |
| 41 | +# ptp_cycle_configs='[{\"name\": \"ntpfailover\", \"urls\": [ |
| 42 | +# \"https://gitlab.cee.redhat.com/telcov10n/ztp-site-configs-ci/-/raw/ptp_gm/policygentemplates/4.20/ptp-test/PtpConfigGmWpcNtpCustom.yaml\", |
| 43 | +# \"https://gitlab.cee.redhat.com/telcov10n/ztp-site-configs-ci/-/raw/ptp_gm/policygentemplates/4.20/ptp-test/PtpConfigSlaveNtpCustom.yaml\" |
| 44 | +# ]}]'" |
| 45 | +# |
| 46 | +# Available extra-vars: |
| 47 | +# hub_kubeconfig # string: Path to hub kubeconfig file on the bastion (enables spoke discovery |
| 48 | +# # and is mounted directly into the eco-gotests container). |
| 49 | +# spoke_cluster_label_selector # string: Label selector for spoke ManagedCluster (required with hub_kubeconfig). |
| 50 | +# bmc_user # string: BMC username (required for power management tests). |
| 51 | +# bmc_password # string: BMC password (required for power management tests). |
| 52 | +# kubeconfig # string: Path to spoke kubeconfig (alternative to hub_kubeconfig discovery). |
| 53 | +# spoke_kubeconfig # string: Same as kubeconfig, used for oc commands between PTP cycles. |
| 54 | +# labels # string: Test labels filter (e.g. !no-container). |
| 55 | +# ptp_cycle_configs # list: [{name, urls[]}] PTP config cycles to run after ZTP features. |
| 56 | +# # Example: ptp_cycle_configs='[{"name": "ntpfailover", "urls": [ |
| 57 | +# # "https://gitlab.cee.redhat.com/telcov10n/ztp-site-configs-ci/-/raw/ptp_gm/policygentemplates/4.20/ptp-test/PtpConfigGmWpcNtpCustom.yaml", |
| 58 | +# # "https://gitlab.cee.redhat.com/telcov10n/ztp-site-configs-ci/-/raw/ptp_gm/policygentemplates/4.20/ptp-test/PtpConfigSlaveNtpCustom.yaml" |
| 59 | +# # ]}]' |
| 60 | +# eco_gotests_features # list: Features to run in the first cycle (with ZTP PtpConfigs). |
| 61 | +# # Supported values: containernshide, powermanagement, deploymenttypes. |
| 62 | +# # Defaults to all three. Example: eco_gotests_features='["containernshide","powermanagement"]' |
| 63 | +# eco_gotests_tag # string: Override image tag (e.g. "latest", "v4.18.0"). Auto-detects from cluster version if not set. |
| 64 | +# eco_gotest_base_dir # string: Base directory for PTP cycle reports (default: /tmp/eco_gotests_ptp_gm). |
| 65 | +# test_timeout # string: Per-cycle timeout (default: 12h). |
| 66 | +# mirror_registry # string: Disconnected registry URL host:port. |
| 67 | +# cnf_test_image # string: Override ECO_CNF_RAN_TEST_IMAGE passed to the eco-gotests container. |
| 68 | +# additional_test_env_variables # string: Additional env variables for the eco-gotests container (PTP cycles). |
| 69 | + |
| 70 | +- name: Deploy RAN PTP GM tests script |
| 71 | + hosts: bastion |
| 72 | + gather_facts: true |
| 73 | + vars: |
| 74 | + eco_gotests_image: quay.io/ocp-edge-qe/eco-gotests |
| 75 | + eco_gotest_base_dir: /tmp/eco_gotests_ptp_gm |
| 76 | + test_timeout: "12h" |
| 77 | + script_name: "eco-gotests-ptp-gm-run.sh" |
| 78 | + pull_container_image: true |
| 79 | + mirror_registry: "" |
| 80 | + additional_test_env_variables: "" |
| 81 | + auth_kubeconfig_path: "/tmp/auth_kubeconfigs" |
| 82 | + eco_gotests_features: |
| 83 | + - containernshide |
| 84 | + - powermanagement |
| 85 | + - deploymenttypes |
| 86 | + tasks: |
| 87 | + - name: Ensure required variables are defined |
| 88 | + ansible.builtin.assert: |
| 89 | + that: |
| 90 | + - (hub_kubeconfig is defined and spoke_cluster_label_selector is defined) or kubeconfig is defined |
| 91 | + - labels is defined |
| 92 | + - ptp_cycle_configs is defined |
| 93 | + |
| 94 | + - name: Set up kubeconfig directory and discover spoke |
| 95 | + when: hub_kubeconfig is defined |
| 96 | + block: |
| 97 | + - name: Ensure auth_kubeconfig_path directory does not exist |
| 98 | + ansible.builtin.file: |
| 99 | + path: "{{ auth_kubeconfig_path }}" |
| 100 | + state: absent |
| 101 | + |
| 102 | + - name: Ensure auth_kubeconfig directory is present |
| 103 | + ansible.builtin.file: |
| 104 | + path: "{{ auth_kubeconfig_path }}/spokes" |
| 105 | + state: directory |
| 106 | + recurse: true |
| 107 | + mode: "0777" |
| 108 | + |
| 109 | + - name: Get managed cluster (spoke) |
| 110 | + kubernetes.core.k8s_info: |
| 111 | + api_version: cluster.open-cluster-management.io/v1 |
| 112 | + kind: ManagedCluster |
| 113 | + kubeconfig: "{{ hub_kubeconfig }}" |
| 114 | + label_selectors: "{{ spoke_cluster_label_selector }}" |
| 115 | + register: spoke_cluster_info |
| 116 | + |
| 117 | + - name: Get spoke admin kubeconfig secret |
| 118 | + kubernetes.core.k8s_info: |
| 119 | + api_version: v1 |
| 120 | + kind: Secret |
| 121 | + name: "{{ spoke_cluster_info.resources[0].metadata.name }}-admin-kubeconfig" |
| 122 | + namespace: "{{ spoke_cluster_info.resources[0].metadata.name }}" |
| 123 | + kubeconfig: "{{ hub_kubeconfig }}" |
| 124 | + register: spoke_kubeconfig_secret |
| 125 | + |
| 126 | + - name: Get BMC address of spoke |
| 127 | + kubernetes.core.k8s_info: |
| 128 | + api_version: metal3.io/v1alpha1 |
| 129 | + kind: BareMetalHost |
| 130 | + namespace: "{{ spoke_cluster_info.resources[0].metadata.name }}" |
| 131 | + kubeconfig: "{{ hub_kubeconfig }}" |
| 132 | + register: spoke_bmc_host |
| 133 | + |
| 134 | + - name: Extract BMC IP from spoke BMC address |
| 135 | + ansible.builtin.set_fact: |
| 136 | + spoke_bmc_ip: "{{ spoke_bmc_host.resources[0].spec.bmc.address | regex_search('\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}') }}" |
| 137 | + |
| 138 | + - name: Write spoke kubeconfig to test directory |
| 139 | + ansible.builtin.copy: |
| 140 | + content: "{{ spoke_kubeconfig_secret.resources[0].data.kubeconfig | b64decode }}" |
| 141 | + dest: "{{ auth_kubeconfig_path }}/spokes/spoke-kubeconfig" |
| 142 | + mode: "0600" |
| 143 | + |
| 144 | + - name: Set kubeconfig from discovered spoke |
| 145 | + ansible.builtin.set_fact: |
| 146 | + kubeconfig: "{{ auth_kubeconfig_path }}/spokes/spoke-kubeconfig" |
| 147 | + spoke_kubeconfig: "{{ auth_kubeconfig_path }}/spokes/spoke-kubeconfig" |
| 148 | + |
| 149 | + - name: Ensure base directory does not exist |
| 150 | + ansible.builtin.file: |
| 151 | + path: "{{ eco_gotest_base_dir }}" |
| 152 | + state: absent |
| 153 | + |
| 154 | + - name: Ensure base directory is present |
| 155 | + ansible.builtin.file: |
| 156 | + path: "{{ eco_gotest_base_dir }}" |
| 157 | + state: directory |
| 158 | + mode: "0760" |
| 159 | + |
| 160 | + - name: Gather cluster network information |
| 161 | + register: cluster_info |
| 162 | + environment: |
| 163 | + K8S_AUTH_KUBECONFIG: "{{ kubeconfig }}" |
| 164 | + kubernetes.core.k8s_info: |
| 165 | + api: operator.openshift.io/v1 |
| 166 | + kind: Network |
| 167 | + name: cluster |
| 168 | + |
| 169 | + - name: Extract OpenShift version details |
| 170 | + ansible.builtin.set_fact: |
| 171 | + version: "{{ cluster_info.resources[0].status.version.split('.')[0] }}.{{ cluster_info.resources[0].status.version.split('.')[1] }}" |
| 172 | + |
| 173 | + - name: Print cluster version |
| 174 | + ansible.builtin.debug: |
| 175 | + msg: "Cluster version: {{ version }}" |
| 176 | + |
| 177 | + - name: Mirror eco-gotests image to disconnected registry |
| 178 | + when: mirror_registry | default('') | length > 0 |
| 179 | + block: |
| 180 | + - name: Set eco-gotests mirror tag |
| 181 | + ansible.builtin.set_fact: |
| 182 | + eco_gotests_tag: "{{ eco_gotests_tag | default('v' ~ version ~ '.0') }}" |
| 183 | + |
| 184 | + - name: Copy eco-gotests image to disconnected registry |
| 185 | + ansible.builtin.command: > |
| 186 | + skopeo copy |
| 187 | + --dest-tls-verify=false |
| 188 | + docker://{{ eco_gotests_image }}:{{ eco_gotests_tag }} |
| 189 | + docker://{{ mirror_registry }}/{{ eco_gotests_image.split('/')[1:] | join('/') }}:{{ eco_gotests_tag }} |
| 190 | + register: skopeo_result |
| 191 | + changed_when: skopeo_result.rc == 0 |
| 192 | + |
| 193 | + - name: Override eco-gotests image source to disconnected registry |
| 194 | + ansible.builtin.set_fact: |
| 195 | + eco_gotests_image: "{{ mirror_registry }}/{{ eco_gotests_image.split('/')[1:] | join('/') }}" |
| 196 | + |
| 197 | + - name: Mirror PTP images to disconnected registry |
| 198 | + when: mirror_registry | default('') | length > 0 |
| 199 | + block: |
| 200 | + - name: Write pull secret auth file for registry mirroring |
| 201 | + no_log: true |
| 202 | + ansible.builtin.copy: |
| 203 | + content: "{{ pull_secret_string | b64decode }}" |
| 204 | + dest: "{{ pull_secret_file | default('/tmp/auth.json') }}" |
| 205 | + mode: '0600' |
| 206 | + |
| 207 | + - name: Mirror cloud-event-consumer v1 image |
| 208 | + ansible.builtin.command: > |
| 209 | + skopeo copy |
| 210 | + --dest-tls-verify=false |
| 211 | + --all |
| 212 | + docker://quay.io/redhat-cne/cloud-event-consumer:4.18 |
| 213 | + docker://{{ mirror_registry }}/ran-test/cloud-event-consumer:v1 |
| 214 | + register: skopeo_v1_result |
| 215 | + changed_when: skopeo_v1_result.rc == 0 |
| 216 | + |
| 217 | + - name: Mirror cloud-event-consumer v2 image |
| 218 | + ansible.builtin.command: > |
| 219 | + skopeo copy |
| 220 | + --dest-tls-verify=false |
| 221 | + --all |
| 222 | + docker://quay.io/redhat-cne/cloud-event-consumer:latest |
| 223 | + docker://{{ mirror_registry }}/ran-test/cloud-event-consumer:v2 |
| 224 | + register: skopeo_v2_result |
| 225 | + changed_when: skopeo_v2_result.rc == 0 |
| 226 | + |
| 227 | + - name: Mirror ptp-must-gather image (OCP < 4.21 only) |
| 228 | + when: version.split('.')[1] | int < 21 |
| 229 | + ansible.builtin.command: > |
| 230 | + skopeo copy |
| 231 | + --dest-tls-verify=false |
| 232 | + --all |
| 233 | + --authfile {{ pull_secret_file | default('/tmp/auth.json') }} |
| 234 | + docker://registry.redhat.io/openshift4/ptp-must-gather-rhel9:v{{ version }} |
| 235 | + docker://{{ mirror_registry }}/ran-test/ptp-must-gather:v{{ version }} |
| 236 | + register: skopeo_must_gather_result |
| 237 | + changed_when: skopeo_must_gather_result.rc == 0 |
| 238 | + |
| 239 | + - name: Set PTP event consumer mirror fact |
| 240 | + ansible.builtin.set_fact: |
| 241 | + ptp_event_consumer_image: "{{ mirror_registry }}/ran-test/cloud-event-consumer" |
| 242 | + |
| 243 | + - name: Set PTP must-gather mirror fact (OCP < 4.21 only) |
| 244 | + when: version.split('.')[1] | int < 21 |
| 245 | + ansible.builtin.set_fact: |
| 246 | + ptp_must_gather_image: "{{ mirror_registry }}/ran-test/ptp-must-gather:v{{ version }}" |
| 247 | + |
| 248 | + - name: Remove eco-gotests image |
| 249 | + when: pull_container_image is true |
| 250 | + containers.podman.podman_image: |
| 251 | + name: "{{ eco_gotests_image }}" |
| 252 | + state: absent |
| 253 | + tag: "{{ item }}" |
| 254 | + loop: "{{ (['v' + version + '.0', 'latest'] + ([eco_gotests_tag] if eco_gotests_tag is defined else [])) | unique }}" |
| 255 | + |
| 256 | + - name: Pull user-specified eco-gotests image |
| 257 | + when: eco_gotests_tag is defined and pull_container_image is true |
| 258 | + containers.podman.podman_image: |
| 259 | + name: "{{ eco_gotests_image }}" |
| 260 | + tag: "{{ eco_gotests_tag }}" |
| 261 | + |
| 262 | + - name: Try pulling cluster version matched image, fallback to latest if it fails |
| 263 | + when: eco_gotests_tag is not defined and pull_container_image is true |
| 264 | + block: |
| 265 | + - name: Pull a cluster version matched eco-gotests image |
| 266 | + containers.podman.podman_image: |
| 267 | + name: quay.io/ocp-edge-qe/eco-gotests |
| 268 | + tag: v{{ version }}.0 |
| 269 | + |
| 270 | + - name: Set tag to specific version |
| 271 | + ansible.builtin.set_fact: |
| 272 | + eco_gotests_tag: "v{{ version }}.0" |
| 273 | + |
| 274 | + rescue: |
| 275 | + - name: Pull latest version of eco-gotests image as fallback |
| 276 | + containers.podman.podman_image: |
| 277 | + name: quay.io/ocp-edge-qe/eco-gotests |
| 278 | + tag: latest |
| 279 | + |
| 280 | + - name: Set tag to latest |
| 281 | + ansible.builtin.set_fact: |
| 282 | + eco_gotests_tag: latest |
| 283 | + |
| 284 | + - name: Set eco-gotests feature configurations |
| 285 | + ansible.builtin.set_fact: |
| 286 | + _eco_gotests_feature_configs: |
| 287 | + - name: containernshide |
| 288 | + additional_test_env_variables: >- |
| 289 | + -e ECO_TEST_TRACE=true |
| 290 | + -e ECO_VERBOSE_SCRIPT=true |
| 291 | + - name: powermanagement |
| 292 | + additional_test_env_variables: >- |
| 293 | + -e ECO_CNF_RAN_BMC_USERNAME={{ bmc_user | default('') }} |
| 294 | + -e ECO_CNF_RAN_BMC_PASSWORD={{ bmc_password | default('') }} |
| 295 | + -e ECO_CNF_RAN_BMC_HOSTS={{ spoke_bmc_ip | default('') }} |
| 296 | + -e ECO_TEST_TRACE=true |
| 297 | + -e ECO_VERBOSE_SCRIPT=true |
| 298 | + - name: deploymenttypes |
| 299 | + additional_test_env_variables: >- |
| 300 | + -e ECO_CNF_RAN_SKIP_TLS_VERIFY=true |
| 301 | + -e ECO_TEST_TRACE=true |
| 302 | + -e ECO_VERBOSE_SCRIPT=true |
| 303 | +
|
| 304 | + - name: Generate PTP GM test execution script |
| 305 | + ansible.builtin.template: |
| 306 | + src: templates/run_eco_gotests_ptp_gm.j2 |
| 307 | + dest: "{{ eco_gotest_base_dir }}/{{ script_name }}" |
| 308 | + mode: "0764" |
0 commit comments