heat_template_version: rocky

description: Triggers a Mistral workflow for the deployment of Kubernetes

parameters:
  RoleNetIpMap:
    default: {}
    type: json
  ServiceData:
    default: {}
    description: Dictionary packing service data
    type: json
  ServiceNetMap:
    default: {}
    description: Mapping of service_name -> network name. Typically set
                 via parameter_defaults in the resource registry.  This
                 mapping overrides those in ServiceNetMapDefaults.
    type: json
  DefaultPasswords:
    default: {}
    type: json
  RoleName:
    default: ''
    description: Role name on which the service is applied
    type: string
  RoleParameters:
    default: {}
    description: Parameters specific to the role
    type: json
  EndpointMap:
    default: {}
    description: Mapping of service endpoint -> protocol. Typically set
                 via parameter_defaults in the resource registry.
    type: json
  KubesprayIgnoreAssertErrors:
    default: false
    description: Ignore kubespray pre-flight checks. Useful for deploying
                 on environments with swap enabled.
    type: boolean

outputs:
  role_data:
    description: Role data for the Kubernetes Service
    value:
      service_name: kubernetes_master
      firewall_rules:
        '200 kubernetes-master api':
          dport: 6443
          proto: tcp
        '200 kubernetes-master etcd':
          dport:
            - 2379
            - 2380
          proto: tcp
        '200 kubernetes-master flannel':
          dport:
            - 8285
            - 8472
          proto: udp
      upgrade_tasks: []
      step_config: ''
      external_deploy_tasks:
        # FIXME: remove this block when kubespray is packaged
        - name: kubernetes_master step 2 kubespray repository
          when: step|int == 2
          block:
            - name: check kubespray directory existence
              stat:
                path: /usr/share/kubespray
              register: kubespray_stat
            - set_fact:
                kubespray_dir: >-
                  {%- if kubespray_stat.stat.exists -%}
                    /usr/share/kubespray
                  {%- elif ansible_user_id == 'mistral' -%}
                    /var/lib/mistral/kubespray
                  {%- else -%}
                    {{ ansible_user_dir }}/kubespray
                  {%- endif -%}
            - name: check cloned kubespray directory existence
              stat:
                path: "{{ kubespray_dir }}"
              register: kubespray_cloned_stat
              when: not kubespray_stat.stat.exists
            - name: download kubespray source
              shell: |
                set -eux
                mkdir '{{ kubespray_dir }}'
                cd '{{ kubespray_dir }}'
                curl -Lo kubespray.tar.gz 'https://github.com/kubernetes-incubator/kubespray/archive/master.tar.gz'
                tar --strip-components 1 -xzvf kubespray.tar.gz
              # do not overwrite existing contents
              when: not kubespray_stat.stat.exists and not kubespray_cloned_stat.stat.exists
        - name: kubernetes_master step 2
          when: step|int == 2
          block:
            - name: create kubespray temp dirs
              become: true
              file:
                path: "{{item}}"
                state: directory
                owner: "{{ ansible_user }}"
              with_items:
                - "{{playbook_dir}}/kubespray"
                - "{{playbook_dir}}/kubespray/artifacts"
            - name: generate kubespray inventory
              copy:
                dest: "{{playbook_dir}}/kubespray/inventory.yml"
                content: |
                  kube-master:
                    hosts:
                      {% for host in groups['kubernetes_master'] -%}
                      {{ hostvars.raw_get(host)['ansible_hostname'] }}:
                        ansible_user: {{ hostvars.raw_get(host)['ansible_user'] | default(hostvars.raw_get(host)['ansible_ssh_user']) | default('root') }}
                        ansible_host: {{ hostvars.raw_get(host)['ansible_host'] | default(host) }}
                        ansible_become: true
                      {% endfor %}

                  kube-node:

                    hosts:
                      {% for host in groups['kubernetes_worker'] -%}
                      {{ hostvars.raw_get(host)['ansible_hostname'] }}:
                        ansible_user: {{ hostvars.raw_get(host)['ansible_user'] | default(hostvars.raw_get(host)['ansible_ssh_user']) | default('root') }}
                        ansible_host: {{ hostvars.raw_get(host)['ansible_host'] | default(host) }}
                        ansible_become: true
                      {% endfor %}

                  etcd:
                    children:
                      kube-master: {}

                  k8s-cluster:
                    children:
                      kube-master: {}
                      kube-node: {}
            - name: generate kubespray global vars
              copy:
                dest: "{{playbook_dir}}/kubespray/global_vars.yml"
                content:
                  str_replace:
                    template: |
                      kubeconfig_localhost: true
                      artifacts_dir: '{{playbook_dir}}/kubespray/artifacts'
                      ignore_assert_errors: IGNORE_ASSERT_ERRORS
                      kubelet_fail_swap_on: KUBELET_FAIL_SWAP_ON
                    params:
                      IGNORE_ASSERT_ERRORS: {get_param: KubesprayIgnoreAssertErrors}
                      KUBELET_FAIL_SWAP_ON:
                        yaql:
                          expression: not $.data
                          data: {get_param: KubesprayIgnoreAssertErrors}
            - name: generate kubespray playbook
              copy:
                dest: "{{playbook_dir}}/kubespray/playbook.yml"
                content: |
                  - import_playbook: {{ kubespray_dir|default('/usr/share/kubespray') }}/cluster.yml
            - name: set kubespray command
              set_fact:
                # NOTE: We could let kubespray configure docker
                # (remove --skip-tags docker) and run it in step 1
                # when this RFE is implemented:
                # https://github.com/kubernetes-incubator/kubespray/issues/1836
                kubespray_command: >-
                  {%- if kubespray_command is defined -%}
                  {{kubespray_command}}
                  {%- else -%}
                  ANSIBLE_HOST_KEY_CHECKING=False
                  ansible-playbook
                  -i '{{playbook_dir}}/kubespray/inventory.yml'
                  --skip-tags docker,bastion-ssh-config
                  --extra-vars '@{{playbook_dir}}/kubespray/global_vars.yml'
                  {% if ansible_ssh_private_key_file is defined %}--private-key '{{ansible_ssh_private_key_file}}'{% endif %}
                  '{{playbook_dir}}/kubespray/playbook.yml'
                  {%- endif -%}
            - name: print kubespray command
              debug:
                var: kubespray_command
            - name: run kubespray (immediate log at {{playbook_dir}}/kubespray/playbook.log)
              shell: |
                {{kubespray_command}} 2>&1 | tee {{playbook_dir}}/kubespray/playbook.log
                exit ${PIPESTATUS[0]}
