---
- name: is there already a subscription?
  kubernetes.core.k8s_info:
    kubeconfig: "{{ ansible_facts['user_dir'] }}/kubeconfig-ocp4"
    validate_certs: no
    api_version: operators.coreos.com/v1alpha1
    kind: subscription
    namespace: openshift-sso
    name: rhsso
  register: sub

- name: oi - is there already an operator?
  kubernetes.core.k8s_info:
    kubeconfig: "{{ ansible_facts['user_dir'] }}/kubeconfig-ocp4"
    validate_certs: no
    api_version: operators.coreos.com/v1alpha1
    kind: clusterserviceversion
    namespace: openshift-sso
    name: "{{ sub.resources[0].status.installedCSV }}"
  register: csv
  when:
    - sub.resources is defined
    - (sub.resources | length) > 0
    - sub.resources[0].spec.name == "rhsso-operator"
    - sub.resources[0].status.installedCSV is defined

- name: assert csv is there
  set_fact:
    csv_is_there: true

- name: reset the above fact if not the case
  set_fact:
    csv_is_there: false
  when: (csv is not defined) or (csv.resources is not defined) or (csv.resources | length == 0) or (csv.resources[0].status.phase != "Succeeded")

- name: is there a rhsso pod?
  kubernetes.core.k8s_info:
    kubeconfig: "{{ ansible_facts['user_dir'] }}/kubeconfig-ocp4"
    validate_certs: no
    api_version: v1
    kind: pod
    namespace: openshift-sso
    label_selectors:
      - app = keycloak
      - component = keycloak
  register: rhsso_pod

- name: assert central is there
  set_fact:
    rhsso_is_there: true

- name: reset the above fact if not the case
  set_fact:
    rhsso_is_there: false
  when: (rhsso_pod is not defined) or (rhsso_pod.resources is not defined) or (rhsso_pod.resources | length == 0) or (rhsso_pod.resources[0].status.phase != "Running")

#- name: is there anyone home at the api endpoint?

- name: create ns, og, and sub
  kubernetes.core.k8s:
    kubeconfig: "{{ ansible_facts['user_dir'] }}/kubeconfig-ocp4"
    validate_certs: no
    template: templates/rhsso-ns-and-sub.yml
  when: not csv_is_there

- name: wait until csv is there and ready
  kubernetes.core.k8s_info:
    kubeconfig: "{{ ansible_facts['user_dir'] }}/kubeconfig-ocp4"
    validate_certs: no
    api_version: operators.coreos.com/v1alpha1
    kind: clusterserviceversion
    name: rhsso-operator.{{ sso_z }}
    namespace: openshift-sso
  when: not csv_is_there
  register: csv
  until: (csv.resources | length) > 0 and csv.resources[0].status.phase == "Succeeded"
  retries: 30
  delay: 5

- name: deploy cr
  kubernetes.core.k8s:
    kubeconfig: "{{ ansible_facts['user_dir'] }}/kubeconfig-ocp4"
    validate_certs: no
    src: files/rhsso-cr.yml
  when: not rhsso_is_there

- name: wait for rhsso pod to be up
  kubernetes.core.k8s_info:
    kubeconfig: "{{ ansible_facts['user_dir'] }}/kubeconfig-ocp4"
    validate_certs: no
    api_version: v1
    kind: pod
    namespace: openshift-sso
    label_selectors:
      - app = keycloak
      - component = keycloak
  when: not rhsso_is_there
  register: rhsso_pod
  until: (rhsso_pod.resources | length) > 0 and rhsso_pod.resources[0].status.phase == "Running"
  retries: 30
  delay: 5

- name: look up route
  kubernetes.core.k8s_info:
    kubeconfig: "{{ ansible_facts['user_dir'] }}/kubeconfig-ocp4"
    validate_certs: no
    api_version: route.openshift.io/v1
    kind: route
    namespace: openshift-sso
    name: keycloak
  register: rhsso_route

- assert:
    that: rhsso_route.resources | length > 0
    fail_msg: "ERROR: RHSSO seems to be there, but route is not present."
    success_msg: "OK, got route to RHSSO."

- name: store route hostname as fact
  set_fact:
    rhsso_ep: "{{ rhsso_route.resources[0].spec.host }}"

- name: store the api endpoint in a file
  copy:
    dest: "{{ ansible_facts['user_dir'] }}/rhsso-endpoint"
    content: "https://{{ rhsso_ep }}/auth/admin"

- name: look up secret
  kubernetes.core.k8s_info:
    kubeconfig: "{{ ansible_facts['user_dir'] }}/kubeconfig-ocp4"
    validate_certs: no
    api_version: v1
    kind: secret
    namespace: openshift-sso
    name: credential-rhsso
  register: rhsso_secret

- assert:
    that: rhsso_secret.resources | length > 0
    fail_msg: "ERROR: RHSSO seems to be there, but auth secret is not present."
    success_msg: "OK, got secret to RHSSO."

- name: store rhsso pass as fact
  set_fact:
    rhsso_pass: "{{ rhsso_secret.resources[0].data.ADMIN_PASSWORD }}"

- name: store the password in a file
  copy:
    dest: "{{ ansible_facts['user_dir'] }}/rhsso-password"
    content: "{{ rhsso_pass | string | b64decode }}"

- name: (re)apply the realm if necessary
  kubernetes.core.k8s:
    kubeconfig: "{{ ansible_facts['user_dir'] }}/kubeconfig-ocp4"
    validate_certs: no
    src: files/rhsso-realm.yml

# TODO: wait for realm to reconcile

- name: (re)apply the client if necessary
  kubernetes.core.k8s:
    kubeconfig: "{{ ansible_facts['user_dir'] }}/kubeconfig-ocp4"
    validate_certs: no
    src: files/rhsso-client.yml
    apply: yes

- name: make sure rhsso pod is ready
  kubernetes.core.k8s_info:
    kubeconfig: "{{ ansible_facts['user_dir'] }}/kubeconfig-ocp4"
    validate_certs: no
    api_version: v1
    kind: pod
    namespace: openshift-sso
    label_selectors:
      - app = keycloak
      - component = keycloak
  when: not rhsso_is_there
  register: rhsso_pod
  until: (rhsso_pod.resources | length) > 0 and rhsso_pod.resources[0].status.containerStatuses[0].ready
  retries: 60
  delay: 5

- name: get an auth token
  uri:
    method: POST
    return_content: true
    validate_certs: false
    url: "https://{{ rhsso_ep }}/auth/realms/master/protocol/openid-connect/token"
    headers:
      Accept: application/json
      Content-Type: application/x-www-form-urlencoded
    body_format: json
    body: "client_id=admin-cli&username=admin&password={{ rhsso_pass | string | b64decode }}&grant_type=password"
  register: rhsso_token_rsp

- assert:
    that: rhsso_token_rsp.json is defined and rhsso_token_rsp.json.access_token is defined
    fail_msg: "ERROR: Failed to obtain authentication token from RHSSO."
    success_msg: "OK, got auth token; proceeding."

- name: store the token as a fact
  set_fact:
    rhsso_token: "{{ rhsso_token_rsp.json.access_token }}"

- name: get existing role list
  uri:
    method: GET
    return_content: true
    validate_certs: false
    url: "https://{{ rhsso_ep }}/auth/admin/realms/rhacs/roles"
    headers:
      Authorization: Bearer {{ rhsso_token }}
      Accept: application/json
  register: rhsso_roles_raw

- name: store existing roles as a list
  set_fact:
    rhsso_roles: "{{ rhsso_roles_raw.json | items2dict(key_name='name', value_name='id') }}"

- name: create roles
  uri:
    method: POST
    return_content: true
    validate_certs: false
    url: "https://{{ rhsso_ep }}/auth/admin/realms/rhacs/roles"
    headers:
      Authorization: Bearer {{ rhsso_token }}
      Accept: application/json
      Content-Type: application/json
    body_format: json
    body: '{"name": "{{ item | string }}"}'
    status_code:
      - 200
      - 201
  loop:
    - admins
    - analysts
    - cicd
    - reporters
    - developers
  when: item not in rhsso_roles.keys()

- name: get existing group list
  uri:
    method: GET
    return_content: true
    validate_certs: false
    url: "https://{{ rhsso_ep }}/auth/admin/realms/rhacs/groups"
    headers:
      Authorization: Bearer {{ rhsso_token }}
      Accept: application/json
  register: rhsso_groups_raw

- name: store existing groups as a list
  set_fact:
    rhsso_groups: "{{ rhsso_groups_raw.json | items2dict(key_name='name', value_name='id') }}"

- name: create groups
  uri:
    method: POST
    return_content: true
    validate_certs: false
    url: "https://{{ rhsso_ep }}/auth/admin/realms/rhacs/groups"
    headers:
      Authorization: Bearer {{ rhsso_token }}
      Accept: application/json
      Content-Type: application/json
    body_format: json
    body: '{"name": "{{ item | string }}" }'
    status_code:
      - 200
      - 201
  loop:
    - admins
    - analysts
    - cicd
    - reporters
    - developers
  when: item not in rhsso_groups.keys()

- name: retrieve group list again
  uri:
    method: GET
    return_content: true
    validate_certs: false
    url: "https://{{ rhsso_ep }}/auth/admin/realms/rhacs/groups"
    headers:
      Authorization: Bearer {{ rhsso_token }}
      Accept: application/json
  register: rhsso_groups_raw

- name: reformat existing groups as a list
  set_fact:
    rhsso_groups: "{{ rhsso_groups_raw.json | items2dict(key_name='name', value_name='id') }}"

# XXX for some dumbass reason realmRoles assignment won't stick, either when creating or updating XXX
- name: assign realm roles
  uri:
    method: POST
    return_content: true
    validate_certs: false
    url: "https://{{ rhsso_ep }}/auth/admin/realms/rhacs/groups"
    headers:
      Authorization: Bearer {{ rhsso_token }}
      Accept: application/json
      Content-Type: application/json
    body_format: json
    body: '{"id": "{{ rhsso_groups[item] }}", "name": "{{ item | string }}", "realmRoles": [ "{{ item | string }}" ]}'
    status_code:
      - 200
      - 201
      - 204
  loop:
    - admins
    - analysts
    - cicd
    - reporters
    - developers

- name: create the users
  kubernetes.core.k8s:
    kubeconfig: "{{ ansible_facts['user_dir'] }}/kubeconfig-ocp4"
    validate_certs: no
    template: templates/rhsso-users.yml
...