From c2f3486ca4b2d1f9387e21192ea9d5f4ec70e623 Mon Sep 17 00:00:00 2001 From: Steven Fitzpatrick Date: Thu, 10 Oct 2019 00:22:33 -0500 Subject: [PATCH] OSH-Infra Selenium Tests Refactor This change would update the LMA selenium tests to share a more similar structure. Additional logging is introduced, and the scripts will fail gracefully if the targeted service cannot be reached. Change-Id: Ief7f69b952b2f0e33b7b738bb76083247766f662 --- tools/deployment/common/grafana-selenium.sh | 8 +- tools/deployment/common/kibana-selenium.sh | 14 +- tools/deployment/common/nagios-selenium.sh | 6 + .../deployment/common/prometheus-selenium.sh | 6 + tools/gate/selenium/grafanaSelenium.py | 163 +++++++++--------- tools/gate/selenium/kibanaSelenium.py | 111 ++++++------ tools/gate/selenium/nagiosSelenium.py | 124 ++++++------- tools/gate/selenium/prometheusSelenium.py | 127 +++++++------- tools/gate/selenium/seleniumtester.py | 102 +++++++++++ 9 files changed, 392 insertions(+), 269 deletions(-) create mode 100644 tools/gate/selenium/seleniumtester.py diff --git a/tools/deployment/common/grafana-selenium.sh b/tools/deployment/common/grafana-selenium.sh index 75a6c4f2d..7f8971141 100755 --- a/tools/deployment/common/grafana-selenium.sh +++ b/tools/deployment/common/grafana-selenium.sh @@ -1,6 +1,12 @@ #!/bin/bash +set -xe + +export CHROMEDRIVER="${CHROMEDRIVER:="/etc/selenium/chromedriver"}" +export ARTIFACTS_DIR="${ARTIFACTS_DIR:="/tmp/artifacts/"}" + export GRAFANA_USER="admin" export GRAFANA_PASSWORD="password" -export GRAFANA_URI="http://grafana.osh-infra.svc.cluster.local" +export GRAFANA_URI="grafana.osh-infra.svc.cluster.local" + python tools/gate/selenium/grafanaSelenium.py diff --git a/tools/deployment/common/kibana-selenium.sh b/tools/deployment/common/kibana-selenium.sh index a23115e18..eae9c81ae 100755 --- a/tools/deployment/common/kibana-selenium.sh +++ b/tools/deployment/common/kibana-selenium.sh @@ -1,8 +1,16 @@ #!/bin/bash +set -xe + +export CHROMEDRIVER="${CHROMEDRIVER:="/etc/selenium/chromedriver"}" +export ARTIFACTS_DIR="${ARTIFACTS_DIR:="/tmp/artifacts/"}" + export KIBANA_USER="admin" export KIBANA_PASSWORD="changeme" -export KIBANA_LOGSTASH_URI="kibana.osh-infra.svc.cluster.local/app/kibana#/discover?_g=()&_a=(columns:!(_source),index:'logstash-*',interval:auto,query:(match_all:()),sort:!('@timestamp',desc))" -export KIBANA_KERNEL_URI="kibana.osh-infra.svc.cluster.local/app/kibana#/discover?_g=()&_a=(columns:!(_source),index:'kernel-*',interval:auto,query:(match_all:()),sort:!('@timestamp',desc))" -export KIBANA_JOURNAL_URI="kibana.osh-infra.svc.cluster.local/app/kibana#/discover?_g=()&_a=(columns:!(_source),index:'journal-*',interval:auto,query:(match_all:()),sort:!('@timestamp',desc))" +export KIBANA_URI="kibana.osh-infra.svc.cluster.local" + +export KERNEL_QUERY="discover?_g=()&_a=(columns:!(_source),index:'kernel-*',interval:auto,query:(match_all:()),sort:!('@timestamp',desc))" +export JOURNAL_QUERY="discover?_g=()&_a=(columns:!(_source),index:'journal-*',interval:auto,query:(match_all:()),sort:!('@timestamp',desc))" +export LOGSTASH_QUERY="discover?_g=()&_a=(columns:!(_source),index:'logstash-*',interval:auto,query:(match_all:()),sort:!('@timestamp',desc))" + python tools/gate/selenium/kibanaSelenium.py diff --git a/tools/deployment/common/nagios-selenium.sh b/tools/deployment/common/nagios-selenium.sh index 04749b700..638e5b941 100755 --- a/tools/deployment/common/nagios-selenium.sh +++ b/tools/deployment/common/nagios-selenium.sh @@ -1,6 +1,12 @@ #!/bin/bash +set -xe + +export CHROMEDRIVER="${CHROMEDRIVER:="/etc/selenium/chromedriver"}" +export ARTIFACTS_DIR="${ARTIFACTS_DIR:="/tmp/artifacts/"}" + export NAGIOS_USER="nagiosadmin" export NAGIOS_PASSWORD="password" export NAGIOS_URI="nagios.osh-infra.svc.cluster.local" + python tools/gate/selenium/nagiosSelenium.py diff --git a/tools/deployment/common/prometheus-selenium.sh b/tools/deployment/common/prometheus-selenium.sh index f213696d3..eb0ad7799 100755 --- a/tools/deployment/common/prometheus-selenium.sh +++ b/tools/deployment/common/prometheus-selenium.sh @@ -1,6 +1,12 @@ #!/bin/bash +set -xe + +export CHROMEDRIVER="${CHROMEDRIVER:="/etc/selenium/chromedriver"}" +export ARTIFACTS_DIR="${ARTIFACTS_DIR:="/tmp/artifacts/"}" + export PROMETHEUS_USER="admin" export PROMETHEUS_PASSWORD="changeme" export PROMETHEUS_URI="prometheus.osh-infra.svc.cluster.local" + python tools/gate/selenium/prometheusSelenium.py diff --git a/tools/gate/selenium/grafanaSelenium.py b/tools/gate/selenium/grafanaSelenium.py index a2d9d34ce..d4af182c5 100755 --- a/tools/gate/selenium/grafanaSelenium.py +++ b/tools/gate/selenium/grafanaSelenium.py @@ -1,95 +1,90 @@ -import logging -import os +# Copyright 2019 The Openstack-Helm Authors. + +# 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. + import sys -from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC -from selenium.webdriver.chrome.options import Options +from selenium.common.exceptions import TimeoutException +from selenium.common.exceptions import NoSuchElementException +from seleniumtester import SeleniumTester -# Create logger, console handler and formatter -logger = logging.getLogger('Grafana Selenium Tests') -logger.setLevel(logging.DEBUG) -ch = logging.StreamHandler() -ch.setLevel(logging.DEBUG) -formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') +st = SeleniumTester('Grafana') -# Set the formatter and add the handler -ch.setFormatter(formatter) -logger.addHandler(ch) +username = st.get_variable('GRAFANA_USER') +password = st.get_variable('GRAFANA_PASSWORD') +grafana_uri = st.get_variable('GRAFANA_URI') +grafana_url = 'http://{}'.format(grafana_uri) -# Get Grafana admin user name -if "GRAFANA_USER" in os.environ: - grafana_user = os.environ['GRAFANA_USER'] - logger.info('Found Grafana username') -else: - logger.critical('Grafana username environment variable not set') - sys.exit(1) +try: + st.logger.info('Attempting to connect to Grafana') + st.browser.get(grafana_url) + el = WebDriverWait(st.browser, 15).until( + EC.title_contains('Grafana') + ) + st.logger.info('Connected to Grafana') +except TimeoutException: + st.logger.critical('Timed out waiting to connect to Grafana') + st.browser.quit() + sys.exit(1) -if "GRAFANA_PASSWORD" in os.environ: - grafana_password = os.environ['GRAFANA_PASSWORD'] - logger.info('Found Grafana password') -else: - logger.critical('Grafana password environment variable not set') - sys.exit(1) +try: + st.logger.info('Attempting to login to Grafana') + st.browser.find_element_by_name('username').send_keys(username) + st.browser.find_element_by_name('password').send_keys(password) + st.browser.find_element_by_css_selector( + 'body > grafana-app > div.main-view > div > div:nth-child(1) > div > ' + 'div > div.login-inner-box > form > div.login-button-group > button' + ).click() + st.logger.info("Successfully logged in to Grafana") +except NoSuchElementException: + st.logger.error("Failed to log in to Grafana") + st.browser.quit() + sys.exit(1) -if "GRAFANA_URI" in os.environ: - grafana_uri = os.environ['GRAFANA_URI'] - logger.info('Found Grafana URI') -else: - logger.critical('Grafana URI environment variable not set') - sys.exit(1) +try: + st.logger.info('Attempting to visit Nodes dashboard') + st.click_link_by_name('Home') + st.click_link_by_name('Nodes') + el = WebDriverWait(st.browser, 15).until( + EC.presence_of_element_located( + (By.XPATH, '/html/body/grafana-app/div[2]/div/div[1]/div/div/' + 'div[1]/dashboard-grid/div/div[1]/div/plugin-component/' + 'panel-plugin-graph/grafana-panel/div/div[2]') + ) + ) + st.take_screenshot('Grafana Nodes') +except TimeoutException: + st.logger.error('Failed to load Nodes dashboard') + st.browser.quit() + sys.exit(1) -options = Options() -options.add_argument('--headless') -options.add_argument('--no-sandbox') -options.add_argument('--window-size=1920x1080') +try: + st.logger.info('Attempting to visit Cluster Status dashboard') + st.click_link_by_name('Nodes') + st.click_link_by_name('Kubernetes Cluster Status') + el = WebDriverWait(st.browser, 15).until( + EC.presence_of_element_located( + (By.XPATH, '/html/body/grafana-app/div[2]/div/div[1]/div/' + 'div/div[1]/dashboard-grid/div/div[5]/div/plugin-component/' + 'panel-plugin-singlestat/grafana-panel/div') + ) + ) + st.take_screenshot('Grafana Cluster Status') +except TimeoutException: + st.logger.error('Failed to load Cluster Status dashboard') + st.browser.quit() + sys.exit(1) -browser = webdriver.Chrome('/etc/selenium/chromedriver', chrome_options=options) - -browser.get(grafana_uri) -username = browser.find_element_by_name('username') -username.send_keys(grafana_user) - -password = browser.find_element_by_name('password') -password.send_keys(grafana_password) - -login = browser.find_element_by_css_selector('body > grafana-app > div.main-view > div > div:nth-child(1) > div > div > div.login-inner-box > form > div.login-button-group > button') -login.click() - -el = WebDriverWait(browser, 15).until( - EC.presence_of_element_located((By.LINK_TEXT, 'Home')) -) - -homeBtn = browser.find_element_by_link_text('Home') -homeBtn.click() - - -el = WebDriverWait(browser, 15).until( - EC.presence_of_element_located((By.LINK_TEXT, 'Nodes')) -) - -nodeBtn = browser.find_element_by_link_text('Nodes') -nodeBtn.click() - -el = WebDriverWait(browser, 15).until( - EC.presence_of_element_located((By.XPATH, '/html/body/grafana-app/div[2]/div/div[1]/div/div/div[1]/dashboard-grid/div/div[1]/div/plugin-component/panel-plugin-graph/grafana-panel/div/div[2]')) -) - -browser.save_screenshot('/tmp/artifacts/Grafana_Nodes.png') - -nodeBtn = browser.find_element_by_link_text('Nodes') -nodeBtn.click() - -el = WebDriverWait(browser, 15).until( - EC.presence_of_element_located((By.LINK_TEXT, 'Kubernetes Cluster Status')) -) - -healthBtn = browser.find_element_by_link_text('Kubernetes Cluster Status') -healthBtn.click() - -el = WebDriverWait(browser, 15).until( - EC.presence_of_element_located((By.XPATH, '/html/body/grafana-app/div[2]/div/div[1]/div/div/div[1]/dashboard-grid/div/div[5]/div/plugin-component/panel-plugin-singlestat/grafana-panel/div')) -) - -browser.save_screenshot('/tmp/artifacts/Grafana_ClusterStatus.png') +st.browser.quit() diff --git a/tools/gate/selenium/kibanaSelenium.py b/tools/gate/selenium/kibanaSelenium.py index 308845323..78aa595f0 100644 --- a/tools/gate/selenium/kibanaSelenium.py +++ b/tools/gate/selenium/kibanaSelenium.py @@ -1,74 +1,79 @@ -import logging -import os +# Copyright 2019 The Openstack-Helm Authors. + +# 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. + import sys -from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC -from selenium.webdriver.chrome.options import Options from selenium.common.exceptions import TimeoutException +from seleniumtester import SeleniumTester -logger = logging.getLogger('Kibana Selenium Tests') -logger.setLevel(logging.DEBUG) -ch = logging.StreamHandler() -ch.setLevel(logging.DEBUG) -formatter = logging.Formatter( - '%(asctime)s - %(name)s - %(levelname)s - %(message)s') +st = SeleniumTester('Kibana') -ch.setFormatter(formatter) -logger.addHandler(ch) +username = st.get_variable('KIBANA_USER') +password = st.get_variable('KIBANA_PASSWORD') +kibana_uri = st.get_variable('KIBANA_URI') +kibana_url = 'http://{0}:{1}@{2}'.format(username, password, kibana_uri) -artifacts = '/tmp/artifacts/' -if not os.path.exists(artifacts): - os.makedirs(artifacts) +try: + st.logger.info('Attempting to connect to Kibana') + st.browser.get(kibana_url) + el = WebDriverWait(st.browser, 45).until( + EC.title_contains('Kibana') + ) + st.logger.info('Connected to Kibana') +except TimeoutException: + st.logger.critical('Timed out waiting for Kibana') + st.browser.quit() + sys.exit(1) +kernel_query = st.get_variable('KERNEL_QUERY') +journal_query = st.get_variable('JOURNAL_QUERY') +logstash_query = st.get_variable('LOGSTASH_QUERY') -def get_variable(env_var): - if env_var in os.environ: - logger.info('Found "{}"'.format(env_var)) - return os.environ[env_var] - else: - logger.critical('Variable "{}" is not defined!'.format(env_var)) - sys.exit(1) +queries = [(kernel_query, 'Kernel'), + (journal_query, 'Journal'), + (logstash_query, 'Logstash')] - -kibana_user = get_variable('KIBANA_USER') -kibana_password = get_variable('KIBANA_PASSWORD') -kibana_journal_uri = get_variable('KIBANA_JOURNAL_URI') -kibana_kernel_uri = get_variable('KIBANA_KERNEL_URI') -kibana_logstash_uri = get_variable('KIBANA_LOGSTASH_URI') - -options = Options() -options.add_argument('--headless') -options.add_argument('--no-sandbox') -options.add_argument('--window-size=1920x1080') - -targets = [(kibana_kernel_uri, 'Kernel'), - (kibana_journal_uri, 'Journal'), - (kibana_logstash_uri, 'Logstash')] - -for target, name in targets: +for query, name in queries: retry = 3 while retry > 0: - prefix = '' - browser = webdriver.Chrome( - '/etc/selenium/chromedriver', chrome_options=options) - url = "http://{0}:{1}@{2}".format(kibana_user, kibana_password, target) - browser.get(url) + query_url = '{}/app/kibana#/{}'.format(kibana_url, query) try: - WebDriverWait(browser, 60).until( + st.logger.info('Attempting to query {} index'.format(name)) + st.browser.get(query_url) + WebDriverWait(st.browser, 60).until( EC.presence_of_element_located( (By.XPATH, '//*[@id="kibana-body"]/div[1]/div/div/div[3]/' - 'discover-app/div/div[2]/div[2]/div/div[2]/div[2]/' - 'doc-table/div/table/tbody/tr[1]/td[2]')) + 'discover-app/div/div[2]/div[2]/div/div[2]/div[2]/' + 'doc-table/div/table/tbody/tr[1]/td[2]') + ) ) - logger.info('{} index loaded successfully'.format(name)) + st.logger.info('{} index loaded successfully'.format(name)) + st.take_screenshot('Kibana {} Index'.format(name)) retry = 0 + except TimeoutException: - logger.error('Error occured loading {} index'.format(name)) - prefix = 'Error_' - browser.save_screenshot( - artifacts + '{}Kibana_{}.png'.format(prefix, name)) - browser.quit() + if retry > 1: + st.logger.warning('Timed out loading {} index'.format(name)) + else: + st.logger.error('Could not load {} index'.format(name)) + retry -= 1 + if retry <= 0: + # Reset test condition + st.browser.get(kibana_url) + +st.browser.quit() diff --git a/tools/gate/selenium/nagiosSelenium.py b/tools/gate/selenium/nagiosSelenium.py index 3457bccd4..4d44c9573 100755 --- a/tools/gate/selenium/nagiosSelenium.py +++ b/tools/gate/selenium/nagiosSelenium.py @@ -1,70 +1,76 @@ -import os -import logging +# Copyright 2019 The Openstack-Helm Authors. + +# 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. + import sys -from selenium import webdriver -from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC -from selenium.webdriver.chrome.options import Options +from selenium.common.exceptions import TimeoutException +from selenium.common.exceptions import NoSuchElementException +from seleniumtester import SeleniumTester +st = SeleniumTester('Nagios') -# Create logger, console handler and formatter -logger = logging.getLogger('Nagios Selenium Tests') -logger.setLevel(logging.DEBUG) -ch = logging.StreamHandler() -ch.setLevel(logging.DEBUG) -formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') +username = st.get_variable('NAGIOS_USER') +password = st.get_variable('NAGIOS_PASSWORD') +nagios_uri = st.get_variable('NAGIOS_URI') +nagios_url = 'http://{0}:{1}@{2}'.format(username, password, nagios_uri) -# Set the formatter and add the handler -ch.setFormatter(formatter) -logger.addHandler(ch) +try: + st.logger.info('Attempting to connect to Nagios') + st.browser.get(nagios_url) + el = WebDriverWait(st.browser, 15).until( + EC.title_contains('Nagios') + ) + st.logger.info('Connected to Nagios') +except TimeoutException: + st.logger.critical('Timed out waiting for Nagios') + st.browser.quit() + sys.exit(1) -# Get Grafana admin user name -if "NAGIOS_USER" in os.environ: - nagios_user = os.environ['NAGIOS_USER'] - logger.info('Found Nagios username') -else: - logger.critical('Nagios username environment variable not set') - sys.exit(1) +try: + st.logger.info('Switching Focus to Navigation side frame') + sideFrame = st.browser.switch_to.frame('side') +except NoSuchElementException: + st.logger.error('Failed selecting side frame') + st.browser.quit() + sys.exit(1) -if "NAGIOS_PASSWORD" in os.environ: - nagios_password = os.environ['NAGIOS_PASSWORD'] - logger.info('Found Nagios password') -else: - logger.critical('Nagios password environment variable not set') - sys.exit(1) +try: + st.logger.info('Attempting to visit Services page') + st.click_link_by_name('Services') + st.take_screenshot('Nagios Services') +except TimeoutException: + st.logger.error('Failed to load Services page') + st.browser.quit() + sys.exit(1) -if "NAGIOS_URI" in os.environ: - nagios_uri = os.environ['NAGIOS_URI'] - logger.info('Found Nagios URI') -else: - logger.critical('Nagios URI environment variable not set') - sys.exit(1) +try: + st.logger.info('Attempting to visit Host Groups page') + st.click_link_by_name('Host Groups') + st.take_screenshot('Nagios Host Groups') +except TimeoutException: + st.logger.error('Failed to load Host Groups page') + st.browser.quit() + sys.exit(1) -options = Options() -options.add_argument('--headless') -options.add_argument('--no-sandbox') -options.add_argument('--window-size=1920x1080') +try: + st.logger.info('Attempting to visit Hosts page') + st.click_link_by_name('Hosts') + st.take_screenshot('Nagios Hosts') +except TimeoutException: + st.logger.error('Failed to load Hosts page') + st.browser.quit() + sys.exit(1) -browser = webdriver.Chrome('/etc/selenium/chromedriver', chrome_options=options) -browser.get('http://'+nagios_user+':'+nagios_password+'@'+nagios_uri) - -sideFrame = browser.switch_to.frame('side') - -services = browser.find_element_by_link_text('Services') -services.click() - -el = WebDriverWait(browser, 15) -browser.save_screenshot('/tmp/artifacts/Nagios_Services.png') - -hostGroups = browser.find_element_by_link_text('Host Groups') -hostGroups.click() - -el = WebDriverWait(browser, 15) -browser.save_screenshot('/tmp/artifacts/Nagios_HostGroups.png') - -hosts = browser.find_element_by_link_text('Hosts') -hosts.click() - -el = WebDriverWait(browser, 15) -browser.save_screenshot('/tmp/artifacts/Nagios_Hosts.png') +st.browser.quit() diff --git a/tools/gate/selenium/prometheusSelenium.py b/tools/gate/selenium/prometheusSelenium.py index 71e3ef473..cb552dc54 100755 --- a/tools/gate/selenium/prometheusSelenium.py +++ b/tools/gate/selenium/prometheusSelenium.py @@ -1,79 +1,68 @@ -import os -import logging +# Copyright 2019 The Openstack-Helm Authors. + +# 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. + import sys -from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC -from selenium.webdriver.chrome.options import Options +from selenium.common.exceptions import TimeoutException +from seleniumtester import SeleniumTester -# Create logger, console handler and formatter -logger = logging.getLogger('Prometheus Selenium Tests') -logger.setLevel(logging.DEBUG) -ch = logging.StreamHandler() -ch.setLevel(logging.DEBUG) -formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') +st = SeleniumTester('Prometheus') -# Set the formatter and add the handler -ch.setFormatter(formatter) -logger.addHandler(ch) +username = st.get_variable('PROMETHEUS_USER') +password = st.get_variable('PROMETHEUS_PASSWORD') +prometheus_uri = st.get_variable('PROMETHEUS_URI') +prometheus_url = 'http://{}:{}@{}'.format(username, password, prometheus_uri) -# Get Grafana admin user name -if "PROMETHEUS_USER" in os.environ: - prometheus_user = os.environ['PROMETHEUS_USER'] - logger.info('Found Prometheus username') -else: - logger.critical('Prometheus username environment variable not set') - sys.exit(1) +try: + st.logger.info('Attempting to connect to Prometheus') + st.browser.get(prometheus_url) + el = WebDriverWait(st.browser, 15).until( + EC.title_contains('Prometheus') + ) + st.logger.info('Connected to Prometheus') + st.take_screenshot('Prometheus Dashboard') +except TimeoutException: + st.logger.critical('Timed out waiting for Prometheus') + st.browser.quit() + sys.exit(1) -if "PROMETHEUS_PASSWORD" in os.environ: - prometheus_password = os.environ['PROMETHEUS_PASSWORD'] - logger.info('Found Prometheus password') -else: - logger.critical('Prometheus password environment variable not set') - sys.exit(1) +try: + st.logger.info('Attempting to view Runtime Information') + st.click_link_by_name('Status') + st.click_link_by_name('Runtime & Build Information') + el = WebDriverWait(st.browser, 15).until( + EC.presence_of_element_located((By.XPATH, '/html/body/div/table[1]')) + ) + st.take_screenshot('Prometheus Runtime Info') +except TimeoutException: + st.logger.error('Failed to load Runtime Information page') + st.browser.quit() + sys.exit(1) -if "PROMETHEUS_URI" in os.environ: - prometheus_uri = os.environ['PROMETHEUS_URI'] - logger.info('Found Prometheus URI') -else: - logger.critical('Prometheus URI environment variable not set') - sys.exit(1) +try: + st.logger.info('Attempting to view Runtime Information') + st.click_link_by_name('Status') + st.click_link_by_name('Command-Line Flags') + el = WebDriverWait(st.browser, 15).until( + EC.presence_of_element_located((By.XPATH, '/html/body/div/table')) + ) + st.take_screenshot('Prometheus Command Line Flags') +except TimeoutException: + st.logger.error('Failed to load Command Line Flags page') + st.browser.quit() + sys.exit(1) -options = Options() -options.add_argument('--headless') -options.add_argument('--no-sandbox') -options.add_argument('--window-size=1920x1080') - -browser = webdriver.Chrome('/etc/selenium/chromedriver', chrome_options=options) - -browser.get("http://"+prometheus_user+":"+prometheus_password+"@"+prometheus_uri) - -el = WebDriverWait(browser, 15).until( - EC.presence_of_element_located((By.NAME, 'submit')) -) - -browser.save_screenshot('/tmp/artifacts/Prometheus_Dash.png') - - -statusBtn = browser.find_element_by_link_text('Status') -statusBtn.click() - -browser.find_element_by_link_text('Runtime & Build Information').click() - -el = WebDriverWait(browser, 15).until( - EC.presence_of_element_located((By.XPATH, '/html/body/div/table[1]')) -) - -browser.save_screenshot('/tmp/artifacts/Prometheus_RuntimeInfo.png') - -statusBtn = browser.find_element_by_link_text('Status') -statusBtn.click() - -browser.find_element_by_link_text('Command-Line Flags').click() - -el = WebDriverWait(browser, 15).until( - EC.presence_of_element_located((By.XPATH, '/html/body/div/table')) -) - -browser.save_screenshot('/tmp/artifacts/Prometheus_CommandLineFlags.png') +st.browser.quit() diff --git a/tools/gate/selenium/seleniumtester.py b/tools/gate/selenium/seleniumtester.py new file mode 100644 index 000000000..7d18d6f4c --- /dev/null +++ b/tools/gate/selenium/seleniumtester.py @@ -0,0 +1,102 @@ +# Copyright 2019 The Openstack-Helm Authors. + +# 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. + +import os +import logging +import sys +from selenium import webdriver +from selenium.webdriver.common.by import By +from selenium.webdriver.support.ui import WebDriverWait +from selenium.webdriver.support import expected_conditions as EC +from selenium.webdriver.chrome.options import Options +from selenium.common.exceptions import TimeoutException +from selenium.common.exceptions import NoSuchElementException +from selenium.common.exceptions import ScreenshotException + +class SeleniumTester(): + def __init__(self, name): + self.logger = self.get_logger(name) + self.chrome_driver = self.get_variable('CHROMEDRIVER') + self.artifacts_dir = self.get_variable('ARTIFACTS_DIR') + self.initialize_artifiacts_dir() + self.browser = self.get_browser() + + def get_logger(self, name): + logger = logging.getLogger('{} Selenium Tests'.format(name)) + logger.setLevel(logging.DEBUG) + ch = logging.StreamHandler() + ch.setLevel(logging.DEBUG) + formatter = logging.Formatter( + '%(asctime)s - %(name)s - %(levelname)s - %(message)s' + ) + + # Set the formatter and add the handler + ch.setFormatter(formatter) + logger.addHandler(ch) + return logger + + def get_variable(self, env_var): + if env_var in os.environ: + self.logger.info('Found "{}"'.format(env_var)) + return os.environ[env_var] + else: + self.logger.critical( + 'Variable "{}" is not defined!'.format(env_var) + ) + sys.exit(1) + + def get_browser(self): + options = Options() + options.add_argument('--headless') + options.add_argument('--no-sandbox') + options.add_argument('--window-size=1920x1080') + browser = webdriver.Chrome(self.chrome_driver, chrome_options=options) + return browser + + def initialize_artifiacts_dir(self): + if self.artifacts_dir and not os.path.exists(self.artifacts_dir): + os.makedirs(self.artifacts_dir) + self.logger.info( + 'Created {} for test artifacts'.format(self.artifacts_dir) + ) + + def click_link_by_name(self, link_name): + try: + el = WebDriverWait(self.browser, 15).until( + EC.presence_of_element_located((By.LINK_TEXT, link_name)) + ) + self.logger.info("Clicking '{}' link".format(link_name)) + link = self.browser.find_element_by_link_text(link_name) + link.click() + except (TimeoutException, NoSuchElementException): + self.logger.error("Failed clicking '{}' link".format(link_name)) + self.browser.quit() + sys.exit(1) + + def take_screenshot(self, page_name): + file_name = page_name.replace(' ', '_') + try: + el = WebDriverWait(self.browser, 15) + self.browser.save_screenshot( + '{}{}.png'.format(self.artifacts_dir, file_name) + ) + self.logger.info( + "Successfully captured {} screenshot".format(page_name) + ) + except ScreenshotException: + self.logger.error( + "Failed to capture {} screenshot".format(page_name) + ) + self.browser.quit() + sys.exit(1)