---
# TODO: add ability to configure certificates given either a local file to
#       point to or certificate contents, set in default cert locations.

# Authentication Variable Validation
# TODO: validate the different identity provider kinds as well
- fail:
    msg: >
      Invalid OAuth grant method: {{ openshift_master_oauth_grant_method }}
  when:
  - openshift_master_oauth_grant_method not in openshift_master_valid_grant_methods

- name: Check that origin image is present
  command: 'docker images -q "{{ osm_image }}"'
  register: control_plane_image

# This task runs async to save time while the master is being configured
- name: Pre-pull Origin image
  docker_image:
    name: "{{ osm_image }}"
  environment:
    NO_PROXY: "{{ openshift.common.no_proxy | default('') }}"
  when: control_plane_image.stdout_lines == []
  # 10 minutes to pull the image
  async: 600
  poll: 0
  register: image_prepull

- name: Open up firewall ports
  import_tasks: firewall.yml

- name: Prepare static pod scripts
  import_tasks: static_shim.yml

- name: Create r_openshift_master_data_dir
  file:
    path: "{{ r_openshift_master_data_dir }}"
    state: directory
    mode: 0755
    owner: root
    group: root

- name: Create config parent directory if it does not exist
  file:
    path: "/etc/origin/master"
    state: directory

- name: Create flexvolume directory when on atomic hosts
  file:
    state: directory
    path: "/etc/origin/kubelet-plugins/volume/exec"
    mode: '0750'
  when: openshift_is_atomic | bool

- name: Flex volume directory on non-atomic host
  file:
    state: directory
    path: "/usr/libexec/kubernetes/kubelet-plugins/volume/exec/"
    mode: '0750'
  when: not openshift_is_atomic | bool

- name: Create the policy file if it does not already exist
  command: >
    {{ openshift_client_binary }} adm create-bootstrap-policy-file
      --filename={{ openshift_master_policy }}
  args:
    creates: "{{ openshift_master_policy }}"

- name: Create the scheduler config
  copy:
    content: "{{ scheduler_config | to_nice_json }}"
    dest: "{{ openshift_master_scheduler_conf }}"
    backup: true

- import_tasks: htpass_provider.yml

- name: Create the ldap ca file if needed
  copy:
    dest: "{{ item.ca if 'ca' in item and '/' in item.ca else '/etc/origin/master/' ~ item.ca | default('ldap_ca.crt') }}"
    content: "{{ openshift.master.ldap_ca }}"
    mode: 0600
    backup: yes
  when:
  - openshift.master.ldap_ca is defined
  - item.kind == 'LDAPPasswordIdentityProvider'
  with_items: "{{ openshift_master_identity_providers }}"

- name: Create the openid ca file if needed
  copy:
    dest: "{{ item.ca if 'ca' in item and '/' in item.ca else '/etc/origin/master/' ~ item.ca | default('openid_ca.crt') }}"
    content: "{{ openshift.master.openid_ca }}"
    mode: 0600
    backup: yes
  when:
  - openshift.master.openid_ca is defined
  - item.kind == 'OpenIDIdentityProvider'
  - item.ca | default('') != ''
  with_items: "{{ openshift_master_identity_providers }}"

- name: Create the request header ca file if needed
  copy:
    dest: "{{ item.clientCA if 'clientCA' in item and '/' in item.clientCA else '/etc/origin/master/' ~ item.clientCA | default('request_header_ca.crt') }}"
    content: "{{ openshift_master_request_header_ca }}"
    mode: 0600
    backup: yes
  when:
  - openshift_master_request_header_ca != l_osm_request_header_none
  - item.kind == 'RequestHeaderIdentityProvider'
  - item.clientCA | default('') != ''
  with_items: "{{ openshift_master_identity_providers }}"

- name: Set fact of all etcd host IPs
  openshift_facts:
    role: common
    local_facts:
      no_proxy_etcd_host_ips: "{{ openshift_no_proxy_etcd_host_ips }}"

- name: Create session secrets file
  template:
    dest: "{{ openshift_master_session_secrets_file }}"
    src: sessionSecretsFile.yaml.v1.j2
    owner: root
    group: root
    mode: 0600

- set_fact:
    # translate_idps is a custom filter in role lib_utils
    translated_identity_providers: "{{ openshift_master_identity_providers | translate_idps('v1') }}"

# TODO: add the validate parameter when there is a validation command to run
- name: Create master config
  template:
    dest: "{{ openshift_master_config_file }}"
    src: master.yaml.v1.j2
    backup: true
    owner: root
    group: root
    mode: 0600

- import_tasks: set_loopback_context.yml

- name: Create the master service env file
  template:
    src: "master.env.j2"
    dest: /etc/origin/master/master.env
    backup: true

- import_tasks: static.yml

- name: Establish the default bootstrap kubeconfig for masters
  copy:
    remote_src: true
    src: "/etc/origin/master/admin.kubeconfig"
    dest: "{{ item }}"
    mode: 0600
  with_items:
  # bootstrap as an admin
  - /etc/origin/node/bootstrap.kubeconfig
  # copy to this location to bypass initial bootstrap request
  - /etc/origin/node/node.kubeconfig

- name: Check status of control plane image pre-pull
  async_status:
    jid: "{{ image_prepull.ansible_job_id }}"
  register: job_result
  until: job_result.finished
  when: control_plane_image.stdout_lines == []
  retries: 20
  delay: 30
  failed_when: false

- name: Check status of etcd image pre-pull
  async_status:
    jid: "{{ etcd_prepull.ansible_job_id }}"
  register: job_result
  until: job_result.finished
  when:
  - etcd_image_exists is defined
  - "'stdout_lines' in etcd_image_exists"
  - etcd_image_exists.stdout_lines == []
  retries: 20
  delay: 30
  failed_when: false

- name: Start and enable self-hosting node
  systemd:
    name: "{{ openshift_service_type }}-node"
    state: restarted
    enabled: yes
  register: node_start
  ignore_errors: yes

- when: node_start is failed
  block:
  - name: Get node logs
    command: journalctl --no-pager -n 300 -u {{ openshift_service_type }}-node
    register: logs_node
    ignore_errors: true
  - debug:
      msg: "{{ logs_node.stdout_lines }}"
  - fail:
      msg: Node start failed.

- name: Wait for control plane pods to appear
  oc_obj:
    state: list
    kind: pod
    name: "master-{{ item }}-{{ openshift.node.nodename | lower }}"
    namespace: kube-system
  register: control_plane_pods
  until:
  - "'results' in control_plane_pods"
  - "'results' in control_plane_pods.results"
  - control_plane_pods.results.results | length > 0
  retries: 60
  delay: 5
  with_items:
  - "{{ 'etcd' if inventory_hostname in groups['oo_etcd_to_config'] else omit }}"
  - api
  - controllers
  ignore_errors: true

- when: control_plane_pods is failed
  block:
  - name: Check status in the kube-system namespace
    command: >
      {{ openshift_client_binary }} status --config={{ openshift.common.config_base }}/master/admin.kubeconfig -n kube-system
    register: control_plane_status
    ignore_errors: true
  - debug:
      msg: "{{ control_plane_status.stdout_lines }}"
  - name: Get pods in the kube-system namespace
    command: >
      {{ openshift_client_binary }} get pods --config={{ openshift.common.config_base }}/master/admin.kubeconfig -n kube-system -o wide
    register: control_plane_pods_list
    ignore_errors: true
  - debug:
      msg: "{{ control_plane_pods_list.stdout_lines }}"
  - name: Get events in the kube-system namespace
    command: >
      {{ openshift_client_binary }} get events --config={{ openshift.common.config_base }}/master/admin.kubeconfig -n kube-system
    register: control_plane_events
    ignore_errors: true
  - debug:
      msg: "{{ control_plane_events.stdout_lines }}"
  - name: Get node logs
    command: journalctl --no-pager -n 300 -u {{ openshift_service_type }}-node
    register: logs_node
    ignore_errors: true
  - debug:
      msg: "{{ logs_node.stdout_lines }}"
  - name: Report control plane errors
    fail:
      msg: Control plane pods didn't come up

- name: Wait for all control plane pods to become ready
  oc_obj:
    state: list
    kind: pod
    name: "master-{{ item }}-{{ openshift.node.nodename | lower }}"
    namespace: kube-system
  register: control_plane_health
  until:
  - "'results' in control_plane_health"
  - "'results' in control_plane_health.results"
  - control_plane_health.results.results | length > 0
  - "'status' in control_plane_health.results.results[0]"
  - "'conditions' in control_plane_health.results.results[0].status"
  - control_plane_health.results.results[0].status.conditions | selectattr('type', 'match', '^Ready$') | map(attribute='status') | join | bool == True
  retries: 60
  delay: 5
  with_items:
  - "{{ 'etcd' if inventory_hostname in groups['oo_etcd_to_config'] else '' }}"
  - api
  - controllers
  when:
  - item != ''

- when: control_plane_health is failed
  block:
  - debug:
      msg: "{{ control_plane_pods_list.stdout_lines }}"
  - name: Get events in the kube-system namespace
    command: >
      {{ openshift_client_binary }} get events --config={{ openshift.common.config_base }}/master/admin.kubeconfig -n kube-system
    register: control_plane_events
    ignore_errors: true
  - debug:
      msg: "{{ control_plane_events.stdout_lines }}"
  - name: Get node logs
    command: journalctl --no-pager -n 300 -u {{ openshift_service_type }}-node
    register: logs_node
    ignore_errors: true
  - debug:
      msg: "{{ logs_node.stdout_lines }}"
  - name: Get API logs
    command: >
      /usr/local/bin/master-logs api api
    register: control_plane_logs_api
    ignore_errors: true
  - debug:
      msg: "{{ control_plane_logs_api.stdout_lines }}"
  - name: Get controllers logs
    command: >
      /usr/local/bin/master-logs controllers controllers
    register: control_plane_logs_controllers
    ignore_errors: true
  - debug:
      msg: "{{ control_plane_logs_controllers.stdout_lines }}"
  - name: Get etcd logs
    command: >
      /usr/local/bin/master-logs etcd etcd
    register: control_plane_logs_etcd
    when: inventory_hostname in groups['oo_etcd_to_config']
    ignore_errors: true
  - debug:
      msg: "{{ control_plane_logs_controllers.stdout_lines }}"
    when: inventory_hostname in groups['oo_etcd_to_config']
  - name: Report control plane errors
    fail:
      msg: Control plane pods didn't pass health check

- import_tasks: check_master_api_is_ready.yml

- name: Remove oc cache to refresh a list of APIs
  file:
    path: "~/.kube/cache"
    state: absent
