From e57e4c2d7c9007ab110a2cc103a451aa12f0df97 Mon Sep 17 00:00:00 2001 From: Dmitry Tantsur Date: Tue, 26 Aug 2025 12:49:22 +0200 Subject: [PATCH] Run the ironic-standalone-operator tests as non-voting job Unlike the existing Metal3 job, this one covers a large number of different Ironic configurations and is also sensitive to performance regressions on the API layer. Claude Code was used for the initial pass of converting the existing Github workflow to Ansible. Assisted-By: Claude Code Change-Id: I80490c4ca89ab40d3cdc4ced7964d3dc06cd9a05 Signed-off-by: Dmitry Tantsur --- playbooks/irso-ci/post.yaml | 47 ++++++++++++++++++ playbooks/irso-ci/pre.yaml | 96 +++++++++++++++++++++++++++++++++++++ playbooks/irso-ci/run.yaml | 25 ++++++++++ zuul.d/metal3-jobs.yaml | 36 ++++++++++++-- zuul.d/project.yaml | 2 + 5 files changed, 201 insertions(+), 5 deletions(-) create mode 100644 playbooks/irso-ci/post.yaml create mode 100644 playbooks/irso-ci/pre.yaml create mode 100644 playbooks/irso-ci/run.yaml diff --git a/playbooks/irso-ci/post.yaml b/playbooks/irso-ci/post.yaml new file mode 100644 index 0000000000..0093fe2408 --- /dev/null +++ b/playbooks/irso-ci/post.yaml @@ -0,0 +1,47 @@ +--- +- name: IrSO Functional Tests - Log Collection + hosts: all + gather_facts: no + vars: + local_install_path: /usr/local + logdir: "{{ ansible_user_dir }}/metal3-logs" + junit_output: "{{ logdir }}/report.xml" + junit2html_venv: "{{ ansible_user_dir }}/venv" + environment: + CLUSTER_TYPE: minikube + CONTAINER_RUNTIME: docker + LOGDIR: "{{ ansible_user_dir }}/metal3-logs" + PATH: "{{ local_install_path }}/go/bin:{{ local_install_path }}/bin:{{ ansible_env.PATH }}" + JUNIT_OUTPUT: "{{ junit_output }}" + + tasks: + - name: Collect logs + command: "{{ irso_source }}/test/collect-logs.sh" + ignore_errors: yes + + - name: Check if JUnit report exists + stat: + path: "{{ junit_output }}" + register: junit_report + + - name: Convert the JUnit report to HTML + command: "{{ junit2html_venv }}/bin/junit2html '{{ junit_output }}' '{{ logdir }}/report.html'" + args: + creates: "{{ logdir }}/report.html" + when: junit_report.stat.exists + + - name: Copy logs to the zuul location + synchronize: + src: "{{ logdir }}/" + dest: "{{ zuul.executor.log_root }}/{{ inventory_hostname }}/" + mode: pull + become: true + + - name: Store JUnit report as a Zuul artifact + zuul_return: + data: + zuul: + artifacts: + - name: Test Results + url: 'controller/report.html' + when: junit_report.stat.exists diff --git a/playbooks/irso-ci/pre.yaml b/playbooks/irso-ci/pre.yaml new file mode 100644 index 0000000000..b4d575b412 --- /dev/null +++ b/playbooks/irso-ci/pre.yaml @@ -0,0 +1,96 @@ +--- +- name: IrSO Functional Tests - Preparation + hosts: all + vars: + local_install_path: /usr/local + junit2html_venv: "{{ ansible_user_dir }}/venv" + kubectl_version: "1.33.4" + logdir: "{{ ansible_user_dir }}/metal3-logs" + environment: + PATH: "{{ local_install_path }}/go/bin:{{ local_install_path }}/bin:{{ ansible_env.PATH }}" + + tasks: + - name: Install packages + package: + name: + - docker.io + - python3-venv + state: present + become: yes + + - name: Activate docker + service: + name: docker + state: started + become: yes + + - name: Allow the current user to use docker + user: + name: "{{ ansible_user_id }}" + groups: docker + append: yes + become: yes + + - name: Reset connection to apply group changes + meta: reset_connection + + # NOTE(dtantsur): global pip is deliberately broken in Ubuntu, use venv + - name: Create a venv for junit2html + command: python3 -m venv "{{ junit2html_venv }}" + args: + creates: "{{ junit2html_venv }}" + + - name: Install junit2html + pip: + name: junit2html + executable: "{{ junit2html_venv }}/bin/pip" + + - name: Ensure log directory exists + file: + path: "{{ logdir }}" + state: directory + + - name: Checkout Metal3 repositories + git: + repo: "https://github.com/metal3-io/{{ item.name }}.git" + dest: "{{ item.path }}" + force: yes + loop: + - name: ironic-image + path: "{{ ironic_image_source }}" + - name: ironic-standalone-operator + path: "{{ irso_source }}" + + - name: Calculate go version + shell: make -sC "{{ irso_source }}" go-version 2> /dev/null | tail -n1 + register: go_version + + - name: Download and install Go + unarchive: + src: "https://golang.org/dl/go{{ go_version.stdout | trim }}.linux-amd64.tar.gz" + dest: /usr/local + remote_src: yes + owner: root + group: root + mode: '0755' + become: yes + + - name: Download Kubectl + ansible.builtin.get_url: + url: "https://dl.k8s.io/release/v{{ kubectl_version }}/bin/linux/amd64/kubectl" + dest: "{{ local_install_path }}/bin/kubectl" + mode: '0755' + become: yes + + - name: Download minikube + get_url: + url: https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64 + dest: "{{ local_install_path }}/bin/minikube" + mode: '0755' + become: yes + + - name: Setup minikube cluster + # FIXME(dtantsur): we definitely need to run minikube with --ha so that + # HA tests actually use a multi-replica configuration. Unfortunately, + # I could not make HA minikube work on OpenInfra nodes. + command: minikube start --driver=docker diff --git a/playbooks/irso-ci/run.yaml b/playbooks/irso-ci/run.yaml new file mode 100644 index 0000000000..4335cd7e82 --- /dev/null +++ b/playbooks/irso-ci/run.yaml @@ -0,0 +1,25 @@ +--- +- name: IrSO Functional Tests + hosts: all + vars: + local_install_path: /usr/local + logdir: "{{ ansible_user_dir }}/metal3-logs" + environment: + CLUSTER_TYPE: minikube + CONTAINER_RUNTIME: docker + IRONIC_CUSTOM_IMAGE: localhost/ironic:test + IRONIC_CUSTOM_VERSION: latest + IRONIC_SOURCE: "{{ ansible_user_dir }}/{{ zuul.projects['opendev.org/openstack/ironic'].src_dir }}" + LOGDIR: "{{ logdir }}" + PATH: "{{ local_install_path }}/go/bin:{{ local_install_path }}/bin:{{ ansible_env.PATH }}" + JUNIT_OUTPUT: "{{ logdir }}/report.xml" + + tasks: + - name: Prepare tests + command: "{{ irso_source }}/test/prepare.sh" + + - name: Build and load the image + command: "{{ ironic_image_source }}/hack/prepare-irso-tests.sh" + + - name: Run tests + command: "{{ irso_source }}/test/run.sh" diff --git a/zuul.d/metal3-jobs.yaml b/zuul.d/metal3-jobs.yaml index 34c0e9cc2f..ce539b23bb 100644 --- a/zuul.d/metal3-jobs.yaml +++ b/zuul.d/metal3-jobs.yaml @@ -4,12 +4,9 @@ abstract: true description: Base job for metal3-dev-env based ironic jobs. nodeset: ironic-single-node-noble - run: playbooks/metal3-ci/run.yaml - post-run: playbooks/metal3-ci/post.yaml timeout: 5400 required-projects: - opendev.org/openstack/ironic - - opendev.org/openstack/ironic-inspector irrelevant-files: - ^.*\.rst$ - ^api-ref/.*$ @@ -18,8 +15,6 @@ - ^install-guide/.*$ - ^ironic/locale/.*$ - ^ironic/tests/.*$ - - ^ironic_inspector/locale/.*$ - - ^ironic_inspector/test/.*$ - ^releasenotes/.*$ - ^setup.cfg$ - ^test-requirements.txt$ @@ -29,3 +24,34 @@ name: metal3-integration description: Run metal3 CI on ironic. parent: metal3-base + run: playbooks/metal3-ci/run.yaml + post-run: playbooks/metal3-ci/post.yaml + +- job: + name: metal3-ironic-standalone-operator-functional + description: | + Ironic Standalone Operator functional tests. + + These tests set up a Minikube cluster and create Ironic installations in + various configurations supported by IrSO. The operator itself is only + installed once, its logs are saved in the "controller" directory. Each + test gets its own logs directory based on its name. This directory + contains logs from all created pods, as well as dumps of various helpful + Kubernetes resources. + + Upgrade tests are not currently run by this job because it uses a custom + ironic-image container. + parent: metal3-base + pre-run: playbooks/irso-ci/pre.yaml + run: playbooks/irso-ci/run.yaml + post-run: playbooks/irso-ci/post.yaml + timeout: 7200 + nodeset: ironic-single-node-noble + required-projects: + - opendev.org/openstack/ironic + # FIXME(dtantsur): add these to zuul config and stop cloning manually + # - github.com/metal3-io/ironic-image + # - github.com/metal3-io/ironic-standalone-operator + vars: + ironic_image_source: "{{ ansible_user_dir }}/ironic-image" + irso_source: "{{ ansible_user_dir }}/ironic-standalone-operator" diff --git a/zuul.d/project.yaml b/zuul.d/project.yaml index c4786a5c36..638c28cb3d 100644 --- a/zuul.d/project.yaml +++ b/zuul.d/project.yaml @@ -61,6 +61,8 @@ # stable branches, and as far as we are aware these jobs # can be removed once this branch is made stable. - metal3-integration + - metal3-ironic-standalone-operator-functional: + voting: false # Non-voting jobs - ironic-inspector-tempest: voting: false