Skip to content

Commit 8e482d6

Browse files
Adapt openstack_test stage to OTE after legacy Makefile drop
Upstream openstack-test removed make openstack-tests on release-4.20+ (PR #303). Use make extension / run-suite for those releases and keep the legacy path for older branches still under test. Co-authored-by: Cursor <cursoragent@cursor.com>
1 parent 54d97d5 commit 8e482d6

2 files changed

Lines changed: 228 additions & 10 deletions

File tree

collection/stages/roles/openstack_test/defaults/main.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,12 @@
33
openstack_test_name: openstack-test
44
openstack_testsuite_name: openstack
55
openstack_test_dir: "{{ artifacts_dir }}/{{ openstack_test_name }}"
6+
# Installed binary path is set in run_openstack_test.yml (OTE vs legacy).
67
openstack_test_executable: "{{ home_dir }}/openstack-tests"
78
openstack_test_results_dir: "{{ artifacts_dir }}/{{ openstack_test_name }}-results"
89
openstack_tests_allowlist_file: ""
910
openstack_tests_blocklist_file: ""
1011
openstack_tests_go_version: "{{ tests.default_go_version_target }}"
12+
# OTE (OpenShift Tests Extension) — used when discovered_openshift_release >= 4.20
13+
openstack_test_suite: openstack-test/all
14+
openstack_test_ote_binary_relpath: bin/openstack-test-tests-ext

collection/stages/roles/openstack_test/tasks/run_openstack_test.yml

Lines changed: 224 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
---
2-
- name: Set artifact paths
2+
- name: Set artifact paths and OTE vs legacy mode
33
ansible.builtin.set_fact:
44
all_tests_path: >-
55
{{ openstack_test_results_dir }}/openstack_tests.txt
@@ -9,35 +9,87 @@
99
{{ openstack_tests_blocklist_file | ternary(openstack_test_results_dir + '/blocklist.txt', '') }}
1010
tests_to_run_path: >-
1111
{{ openstack_test_results_dir }}/list_of_tests_to_run.txt
12+
openstack_test_log_path: >-
13+
{{ openstack_test_results_dir }}/{{ openstack_test_name }}.log
14+
openstack_test_junit_path: >-
15+
{{ openstack_test_results_dir }}/junit_e2e_openstack.xml
16+
# Upstream dropped make openstack-tests on release-4.20+ (OTE migration,
17+
# openshift/openstack-test#303 / OSASINFRA-4375). Older release branches
18+
# still ship the legacy target.
19+
openstack_test_use_ote: "{{ discovered_openshift_release is version('4.20', '>=') }}"
1220

13-
- name: Build the openstack-tests for tests in the "openstack-test" repository
21+
- name: Set openstack-test executable path for OTE
22+
ansible.builtin.set_fact:
23+
openstack_test_executable: "{{ home_dir }}/openstack-test-tests-ext"
24+
when: openstack_test_use_ote | bool
25+
26+
- name: Set openstack-test executable path for legacy openshift-tests
27+
ansible.builtin.set_fact:
28+
openstack_test_executable: "{{ home_dir }}/openstack-tests"
29+
when: not (openstack_test_use_ote | bool)
30+
31+
# --- Build ---
32+
# OTE: make extension → bin/openstack-test-tests-ext (openshift/openstack-test#303)
33+
- name: Build the OTE openstack-test extension binary
34+
ansible.builtin.shell: |
35+
source {{ home_dir }}/.bashrc
36+
make extension
37+
args:
38+
chdir: "{{ openstack_test_dir }}"
39+
changed_when: true
40+
when: openstack_test_use_ote | bool
41+
42+
- name: Build the legacy openstack-tests binary
1443
ansible.builtin.shell: |
1544
source {{ home_dir }}/.bashrc
1645
make openstack-tests
1746
args:
1847
chdir: "{{ openstack_test_dir }}"
1948
changed_when: true
49+
when: not (openstack_test_use_ote | bool)
2050

21-
- name: Copy openstack-test executable
51+
- name: Copy OTE openstack-test executable
52+
ansible.builtin.copy:
53+
src: "{{ openstack_test_dir }}/{{ openstack_test_ote_binary_relpath }}"
54+
dest: "{{ openstack_test_executable }}"
55+
mode: u=rwx,g=rwx,o=rwx
56+
remote_src: yes
57+
when: openstack_test_use_ote | bool
58+
59+
- name: Copy legacy openstack-test executable
2260
ansible.builtin.copy:
2361
src: "{{ openstack_test_dir }}/openstack-tests"
2462
dest: "{{ openstack_test_executable }}"
2563
mode: u=rwx,g=rwx,o=rwx
2664
remote_src: yes
65+
when: not (openstack_test_use_ote | bool)
2766

2867
- name: Remove source directory once compilation succeeded
2968
ansible.builtin.file:
3069
path: "{{ openstack_test_dir }}"
3170
state: absent
3271

33-
- name: Prepare {{ all_tests_path }} file with all the tests that can be run
72+
# --- List tests ---
73+
- name: Prepare {{ all_tests_path }} with OTE list (names)
74+
ansible.builtin.shell: >
75+
{{ openstack_test_executable }} list
76+
--suite {{ openstack_test_suite }}
77+
-o names > {{ all_tests_path }}
78+
environment:
79+
OS_CLOUD: "{{ user_cloud }}"
80+
KUBECONFIG: "{{ kubeconfig }}"
81+
changed_when: true
82+
when: openstack_test_use_ote | bool
83+
84+
- name: Prepare {{ all_tests_path }} with legacy dry-run
3485
ansible.builtin.shell: >
3586
{{ openstack_test_executable }} run openshift/openstack
3687
--dry-run > {{ all_tests_path }}
3788
environment:
3889
OS_CLOUD: "{{ user_cloud }}"
3990
KUBECONFIG: "{{ kubeconfig }}"
4091
changed_when: true
92+
when: not (openstack_test_use_ote | bool)
4193

4294
- name: Convert the allowlist YAML files to TXT
4395
ansible.builtin.include_role:
@@ -67,13 +119,102 @@
67119
blocklist_file: "{{ blocklist_path }}"
68120
output_file: "{{ tests_to_run_path }}"
69121

122+
- name: Detect whether allow or block list filtering is active
123+
ansible.builtin.set_fact:
124+
openstack_test_filtering: "{{ (openstack_tests_allowlist_file | length > 0) or (openstack_tests_blocklist_file | length > 0) }}"
125+
70126
- name: Run the openshift tests
71127
block:
72-
- name: Run openstack tests
128+
- name: Run OTE suite (no allow/block filter)
129+
ansible.builtin.shell: >
130+
{{ openstack_test_executable }} run-suite {{ openstack_test_suite }}
131+
--junit-path {{ openstack_test_junit_path }}
132+
> {{ openstack_test_log_path }}
133+
environment:
134+
# RHOSO_KUBECONFIG and SHIFTSTACK_PASS_FILE are required for the observability test
135+
OS_CLOUD: "{{ user_cloud }}"
136+
KUBECONFIG: "{{ kubeconfig }}"
137+
RHOSO_KUBECONFIG: "{{ rhoso_kubeconfig }}"
138+
SHIFTSTACK_PASS_FILE: "{{ kubeadmin_password }}"
139+
changed_when: true
140+
when:
141+
- openstack_test_use_ote | bool
142+
- not (openstack_test_filtering | bool)
143+
144+
# OTE run-test has no --junit-path; pipe filtered names via stdin and
145+
# synthesize junit_e2e_*.xml from JSON results for post_openshift_tests.
146+
- name: Run OTE filtered tests via run-test and write junit
147+
ansible.builtin.shell: |
148+
set -o pipefail
149+
cat {{ tests_to_run_path }} | {{ openstack_test_executable }} run-test \
150+
> {{ openstack_test_log_path }}
151+
python3 - {{ openstack_test_log_path }} {{ openstack_test_junit_path }} <<'PY'
152+
import json
153+
import sys
154+
import xml.etree.ElementTree as ET
155+
156+
log_path, junit_path = sys.argv[1], sys.argv[2]
157+
with open(log_path, encoding="utf-8") as f:
158+
raw = f.read().strip()
159+
if not raw:
160+
results = []
161+
else:
162+
try:
163+
data = json.loads(raw)
164+
results = data if isinstance(data, list) else [data]
165+
except json.JSONDecodeError:
166+
results = []
167+
for line in raw.splitlines():
168+
line = line.strip()
169+
if not line:
170+
continue
171+
try:
172+
results.append(json.loads(line))
173+
except json.JSONDecodeError:
174+
continue
175+
176+
suite = ET.Element("testsuite", name="openstack-test")
177+
for r in results:
178+
name = r.get("name", "unknown")
179+
duration_ms = r.get("duration") or 0
180+
try:
181+
time_s = f"{float(duration_ms) / 1000.0:.3f}"
182+
except (TypeError, ValueError):
183+
time_s = "0"
184+
case = ET.SubElement(suite, "testcase", name=name, time=time_s)
185+
result = (r.get("result") or "").lower()
186+
if result == "failed":
187+
fail = ET.SubElement(case, "failure")
188+
fail.text = r.get("error") or r.get("output") or "failed"
189+
elif result == "skipped":
190+
skip = ET.SubElement(case, "skipped")
191+
skip.text = r.get("output") or "skipped"
192+
suite.set("tests", str(len(results)))
193+
suite.set(
194+
"failures",
195+
str(sum(1 for r in results if (r.get("result") or "").lower() == "failed")),
196+
)
197+
suite.set(
198+
"skipped",
199+
str(sum(1 for r in results if (r.get("result") or "").lower() == "skipped")),
200+
)
201+
ET.ElementTree(suite).write(junit_path, encoding="utf-8", xml_declaration=True)
202+
PY
203+
environment:
204+
OS_CLOUD: "{{ user_cloud }}"
205+
KUBECONFIG: "{{ kubeconfig }}"
206+
RHOSO_KUBECONFIG: "{{ rhoso_kubeconfig }}"
207+
SHIFTSTACK_PASS_FILE: "{{ kubeadmin_password }}"
208+
changed_when: true
209+
when:
210+
- openstack_test_use_ote | bool
211+
- openstack_test_filtering | bool
212+
213+
- name: Run legacy openstack tests
73214
ansible.builtin.shell: >
74215
{{ openstack_test_executable }} run openshift/openstack
75216
-f {{ tests_to_run_path }}
76-
--output-file {{ openstack_test_results_dir }}/{{ openstack_test_name }}.log
217+
--output-file {{ openstack_test_log_path }}
77218
--junit-dir={{ openstack_test_results_dir }} > /dev/null
78219
environment:
79220
# RHOSO_KUBECONFIG and SHIFTSTACK_PASS_FILE are required for the observability test
@@ -82,6 +223,7 @@
82223
RHOSO_KUBECONFIG: "{{ rhoso_kubeconfig }}"
83224
SHIFTSTACK_PASS_FILE: "{{ kubeadmin_password }}"
84225
changed_when: true
226+
when: not (openstack_test_use_ote | bool)
85227

86228
rescue:
87229
- name: Mark the openshift tests as UNSTABLE
@@ -92,21 +234,93 @@
92234
unstable_msg: >-
93235
The openshift test Suite failed.
94236
95-
- name: Get the number of failed openstack tests
237+
- name: Get the number of failed openstack tests (OTE JSON log)
238+
ansible.builtin.shell: |
239+
set -o pipefail
240+
python3 - {{ openstack_test_log_path }} failed <<'PY' || true
241+
import json
242+
import sys
243+
path, want = sys.argv[1], sys.argv[2]
244+
try:
245+
with open(path, encoding="utf-8") as f:
246+
raw = f.read().strip()
247+
except OSError:
248+
print(0)
249+
raise SystemExit
250+
if not raw:
251+
print(0)
252+
raise SystemExit
253+
results = []
254+
try:
255+
data = json.loads(raw)
256+
results = data if isinstance(data, list) else [data]
257+
except json.JSONDecodeError:
258+
for line in raw.splitlines():
259+
line = line.strip()
260+
if not line:
261+
continue
262+
try:
263+
results.append(json.loads(line))
264+
except json.JSONDecodeError:
265+
continue
266+
print(sum(1 for r in results if (r.get("result") or "").lower() == want))
267+
PY
268+
register: number_of_failed_tests
269+
changed_when: false
270+
when: openstack_test_use_ote | bool
271+
272+
- name: Get the number of passed openstack tests (OTE JSON log)
273+
ansible.builtin.shell: |
274+
set -o pipefail
275+
python3 - {{ openstack_test_log_path }} passed <<'PY' || true
276+
import json
277+
import sys
278+
path, want = sys.argv[1], sys.argv[2]
279+
try:
280+
with open(path, encoding="utf-8") as f:
281+
raw = f.read().strip()
282+
except OSError:
283+
print(0)
284+
raise SystemExit
285+
if not raw:
286+
print(0)
287+
raise SystemExit
288+
results = []
289+
try:
290+
data = json.loads(raw)
291+
results = data if isinstance(data, list) else [data]
292+
except json.JSONDecodeError:
293+
for line in raw.splitlines():
294+
line = line.strip()
295+
if not line:
296+
continue
297+
try:
298+
results.append(json.loads(line))
299+
except json.JSONDecodeError:
300+
continue
301+
print(sum(1 for r in results if (r.get("result") or "").lower() == want))
302+
PY
303+
register: number_of_passed_tests
304+
changed_when: false
305+
when: openstack_test_use_ote | bool
306+
307+
- name: Get the number of failed openstack tests (legacy log)
96308
ansible.builtin.shell: >
97309
set -o pipefail &&
98-
grep -e "^failed:" {{ openstack_test_results_dir }}/{{ openstack_test_name }}.log | wc -l
310+
grep -e "^failed:" {{ openstack_test_log_path }} | wc -l
99311
|| true
100312
register: number_of_failed_tests
101313
changed_when: false
314+
when: not (openstack_test_use_ote | bool)
102315

103-
- name: Get the number of passed openstack tests
316+
- name: Get the number of passed openstack tests (legacy log)
104317
ansible.builtin.shell: >
105318
set -o pipefail &&
106-
grep -e "^passed:" {{ openstack_test_results_dir }}/{{ openstack_test_name }}.log | wc -l
319+
grep -e "^passed:" {{ openstack_test_log_path }} | wc -l
107320
|| true
108321
register: number_of_passed_tests
109322
changed_when: false
323+
when: not (openstack_test_use_ote | bool)
110324

111325
# This fail task is added to detect failures in openstack-test execution
112326
- name: Fail the playbook in case there are no failed and passed tests

0 commit comments

Comments
 (0)