--- - name: Check if controller has conf/k3s.cfg (optional) ansible.builtin.stat: path: "{{ role_path }}/../../../conf/k3s.cfg" register: _k3s_prole_cfg_stat delegate_to: localhost - name: Load CNPG version from prole.cfg (pinned) ansible.builtin.set_fact: cnpg_version_raw: >- {{ lookup( 'ansible.builtin.ini', 'CNPG_VERSION section=Global file=' ~ (role_path ~ '/../../../conf/k3s.cfg'), default=(k3s_cnpg_version_default | default('1.28.1')), errors='ignore' ) if _k3s_prole_cfg_stat.stat.exists else (k3s_cnpg_version_default | default('1.28.1')) }} - name: Normalize CNPG version ansible.builtin.set_fact: cnpg_version: "{{ cnpg_version_raw | trim | regex_replace('^v', '') }}" - name: Derive CNPG release series from version ansible.builtin.set_fact: cnpg_release_series: "{{ (cnpg_version.split('.')[:2]) | join('.') }}" - 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_version }}.yaml" - 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=' ~ (role_path ~ '/../../../conf/k3s.cfg'), default='', errors='ignore' ) if _k3s_prole_cfg_stat.stat.exists else '' }} - 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_version }}_linux_{{ cnpg_arch }}.tar.gz" cnpg_plugin_url: "https://github.com/cloudnative-pg/cloudnative-pg/releases/download/v{{ cnpg_version }}/kubectl-cnpg_{{ cnpg_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 == '' or ((k3s_cnpg_upgrade | default(false)) | bool and cnpg_plugin_installed_version != cnpg_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 == '' or ((k3s_cnpg_upgrade | default(false)) | bool and cnpg_plugin_installed_version != cnpg_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 == '' or ((k3s_cnpg_upgrade | default(false)) | bool and cnpg_plugin_installed_version != cnpg_version) - name: Check for CNPG controller deployment ansible.builtin.command: kubectl get deployment -n cnpg-system cnpg-controller-manager environment: KUBECONFIG: /etc/rancher/k3s/k3s.yaml register: cnpg_controller_deploy changed_when: false failed_when: false when: cnpg_k3s_api_check.rc == 0 - name: Apply CNPG operator manifest (install only; pinned) 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 - cnpg_controller_deploy.rc != 0 - name: Notify explicit CNPG operator upgrade handler (opt-in) ansible.builtin.debug: msg: "CNPG operator upgrade requested (k3s_cnpg_upgrade=true). Upgrading to pinned CNPG_VERSION={{ cnpg_version }} via handler." changed_when: true notify: - Upgrade CNPG operator when: - cnpg_k3s_api_check.rc == 0 - cnpg_controller_deploy.rc == 0 - (k3s_cnpg_upgrade | default(false)) | bool - name: Verify CNPG controller rollout (new install) 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 - cnpg_controller_deploy.rc != 0 - name: Restart CNPG controller if rollout failed (new install; 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_controller_deploy.rc != 0 - cnpg_rollout_check.rc != 0 changed_when: true - name: Final CNPG controller rollout check (new install) 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 - cnpg_controller_deploy.rc != 0