Fix horizon dashboard
Port the python2.7 local settings overrides to the python3.6 directory structure. Move all local_settings.py overrides into _05_snap_tweaks.py as part of troubleshooting some remaining problems. Everything is more organized and functional now :-) Added selenium tests. Change-Id: I54923e1dc9c7ffa47c2ef6fb90ea9d224b0d2eee
This commit is contained in:
parent
30f09c0c9a
commit
0b4c7a22a3
@ -1,4 +1,4 @@
|
||||
#!/usr/bin/env python2
|
||||
#!/usr/bin/env python3
|
||||
import os
|
||||
import sys
|
||||
|
||||
|
@ -1,22 +0,0 @@
|
||||
# Tweaks to make this run nicely in a snap.
|
||||
|
||||
# We don't want django to try writing the secret key before we've told
|
||||
# it not to attempt to write it out in the read only snap dir in our
|
||||
# local_settings.py. So we override the behavior of the default
|
||||
# settings.py here.
|
||||
SECRET_KEY = "overridethis!"
|
||||
|
||||
# Django wants to write out compressed files even when we turn
|
||||
# compression off (either a bug or something that I'm not
|
||||
# understanding). Tell it to write them some place writeable.
|
||||
STATIC_ROOT = '/var/snap/microstack/common/var/horizon/static'
|
||||
|
||||
# Disable extra themes for now. TODO: Re-enable when
|
||||
# https://github.com/CanonicalLtd/microstack/issues/39 is
|
||||
# addressed. (You'll need to uncomment the material theme below when testing
|
||||
# the fix.)
|
||||
AVAILABLE_THEMES = [
|
||||
('default', 'Default', 'themes/default'),
|
||||
# ('material', 'Material', 'themes/material'),
|
||||
('ubuntu', 'Ubuntu', 'themes/ubuntu'),
|
||||
]
|
@ -0,0 +1,53 @@
|
||||
# Tweaks to make this run nicely in a snap.
|
||||
|
||||
# TODO: turn this off once everything is working nicely.
|
||||
DEBUG = True
|
||||
|
||||
# Set our webroot.
|
||||
WEBROOT = '/'
|
||||
|
||||
# Caches and such should get written out here.
|
||||
LOCAL_PATH = '/var/snap/microstack/common/etc/horizon/'
|
||||
|
||||
# We don't want django to try writing the secret key before we've told
|
||||
# it not to attempt to write it out in the read only snap dir in our
|
||||
# local_settings.py. So we override the behavior of the default
|
||||
# settings.py here.
|
||||
SECRET_KEY = secret_key.generate_or_read_from_file(
|
||||
os.path.join(LOCAL_PATH, '.secret_key_store'))
|
||||
|
||||
# Django wants to write out compressed files even when we turn
|
||||
# compression off (either a bug or something that I'm not
|
||||
# understanding). Tell it to write them some place writeable.
|
||||
STATIC_ROOT = '/var/snap/microstack/common/var/horizon/static'
|
||||
|
||||
# Disable extra themes for now. TODO: Re-enable when
|
||||
# https://github.com/CanonicalLtd/microstack/issues/39 is
|
||||
# addressed. (You'll need to uncomment the material theme below when testing
|
||||
# the fix.)
|
||||
AVAILABLE_THEMES = [
|
||||
('default', 'Default', 'themes/default'),
|
||||
# ('material', 'Material', 'themes/material'),
|
||||
('ubuntu', 'Ubuntu', 'themes/ubuntu'),
|
||||
]
|
||||
|
||||
# Point us at keystone.
|
||||
OPENSTACK_HOST = "10.20.20.1"
|
||||
OPENSTACK_KEYSTONE_URL = "http://%s:5000/v3" % OPENSTACK_HOST
|
||||
OPENSTACK_KEYSTONE_DEFAULT_ROLE = "_member_"
|
||||
|
||||
# Turn off external access for now. (This should be turned on once we
|
||||
# have hooks for setting a non default password.)
|
||||
ALLOWED_HOSTS = ['10.20.20.1', 'localhost', '127.0.0.1']
|
||||
|
||||
# Use memcached as our caching backend.
|
||||
CACHES = {
|
||||
'default': {
|
||||
#
|
||||
'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
|
||||
'LOCATION': '10.20.20.1:11211',
|
||||
}
|
||||
}
|
||||
SESSION_ENGINE='django.contrib.sessions.backends.cache'
|
||||
|
||||
|
@ -8,7 +8,7 @@ from horizon.utils import secret_key
|
||||
|
||||
from openstack_dashboard.settings import HORIZON_CONFIG
|
||||
|
||||
DEBUG = True
|
||||
DEBUG = False
|
||||
|
||||
# This setting controls whether or not compression is enabled. Disabling
|
||||
# compression makes Horizon considerably slower, but makes it much easier
|
||||
@ -26,6 +26,8 @@ DEBUG = True
|
||||
WEBROOT = '/'
|
||||
#LOGIN_URL = WEBROOT + 'auth/login/'
|
||||
#LOGOUT_URL = WEBROOT + 'auth/logout/'
|
||||
#LOGIN_ERROR = WEBROOT + 'auth/error/'
|
||||
|
||||
#
|
||||
# LOGIN_REDIRECT_URL can be used as an alternative for
|
||||
# HORIZON_CONFIG.user_home, if user_home is not set.
|
||||
@ -36,7 +38,7 @@ WEBROOT = '/'
|
||||
# with the list of host/domain names that the application can serve.
|
||||
# For more information see:
|
||||
# https://docs.djangoproject.com/en/dev/ref/settings/#allowed-hosts
|
||||
ALLOWED_HOSTS = ['10.20.20.1', 'localhost']
|
||||
#ALLOWED_HOSTS = '*'
|
||||
|
||||
# Set SSL proxy settings:
|
||||
# Pass this header from the proxy after terminating the SSL,
|
||||
@ -63,10 +65,9 @@ ALLOWED_HOSTS = ['10.20.20.1', 'localhost']
|
||||
# use of the decimal point, so valid options would be 2.0 or 3.
|
||||
# Minimum compute version to get the instance locked status is 2.9.
|
||||
#OPENSTACK_API_VERSIONS = {
|
||||
# "data-processing": 1.1,
|
||||
# "identity": 3,
|
||||
# "image": 2,
|
||||
# "volume": 2,
|
||||
# "volume": 3,
|
||||
# "compute": 2,
|
||||
#}
|
||||
|
||||
@ -111,7 +112,15 @@ ALLOWED_HOSTS = ['10.20.20.1', 'localhost']
|
||||
# Toggle showing the openrc file for Keystone V2.
|
||||
# If set to false the link will be removed from the user dropdown menu
|
||||
# and the API Access page
|
||||
#SHOW_KEYSTONE_V2_RC = True
|
||||
#SHOW_KEYSTONE_V2_RC = False
|
||||
|
||||
# Controls whether the keystone openrc file is accesible from the user
|
||||
# menu and the api access panel.
|
||||
SHOW_OPENRC_FILE = True
|
||||
|
||||
# Controls whether clouds.yaml is accesible from the user
|
||||
# menu and the api access panel.
|
||||
SHOW_OPENSTACK_CLOUDS_YAML = True
|
||||
|
||||
# If provided, a "Report Bug" link will be displayed in the site header
|
||||
# which links to the value of this setting (ideally a URL containing
|
||||
@ -137,7 +146,6 @@ ALLOWED_HOSTS = ['10.20.20.1', 'localhost']
|
||||
#HORIZON_CONFIG["disable_password_reveal"] = False
|
||||
|
||||
#LOCAL_PATH = os.path.dirname(os.path.abspath(__file__))
|
||||
LOCAL_PATH = '/var/snap/microstack/common/etc/horizon/'
|
||||
|
||||
# Set custom secret key:
|
||||
# You can either set it to a specific value or you can let horizon generate a
|
||||
@ -148,24 +156,24 @@ LOCAL_PATH = '/var/snap/microstack/common/etc/horizon/'
|
||||
# (usually behind a load-balancer). Either you have to make sure that a session
|
||||
# gets all requests routed to the same dashboard instance or you set the same
|
||||
# SECRET_KEY for all of them.
|
||||
SECRET_KEY = secret_key.generate_or_read_from_file(
|
||||
os.path.join(LOCAL_PATH, '.secret_key_store'))
|
||||
#SECRET_KEY = secret_key.generate_or_read_from_file(
|
||||
# os.path.join(LOCAL_PATH, '.secret_key_store'))
|
||||
|
||||
# We recommend you use memcached for development; otherwise after every reload
|
||||
# of the django development server, you will have to login again. To use
|
||||
# memcached set CACHES to something like
|
||||
# memcached set CACHES to something like below.
|
||||
# For more information, see
|
||||
# https://docs.djangoproject.com/en/1.11/topics/http/sessions/.
|
||||
#CACHES = {
|
||||
# 'default': {
|
||||
# 'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
|
||||
# 'LOCATION': '127.0.0.1:11211',
|
||||
# 'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
|
||||
# },
|
||||
#}
|
||||
|
||||
CACHES = {
|
||||
'default': {
|
||||
'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
|
||||
},
|
||||
}
|
||||
# If you use ``tox -e runserver`` for developments,then configure
|
||||
# SESSION_ENGINE to django.contrib.sessions.backends.signed_cookies
|
||||
# as shown below:
|
||||
#SESSION_ENGINE = 'django.contrib.sessions.backends.signed_cookies'
|
||||
|
||||
# Send email to the console by default
|
||||
EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'
|
||||
@ -232,6 +240,21 @@ OPENSTACK_KEYSTONE_DEFAULT_ROLE = "_member_"
|
||||
# "acme_saml2": ("acme", "saml2"),
|
||||
#}
|
||||
|
||||
# Enables redirection on login to the identity provider defined on
|
||||
# WEBSSO_DEFAULT_REDIRECT_PROTOCOL and WEBSSO_DEFAULT_REDIRECT_REGION
|
||||
#WEBSSO_DEFAULT_REDIRECT = False
|
||||
|
||||
# Specifies the protocol to use for default redirection on login
|
||||
#WEBSSO_DEFAULT_REDIRECT_PROTOCOL = None
|
||||
|
||||
# Specifies the region to which the connection will be established on login
|
||||
#WEBSSO_DEFAULT_REDIRECT_REGION = OPENSTACK_KEYSTONE_URL
|
||||
|
||||
# Enables redirection on logout to the method specified on the identity provider.
|
||||
# Once logout the client will be redirected to the address specified in this
|
||||
# variable.
|
||||
#WEBSSO_DEFAULT_REDIRECT_LOGOUT = None
|
||||
|
||||
# If set this URL will be used for web single-sign-on authentication
|
||||
# instead of OPENSTACK_KEYSTONE_URL. This is needed in the deployment
|
||||
# scenarios where network segmentation is used per security requirement.
|
||||
@ -523,6 +546,7 @@ TIME_ZONE = "UTC"
|
||||
#AVAILABLE_THEMES = [
|
||||
# ('default', 'Default', 'themes/default'),
|
||||
# ('material', 'Material', 'themes/material'),
|
||||
# ('example', 'Example', 'themes/example'),
|
||||
#]
|
||||
|
||||
LOGGING = {
|
||||
@ -780,12 +804,6 @@ SECURITY_GROUP_RULES = {
|
||||
# See Metadata Definitions on:
|
||||
# https://docs.openstack.org/glance/latest/user/glancemetadefcatalogapi.html
|
||||
|
||||
# The hash algorithm to use for authentication tokens. This must
|
||||
# match the hash algorithm that the identity server and the
|
||||
# auth_token middleware are using. Allowed values are the
|
||||
# algorithms supported by Python's hashlib library.
|
||||
#OPENSTACK_TOKEN_HASH_ALGORITHM = 'md5'
|
||||
|
||||
# AngularJS requires some settings to be made available to
|
||||
# the client side. Some settings are required by in-tree / built-in horizon
|
||||
# features. These settings must be added to REST_API_REQUIRED_SETTINGS in the
|
Before Width: | Height: | Size: 90 KiB After Width: | Height: | Size: 90 KiB |
Before Width: | Height: | Size: 5.1 KiB After Width: | Height: | Size: 5.1 KiB |
Before Width: | Height: | Size: 5.1 KiB After Width: | Height: | Size: 5.1 KiB |
@ -1 +1,3 @@
|
||||
petname
|
||||
selenium
|
||||
xvfbwrapper
|
||||
|
@ -161,12 +161,14 @@ done;
|
||||
|
||||
# Cleanup
|
||||
unset IP
|
||||
echo "++++++++++++++++++++++++++++++++++++++++++++++++++"
|
||||
echo "++ Completed tests. Cleaning up ++"
|
||||
echo "++++++++++++++++++++++++++++++++++++++++++++++++++"
|
||||
if [[ $PREFIX == *"multipass"* ]]; then
|
||||
echo "++++++++++++++++++++++++++++++++++++++++++++++++++"
|
||||
echo "++ Completed tests. Cleaning up ++"
|
||||
echo "++++++++++++++++++++++++++++++++++++++++++++++++++"
|
||||
sudo multipass delete $MACHINE
|
||||
sudo multipass purge
|
||||
else
|
||||
$PREFIX sudo snap remove microstack
|
||||
echo "++++++++++++++++++++++++++++++++++++++++++++++++++"
|
||||
echo "++ Completed tests. Leaving snap installed. ++"
|
||||
echo "++++++++++++++++++++++++++++++++++++++++++++++++++"
|
||||
fi
|
||||
|
47
tests/test_horizonlogin.py
Executable file
47
tests/test_horizonlogin.py
Executable file
@ -0,0 +1,47 @@
|
||||
#!/usr/bin/env python
|
||||
"""
|
||||
test_horizonlogin.py
|
||||
|
||||
This is a basic test of Horizon functionality. We verify that:
|
||||
|
||||
1) Horizon is running, and we can hit the landing page.
|
||||
2) We can login successfully.
|
||||
|
||||
This is based on code generated by the Selinum Web IDE.
|
||||
|
||||
"""
|
||||
|
||||
import os
|
||||
import socket
|
||||
import unittest
|
||||
import xvfbwrapper
|
||||
from selenium import webdriver
|
||||
from selenium.webdriver.common.by import By
|
||||
|
||||
|
||||
class TestHorizonlogin(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.display = xvfbwrapper.Xvfb(width=1280, height=720)
|
||||
self.display.start()
|
||||
self.driver = webdriver.PhantomJS()
|
||||
|
||||
def tearDown(self):
|
||||
self.driver.quit()
|
||||
self.display.stop()
|
||||
|
||||
def test_horizonlogin(self):
|
||||
self.driver.get("http://10.20.20.1/")
|
||||
# Login to horizon!
|
||||
self.driver.find_element(By.ID, "id_username").click()
|
||||
self.driver.find_element(By.ID, "id_username").send_keys("admin")
|
||||
self.driver.find_element(By.ID, "id_password").send_keys("keystone")
|
||||
self.driver.find_element(By.CSS_SELECTOR, "#loginBtn > span").click()
|
||||
# Verify that we can click something on the dashboard -- e.g.,
|
||||
# we're still not sitting at the login screen.
|
||||
self.driver.find_element(By.LINK_TEXT, "Images").click()
|
||||
|
||||
if __name__ == '__main__':
|
||||
# Run our tests, ignorning deprecation warnings and warnings about
|
||||
# unclosed sockets. (TODO: setup a selenium server so that we can
|
||||
# move from PhantomJS, which is deprecated, to to Selenium headless.)
|
||||
unittest.main(warnings='ignore')
|
@ -5,10 +5,19 @@ set -ex
|
||||
export PATH=/snap/bin:$PATH
|
||||
|
||||
sudo apt update
|
||||
sudo apt install -y snapd
|
||||
|
||||
# Install the X virtual framebuffer, which is required for selenium
|
||||
# tests of the horizon dashboard.
|
||||
sudo apt install -y xvfb npm libfontconfig1
|
||||
sudo npm install -g phantomjs-prebuilt
|
||||
# Verify that PhantomJS, our selenium web driver, works.
|
||||
phantomjs -v
|
||||
|
||||
# Setup snapd and snapcraft
|
||||
sudo apt install -y snapd
|
||||
sudo snap install --classic snapcraft
|
||||
sudo snap install --classic lxd
|
||||
sudo lxd init --auto
|
||||
|
||||
# Build our snap!
|
||||
sudo snapcraft --use-lxd
|
||||
|
19
tox.ini
19
tox.ini
@ -3,9 +3,10 @@ envlist = init_lint, init_unit, multipass
|
||||
skipsdist = True
|
||||
|
||||
[testenv]
|
||||
basepython=python3
|
||||
install_command = pip install {opts} {packages}
|
||||
setenv =
|
||||
PATH = {env:PATH}:/snap/bin
|
||||
PATH = /snap/bin:{env:PATH}
|
||||
passenv = HOME TERM
|
||||
whitelist_externals =
|
||||
sudo
|
||||
@ -15,10 +16,12 @@ whitelist_externals =
|
||||
# Testing environment for the gerrit gate. Named 'snap' to conform to
|
||||
# the requirements of the snap friendly job that we inherit from in
|
||||
# .zuul.yaml.
|
||||
basepython=python3
|
||||
deps = -r{toxinidir}/test-requirements.txt
|
||||
commands =
|
||||
{toxinidir}/tools/lxd_build.sh
|
||||
{toxinidir}/tests/basic-test.sh
|
||||
{toxinidir}/tests/test_horizonlogin.py
|
||||
|
||||
[testenv:multipass]
|
||||
# Default testing environment for a human operated machine. Builds the
|
||||
@ -28,6 +31,7 @@ commands =
|
||||
# use the "snap" environment above. Beware that you will wind up with
|
||||
# a lot of things installed, including potentially the locally built
|
||||
# version of MicroStack!
|
||||
deps = -r{toxinidir}/test-requirements.txt
|
||||
commands =
|
||||
{toxinidir}/tools/multipass_build.sh
|
||||
{toxinidir}/tests/basic-test.sh -m
|
||||
@ -37,15 +41,22 @@ commands =
|
||||
commands =
|
||||
{toxinidir}/tests/basic-test.sh -m
|
||||
|
||||
|
||||
[testenv:init_lint]
|
||||
basepython=python3
|
||||
deps = -r{toxinidir}/tools/init/test-requirements.txt
|
||||
-r{toxinidir}/tools/init/requirements.txt
|
||||
commands = flake8 {toxinidir}/tools/init/init/
|
||||
|
||||
[testenv:init_unit]
|
||||
basepython=python3
|
||||
deps = -r{toxinidir}/tools/init/test-requirements.txt
|
||||
-r{toxinidir}/tools/init/requirements.txt
|
||||
commands = stestr run {posargs}
|
||||
|
||||
[testenv:browser]
|
||||
# Run browser tests. Assumes that you have the snap installed and
|
||||
# initialized locally, and a valid DISPLAY (install xvfb for a virtual
|
||||
# one).
|
||||
# TODO: figure out how to integrate this w/ multipass. (e.g. setup
|
||||
# port forwarding and call into the mulitpass machine.)
|
||||
deps = -r{toxinidir}/test-requirements.txt
|
||||
commands =
|
||||
{toxinidir}/tests/test_horizonlogin.py
|
||||
|
Loading…
Reference in New Issue
Block a user