rework functional tests to be a tempest plugin
Change-Id: Ic38b628a4c17e2a8d307ecdeb08c639975a364aa
This commit is contained in:
parent
54e55e4b47
commit
01786798d8
133
devstack/create_config
Executable file
133
devstack/create_config
Executable file
@ -0,0 +1,133 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# create_config script for devstack plugin script
|
||||
# Build config for run functional tests with or wuthout tempest
|
||||
|
||||
set -o xtrace
|
||||
set +o errexit
|
||||
|
||||
TIMEOUT=${TIMEOUT:-180}
|
||||
GCE_SCHEMA=${GCE_SCHEMA:-etc/gceapi/protocols/v1.json}
|
||||
GCE_CRED_TYPE=${GCE_CRED_TYPE:-os_token}
|
||||
GCE_API_PROTOCOL=${GCE_API_PROTOCOL:-http}
|
||||
GCE_HOST=${GCE_HOST:-localhost}
|
||||
GCE_PORT=${GCE_PORT:-8787}
|
||||
GCE_DISCOVERY_URL=${GCE_DISCOVERY_URL:-/discovery/v1/apis/\{api\}/\{apiVersion\}/rest}
|
||||
ZONE=${ZONE:-nova}
|
||||
REGION=${REGION:-region-one}
|
||||
|
||||
|
||||
TEST_CONFIG="$1"
|
||||
if [[ -z "$TEST_CONFIG" ]]; then
|
||||
die $LINENO "Please pass config name"
|
||||
fi
|
||||
sudo rm -f $GCEAPI_DIR/$TEST_CONFIG
|
||||
|
||||
if [[ -n "$TOP_DIR" ]]; then
|
||||
source $TOP_DIR/accrc/admin/admin
|
||||
unset OS_AUTH_TYPE
|
||||
fi
|
||||
|
||||
openstack endpoint list
|
||||
if [[ "$?" -ne "0" ]]; then
|
||||
die $LINENO "OpenStack CLI doesn't work. Looks like credentials are absent."
|
||||
fi
|
||||
|
||||
|
||||
# create separate user/project
|
||||
project_name="project-$(cat /dev/urandom | tr -cd 'a-f0-9' | head -c 8)"
|
||||
eval $(openstack project create -f shell -c id $project_name)
|
||||
project_id=$id
|
||||
[[ -n "$project_id" ]] || { echo "Can't create project"; exit 1; }
|
||||
user_name="user-$(cat /dev/urandom | tr -cd 'a-f0-9' | head -c 8)"
|
||||
password='password'
|
||||
eval $(openstack user create "$user_name" --project "$project_id" --password "$password" --email "$user_name@example.com" -f shell -c id)
|
||||
user_id=$id
|
||||
[[ -n "$user_id" ]] || { echo "Can't create user"; exit 1; }
|
||||
# add 'Member' role for swift access
|
||||
role_id=$(openstack role show Member -c id -f value)
|
||||
openstack role add --project $project_id --user $user_id $role_id
|
||||
|
||||
# prepare flavors
|
||||
flavor_name="n1.standard.1"
|
||||
if [[ -z "$(nova flavor-list | grep $flavor_name)" ]]; then
|
||||
nova flavor-create --is-public True $flavor_name 16 512 0 1
|
||||
[[ "$?" -eq 0 ]] || { echo "Failed to prepare flavor"; exit 1; }
|
||||
fi
|
||||
|
||||
# create default network
|
||||
if [[ -n $(openstack service list | grep neutron) ]]; then
|
||||
# neutron networking
|
||||
networking="neutron"
|
||||
net_id=$(neutron net-create --tenant-id $project_id "default" | grep ' id ' | awk '{print $4}')
|
||||
[[ -n "$net_id" ]] || { echo "net-create failed"; exit 1; }
|
||||
subnet_id=$(neutron subnet-create --tenant-id $project_id --ip_version 4 --gateway 10.240.0.1 --name "private_subnet" $net_id 10.240.0.0/16 | grep ' id ' | awk '{print $4}')
|
||||
[[ -n "$subnet_id" ]] || { echo "subnet-create failed"; exit 1; }
|
||||
router_id=$(neutron router-create --tenant-id $project_id "private_router" | grep ' id ' | awk '{print $4}')
|
||||
[[ -n "$router_id" ]] || { echo "router-create failed"; exit 1; }
|
||||
neutron router-interface-add $router_id $subnet_id
|
||||
[[ "$?" -eq 0 ]] || { echo "router-interface-add failed"; exit 1; }
|
||||
public_net_id=$(neutron net-list | grep public | awk '{print $2}')
|
||||
[[ -n "$public_net_id" ]] || { echo "can't find public network"; exit 1; }
|
||||
neutron router-gateway-set $router_id $public_net_id
|
||||
[[ "$?" -eq 0 ]] || { echo "router-gateway-set failed"; exit 1; }
|
||||
else
|
||||
# nova networking
|
||||
networking="nova-network"
|
||||
nova network-create "default" --fixed-range-v4 10.240.0.0/16 --gateway 10.240.0.1
|
||||
fi
|
||||
|
||||
#create image in raw format
|
||||
os_image_name="cirros-0.3.4-raw-image"
|
||||
if [[ -z "$(openstack image list | grep $os_image_name)" ]]; then
|
||||
image_name="cirros-0.3.4-x86_64-disk.img"
|
||||
cirros_image_url="http://download.cirros-cloud.net/0.3.4/$image_name"
|
||||
sudo rm -f /tmp/$image_name
|
||||
wget -nv -P /tmp $cirros_image_url
|
||||
[[ "$?" -eq 0 ]] || { echo "Failed to download image"; exit 1; }
|
||||
openstack image create --disk-format raw --container-format bare --public --file "/tmp/$image_name" $os_image_name
|
||||
[[ "$?" -eq 0 ]] || { echo "Failed to prepare image"; exit 1; }
|
||||
fi
|
||||
|
||||
export OS_PROJECT_NAME=$project_name
|
||||
export OS_TENANT_NAME=$project_name
|
||||
export OS_USERNAME=$user_name
|
||||
export OS_PASSWORD=$password
|
||||
|
||||
|
||||
# convert flavor name: becase GCE dowsn't allows '.' and converts '-' into '.'
|
||||
flavor_name=${flavor_name//\./-}
|
||||
|
||||
sudo bash -c "cat > $GCEAPI_DIR/$TEST_CONFIG <<EOF
|
||||
[gce]
|
||||
# Generic options
|
||||
build_timeout = $TIMEOUT
|
||||
build_interval = 1
|
||||
|
||||
# GCE API schema
|
||||
schema = $GCE_SCHEMA
|
||||
|
||||
# GCE auth options
|
||||
cred_type = $GCE_CRED_TYPE
|
||||
auth_url = $OS_AUTH_URL
|
||||
username = $OS_USERNAME
|
||||
password = $OS_PASSWORD
|
||||
|
||||
# GCE services address
|
||||
protocol = $GCE_API_PROTOCOL
|
||||
host = $GCE_HOST
|
||||
port = $GCE_PORT
|
||||
|
||||
# GCE API URLs
|
||||
discovery_url = $GCE_DISCOVERY_URL
|
||||
|
||||
# GCE resource IDs for testing
|
||||
project_id = $OS_PROJECT_NAME
|
||||
zone = $ZONE
|
||||
networking = $networking
|
||||
region = $REGION
|
||||
machine_type = $flavor_name
|
||||
image = $OS_PROJECT_NAME/global/images/$os_image_name
|
||||
EOF"
|
||||
|
||||
sudo chown -f $STACK_USER $GCEAPI_DIR/$TEST_CONFIG
|
@ -211,14 +211,20 @@ function install_gceapi() {
|
||||
|
||||
# start_gceapi() - Start running processes, including screen
|
||||
function start_gceapi() {
|
||||
screen_it gce-api "cd $GCEAPI_DIR && $GCEAPI_BIN_DIR/gce-api --config-file $GCEAPI_CONF_DIR/gceapi.conf"
|
||||
run_process gce-api "$GCEAPI_BIN_DIR/gce-api --config-file $GCEAPI_CONF_DIR/gceapi.conf"
|
||||
|
||||
echo "Waiting for GCE API to start..."
|
||||
if ! wait_for_service $SERVICE_TIMEOUT \
|
||||
"$SERVICE_PROTOCOL://$SERVICE_HOST:$GCEAPI_SERVICE_PORT/"; then
|
||||
die $LINENO "GCE API did not start"
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
# stop_gceapi() - Stop running processes
|
||||
function stop_gceapi() {
|
||||
# Kill the gceapi screen windows
|
||||
screen -S $SCREEN_NAME -p gce-api -X kill
|
||||
stop_process gce-api
|
||||
}
|
||||
|
||||
function cleanup_gceapi() {
|
||||
@ -227,6 +233,15 @@ function cleanup_gceapi() {
|
||||
sudo rm -rf $GCEAPI_KEYSTONE_SIGNING_DIR
|
||||
}
|
||||
|
||||
function configure_functional_tests() {
|
||||
(source $GCEAPI_DIR/devstack/create_config "functional_tests.conf")
|
||||
if [[ "$?" -ne "0" ]]; then
|
||||
warn $LINENO "GCE API tests config could not be created."
|
||||
elif is_service_enabled tempest; then
|
||||
cat "$GCEAPI_DIR/functional_tests.conf" >> $TEMPEST_CONFIG
|
||||
fi
|
||||
}
|
||||
|
||||
# main dispatcher
|
||||
if [[ "$1" == "stack" && "$2" == "install" ]]; then
|
||||
echo_summary "Installing gce-api"
|
||||
@ -239,6 +254,7 @@ elif [[ "$1" == "stack" && "$2" == "extra" ]]; then
|
||||
echo_summary "Initializing gce-api"
|
||||
init_gceapi
|
||||
start_gceapi
|
||||
configure_functional_tests
|
||||
fi
|
||||
|
||||
if [[ "$1" == "unstack" ]]; then
|
||||
|
@ -17,18 +17,23 @@
|
||||
# Sleep some time until all services are starting
|
||||
sleep 5
|
||||
|
||||
export TEST_CONFIG_DIR=$(readlink -f .)
|
||||
export GCEAPI_DIR=$(readlink -f .)
|
||||
export TEST_CONFIG="functional_tests.conf"
|
||||
|
||||
# save original creds(admin) for later usage
|
||||
OLD_OS_PROJECT_NAME=$OS_PROJECT_NAME
|
||||
OLD_OS_USERNAME=$OS_USERNAME
|
||||
OLD_OS_PASSWORD=$OS_PASSWORD
|
||||
|
||||
# bug somewhere
|
||||
unset OS_AUTH_TYPE
|
||||
|
||||
if [[ ! -f $TEST_CONFIG_DIR/$TEST_CONFIG ]]; then
|
||||
function die() {
|
||||
echo "ERROR in $1: $2"
|
||||
exit 1
|
||||
}
|
||||
export -f die
|
||||
function warn() {
|
||||
echo "WARNING in $1: $2"
|
||||
}
|
||||
export -f warn
|
||||
|
||||
if [[ ! -f $GCEAPI_DIR/$TEST_CONFIG ]]; then
|
||||
|
||||
openstack endpoint list --os-identity-api-version=3
|
||||
openstack service list --long
|
||||
@ -37,119 +42,28 @@ if [[ ! -f $TEST_CONFIG_DIR/$TEST_CONFIG ]]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# create separate user/project
|
||||
project_name="project-$(cat /dev/urandom | tr -cd 'a-f0-9' | head -c 8)"
|
||||
eval $(openstack project create -f shell -c id $project_name)
|
||||
project_id=$id
|
||||
[[ -n "$project_id" ]] || { echo "Can't create project"; exit 1; }
|
||||
user_name="user-$(cat /dev/urandom | tr -cd 'a-f0-9' | head -c 8)"
|
||||
password='password'
|
||||
eval $(openstack user create "$user_name" --project "$project_id" --password "$password" --email "$user_name@example.com" -f shell -c id)
|
||||
user_id=$id
|
||||
[[ -n "$user_id" ]] || { echo "Can't create user"; exit 1; }
|
||||
# add 'Member' role for swift access
|
||||
role_id=$(openstack role show Member -c id -f value)
|
||||
openstack role add --project $project_id --user $user_id $role_id
|
||||
|
||||
# prepare flavors
|
||||
flavor_name="n1.standard.1"
|
||||
if [[ -z "$(nova flavor-list | grep $flavor_name)" ]]; then
|
||||
nova flavor-create --is-public True $flavor_name 16 512 0 1
|
||||
[[ "$?" -eq 0 ]] || { echo "Failed to prepare flavor"; exit 1; }
|
||||
STACK_USER=$(whoami) $GCEAPI_DIR/devstack/create_config $TEST_CONFIG
|
||||
if [[ "$?" -ne "0" ]]; then
|
||||
echo "Config creation has failed."
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
# create default network
|
||||
if [[ -n $(openstack service list | grep neutron) ]]; then
|
||||
# neutron networking
|
||||
networking="neutron"
|
||||
net_id=$(neutron net-create --tenant-id $project_id "default" | grep ' id ' | awk '{print $4}')
|
||||
[[ -n "$net_id" ]] || { echo "net-create failed"; exit 1; }
|
||||
subnet_id=$(neutron subnet-create --tenant-id $project_id --ip_version 4 --gateway 10.240.0.1 --name "private_subnet" $net_id 10.240.0.0/16 | grep ' id ' | awk '{print $4}')
|
||||
[[ -n "$subnet_id" ]] || { echo "subnet-create failed"; exit 1; }
|
||||
router_id=$(neutron router-create --tenant-id $project_id "private_router" | grep ' id ' | awk '{print $4}')
|
||||
[[ -n "$router_id" ]] || { echo "router-create failed"; exit 1; }
|
||||
neutron router-interface-add $router_id $subnet_id
|
||||
[[ "$?" -eq 0 ]] || { echo "router-interface-add failed"; exit 1; }
|
||||
public_net_id=$(neutron net-list | grep public | awk '{print $2}')
|
||||
[[ -n "$public_net_id" ]] || { echo "can't find public network"; exit 1; }
|
||||
neutron router-gateway-set $router_id $public_net_id
|
||||
[[ "$?" -eq 0 ]] || { echo "router-gateway-set failed"; exit 1; }
|
||||
else
|
||||
# nova networking
|
||||
networking="nova-network"
|
||||
nova network-create "default" --fixed-range-v4 10.240.0.0/16 --gateway 10.240.0.1
|
||||
fi
|
||||
|
||||
#create image in raw format
|
||||
os_image_name="cirros-0.3.4-raw-image"
|
||||
if [[ -z "$(openstack image list | grep $os_image_name)" ]]; then
|
||||
image_name="cirros-0.3.4-x86_64-disk.img"
|
||||
cirros_image_url="http://download.cirros-cloud.net/0.3.4/$image_name"
|
||||
sudo rm -f /tmp/$image_name
|
||||
wget -nv -P /tmp $cirros_image_url
|
||||
[[ "$?" -eq 0 ]] || { echo "Failed to download image"; exit 1; }
|
||||
openstack image create --disk-format raw --container-format bare --public --file "/tmp/$image_name" $os_image_name
|
||||
[[ "$?" -eq 0 ]] || { echo "Failed to prepare image"; exit 1; }
|
||||
fi
|
||||
|
||||
export OS_PROJECT_NAME=$project_name
|
||||
export OS_TENANT_NAME=$project_name
|
||||
export OS_USERNAME=$user_name
|
||||
export OS_PASSWORD=$password
|
||||
|
||||
sudo bash -c "cat > $TEST_CONFIG_DIR/$TEST_CONFIG <<EOF
|
||||
[gce]
|
||||
# Generic options
|
||||
build_timeout=${TIMEOUT:-180}
|
||||
build_interval=1
|
||||
|
||||
# GCE API schema
|
||||
schema=${GCE_SCHEMA:-'etc/gceapi/protocols/v1.json'}
|
||||
|
||||
# GCE auth options
|
||||
cred_type=${GCE_CRED_TYPE:-'os_token'}
|
||||
auth_url=${OS_AUTH_URL}
|
||||
username=${OS_USERNAME}
|
||||
password=${OS_PASSWORD}
|
||||
|
||||
# GCE services address
|
||||
protocol=${GCE_API_PROTOCOL:-'http'}
|
||||
host=${GCE_HOST:-'localhost'}
|
||||
port=${GCE_PORT:-8787}
|
||||
|
||||
# GCE API URLs
|
||||
discovery_url=${GCE_DISCOVERY_URL:-'/discovery/v1/apis/{api}/{apiVersion}/rest'}
|
||||
|
||||
# GCE resource IDs for testing
|
||||
project_id=${OS_PROJECT_NAME}
|
||||
zone=${ZONE:-'nova'}
|
||||
networking=${networking}
|
||||
region=${REGION:-'region-one'}
|
||||
# convert flavor name: becase GCE dowsn't allows '.' and converts '-' into '.'
|
||||
machine_type=${flavor_name//\./-}
|
||||
image=${OS_PROJECT_NAME}/global/images/${os_image_name}
|
||||
EOF"
|
||||
fi
|
||||
|
||||
sudo pip install -r test-requirements.txt
|
||||
sudo pip install google-api-python-client
|
||||
sudo pip install virtualenv
|
||||
sudo rm -rf .venv
|
||||
sudo virtualenv .venv --system-site-package
|
||||
sudo chown -R $USER .venv
|
||||
source .venv/bin/activate
|
||||
pip install -r test-requirements.txt
|
||||
pip install google-api-python-client
|
||||
sudo OS_STDOUT_CAPTURE=-1 OS_STDERR_CAPTURE=-1 OS_TEST_TIMEOUT=500 OS_TEST_LOCK_PATH=${TMPDIR:-'/tmp'} \
|
||||
python -m subunit.run discover -t ./ ./gceapi/tests/functional/api | subunit-2to1 | tools/colorizer.py
|
||||
RETVAL=$?
|
||||
deactivate
|
||||
|
||||
# Here can be some commands for log archiving, etc...
|
||||
|
||||
echo Enumerate resources to check what left after tests
|
||||
for i in instances images disks snapshots
|
||||
do
|
||||
echo "List of "$i
|
||||
gcloud compute $i list
|
||||
echo ""
|
||||
done
|
||||
export OS_PROJECT_NAME=$OLD_OS_PROJECT_NAME
|
||||
export OS_TENANT_NAME=$OLD_OS_PROJECT_NAME
|
||||
export OS_USERNAME=$OLD_OS_USERNAME
|
||||
export OS_PASSWORD=$OLD_OS_PASSWORD
|
||||
openstack flavor list
|
||||
openstack image list
|
||||
openstack server list --all-projects
|
||||
|
@ -14,84 +14,22 @@
|
||||
# under the License.
|
||||
|
||||
|
||||
from os import environ
|
||||
from os import path
|
||||
import logging as std_logging
|
||||
import os
|
||||
|
||||
from oslo_config import cfg
|
||||
from oslo_log import log as logging
|
||||
|
||||
from gceapi.tests.functional import config_opts
|
||||
|
||||
|
||||
OPTIONS_GROUP = cfg.OptGroup(name='gce', title='GCE options')
|
||||
OPTIONS = [
|
||||
# Generic options
|
||||
cfg.IntOpt('build_timeout',
|
||||
default=180,
|
||||
help='Timeout'),
|
||||
cfg.IntOpt('build_interval',
|
||||
default=1,
|
||||
help='Interval'),
|
||||
LOG = logging.getLogger('gceapi')
|
||||
|
||||
# GCE auth options
|
||||
cfg.StrOpt('cred_type',
|
||||
default='os_token',
|
||||
help='Method how to get credentials:'
|
||||
'\n\tos_token - request token from OS keystone directly'
|
||||
'\n\tgcloud_auth - use app credentials that should be'
|
||||
'obtained before via gcloud auth'),
|
||||
cfg.StrOpt('username',
|
||||
default='demo',
|
||||
help='User name'),
|
||||
cfg.StrOpt('password',
|
||||
default='password',
|
||||
help='User password'),
|
||||
cfg.StrOpt('auth_url',
|
||||
default='http://localhost:5000/v2.0/',
|
||||
help='OAuth API relative URL'),
|
||||
|
||||
# GCE API schema
|
||||
cfg.StrOpt('schema',
|
||||
default='etc/gceapi/protocols/v1.json',
|
||||
help='Json file with API schema for validation'),
|
||||
|
||||
# GCE services address
|
||||
cfg.StrOpt('protocol',
|
||||
default='http',
|
||||
help='GCE protocl (http or https)'),
|
||||
cfg.StrOpt('host',
|
||||
default='localhost',
|
||||
help='GCE service host'),
|
||||
cfg.IntOpt('port',
|
||||
default=8787,
|
||||
help='GCE service port'),
|
||||
|
||||
# GCE API URLs
|
||||
cfg.StrOpt('discovery_url',
|
||||
default='/discovery/v1/apis/{api}/{apiVersion}/rest',
|
||||
help='Discovery API relative URL'),
|
||||
|
||||
# GCE resource IDs for testing
|
||||
# Note that Google's project has Name, ID and Number, for project
|
||||
# identification ID should be used, but in Openstack project has
|
||||
# Name and ID, where Name is corresponds to Project ID in Google, ID is
|
||||
# Openstack ID's and has no relation to Google's ID and Number.
|
||||
cfg.StrOpt('project_id',
|
||||
default='test',
|
||||
help='GCE Project ID for testing'),
|
||||
cfg.StrOpt('zone',
|
||||
default='nova',
|
||||
help='GCE Zone for testing'),
|
||||
cfg.StrOpt('region',
|
||||
default='us-central1',
|
||||
help='GCE Region for testing'),
|
||||
cfg.StrOpt('networking',
|
||||
default='neutron',
|
||||
help='Types of OS networking: neutron or nova-network'),
|
||||
|
||||
cfg.StrOpt('machine_type',
|
||||
default='n1-standard-1',
|
||||
help='Machine type - a type of instance ot be created'),
|
||||
cfg.StrOpt('image',
|
||||
default='debian-cloud/global/images/debian-7-wheezy-v20150929',
|
||||
help='Image to create instances'),
|
||||
]
|
||||
def get_base_dir():
|
||||
cur_dir = os.path.dirname(__file__)
|
||||
base_dir = os.path.dirname(os.path.dirname(os.path.dirname(cur_dir)))
|
||||
return os.environ.get('TEST_CONFIG_DIR', base_dir)
|
||||
|
||||
|
||||
# This should never be called outside of this class
|
||||
@ -101,34 +39,30 @@ class ConfigPrivate(object):
|
||||
def __init__(self):
|
||||
"""Initialize a configuration from a conf directory and conf file."""
|
||||
super(ConfigPrivate, self).__init__()
|
||||
base_dir = self._get_base_dir()
|
||||
cfg_file_path = self._get_default_config_path(base_dir)
|
||||
config_files = []
|
||||
if path.exists(cfg_file_path):
|
||||
config_files.append(cfg_file_path)
|
||||
cfg.CONF.register_group(OPTIONS_GROUP)
|
||||
cfg.CONF.register_opts(OPTIONS, group=OPTIONS_GROUP)
|
||||
cfg.CONF([], project='gceapi', default_config_files=config_files)
|
||||
self.gce = cfg.CONF.gce
|
||||
# Load API scheme for API calls validation
|
||||
with open(self._get_default_schema_path(base_dir), 'r') as f:
|
||||
from json import load
|
||||
self.gce.schema = load(f)
|
||||
|
||||
@staticmethod
|
||||
def _get_base_dir():
|
||||
cur_dir = path.dirname(__file__)
|
||||
base_dir = path.dirname(path.dirname(path.dirname(cur_dir)))
|
||||
return environ.get('TEST_CONFIG_DIR', base_dir)
|
||||
# if this was run from tempest runner then config already parsed
|
||||
if config_opts.OPTIONS_GROUP.name in cfg.CONF:
|
||||
self.gce = cfg.CONF.gce
|
||||
return
|
||||
|
||||
cfg_file_path = self._get_default_config_path(get_base_dir())
|
||||
config_files = []
|
||||
if os.path.exists(cfg_file_path):
|
||||
config_files.append(cfg_file_path)
|
||||
|
||||
conf = cfg.CONF
|
||||
conf([], project='gceapi', default_config_files=config_files)
|
||||
conf.register_group(config_opts.OPTIONS_GROUP)
|
||||
group_name = config_opts.OPTIONS_GROUP.name
|
||||
for opt in config_opts.OPTIONS:
|
||||
conf.register_opt(opt, group=group_name)
|
||||
self.gce = cfg.CONF.gce
|
||||
conf.log_opt_values(LOG, std_logging.DEBUG)
|
||||
|
||||
@staticmethod
|
||||
def _get_default_config_path(base_dir):
|
||||
conf_file = environ.get('TEST_CONFIG', 'functional_tests.conf')
|
||||
return path.join(base_dir, conf_file)
|
||||
|
||||
def _get_default_schema_path(self, base_dir):
|
||||
schema_file = environ.get('TEST_SCHEMA', self.gce.schema)
|
||||
return path.join(base_dir, schema_file)
|
||||
conf_file = os.environ.get('TEST_CONFIG', 'functional_tests.conf')
|
||||
return os.path.join(base_dir, conf_file)
|
||||
|
||||
|
||||
class ConfigProxy(object):
|
||||
|
92
gceapi/tests/functional/config_opts.py
Normal file
92
gceapi/tests/functional/config_opts.py
Normal file
@ -0,0 +1,92 @@
|
||||
# Copyright 2012 OpenStack Foundation
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# 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 oslo_config import cfg
|
||||
|
||||
|
||||
OPTIONS_GROUP = cfg.OptGroup(name='gce', title='GCE options')
|
||||
OPTIONS = [
|
||||
# Generic options
|
||||
cfg.IntOpt('build_timeout',
|
||||
default=180,
|
||||
help='Timeout'),
|
||||
cfg.IntOpt('build_interval',
|
||||
default=1,
|
||||
help='Interval'),
|
||||
|
||||
# GCE auth options
|
||||
cfg.StrOpt('cred_type',
|
||||
default='os_token',
|
||||
help='Method how to get credentials:'
|
||||
'\n\tos_token - request token from OS keystone directly'
|
||||
'\n\tgcloud_auth - use app credentials that should be'
|
||||
'obtained before via gcloud auth'),
|
||||
cfg.StrOpt('username',
|
||||
default='demo',
|
||||
help='User name'),
|
||||
cfg.StrOpt('password',
|
||||
default='password',
|
||||
help='User password'),
|
||||
cfg.StrOpt('auth_url',
|
||||
default='http://localhost:5000/v2.0/',
|
||||
help='OAuth API relative URL'),
|
||||
|
||||
# GCE API schema
|
||||
cfg.StrOpt('schema',
|
||||
default='etc/gceapi/protocols/v1.json',
|
||||
help='Json file with API schema for validation'),
|
||||
|
||||
# GCE services address
|
||||
cfg.StrOpt('protocol',
|
||||
default='http',
|
||||
help='GCE protocl (http or https)'),
|
||||
cfg.StrOpt('host',
|
||||
default='localhost',
|
||||
help='GCE service host'),
|
||||
cfg.IntOpt('port',
|
||||
default=8787,
|
||||
help='GCE service port'),
|
||||
|
||||
# GCE API URLs
|
||||
cfg.StrOpt('discovery_url',
|
||||
default='/discovery/v1/apis/{api}/{apiVersion}/rest',
|
||||
help='Discovery API relative URL'),
|
||||
|
||||
# GCE resource IDs for testing
|
||||
# Note that Google's project has Name, ID and Number, for project
|
||||
# identification ID should be used, but in Openstack project has
|
||||
# Name and ID, where Name is corresponds to Project ID in Google, ID is
|
||||
# Openstack ID's and has no relation to Google's ID and Number.
|
||||
cfg.StrOpt('project_id',
|
||||
default='test',
|
||||
help='GCE Project ID for testing'),
|
||||
cfg.StrOpt('zone',
|
||||
default='nova',
|
||||
help='GCE Zone for testing'),
|
||||
cfg.StrOpt('region',
|
||||
default='us-central1',
|
||||
help='GCE Region for testing'),
|
||||
cfg.StrOpt('networking',
|
||||
default='neutron',
|
||||
help='Types of OS networking: neutron or nova-network'),
|
||||
|
||||
cfg.StrOpt('machine_type',
|
||||
default='n1-standard-1',
|
||||
help='Machine type - a type of instance ot be created'),
|
||||
cfg.StrOpt('image',
|
||||
default='debian-cloud/global/images/debian-7-wheezy-v20150929',
|
||||
help='Image to create instances'),
|
||||
]
|
38
gceapi/tests/functional/plugin.py
Normal file
38
gceapi/tests/functional/plugin.py
Normal file
@ -0,0 +1,38 @@
|
||||
# Copyright 2012 OpenStack Foundation
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# 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 tempest import config
|
||||
from tempest.test_discover import plugins
|
||||
|
||||
from gceapi.tests.functional import config_opts as gce_config
|
||||
|
||||
|
||||
class GCETempestPlugin(plugins.TempestPlugin):
|
||||
def load_tests(self):
|
||||
base_path = os.path.split(os.path.dirname(os.path.dirname(
|
||||
os.path.dirname(os.path.abspath(__file__)))))[0]
|
||||
test_dir = "gceapi/tests/functional"
|
||||
full_test_dir = os.path.join(base_path, test_dir)
|
||||
return full_test_dir, base_path
|
||||
|
||||
def register_opts(self, conf):
|
||||
if gce_config.OPTIONS_GROUP.name not in conf:
|
||||
config.register_opt_group(conf, gce_config.OPTIONS_GROUP,
|
||||
gce_config.OPTIONS)
|
||||
|
||||
def get_opt_lists(self):
|
||||
return [(gce_config.OPTIONS_GROUP.name, config.OPTIONS)]
|
@ -15,6 +15,7 @@
|
||||
# under the License.
|
||||
|
||||
import json
|
||||
import os
|
||||
import re
|
||||
import string
|
||||
import time
|
||||
@ -32,7 +33,7 @@ from gceapi.tests.functional import config
|
||||
from gceapi.tests.functional import credentials
|
||||
|
||||
|
||||
CONF = config.CONF.gce
|
||||
CONF = config.CONF
|
||||
LOG = logging.getLogger("gceapi")
|
||||
API_NAME = 'compute'
|
||||
API_VER = 'v1'
|
||||
@ -87,6 +88,30 @@ class LocalRefResolver(jsonschema.RefResolver):
|
||||
return super(LocalRefResolver, self).resolve_from_url(url)
|
||||
|
||||
|
||||
class SchemaHolder(object):
|
||||
|
||||
_instance = None
|
||||
|
||||
def __new__(cls, *args, **kwargs):
|
||||
if not cls._instance:
|
||||
cls._instance = super(SchemaHolder, cls).__new__(
|
||||
cls, *args, **kwargs)
|
||||
return cls._instance
|
||||
|
||||
_schema = None
|
||||
|
||||
def get_schema(self, schema_file):
|
||||
if self._schema:
|
||||
return self._schema
|
||||
|
||||
schema_path = os.path.join(config.get_base_dir(), schema_file)
|
||||
# Load API scheme for API calls validation
|
||||
with open(schema_path, 'r') as f:
|
||||
self._schema = json.load(f)
|
||||
|
||||
return self._schema
|
||||
|
||||
|
||||
class GCEApi(object):
|
||||
def __init__(self, cred_provider):
|
||||
self._compute = None
|
||||
@ -95,7 +120,8 @@ class GCEApi(object):
|
||||
self._scheme_ref_resolver = 0
|
||||
|
||||
def init(self):
|
||||
self._schema = schema.Schemas(CONF.schema)
|
||||
_schema = SchemaHolder().get_schema(CONF.gce.schema)
|
||||
self._schema = schema.Schemas(_schema)
|
||||
self._scheme_ref_resolver = LocalRefResolver.from_schema(
|
||||
self._schema.schemas)
|
||||
self._build_api()
|
||||
@ -131,15 +157,15 @@ class GCEApi(object):
|
||||
|
||||
@property
|
||||
def _host_url(self):
|
||||
cfg = CONF
|
||||
cfg = CONF.gce
|
||||
if self._is_standard_port(cfg.protocol, cfg.port):
|
||||
return '{}://{}'.format(cfg.protocol, cfg.host)
|
||||
return '{}://{}:{}'.format(cfg.protocol, cfg.host, cfg.port)
|
||||
|
||||
@property
|
||||
def _discovery_url(self):
|
||||
t = '{}{}' if CONF.discovery_url.startswith('/') else '{}/{}'
|
||||
return t.format(self._host_url, CONF.discovery_url)
|
||||
t = '{}{}' if CONF.gce.discovery_url.startswith('/') else '{}/{}'
|
||||
return t.format(self._host_url, CONF.gce.discovery_url)
|
||||
|
||||
@property
|
||||
def _api_url(self):
|
||||
@ -147,14 +173,14 @@ class GCEApi(object):
|
||||
|
||||
@property
|
||||
def project_url(self):
|
||||
return '{}/projects/{}'.format(self._api_url, CONF.project_id)
|
||||
return '{}/projects/{}'.format(self._api_url, CONF.gce.project_id)
|
||||
|
||||
def get_zone_url(self, resource=None, zone=None):
|
||||
if resource and self._is_absolute_url(resource):
|
||||
return resource
|
||||
z = zone
|
||||
if z is None:
|
||||
z = CONF.zone
|
||||
z = CONF.gce.zone
|
||||
if not self._is_absolute_url(z):
|
||||
t = '{}/{}' if z.startswith('zones/') else '{}/zones/{}'
|
||||
z = t.format(self.project_url, z)
|
||||
@ -167,7 +193,7 @@ class GCEApi(object):
|
||||
return resource
|
||||
r = region
|
||||
if r is None:
|
||||
r = CONF.region
|
||||
r = CONF.gce.region
|
||||
if not self._is_absolute_url(r):
|
||||
t = '{}/{}' if r.startswith('regions/') else '{}/regions/{}'
|
||||
r = t.format(self.project_url, r)
|
||||
@ -197,7 +223,7 @@ class GCETestCase(base.BaseTestCase):
|
||||
|
||||
@property
|
||||
def cfg(self):
|
||||
return CONF
|
||||
return CONF.gce
|
||||
|
||||
@staticmethod
|
||||
def trace(msg):
|
||||
@ -209,7 +235,7 @@ class GCETestCase(base.BaseTestCase):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
cls._credentials_provider = credentials.CredentialsProvider(CONF)
|
||||
cls._credentials_provider = credentials.CredentialsProvider(CONF.gce)
|
||||
cls._api = GCEApi(cls._credentials_provider)
|
||||
cls._api.init()
|
||||
super(GCETestCase, cls).setUpClass()
|
||||
|
Loading…
Reference in New Issue
Block a user