---
- name: Generate broadcast websocket secret
  set_fact:
    broadcast_websocket_secret: "{{ lookup('password', '/dev/null length=128') }}"
  run_once: true
  no_log: true
  when: broadcast_websocket_secret is not defined

- fail:
    msg: "Only set one of kubernetes_context or openshift_host"
  when: openshift_host is defined and kubernetes_context is defined

- include_tasks: "{{ tasks }}"
  with_items:
    - openshift_auth.yml
    - openshift.yml
  loop_control:
    loop_var: tasks
  when: openshift_host is defined

- include_tasks: "{{ tasks }}"
  with_items:
    - kubernetes_auth.yml
    - kubernetes.yml
  loop_control:
    loop_var: tasks
  when: kubernetes_context is defined

- name: Use kubectl or oc
  set_fact:
    kubectl_or_oc: "{{ openshift_oc_bin if openshift_oc_bin is defined else 'kubectl' }}"

- set_fact:
    deployment_object: "deployment"

- name: Record deployment size
  shell: |
    {{ kubectl_or_oc }} get {{ deployment_object }} \
      {{ kubernetes_deployment_name }} \
      -n {{ kubernetes_namespace }} -o=jsonpath='{.status.replicas}'
  register: deployment_details
  ignore_errors: true

- name: Set expected post-deployment Replicas value
  set_fact:
    kubernetes_deployment_replica_size: "{{ deployment_details.stdout | int }}"
  when: deployment_details.rc == 0

- name: Delete existing Deployment (or StatefulSet)
  shell: |
    {{ kubectl_or_oc }} delete sts \
      {{ kubernetes_deployment_name }} -n {{ kubernetes_namespace }} --ignore-not-found
    {{ kubectl_or_oc }} delete {{ deployment_object }} \
      {{ kubernetes_deployment_name }} -n {{ kubernetes_namespace }} --ignore-not-found

- name: Get Postgres Service Detail
  shell: "{{ kubectl_or_oc }} describe svc {{ postgresql_service_name }} -n {{ kubernetes_namespace }}"
  register: postgres_svc_details
  ignore_errors: true
  when: "pg_hostname is not defined or pg_hostname == ''"

- name: Deploy PostgreSQL (OpenShift)
  block:
    - name: Template PostgreSQL Deployment (OpenShift)
      template:
        src: postgresql-persistent.yml.j2
        dest: "{{ kubernetes_base_path }}/postgresql-persistent.yml"
        mode: '0600'

    - name: Deploy and Activate Postgres (OpenShift)
      shell: |
        {{ openshift_oc_bin }} new-app --file={{ kubernetes_base_path }}/postgresql-persistent.yml \
          -e MEMORY_LIMIT={{ pg_memory_limit|default('512') }}Mi \
          -e DATABASE_SERVICE_NAME=postgresql  \
          -e POSTGRESQL_MAX_CONNECTIONS={{ pg_max_connections|default(1024) }} \
          -e POSTGRESQL_USER={{ pg_username }} \
          -e POSTGRESQL_PASSWORD={{ pg_password | quote }} \
          -e POSTGRESQL_DATABASE={{ pg_database | quote }} \
          -e POSTGRESQL_VERSION=12 \
          -n {{ kubernetes_namespace }}
      register: openshift_pg_activate
      no_log: true
  when:
    - pg_hostname is not defined or pg_hostname == ''
    - postgres_svc_details is defined and postgres_svc_details.rc != 0
    - openshift_host is defined

- name: Deploy PostgreSQL (Kubernetes)
  block:
    - name: Create Temporary Values File (Kubernetes)
      tempfile:
        state: file
        suffix: .yml
      register: values_file

    - name: Populate Temporary Values File (Kubernetes)
      template:
        src: postgresql-values.yml.j2
        dest: "{{ values_file.path }}"
      no_log: true

    - name: Deploy and Activate Postgres (Kubernetes)
      shell: |
        helm repo add stable https://charts.helm.sh/stable
        helm repo update
        helm upgrade {{ postgresql_service_name }} \
          --install \
          --namespace {{ kubernetes_namespace }} \
          --version="8.3.0" \
          --values {{ values_file.path }} \
          stable/postgresql
      register: kubernetes_pg_activate
      no_log: true

    - name: Remove tempfile
      file:
        path: "{{ values_file.path }}"
        state: absent
  when:
    - pg_hostname is not defined or pg_hostname == ''
    - postgres_svc_details is defined and postgres_svc_details.rc != 0
    - kubernetes_context is defined

- name: Set postgresql hostname to helm package service (Kubernetes)
  set_fact:
    pg_hostname: "{{ postgresql_service_name }}"
  when:
    - pg_hostname is not defined or pg_hostname == ''
    - kubernetes_context is defined

- name: Wait for Postgres to activate
  pause:
    seconds: "{{ postgress_activate_wait }}"
  when: openshift_pg_activate.changed or kubernetes_pg_activate.changed

- name: Check postgres version and upgrade Postgres if necessary (Openshift)
  block:
    - name: Check if Postgres 10 is being used
      shell: |
        POD=$({{ kubectl_or_oc }} -n {{ kubernetes_namespace }} \
          get pods -l=name=postgresql --field-selector status.phase=Running -o jsonpath="{.items[0].metadata.name}")
        {{ kubectl_or_oc }} exec $POD -n {{ kubernetes_namespace }} -- bash -c "psql -tAc 'select version()'"
      register: pg_version
    - name: Upgrade postgres if necessary
      block:
        - name: Set new pg image
          shell: |
            IMAGE=registry.redhat.io/rhel-8/postgresql-12
            {{ kubectl_or_oc }} -n {{ kubernetes_namespace }} set image dc/postgresql postgresql=$IMAGE

        - name: Wait for change to take affect
          pause:
            seconds: 5

        - name: Set env var for pg upgrade
          shell: |
            {{ kubectl_or_oc }} -n {{ kubernetes_namespace }} set env dc/postgresql POSTGRESQL_UPGRADE=copy

        - name: Wait for change to take affect
          pause:
            seconds: 5

        - name: Set env var for new pg version
          shell: |
            {{ kubectl_or_oc }} -n {{ kubernetes_namespace }} set env dc/postgresql POSTGRESQL_VERSION=12

        - name: Wait for Postgres to redeploy
          pause:
            seconds: "{{ postgress_activate_wait }}"

        - name: Wait for Postgres to finish upgrading
          shell: |
            POD=$({{ kubectl_or_oc }} -n {{ kubernetes_namespace }} \
              get pods -l=name=postgresql -o jsonpath="{.items[0].metadata.name}")
            {{ kubectl_or_oc }} -n {{ kubernetes_namespace }} logs $POD | grep 'Upgrade DONE'
          register: pg_upgrade_logs
          retries: 360
          delay: 10
          until: pg_upgrade_logs is success

        - name: Unset upgrade env var
          shell: |
            {{ kubectl_or_oc }} -n {{ kubernetes_namespace }} set env dc/postgresql POSTGRESQL_UPGRADE-

        - name: Wait for Postgres to redeploy
          pause:
            seconds: "{{ postgress_activate_wait }}"
      when: "pg_version is success and '10' in pg_version.stdout"
  when:
    - pg_hostname is not defined or pg_hostname == ''
    - postgres_svc_details is defined and postgres_svc_details.rc != 0
    - openshift_host is defined

- name: Set image names if using custom registry
  block:
    - name: Set awx image name
      set_fact:
        kubernetes_awx_image: "{{ docker_registry }}/{{ docker_registry_repository }}/{{ awx_image }}"
      when: kubernetes_awx_image is not defined
  when: docker_registry is defined

- name: Determine Deployment api version
  set_fact:
    kubernetes_deployment_api_version: "{{ 'apps/v1' if kube_api_version is version('1.9', '>=') else 'apps/v1beta1' }}"

- name: Use Custom Root CA file for PosgtreSQL SSL communication
  block:
    - name: Get Root CA file contents
      set_fact:
        postgres_root_ca_cert: "{{ lookup('file', pg_root_ca_file) }}"
      no_log: true

    - name: Render Root CA template
      set_fact:
        postgres_root_ca: "{{ lookup('template', 'postgres_root_ca.yml.j2') }}"
      no_log: true

    - name: Apply Root CA template
      shell: |
        echo {{ postgres_root_ca | quote }} | {{ kubectl_or_oc }} apply -f -
      no_log: true

    - name: Set Root CA file name
      set_fact:
        postgres_root_ca_filename: 'postgres_root_ca.crt'

    - name: Set Root CA file location
      set_fact:
        ca_trust_bundle: '/etc/tower/{{ postgres_root_ca_filename }}'
  when:
    - pg_root_ca_file is defined
    - pg_root_ca_file != ''

- name: Render deployment templates
  set_fact:
    "{{ item }}": "{{ lookup('template', item + '.yml.j2') }}"
  with_items:
    - 'configmap'
    - 'secret'
    - 'deployment'
    - 'supervisor'
  no_log: true

- name: Apply Deployment
  shell: |
    echo {{ item | quote }} | {{ kubectl_or_oc }} apply -f -
  with_items:
    - "{{ configmap }}"
    - "{{ secret }}"
    - "{{ deployment }}"
    - "{{ supervisor }}"
  no_log: true

- name: Delete any existing management pod
  shell: |
    {{ kubectl_or_oc }} -n {{ kubernetes_namespace }} \
      delete pod ansible-tower-management --grace-period=0 --ignore-not-found

- name: Template management pod
  set_fact:
    management_pod: "{{ lookup('template', 'management-pod.yml.j2') }}"

- name: Create management pod
  shell: |
    echo {{ management_pod | quote }} | {{ kubectl_or_oc }} apply -f -

- name: Wait for management pod to start
  shell: |
    {{ kubectl_or_oc }} -n {{ kubernetes_namespace }} \
      get pod ansible-tower-management -o jsonpath="{.status.phase}"
  register: result
  until: result.stdout == "Running"
  retries: 60
  delay: 10

- name: Migrate database
  shell: |
    {{ kubectl_or_oc }} -n {{ kubernetes_namespace }} exec ansible-tower-management -- \
      bash -c "awx-manage migrate --noinput"

- name: Check for Tower Super users
  shell: |
    {{ kubectl_or_oc }} -n {{ kubernetes_namespace }} exec ansible-tower-management -- \
      bash -c "echo 'from django.contrib.auth.models import User; nsu = User.objects.filter(is_superuser=True).count(); exit(0 if nsu > 0 else 1)' | awx-manage shell"
  register: super_check
  ignore_errors: true
  changed_when: super_check.rc > 0

- name: create django super user if it does not exist
  shell: |
    {{ kubectl_or_oc }} -n {{ kubernetes_namespace }} exec ansible-tower-management -- \
      bash -c "echo \"from django.contrib.auth.models import User; User.objects.create_superuser('{{ admin_user }}', '{{ admin_email }}', '{{ admin_password }}')\" | awx-manage shell"
  no_log: true
  when: super_check.rc > 0

- name: update django super user password
  shell: |
    {{ kubectl_or_oc }} -n {{ kubernetes_namespace }} exec ansible-tower-management -- \
      bash -c "awx-manage update_password --username='{{ admin_user }}' --password='{{ admin_password }}'"
  no_log: true
  register: result
  changed_when: "'Password updated' in result.stdout"

- name: Create the default organization if it is needed.
  shell: |
    {{ kubectl_or_oc }} -n {{ kubernetes_namespace }} exec ansible-tower-management -- \
      bash -c "awx-manage create_preload_data"
  register: cdo
  changed_when: "'added' in cdo.stdout"
  when: create_preload_data | bool

- name: Delete management pod
  shell: |
    {{ kubectl_or_oc }} -n {{ kubernetes_namespace }} \
      delete pod ansible-tower-management --grace-period=0 --ignore-not-found

- name: Scale up deployment
  shell: |
    {{ kubectl_or_oc }} -n {{ kubernetes_namespace }} \
      scale {{ deployment_object }} {{ kubernetes_deployment_name }} --replicas={{ replicas | default(kubernetes_deployment_replica_size) }}
