grafana : import and screenshot project-config graphs
This is a job that imports the graphs we have defined in project-config/grafana to a testing grafana instance, then takes some screenshots to validate the layout and aid review. Operation is fairly straight-forward; a grafana container is setup (see related work in Ibbc2b116d0c496655a7ce6bb6971e8270ac32647) and grafyaml is used to import the dashboards from project-config. We query the grafana instance to find the dashboards, then use selenium and a small helper to take screenshots of each. It pulls graphyaml from the buildset registry as a soft dependency, so we can also add it as an extra test to the grafyaml repo. Change-Id: Ice0863d5a180738119d572df1871093a292126be
This commit is contained in:
parent
eea8a20d03
commit
59e8221e7c
50
playbooks/grafana/files/screenshot.py
Normal file
50
playbooks/grafana/files/screenshot.py
Normal file
@ -0,0 +1,50 @@
|
||||
#! /usr/bin/env python3
|
||||
#
|
||||
# Copyright 2022 RedHat, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
#
|
||||
|
||||
# A selenium wrapper to take OpenDev grafana screenshots in CI
|
||||
|
||||
import sys
|
||||
import time
|
||||
from selenium import webdriver
|
||||
from selenium.webdriver.support.ui import WebDriverWait
|
||||
|
||||
out = sys.argv[1]
|
||||
height = sys.argv[2]
|
||||
url = sys.argv[3]
|
||||
|
||||
print("Getting %s -> %s" % (url, out))
|
||||
|
||||
firefox_options = webdriver.FirefoxOptions()
|
||||
|
||||
driver = webdriver.Remote(
|
||||
command_executor='http://localhost:4444/wd/hub',
|
||||
options=firefox_options)
|
||||
|
||||
driver.set_window_size(1920, height)
|
||||
driver.get(url)
|
||||
|
||||
WebDriverWait(driver, 30).until(
|
||||
lambda driver: driver.execute_script(
|
||||
'return document.readyState') == 'complete')
|
||||
|
||||
# NOTE(ianw) : Grafana is a magic react app and I haven't found
|
||||
# anything to reliably activate on other than just waiting a bit.
|
||||
time.sleep(5)
|
||||
|
||||
driver.get_screenshot_as_file(out)
|
||||
|
||||
driver.quit()
|
132
playbooks/grafana/main.yaml
Normal file
132
playbooks/grafana/main.yaml
Normal file
@ -0,0 +1,132 @@
|
||||
- name: Take screenshots of project-config grafana graphs
|
||||
hosts: all
|
||||
tasks:
|
||||
|
||||
- name: install docker
|
||||
include_role:
|
||||
name: ensure-docker
|
||||
|
||||
# NOTE: keep after ensure-docker
|
||||
- name: Use buildset registry
|
||||
include_role:
|
||||
name: use-buildset-registry
|
||||
|
||||
- name: install pip
|
||||
include_role:
|
||||
name: ensure-pip
|
||||
|
||||
- name: Install dependencies
|
||||
package:
|
||||
name:
|
||||
- python3-docker
|
||||
state: present
|
||||
become: yes
|
||||
|
||||
- name: Make environment vars
|
||||
set_fact:
|
||||
SECRETS_DIR: '{{ ansible_user_dir }}/grafana-secrets'
|
||||
GRAFYAML_DIR: "{{ ansible_user_dir }}/{{ zuul.projects['opendev.org/openstack/project-config'].src_dir }}/grafana"
|
||||
SCREENSHOTS: '{{ ansible_user_dir }}/screenshots'
|
||||
# NOTE(ianw) : screenshots are 1920 x this height. This means
|
||||
# it is about the right width to see easily. 5000 is a
|
||||
# generic compromise; a bit long for some graphs, but it's
|
||||
# just a solid black that compresses well in the .pngs. If
|
||||
# required we can key each graph to individual heights with a
|
||||
# config file or something some other time.
|
||||
SCREENSHOT_HEIGHT: '5000'
|
||||
|
||||
- name: Setup test environment
|
||||
shell:
|
||||
executable: /bin/bash
|
||||
cmd: |
|
||||
set -x
|
||||
mkdir -p {{ SCREENSHOTS }}
|
||||
mkdir -p {{ SECRETS_DIR }}
|
||||
echo "password" > {{ SECRETS_DIR }}/admin_password
|
||||
echo "admin" > {{ SECRETS_DIR }}/admin_user
|
||||
echo "key" > {{ SECRETS_DIR }}/secret_key
|
||||
|
||||
- name: Run grafana
|
||||
become: true
|
||||
docker_container:
|
||||
name: grafana-opendev_test
|
||||
image: "docker.io/grafana/grafana-oss"
|
||||
state: started
|
||||
network_mode: host
|
||||
volumes:
|
||||
- '{{ SECRETS_DIR }}:/etc/grafana/secrets'
|
||||
env:
|
||||
GF_AUTH_ANONYMOUS_ENABLED: 'true'
|
||||
GF_USER_ALLOW_SIGN_UP: 'false'
|
||||
GF_SECURITY_ADMIN_PASSWORD__FILE: /etc/grafana/secrets/admin_password
|
||||
GF_SECURITY_ADMIN_USER__FILE: /etc/grafana/secrets/admin_user
|
||||
GF_SECURITY_SECRET_KEY__FILE: /etc/grafana/secrets/secret_key
|
||||
|
||||
- name: Run selenium
|
||||
become: true
|
||||
docker_container:
|
||||
name: selenium-firefox
|
||||
state: started
|
||||
image: "docker.io/selenium/standalone-firefox"
|
||||
# needs to talk to localhost
|
||||
network_mode: host
|
||||
|
||||
- name: Install selenium bindings
|
||||
pip:
|
||||
name: selenium
|
||||
virtualenv: '{{ ansible_user_dir }}/venv'
|
||||
virtualenv_command: '{{ ensure_pip_virtualenv_command }}'
|
||||
|
||||
- name: Copy screenshot helper
|
||||
copy:
|
||||
src: 'screenshot.py'
|
||||
dest: '{{ ansible_user_dir }}'
|
||||
|
||||
- name: Import dashboards
|
||||
shell:
|
||||
executable: /bin/bash
|
||||
cmd: |
|
||||
docker run --rm -t --network=host -e 'GRAFANA_URL=http://admin:password@localhost:3000' -v {{ GRAFYAML_DIR }}:/grafana:ro opendevorg/grafyaml
|
||||
|
||||
- name: Get list of dashboards
|
||||
uri:
|
||||
url: 'http://localhost:3000/api/search'
|
||||
method: GET
|
||||
return_content: yes
|
||||
validate_certs: false
|
||||
status_code: 200
|
||||
body_format: json
|
||||
register: _dashboards
|
||||
|
||||
- name: List found dashboard URLs
|
||||
debug:
|
||||
msg: "{{ _dashboards.json | map(attribute='url') | list }}"
|
||||
|
||||
# NOTE(ianw) : Per the notes in the helper, this pauses for 5
|
||||
# seconds for each shot to allow the app to initalize. I tried
|
||||
# running this in parallel but it seemed to deadlock. I belive it
|
||||
# has something to do with with the way selenium works with the
|
||||
# headless browser. So it might be possible to speed up.
|
||||
- name: Take screenshots
|
||||
shell:
|
||||
executable: /bin/bash
|
||||
cmd: |
|
||||
set -x
|
||||
name=$(basename {{ item }})
|
||||
url="http://localhost:3000{{ item }}"
|
||||
{{ ansible_user_dir }}/venv/bin/python {{ ansible_user_dir }}/screenshot.py "{{ SCREENSHOTS }}/${name}.png" {{ SCREENSHOT_HEIGHT }} "${url}"
|
||||
loop: "{{ _dashboards.json | map(attribute='url') | list }}"
|
||||
|
||||
- name: Copy output
|
||||
synchronize:
|
||||
src: '{{ SCREENSHOTS }}'
|
||||
dest: '{{ zuul.executor.log_root }}'
|
||||
mode: pull
|
||||
|
||||
- name: Return screenshots artifact
|
||||
zuul_return:
|
||||
data:
|
||||
zuul:
|
||||
artifacts:
|
||||
- name: Screenshots
|
||||
url: "screenshots"
|
@ -1282,6 +1282,19 @@
|
||||
- other-requirements.txt
|
||||
- tox.ini
|
||||
|
||||
- job:
|
||||
name: project-config-grafana
|
||||
description: |
|
||||
Validates import and creates screenshots of project-config
|
||||
defined graphs.
|
||||
run: playbooks/grafana/main.yaml
|
||||
required-projects:
|
||||
- openstack/project-config
|
||||
dependencies:
|
||||
- name: opendev-buildset-registry
|
||||
- name: grafyaml-build-image
|
||||
soft: true
|
||||
|
||||
- job:
|
||||
name: project-config-irc-access
|
||||
parent: tox
|
||||
|
@ -5,6 +5,10 @@
|
||||
|
||||
check:
|
||||
jobs:
|
||||
- opendev-buildset-registry
|
||||
- project-config-grafana:
|
||||
files:
|
||||
- playbooks/grafana
|
||||
- openafs-rpm-package-build-centos-7-x86
|
||||
- openafs-rpm-package-build-centos-8-stream-x86
|
||||
- openafs-rpm-package-build-centos-8-stream-arm64
|
||||
|
Loading…
x
Reference in New Issue
Block a user