Implement yaql tests
As we already have yaql expression almost in each task, implement
basic syntax tests for these expressions.
Change-Id: Idb7768eca9be3def4783a70b2ef3b1dafc0d0510
Closes-Bug: #1588910
DocImpact
(cherry picked from commit d5891879a8
)
This commit is contained in:
parent
e283b62750
commit
268dfb0c1e
|
@ -0,0 +1,179 @@
|
|||
#!/usr/bin/env python
|
||||
"""Tests for YAQL expressions in Fuel tasks.yaml files
|
||||
Load and evaluate YAQL expressions from tasks.
|
||||
Usage:
|
||||
check_yaqls.py [--dir DIRPATH] [--fixtures FIXT_DIR] [--cluster CLUSTER_ID] [--node NODE_ID]
|
||||
check_yaqls.py --file FILEPATH [--fixtures FIXT_DIR] [--cluster CLUSTER_ID] [--node NODE_ID]
|
||||
check_yaqls.py -h
|
||||
check_yaqls.py --version
|
||||
|
||||
Options:
|
||||
-d --dir DIRPATH try to load all YAQL expressions from all tasks.yaml files found in directory and subdirectories [default: ../../deployment]
|
||||
-f --file FILEPATH try to load all expressions from file
|
||||
-x --fixtures FIXT_DIR use this directory to load fixtures from [default: fixtures]
|
||||
-c --cluster CLUSTER_ID use this cluster ID [default: 1]
|
||||
-n --node NODE_ID use this node [default: 1]
|
||||
-h --help show this help
|
||||
--version show version
|
||||
"""
|
||||
import collections
|
||||
import json
|
||||
import logging
|
||||
import os
|
||||
import sys
|
||||
import traceback
|
||||
import yaml
|
||||
|
||||
from docopt import docopt
|
||||
from nailgun.fuyaql import fuyaql
|
||||
|
||||
TEST_FAILED = False
|
||||
options = docopt(__doc__, version='0.1')
|
||||
|
||||
|
||||
def load_tasks_from_directory(directory):
|
||||
"""Loads tasks from dir and subdirs.
|
||||
|
||||
:param directory: directory from which tasks will be loaded
|
||||
:return: dict with task names as keys and task expressions as values
|
||||
"""
|
||||
tasks_list = []
|
||||
for root, dirs, files in os.walk(directory):
|
||||
for filename in files:
|
||||
if filename == 'tasks.yaml':
|
||||
tasks_list.append(os.path.join(root, filename))
|
||||
|
||||
tasks_conditions = dict()
|
||||
for tasks in tasks_list:
|
||||
tasks_conditions.update(load_tasks_from_file(tasks))
|
||||
return tasks_conditions
|
||||
|
||||
|
||||
def load_tasks_from_file(tasks_file):
|
||||
"""Loads tasks from file.
|
||||
|
||||
:param tasks_file: file from which tasks will be loaded
|
||||
:return: dict with task names as keys and task expressions as values
|
||||
"""
|
||||
tasks_conditions = dict()
|
||||
with open(tasks_file, 'rt') as f:
|
||||
yml = yaml.safe_load(f)
|
||||
tasks_conditions.update(
|
||||
{t['id']: t.get('condition', {}).get('yaql_exp', {}) for t in yml})
|
||||
return tasks_conditions
|
||||
|
||||
|
||||
def load_tasks():
|
||||
"""Load tasks from directory or file
|
||||
|
||||
:return: hash with tasks names and conditions
|
||||
"""
|
||||
if not options['--file']:
|
||||
current_dir = os.path.dirname(os.path.realpath(__file__))
|
||||
deployment_dir = current_dir + "/" + options['--dir']
|
||||
print('deployment dir is %s' % deployment_dir)
|
||||
tasks = load_tasks_from_directory(deployment_dir)
|
||||
else:
|
||||
tasks_file = options['--file']
|
||||
tasks = load_tasks_from_file(tasks_file)
|
||||
return tasks
|
||||
|
||||
|
||||
def get_logger():
|
||||
"""Get a logger and disable DEBUG state
|
||||
|
||||
:return: logger instance
|
||||
"""
|
||||
logger = logging.getLogger(__name__)
|
||||
logger.propagate = False
|
||||
logging.disable(logging.DEBUG)
|
||||
return logger
|
||||
|
||||
|
||||
def get_evaluator():
|
||||
"""Get a YAQL evaluator
|
||||
|
||||
:return: FuYaqlController evaluator instance
|
||||
"""
|
||||
evaluator = fuyaql.FuYaqlController()
|
||||
evaluator._cluster = True
|
||||
evaluator._node_id = options['--node']
|
||||
return evaluator
|
||||
|
||||
|
||||
def set_evaluator_data(evaluator, old_context, new_context):
|
||||
"""Set evaluator data
|
||||
|
||||
:param evaluator: FuYaqlController evaluator instance
|
||||
:param old_context: hash to use as an old context
|
||||
:param new_context: hash to use as a new context
|
||||
"""
|
||||
try:
|
||||
with open(os.path.expanduser(old_context), 'r') as f:
|
||||
current_state = json.load(f)
|
||||
with open(os.path.expanduser(new_context), 'r') as f:
|
||||
expected_state = json.load(f)
|
||||
except IOError:
|
||||
print("Cannot open context fixtures file.")
|
||||
print(traceback.format_exc())
|
||||
sys.exit(1)
|
||||
evaluator._infos = current_state, expected_state
|
||||
|
||||
|
||||
def load_fixtures_from_directory(directory):
|
||||
"""Recursively load fixture sets from directory
|
||||
|
||||
:param directory: path to a directory with fixtures
|
||||
:return: dictionary with fixtures name and path to context files
|
||||
"""
|
||||
fixtures = collections.defaultdict(dict)
|
||||
for root, dirs, files in os.walk(directory):
|
||||
for filename in files:
|
||||
if filename.endswith('_old_context.json'):
|
||||
base_name = filename.split('_old_context.json')[0]
|
||||
fixtures[base_name]['old'] = os.path.join(root, filename)
|
||||
elif filename.endswith('_new_context.json'):
|
||||
base_name = filename.split('_new_context.json')[0]
|
||||
fixtures[base_name]['new'] = os.path.join(root, filename)
|
||||
return fixtures
|
||||
|
||||
|
||||
tasks = load_tasks()
|
||||
logger = get_logger()
|
||||
evaluator = get_evaluator()
|
||||
fixtures = load_fixtures_from_directory(options['--fixtures'])
|
||||
|
||||
|
||||
for basename, files_hash in fixtures.items():
|
||||
print("Start evaluating for {} context".format(basename))
|
||||
set_evaluator_data(evaluator, files_hash['old'], files_hash['new'])
|
||||
failed_tasks = dict()
|
||||
|
||||
for task_name, expression in tasks.items():
|
||||
# There are tasks without yaql_expressions
|
||||
if not expression:
|
||||
continue
|
||||
try:
|
||||
res = evaluator.evaluate(expression)
|
||||
print("Expression for %s task looks valid" % task_name)
|
||||
except Exception as e:
|
||||
print("Expression for %s task doesn't looks valid" % task_name)
|
||||
print("%s" % expression)
|
||||
print(traceback.format_exc())
|
||||
failed_tasks[task_name] = 'Fail'
|
||||
|
||||
if failed_tasks:
|
||||
print('*'*20 + ' List of failed tasks ' + '*'*20)
|
||||
for name in failed_tasks:
|
||||
print(name)
|
||||
TEST_FAILED = True
|
||||
|
||||
if TEST_FAILED:
|
||||
print("Some tasks failed, check the output")
|
||||
sys.exit(1)
|
||||
|
||||
print('*'*20 + ' There is no failed tasks ' + '*'*20)
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
#!/bin/sh
|
||||
# It is a workaround for old pip and tox versions. CI uses tox 1.6 and it
|
||||
# can't manage hash symbols right way (look at
|
||||
# https://bitbucket.org/hpk42/tox/issues/181/hash-number-sign-cannot-be-escaped-in)
|
||||
# We can use deps field for tox but at the same time CI uses pip 1.5.4 and it
|
||||
# can't properly install package from a vcs subdirectory. Also we can't just
|
||||
# update pip from tox deps as dependencies doesn't managed in a consequent way in tox.
|
||||
# TODO(sbog): move this into tox configuration when CI will use newer versions of tox and pip (tested for pip 7.1.2 and tox 2.3.1)
|
||||
pip install -e "git+https://github.com/openstack/fuel-web.git#egg=nailgun&subdirectory=nailgun"
|
|
@ -0,0 +1,35 @@
|
|||
#!/bin/bash
|
||||
set -eux
|
||||
DIR=`dirname $0`
|
||||
cd "${DIR}" || exit 1
|
||||
|
||||
REPO_URL=${NOOP_FIXTURES_REPO_URL:-'https://github.com/openstack/fuel-noop-fixtures.git'}
|
||||
clone_fixtures_repo() {
|
||||
if ! [ -d 'fuel-noop-fixtures' ]; then
|
||||
echo "Cloning the repository..."
|
||||
git clone "${REPO_URL}" 'fuel-noop-fixtures'
|
||||
fi
|
||||
}
|
||||
|
||||
link_yaql_fixtures() {
|
||||
if ! [ -L 'fixtures' ]; then
|
||||
echo "Linking repo fixtures to the local FS..."
|
||||
ln -sf 'fuel-noop-fixtures/yaql' 'fixtures'
|
||||
fi
|
||||
}
|
||||
|
||||
check_tox() {
|
||||
type tox >/dev/null 2>&1 || { echo >&2 "Tox is required to be installed to run tests."; exit 1; }
|
||||
}
|
||||
|
||||
run_tox() {
|
||||
echo "Run tests..."
|
||||
tox
|
||||
}
|
||||
|
||||
check_tox
|
||||
clone_fixtures_repo
|
||||
link_yaql_fixtures
|
||||
run_tox
|
||||
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
[tox]
|
||||
minversion = 1.6
|
||||
envlist = py27
|
||||
skipsdist = True
|
||||
|
||||
[testenv]
|
||||
deps = docopt
|
||||
commands =
|
||||
pip install pip --upgrade
|
||||
./install_nailgun.sh
|
||||
python check_yaqls.py
|
|
@ -0,0 +1,5 @@
|
|||
#!/bin/sh
|
||||
DIR=`dirname $0`
|
||||
cd $DIR || exit 1
|
||||
|
||||
../../tests/yaql/run_tests.sh
|
Loading…
Reference in New Issue