Skip to content

Commit c519edd

Browse files
committed
DNM: Add OCP upgrade stage for OSP 18
Port upgrade functionality from openshift-ir-plugin to support sequential OCP upgrades on OSP 18. Supports versions 4.16-4.23, automatically builds upgrade paths skipping unsupported versions like 4.17. Includes version-specific workarounds for 4.16 consoleplugins and 4.19 k8s API acknowledgment. Collects must-gather on failure. Change-Id: I8c0b804cb91774fb5bb5fccf47cdb6015d46d771 Signed-off-by: Daniel Lawton <dlawton@redhat.com>
1 parent 736ee2b commit c519edd

10 files changed

Lines changed: 398 additions & 0 deletions

File tree

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
---
2+
# Target version to upgrade to (e.g., "4.21")
3+
# This should be set in job definitions
4+
upgrade_target_version: ""
5+
6+
# Optional: specific build name to upgrade to (e.g., "4.19.3")
7+
# If empty, will use latest from channel
8+
upgrade_build_name: ""
9+
10+
# Optional: release channel (candidate, fast, stable, eus)
11+
# Used if upgrade_build_name is empty
12+
upgrade_channel: "candidate"
13+
14+
# Wait parameters for health checks
15+
wait_retries: 90
16+
wait_delay: 120
17+
18+
# OSP 18 supported OCP versions
19+
# Note: 4.17 is NOT supported on OSP 18
20+
osp18_supported_versions:
21+
- "4.16"
22+
- "4.18"
23+
- "4.19"
24+
- "4.20"
25+
- "4.21"
26+
- "4.22"
27+
- "4.23"
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
---
2+
collections:
3+
- shiftstack.tools
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
---
2+
# Main entry point - orchestrates sequential OCP upgrades
3+
# This role upgrades from the current cluster version to upgrade_target_version
4+
# following OSP 18 supported version path (skipping unsupported versions like 4.17)
5+
6+
- name: Validate required variables
7+
ansible.builtin.assert:
8+
that:
9+
- upgrade_target_version is defined
10+
- upgrade_target_version | length > 0
11+
fail_msg: "upgrade_target_version must be defined (e.g., '4.21')"
12+
13+
- name: Discover current OCP version
14+
ansible.builtin.include_role:
15+
name: shiftstack.tools.tools_get_deploy_info
16+
tasks_from: discover_ocp_version.yml
17+
18+
- name: Display current cluster version
19+
ansible.builtin.debug:
20+
msg: "Current OCP version: {{ discovered_openshift_release }}"
21+
22+
- name: Build upgrade path from current version to target (only OSP 18 supported versions)
23+
ansible.builtin.set_fact:
24+
upgrade_path: "{{ osp18_supported_versions |
25+
select('version', discovered_openshift_release, '>') |
26+
select('version', upgrade_target_version, '<=') |
27+
list }}"
28+
29+
- name: Validate upgrade path is not empty
30+
ansible.builtin.assert:
31+
that:
32+
- upgrade_path | length > 0
33+
fail_msg: |
34+
No upgrade path found from {{ discovered_openshift_release }} to {{ upgrade_target_version }}.
35+
OSP 18 supported versions: {{ osp18_supported_versions | join(', ') }}
36+
success_msg: "Upgrade path validated: {{ discovered_openshift_release }} → {{ upgrade_path | join(' → ') }}"
37+
38+
- name: Display upgrade path
39+
ansible.builtin.debug:
40+
msg: "Upgrade path: {{ discovered_openshift_release }} → {{ upgrade_path | join(' → ') }}"
41+
42+
- name: Execute sequential upgrades
43+
ansible.builtin.include_tasks: single_upgrade.yml
44+
loop: "{{ upgrade_path }}"
45+
loop_control:
46+
loop_var: target_release
47+
label: "Upgrade to {{ target_release }}"
48+
49+
- name: Display upgrade completion
50+
ansible.builtin.debug:
51+
msg: "Successfully upgraded cluster from {{ discovered_openshift_release }} to {{ upgrade_target_version }}"
Lines changed: 228 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,228 @@
1+
---
2+
# Single upgrade step: upgrade from current version to target_release
3+
# This file is included in a loop from main.yml with target_release variable
4+
5+
- name: Check cluster health before upgrading to {{ target_release }}
6+
ansible.builtin.include_role:
7+
name: shiftstack.tools.tools_cluster_checks
8+
vars:
9+
actions:
10+
- wait_until_cluster_is_healthy
11+
- wait_until_nodes_ready
12+
- wait_until_no_unschedulable_nodes
13+
wait_retries: 1
14+
wait_delay: 0
15+
16+
- name: Get the ClusterVersion object before upgrade
17+
ansible.builtin.shell: |
18+
oc get clusterversion version -o json
19+
register: cluster_version_json_before
20+
changed_when: false
21+
22+
- name: Parse ClusterVersion before upgrade
23+
ansible.builtin.set_fact:
24+
cluster_version_before_upgrade: "{{ cluster_version_json_before.stdout | from_json }}"
25+
26+
- name: Get current cluster version from history
27+
ansible.builtin.set_fact:
28+
current_version: "{{ cluster_version_before_upgrade.status.history[0].version }}"
29+
30+
- name: Check the version to upgrade to is >= the current version
31+
ansible.builtin.assert:
32+
that:
33+
- target_release is version(current_version | regex_replace('^(\\d+\\.\\d+).*', '\\1'), '>=')
34+
fail_msg: "The version to upgrade to ({{ target_release }}) must be >= the current version ({{ current_version }})"
35+
36+
- name: Get the OCP release build name to upgrade to
37+
ansible.builtin.include_role:
38+
name: shiftstack.tools.tools_get_openshift_release
39+
tasks_from: get_openshift_release_build_name.yml
40+
vars:
41+
openshift_release: "{{ target_release }}"
42+
openshift_build_name: "{{ upgrade_build_name }}"
43+
44+
- name: Print upgrade versions
45+
ansible.builtin.debug:
46+
msg: "Upgrading FROM: '{{ current_version }}' TO: '{{ openshift_release_build_name }}'"
47+
48+
- name: Mark the OpenShift version to upgrade to
49+
ansible.builtin.debug:
50+
msg: "Build mark: upgrade_to={{ openshift_release_build_name }}"
51+
52+
# Version-specific workarounds for OSP 18
53+
- name: Set patch data for consoleplugins (4.16 only)
54+
ansible.builtin.set_fact:
55+
console_patch:
56+
storedVersions:
57+
- v1
58+
when: openshift_release_build_name is regex('^4\\.16\\..*')
59+
60+
- name: Set consoleplugins to v1 for 4.16 upgrade
61+
ansible.builtin.shell: |
62+
oc patch crd consoleplugins.console.openshift.io --subresource='status' --type="merge" -p '{{ console_patch | to_json }}'
63+
when: openshift_release_build_name is regex('^4\\.16\\..*')
64+
changed_when: true
65+
66+
- name: Set ack data for 4.19 upgrade handholding
67+
ansible.builtin.set_fact:
68+
ack419_patch:
69+
data:
70+
ack-4.18-kube-1.32-api-removals-in-4.19: "true"
71+
when: openshift_release_build_name is regex('^4\\.19\\..*')
72+
73+
- name: Manual ack for 4.19 upgrade (k8s 1.32 API removals)
74+
ansible.builtin.shell: |
75+
oc -n openshift-config patch cm admin-acks --type="merge" -p '{{ ack419_patch | to_json }}'
76+
when: openshift_release_build_name is regex('^4\\.19\\..*')
77+
changed_when: true
78+
79+
# Get the digest ID from the release image
80+
- name: Create secret.json for OCP release info
81+
ansible.builtin.copy:
82+
content: "{{ ocp_pull_secret }}"
83+
dest: /tmp/secret.json
84+
mode: '0600'
85+
86+
- name: Get the OCP release digest
87+
ansible.builtin.shell: |
88+
oc adm release info registry.ci.openshift.org/ocp/release:{{ openshift_release_build_name }} --registry-config=/tmp/secret.json | grep Digest | awk '{print $2}'
89+
register: release_digest
90+
changed_when: false
91+
92+
- name: Display release digest
93+
ansible.builtin.debug:
94+
msg: "{{ openshift_release_build_name }} release digest: {{ release_digest.stdout }}"
95+
96+
- name: Run openshift upgrade command
97+
ansible.builtin.shell: |
98+
oc adm upgrade --to-image=registry.ci.openshift.org/ocp/release@{{ release_digest.stdout }} --allow-explicit-upgrade --force
99+
register: upgrade
100+
changed_when: true
101+
102+
- name: Display upgrade command output
103+
ansible.builtin.debug:
104+
var: upgrade
105+
106+
- name: Check the upgrade command returns ok
107+
ansible.builtin.assert:
108+
that:
109+
- upgrade.rc == 0
110+
fail_msg: "oc adm upgrade command returned {{ upgrade.rc }} and stderr {{ upgrade.stderr_lines }}"
111+
112+
- name: Set upgrade start datetime
113+
ansible.builtin.set_fact:
114+
start_time: "{{ lookup('pipe', 'date +%Y-%m-%dT%H:%M:%S') }}"
115+
116+
- name: Wait until the upgrade starts (Progressing=True)
117+
ansible.builtin.shell: |
118+
oc get clusterversion version -o json | jq '.status.conditions[] | select(.type=="Progressing" and .status=="True")'
119+
register: progressing_check
120+
until: progressing_check.stdout | length > 0
121+
retries: 20
122+
delay: 15
123+
changed_when: false
124+
125+
# Main upgrade validation block with must-gather rescue
126+
- name: Block for upgrade checks with must-gather on failure
127+
block:
128+
- name: Wait until the upgrade is completed (cluster is healthy)
129+
ansible.builtin.include_role:
130+
name: shiftstack.tools.tools_cluster_checks
131+
vars:
132+
actions:
133+
- wait_until_cluster_is_healthy
134+
wait_retries: 90
135+
wait_delay: 120
136+
137+
- name: Wait until cluster nodes are ready after OCP upgrade
138+
ansible.builtin.include_role:
139+
name: shiftstack.tools.tools_cluster_checks
140+
vars:
141+
actions:
142+
- wait_until_nodes_ready
143+
wait_retries: 80
144+
wait_delay: 30
145+
146+
- name: Wait until there are no unschedulable nodes after OCP upgrade
147+
ansible.builtin.include_role:
148+
name: shiftstack.tools.tools_cluster_checks
149+
vars:
150+
actions:
151+
- wait_until_no_unschedulable_nodes
152+
wait_retries: 80
153+
wait_delay: 30
154+
155+
- name: Set upgrade finish datetime
156+
ansible.builtin.set_fact:
157+
finish_time: "{{ lookup('pipe', 'date +%Y-%m-%dT%H:%M:%S') }}"
158+
159+
- name: Set the upgrade execution time in minutes
160+
ansible.builtin.set_fact:
161+
upgrade_time: "{{ ( ((finish_time | to_datetime('%Y-%m-%dT%H:%M:%S')) - (start_time | to_datetime('%Y-%m-%dT%H:%M:%S'))).total_seconds() / 60 ) | int }}"
162+
163+
- name: Mark the upgrade execution time
164+
ansible.builtin.debug:
165+
msg: "Build mark: upgrade_minutes={{ upgrade_time }}"
166+
167+
- name: Check there are no pods in CrashLoopBackOff
168+
ansible.builtin.include_role:
169+
name: shiftstack.tools.tools_cluster_checks
170+
vars:
171+
actions:
172+
- check_no_crashloopbackoff
173+
174+
- name: Wait until the running cluster pods are ready after OCP upgrade
175+
ansible.builtin.include_role:
176+
name: shiftstack.tools.tools_cluster_checks
177+
vars:
178+
actions:
179+
- wait_until_pods_ready
180+
wait_retries: 20
181+
wait_delay: 30
182+
183+
- name: Get the ClusterVersion object after upgrade
184+
ansible.builtin.shell: |
185+
oc get clusterversion version -o json
186+
register: cluster_version_json_after
187+
changed_when: false
188+
189+
- name: Parse ClusterVersion after upgrade
190+
ansible.builtin.set_fact:
191+
cluster_version_after: "{{ cluster_version_json_after.stdout | from_json }}"
192+
193+
- name: Check the upgraded cluster version is the desired one
194+
ansible.builtin.assert:
195+
that:
196+
- cluster_version_after.status.history[0].version == openshift_release_build_name
197+
fail_msg: "Cluster upgraded to '{{ cluster_version_after.status.history[0].version }}' instead of '{{ openshift_release_build_name }}'"
198+
success_msg: "Cluster successfully upgraded to '{{ cluster_version_after.status.history[0].version }}'"
199+
200+
- name: Check cluster operators are ready after the OCP upgrade
201+
ansible.builtin.include_role:
202+
name: shiftstack.tools.tools_cluster_checks
203+
vars:
204+
actions:
205+
- check_cluster_operators
206+
release_name: "{{ openshift_release_build_name | default('') }}"
207+
208+
rescue:
209+
- name: Run must-gather for failed upgrade
210+
ansible.builtin.include_role:
211+
name: shiftstack.tools.tools_must-gather
212+
vars:
213+
must_gather_dir_suffix: "must-gather-upgrade-{{ target_release }}"
214+
215+
- name: Fail inside rescue block
216+
ansible.builtin.fail:
217+
msg: "The cluster is not healthy after the upgrade to {{ target_release }}. Check must-gather artifacts."
218+
219+
# Post-upgrade tasks
220+
- name: Get the installer and oc client binaries for {{ openshift_release_build_name }} release
221+
ansible.builtin.include_role:
222+
name: shiftstack.tools.tools_get_openshift_release
223+
tasks_from: get_openshift_release_binaries.yml
224+
vars:
225+
binaries:
226+
- installer
227+
- client
228+
release_name: "{{ openshift_release_build_name | default('') }}"
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
---
2+
# Example job: Single-hop upgrade on OSP 18
3+
# Upgrades from 4.16 to 4.18 (skipping 4.17 which is not supported on OSP 18)
4+
openshift_release: 4.16
5+
installation_type: ipi
6+
stages:
7+
- cleanup
8+
- prepare
9+
- install
10+
- post
11+
- verification
12+
- upgrade
13+
14+
# Target version for upgrade stage
15+
upgrade_target_version: "4.18"
16+
upgrade_channel: candidate
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
---
2+
# Example job: Full OSP 18 upgrade chain
3+
# Sequential upgrade: 4.16 → 4.18 → 4.19 → 4.20 → 4.21
4+
# Note: OSP 18 supports 4.16, 4.18, 4.19, 4.20, 4.21 (NOT 4.17)
5+
openshift_release: 4.16
6+
installation_type: ipi
7+
stages:
8+
- cleanup
9+
- prepare
10+
- install
11+
- post
12+
- verification
13+
- upgrade
14+
15+
# Target version for upgrade stage
16+
upgrade_target_version: "4.21"
17+
upgrade_channel: candidate
18+
19+
# Optional: Enable availability zones for testing CPMS updates
20+
# provision_az_enable: true
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
---
2+
# Example job: Upgrade from 4.19 to 4.21 on OSP 18
3+
# Tests the 4.19 ACK workaround when upgrading TO 4.19
4+
openshift_release: 4.19
5+
installation_type: ipi
6+
stages:
7+
- cleanup
8+
- prepare
9+
- install
10+
- post
11+
- verification
12+
- upgrade
13+
14+
# Target version for upgrade stage
15+
upgrade_target_version: "4.21"
16+
upgrade_channel: candidate
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
---
2+
# Example job: Upgrade from 4.22 to 4.23 on OSP 18
3+
# Single-hop upgrade for testing latest versions
4+
openshift_release: 4.22
5+
installation_type: ipi
6+
stages:
7+
- cleanup
8+
- prepare
9+
- install
10+
- post
11+
- verification
12+
- upgrade
13+
14+
# Target version for upgrade stage
15+
upgrade_target_version: "4.23"
16+
upgrade_channel: candidate

playbooks/ocp_testing.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,10 @@
8484
ansible.builtin.import_playbook: plays/verification.yaml
8585
when: "'verification' in stages"
8686

87+
- name: Upgrade OpenShift cluster
88+
ansible.builtin.import_playbook: plays/upgrade.yaml
89+
when: "'upgrade' in stages"
90+
8791
- name: Day2ops OpenShift stage
8892
ansible.builtin.import_playbook: plays/day2ops.yaml
8993
when: "'day2ops' in stages"

0 commit comments

Comments
 (0)