---
- name: deploy browsertrix cloud on digital ocean
  hosts: localhost
  connection: local
  gather_facts: false
  vars_files:
    - ../group_vars/do/main.yml

  tasks:

  # ===========================================
  # Init
    - name: d_ocean | init | install doctl and helm
      ansible.builtin.package:
        name: "{{ item }}"
        state: present
      loop:
        - helm
        - doctl

    - name: d_ocean | init | set full domain
      ansible.builtin.set_fact:
        full_domain: "{{ subdomain + '.' + domain if subdomain else domain }}"

  # MongoDB
  # ===========================================
    - name: d_ocean | db | test for existing mongodb
      ansible.builtin.command: doctl db list -o json
      changed_when: false
      failed_when: false
      register: db_check

    - name: d_ocean | db | create mongodb database
      ansible.builtin.command: doctl databases create {{ db_name }} --region {{ droplet_region }} --engine mongodb --version 6 --output json
      async: 1800
      poll: 60
      register: db_create
      when: "db_check.stdout | from_json | json_query(name_query) | length < 1"
      vars:
        name_query: '[?name==`{{db_name}}`]'

    - name: d_ocean | db | set db url
      ansible.builtin.set_fact:
        db_url:  "{{ db_create.stdout if db_create.changed == false else db_check.stdout | from_json | json_query(name_query) | json_query('[0].private_connection.uri') }}" 
      vars:
        name_query: '[?name==`{{db_name}}`]'

    - name: d_ocean | db | set db id
      ansible.builtin.set_fact:
        db_uuid: "{{ db_create.stdout if db_create.changed == false else db_check.stdout | from_json | json_query(name_query) | json_query('[0].id')}}"
      vars:
        name_query: '[?name==`{{db_name}}`]'

  # Storage (Space)
  # ===========================================
    - name: d_ocean | space | create new
      community.digitalocean.digital_ocean_spaces:
        name: "{{ bucket_name }}"
        state: present
        oauth_token: "{{ lookup('env', 'DO_API_TOKEN') }}"
        aws_access_key_id: "{{ lookup('env', 'DO_AWS_ACCESS_KEY') }}"
        aws_secret_access_key: "{{ lookup('env', 'DO_AWS_SECRET_KEY') }}"
        region: "{{ droplet_region }}"
      register: db_space_result
      ignore_errors: true

    - name: d_ocean | space | set endpoint urls
      ansible.builtin.set_fact:
        endpoint_url: "{{ db_space_result.data.space.endpoint_url }}/"
        bucket_endpoint_url: "{{ db_space_result.data.space.endpoint_url }}/{{ db_space_result.data.space.name }}/{{ bucket_path }}/"

    - name: d_ocean | space | set bucket cors
      community.aws.aws_s3_cors:
        name: "{{ bucket_name }}"
        aws_access_key: "{{ lookup('env', 'DO_AWS_ACCESS_KEY') }}"
        aws_secret_key: "{{ lookup('env', 'DO_AWS_SECRET_KEY') }}"
        endpoint_url: "{{ endpoint_url }}"
        region: "{{ droplet_region }}"
        state: present
        rules:
          - allowed_origins:
              - "https://{{ full_domain }}"
            allowed_methods:
              - GET
              - HEAD
            allowed_headers:
              - "*"
            expose_headers:
              - Content-Range
              - Content-Encoding
              - Content-Length

  # K8S
  # ===========================================
    - name: d_ocean | k8s | test for existing k8s cluster
      ansible.builtin.command: doctl k8s cluster list
      changed_when: false
      failed_when: false
      register: cluster_check

    - name: d_ocean | k8s | create a kubernetes cluster in {{ droplet_region }}
      # skip_ansible_lint
      ansible.builtin.command: >-
        doctl kubernetes cluster create {{ k8s_name }} --1-clicks ingress-nginx,cert-manager --node-pool
        "{{ node_pools | select('match','name=*') | list |join(',') }}"
        --region={{ droplet_region }}

      async: 1800
      poll: 60
      changed_when: false
      when: cluster_check.stdout.find(k8s_name) == -1

    - name: d_ocean | k8s | test for existing k8s cluster's node pools
      ansible.builtin.command: doctl kubernetes cluster node-pool list {{ k8s_name }}
      changed_when: false
      failed_when: false
      register: cluster_nodepools_check

    - name: d_ocean | k8s | create a admin node pool in the cluster {{ k8s_name }}
      # skip_ansible_lint
      ansible.builtin.command: >-
        doctl kubernetes cluster node-pool create {{ k8s_name }} 
          --name {{ admin_node_pool.name }}   --size {{ admin_node_pool.size }} 
          --label {{ admin_node_pool.label }} --count {{ admin_node_pool.count }} 

      async: 1800
      poll: 60
      changed_when: false
      when: enable_admin_addons and cluster_nodepools_check.stdout.find(admin_node_pool.name) == -1

    - name: d_ocean | k8s | remove a admin node pool from the cluster {{ k8s_name }}
      # skip_ansible_lint
      ansible.builtin.command: >-
        echo "yes" | doctl kubernetes cluster node-pool delete {{ k8s_name }} {{ admin_node_pool.name }}

      async: 1800
      poll: 60
      changed_when: false
      when: not enable_admin_addons and cluster_nodepools_check.stdout.find(admin_node_pool.name) >= 0

    - name: d_ocean | k8s | Get information about our cluster
      community.digitalocean.digital_ocean_kubernetes_info:
        oauth_token: "{{ lookup('ansible.builtin.env', 'DO_API_TOKEN') }}"
        name: "{{ k8s_name }}"
        return_kubeconfig: true
      register: my_cluster

    - name: d_ocean | k8s | print information about an existing DigitalOcean Kubernetes cluster
      ansible.builtin.debug:
        msg: Cluster name is {{ my_cluster.data.name }}, ID is {{ my_cluster.data.id }}
      failed_when: not my_cluster

    - name: d_ocean | k8s | save kubectl config to kube_dir
      ansible.builtin.command: doctl kubernetes cluster kubeconfig save {{ my_cluster.data.id }}
      changed_when: false

    - name: d_ocean | k8s | get loadbalancer info from doctl
      ansible.builtin.command: doctl k8s cluster list-associated-resources {{ my_cluster.data.id }} --format LoadBalancers --output json
      register: lb_id_result
      retries: 100
      delay: 5
      changed_when: lb_id_result.stdout | from_json | json_query('load_balancers') | length > 0
      until: lb_id_result.stdout | from_json | json_query('load_balancers') | length > 0

    - name: d_ocean | k8s | parse lb id
      ansible.builtin.set_fact:
        lb_id: "{{ lb_id_result.stdout | from_json | json_query('load_balancers[0].id') }}"

  # DNS
  # ===========================================
    - name: d_ocean | dns | grab loadbalancer ip using doctl
      ansible.builtin.command: doctl compute load-balancer get --format IP "{{ lb_id }}"
      register: loadbalancer_ip_result
      retries: 100
      delay: 5
      changed_when: loadbalancer_ip_result.stdout_lines | length > 1
      until: loadbalancer_ip_result.stdout_lines | length > 1

    - name: d_ocean | dns | parse ip
      ansible.builtin.set_fact:
        lb_ip: "{{ loadbalancer_ip_result.stdout_lines[1] }}"

    - name: d_ocean | dns | register the dns for browsertrix cloud
      ansible.builtin.command: >-
          doctl compute domain records create --record-type A --record-name "{{ subdomain if subdomain else '@' }}" --record-data "{{ lb_ip }}" "{{ domain }}"

      changed_when: dns_result.rc == 0
      register: dns_result


  # Signing + DNS
  # ===========================================
    - name: d_coean | signing | set signing domain + authtoken
      ansible.builtin.set_fact:
        full_signing_domain: "{{ signing_host }}.{{ full_domain }}"
        signing_subdomain: "{{ signing_host + '.' + subdomain if subdomain else signing_host }}"
        signing_authtoken: "{{ 99999999 | random | to_uuid }}"

      when: enable_signing

    - name: d_ocean | signing | register the dns for signing subdomain
      ansible.builtin.command: >-
          doctl compute domain records create --record-type A --record-name "{{ signing_subdomain }}" --record-data "{{ lb_ip }}" "{{ domain }}"

      register: signing_dns_result
      when: enable_signing


  # Registry
  # ===========================================
    - name: d_ocean | registry | get endpoint, if using registry
      ansible.builtin.command: doctl registry get --format Endpoint
      register: do_registry_result
      when: use_do_registry
      failed_when: do_registry_result.stdout_lines | length < 2

    - name: d_ocean | registry | store registry endpoint
      ansible.builtin.set_fact:
        registry_endpoint: "{{ do_registry_result.stdout_lines[1] }}"
      when: use_do_registry

    - name: d_ocean | registry | configure kubectl
      ansible.builtin.shell: doctl k8s cluster kubeconfig save {{ my_cluster.data.id }}
      when: configure_kubectl

    - name: d_ocean | registry | add to new k8s cluster
      ansible.builtin.shell: set -o pipefail && doctl registry kubernetes-manifest | kubectl apply -f -
      when: use_do_registry

  # Addons
  # ===========================================
    - name: d_ocean | addons | run all admin bookstrap scripts
      ansible.builtin.command: >-
          ../../chart/admin/logging/scripts/eck_install.sh
      register: addons_init
      when: enable_admin_addons

  # Helm Output + Deploy
  # ===========================================
    - name: d_ocean | helm | output values yaml
      ansible.builtin.template:
        src: ../group_vars/do/do-values.template.yaml
        dest: ../deploys/{{ project_name }}-values.yaml
        mode: u+rw

    - name: d_ocean | helm | deploy btrix
      ansible.builtin.command: helm upgrade --install -f ../../chart/values.yaml -f ../deploys/{{ project_name }}-values.yaml btrix ../../chart/
      register: helm_result
      changed_when: helm_result.rc == 0

      tags: helm_upgrade
