---
- name: Install etcd
  package:
    name: "etcd"
    state: present
  when:
  - not etcd_is_atomic | bool
  - not inventory_hostname in groups['oo_masters']
  register: result
  until: result is succeeded

- name: Check status of etcd certificates
  stat:
    path: "{{ item }}"
    get_checksum: false
    get_attributes: false
    get_mime: false
  with_items:
  - "{{ etcd_cert_file }}"
  - "{{ etcd_peer_cert_file }}"
  - "{{ etcd_ca_file }}"
  register: g_etcd_server_cert_stat_result


- set_fact:
    etcd_server_certs_missing: "{{ true if etcd_certificates_redeploy | default(false) | bool
                                   else (False in (g_etcd_server_cert_stat_result.results
                                                   | default({})
                                                   | lib_utils_oo_collect(attribute='stat.exists')
                                                   | list)) }}"
    etcd_file_owner: "{{ ('etcd' in (g_etcd_server_cert_stat_result.results
                                            | default({})
                                            | lib_utils_oo_collect(attribute='stat.pw_name')
                                            | list)) }}"

- name: Ensure generated_certs directory present
  file:
    path: "{{ etcd_generated_certs_dir }}/{{ etcd_cert_subdir }}"
    state: directory
    mode: 0700
  when: etcd_server_certs_missing | bool
  delegate_to: "{{ etcd_ca_host }}"

- name: Create the server csr
  command: >
    openssl req -new -keyout {{ etcd_cert_prefix }}server.key
    -config {{ etcd_openssl_conf }}
    -out {{ etcd_cert_prefix }}server.csr
    -reqexts {{ etcd_req_ext }} -batch -nodes
    -subj /CN={{ etcd_hostname }}
  args:
    chdir: "{{ etcd_generated_certs_dir }}/{{ etcd_cert_subdir }}"
    creates: "{{ etcd_generated_certs_dir ~ '/' ~  etcd_cert_subdir ~ '/'
                 ~ etcd_cert_prefix ~ 'server.csr' }}"
  environment:
    SAN: "IP:{{ etcd_ip }},DNS:{{ etcd_hostname }}"
  when: etcd_server_certs_missing | bool
  delegate_to: "{{ etcd_ca_host }}"

# Certificates must be signed serially in order to avoid competing
# for the serial file.
# delegated_serial_command is a custom module in lib_utils
- name: Sign and create the server crt
  delegated_serial_command:
    command: >
      openssl ca -name {{ etcd_ca_name }} -config {{ etcd_openssl_conf }}
      -out {{ etcd_cert_prefix }}server.crt
      -in {{ etcd_cert_prefix }}server.csr
      -extensions {{ etcd_ca_exts_server }} -batch
    chdir: "{{ etcd_generated_certs_dir }}/{{ etcd_cert_subdir }}"
    creates: "{{ etcd_generated_certs_dir ~ '/' ~  etcd_cert_subdir ~ '/'
                 ~ etcd_cert_prefix ~ 'server.crt' }}"
  environment:
    SAN: "IP:{{ etcd_ip }}"
  when: etcd_server_certs_missing | bool
  delegate_to: "{{ etcd_ca_host }}"

- name: Create the peer csr
  command: >
    openssl req -new -keyout {{ etcd_cert_prefix }}peer.key
    -config {{ etcd_openssl_conf }}
    -out {{ etcd_cert_prefix }}peer.csr
    -reqexts {{ etcd_req_ext }} -batch -nodes
    -subj /CN={{ etcd_hostname }}
  args:
    chdir: "{{ etcd_generated_certs_dir }}/{{ etcd_cert_subdir }}"
    creates: "{{ etcd_generated_certs_dir ~ '/' ~  etcd_cert_subdir ~ '/'
                 ~ etcd_cert_prefix ~ 'peer.csr' }}"
  environment:
    SAN: "IP:{{ etcd_ip }},DNS:{{ etcd_hostname }}"
  when: etcd_server_certs_missing | bool
  delegate_to: "{{ etcd_ca_host }}"

# Certificates must be signed serially in order to avoid competing
# for the serial file.
# delegated_serial_command is a custom module in lib_utils
- name: Sign and create the peer crt
  delegated_serial_command:
    command: >
      openssl ca -name {{ etcd_ca_name }} -config {{ etcd_openssl_conf }}
      -out {{ etcd_cert_prefix }}peer.crt
      -in {{ etcd_cert_prefix }}peer.csr
      -extensions {{ etcd_ca_exts_peer }} -batch
    chdir: "{{ etcd_generated_certs_dir }}/{{ etcd_cert_subdir }}"
    creates: "{{ etcd_generated_certs_dir ~ '/' ~  etcd_cert_subdir ~ '/'
                 ~ etcd_cert_prefix ~ 'peer.crt' }}"
  environment:
    SAN: "IP:{{ etcd_ip }}"
  when: etcd_server_certs_missing | bool
  delegate_to: "{{ etcd_ca_host }}"

- file:
    src: "{{ etcd_ca_cert }}"
    dest: "{{ etcd_generated_certs_dir}}/{{ etcd_cert_subdir }}/{{ etcd_cert_prefix }}ca.crt"
    state: hard
    force: yes
  when: etcd_server_certs_missing | bool
  delegate_to: "{{ etcd_ca_host }}"

- name: Create a tarball of the etcd certs
  command: >
    tar -czvf {{ etcd_generated_certs_dir }}/{{ etcd_cert_subdir }}.tgz
      -C {{ etcd_generated_certs_dir }}/{{ etcd_cert_subdir }} .
  args:
    creates: "{{ etcd_generated_certs_dir }}/{{ etcd_cert_subdir }}.tgz"
    # Disables the following warning:
    # Consider using unarchive module rather than running tar
    warn: no
  when: etcd_server_certs_missing | bool
  delegate_to: "{{ etcd_ca_host }}"

- name: Retrieve etcd cert tarball
  fetch:
    src: "{{ etcd_generated_certs_dir }}/{{ etcd_cert_subdir }}.tgz"
    dest: "/tmp"
    fail_on_missing: yes
    validate_checksum: yes
  when: etcd_server_certs_missing | bool
  delegate_to: "{{ etcd_ca_host }}"

- name: Ensure certificate directory exists
  file:
    path: "{{ item }}"
    state: directory
  with_items:
  - "{{ etcd_cert_config_dir }}"
  when: etcd_server_certs_missing | bool

- name: Unarchive cert tarball
  unarchive:
    src: "/tmp/{{ inventory_hostname }}/{{ etcd_generated_certs_dir }}/{{ etcd_cert_subdir }}.tgz"
    dest: "{{ etcd_cert_config_dir }}"
  when: etcd_server_certs_missing | bool

- name: Create a tarball of the etcd ca certs
  command: >
    tar -czvf {{ etcd_generated_certs_dir }}/{{ etcd_ca_name }}.tgz
      -C {{ etcd_ca_dir }} .
  args:
    creates: "{{ etcd_generated_certs_dir }}/{{ etcd_ca_name }}.tgz"
    warn: no
  when: etcd_server_certs_missing | bool
  delegate_to: "{{ etcd_ca_host }}"

- name: Retrieve etcd ca cert tarball
  fetch:
    src: "{{ etcd_generated_certs_dir }}/{{ etcd_ca_name }}.tgz"
    dest: "/tmp"
    fail_on_missing: yes
    validate_checksum: yes
  when: etcd_server_certs_missing | bool
  delegate_to: "{{ etcd_ca_host }}"

- name: Ensure ca directory exists
  file:
    path: "{{ item }}"
    state: directory
  with_items:
  - "{{ etcd_ca_dir }}"
  when: etcd_server_certs_missing | bool

- name: Delete temporary directory
  local_action: file path="/tmp/{{ inventory_hostname }}" state=absent
  changed_when: False
  when: etcd_server_certs_missing | bool

- name: Validate permissions on certificate files
  file:
    path: "{{ item }}"
    mode: 0600
    owner: "{{ 'etcd' if etcd_file_owner | bool else omit }}"
    group: "{{ 'etcd' if etcd_file_owner | bool else omit }}"
  when: etcd_url_scheme == 'https'
  with_items:
  - "{{ etcd_ca_file }}"
  - "{{ etcd_cert_file }}"
  - "{{ etcd_key_file }}"

- name: Validate permissions on peer certificate files
  file:
    path: "{{ item }}"
    mode: 0600
    owner: "{{ 'etcd' if etcd_file_owner | bool else omit }}"
    group: "{{ 'etcd' if etcd_file_owner | bool else omit }}"
  when: etcd_peer_url_scheme == 'https'
  with_items:
  - "{{ etcd_peer_ca_file }}"
  - "{{ etcd_peer_cert_file }}"
  - "{{ etcd_peer_key_file }}"

# this may not be right
- name: Validate permissions on the config dir
  file:
    path: "{{ etcd_conf_dir }}"
    state: directory
    mode: 0700
    owner: "{{ 'etcd' if etcd_file_owner | bool else omit }}"
    group: "{{ 'etcd' if etcd_file_owner | bool else omit }}"
