--- - name: Ensure that Grafana has nodes to run on import_role: name: openshift_control_plane 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 }} 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: oc sa get-token {{ grafana_prometheus_serviceaccount }} -n {{ grafana_prometheus_namespace }} register: prometheus_sa_token - name: Get the grafana SA token shell: oc 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 headers: Content-Type: "Content-Type: application/json" register: add_ds - name: Regex set data soure 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 soure 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 - name: Add openshift dashboard uri: url: "{{ grafana_route }}/api/dashboards/db" user: "{{ grafana_sa_token.stdout }}" force_basic_auth: true method: POST body: '{{ slurpfile["content"] | b64decode }}' body_format: json headers: Content-Type: "Content-Type: application/json" register: add_ds - name: Slurp dashboard file slurp: src: "{{ node_exporter_dashboard }}" register: slurpfile - name: Add node exporter dashboard uri: url: "{{ grafana_route }}/api/dashboards/db" user: "{{ grafana_sa_token.stdout }}" force_basic_auth: true method: POST body: '{{ slurpfile["content"] | b64decode }}' body_format: json headers: Content-Type: "Content-Type: application/json" register: add_ds when: grafana_node_exporter | default(false) | bool == true