---

- name: Ensure that Grafana has nodes to run on
  import_role:
    name: openshift_master
    tasks_from: ensure_nodes_matching_selector.yml
  vars:
    openshift_master_ensure_nodes_selector: "{{ grafana_node_selector | map_to_pairs }}"
    openshift_master_ensure_nodes_service: Grafana

- name: Create grafana namespace
  oc_project:
    state: present
    name: "{{ grafana_namespace }}"
    node_selector: "{{ grafana_node_selector | lib_utils_oo_selector_to_string_list() }}"
    description: Grafana

- name: create grafana_serviceaccount_name serviceaccount
  oc_serviceaccount:
    state: present
    name: "{{ grafana_serviceaccount_name }}"
    namespace: "{{ grafana_namespace }}"
  changed_when: no

# TODO remove this when annotations are supported by oc_serviceaccount
- name: annotate serviceaccount
  command: >
    {{ openshift_client_binary }} annotate --overwrite -n {{ grafana_namespace }}
    serviceaccount {{ grafana_serviceaccount_name }} {{ item }}
    --config={{ openshift.common.config_base }}/master/admin.kubeconfig
  with_items:
    "{{ grafana_serviceaccount_annotations }}"

# create clusterrolebinding for prometheus serviceaccount
- name: Set cluster-reader permissions for grafana
  oc_adm_policy_user:
    state: present
    namespace: "{{ grafana_namespace }}"
    resource_kind: cluster-role
    resource_name: cluster-reader
    user: "system:serviceaccount:{{ grafana_namespace }}:{{ grafana_serviceaccount_name }}"

- name: create grafana routes
  oc_route:
    state: present
    name: "{{ item.name }}"
    host: "{{ item.host }}"
    namespace: "{{ grafana_namespace }}"
    service_name: "{{ item.name }}"
    tls_termination: reencrypt
  with_items:
  - name: grafana
    host: "{{ grafana_hostname }}"

- name: create services for grafana
  oc_service:
    name: "{{ grafana_service_name }}"
    namespace: "{{ grafana_namespace }}"
    labels:
      name: grafana
    annotations:
      prometheus.io/scrape: "true"
      prometheus.io/scheme: https
      service.alpha.openshift.io/serving-cert-secret-name: grafana-tls
    ports:
    - name: grafana
      port: "{{ grafana_service_port }}"
      targetPort: "{{ grafana_service_targetport }}"
      protocol: TCP
    selector:
      app: grafana

- name: Set grafana secrets
  oc_secret:
    state: present
    name: "{{ item }}-proxy"
    namespace: "{{ grafana_namespace }}"
    contents:
    - path: session_secret
      data: "{{ 43 | lib_utils_oo_random_word }}="
  with_items:
  - grafana

# Storage
- name: create grafana pvc
  oc_pvc:
    namespace: "{{ grafana_namespace }}"
    name: "{{ grafana_pvc_name }}"
    access_modes: "{{ grafana_pvc_access_modes }}"
    volume_capacity: "{{ grafana_pvc_size }}"
    selector: "{{ grafana_pvc_pv_selector }}"
    storage_class_name: "{{ grafana_sc_name }}"
  when: grafana_storage_type == 'pvc'

- name: template grafana components
  template:
    src: "{{ item }}.j2"
    dest: "{{ mktemp.stdout }}/{{ item }}"
  changed_when: no
  with_items:
  - "grafana.yml"
  - "grafana-config.yml"

- name: Set grafana configmap
  oc_configmap:
    state: present
    name: "grafana-config"
    namespace: "{{ grafana_namespace }}"
    from_file:
      defaults.ini: "{{ mktemp.stdout }}/grafana-config.yml"

- name: Set grafana deployment
  oc_obj:
    state: present
    name: "grafana"
    namespace: "{{ grafana_namespace }}"
    kind: deployment
    files:
    - "{{ mktemp.stdout }}/grafana.yml"

- name: Copy Grafana files
  copy:
    src: "dashboards/{{ item }}"
    dest: "{{ mktemp.stdout }}/{{ item }}"
  with_items:
  - "{{ grafana_dashboards }}"

- name: Wait for grafana pod
  oc_obj:
    namespace: "{{ grafana_namespace }}"
    kind: pod
    state: list
    selector: "app=grafana"
  register: grafana_pod
  until:
  - "grafana_pod.results.results[0]['items'] | count > 0"
  # Pod's 'Ready' status must be True
  - "grafana_pod.results.results[0]['items'] | lib_utils_oo_collect(attribute='status.conditions') | lib_utils_oo_collect(attribute='status', filters={'type': 'Ready'}) | map('bool') | select | list | count == 1"
  delay: 10
  retries: "{{ (grafana_timeout | int / 10) | int }}"

- name: Get the prometheus SA token
  shell: "{{ openshift_client_binary }} --config={{ openshift.common.config_base }}/master/admin.kubeconfig sa get-token {{ grafana_prometheus_serviceaccount }} -n {{ grafana_prometheus_namespace }}"
  register: prometheus_sa_token

- name: Get the grafana SA token
  shell: "{{ openshift_client_binary }} --config={{ openshift.common.config_base }}/master/admin.kubeconfig sa get-token {{ grafana_serviceaccount_name }} -n {{ grafana_namespace }}"
  register: grafana_sa_token

- name: Get prometheus route
  oc_route:
    state: list
    name: prometheus
    namespace: "{{ grafana_prometheus_namespace }}"
  register: prometheus_route

- name: Get grafana route
  oc_route:
    state: list
    name: grafana
    namespace: "{{ grafana_namespace }}"
  register: grafana_route

- name: set facts
  set_fact:
    payload_data: "{{ grafana_datasource_json | regex_replace('grafana_name', grafana_datasource_name ) | regex_replace('prometheus_url', prometheus_route.results[0].spec.host ) | regex_replace('satoken',  prometheus_sa_token.stdout ) }}"
    grafana_route: "https://{{ grafana_route.results[0].spec.host }}"

- name: Add new datasource to grafana
  uri:
    url: "{{ grafana_route }}/api/datasources"
    user: "{{ grafana_sa_token.stdout }}"
    force_basic_auth: true
    method: POST
    body: '{{ payload_data }}'
    body_format: json
    status_code:
    - 200
    - 409
    headers:
      Content-Type: "Content-Type: application/json"
  register: add_ds

- block:
  - name: Retrieve current grafana datasource
    uri:
      url: "{{ grafana_route }}/api/datasources/name/{{ grafana_datasource_name }}"
      user: "{{ grafana_sa_token.stdout }}"
      validate_certs: false
      method: GET
      status_code:
      - 200
    register: grafana_ds
  - name: Update grafana datasource
    uri:
      url: "{{ grafana_route }}/api/datasources/{{ grafana_ds.json['id'] }}"
      user: "{{ grafana_sa_token.stdout }}"
      validate_certs: false
      method: PUT
      body: '{{ payload_data }}'
      body_format: json
      headers:
        Content-Type: "Content-Type: application/json"
      status_code:
      - 200
    register: update_ds
  when: add_ds.status == 409

- name: Regex set data source name for openshift dashboard
  replace:
    path: "{{ mktemp.stdout }}/openshift-cluster-monitoring.json"
    regexp: '{{ item.regexp }}'
    replace: '{{ item.replace }}'
    backup: yes
  with_items:
  - regexp: '##DS_PR##'
    replace: '{{ grafana_datasource_name }}'
  - regexp: 'Xs'
    replace: '{{ grafana_graph_granularity }}'

- name: Regex set data source name for node exporter
  replace:
    path: "{{ mktemp.stdout }}/node-exporter-full-dashboard.json"
    regexp: '{{ item.regexp }}'
    replace: '{{ item.replace }}'
    backup: yes
  with_items:
  - regexp: '##DS_PR##'
    replace: '{{ grafana_datasource_name }}'
  - regexp: 'Xs'
    replace: '{{ grafana_graph_granularity }}'
  when: grafana_node_exporter | default(false) | bool == true

- set_fact:
    cluster_monitoring_dashboard: "{{ mktemp.stdout }}/openshift-cluster-monitoring.json"
    node_exporter_dashboard: "{{ mktemp.stdout }}/node-exporter-full-dashboard.json"

- name: Slurp dashboard file
  slurp:
    src: "{{ cluster_monitoring_dashboard }}"
  register: slurpfile

- set_fact:
    dashboard_data: '{{ slurpfile["content"] | b64decode | from_json | combine({ "dashboard": { "overwrite": true } }, recursive=True) | to_json }}'

- name: Add openshift dashboard
  uri:
    url: "{{ grafana_route }}/api/dashboards/db"
    user: "{{ grafana_sa_token.stdout }}"
    force_basic_auth: true
    method: POST
    body: '{{ dashboard_data }}'
    body_format: json
    status_code:
    - 200
    - 412
    headers:
      Content-Type: "Content-Type: application/json"
  register: add_ds

- name: Slurp dashboard file
  slurp:
    src: "{{ node_exporter_dashboard }}"
  register: slurpfile

- set_fact:
    dashboard_data: '{{ slurpfile["content"] | b64decode | from_json | combine({ "dashboard": { "overwrite": true } }, recursive=True) | to_json }}'

- name: Add node exporter dashboard
  uri:
    url: "{{ grafana_route }}/api/dashboards/db"
    user: "{{ grafana_sa_token.stdout }}"
    force_basic_auth: true
    method: POST
    body: '{{ dashboard_data }}'
    body_format: json
    status_code:
    - 200
    - 412
    headers:
      Content-Type: "Content-Type: application/json"
  register: add_ds
  when: grafana_node_exporter | default(false) | bool == true
