---
- name: Set kubeadm_discovery_address
  set_fact:
    # noqa: jinja[spacing]
    kubeadm_discovery_address: >-
      {%- if "127.0.0.1" in kube_apiserver_endpoint or "localhost" in kube_apiserver_endpoint -%}
      {{ first_kube_control_plane_address | ansible.utils.ipwrap }}:{{ kube_apiserver_port }}
      {%- else -%}
      {{ kube_apiserver_endpoint | replace("https://", "") }}
      {%- endif %}
  tags:
    - facts

- name: Check if kubelet.conf exists
  stat:
    path: "{{ kube_config_dir }}/kubelet.conf"
    get_attributes: false
    get_checksum: false
    get_mime: false
  register: kubelet_conf

- name: Check if kubeadm CA cert is accessible
  stat:
    path: "{{ kube_cert_dir }}/ca.crt"
    get_attributes: false
    get_checksum: false
    get_mime: false
  register: kubeadm_ca_stat
  delegate_to: "{{ groups['kube_control_plane'][0] }}"
  run_once: true

- name: Fetch CA certificate from control plane node
  slurp:
    src: "{{ kube_cert_dir }}/ca.crt"
  register: ca_cert_content
  when:
    - kubeadm_ca_stat.stat is defined
    - kubeadm_ca_stat.stat.exists
  delegate_to: "{{ groups['kube_control_plane'][0] }}"
  run_once: true

- name: Create kubeadm token for joining nodes with 24h expiration (default)
  command: "{{ bin_dir }}/kubeadm token create"
  register: temp_token
  delegate_to: "{{ groups['kube_control_plane'][0] }}"
  when: kubeadm_token is not defined
  changed_when: false

- name: Set kubeadm_token to generated token
  set_fact:
    kubeadm_token: "{{ temp_token.stdout }}"
  when: kubeadm_token is not defined

- name: Get kubeconfig for join discovery process
  command: "{{ kubectl }} -n kube-public get cm cluster-info -o jsonpath='{.data.kubeconfig}'"
  register: kubeconfig_file_discovery
  run_once: true
  delegate_to: "{{ groups['kube_control_plane'] | first }}"
  when: kubeadm_use_file_discovery

- name: Copy discovery kubeconfig
  copy:
    dest: "{{ kube_config_dir }}/cluster-info-discovery-kubeconfig.yaml"
    content: "{{ kubeconfig_file_discovery.stdout }}"
    owner: "root"
    mode: "0644"
  when:
    - ('kube_control_plane' not in group_names)
    - not kubelet_conf.stat.exists
    - kubeadm_use_file_discovery

- name: Create kubeadm client config
  template:
    src: "kubeadm-client.conf.j2"
    dest: "{{ kube_config_dir }}/kubeadm-client.conf"
    backup: true
    mode: "0640"
    validate: "{{ kubeadm_config_validate_enabled | ternary(bin_dir + '/kubeadm config validate --config %s', omit) }}"
  when: ('kube_control_plane' not in group_names)

- name: Join to cluster if needed
  environment:
    PATH: "{{ bin_dir }}:{{ ansible_env.PATH }}:/sbin"
  when:
    - ('kube_control_plane' not in group_names)
    - not kubelet_conf.stat.exists
  vars:
    ignored:
      - "{{ 'DirAvailable--etc-kubernetes-manifests' if 'all' not in kubeadm_ignore_preflight_errors }}"
      - "{{ kubeadm_ignore_preflight_errors }}"
  command: >-
    timeout -k {{ kubeadm_join_timeout }} {{ kubeadm_join_timeout }}
    {{ bin_dir }}/kubeadm join
    --config {{ kube_config_dir }}/kubeadm-client.conf
    --ignore-preflight-errors={{ ignored | select | flatten | join(',') }}
    --skip-phases={{ kubeadm_join_phases_skip | join(',') }}

- name: Update server field in kubelet kubeconfig
  lineinfile:
    dest: "{{ kube_config_dir }}/kubelet.conf"
    regexp: 'server:'
    line: '    server: {{ kube_apiserver_endpoint }}'
    backup: true
  when:
    - kubeadm_config_api_fqdn is not defined
    - ('kube_control_plane' not in group_names)
    - kubeadm_discovery_address != kube_apiserver_endpoint | replace("https://", "")
  notify: Kubeadm | restart kubelet

- name: Update server field in kubelet kubeconfig - external lb
  lineinfile:
    dest: "{{ kube_config_dir }}/kubelet.conf"
    regexp: '^    server: https'
    line: '    server: {{ kube_apiserver_endpoint }}'
    backup: true
  when:
    - ('kube_control_plane' not in group_names)
    - loadbalancer_apiserver is defined
  notify: Kubeadm | restart kubelet

- name: Get current resourceVersion of kube-proxy configmap
  command: "{{ kubectl }} get configmap kube-proxy -n kube-system -o jsonpath='{.metadata.resourceVersion}'"
  register: original_configmap_resource_version
  run_once: true
  delegate_to: "{{ groups['kube_control_plane'] | first }}"
  delegate_facts: false
  when:
    - kube_proxy_deployed
  tags:
    - kube-proxy

# FIXME(mattymo): Need to point to localhost, otherwise control plane nodes will all point
#                 incorrectly to first control plane node, creating SPoF.
- name: Update server field in kube-proxy kubeconfig
  shell: >-
    set -o pipefail && {{ kubectl }} get configmap kube-proxy -n kube-system -o yaml
    | sed 's#server:.*#server: https://127.0.0.1:{{ kube_apiserver_port }}#g'
    | {{ kubectl }} replace -f -
  args:
    executable: /bin/bash
  run_once: true
  delegate_to: "{{ groups['kube_control_plane'] | first }}"
  delegate_facts: false
  when:
    - kubeadm_config_api_fqdn is not defined
    - kubeadm_discovery_address != kube_apiserver_endpoint | replace("https://", "")
    - kube_proxy_deployed
    - loadbalancer_apiserver_localhost
  tags:
    - kube-proxy

- name: Update server field in kube-proxy kubeconfig - external lb
  shell: >-
    set -o pipefail && {{ kubectl }} get configmap kube-proxy -n kube-system -o yaml
    | sed 's#server:.*#server: {{kube_apiserver_endpoint}}#g'
    | {{ kubectl }} replace -f -
  args:
    executable: /bin/bash
  run_once: true
  delegate_to: "{{ groups['kube_control_plane'] | first }}"
  delegate_facts: false
  when:
    - kube_proxy_deployed
    - loadbalancer_apiserver is defined
  tags:
    - kube-proxy

- name: Get new resourceVersion of kube-proxy configmap
  command: "{{ kubectl }} get configmap kube-proxy -n kube-system -o jsonpath='{.metadata.resourceVersion}'"
  register: new_configmap_resource_version
  run_once: true
  delegate_to: "{{ groups['kube_control_plane'] | first }}"
  delegate_facts: false
  when:
    - kube_proxy_deployed
  tags:
    - kube-proxy

- name: Set ca.crt file permission
  file:
    path: "{{ kube_cert_dir }}/ca.crt"
    owner: root
    group: root
    mode: "0644"

- name: Restart all kube-proxy pods to ensure that they load the new configmap
  command: "{{ kubectl }} delete pod -n kube-system -l k8s-app=kube-proxy --force --grace-period=0"
  run_once: true
  delegate_to: "{{ groups['kube_control_plane'] | first }}"
  delegate_facts: false
  when:
    - kubeadm_config_api_fqdn is not defined or loadbalancer_apiserver is defined
    - kubeadm_discovery_address != kube_apiserver_endpoint | replace("https://", "") or loadbalancer_apiserver is defined
    - kube_proxy_deployed
    - original_configmap_resource_version.stdout != new_configmap_resource_version.stdout
  tags:
    - kube-proxy

- name: Extract etcd certs from control plane if using etcd kubeadm mode
  include_tasks: kubeadm_etcd_node.yml
  when:
    - etcd_deployment_type == "kubeadm"
    - inventory_hostname not in groups['kube_control_plane']
    - kube_network_plugin in ["calico", "flannel", "cilium"] or cilium_deploy_additionally
    - kube_network_plugin != "calico" or calico_datastore == "etcd"
