---
- name: Gen_certs | create etcd cert dir
  file:
    path: "{{ etcd_cert_dir }}"
    group: "{{ etcd_cert_group }}"
    state: directory
    owner: "{{ etcd_owner }}"
    mode: "0700"

- name: "Gen_certs | create etcd script dir (on {{ groups['etcd'][0] }})"
  file:
    path: "{{ etcd_script_dir }}"
    state: directory
    owner: root
    mode: "0700"
  run_once: true
  when: inventory_hostname == groups['etcd'][0]

- name: Gen_certs | write openssl config
  template:
    src: "openssl.conf.j2"
    dest: "{{ etcd_config_dir }}/openssl.conf"
    mode: "0640"
  run_once: true
  delegate_to: "{{ groups['etcd'][0] }}"
  when:
    - gen_certs | default(false)
    - inventory_hostname == groups['etcd'][0]

- name: Gen_certs | copy certs generation script
  template:
    src: "make-ssl-etcd.sh.j2"
    dest: "{{ etcd_script_dir }}/make-ssl-etcd.sh"
    mode: "0700"
  run_once: true
  when:
    - inventory_hostname == groups['etcd'][0]

- name: Gen_certs | run cert generation script for etcd and kube control plane nodes
  command: "bash -x {{ etcd_script_dir }}/make-ssl-etcd.sh -f {{ etcd_config_dir }}/openssl.conf -d {{ etcd_cert_dir }}"
  environment:
    MASTERS: "{{ groups['gen_master_certs_True'] | ansible.builtin.intersect(groups['etcd']) | join(' ') }}"
    HOSTS: "{{ groups['gen_node_certs_True'] | ansible.builtin.intersect(groups['kube_control_plane']) | join(' ') }}"
  run_once: true
  delegate_to: "{{ groups['etcd'][0] }}"
  when: gen_certs | default(false)
  notify: Set etcd_secret_changed

- name: Gen_certs | run cert generation script for all clients
  command: "bash -x {{ etcd_script_dir }}/make-ssl-etcd.sh -f {{ etcd_config_dir }}/openssl.conf -d {{ etcd_cert_dir }}"
  environment:
    HOSTS: "{{ groups['gen_node_certs_True'] | ansible.builtin.intersect(groups['k8s_cluster']) | join(' ') }}"
  run_once: true
  delegate_to: "{{ groups['etcd'][0] }}"
  when:
    - kube_network_plugin in ["calico", "flannel", "cilium"] or cilium_deploy_additionally
    - kube_network_plugin != "calico" or calico_datastore == "etcd"
    - gen_certs | default(false)
  notify: Set etcd_secret_changed

- name: Gen_certs | Gather etcd member/admin and kube_control_plane client certs from first etcd node
  slurp:
    src: "{{ item }}"
  register: etcd_master_certs
  with_items:
    - "{{ etcd_cert_dir }}/ca.pem"
    - "{{ etcd_cert_dir }}/ca-key.pem"
    - "[{% for node in groups['etcd'] %}
        '{{ etcd_cert_dir }}/admin-{{ node }}.pem',
        '{{ etcd_cert_dir }}/admin-{{ node }}-key.pem',
        '{{ etcd_cert_dir }}/member-{{ node }}.pem',
        '{{ etcd_cert_dir }}/member-{{ node }}-key.pem',
        {% endfor %}]"
    - "[{% for node in (groups['kube_control_plane']) %}
        '{{ etcd_cert_dir }}/node-{{ node }}.pem',
        '{{ etcd_cert_dir }}/node-{{ node }}-key.pem',
        {% endfor %}]"
  delegate_to: "{{ groups['etcd'][0] }}"
  when:
    - ('etcd' in group_names)
    - sync_certs | default(false)
    - inventory_hostname != groups['etcd'][0]
  notify: Set etcd_secret_changed

- name: Gen_certs | Write etcd member/admin and kube_control_plane client certs to other etcd nodes
  copy:
    dest: "{{ item.item }}"
    content: "{{ item.content | b64decode }}"
    group: "{{ etcd_cert_group }}"
    owner: "{{ etcd_owner }}"
    mode: "0640"
  with_items: "{{ etcd_master_certs.results }}"
  when:
    - ('etcd' in group_names)
    - sync_certs | default(false)
    - inventory_hostname != groups['etcd'][0]
  loop_control:
    label: "{{ item.item }}"

- name: Gen_certs | Gather node certs from first etcd node
  slurp:
    src: "{{ item }}"
  register: etcd_master_node_certs
  with_items:
    - "[{% for node in groups['k8s_cluster'] %}
        '{{ etcd_cert_dir }}/node-{{ node }}.pem',
        '{{ etcd_cert_dir }}/node-{{ node }}-key.pem',
        {% endfor %}]"
  delegate_to: "{{ groups['etcd'][0] }}"
  when:
    - ('etcd' in group_names)
    - inventory_hostname != groups['etcd'][0]
    - kube_network_plugin in ["calico", "flannel", "cilium"] or cilium_deploy_additionally
    - kube_network_plugin != "calico" or calico_datastore == "etcd"
  notify: Set etcd_secret_changed

- name: Gen_certs | Write node certs to other etcd nodes
  copy:
    dest: "{{ item.item }}"
    content: "{{ item.content | b64decode }}"
    group: "{{ etcd_cert_group }}"
    owner: "{{ etcd_owner }}"
    mode: "0640"
  with_items: "{{ etcd_master_node_certs.results }}"
  when:
    - ('etcd' in group_names)
    - inventory_hostname != groups['etcd'][0]
    - kube_network_plugin in ["calico", "flannel", "cilium"] or cilium_deploy_additionally
    - kube_network_plugin != "calico" or calico_datastore == "etcd"
  loop_control:
    label: "{{ item.item }}"

- name: Gen_certs | Generate etcd certs
  include_tasks: gen_nodes_certs_script.yml
  when:
    - ('kube_control_plane' in group_names) and
        sync_certs | default(false) and inventory_hostname not in groups['etcd']

- name: Gen_certs | Generate etcd certs on nodes if needed
  include_tasks: gen_nodes_certs_script.yml
  when:
    - kube_network_plugin in ["calico", "flannel", "cilium"] or cilium_deploy_additionally
    - kube_network_plugin != "calico" or calico_datastore == "etcd"
    - ('k8s_cluster' in group_names) and
        sync_certs | default(false) and inventory_hostname not in groups['etcd']

# This is a hack around the fact kubeadm expect the same certs path on all kube_control_plane
# TODO: fix certs generation to have the same file everywhere
# OR work with kubeadm on node-specific config
- name: Gen_certs | Pretend all control plane have all certs (with symlinks)
  file:
    state: link
    src: "{{ etcd_cert_dir }}/node-{{ inventory_hostname }}{{ item[0] }}.pem"
    dest: "{{ etcd_cert_dir }}/node-{{ item[1] }}{{ item[0] }}.pem"
    mode: "0640"
  loop: "{{ suffixes | product(groups['kube_control_plane']) }}"
  vars:
    suffixes:
      - ''
      - '-key'
  when:
    - ('kube_control_plane' in group_names)
    - item[1] != inventory_hostname
  register: symlink_created
  failed_when:
    - symlink_created is failed
    - ('refusing to convert from file to symlink' not in symlink_created.msg)
