---
- name: Sonatype Nexus deployment
  hosts: master
  vars:
    nexus_url: "https://{{ nexus_hostname }}/service/rest/v1"
    nexus_admin_password: "{{ lookup('community.hashi_vault.hashi_vault', vault_mount_point + '/nexus_admin_password:value', token_validate=false) }}"
    nexus_binder_password: "{{ lookup('community.hashi_vault.hashi_vault', vault_mount_point + '/nexus_binder_password:value', token_validate=false) }}"
    nexus_notebooks_password: "{{ lookup('community.hashi_vault.hashi_vault', vault_mount_point + '/nexus_notebooks_password:value',
      token_validate=false) }}"
    nexus_writer_password: "{{ lookup('community.hashi_vault.hashi_vault', vault_mount_point + '/nexus_writer_password:value', token_validate=false) }}"
    nexus_blobstore_name: default
    nexus_blobstore_type: file
    nexus_repository_name: container-notebooks
    nexus_docker_port: 8082
  become: true
  tasks:
    - name: Create Nexus configuration file on master
      vars:
        name: nexus
      template:
        src: templates/nexus.yaml
        dest: /tmp/nexus.yaml
        mode: 0600
    - name: Deploy/update Nexus instance
      command: kubectl apply -f /tmp/nexus.yaml
      environment:
        KUBECONFIG: /etc/kubernetes/admin.conf
        PATH: /sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin
      when: true
    - name: Wait for Nexus pod ready
      command: kubectl wait pod --all --namespace nexus --for condition=ready --timeout=5m
      environment:
        KUBECONFIG: /etc/kubernetes/admin.conf
      changed_when: false
      when: true
    - name: Wait for Nexus REST API
      uri:
        url: "{{ nexus_url }}/status"
        status_code: 200
        method: GET
      register: _result
      until: _result.status == 200
      retries: 120
      delay: 15
    - name: Check the admin password
      uri:
        url: "{{ nexus_url }}/status"
        force_basic_auth: true
        method: HEAD
        user: 'admin'
        password: "{{ nexus_admin_password }}"
        status_code: 200, 401
      register: nexus_admin_password_check
    - name: Admin password setup
      when:
        - nexus_admin_password_check.status == 401
      block:
        - name: Get initial admin password
          shell: 'kubectl exec -it -n nexus $(kubectl get pod -n nexus -l app=sonatype-nexus -o name) -- cat /nexus-data/admin.password'
          register: nexus_admin_password_initial
          changed_when: false
          environment:
            KUBECONFIG: /etc/kubernetes/admin.conf
        - name: Set the admin password
          uri:
            url: "{{ nexus_url }}/security/users/admin/change-password"
            force_basic_auth: true
            headers:
              Content-Type: text/plain
            method: PUT
            user: 'admin'
            password: "{{ nexus_admin_password_initial.stdout }}"
            body: "{{ nexus_admin_password }}"
            body_format: raw
            status_code: [200, 204]
    - name: Check blobstore
      uri:
        url: "{{ nexus_url }}/blobstores/{{ nexus_blobstore_type }}/{{ nexus_blobstore_name }}"
        force_basic_auth: true
        user: 'admin'
        password: "{{ nexus_admin_password }}"
        # XXX: workaround REST API bug for S3 (Nexus 3.33.0-01)
        status_code: [200, 400, 404, 500]
      register: nexus_blobstore_check
    # XXX: REST API bug II - needs to be created manually
    - name: Create blobstore
      when: &blobstore_changed
        - nexus_blobstore_check.status == 404 or nexus_blobstore_check.status == 400
      uri:
        url: "{{ nexus_url }}/blobstores/{{ nexus_blobstore_type }}"
        force_basic_auth: true
        method: POST
        user: 'admin'
        password: "{{ nexus_admin_password }}"
        body: "{{ lookup('template', 'templates/nexus-blobstore.yaml') | from_yaml }}"
        body_format: json
        status_code: [200, 201]
      changed_when: *blobstore_changed
    - name: Check binder repository
      uri:
        url: "{{ nexus_url }}/repositories/docker/hosted/{{ nexus_repository_name }}"
        force_basic_auth: true
        user: 'admin'
        password: "{{ nexus_admin_password }}"
        status_code: [200, 404]
      register: nexus_repository_check
    - name: Delete original repositories
      when: &repositories_deleted
        - nexus_repository_check.status == 404
      uri:
        url: "{{ nexus_url }}/repositories/{{ item }}"
        force_basic_auth: true
        method: DELETE
        user: 'admin'
        password: "{{ nexus_admin_password }}"
        status_code: [200, 204, 404]
      register: _result
      loop:
        - maven-central
        - maven-public
        - maven-releases
        - maven-snapshots
        - nuget-group
        - nuget-hosted
        - nuget.org-proxy
      changed_when: _result.status == 200 or _result.status == 204
    - name: Create repositories
      include_tasks: subtasks/nexus-repository.yaml
      loop:
        - name: "{{ nexus_repository_name }}"
          type: docker/hosted
        - name: registry
          type: docker/hosted
    - name: Create roles
      include_tasks: subtasks/nexus-role.yaml
      loop:
        - anonymous
        - binder
        - registry-read
        - registry-write
    - name: Create users
      include_tasks: subtasks/nexus-user.yaml
      loop:
        - binder
        - notebooks
        - writer
    - name: Check security realms
      uri:
        url: "{{ nexus_url }}/security/realms/active"
        force_basic_auth: true
        user: 'admin'
        password: "{{ nexus_admin_password }}"
        return_content: true
      register: nexus_realms_check
    - name: Update securty realms
      when: &realms_changed
        - '"DockerToken" not in nexus_realms_check.content'
      uri:
        url: "{{ nexus_url }}/security/realms/active"
        force_basic_auth: true
        headers:
          accept: application/json
          Content-Type: application/json
        method: PUT
        user: 'admin'
        password: "{{ nexus_admin_password }}"
        body: "{{ lookup('template', 'templates/nexus-realms.yaml') | from_yaml }}"
        body_format: json
        status_code: [200, 204]
      changed_when: *realms_changed