From ff4de880ae54c36120e7ac562df9e692b050e06f Mon Sep 17 00:00:00 2001 From: Max Gautier Date: Wed, 13 Nov 2024 16:01:17 +0100 Subject: [PATCH] CI: Replace kubevirt dynamic inventory with generated yaml VirtualMachineInstance resources sometimes temporarily loose their IP (at least as far as the kubevirt controllers can see). See https://github.com/kubevirt/kubevirt/issues/12698 for the upstream bug. This does not seems to affect actual connection (if it did, our current CI would not work). However, our CI execute multiple playbooks, and in particular: 1. The provisioning playbook (which checks that the IPs have been provisioned by querying the K8S API) 2. Kubespray itself If any of the VirtualMachineInstance looses its IP between after 1 checked for it, and before 2 starts, the dynamic inventory (which is invoked when the playbook is launched by ansible-playbook) will not have an ip for that host, and will try to use the name for ssh, which of course will not work. Instead, when we have a valid state during provisioning (all IPs presents), use it to construct a static inventory which will be used for the rest of the CI run. --- pipeline.Dockerfile | 2 +- .../roles/packet-ci/tasks/create-vms.yml | 26 ++++++++++++++++--- .../packet-ci/templates/inv.kubevirt.yml.j2 | 16 ------------ .../roles/packet-ci/templates/vm.yml.j2 | 5 ++-- 4 files changed, 25 insertions(+), 24 deletions(-) delete mode 100644 tests/cloud_playbooks/roles/packet-ci/templates/inv.kubevirt.yml.j2 diff --git a/pipeline.Dockerfile b/pipeline.Dockerfile index a8af1897b..49d00ae4f 100644 --- a/pipeline.Dockerfile +++ b/pipeline.Dockerfile @@ -60,4 +60,4 @@ RUN update-alternatives --install /usr/bin/python python /usr/bin/python3 1 \ && vagrant plugin install vagrant-libvirt \ # Install Kubernetes collections && pip install --no-compile --no-cache-dir kubernetes \ - && ansible-galaxy collection install kubernetes.core kubevirt.core + && ansible-galaxy collection install kubernetes.core diff --git a/tests/cloud_playbooks/roles/packet-ci/tasks/create-vms.yml b/tests/cloud_playbooks/roles/packet-ci/tasks/create-vms.yml index 30e27c76f..21206e888 100644 --- a/tests/cloud_playbooks/roles/packet-ci/tasks/create-vms.yml +++ b/tests/cloud_playbooks/roles/packet-ci/tasks/create-vms.yml @@ -21,8 +21,26 @@ retries: 30 delay: 10 -- name: "Create inventory for CI tests" - template: - src: "inv.kubevirt.yml.j2" - dest: "{{ inventory_path }}/inv.kubevirt.yml" +- name: Massage VirtualMachineInstance data into an Ansible inventory structure + vars: + ips: "{{ vmis.resources | map(attribute='status.interfaces.0.ipAddress') }}" + names: "{{ vmis.resources | map(attribute='metadata.name') }}" + _groups: "{{ vmis.resources | map(attribute='metadata.annotations.ansible_groups') | map('split', ',') }}" + hosts: "{{ ips | zip(_groups, names) + | map('zip', ['ansible_host', 'ansible_groups', 'k8s_vmi_name']) + | map('map', 'reverse') | map('community.general.dict') }}" + loop: "{{ hosts | map(attribute='ansible_groups') | flatten | unique }}" + set_fact: + ci_inventory: "{{ ci_inventory|d({}) | combine({ + item: { + 'hosts': hosts | selectattr('ansible_groups', 'contains', item) + | rekey_on_member('k8s_vmi_name') + } + }) + }}" + +- name: Create inventory for CI tests + copy: + content: "{{ ci_inventory | to_yaml }}" + dest: "{{ inventory_path }}/ci_inventory.yml" mode: "0644" diff --git a/tests/cloud_playbooks/roles/packet-ci/templates/inv.kubevirt.yml.j2 b/tests/cloud_playbooks/roles/packet-ci/templates/inv.kubevirt.yml.j2 deleted file mode 100644 index 435a5f5c3..000000000 --- a/tests/cloud_playbooks/roles/packet-ci/templates/inv.kubevirt.yml.j2 +++ /dev/null @@ -1,16 +0,0 @@ -plugin: kubevirt.core.kubevirt -namespaces: -- {{ pod_namespace }} -label_selector: ci_job_id={{ ci_job_id }} -create_groups: true -compose: - ci_groups: | - group_names | - select('ansible.builtin.match', 'label_kubespray_io*') | - map('regex_replace', 'label_kubespray_io_(.*)_true', '\1') -use_service: false -host_format: "{name}" -keyed_groups: -- key: ci_groups - prefix: "" - separator: "" diff --git a/tests/cloud_playbooks/roles/packet-ci/templates/vm.yml.j2 b/tests/cloud_playbooks/roles/packet-ci/templates/vm.yml.j2 index 139103c72..920944963 100644 --- a/tests/cloud_playbooks/roles/packet-ci/templates/vm.yml.j2 +++ b/tests/cloud_playbooks/roles/packet-ci/templates/vm.yml.j2 @@ -6,15 +6,14 @@ metadata: namespace: {{ pod_namespace }} annotations: kubespray.com/ci.template-path: "tests/cloud_playbooks/roles/packet-ci/templates/vm.yml.j2" + ansible_groups: "{{ kubespray_groups | join(',') }}" + # This does not use a dns prefix because dots are hard to escape with map(attribute=) in Jinja labels: kubevirt.io/os: {{ cloud_image }} kubevirt.io/size: small kubevirt.io/domain: "{{ test_name }}" ci_job_id: "{{ ci_job_id }}" ci_job_name: "{{ ci_job_name }}" - {% for group in kubespray_groups -%} - kubespray.io/{{ group }}: "true" - {% endfor -%} # leverage the Kubernetes GC for resources cleanup ownerReferences: - apiVersion: v1