--- - name: Load CNPG release series from prole.cfg ansible.builtin.set_fact: cnpg_release_series_raw: "{{ lookup('ansible.builtin.ini', 'CNPG_RELEASE_SERIES section=Global file=' + playbook_dir + '/../../conf/prole.cfg', default='1.28') }}" - name: Normalize CNPG release series ansible.builtin.set_fact: cnpg_release_series: "{{ cnpg_release_series_raw | trim | regex_replace('^v', '') }}" - name: Resolve latest CNPG release for series ansible.builtin.shell: | python3 - <<'PY' import json import sys import urllib.request series = "{{ cnpg_release_series }}" url = "https://api.github.com/repos/cloudnative-pg/cloudnative-pg/releases?per_page=100" try: with urllib.request.urlopen(url, timeout=10) as resp: data = json.load(resp) except Exception: print("") sys.exit(0) versions = [] for rel in data: tag = (rel.get("tag_name") or "").lstrip("v") if tag.startswith(series + "."): try: tuple(int(x) for x in tag.split(".")) versions.append(tag) except ValueError: continue if not versions: print("") sys.exit(0) def parse(v): return tuple(int(x) for x in v.split(".")) versions.sort(key=parse) print(versions[-1]) PY register: cnpg_latest_version_cmd changed_when: false run_once: true delegate_to: localhost become: false - name: Cache CNPG latest version ansible.builtin.set_fact: cnpg_latest_version: "{{ (cnpg_latest_version_cmd.stdout | trim) if (cnpg_latest_version_cmd.stdout | trim) else (cnpg_release_series ~ '.0') }}" run_once: true delegate_to: localhost delegate_facts: true become: false - name: Share CNPG latest version ansible.builtin.set_fact: cnpg_latest_version: "{{ hostvars['localhost'].cnpg_latest_version }}" - name: Build CNPG manifest URL ansible.builtin.set_fact: cnpg_manifest_url: "https://raw.githubusercontent.com/cloudnative-pg/cloudnative-pg/release-{{ cnpg_release_series }}/releases/cnpg-{{ cnpg_latest_version }}.yaml" - name: Check prole.cfg on controller ansible.builtin.stat: path: "{{ playbook_dir }}/../../conf/prole.cfg" register: cnpg_prole_cfg run_once: true delegate_to: localhost become: false - name: Save CNPG release series to prole.cfg ansible.builtin.lineinfile: path: "{{ playbook_dir }}/../../conf/prole.cfg" regexp: '^CNPG_RELEASE_SERIES\s*=' line: "CNPG_RELEASE_SERIES = {{ cnpg_release_series }}" insertafter: '^\[Global\]' run_once: true delegate_to: localhost become: false when: cnpg_prole_cfg.stat.exists - name: Save CNPG version to prole.cfg ansible.builtin.lineinfile: path: "{{ playbook_dir }}/../../conf/prole.cfg" regexp: '^CNPG_VERSION\s*=' line: "CNPG_VERSION = {{ cnpg_latest_version }}" insertafter: '^\[Global\]' run_once: true delegate_to: localhost become: false when: cnpg_prole_cfg.stat.exists - name: Load k3s server URL from prole.cfg ansible.builtin.set_fact: cnpg_prole_k3s_server_cfg: "{{ lookup('ansible.builtin.ini', 'PROLE_K3S_SERVER section=Global file=' + playbook_dir + '/../../conf/prole.cfg', default='') }}" - name: Resolve k3s API URL for kubectl ansible.builtin.set_fact: cnpg_k3s_server_url_raw: >- {{ (k3s_server_url | default('')) if (k3s_server_url | default('') | length > 0) else (cnpg_prole_k3s_server_cfg | default('')) if (cnpg_prole_k3s_server_cfg | default('') | length > 0) else 'https://' + inventory_hostname + ':6443' }} - name: Normalize k3s API URL for kubectl ansible.builtin.set_fact: cnpg_k3s_server_url: "{{ cnpg_k3s_server_url_raw if cnpg_k3s_server_url_raw.startswith('http') else 'https://' + cnpg_k3s_server_url_raw }}" - name: Check for local k3s kubeconfig ansible.builtin.stat: path: /etc/rancher/k3s/k3s.yaml register: cnpg_kubeconfig_stat - name: Ensure k3s kubeconfig for kubectl on hosts ansible.builtin.copy: dest: /etc/rancher/k3s/k3s.yaml owner: root group: "{{ k3s_kubeconfig_group | default('root') }}" mode: "{{ k3s_write_kubeconfig_mode | default('0640') }}" content: | apiVersion: v1 kind: Config clusters: - cluster: server: {{ cnpg_k3s_server_url }} insecure-skip-tls-verify: true name: prole-k3s contexts: - context: cluster: prole-k3s user: prole-k3s name: prole-k3s current-context: prole-k3s users: - name: prole-k3s user: token: {{ k3s_token }} when: - not cnpg_kubeconfig_stat.stat.exists - cnpg_k3s_server_url | length > 0 - k3s_token | default('') | length > 0 - name: Check k3s API availability for CNPG ansible.builtin.command: kubectl get nodes environment: KUBECONFIG: /etc/rancher/k3s/k3s.yaml register: cnpg_k3s_api_check changed_when: false failed_when: false - name: Map kubectl-cnpg architecture ansible.builtin.set_fact: cnpg_arch_map: x86_64: x86_64 amd64: x86_64 aarch64: arm64 arm64: arm64 ppc64le: ppc64le s390x: s390x - name: Set cnpg architecture and supported arches ansible.builtin.set_fact: cnpg_arch: "{{ cnpg_arch_map.get(ansible_architecture, ansible_architecture) }}" cnpg_supported_arches: - x86_64 - arm64 - ppc64le - s390x - name: Check kubectl-cnpg version ansible.builtin.command: kubectl cnpg version register: cnpg_plugin_version_check changed_when: false failed_when: false - name: Parse installed kubectl-cnpg version ansible.builtin.set_fact: cnpg_plugin_installed_version: "{{ (cnpg_plugin_version_check.stdout ~ ' ' ~ cnpg_plugin_version_check.stderr) | regex_search('Version:([0-9]+\\.[0-9]+\\.[0-9]+)', '\\1') | default('') }}" - name: Build kubectl-cnpg download URL ansible.builtin.set_fact: cnpg_plugin_asset: "kubectl-cnpg_{{ cnpg_latest_version }}_linux_{{ cnpg_arch }}.tar.gz" cnpg_plugin_url: "https://github.com/cloudnative-pg/cloudnative-pg/releases/download/v{{ cnpg_latest_version }}/kubectl-cnpg_{{ cnpg_latest_version }}_linux_{{ cnpg_arch }}.tar.gz" when: cnpg_arch in cnpg_supported_arches - name: Download kubectl-cnpg ansible.builtin.get_url: url: "{{ cnpg_plugin_url }}" dest: "/tmp/{{ cnpg_plugin_asset }}" mode: "0644" when: - cnpg_arch in cnpg_supported_arches - cnpg_plugin_installed_version != cnpg_latest_version - name: Install kubectl-cnpg ansible.builtin.unarchive: src: "/tmp/{{ cnpg_plugin_asset }}" dest: /usr/local/bin remote_src: true when: - cnpg_arch in cnpg_supported_arches - cnpg_plugin_installed_version != cnpg_latest_version - name: Ensure kubectl-cnpg is executable ansible.builtin.file: path: /usr/local/bin/kubectl-cnpg mode: "0755" when: - cnpg_arch in cnpg_supported_arches - cnpg_plugin_installed_version != cnpg_latest_version - name: Apply CNPG operator manifest ansible.builtin.command: kubectl apply --server-side -f {{ cnpg_manifest_url }} environment: KUBECONFIG: /etc/rancher/k3s/k3s.yaml register: cnpg_apply changed_when: "'created' in cnpg_apply.stdout or 'configured' in cnpg_apply.stdout" when: cnpg_k3s_api_check.rc == 0 - name: Verify CNPG controller rollout ansible.builtin.command: kubectl rollout status deployment -n cnpg-system cnpg-controller-manager --timeout=60s environment: KUBECONFIG: /etc/rancher/k3s/k3s.yaml register: cnpg_rollout_check changed_when: false failed_when: false when: cnpg_k3s_api_check.rc == 0 - name: Restart CNPG controller if rollout failed (possibly stuck on tainted node) ansible.builtin.command: kubectl rollout restart deployment -n cnpg-system cnpg-controller-manager environment: KUBECONFIG: /etc/rancher/k3s/k3s.yaml when: - cnpg_k3s_api_check.rc == 0 - cnpg_rollout_check.rc != 0 changed_when: true - name: Final CNPG controller rollout check ansible.builtin.command: kubectl rollout status deployment -n cnpg-system cnpg-controller-manager --timeout=300s environment: KUBECONFIG: /etc/rancher/k3s/k3s.yaml changed_when: false when: cnpg_k3s_api_check.rc == 0