Removing all code from previous dashboard incarnation
Clearing out all of the old code from the Sahara dashboard repo in preparation for bringing the new code back into the repo for the Mitaka release. Change-Id: I83cb932c35987ea80ac9233bd355355398b9164b
This commit is contained in:
parent
acefa0451d
commit
01d6e53630
4
.mailmap
4
.mailmap
@ -1,4 +0,0 @@
|
||||
# Format is:
|
||||
# <preferred e-mail> <other e-mail 1>
|
||||
# <preferred e-mail> <other e-mail 2>
|
||||
Timur Nurlygayanov <tnurlygayanov@mirantis.com>
|
@ -1,7 +0,0 @@
|
||||
[DEFAULT]
|
||||
test_command=OS_STDOUT_CAPTURE=${OS_STDOUT_CAPTURE:-1} \
|
||||
OS_STDERR_CAPTURE=${OS_STDERR_CAPTURE:-1} \
|
||||
OS_TEST_TIMEOUT=${OS_TEST_TIMEOUT:-60} \
|
||||
${PYTHON:-python} -m subunit.run discover saharadashboard/tests $LISTOPT $IDOPTION
|
||||
test_id_option=--load-list $IDFILE
|
||||
test_list_option=--list
|
11
MANIFEST.in
11
MANIFEST.in
@ -1,11 +0,0 @@
|
||||
include AUTHORS
|
||||
include README.rst
|
||||
include ChangeLog
|
||||
include LICENSE
|
||||
|
||||
include saharadashboard/templates/**.html
|
||||
|
||||
exclude .gitignore
|
||||
exclude .gitreview
|
||||
|
||||
global-exclude *.pyc
|
10
README.rst
10
README.rst
@ -4,14 +4,8 @@ OpenStack Dashboard plugin for Sahara project
|
||||
NOTE:
|
||||
=====
|
||||
|
||||
Sahara Dashboard is now integrated into the Horizon project. http://github.com/openstack/horizon
|
||||
The panels can now be found in the data_processing module of Projects Dashboard.
|
||||
https://github.com/openstack/horizon/tree/master/openstack_dashboard/dashboards/project/data_processing
|
||||
|
||||
This repository will now contain only selenium based tests for the Data Processing Panels.
|
||||
|
||||
This change is not meant to be backported to stable/icehouse or any other tags or branches.
|
||||
So you can still use Sahara Dasboard as a separate dashboard with stable/icehouse version of Horizon.
|
||||
As of the Mitaka release, the dashboard for sahara is now maintained
|
||||
outside of the horzon codebase, in the repository.
|
||||
|
||||
Links:
|
||||
------
|
||||
|
23
manage.py
Executable file
23
manage.py
Executable file
@ -0,0 +1,23 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
# 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 sys
|
||||
|
||||
from django.core.management import execute_from_command_line
|
||||
|
||||
if __name__ == "__main__":
|
||||
os.environ.setdefault("DJANGO_SETTINGS_MODULE",
|
||||
"sahara-dashboard.test.settings")
|
||||
execute_from_command_line(sys.argv)
|
@ -1,4 +0,0 @@
|
||||
[DEFAULT]
|
||||
modules=importutils
|
||||
base=saharadashboard
|
||||
|
@ -3,3 +3,12 @@
|
||||
# process, which may cause wedges in the gate later.
|
||||
|
||||
pbr>=1.6
|
||||
# Horizon Core Requirements
|
||||
Babel>=1.3
|
||||
Django<1.9,>=1.8
|
||||
django-compressor>=1.4
|
||||
django-openstack-auth>=2.0.0
|
||||
iso8601>=0.1.9
|
||||
python-keystoneclient!=1.8.0,>=1.6.0
|
||||
python-manilaclient>=1.3.0
|
||||
python-saharaclient>=0.10.0
|
||||
|
548
run_tests.sh
Normal file
548
run_tests.sh
Normal file
@ -0,0 +1,548 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -o errexit
|
||||
|
||||
function usage {
|
||||
echo "Usage: $0 [OPTION]..."
|
||||
echo "Run Horizon's test suite(s)"
|
||||
echo ""
|
||||
echo " -V, --virtual-env Always use virtualenv. Install automatically"
|
||||
echo " if not present"
|
||||
echo " -N, --no-virtual-env Don't use virtualenv. Run tests in local"
|
||||
echo " environment"
|
||||
echo " -c, --coverage Generate reports using Coverage"
|
||||
echo " -f, --force Force a clean re-build of the virtual"
|
||||
echo " environment. Useful when dependencies have"
|
||||
echo " been added."
|
||||
echo " -m, --manage Run a Django management command."
|
||||
echo " --makemessages Create/Update English translation files."
|
||||
echo " --compilemessages Compile all translation files."
|
||||
echo " --check-only Do not update translation files (--makemessages only)."
|
||||
echo " --pseudo Pseudo translate a language."
|
||||
echo " -p, --pep8 Just run pep8"
|
||||
echo " -8, --pep8-changed [<basecommit>]"
|
||||
echo " Just run PEP8 and HACKING compliance check"
|
||||
echo " on files changed since HEAD~1 (or <basecommit>)"
|
||||
echo " -P, --no-pep8 Don't run pep8 by default"
|
||||
echo " -t, --tabs Check for tab characters in files."
|
||||
echo " -y, --pylint Just run pylint"
|
||||
echo " -q, --quiet Run non-interactively. (Relatively) quiet."
|
||||
echo " Implies -V if -N is not set."
|
||||
echo " --only-selenium Run only the Selenium unit tests"
|
||||
echo " --with-selenium Run unit tests including Selenium tests"
|
||||
echo " --selenium-headless Run Selenium tests headless"
|
||||
echo " --integration Run the integration tests (requires a running "
|
||||
echo " OpenStack environment)"
|
||||
echo " --runserver Run the Django development server for"
|
||||
echo " openstack_dashboard in the virtual"
|
||||
echo " environment."
|
||||
echo " --docs Just build the documentation"
|
||||
echo " --backup-environment Make a backup of the environment on exit"
|
||||
echo " --restore-environment Restore the environment before running"
|
||||
echo " --destroy-environment Destroy the environment and exit"
|
||||
echo " -h, --help Print this usage message"
|
||||
echo ""
|
||||
echo "Note: with no options specified, the script will try to run the tests in"
|
||||
echo " a virtual environment, If no virtualenv is found, the script will ask"
|
||||
echo " if you would like to create one. If you prefer to run tests NOT in a"
|
||||
echo " virtual environment, simply pass the -N option."
|
||||
exit
|
||||
}
|
||||
|
||||
# DEFAULTS FOR RUN_TESTS.SH
|
||||
#
|
||||
root=`pwd -P`
|
||||
venv=$root/.venv
|
||||
venv_env_version=$venv/environments
|
||||
with_venv=tools/with_venv.sh
|
||||
included_dirs="sahara-dashboard"
|
||||
|
||||
always_venv=0
|
||||
backup_env=0
|
||||
command_wrapper=""
|
||||
destroy=0
|
||||
force=0
|
||||
just_pep8=0
|
||||
just_pep8_changed=0
|
||||
no_pep8=0
|
||||
just_pylint=0
|
||||
just_docs=0
|
||||
just_tabs=0
|
||||
never_venv=0
|
||||
quiet=0
|
||||
restore_env=0
|
||||
runserver=0
|
||||
only_selenium=0
|
||||
with_selenium=0
|
||||
selenium_headless=0
|
||||
integration=0
|
||||
testopts=""
|
||||
testargs=""
|
||||
with_coverage=0
|
||||
makemessages=0
|
||||
compilemessages=0
|
||||
check_only=0
|
||||
pseudo=0
|
||||
manage=0
|
||||
|
||||
# Jenkins sets a "JOB_NAME" variable, if it's not set, we'll make it "default"
|
||||
[ "$JOB_NAME" ] || JOB_NAME="default"
|
||||
|
||||
function process_option {
|
||||
# If running manage command, treat the rest of options as arguments.
|
||||
if [ $manage -eq 1 ]; then
|
||||
testargs="$testargs $1"
|
||||
return 0
|
||||
fi
|
||||
|
||||
case "$1" in
|
||||
-h|--help) usage;;
|
||||
-V|--virtual-env) always_venv=1; never_venv=0;;
|
||||
-N|--no-virtual-env) always_venv=0; never_venv=1;;
|
||||
-p|--pep8) just_pep8=1;;
|
||||
-8|--pep8-changed) just_pep8_changed=1;;
|
||||
-P|--no-pep8) no_pep8=1;;
|
||||
-y|--pylint) just_pylint=1;;
|
||||
-f|--force) force=1;;
|
||||
-t|--tabs) just_tabs=1;;
|
||||
-q|--quiet) quiet=1;;
|
||||
-c|--coverage) with_coverage=1;;
|
||||
-m|--manage) manage=1;;
|
||||
--makemessages) makemessages=1;;
|
||||
--compilemessages) compilemessages=1;;
|
||||
--check-only) check_only=1;;
|
||||
--pseudo) pseudo=1;;
|
||||
--only-selenium) only_selenium=1;;
|
||||
--with-selenium) with_selenium=1;;
|
||||
--selenium-headless) selenium_headless=1;;
|
||||
--integration) integration=1;;
|
||||
--docs) just_docs=1;;
|
||||
--runserver) runserver=1;;
|
||||
--backup-environment) backup_env=1;;
|
||||
--restore-environment) restore_env=1;;
|
||||
--destroy-environment) destroy=1;;
|
||||
-*) testopts="$testopts $1";;
|
||||
*) testargs="$testargs $1"
|
||||
esac
|
||||
}
|
||||
|
||||
function run_management_command {
|
||||
${command_wrapper} python $root/manage.py $testopts $testargs
|
||||
}
|
||||
|
||||
function run_server {
|
||||
echo "Starting Django development server..."
|
||||
${command_wrapper} python $root/manage.py runserver $testopts $testargs
|
||||
echo "Server stopped."
|
||||
}
|
||||
|
||||
function run_pylint {
|
||||
echo "Running pylint ..."
|
||||
PYTHONPATH=$root ${command_wrapper} pylint --rcfile=.pylintrc -f parseable $included_dirs > pylint.txt || true
|
||||
CODE=$?
|
||||
grep Global -A2 pylint.txt
|
||||
if [ $CODE -lt 32 ]; then
|
||||
echo "Completed successfully."
|
||||
exit 0
|
||||
else
|
||||
echo "Completed with problems."
|
||||
exit $CODE
|
||||
fi
|
||||
}
|
||||
|
||||
function warn_on_flake8_without_venv {
|
||||
set +o errexit
|
||||
${command_wrapper} python -c "import hacking" 2>/dev/null
|
||||
no_hacking=$?
|
||||
set -o errexit
|
||||
if [ $never_venv -eq 1 -a $no_hacking -eq 1 ]; then
|
||||
echo "**WARNING**:" >&2
|
||||
echo "OpenStack hacking is not installed on your host. Its detection will be missed." >&2
|
||||
echo "Please install or use virtual env if you need OpenStack hacking detection." >&2
|
||||
fi
|
||||
}
|
||||
|
||||
function run_pep8 {
|
||||
echo "Running flake8 ..."
|
||||
warn_on_flake8_without_venv
|
||||
DJANGO_SETTINGS_MODULE=sahara-dashboard.test.settings ${command_wrapper} flake8
|
||||
}
|
||||
|
||||
function run_pep8_changed {
|
||||
# NOTE(gilliard) We want use flake8 to check the entirety of every file that has
|
||||
# a change in it. Unfortunately the --filenames argument to flake8 only accepts
|
||||
# file *names* and there are no files named (eg) "nova/compute/manager.py". The
|
||||
# --diff argument behaves surprisingly as well, because although you feed it a
|
||||
# diff, it actually checks the file on disk anyway.
|
||||
local base_commit=${testargs:-HEAD~1}
|
||||
files=$(git diff --name-only $base_commit | tr '\n' ' ')
|
||||
echo "Running flake8 on ${files}"
|
||||
warn_on_flake8_without_venv
|
||||
diff -u --from-file /dev/null ${files} | DJANGO_SETTINGS_MODULE=sahara-dashboard.test.settings ${command_wrapper} flake8 --diff
|
||||
exit
|
||||
}
|
||||
|
||||
function run_sphinx {
|
||||
echo "Building sphinx..."
|
||||
DJANGO_SETTINGS_MODULE=sahara-dashboard.test.settings ${command_wrapper} python setup.py build_sphinx
|
||||
echo "Build complete."
|
||||
}
|
||||
|
||||
function tab_check {
|
||||
TAB_VIOLATIONS=`find $included_dirs -type f -regex ".*\.\(css\|js\|py\|html\)" -print0 | xargs -0 awk '/\t/' | wc -l`
|
||||
if [ $TAB_VIOLATIONS -gt 0 ]; then
|
||||
echo "TABS! $TAB_VIOLATIONS of them! Oh no!"
|
||||
HORIZON_FILES=`find $included_dirs -type f -regex ".*\.\(css\|js\|py|\html\)"`
|
||||
for TABBED_FILE in $HORIZON_FILES
|
||||
do
|
||||
TAB_COUNT=`awk '/\t/' $TABBED_FILE | wc -l`
|
||||
if [ $TAB_COUNT -gt 0 ]; then
|
||||
echo "$TABBED_FILE: $TAB_COUNT"
|
||||
fi
|
||||
done
|
||||
fi
|
||||
return $TAB_VIOLATIONS;
|
||||
}
|
||||
|
||||
function destroy_venv {
|
||||
echo "Cleaning environment..."
|
||||
echo "Removing virtualenv..."
|
||||
rm -rf $venv
|
||||
echo "Virtualenv removed."
|
||||
}
|
||||
|
||||
function environment_check {
|
||||
echo "Checking environment."
|
||||
if [ -f $venv_env_version ]; then
|
||||
set +o errexit
|
||||
cat requirements.txt test-requirements.txt | cmp $venv_env_version - > /dev/null
|
||||
local env_check_result=$?
|
||||
set -o errexit
|
||||
if [ $env_check_result -eq 0 ]; then
|
||||
# If the environment exists and is up-to-date then set our variables
|
||||
command_wrapper="${root}/${with_venv}"
|
||||
echo "Environment is up to date."
|
||||
return 0
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ $always_venv -eq 1 ]; then
|
||||
install_venv
|
||||
else
|
||||
if [ ! -e ${venv} ]; then
|
||||
echo -e "Environment not found. Install? (Y/n) \c"
|
||||
else
|
||||
echo -e "Your environment appears to be out of date. Update? (Y/n) \c"
|
||||
fi
|
||||
read update_env
|
||||
if [ "x$update_env" = "xY" -o "x$update_env" = "x" -o "x$update_env" = "xy" ]; then
|
||||
install_venv
|
||||
else
|
||||
# Set our command wrapper anyway.
|
||||
command_wrapper="${root}/${with_venv}"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
function sanity_check {
|
||||
# Anything that should be determined prior to running the tests, server, etc.
|
||||
# Don't sanity-check anything environment-related in -N flag is set
|
||||
if [ $never_venv -eq 0 ]; then
|
||||
if [ ! -e ${venv} ]; then
|
||||
echo "Virtualenv not found at $venv. Did install_venv.py succeed?"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
# Remove .pyc files. This is sanity checking because they can linger
|
||||
# after old files are deleted.
|
||||
find . -name "*.pyc" -exec rm -rf {} \;
|
||||
}
|
||||
|
||||
function backup_environment {
|
||||
if [ $backup_env -eq 1 ]; then
|
||||
echo "Backing up environment \"$JOB_NAME\"..."
|
||||
if [ ! -e ${venv} ]; then
|
||||
echo "Environment not installed. Cannot back up."
|
||||
return 0
|
||||
fi
|
||||
if [ -d /tmp/.horizon_environment/$JOB_NAME ]; then
|
||||
mv /tmp/.horizon_environment/$JOB_NAME /tmp/.horizon_environment/$JOB_NAME.old
|
||||
rm -rf /tmp/.horizon_environment/$JOB_NAME
|
||||
fi
|
||||
mkdir -p /tmp/.horizon_environment/$JOB_NAME
|
||||
cp -r $venv /tmp/.horizon_environment/$JOB_NAME/
|
||||
# Remove the backup now that we've completed successfully
|
||||
rm -rf /tmp/.horizon_environment/$JOB_NAME.old
|
||||
echo "Backup completed"
|
||||
fi
|
||||
}
|
||||
|
||||
function restore_environment {
|
||||
if [ $restore_env -eq 1 ]; then
|
||||
echo "Restoring environment from backup..."
|
||||
if [ ! -d /tmp/.horizon_environment/$JOB_NAME ]; then
|
||||
echo "No backup to restore from."
|
||||
return 0
|
||||
fi
|
||||
|
||||
cp -r /tmp/.horizon_environment/$JOB_NAME/.venv ./ || true
|
||||
|
||||
echo "Environment restored successfully."
|
||||
fi
|
||||
}
|
||||
|
||||
function install_venv {
|
||||
# Install with install_venv.py
|
||||
export PIP_DOWNLOAD_CACHE=${PIP_DOWNLOAD_CACHE-/tmp/.pip_download_cache}
|
||||
export PIP_USE_MIRRORS=true
|
||||
if [ $quiet -eq 1 ]; then
|
||||
export PIP_NO_INPUT=true
|
||||
fi
|
||||
echo "Fetching new src packages..."
|
||||
rm -rf $venv/src
|
||||
python tools/install_venv.py
|
||||
command_wrapper="$root/${with_venv}"
|
||||
# Make sure it worked and record the environment version
|
||||
sanity_check
|
||||
chmod -R 754 $venv
|
||||
cat requirements.txt test-requirements.txt > $venv_env_version
|
||||
}
|
||||
|
||||
function run_tests {
|
||||
sanity_check
|
||||
|
||||
if [ $with_selenium -eq 1 ]; then
|
||||
export WITH_SELENIUM=1
|
||||
elif [ $only_selenium -eq 1 ]; then
|
||||
export WITH_SELENIUM=1
|
||||
export SKIP_UNITTESTS=1
|
||||
fi
|
||||
|
||||
if [ $selenium_headless -eq 1 ]; then
|
||||
export SELENIUM_HEADLESS=1
|
||||
fi
|
||||
|
||||
if [ -z "$testargs" ]; then
|
||||
run_tests_all
|
||||
else
|
||||
run_tests_subset
|
||||
fi
|
||||
}
|
||||
|
||||
function run_tests_subset {
|
||||
project=`echo $testargs | awk -F. '{print $1}'`
|
||||
${command_wrapper} python $root/manage.py test --settings=$project.test.settings $testopts $testargs
|
||||
}
|
||||
|
||||
function run_tests_all {
|
||||
echo "Running Sahara-Dashboard application tests"
|
||||
export NOSE_XUNIT_FILE=sahara-dashboard/nosetests.xml
|
||||
if [ "$NOSE_WITH_HTML_OUTPUT" = '1' ]; then
|
||||
export NOSE_HTML_OUT_FILE='sahara_dashboard_nose_results.html'
|
||||
fi
|
||||
if [ $with_coverage -eq 1 ]; then
|
||||
${command_wrapper} python -m coverage.__main__ erase
|
||||
coverage_run="python -m coverage.__main__ run -p"
|
||||
fi
|
||||
${command_wrapper} ${coverage_run} $root/manage.py test sahara-dashboard --settings=sahara-dashboard.test.settings $testopts
|
||||
# get results of the Horizon tests
|
||||
SAHARA_DASHBOARD_RESULT=$?
|
||||
|
||||
if [ $with_coverage -eq 1 ]; then
|
||||
echo "Generating coverage reports"
|
||||
${command_wrapper} python -m coverage.__main__ combine
|
||||
${command_wrapper} python -m coverage.__main__ xml -i --omit='/usr*,setup.py,*egg*,.venv/*'
|
||||
${command_wrapper} python -m coverage.__main__ html -i --omit='/usr*,setup.py,*egg*,.venv/*' -d reports
|
||||
fi
|
||||
# Remove the leftover coverage files from the -p flag earlier.
|
||||
rm -f .coverage.*
|
||||
|
||||
PEP8_RESULT=0
|
||||
if [ $no_pep8 -eq 0 ] && [ $only_selenium -eq 0 ]; then
|
||||
run_pep8
|
||||
PEP8_RESULT=$?
|
||||
fi
|
||||
|
||||
TEST_RESULT=$(($SAHARA_DASHBOARD_RESULT || $PEP8_RESULT))
|
||||
if [ $TEST_RESULT -eq 0 ]; then
|
||||
echo "Tests completed successfully."
|
||||
else
|
||||
echo "Tests failed."
|
||||
fi
|
||||
exit $TEST_RESULT
|
||||
}
|
||||
|
||||
function run_integration_tests {
|
||||
export INTEGRATION_TESTS=1
|
||||
|
||||
if [ $selenium_headless -eq 1 ]; then
|
||||
export SELENIUM_HEADLESS=1
|
||||
fi
|
||||
|
||||
echo "Running Horizon integration tests..."
|
||||
if [ -z "$testargs" ]; then
|
||||
${command_wrapper} nosetests openstack_dashboard/test/integration_tests/tests
|
||||
else
|
||||
${command_wrapper} nosetests $testargs
|
||||
fi
|
||||
exit 0
|
||||
}
|
||||
|
||||
function run_makemessages {
|
||||
OPTS="-l en --no-obsolete --settings=openstack_dashboard.test.settings"
|
||||
DASHBOARD_OPTS="--extension=html,txt,csv --ignore=openstack"
|
||||
echo -n "horizon: "
|
||||
cd horizon
|
||||
${command_wrapper} $root/manage.py makemessages $OPTS
|
||||
HORIZON_PY_RESULT=$?
|
||||
echo -n "horizon javascript: "
|
||||
${command_wrapper} $root/manage.py makemessages -d djangojs $OPTS
|
||||
HORIZON_JS_RESULT=$?
|
||||
echo -n "openstack_dashboard: "
|
||||
cd ../openstack_dashboard
|
||||
${command_wrapper} $root/manage.py makemessages $DASHBOARD_OPTS $OPTS
|
||||
DASHBOARD_RESULT=$?
|
||||
cd ..
|
||||
if [ $check_only -eq 1 ]; then
|
||||
git checkout -- horizon/locale/en/LC_MESSAGES/django*.po
|
||||
git checkout -- openstack_dashboard/locale/en/LC_MESSAGES/django.po
|
||||
fi
|
||||
exit $(($HORIZON_PY_RESULT || $HORIZON_JS_RESULT || $DASHBOARD_RESULT))
|
||||
}
|
||||
|
||||
function run_compilemessages {
|
||||
OPTS="--settings=openstack_dashboard.test.settings"
|
||||
cd horizon
|
||||
${command_wrapper} $root/manage.py compilemessages $OPTS
|
||||
HORIZON_PY_RESULT=$?
|
||||
cd ../openstack_dashboard
|
||||
${command_wrapper} $root/manage.py compilemessages $OPTS
|
||||
DASHBOARD_RESULT=$?
|
||||
cd ..
|
||||
# English is the source language, so compiled catalogs are unnecessary.
|
||||
rm -vf horizon/locale/en/LC_MESSAGES/django*.mo
|
||||
rm -vf openstack_dashboard/locale/en/LC_MESSAGES/django.mo
|
||||
exit $(($HORIZON_PY_RESULT || $DASHBOARD_RESULT))
|
||||
}
|
||||
|
||||
function run_pseudo {
|
||||
for lang in $testargs
|
||||
# Use English po file as the source file/pot file just like real Horizon translations
|
||||
do
|
||||
${command_wrapper} $root/tools/pseudo.py openstack_dashboard/locale/en/LC_MESSAGES/django.po openstack_dashboard/locale/$lang/LC_MESSAGES/django.po $lang
|
||||
${command_wrapper} $root/tools/pseudo.py horizon/locale/en/LC_MESSAGES/django.po horizon/locale/$lang/LC_MESSAGES/django.po $lang
|
||||
${command_wrapper} $root/tools/pseudo.py horizon/locale/en/LC_MESSAGES/djangojs.po horizon/locale/$lang/LC_MESSAGES/djangojs.po $lang
|
||||
done
|
||||
exit $?
|
||||
}
|
||||
|
||||
|
||||
# ---------PREPARE THE ENVIRONMENT------------ #
|
||||
|
||||
# PROCESS ARGUMENTS, OVERRIDE DEFAULTS
|
||||
for arg in "$@"; do
|
||||
process_option $arg
|
||||
done
|
||||
|
||||
if [ $quiet -eq 1 ] && [ $never_venv -eq 0 ] && [ $always_venv -eq 0 ]
|
||||
then
|
||||
always_venv=1
|
||||
fi
|
||||
|
||||
# If destroy is set, just blow it away and exit.
|
||||
if [ $destroy -eq 1 ]; then
|
||||
destroy_venv
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Ignore all of this if the -N flag was set
|
||||
if [ $never_venv -eq 0 ]; then
|
||||
|
||||
# Restore previous environment if desired
|
||||
if [ $restore_env -eq 1 ]; then
|
||||
restore_environment
|
||||
fi
|
||||
|
||||
# Remove the virtual environment if --force used
|
||||
if [ $force -eq 1 ]; then
|
||||
destroy_venv
|
||||
fi
|
||||
|
||||
# Then check if it's up-to-date
|
||||
environment_check
|
||||
|
||||
# Create a backup of the up-to-date environment if desired
|
||||
if [ $backup_env -eq 1 ]; then
|
||||
backup_environment
|
||||
fi
|
||||
fi
|
||||
|
||||
# ---------EXERCISE THE CODE------------ #
|
||||
|
||||
# Run management commands
|
||||
if [ $manage -eq 1 ]; then
|
||||
run_management_command
|
||||
exit $?
|
||||
fi
|
||||
|
||||
# Build the docs
|
||||
if [ $just_docs -eq 1 ]; then
|
||||
run_sphinx
|
||||
exit $?
|
||||
fi
|
||||
|
||||
# Update translation files
|
||||
if [ $makemessages -eq 1 ]; then
|
||||
run_makemessages
|
||||
exit $?
|
||||
fi
|
||||
|
||||
# Compile translation files
|
||||
if [ $compilemessages -eq 1 ]; then
|
||||
run_compilemessages
|
||||
exit $?
|
||||
fi
|
||||
|
||||
# Generate Pseudo translation
|
||||
if [ $pseudo -eq 1 ]; then
|
||||
run_pseudo
|
||||
exit $?
|
||||
fi
|
||||
|
||||
# PEP8
|
||||
if [ $just_pep8 -eq 1 ]; then
|
||||
run_pep8
|
||||
exit $?
|
||||
fi
|
||||
|
||||
if [ $just_pep8_changed -eq 1 ]; then
|
||||
run_pep8_changed
|
||||
exit $?
|
||||
fi
|
||||
|
||||
# Pylint
|
||||
if [ $just_pylint -eq 1 ]; then
|
||||
run_pylint
|
||||
exit $?
|
||||
fi
|
||||
|
||||
# Tab checker
|
||||
if [ $just_tabs -eq 1 ]; then
|
||||
tab_check
|
||||
exit $?
|
||||
fi
|
||||
|
||||
# Integration tests
|
||||
if [ $integration -eq 1 ]; then
|
||||
run_integration_tests
|
||||
exit $?
|
||||
fi
|
||||
|
||||
# Django development server
|
||||
if [ $runserver -eq 1 ]; then
|
||||
run_server
|
||||
exit $?
|
||||
fi
|
||||
|
||||
# Full test suite
|
||||
run_tests || exit
|
185
sahara-dashboard/test/settings.py
Normal file
185
sahara-dashboard/test/settings.py
Normal file
@ -0,0 +1,185 @@
|
||||
#
|
||||
# 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 importlib
|
||||
import os
|
||||
import six
|
||||
|
||||
from horizon.test.settings import * # noqa
|
||||
from horizon.utils import secret_key
|
||||
from openstack_dashboard import exceptions
|
||||
|
||||
|
||||
DEBUG = True
|
||||
TEMPLATE_DEBUG = DEBUG
|
||||
|
||||
TEST_DIR = os.path.dirname(os.path.abspath(__file__))
|
||||
ROOT_PATH = os.path.abspath(os.path.join(TEST_DIR, ".."))
|
||||
|
||||
MEDIA_ROOT = os.path.abspath(os.path.join(ROOT_PATH, '..', 'media'))
|
||||
MEDIA_URL = '/media/'
|
||||
STATIC_ROOT = os.path.abspath(os.path.join(ROOT_PATH, '..', 'static'))
|
||||
STATIC_URL = '/static/'
|
||||
|
||||
SECRET_KEY = secret_key.generate_or_read_from_file(
|
||||
os.path.join(TEST_DIR, '.secret_key_store'))
|
||||
ROOT_URLCONF = 'sahara-dashboard.test.urls'
|
||||
TEMPLATE_DIRS = (
|
||||
os.path.join(TEST_DIR, 'templates'),
|
||||
)
|
||||
|
||||
TEMPLATE_CONTEXT_PROCESSORS += (
|
||||
'openstack_dashboard.context_processors.openstack',
|
||||
)
|
||||
|
||||
INSTALLED_APPS = (
|
||||
'django.contrib.contenttypes',
|
||||
'django.contrib.auth',
|
||||
'django.contrib.sessions',
|
||||
'django.contrib.staticfiles',
|
||||
'django.contrib.messages',
|
||||
'django.contrib.humanize',
|
||||
'django_nose',
|
||||
'openstack_auth',
|
||||
'compressor',
|
||||
'horizon',
|
||||
'openstack_dashboard',
|
||||
'openstack_dashboard.dashboards',
|
||||
)
|
||||
|
||||
AUTHENTICATION_BACKENDS = ('openstack_auth.backend.KeystoneBackend',)
|
||||
|
||||
SITE_BRANDING = 'OpenStack'
|
||||
|
||||
HORIZON_CONFIG = {
|
||||
"password_validator": {
|
||||
"regex": '^.{8,18}$',
|
||||
"help_text": "Password must be between 8 and 18 characters."
|
||||
},
|
||||
'user_home': None,
|
||||
'help_url': "http://docs.openstack.org",
|
||||
'exceptions': {'recoverable': exceptions.RECOVERABLE,
|
||||
'not_found': exceptions.NOT_FOUND,
|
||||
'unauthorized': exceptions.UNAUTHORIZED},
|
||||
'angular_modules': [],
|
||||
'js_files': [],
|
||||
}
|
||||
|
||||
# Load the pluggable dashboard settings
|
||||
from openstack_dashboard.utils import settings
|
||||
dashboard_module_names = [
|
||||
'openstack_dashboard.enabled',
|
||||
'openstack_dashboard.local.enabled',
|
||||
'sahara-dashboard.enabled',
|
||||
]
|
||||
dashboard_modules = []
|
||||
# All dashboards must be enabled for the namespace to get registered, which is
|
||||
# needed by the unit tests.
|
||||
for module_name in dashboard_module_names:
|
||||
module = importlib.import_module(module_name)
|
||||
dashboard_modules.append(module)
|
||||
for submodule in six.itervalues(settings.import_submodules(module)):
|
||||
if getattr(submodule, 'DISABLED', None):
|
||||
delattr(submodule, 'DISABLED')
|
||||
INSTALLED_APPS = list(INSTALLED_APPS) # Make sure it's mutable
|
||||
settings.update_dashboards(dashboard_modules, HORIZON_CONFIG, INSTALLED_APPS)
|
||||
|
||||
# Set to True to allow users to upload images to glance via Horizon server.
|
||||
# When enabled, a file form field will appear on the create image form.
|
||||
# See documentation for deployment considerations.
|
||||
HORIZON_IMAGES_ALLOW_UPLOAD = True
|
||||
|
||||
AVAILABLE_REGIONS = [
|
||||
('http://localhost:5000/v2.0', 'local'),
|
||||
('http://remote:5000/v2.0', 'remote'),
|
||||
]
|
||||
|
||||
OPENSTACK_API_VERSIONS = {
|
||||
"identity": 3
|
||||
}
|
||||
|
||||
OPENSTACK_KEYSTONE_URL = "http://localhost:5000/v2.0"
|
||||
OPENSTACK_KEYSTONE_DEFAULT_ROLE = "_member_"
|
||||
|
||||
OPENSTACK_KEYSTONE_MULTIDOMAIN_SUPPORT = True
|
||||
OPENSTACK_KEYSTONE_DEFAULT_DOMAIN = 'test_domain'
|
||||
|
||||
OPENSTACK_KEYSTONE_BACKEND = {
|
||||
'name': 'native',
|
||||
'can_edit_user': True,
|
||||
'can_edit_group': True,
|
||||
'can_edit_project': True,
|
||||
'can_edit_domain': True,
|
||||
'can_edit_role': True
|
||||
}
|
||||
|
||||
OPENSTACK_CINDER_FEATURES = {
|
||||
'enable_backup': True,
|
||||
}
|
||||
|
||||
OPENSTACK_NEUTRON_NETWORK = {
|
||||
'enable_lb': True
|
||||
}
|
||||
|
||||
OPENSTACK_HYPERVISOR_FEATURES = {
|
||||
'can_set_mount_point': True,
|
||||
|
||||
# NOTE: as of Grizzly this is not yet supported in Nova so enabling this
|
||||
# setting will not do anything useful
|
||||
'can_encrypt_volumes': False
|
||||
}
|
||||
|
||||
LOGGING['loggers']['openstack_dashboard'] = {
|
||||
'handlers': ['test'],
|
||||
'propagate': False,
|
||||
}
|
||||
|
||||
LOGGING['loggers']['selenium'] = {
|
||||
'handlers': ['test'],
|
||||
'propagate': False,
|
||||
}
|
||||
|
||||
LOGGING['loggers']['sahara-dashboard'] = {
|
||||
'handlers': ['test'],
|
||||
'propagate': False,
|
||||
}
|
||||
|
||||
SECURITY_GROUP_RULES = {
|
||||
'all_tcp': {
|
||||
'name': 'ALL TCP',
|
||||
'ip_protocol': 'tcp',
|
||||
'from_port': '1',
|
||||
'to_port': '65535',
|
||||
},
|
||||
'http': {
|
||||
'name': 'HTTP',
|
||||
'ip_protocol': 'tcp',
|
||||
'from_port': '80',
|
||||
'to_port': '80',
|
||||
},
|
||||
}
|
||||
|
||||
NOSE_ARGS = ['--nocapture',
|
||||
'--nologcapture',
|
||||
'--cover-package=openstack_dashboard',
|
||||
'--cover-inclusive',
|
||||
'--all-modules']
|
||||
|
||||
POLICY_FILES_PATH = os.path.join(ROOT_PATH, "conf")
|
||||
POLICY_FILES = {
|
||||
'identity': 'keystone_policy.json',
|
||||
'compute': 'nova_policy.json'
|
||||
}
|
||||
|
||||
# The openstack_auth.user.Token object isn't JSON-serializable ATM
|
||||
SESSION_SERIALIZER = 'django.contrib.sessions.serializers.PickleSerializer'
|
@ -1,54 +0,0 @@
|
||||
Sahara Dashboard Selenium Tests
|
||||
=====================================
|
||||
|
||||
|
||||
Main goal of Selenium Tests
|
||||
----------
|
||||
|
||||
Selenium tests for Sahara Dashboard are designed to check the correctness of the Sahara Dashboard Horizon plug-in.
|
||||
|
||||
|
||||
How to run UI tests:
|
||||
----------
|
||||
|
||||
It's assumed that sahara and horizon are already installed and running.
|
||||
|
||||
Information about installation and start of sahara and horizon can be found on the sahara site
|
||||
http://docs.openstack.org/developer/sahara/#user-guide
|
||||
in tabs Sahara Installation Guide and Sahara UI Installation Guide.
|
||||
|
||||
1. Go to sahara dashboard path.
|
||||
2. Create config file for selenium tests - `saharadashboard/tests/configs/config.py`.
|
||||
You can take a look at the sample config file - `saharadashboard/tests/configs/config.py.sample`.
|
||||
All values used in `saharadashboard/tests/configs/parameters.py` file are
|
||||
defaults, so, if they are applicable for your environment then you can skip
|
||||
config file creation.
|
||||
|
||||
3. Install virtual framebuffer X server for X Version 11 (Xvfb):
|
||||
sudo apt-get -y install xvfb
|
||||
|
||||
4. Install Firefox:
|
||||
sudo add-apt-repository ppa:ubuntu-mozilla-security/ppa
|
||||
sudo apt-get update
|
||||
sudo apt-get install firefox libstdc++5
|
||||
|
||||
5. To run ui tests you should use the corresponding tox env: `tox -e uitests`.
|
||||
If need to run only one test module, use:
|
||||
|
||||
tox -e uitests -- '<module_name>'
|
||||
|
||||
<module_name> may be equal 'cluster', 'cluster_template', 'image_registry', 'node_group_template', 'image_registry', 'vanilla', 'hdp'
|
||||
It's full list of actual modules.
|
||||
|
||||
|
||||
Coverage:
|
||||
----------
|
||||
|
||||
-Clusters
|
||||
-Cluster templates
|
||||
-Node group templates
|
||||
-Image registry
|
||||
-Data sources
|
||||
-Job binaries
|
||||
-Jobs
|
||||
-Job executions
|
@ -1,970 +0,0 @@
|
||||
# Copyright (c) 2013 Mirantis 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.
|
||||
|
||||
import logging
|
||||
import os
|
||||
import time
|
||||
import traceback
|
||||
|
||||
import selenium.common.exceptions as selenim_except
|
||||
from selenium import webdriver
|
||||
import selenium.webdriver.common.by as by
|
||||
from swiftclient import client as swift_client
|
||||
import unittest2
|
||||
|
||||
import saharadashboard.tests.configs.config as cfg
|
||||
|
||||
|
||||
logger = logging.getLogger('swiftclient')
|
||||
logger.setLevel(logging.WARNING)
|
||||
|
||||
|
||||
class UITestCase(unittest2.TestCase):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
try:
|
||||
cls.ifFail = False
|
||||
cls.driver = webdriver.Firefox()
|
||||
cls.driver.get(cfg.common.base_url + "/")
|
||||
cls.find_clear_send(by.By.ID, "id_username", cfg.common.user)
|
||||
cls.find_clear_send(by.By.ID, "id_password", cfg.common.password)
|
||||
cls.driver.find_element_by_xpath(
|
||||
"//button[@type='submit']").click()
|
||||
except Exception:
|
||||
traceback.print_exc()
|
||||
cls.ifFail = True
|
||||
pass
|
||||
|
||||
def setUp(self):
|
||||
if self.ifFail:
|
||||
self.fail("setUpClass method is fail")
|
||||
self.await_element(by.By.CLASS_NAME, 'clearfix',
|
||||
'authorization failed')
|
||||
|
||||
def image_registry(self, image_name, user_name=None, description=None,
|
||||
tags_to_add=None, tags_to_remove=None, positive=True,
|
||||
close_window=True, message=''):
|
||||
if positive:
|
||||
message = 'Success: Successfully updated image.'
|
||||
self.image_registry_helper(image_name, user_name, description,
|
||||
tags_to_add, tags_to_remove, positive,
|
||||
close_window, message, 'Registry')
|
||||
|
||||
def edit_tags_by_image_name(self, image_name, user_name=None,
|
||||
description=None, tags_to_add=None,
|
||||
positive=True, message=None, close_window=True,
|
||||
tags_to_remove=None):
|
||||
if positive:
|
||||
message = 'Success: Successfully updated image.'
|
||||
self.image_registry_helper(image_name, user_name, description,
|
||||
tags_to_add, tags_to_remove, positive,
|
||||
close_window, message, 'Edit')
|
||||
|
||||
def create_node_group_template(
|
||||
self, name, list_processes, plugin, flavor=None, params=None,
|
||||
storage={'type': 'Ephemeral Drive'}, description=None,
|
||||
positive=True, message=None, close_window=True):
|
||||
driver = self.driver
|
||||
if not flavor:
|
||||
flavor = cfg.common.flavor
|
||||
driver.get(cfg.common.base_url +
|
||||
"/project/data_processing/nodegroup_templates/")
|
||||
self.await_element(by.By.ID, "nodegroup_templates__action_create")
|
||||
driver.find_element_by_id("nodegroup_templates__action_create").click()
|
||||
self.choose_plugin_name(plugin.plugin_name, plugin.hadoop_version,
|
||||
name, description, "id_nodegroup_name")
|
||||
self.driver.find_element_by_xpath(
|
||||
"//select[@id='id_flavor']/option[text()='%s']" % flavor).click()
|
||||
self.driver.find_element_by_xpath(
|
||||
"//*[@id='id_storage']/option[text()='%s']"
|
||||
% storage['type']).click()
|
||||
if storage['type'] == "Cinder Volume":
|
||||
self.find_clear_send(by.By.ID, "id_volumes_per_node",
|
||||
storage['volume_per_node'])
|
||||
self.find_clear_send(by.By.ID, "id_volumes_size",
|
||||
storage['volume_size'])
|
||||
if cfg.common.floating_ip_pool:
|
||||
self.driver.find_element_by_xpath(
|
||||
"//*[@id='id_floating_ip_pool']/option[text()='%s']"
|
||||
% cfg.common.floating_ip_pool).click()
|
||||
if cfg.common.auto_security_groups != driver.find_element_by_id(
|
||||
"id_autogroup").is_selected():
|
||||
driver.find_element_by_id("id_autogroup").click()
|
||||
if cfg.common.security_groups:
|
||||
# create dictionary with existing security groups
|
||||
actual_groups = {}
|
||||
for sec_group in driver.find_elements_by_xpath(
|
||||
"//label[contains(@for, 'id_groups_')]"):
|
||||
actual_groups[sec_group.text] = sec_group
|
||||
# search specified in config file security groups of existing
|
||||
for sec_group in cfg.common.security_groups:
|
||||
if sec_group not in actual_groups:
|
||||
self.fail("Security group with name %s not "
|
||||
"found. Aborting." % sec_group)
|
||||
if not actual_groups[sec_group].is_selected():
|
||||
actual_groups[sec_group].click()
|
||||
processes = []
|
||||
for process in list_processes:
|
||||
number_pr = self.search_id_processes(process, plugin)
|
||||
driver.find_element_by_id(
|
||||
"id_processes_%s" % str(number_pr)).click()
|
||||
processes.append(driver.find_element_by_id(
|
||||
"id_processes_%s" % str(number_pr)).
|
||||
find_element_by_xpath('..').text)
|
||||
if params:
|
||||
self.config_helper(params)
|
||||
self.click_visible_key("//input[@value='Create']")
|
||||
if not message:
|
||||
message = "Success: Created Node Group Template %s" % name
|
||||
if close_window:
|
||||
self.check_create_object(
|
||||
name, positive, message,
|
||||
[{2: [name]},
|
||||
{3: [plugin.plugin_overview_name]},
|
||||
{4: [plugin.hadoop_version]}, {5: processes}])
|
||||
else:
|
||||
self.error_helper(message)
|
||||
|
||||
def create_cluster_template(
|
||||
self, name, node_groups, plugin, description=None,
|
||||
close_window=True, anti_affinity_groups=None, positive=True,
|
||||
message=None, params=None):
|
||||
driver = self.driver
|
||||
driver.get(cfg.common.base_url +
|
||||
"/project/data_processing/cluster_templates/")
|
||||
self.await_element(by.By.ID, "cluster_templates__action_create")
|
||||
driver.find_element_by_id("cluster_templates__action_create").click()
|
||||
self.choose_plugin_name(plugin.plugin_name, plugin.hadoop_version,
|
||||
name, description, "id_cluster_template_name")
|
||||
if anti_affinity_groups:
|
||||
for group in anti_affinity_groups:
|
||||
driver.find_element_by_id(
|
||||
"id_anti_affinity_%s" % self.search_id_processes(
|
||||
group, plugin)).click()
|
||||
driver.find_element_by_link_text("Node Groups").click()
|
||||
number_to_add = 0
|
||||
node_groups_list = []
|
||||
for node_group, count in node_groups.items():
|
||||
driver.find_element_by_xpath(
|
||||
"//select[@id='template_id']/option[text()='%s']"
|
||||
% node_group).click()
|
||||
driver.find_element_by_id("add_group_button").click()
|
||||
self.find_clear_send(by.By.ID, "count_%d" % number_to_add, count)
|
||||
node_groups_list.append("%s: %d" % (node_group, count))
|
||||
number_to_add += 1
|
||||
if params:
|
||||
self.config_helper(params)
|
||||
self.click_visible_key("//input[@value='Create']")
|
||||
if not message:
|
||||
message = "Success: Created Cluster Template %s" % name
|
||||
if close_window:
|
||||
self.check_create_object(
|
||||
name, positive, message,
|
||||
[{2: [name]},
|
||||
{3: [plugin.plugin_overview_name]},
|
||||
{4: [plugin.hadoop_version]}, {5: node_groups_list},
|
||||
{6: [description if description else '']}])
|
||||
else:
|
||||
self.error_helper(message)
|
||||
|
||||
def create_cluster(self, name, cluster_template, plugin, keypair=None,
|
||||
close_window=True, description=None, positive=True,
|
||||
await_run=True, message=None):
|
||||
driver = self.driver
|
||||
driver.get(cfg.common.base_url + "/project/data_processing/clusters/")
|
||||
self.await_element(by.By.ID, "clusters__action_create")
|
||||
driver.find_element_by_id("clusters__action_create").click()
|
||||
self.choose_plugin_name(plugin.plugin_name, plugin.hadoop_version,
|
||||
name, description, "id_cluster_name")
|
||||
driver.find_element_by_xpath("//select[@id='id_cluster_template']/"
|
||||
"option[text()='%s']" %
|
||||
cluster_template).click()
|
||||
driver.find_element_by_xpath("//select[@id='id_image']/option"
|
||||
"[text()='%s']" %
|
||||
plugin.base_image).click()
|
||||
if not keypair:
|
||||
keypair = cfg.common.keypair
|
||||
driver.find_element_by_xpath("//select[@id='id_keypair']"
|
||||
"/option[text()='%s']" % keypair).click()
|
||||
if cfg.common.neutron_management_network:
|
||||
driver.find_element_by_xpath(
|
||||
"//select[@id='id_neutron_management_network']/option[text()="
|
||||
"'%s']" % cfg.common.neutron_management_network).click()
|
||||
self.click_visible_key("//input[@value='Create']")
|
||||
if not message:
|
||||
message = 'Success: Created Cluster %s' % name
|
||||
if close_window:
|
||||
self.check_create_object(name, positive, message)
|
||||
else:
|
||||
self.error_helper(message)
|
||||
if await_run:
|
||||
self.await_cluster_active(name)
|
||||
|
||||
def create_data_source(self, name, url, close_window=True,
|
||||
description=None, positive=True, message=None):
|
||||
|
||||
driver = self.driver
|
||||
driver.get(cfg.common.base_url +
|
||||
"/project/data_processing/data_sources/")
|
||||
self.await_element(by.By.ID, "data_sources__action_create data source")
|
||||
driver.find_element_by_id(
|
||||
"data_sources__action_create data source").click()
|
||||
|
||||
self.await_element(by.By.ID, "id_data_source_name")
|
||||
|
||||
self.find_clear_send(by.By.ID, "id_data_source_name", name)
|
||||
self.find_clear_send(by.By.ID, "id_data_source_url", url)
|
||||
self.find_clear_send(by.By.ID, "id_data_source_credential_user",
|
||||
cfg.common.user)
|
||||
self.find_clear_send(by.By.ID, "id_data_source_credential_pass",
|
||||
cfg.common.password)
|
||||
if description:
|
||||
self.find_clear_send(by.By.ID, "id_data_source_description",
|
||||
description)
|
||||
|
||||
driver.find_element_by_xpath("//input[@value='Create']").click()
|
||||
|
||||
if not message:
|
||||
message = 'Success: Data source created'
|
||||
if close_window:
|
||||
self.check_create_object(name, positive, message)
|
||||
else:
|
||||
self.error_helper(message)
|
||||
|
||||
def create_job_binary(self, name, parameters_of_storage, description=None,
|
||||
positive=True, message=None, close_window=True):
|
||||
|
||||
driver = self.driver
|
||||
storage_type = parameters_of_storage['storage_type']
|
||||
driver.get(cfg.common.base_url +
|
||||
"/project/data_processing/job_binaries/")
|
||||
self.await_element(by.By.ID, "job_binaries__action_create job binary")
|
||||
driver.find_element_by_id(
|
||||
"job_binaries__action_create job binary").click()
|
||||
|
||||
self.await_element(by.By.ID, "id_job_binary_name")
|
||||
|
||||
self.find_clear_send(by.By.ID, "id_job_binary_name", name)
|
||||
driver.find_element_by_xpath("//select[@id='id_job_binary_type']/optio"
|
||||
"n[text()='%s']" % storage_type).click()
|
||||
|
||||
if storage_type == 'Swift':
|
||||
self.find_clear_send(by.By.ID, "id_job_binary_url",
|
||||
parameters_of_storage['url'])
|
||||
self.find_clear_send(by.By.ID, "id_job_binary_username",
|
||||
cfg.common.user)
|
||||
self.find_clear_send(by.By.ID, "id_job_binary_password",
|
||||
cfg.common.password)
|
||||
|
||||
elif storage_type == 'Internal database':
|
||||
internal_binary = parameters_of_storage['Internal binary']
|
||||
driver.find_element_by_xpath(
|
||||
"//select[@id='id_job_binary_internal']/option[text()"
|
||||
"='%s']" % internal_binary).click()
|
||||
if internal_binary == '*Upload a new file':
|
||||
file = '%s/saharadashboard/tests/resources/%s' % (
|
||||
os.getcwd(), parameters_of_storage['filename'])
|
||||
driver.find_element_by_id('id_job_binary_file').send_keys(file)
|
||||
|
||||
elif internal_binary == '*Create a script':
|
||||
self.find_clear_send(by.By.ID, "id_job_binary_script_name",
|
||||
parameters_of_storage['script_name'])
|
||||
self.find_clear_send(by.By.ID, "id_job_binary_script",
|
||||
parameters_of_storage['script_text'])
|
||||
|
||||
if description:
|
||||
self.find_clear_send(by.By.ID, "id_job_binary_description",
|
||||
description)
|
||||
|
||||
driver.find_element_by_xpath("//input[@value='Create']").click()
|
||||
|
||||
if not message:
|
||||
message = 'Success: Successfully created job binary'
|
||||
if close_window:
|
||||
self.check_create_object(name, positive, message)
|
||||
else:
|
||||
self.error_helper(message)
|
||||
|
||||
def create_job(self, name, job_type, main=None, libs=None,
|
||||
close_window=True, description=None, positive=True,
|
||||
message=None):
|
||||
|
||||
driver = self.driver
|
||||
driver.get(cfg.common.base_url + "/project/data_processing/jobs/")
|
||||
self.await_element(by.By.ID, "jobs__action_create job")
|
||||
driver.find_element_by_id("jobs__action_create job").click()
|
||||
|
||||
self.await_element(by.By.ID, "id_job_name")
|
||||
self.find_clear_send(by.By.ID, "id_job_name", name)
|
||||
driver.find_element_by_xpath(
|
||||
"//select[@id='id_job_type']/option[text()='%s']"
|
||||
% job_type).click()
|
||||
if main:
|
||||
driver.find_element_by_xpath(
|
||||
"//select[@id='id_main_binary']/option[text()='%s']"
|
||||
% main).click()
|
||||
if description:
|
||||
self.find_clear_send(by.By.ID, "id_job_description", description)
|
||||
if libs:
|
||||
driver.find_element_by_link_text('Libs').click()
|
||||
self.await_element(by.By.ID, "id_lib_binaries")
|
||||
for lib in libs:
|
||||
driver.find_element_by_xpath(
|
||||
"//select[@id='id_lib_binaries']/option[text()='%s']"
|
||||
% lib).click()
|
||||
driver.find_element_by_id('add_lib_button').click()
|
||||
|
||||
driver.find_element_by_xpath("//input[@value='Create']").click()
|
||||
|
||||
if not message:
|
||||
message = 'Success: Job created'
|
||||
if close_window:
|
||||
self.check_create_object(name, positive, message)
|
||||
else:
|
||||
self.error_helper(message)
|
||||
|
||||
def launch_job_on_existing_cluster(self, name, input, output, cluster,
|
||||
configure=None, positive=True,
|
||||
message=None, close_window=True,
|
||||
await_launch=True):
|
||||
|
||||
driver = self.driver
|
||||
driver.get(cfg.common.base_url + "/project/data_processing/jobs/")
|
||||
self.await_element(by.By.ID, "jobs__action_create job")
|
||||
|
||||
action_column = driver.find_element_by_link_text(
|
||||
name).find_element_by_xpath('../../td[4]')
|
||||
action_column.find_element_by_class_name('dropdown-toggle').click()
|
||||
action_column.find_element_by_link_text(
|
||||
'Launch On Existing Cluster').click()
|
||||
|
||||
self.await_element(by.By.ID, "id_job_input")
|
||||
driver.find_element_by_xpath(
|
||||
"//select[@id='id_job_input']/option[text()='%s']" % input).click()
|
||||
driver.find_element_by_xpath(
|
||||
"//select[@id='id_job_output']/option[text()='%s']" %
|
||||
output).click()
|
||||
driver.find_element_by_xpath(
|
||||
"//select[@id='id_cluster']/option[text()='%s']" % cluster).click()
|
||||
|
||||
if configure:
|
||||
driver.find_element_by_link_text('Configure').click()
|
||||
for config_part, values in configure.items():
|
||||
config_number = 1
|
||||
for config, value in values.items():
|
||||
driver.find_element_by_id(
|
||||
config_part).find_element_by_link_text('Add').click()
|
||||
driver.find_element_by_xpath(
|
||||
'//*[@id="%s"]/table/tbody/tr[%i]/td[1]/input' % (
|
||||
config_part, config_number)).send_keys(config)
|
||||
driver.find_element_by_xpath(
|
||||
'//*[@id="%s"]/table/tbody/tr[%i]/td[2]/input' % (
|
||||
config_part, config_number)).send_keys(value)
|
||||
config_number += 1
|
||||
|
||||
driver.find_element_by_xpath("//input[@value='Launch']").click()
|
||||
|
||||
if not message:
|
||||
message = 'Success: Job launched'
|
||||
if close_window:
|
||||
self.check_create_object(name, positive, message,
|
||||
check_create_element=False)
|
||||
if await_launch:
|
||||
self.await_launch_job(name)
|
||||
|
||||
else:
|
||||
self.error_helper(message)
|
||||
|
||||
def delete_node_group_templates(self, names, undelete_names=None,
|
||||
finally_delete=False):
|
||||
url = "/project/data_processing/nodegroup_templates/"
|
||||
delete_button_id = 'nodegroup_templates__action_' \
|
||||
'delete_nodegroup_template'
|
||||
self.delete_and_validate(url, delete_button_id, names, undelete_names,
|
||||
finally_delete)
|
||||
|
||||
def delete_cluster_templates(self, names, undelete_names=None,
|
||||
finally_delete=False):
|
||||
url = "/project/data_processing/cluster_templates/"
|
||||
delete_button_id = "cluster_templates__action_delete_cluster_template"
|
||||
self.delete_and_validate(url, delete_button_id, names, undelete_names,
|
||||
finally_delete)
|
||||
|
||||
def delete_clusters(self, names, undelete_names=None,
|
||||
finally_delete=False, await_delete=False):
|
||||
url = "/project/data_processing/clusters/"
|
||||
delete_button_id = "clusters__action_delete"
|
||||
msg = "Success: Deleted Cluster"
|
||||
self.delete_and_validate(url, delete_button_id, names, undelete_names,
|
||||
finally_delete, succes_msg=msg,
|
||||
await_delete=await_delete)
|
||||
|
||||
def delete_data_sources(self, names, undelete_names=None,
|
||||
finally_delete=False):
|
||||
url = "/project/data_processing/data_sources/"
|
||||
delete_button_id = "data_sources__action_delete"
|
||||
msg = "Success: Deleted Data source"
|
||||
err_msg = 'Error: Unable to delete data source'
|
||||
info_msg = 'Info: Deleted Data source'
|
||||
self.delete_and_validate(url, delete_button_id, names, undelete_names,
|
||||
finally_delete, msg, err_msg, info_msg)
|
||||
|
||||
def delete_job_binaries(self, names, undelete_names=None,
|
||||
finally_delete=False):
|
||||
|
||||
url = "/project/data_processing/job_binaries/"
|
||||
delete_button_id = "job_binaries__action_delete"
|
||||
|
||||
msg = "Success: Deleted Job binary"
|
||||
err_msg = 'Error: Unable to delete job binary'
|
||||
info_msg = 'Info: Deleted Job binary'
|
||||
|
||||
if not undelete_names and len(names) > 1:
|
||||
msg = "Success: Deleted Job binarie"
|
||||
|
||||
if undelete_names and len(names) - len(undelete_names) > 1:
|
||||
info_msg = 'Info: Deleted Job binarie'
|
||||
|
||||
if undelete_names and len(undelete_names) > 1:
|
||||
err_msg = 'Error: Unable to delete job binarie'
|
||||
|
||||
self.delete_and_validate(url, delete_button_id, names, undelete_names,
|
||||
finally_delete, msg, err_msg, info_msg)
|
||||
|
||||
def delete_jobs(self, names, undelete_names=None, finally_delete=False):
|
||||
url = "/project/data_processing/jobs/"
|
||||
delete_button_id = "jobs__action_delete"
|
||||
msg = "Success: Deleted Job"
|
||||
err_msg = 'Error: Unable to delete job'
|
||||
info_msg = 'Info: Deleted Job'
|
||||
self.delete_and_validate(url, delete_button_id, names, undelete_names,
|
||||
finally_delete, msg, err_msg, info_msg)
|
||||
|
||||
def delete_job_executions(self, names, undelete_names=None,
|
||||
finally_delete=False, await_delete=False):
|
||||
url = "/project/data_processing/job_executions/"
|
||||
delete_button_id = 'job_executions__action_delete'
|
||||
msg = "Success: Deleted Job execution"
|
||||
err_msg = "Error: Unable to delete job execution"
|
||||
info_msg = "Info: Deleted Job execution"
|
||||
self.delete_and_validate(url, delete_button_id, names, undelete_names,
|
||||
finally_delete, msg, err_msg, info_msg,
|
||||
await_delete)
|
||||
|
||||
def unregister_images(self, names, undelete_names=None,
|
||||
finally_delete=False):
|
||||
url = '/project/data_processing/data_image_registry/'
|
||||
delete_button_id = "image_registry__action_Unregister"
|
||||
msg = "Success: Unregistered Image"
|
||||
self.delete_and_validate(url, delete_button_id, names, undelete_names,
|
||||
finally_delete, succes_msg=msg,)
|
||||
|
||||
# -------------------------helpers_methods-------------------------------------
|
||||
|
||||
@staticmethod
|
||||
def connect_to_swift():
|
||||
return swift_client.Connection(
|
||||
authurl=cfg.common.keystone_url,
|
||||
user=cfg.common.user,
|
||||
key=cfg.common.password,
|
||||
tenant_name=cfg.common.tenant,
|
||||
auth_version=2
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def delete_swift_container(swift, container):
|
||||
|
||||
try:
|
||||
objects = [obj['name'] for obj
|
||||
in swift.get_container(container)[1]]
|
||||
except Exception:
|
||||
return
|
||||
|
||||
for obj in objects:
|
||||
|
||||
swift.delete_object(container, obj)
|
||||
|
||||
try:
|
||||
swift.delete_container(container)
|
||||
except Exception:
|
||||
return
|
||||
|
||||
@classmethod
|
||||
def find_clear_send(cls, by_find, find_element, send):
|
||||
cls.driver.find_element(by=by_find, value=find_element).clear()
|
||||
cls.driver.find_element(by=by_find, value=find_element).send_keys(send)
|
||||
|
||||
def click_visible_key(self, xpath):
|
||||
keys = self.driver.find_elements_by_xpath(xpath)
|
||||
for key in keys:
|
||||
if key.is_displayed():
|
||||
key.click()
|
||||
|
||||
def delete_and_validate(self, url, delete_button_id, names, undelete_names,
|
||||
finally_delete,
|
||||
succes_msg='Success: Deleted Template',
|
||||
error_msg='Error: Unable to delete template',
|
||||
info_msg='Info: Deleted Template',
|
||||
await_delete=False,):
|
||||
driver = self.driver
|
||||
driver.refresh()
|
||||
driver.get(cfg.common.base_url + url)
|
||||
|
||||
if finally_delete:
|
||||
try:
|
||||
self.await_element(by.By.ID, delete_button_id, await_count=3)
|
||||
except selenim_except.NoSuchElementException:
|
||||
return
|
||||
else:
|
||||
self.await_element(by.By.ID, delete_button_id)
|
||||
|
||||
for name in names:
|
||||
# choose checkbox for this element
|
||||
checkbox = None
|
||||
retry_count = 0
|
||||
while not checkbox:
|
||||
if retry_count > 10:
|
||||
self.fail("id of job execution didn't obtained")
|
||||
try:
|
||||
checkbox = driver.find_element_by_link_text(
|
||||
name).find_element_by_xpath(
|
||||
"../../td[1]/input")
|
||||
except selenim_except.StaleElementReferenceException:
|
||||
time.sleep(1)
|
||||
retry_count += 1
|
||||
except selenim_except.NoSuchElementException:
|
||||
if not finally_delete:
|
||||
print ("element with name %s not found "
|
||||
"for delete" % name)
|
||||
raise
|
||||
if not checkbox.is_selected():
|
||||
checkbox.click()
|
||||
# click deletebutton
|
||||
driver.find_element_by_id(delete_button_id).click()
|
||||
# wait window to confirm the deletion
|
||||
self.await_element(by.By.CLASS_NAME, "btn-primary")
|
||||
# confirm the deletion
|
||||
driver.find_element_by_class_name("btn-primary").click()
|
||||
if finally_delete:
|
||||
return
|
||||
exp_del_obj = list(set(names).symmetric_difference(set(
|
||||
undelete_names if undelete_names else [])))
|
||||
if not undelete_names:
|
||||
if len(names) > 1:
|
||||
succes_msg += "s"
|
||||
succes_msg += ": "
|
||||
self.check_alert("alert-success", succes_msg, names, deleted=True,
|
||||
await_delete=await_delete)
|
||||
elif not exp_del_obj:
|
||||
if len(undelete_names) > 1:
|
||||
error_msg += "s"
|
||||
error_msg += ": "
|
||||
self.check_alert("alert-danger", error_msg, undelete_names,
|
||||
deleted=False)
|
||||
else:
|
||||
if len(undelete_names) > 1:
|
||||
error_msg += "s"
|
||||
error_msg += ": "
|
||||
if len(exp_del_obj) > 1:
|
||||
info_msg += "s"
|
||||
info_msg += ": "
|
||||
self.check_alert("alert-danger", error_msg, undelete_names,
|
||||
deleted=False)
|
||||
self.check_alert("alert-info", info_msg, exp_del_obj, deleted=True,
|
||||
await_delete=await_delete)
|
||||
driver.refresh()
|
||||
|
||||
def error_helper(self, message):
|
||||
driver = self.driver
|
||||
messages = message.split(", ")
|
||||
self.await_element(by.By.CLASS_NAME, "error")
|
||||
errors = driver.find_elements_by_class_name("error")
|
||||
for message in messages:
|
||||
mes = message.split(":")
|
||||
if len(mes) > 1:
|
||||
# if word count for error mesage > 1, then error message
|
||||
# can be on the open tab or on another
|
||||
if len(mes) > 2:
|
||||
# if word count for error mesage > 2, then error message
|
||||
# on another tab
|
||||
# Click the tab indicated in the message
|
||||
driver.find_element_by_link_text(mes.pop(0)).click()
|
||||
error = errors.pop(0).text.split("\n")
|
||||
self.assertEqual(mes[0], error[0])
|
||||
self.assertEqual(mes[1], error[1])
|
||||
else:
|
||||
self.assertEqual(mes[0], errors.pop(0).text)
|
||||
self.assertEqual(errors, [])
|
||||
driver.refresh()
|
||||
|
||||
def config_helper(self, config_list):
|
||||
driver = self.driver
|
||||
for pair in config_list:
|
||||
for par, value in pair.iteritems():
|
||||
if len(par.split(":")) > 1:
|
||||
config_blog = driver.find_element_by_link_text(
|
||||
par.split(":")[0])
|
||||
config_blog.click()
|
||||
|
||||
# Find class for config blog for for unambiguous
|
||||
# finding buttons
|
||||
config_class = driver.find_element_by_id(
|
||||
config_blog.get_attribute('data-target').lstrip("#"))
|
||||
|
||||
config_id = "id_CONF:%s" % par.split(":")[0].split(" ")[0]
|
||||
if config_id == "id_CONF:General":
|
||||
config_id = "id_CONF:general"
|
||||
par = par.split(":")[1]
|
||||
if par == "Show_param":
|
||||
show_button = config_class.find_element_by_class_name(
|
||||
"full-config-show")
|
||||
hide_button = config_class.find_element_by_class_name(
|
||||
"full-config-hide")
|
||||
if value:
|
||||
self.waiting_element_in_visible_state(
|
||||
button=show_button)
|
||||
show_button.click()
|
||||
self.waiting_element_in_visible_state(
|
||||
button=hide_button)
|
||||
else:
|
||||
self.waiting_element_in_visible_state(
|
||||
button=hide_button)
|
||||
hide_button.click()
|
||||
self.waiting_element_in_visible_state(
|
||||
button=show_button)
|
||||
elif par == "Filter":
|
||||
filter_button = config_class.find_element_by_css_selector(
|
||||
"input.form-control.field-filter")
|
||||
filter_button.clear()
|
||||
filter_button.send_keys(value)
|
||||
|
||||
else:
|
||||
self.waiting_element_in_visible_state(
|
||||
by.By.ID, "%s:%s" % (config_id, par))
|
||||
if isinstance(value, bool):
|
||||
if driver.find_element_by_id(
|
||||
"%s:%s" % (config_id,
|
||||
par)).is_selected() != value:
|
||||
driver.find_element_by_id(
|
||||
"%s:%s" % (config_id, par)).click()
|
||||
else:
|
||||
self.find_clear_send(
|
||||
by.By.ID, "%s:%s" % (config_id, par), value)
|
||||
|
||||
def image_registry_helper(self, image_name, user_name, description,
|
||||
tags_to_add, tags_to_remove, positive,
|
||||
close_window, message, operation):
|
||||
driver = self.driver
|
||||
list_for_check_tags = []
|
||||
driver.get(cfg.common.base_url +
|
||||
"/project/data_processing/data_image_registry/")
|
||||
self.await_element(by.By.ID, "image_registry__action_register")
|
||||
if operation == 'Registry':
|
||||
driver.find_element_by_id(
|
||||
"image_registry__action_register").click()
|
||||
else:
|
||||
# Add existing tags in the list
|
||||
list_for_check_tags = driver.\
|
||||
find_element(by=by.By.LINK_TEXT, value=image_name).\
|
||||
find_element_by_xpath('../../td[3]').text.split('\n')
|
||||
# Click "Edit Tags"
|
||||
driver.find_element(by=by.By.LINK_TEXT, value=image_name).\
|
||||
find_element_by_xpath('../../td[4]').\
|
||||
find_element(by=by.By.LINK_TEXT, value='Edit Tags').click()
|
||||
self.await_element(by.By.ID, 'id_user_name')
|
||||
if operation == 'Registry':
|
||||
driver.find_element_by_xpath("//select[@id='id_image_id']"
|
||||
"/option[text()='%s']"
|
||||
% image_name).click()
|
||||
if user_name:
|
||||
self.find_clear_send(by.By.ID, 'id_user_name', user_name)
|
||||
if description:
|
||||
self.find_clear_send(by.By.ID, 'id_description', user_name)
|
||||
if tags_to_add:
|
||||
for tag in tags_to_add:
|
||||
for first, second in tag.iteritems():
|
||||
if first in ["vanilla", 'hdp']:
|
||||
driver.find_element_by_xpath(
|
||||
"//select[@id='plugin_select']/option[text()='%s']"
|
||||
% first).click()
|
||||
driver.find_element_by_xpath(
|
||||
"//select[@id='data_processing_version_%s']"
|
||||
"/option[text()='%s']" % (first, second)).click()
|
||||
driver.find_element_by_id('add_all_btn').click()
|
||||
if first not in list_for_check_tags:
|
||||
list_for_check_tags.append(first)
|
||||
if second not in list_for_check_tags:
|
||||
list_for_check_tags.append(second)
|
||||
elif first == 'custom_tag':
|
||||
self.find_clear_send(by.By.ID, '_sahara_image_tag',
|
||||
second)
|
||||
driver.find_element_by_id('add_tag_btn').click()
|
||||
if second not in list_for_check_tags:
|
||||
list_for_check_tags.append(second)
|
||||
else:
|
||||
self.fail("Tag:%s, %s is unknown" % (first, second))
|
||||
if tags_to_remove:
|
||||
for tag in tags_to_remove:
|
||||
# click "x" in tag
|
||||
driver.find_element_by_xpath(
|
||||
"//div[@id='image_tags_list']//span[contains(.,'%s')]//i"
|
||||
% tag).click()
|
||||
if tag in list_for_check_tags:
|
||||
list_for_check_tags.remove(tag)
|
||||
driver.find_element_by_id('edit_image_tags_btn').click()
|
||||
if positive:
|
||||
self.check_create_object(image_name, positive, message,
|
||||
[{3: list_for_check_tags}])
|
||||
else:
|
||||
if not close_window:
|
||||
self.error_helper(message)
|
||||
else:
|
||||
self.check_create_object(image_name, positive, message)
|
||||
|
||||
def choose_plugin_name(self, plugin_name, hadoop_version, name,
|
||||
description, id_name):
|
||||
self.await_element(by.By.ID, "id_plugin_name")
|
||||
self.driver.find_element_by_xpath(
|
||||
"//select[@id='id_plugin_name']/option[text()='%s']" %
|
||||
plugin_name).click()
|
||||
if plugin_name == "Hortonworks Data Platform":
|
||||
version_id = "id_hdp_version"
|
||||
elif plugin_name == "Vanilla Apache Hadoop":
|
||||
version_id = "id_vanilla_version"
|
||||
else:
|
||||
self.fail("plugin_name:%s is wrong" % plugin_name)
|
||||
self.driver.find_element_by_id(version_id).find_element_by_xpath(
|
||||
"option[text()='%s']" % hadoop_version).click()
|
||||
self.driver.find_element_by_xpath("//input[@value='Create']").click()
|
||||
self.await_element(by.By.ID, id_name)
|
||||
self.find_clear_send(by.By.ID, id_name, name)
|
||||
if description:
|
||||
self.find_clear_send(by.By.ID, "id_description", description)
|
||||
|
||||
def check_alert(self, alert, expected_message, list_obj, deleted=True,
|
||||
await_delete=False):
|
||||
self.await_element(by.By.CLASS_NAME, alert)
|
||||
actual_message = self.find_alert_message(
|
||||
alert, first_character=2, last_character=len(expected_message) + 2)
|
||||
self.assertEqual(actual_message, expected_message)
|
||||
not_expected_objs = list(set(self.find_alert_message(
|
||||
alert, first_character=len(expected_message) + 2).split(
|
||||
", ")).symmetric_difference(set(list_obj)))
|
||||
if not_expected_objs:
|
||||
self.fail("have deleted objects: %s" % not_expected_objs)
|
||||
if deleted:
|
||||
errmsg = "object with name:{} is not deleted"
|
||||
else:
|
||||
errmsg = "object with name:{} is deleted"
|
||||
for name in list_obj:
|
||||
if await_delete:
|
||||
await_count = 0
|
||||
while self.does_element_present(by.By.LINK_TEXT,
|
||||
name) == deleted:
|
||||
self.driver.refresh()
|
||||
time.sleep(5)
|
||||
await_count += 1
|
||||
if await_count > 12:
|
||||
self.fail(errmsg.format(name))
|
||||
return
|
||||
if self.does_element_present(by.By.LINK_TEXT, name) == deleted:
|
||||
self.fail(errmsg.format(name))
|
||||
delete_attempts_count = 0
|
||||
for name in list_obj:
|
||||
while self.does_element_present(by.By.LINK_TEXT, name) == deleted:
|
||||
if delete_attempts_count > cfg.common.await_element:
|
||||
if deleted:
|
||||
errmsg = "object with name:%s is not deleted" % name
|
||||
else:
|
||||
errmsg = "object with name:%s is deleted" % name
|
||||
self.fail(errmsg)
|
||||
time.sleep(1)
|
||||
delete_attempts_count += 1
|
||||
|
||||
def find_alert_message(self, name, first_character=None,
|
||||
last_character=None):
|
||||
driver = self.driver
|
||||
return str(driver.find_element_by_class_name("%s" % name).text[
|
||||
first_character:last_character])
|
||||
|
||||
def search_id_processes(self, process, plugin):
|
||||
return plugin.processes[process]
|
||||
|
||||
def waiting_element_in_visible_state(self, how=None, what=None,
|
||||
button=None):
|
||||
if not button:
|
||||
button = self.driver.find_element(by=how, value=what)
|
||||
for i in range(cfg.common.await_element):
|
||||
if button.is_displayed():
|
||||
break
|
||||
time.sleep(1)
|
||||
else:
|
||||
self.fail("time out for await visible: %s , %s" % (how, what))
|
||||
|
||||
def does_element_present(self, how, what):
|
||||
try:
|
||||
self.driver.find_element(by=how, value=what)
|
||||
except Exception as e:
|
||||
print(e.message)
|
||||
return False
|
||||
return True
|
||||
|
||||
def await_element(self, by, value, message="",
|
||||
await_count=cfg.common.await_element):
|
||||
for i in range(await_count):
|
||||
if self.does_element_present(by, value):
|
||||
break
|
||||
time.sleep(1)
|
||||
else:
|
||||
if not message:
|
||||
message = "time out for await: %s , %s" % (by, value)
|
||||
print(message)
|
||||
raise selenim_except.NoSuchElementException
|
||||
|
||||
def check_create_object(self, name, positive, expected_message,
|
||||
check_columns=None, check_create_element=True):
|
||||
driver = self.driver
|
||||
expected_alert = "alert-danger"
|
||||
unexpected_alert = "alert-success"
|
||||
if positive:
|
||||
expected_alert = "alert-success"
|
||||
unexpected_alert = "alert-danger"
|
||||
for i in range(cfg.common.await_element):
|
||||
if self.does_element_present(by.By.CLASS_NAME, expected_alert):
|
||||
break
|
||||
elif self.does_element_present(by.By.CLASS_NAME, unexpected_alert):
|
||||
fail_mesg = self.driver.find_element(
|
||||
by=by.By.CLASS_NAME, value=unexpected_alert).text[2:]
|
||||
self.fail("Result of creation %s is not expected: %s != %s"
|
||||
% (name, expected_message, fail_mesg))
|
||||
time.sleep(1)
|
||||
else:
|
||||
self.fail("alert check:%s time out" % expected_alert)
|
||||
actual_message = self.driver.find_element(
|
||||
by=by.By.CLASS_NAME, value=expected_alert).text[2:]
|
||||
if check_create_element and positive:
|
||||
self.assertEqual(expected_message, str(actual_message))
|
||||
if not self.does_element_present(by.By.LINK_TEXT, name):
|
||||
self.fail("object with name:%s not found" % name)
|
||||
if check_columns:
|
||||
for column in check_columns:
|
||||
for column_number, expected_values in column.iteritems():
|
||||
actual_values = driver.\
|
||||
find_element_by_link_text(name).\
|
||||
find_element_by_xpath(
|
||||
'../../td[%d]' % column_number).\
|
||||
text.split('\n')
|
||||
self.assertItemsEqual(actual_values, expected_values)
|
||||
else:
|
||||
if expected_message:
|
||||
self.assertEqual(expected_message, str(actual_message))
|
||||
self.driver.refresh()
|
||||
|
||||
def await_cluster_active(self, name):
|
||||
driver = self.driver
|
||||
i = 1
|
||||
while True:
|
||||
|
||||
if i > cfg.common.cluster_creation_timeout * 60:
|
||||
self.fail(
|
||||
'cluster is not getting status \'Active\', '
|
||||
'passed %d minutes' % cfg.common.cluster_creation_timeout)
|
||||
|
||||
try:
|
||||
status = driver.find_element_by_link_text(
|
||||
"selenium-cl").find_element_by_xpath("../../td[3]").text
|
||||
except selenim_except.StaleElementReferenceException:
|
||||
status = 'unknown'
|
||||
|
||||
if str(status) == 'Error':
|
||||
self.fail('Cluster state == \'Error\'.')
|
||||
|
||||
if str(status) == 'Active':
|
||||
break
|
||||
|
||||
time.sleep(5)
|
||||
i += 5
|
||||
|
||||
def await_launch_job(self, job_name):
|
||||
driver = self.driver
|
||||
driver.get(cfg.common.base_url +
|
||||
"/project/data_processing/job_executions/")
|
||||
self.await_element(by.By.ID, 'job_executions')
|
||||
|
||||
job_id = None
|
||||
retry_count = 0
|
||||
while not job_id:
|
||||
if retry_count > 10:
|
||||
self.fail("id of job execution didn't obtained")
|
||||
try:
|
||||
job_id = driver.find_element_by_id(
|
||||
'job_executions').find_elements_by_class_name(
|
||||
'ajax-update')[0].get_attribute('id')
|
||||
self.job_id = job_id.split("_")[-1]
|
||||
# TODO(vrovachev): replace find job_id on commented code
|
||||
# after resolve bug 1391469
|
||||
# job_id = driver.find_element_by_id(
|
||||
# 'job_executions').find_element_by_link_text(
|
||||
# job_name).find_element_by_xpath(
|
||||
# '../..').get_attribute('id')
|
||||
except selenim_except.StaleElementReferenceException:
|
||||
time.sleep(1)
|
||||
retry_count += 1
|
||||
|
||||
status = None
|
||||
retry_count = 0
|
||||
while not status:
|
||||
if retry_count > 10:
|
||||
self.fail("id of job execution didn't obtained")
|
||||
try:
|
||||
status = driver.find_element_by_id(
|
||||
job_id).find_element_by_xpath(
|
||||
"td[contains(@class, 'status_')]").text
|
||||
except selenim_except.StaleElementReferenceException:
|
||||
time.sleep(1)
|
||||
retry_count += 1
|
||||
|
||||
timeout = cfg.common.job_launch_timeout * 60
|
||||
|
||||
while str(status) != 'SUCCEEDED':
|
||||
|
||||
if timeout <= 0:
|
||||
self.fail(
|
||||
'Job did not return to \'SUCCEEDED\' status within '
|
||||
'%d minute(s).' % cfg.common.job_launch_timeout)
|
||||
|
||||
if status == 'KILLED':
|
||||
self.fail('Job status == \'KILLED\'.')
|
||||
|
||||
status = None
|
||||
retry_count = 0
|
||||
while not status:
|
||||
if retry_count > 10:
|
||||
self.fail("id of job execution didn't obtained")
|
||||
try:
|
||||
status = driver.find_element_by_id(
|
||||
job_id).find_element_by_xpath(
|
||||
"td[contains(@class, 'status_')]").text
|
||||
except selenim_except.StaleElementReferenceException:
|
||||
time.sleep(1)
|
||||
retry_count += 1
|
||||
|
||||
time.sleep(1)
|
||||
timeout -= 1
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
cls.driver.quit()
|
@ -1,48 +0,0 @@
|
||||
# Copyright (c) 2013 Mirantis 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.
|
||||
|
||||
from testtools import testcase
|
||||
import unittest2
|
||||
|
||||
from saharadashboard.tests import base
|
||||
import saharadashboard.tests.configs.config as cfg
|
||||
|
||||
|
||||
class UINegativeCreateClusterTemplateTest(base.UITestCase):
|
||||
|
||||
@testcase.attr('cluster_template', 'vanilla')
|
||||
@unittest2.skip
|
||||
@unittest2.skipIf(cfg.vanilla.skip_plugin_tests,
|
||||
'tests for vanilla plugin skipped')
|
||||
def test_create_vanilla_cluster_template_with_wrong_fields(self):
|
||||
self.create_node_group_template('selenium-master', ["NN", "JT"],
|
||||
cfg.vanilla)
|
||||
self.create_node_group_template('selenium-worker', ["DN", "TT"],
|
||||
cfg.vanilla)
|
||||
self.create_cluster_template(
|
||||
"", {'selenium-master': 1, 'selenium-worker': 2}, cfg.vanilla,
|
||||
anti_affinity_groups=["NN", "DN", "TT"],
|
||||
params=[{"General Parameters:Enable Swift": False},
|
||||
{"HDFS Parameters:io.file.buffer.size": "str"},
|
||||
{"MapReduce Parameters:mapreduce.job.counters.max":
|
||||
"str"}],
|
||||
positive=False, close_window=False,
|
||||
message='Details, HDFS Parameters, MapReduce Parameters, '
|
||||
'Template Name:This field is required., '
|
||||
'HDFS Parameters:io.file.buffer.size:Enter a whole number., '
|
||||
'MapReduce Parameters:mapreduce.job.counters.max:'
|
||||
'Enter a whole number.')
|
||||
self.delete_node_group_templates(["selenium-master",
|
||||
"selenium-worker"])
|
@ -1,77 +0,0 @@
|
||||
# Copyright (c) 2013 Mirantis 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.
|
||||
|
||||
from testtools import testcase
|
||||
import unittest2
|
||||
|
||||
from saharadashboard.tests import base
|
||||
import saharadashboard.tests.configs.config as cfg
|
||||
|
||||
|
||||
class UICreateClusterTemplate(base.UITestCase):
|
||||
|
||||
@testcase.attr('cluster_template', 'vanilla')
|
||||
@unittest2.skipIf(cfg.vanilla.skip_plugin_tests,
|
||||
'tests for vanilla plugin skipped')
|
||||
def test_create_cluster_template_for_vanilla(self):
|
||||
self.create_node_group_template('selenium-master', ["NN", "JT"],
|
||||
cfg.vanilla)
|
||||
self.create_node_group_template('selenium-worker', ["DN", "TT"],
|
||||
cfg.vanilla)
|
||||
self.create_node_group_template('selenium-delete', ["NN", "OZ"],
|
||||
cfg.vanilla)
|
||||
self.create_cluster_template(
|
||||
"selenium-clstr-tmpl", {'selenium-master': 1,
|
||||
'selenium-worker': 2},
|
||||
cfg.vanilla, anti_affinity_groups=["NN", "DN", "TT"],
|
||||
params=[{"General Parameters:Enable Swift": False},
|
||||
{"HDFS Parameters:dfs.replication": 2},
|
||||
{"MapReduce Parameters:mapred.output.compress": False}])
|
||||
msg = 'Error: Cluster template with name \'selenium-clstr-tmpl\'' \
|
||||
' already exists'
|
||||
self.create_cluster_template('selenium-clstr-tmpl',
|
||||
{'selenium-delete': 1,
|
||||
'selenium-worker': 2},
|
||||
cfg.vanilla, positive=False, message=msg)
|
||||
self.delete_node_group_templates(["selenium-master", "selenium-worker",
|
||||
"selenium-delete"],
|
||||
undelete_names=["selenium-master",
|
||||
"selenium-worker"])
|
||||
self.delete_cluster_templates(['selenium-clstr-tmpl'])
|
||||
self.delete_node_group_templates(["selenium-master",
|
||||
"selenium-worker"])
|
||||
|
||||
@testcase.attr('cluster_template', 'hdp')
|
||||
@unittest2.skipIf(cfg.hdp.skip_plugin_tests,
|
||||
'tests for hdp plugin skipped')
|
||||
def test_create_cluster_template_for_hdp(self):
|
||||
self.create_node_group_template(
|
||||
'selenium-hdp-master',
|
||||
["NN", "JT", "SNN", "GANGLIA_SERVER", "NAGIOS_SERVER",
|
||||
"AMBARI_SERVER"], cfg.hdp)
|
||||
self.create_node_group_template(
|
||||
'selenium-hdp-worker',
|
||||
["TT", "DN", "HDFS_CLIENT", "MAPREDUCE_CLIENT"], cfg.hdp)
|
||||
self.create_cluster_template(
|
||||
"selenium-hdp", {'selenium-hdp-master': 1,
|
||||
'selenium-hdp-worker': 2}, cfg.hdp,
|
||||
description="hdp plugin", anti_affinity_groups=["NN", "DN", "TT"],
|
||||
params=[{"General Parameters:Show_param": True},
|
||||
{"hadoop_heapsize": 512},
|
||||
{"HDFS Parameters:Show_param": True},
|
||||
{"HDFS Parameters:dfs.replication": 2}])
|
||||
self.delete_cluster_templates(['selenium-hdp'])
|
||||
self.delete_node_group_templates(["selenium-hdp-master",
|
||||
"selenium-hdp-worker"])
|
@ -1,158 +0,0 @@
|
||||
# Copyright (c) 2013 Mirantis 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.
|
||||
|
||||
import random
|
||||
import string
|
||||
|
||||
from testtools import testcase
|
||||
import unittest2
|
||||
|
||||
from saharadashboard.tests import base
|
||||
import saharadashboard.tests.configs.config as cfg
|
||||
|
||||
|
||||
class UICreateCluster(base.UITestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(UICreateCluster, self).setUp()
|
||||
self.pass_test = False
|
||||
self.processes = ["NN", "JT"]
|
||||
self.await_run = False
|
||||
self.master_storage = {'type': 'Ephemeral Drive'}
|
||||
self.anty_affinity = []
|
||||
if not cfg.vanilla.skip_edp_test:
|
||||
self.swift = self.connect_to_swift()
|
||||
self.processes = ["NN", "JT", "OZ"]
|
||||
self.await_run = True
|
||||
if cfg.common.cinder:
|
||||
self.master_storage = {"type": "Cinder Volume",
|
||||
"volume_per_node": 1,
|
||||
"volume_size": 5}
|
||||
if cfg.common.anty_affinity:
|
||||
self.anty_affinity = "NN", "DN", "TT"
|
||||
|
||||
@testcase.attr('cluster', 'vanilla')
|
||||
@unittest2.skipIf(cfg.vanilla.skip_plugin_tests,
|
||||
'tests for vanilla plugin skipped')
|
||||
def test_create_vanilla_cluster(self):
|
||||
|
||||
self.create_node_group_template('selenium-master', self.processes,
|
||||
cfg.vanilla,
|
||||
storage=self.master_storage)
|
||||
self.create_node_group_template('selenium-worker', ["DN", "TT"],
|
||||
cfg.vanilla)
|
||||
self.create_node_group_template('selenium-del1', ["NN", "JT",
|
||||
"DN", "TT"],
|
||||
cfg.vanilla)
|
||||
self.create_node_group_template('selenium-del2',
|
||||
["DN", "TT", "OZ"],
|
||||
cfg.vanilla)
|
||||
self.create_cluster_template("selenium-cl-tmpl",
|
||||
{'selenium-master': 1,
|
||||
'selenium-worker': 1}, cfg.vanilla,
|
||||
anti_affinity_groups=self.anty_affinity)
|
||||
self.create_cluster_template("selenium-cl-tmpl2",
|
||||
{'selenium-master': 1,
|
||||
'selenium-del2': 2},
|
||||
cfg.vanilla,
|
||||
anti_affinity_groups=["NN", "DN",
|
||||
"TT", "JT"])
|
||||
self.create_cluster(cfg.vanilla.cluster_name, 'selenium-cl-tmpl',
|
||||
cfg.vanilla, await_run=self.await_run)
|
||||
if not cfg.vanilla.skip_edp_test:
|
||||
self.edp_helper()
|
||||
self.delete_node_group_templates(["selenium-master",
|
||||
"selenium-worker",
|
||||
"selenium-del1",
|
||||
"selenium-del2"],
|
||||
undelete_names=["selenium-master",
|
||||
"selenium-worker",
|
||||
"selenium-del2"])
|
||||
self.delete_cluster_templates(['selenium-cl-tmpl',
|
||||
'selenium-cl-tmpl2'],
|
||||
undelete_names=["selenium-cl-tmpl"])
|
||||
self.delete_node_group_templates(["selenium-master",
|
||||
"selenium-worker",
|
||||
"selenium-del2"],
|
||||
undelete_names=[
|
||||
"selenium-master",
|
||||
"selenium-worker"])
|
||||
self.delete_clusters([cfg.vanilla.cluster_name], await_delete=True)
|
||||
self.delete_cluster_templates(["selenium-cl-tmpl"])
|
||||
self.delete_node_group_templates(["selenium-master",
|
||||
"selenium-worker"])
|
||||
self.pass_test = True
|
||||
|
||||
def edp_helper(self):
|
||||
self.swift.put_container('selenium-container')
|
||||
self.swift.put_object(
|
||||
'selenium-container', 'input', ''.join(random.choice(
|
||||
':' + ' ' + '\n' + string.ascii_lowercase)
|
||||
for x in range(10000)))
|
||||
|
||||
self.create_data_source(
|
||||
'input', 'selenium-container.sahara/input')
|
||||
self.create_data_source(
|
||||
'output', 'selenium-container.sahara/output')
|
||||
|
||||
parameters_of_storage = {
|
||||
'storage_type': 'Internal database',
|
||||
'Internal binary': '*Upload a new file',
|
||||
'filename': 'edp-lib.jar'}
|
||||
|
||||
self.create_job_binary('edp-lib.jar', parameters_of_storage)
|
||||
|
||||
parameters_of_storage = {
|
||||
'storage_type': 'Internal database',
|
||||
'Internal binary': '*Create a script',
|
||||
'script_name': 'edp-job.pig',
|
||||
'script_text': open('saharadashboard/tests/resources/'
|
||||
'edp-job.pig').read()}
|
||||
|
||||
self.create_job_binary('edp-job.pig', parameters_of_storage)
|
||||
|
||||
self.create_job(
|
||||
'selenium-job', 'Pig', 'edp-job.pig', ['edp-lib.jar'])
|
||||
self.launch_job_on_existing_cluster(
|
||||
'selenium-job', 'input', 'output', cfg.vanilla.cluster_name)
|
||||
|
||||
self.delete_swift_container(self.swift, 'selenium-container')
|
||||
if getattr(self, "job_id", None):
|
||||
self.delete_job_executions([self.job_id], await_delete=True)
|
||||
self.delete_jobs(['selenium-job'])
|
||||
self.delete_job_binaries(['edp-lib.jar', 'edp-job.pig'])
|
||||
self.delete_data_sources(['input', 'output'])
|
||||
|
||||
def cleanup(self):
|
||||
if not cfg.vanilla.skip_edp_test:
|
||||
self.delete_swift_container(self.swift, 'selenium-container')
|
||||
if getattr(self, "job_id", None):
|
||||
self.delete_job_executions([self.job_id], finally_delete=True)
|
||||
self.delete_jobs(['selenium-job'], finally_delete=True)
|
||||
self.delete_job_binaries(['edp-lib.jar', 'edp-job.pig'],
|
||||
finally_delete=True)
|
||||
self.delete_data_sources(['input', 'output'], finally_delete=True)
|
||||
self.delete_clusters([cfg.vanilla.cluster_name], finally_delete=True)
|
||||
self.delete_cluster_templates(['selenium-cl-tmpl',
|
||||
'selenium-cl-tmpl2'],
|
||||
finally_delete=True)
|
||||
self.delete_node_group_templates(["selenium-master", "selenium-worker",
|
||||
"selenium-del1", "selenium-del2"],
|
||||
finally_delete=True)
|
||||
|
||||
def tearDown(self):
|
||||
if not self.pass_test:
|
||||
self.cleanup()
|
||||
super(UICreateCluster, self).tearDown()
|
@ -1,33 +0,0 @@
|
||||
[common]
|
||||
base_url = "http://127.0.0.1:8080"
|
||||
user = "admin"
|
||||
password = "admin"
|
||||
keypair = 'jenkins'
|
||||
tenant = 'admin'
|
||||
auto_security_groups = False
|
||||
security_groups = default
|
||||
flavor = 'm1.minniemouse'
|
||||
# uncomment this parameters if quantum in OpenStack
|
||||
# neutron_management_network = ''
|
||||
# floating_ip_pool = ''
|
||||
keystone_url = 'http://127.0.0.1:5000/v2.0'
|
||||
# in minutes
|
||||
cluster_creation_timeout = 10
|
||||
# in seconds
|
||||
await_element = 10
|
||||
# in minutes
|
||||
job_launch_timeout = 5
|
||||
image_name_for_register = 'image_name'
|
||||
image_name_for_edit = 'image_name'
|
||||
[vanilla]
|
||||
skip_plugin_tests = False
|
||||
plugin_name = "Vanilla Apache Hadoop"
|
||||
plugin_overview_name = "vanilla"
|
||||
hadoop_version = "1.2.1"
|
||||
processes = NN: 0, DN: 1, SNN: 2, OZ: 3, TT: 4, JT: 5
|
||||
base_image = "image_name"
|
||||
[hdp]
|
||||
skip_plugin_tests = False
|
||||
plugin_name = "Hortonworks Data Platform"
|
||||
hadoop_version = "1.3.2"
|
||||
base_image = "image_name"
|
@ -1,169 +0,0 @@
|
||||
# Copyright (c) 2013 Mirantis 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.
|
||||
|
||||
import os
|
||||
|
||||
from oslo_config import cfg
|
||||
|
||||
common_group = cfg.OptGroup(name='common', title="common configs")
|
||||
|
||||
CommonGroup = [
|
||||
cfg.StrOpt('base_url',
|
||||
default='http://127.0.0.1:8080',
|
||||
help="sahara url"),
|
||||
cfg.StrOpt('user',
|
||||
default='admin',
|
||||
help="keystone user"),
|
||||
cfg.StrOpt('password',
|
||||
default='pass',
|
||||
help="password for keystone user"),
|
||||
cfg.StrOpt('keypair',
|
||||
default='public-jenkins',
|
||||
help='keypair for create cluster'),
|
||||
cfg.StrOpt('tenant',
|
||||
default='admin',
|
||||
help='keystone tenant'),
|
||||
cfg.BoolOpt('auto_security_groups',
|
||||
default=False,
|
||||
help="Security Groups for sahara cluster"),
|
||||
cfg.ListOpt('security_groups',
|
||||
default=None,
|
||||
help="Security Groups for sahara cluster"),
|
||||
cfg.StrOpt('flavor',
|
||||
default='m1.minniemouse',
|
||||
help='OpenStack flavor name for image.'),
|
||||
cfg.StrOpt('neutron_management_network',
|
||||
default=None,
|
||||
help='Private network for quantum.'
|
||||
'Must be specified in create cluster tab'),
|
||||
cfg.StrOpt('floating_ip_pool',
|
||||
default=None,
|
||||
help='Public network for quantum.'
|
||||
'Must be specified in create nodegroup template tab'),
|
||||
cfg.StrOpt('keystone_url',
|
||||
default='http://127.0.0.1:5000/v2.0',
|
||||
help='url for keystone authentication'),
|
||||
cfg.BoolOpt('anty_affinity',
|
||||
default=False,
|
||||
help="Parameter for enable/disable Anty Affinity "
|
||||
"Groups for Sahara cluster"),
|
||||
cfg.BoolOpt('cinder',
|
||||
default=False,
|
||||
help="Parameter for enable/disable attach volume disk "
|
||||
"to node for Sahara cluster"),
|
||||
cfg.IntOpt('cluster_creation_timeout',
|
||||
default=10,
|
||||
help="cluster timeout in minutes"),
|
||||
cfg.IntOpt('await_element',
|
||||
default=15,
|
||||
help="await each web element in seconds"),
|
||||
cfg.StrOpt('image_name_for_register',
|
||||
default='fedora_19',
|
||||
help='Image name for register to Sahara'),
|
||||
cfg.StrOpt('image_name_for_edit',
|
||||
default='latest-ci-image',
|
||||
help='Image name for edit in image registry in Sahara'),
|
||||
cfg.IntOpt('job_launch_timeout',
|
||||
default=5,
|
||||
help='Timeout for job launch (in minutes); '
|
||||
'minimal value is 1.'),
|
||||
]
|
||||
|
||||
vanilla_group = cfg.OptGroup(name='vanilla', title="vanilla configs")
|
||||
|
||||
VanillaGroup = [
|
||||
cfg.BoolOpt('skip_plugin_tests',
|
||||
default=False,
|
||||
help="""
|
||||
If this variable is True then
|
||||
tests for vanilla will be skipped
|
||||
"""),
|
||||
cfg.BoolOpt('skip_edp_test', default=True),
|
||||
cfg.StrOpt('plugin_name',
|
||||
default='Vanilla Apache Hadoop',
|
||||
help="plugin title, default: Vanilla Apache Hadoop"),
|
||||
cfg.StrOpt('plugin_overview_name',
|
||||
default='vanilla',
|
||||
help="plugin name in overview"),
|
||||
cfg.StrOpt('cluster_name',
|
||||
default="selenium-cl",
|
||||
help="Name of vanilla cluster"),
|
||||
cfg.StrOpt('hadoop_version',
|
||||
default='1.2.1',
|
||||
help="hadoop version for plugin"),
|
||||
cfg.DictOpt('processes',
|
||||
default={"NN": 0, "DN": 1, "SNN": 2,
|
||||
"OZ": 3, "TT": 4, "JT": 5, "hiveserver": 6},
|
||||
help='numbers of processes for vanilla in saharadashboard'),
|
||||
cfg.StrOpt('base_image',
|
||||
default='ubuntu_sahara_latest',
|
||||
help="image name for start vanilla cluster")
|
||||
]
|
||||
|
||||
hdp_group = cfg.OptGroup(name='hdp', title="hdp configs")
|
||||
|
||||
HdpGroup = [
|
||||
cfg.BoolOpt('skip_plugin_tests',
|
||||
default=False,
|
||||
help="""
|
||||
If this variable is True then
|
||||
tests for hdp will be skipped
|
||||
"""),
|
||||
cfg.StrOpt('plugin_name',
|
||||
default='Hortonworks Data Platform',
|
||||
help="plugin title, default: Hortonworks Data Platform"),
|
||||
cfg.StrOpt('plugin_overview_name',
|
||||
default='hdp',
|
||||
help="plugin name in overview"),
|
||||
cfg.StrOpt('hadoop_version',
|
||||
default='1.3.2',
|
||||
help="hadoop version for plugin"),
|
||||
cfg.DictOpt('processes',
|
||||
default={
|
||||
"NN": 0, "DN": 1, "SNN": 2, "HDFS_CLIENT": 3,
|
||||
" ZOOKEEPER_SERVER": 4, "ZOOKEEPER_CLIENT": 5,
|
||||
"AMBARI_SERVER": 6, "HCAT": 7, "SQOOP": 8,
|
||||
"JT": 9, "TT": 10, "MAPREDUCE_CLIENT": 11,
|
||||
"HIVE_SERVER": 12, "HIVE_METASTORE": 13,
|
||||
"HIVE_CLIENT": 14, "MYSQL_SERVER": 15,
|
||||
"PIG": 16, "WEBHCAT_SERVER": 17, "OOZIE_SERVER": 18,
|
||||
"OOZIE_CLIENT": 19, "GANGLIA_SERVER": 20,
|
||||
"NAGIOS_SERVER": 21, "HBASE_MASTER": 22,
|
||||
"HBASE_REGIONSERVER": 23, "HBASE_CLIENT": 24
|
||||
}, help='numbers of processes for hdp in saharadashboard'),
|
||||
cfg.StrOpt('base_image',
|
||||
default='ib-centos-6-4-64-hdp-13',
|
||||
help="image name for start hdp cluster")
|
||||
]
|
||||
|
||||
|
||||
def register_config(config, config_group, config_opts):
|
||||
|
||||
config.register_group(config_group)
|
||||
config.register_opts(config_opts, config_group)
|
||||
|
||||
path = os.path.join("%s/saharadashboard/tests/configs/config.conf"
|
||||
% os.getcwd())
|
||||
|
||||
if os.path.exists(path):
|
||||
cfg.CONF([], project='saharadashboard', default_config_files=[path])
|
||||
|
||||
register_config(cfg.CONF, common_group, CommonGroup)
|
||||
register_config(cfg.CONF, vanilla_group, VanillaGroup)
|
||||
register_config(cfg.CONF, hdp_group, HdpGroup)
|
||||
|
||||
common = cfg.CONF.common
|
||||
vanilla = cfg.CONF.vanilla
|
||||
hdp = cfg.CONF.hdp
|
@ -1,42 +0,0 @@
|
||||
# Copyright (c) 2013 Mirantis 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.
|
||||
|
||||
from testtools import testcase
|
||||
|
||||
from saharadashboard.tests import base
|
||||
import saharadashboard.tests.configs.config as cfg
|
||||
|
||||
|
||||
class UIImageRegistry(base.UITestCase):
|
||||
|
||||
@testcase.attr('image_registry')
|
||||
def test_edit_tags_for_image(self):
|
||||
self.edit_tags_by_image_name(cfg.common.image_name_for_edit,
|
||||
tags_to_add=[
|
||||
{cfg.hdp.plugin_overview_name:
|
||||
cfg.hdp.hadoop_version},
|
||||
{'custom_tag': 'blabla'}])
|
||||
self.edit_tags_by_image_name(cfg.common.image_name_for_edit,
|
||||
tags_to_add=[{'custom_tag': 'qweqwe'}],
|
||||
tags_to_remove=['qweqwe', 'blabla'])
|
||||
|
||||
@testcase.attr('image_registry')
|
||||
def test_registry_vanilla_image(self):
|
||||
self.image_registry(cfg.common.image_name_for_register,
|
||||
user_name='cloud_user',
|
||||
tags_to_add=[{cfg.vanilla.plugin_overview_name:
|
||||
cfg.vanilla.hadoop_version},
|
||||
{'custom_tag': 'blabla'}])
|
||||
self.unregister_images([cfg.common.image_name_for_register])
|
@ -1,50 +0,0 @@
|
||||
# Copyright (c) 2013 Mirantis 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.
|
||||
|
||||
from testtools import testcase
|
||||
import unittest2
|
||||
|
||||
from saharadashboard.tests import base
|
||||
import saharadashboard.tests.configs.config as cfg
|
||||
|
||||
|
||||
class UINegativeCreateNodeGroupTemplate(base.UITestCase):
|
||||
|
||||
@testcase.attr('node_group_template', 'vanilla')
|
||||
@unittest2.skipIf(cfg.vanilla.skip_plugin_tests,
|
||||
'tests for vanilla plugin skipped')
|
||||
def test_create_vanilla_node_group_template_with_wrong_parameters(self):
|
||||
self.create_node_group_template(
|
||||
"", ["NN", "JT"], cfg.vanilla, flavor="m1.small",
|
||||
params=[{"HDFS Parameters:dfs.datanode.handler.count": "str"},
|
||||
{"MapReduce Parameters:io.sort.mb": "str"}],
|
||||
positive=False, close_window=False,
|
||||
message='Configure Node Group Template, '
|
||||
'HDFS Parameters, MapReduce Parameters, '
|
||||
'Template Name:This field is required., '
|
||||
'HDFS Parameters:dfs.datanode.handler.count:'
|
||||
'Enter a whole number., '
|
||||
'MapReduce Parameters:io.sort.mb:'
|
||||
'Enter a whole number.')
|
||||
|
||||
@testcase.attr('node_group_template', 'vanilla')
|
||||
@unittest2.skipIf(cfg.vanilla.skip_plugin_tests,
|
||||
'tests for vanilla plugin skipped')
|
||||
def test_create_vanilla_node_group_template_with_missing_parameters(self):
|
||||
self.create_node_group_template(
|
||||
"", [], cfg.vanilla, positive=False, close_window=False,
|
||||
message='Configure Node Group Template, '
|
||||
'Template Name:This field is required., '
|
||||
'Processes:This field is required.')
|
@ -1,61 +0,0 @@
|
||||
# Copyright (c) 2013 Mirantis 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.
|
||||
|
||||
from testtools import testcase
|
||||
import unittest2
|
||||
|
||||
from saharadashboard.tests import base
|
||||
import saharadashboard.tests.configs.config as cfg
|
||||
|
||||
|
||||
class UICreateNodeGroupTemplate(base.UITestCase):
|
||||
|
||||
@testcase.attr('node_group_template', 'vanilla')
|
||||
@unittest2.skipIf(cfg.vanilla.skip_plugin_tests,
|
||||
'tests for vanilla plugin skipped')
|
||||
def test_create_node_group_template_vanilla(self):
|
||||
self.create_node_group_template(
|
||||
"selenium-vanilla", ["NN", "JT"], cfg.vanilla, flavor="m1.small",
|
||||
storage={'type': "Cinder Volume", 'volume_per_node': '2',
|
||||
'volume_size': '6'}, description='selenium-test',
|
||||
params=[{"HDFS Parameters:Show_param": True},
|
||||
{"hadoop.native.lib": False}, {"Filter": "heap"},
|
||||
{"Name Node Heap Size": 512},
|
||||
{"Data Node Heap Size": 512},
|
||||
{"Show_param": False}, {"Filter": ""},
|
||||
{"dfs.datanode.max.xcievers": 3555},
|
||||
{"MapReduce Parameters:io.sort.mb": 200},
|
||||
{"mapred.child.java.opts": "-Xmx300m"}])
|
||||
msg = "Error: NodeGroup template with name 'selenium-vanilla'" \
|
||||
" already exists"
|
||||
self.create_node_group_template("selenium-vanilla", ["NN", "JT"],
|
||||
cfg.vanilla, positive=False,
|
||||
message=msg)
|
||||
self.delete_node_group_templates(['selenium-vanilla'])
|
||||
|
||||
@testcase.attr('node_group_template', 'hdp')
|
||||
@unittest2.skipIf(cfg.hdp.skip_plugin_tests,
|
||||
'tests for hdp plugin skipped')
|
||||
def test_create_node_group_template_hdp(self):
|
||||
self.create_node_group_template(
|
||||
"sel-hdp", ["NN", "JT", "HDFS_CLIENT", "AMBARI_SERVER"], cfg.hdp,
|
||||
flavor="m1.small", storage={'type': "Cinder Volume",
|
||||
'volume_per_node': '2',
|
||||
'volume_size': '6'},
|
||||
description='selenium-test')
|
||||
msg = "Error: NodeGroup template with name 'sel-hdp' already exists"
|
||||
self.create_node_group_template("sel-hdp", ["NN", "JT"], cfg.hdp,
|
||||
positive=False, message=msg)
|
||||
self.delete_node_group_templates(['sel-hdp'])
|
@ -1,82 +0,0 @@
|
||||
README for resources
|
||||
=====================================
|
||||
|
||||
Resources in this directory using for check EDP for Sahara.
|
||||
For this purpose the cluster with oozie by process is created.
|
||||
With these resources created and launched jobs.
|
||||
Success of performance of jobs is checked.
|
||||
|
||||
Pig job
|
||||
-------------------------------------
|
||||
|
||||
Description.
|
||||
------------
|
||||
|
||||
Resources 'edp-job.pig' and 'edp-lib.jar' used for create oozie job
|
||||
that deletes all symbols in line after ":".
|
||||
|
||||
Example:
|
||||
--------
|
||||
|
||||
input file:
|
||||
"""
|
||||
qweqwe
|
||||
qweqweqwe:
|
||||
qweqweqwe:qwe
|
||||
:ertertert
|
||||
asd
|
||||
"""
|
||||
|
||||
output file:
|
||||
"""
|
||||
qweqwe
|
||||
qweqweqwe
|
||||
asd
|
||||
"""
|
||||
|
||||
Sources.
|
||||
--------
|
||||
|
||||
Link for 'edp-job.pig':
|
||||
https://github.com/apache/oozie/blob/branch-4.0/examples/src/main/apps/pig/id.pig
|
||||
|
||||
Source for 'edp-lib.jar':
|
||||
https://github.com/apache/oozie/blob/branch-4.0/examples/src/main/java/org/apache/oozie/example/DateList.java
|
||||
|
||||
|
||||
MapReduce job
|
||||
-------------------------------------
|
||||
|
||||
Description.
|
||||
------------
|
||||
|
||||
Resource 'edp-job.jar' used for create oozie job
|
||||
which counts the characters in file and displays values at end of each line.
|
||||
|
||||
Example:
|
||||
--------
|
||||
|
||||
input file:
|
||||
"""
|
||||
qweqwe
|
||||
qweqweqwe:
|
||||
qweqweqwe:qwe
|
||||
:ertertert
|
||||
asd
|
||||
"""
|
||||
|
||||
output file:
|
||||
"""
|
||||
qweqwe 6
|
||||
qweqweqwe: 16
|
||||
qweqweqwe:qwe 29
|
||||
:ertertert 39
|
||||
asd 42
|
||||
"""
|
||||
|
||||
Sources.
|
||||
--------
|
||||
|
||||
Sources for 'edp-job.jar':
|
||||
https://github.com/apache/oozie/blob/branch-4.0/examples/src/main/java/org/apache/oozie/example/SampleMapper.java
|
||||
https://github.com/apache/oozie/blob/branch-4.0/examples/src/main/java/org/apache/oozie/example/SampleReducer.java
|
Binary file not shown.
@ -1,3 +0,0 @@
|
||||
A = load '$INPUT' using PigStorage(':') as (fruit: chararray);
|
||||
B = foreach A generate com.hadoopbook.pig.Trim(fruit);
|
||||
store B into '$OUTPUT' USING PigStorage();
|
Binary file not shown.
@ -1,49 +0,0 @@
|
||||
# Copyright (c) 2013 Mirantis 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.
|
||||
|
||||
import tokenize
|
||||
|
||||
|
||||
def hacking_no_assert_equals(logical_line, tokens):
|
||||
r"""assertEquals() is deprecated, use assertEqual instead.
|
||||
|
||||
Copied from https://review.openstack.org/#/c/35962/
|
||||
|
||||
Okay: self.assertEqual(0, 0)
|
||||
S362: self.assertEquals(0, 0)
|
||||
"""
|
||||
|
||||
for token_type, text, start_index, _, _ in tokens:
|
||||
|
||||
if token_type == tokenize.NAME and text == "assertEquals":
|
||||
yield (
|
||||
start_index[1],
|
||||
"S362: assertEquals is deprecated, use assertEqual")
|
||||
|
||||
|
||||
def hacking_no_author_attr(logical_line, tokens):
|
||||
"""__author__ should not be used.
|
||||
|
||||
S363: __author__ = slukjanov
|
||||
"""
|
||||
for token_type, text, start_index, _, _ in tokens:
|
||||
if token_type == tokenize.NAME and text == "__author__":
|
||||
yield (start_index[1],
|
||||
"S363: __author__ should not be used")
|
||||
|
||||
|
||||
def factory(register):
|
||||
register(hacking_no_assert_equals)
|
||||
register(hacking_no_author_attr)
|
@ -1,18 +0,0 @@
|
||||
# Copyright (c) 2013 Mirantis 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.
|
||||
|
||||
from pbr import version
|
||||
|
||||
version_info = version.VersionInfo('sahara-dashboard')
|
52
setup.cfg
52
setup.cfg
@ -1,25 +1,47 @@
|
||||
[metadata]
|
||||
name = sahara-dashboard
|
||||
version = 2015.1
|
||||
summary = Sahara dashboard
|
||||
description-file = README.rst
|
||||
license = Apache Software License
|
||||
classifiers =
|
||||
Programming Language :: Python
|
||||
Programming Language :: Python :: 2
|
||||
Programming Language :: Python :: 2.7
|
||||
summary = Sahara Management Dashboard
|
||||
description-file =
|
||||
README.rst
|
||||
author = OpenStack
|
||||
author-email = openstack-dev@lists.openstack.org
|
||||
home-page = http://www.openstack.org/
|
||||
classifier =
|
||||
Environment :: OpenStack
|
||||
Intended Audience :: Information Technology
|
||||
Intended Audience :: System Administrators
|
||||
License :: OSI Approved :: Apache Software License
|
||||
Operating System :: POSIX :: Linux
|
||||
author = OpenStack
|
||||
author-email = openstack-dev@lists.openstack.org
|
||||
home-page = http://docs.openstack.org/developer/sahara
|
||||
|
||||
[global]
|
||||
setup-hooks = pbr.hooks.setup_hook
|
||||
Programming Language :: Python
|
||||
Programming Language :: Python :: 2
|
||||
Programming Language :: Python :: 2.7
|
||||
Programming Language :: Python :: 2.6
|
||||
Programming Language :: Python :: 3
|
||||
Programming Language :: Python :: 3.3
|
||||
Programming Language :: Python :: 3.4
|
||||
|
||||
[files]
|
||||
packages =
|
||||
saharadashboard
|
||||
sahara-dashboard
|
||||
|
||||
[build_sphinx]
|
||||
source-dir = doc/source
|
||||
build-dir = doc/build
|
||||
all_files = 1
|
||||
|
||||
[upload_sphinx]
|
||||
upload-dir = doc/build/html
|
||||
|
||||
[compile_catalog]
|
||||
directory = sahara-dashboard/locale
|
||||
domain = sahara-dashboard
|
||||
|
||||
[update_catalog]
|
||||
domain = manila-ui
|
||||
output_dir = manila_ui/locale
|
||||
input_file = manila_ui/locale/manila-ui.pot
|
||||
|
||||
[extract_messages]
|
||||
keywords = _ gettext ngettext l_ lazy_gettext
|
||||
mapping_file = babel.cfg
|
||||
output_file = manila_ui/locale/manila-ui.pot
|
||||
|
@ -2,16 +2,18 @@
|
||||
# of appearance. Changing the order has an impact on the overall integration
|
||||
# process, which may cause wedges in the gate later.
|
||||
|
||||
hacking<0.11,>=0.10.0
|
||||
-e git://github.com/openstack/horizon.git#egg=horizon
|
||||
|
||||
hacking<0.11,>=0.10.0
|
||||
coverage>=3.6
|
||||
ddt>=0.7.0
|
||||
django-nose>=1.2
|
||||
discover
|
||||
mock>=1.2
|
||||
oslo.config>=2.6.0 # Apache-2.0
|
||||
pylint==1.4.4 # GNU GPL v2
|
||||
python-keystoneclient!=1.8.0,>=1.6.0
|
||||
python-swiftclient>=2.2.0
|
||||
selenium
|
||||
mox3>=0.7.0
|
||||
python-subunit>=0.0.18
|
||||
sphinx!=1.2.0,!=1.3b1,<1.3,>=1.1.2
|
||||
oslosphinx>=2.5.0 # Apache-2.0
|
||||
testrepository>=0.0.18
|
||||
testscenarios>=0.4
|
||||
testtools>=1.4.0
|
||||
unittest2
|
||||
|
54
tox.ini
54
tox.ini
@ -1,25 +1,19 @@
|
||||
[tox]
|
||||
minversion = 1.6
|
||||
envlist = py27,pep8,py27dj17
|
||||
skipsdist = True
|
||||
envlist = py26,py27,pep8
|
||||
|
||||
[testenv]
|
||||
usedevelop = True
|
||||
install_command = pip install -U {opts} {packages}
|
||||
setenv =
|
||||
VIRTUAL_ENV={envdir}
|
||||
deps =
|
||||
-r{toxinidir}/requirements.txt
|
||||
-r{toxinidir}/test-requirements.txt
|
||||
VIRTUAL_ENV={envdir}
|
||||
deps = -r{toxinidir}/requirements.txt
|
||||
-r{toxinidir}/test-requirements.txt
|
||||
commands = /bin/bash run_tests.sh -N --no-pep8 {posargs}
|
||||
|
||||
[testenv:uitests]
|
||||
commands = python setup.py testr --slowest --testr-args="--concurrency 1 {posargs}"
|
||||
|
||||
[testenv:cover]
|
||||
commands = python setup.py testr --coverage --testr-args='--concurrency 1 {posargs}'
|
||||
|
||||
[tox:jenkins]
|
||||
downloadcache = ~/cache/pip
|
||||
[testenv:py27]
|
||||
setenv = DJANGO_SETTINGS_MODULE=manila_ui.test.settings
|
||||
|
||||
[testenv:pep8]
|
||||
commands = flake8
|
||||
@ -27,12 +21,30 @@ commands = flake8
|
||||
[testenv:venv]
|
||||
commands = {posargs}
|
||||
|
||||
[flake8]
|
||||
# H904 Wrap long lines in parentheses instead of a backslash
|
||||
ignore = H904
|
||||
show-source = true
|
||||
builtins = _
|
||||
exclude=.venv,.git,.tox,dist,doc,*openstack/common*,*lib/python*,*egg,tools,horizon
|
||||
[testenv:py27dj17]
|
||||
basepython = python2.7
|
||||
commands = pip install django>=1.7,<1.8
|
||||
/bin/bash run_tests.sh -N --no-pep8 {posargs}
|
||||
|
||||
[hacking]
|
||||
local-check-factory = saharadashboard.utils.hacking.checks.factory
|
||||
# Django-1.8 is LTS
|
||||
[testenv:py27dj18]
|
||||
basepython = python2.7
|
||||
commands = pip install django>=1.8,<1.9
|
||||
/bin/bash run_tests.sh -N --no-pep8 {posargs}
|
||||
|
||||
[testenv:cover]
|
||||
commands = python setup.py testr --coverage --testr-args='{posargs}'
|
||||
|
||||
[testenv:docs]
|
||||
commands = python setup.py build_sphinx
|
||||
|
||||
[testenv:debug]
|
||||
commands = oslo_debug_helper {posargs}
|
||||
|
||||
[flake8]
|
||||
show-source = True
|
||||
# E123, E125 skipped as they are invalid PEP-8.
|
||||
# H405 multi line docstring summary not separated with an empty line
|
||||
ignore = E123,E125,H405
|
||||
builtins = _
|
||||
exclude=.venv,.git,.tox,dist,doc,*openstack/common*,*lib/python*,*egg,build,.ropeproject,tools
|
||||
|
Loading…
Reference in New Issue
Block a user