-
Notifications
You must be signed in to change notification settings - Fork 26
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add openstack charm func test runner #220
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,159 @@ | ||
#!/bin/bash -eu | ||
# | ||
# Run Charmed Openstack CI tests manually in a similar way to how they are run | ||
# by OpenStack CI (OSCI). | ||
# | ||
# Usage: clone/fetch charm to test and run from within charm root dir. | ||
# | ||
FUNC_TEST_PR= | ||
FUNC_TEST_TARGET= | ||
MODIFY_BUNDLE_CONSTRAINTS=true | ||
SKIP_BUILD=false | ||
|
||
usage () { | ||
cat << EOF | ||
USAGE: `basename $0` OPTIONS | ||
Run OpenStack charms functional tests manually in a similar way to how | ||
Openstack CI (OSCI) would do it. This tool should be run from within a charm | ||
root. | ||
Not all charms use the same versions and dependencies and an attempt is made to | ||
cover this here but in some cases needs to be dealt with as a pre-requisite to | ||
running the tool. For example some charms need their tests to be run using | ||
python 3.8 and others python 3.10. Some tests might require Juju 2.9 and others | ||
Juju 3.x - the assumption in this runner is that Juju 3.x is ok to use. | ||
OPTIONS: | ||
--func-test-target | ||
Provide the name of a specific test target to run. If none provided | ||
all tests are run based on what is defined in osci.yaml i.e. will do | ||
what osci would do by default. | ||
--func-test-pr | ||
Provides similar functionality to Func-Test-Pr in commit message. Set | ||
to zaza-openstack-tests Pull Request ID. | ||
--skip-build | ||
Skip building charm if already done to save time. | ||
--skip-modify-bundle-constraints | ||
By default we modify test bundle constraints to ensure that applications | ||
have the resources they need. For example nova-compute needs to have | ||
enough capacity to boot the vms required by the tests. | ||
--help | ||
This help message. | ||
EOF | ||
} | ||
|
||
while (($# > 0)) | ||
do | ||
case "$1" in | ||
--func-test-target) | ||
FUNC_TEST_TARGET=$2 | ||
shift | ||
;; | ||
--func-test-pr) | ||
FUNC_TEST_PR=$2 | ||
shift | ||
;; | ||
--skip-modify-bundle-constraints) | ||
MODIFY_BUNDLE_CONSTRAINTS=false | ||
;; | ||
--skip-build) | ||
SKIP_BUILD=true | ||
;; | ||
--help|-h) | ||
usage | ||
exit 0 | ||
;; | ||
*) | ||
echo "ERROR: invalid input '$1'" | ||
usage | ||
exit 1 | ||
;; | ||
esac | ||
shift | ||
done | ||
|
||
set -x | ||
|
||
source ~/novarc | ||
export {,TEST_}CIDR_EXT=`openstack subnet show subnet_${OS_USERNAME}-psd-extra -c cidr -f value` | ||
FIP_MAX=$(ipcalc $CIDR_EXT| awk '$1=="HostMax:" {print $2}') | ||
FIP_MIN=$(ipcalc $CIDR_EXT| awk '$1=="HostMin:" {print $2}') | ||
FIP_MIN_ABC=${FIP_MIN%.*} | ||
FIP_MIN_D=${FIP_MIN##*.} | ||
FIP_MIN=${FIP_MIN_ABC}.$(($FIP_MIN_D + 64)) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This turns out to be gateway_ip + 64 since it's always .1 by default, and as long as this is a /25 or larger it's fine, smaller and it will be greater than the max. It's only until they get the gate fixed anyways... |
||
|
||
CIDR_OAM=`openstack subnet show subnet_${OS_USERNAME}-psd -c cidr -f value` | ||
OAM_MAX=$(ipcalc $CIDR_OAM| awk '$1=="HostMax:" {print $2}') | ||
OAM_MIN=$(ipcalc $CIDR_OAM| awk '$1=="HostMin:" {print $2}') | ||
OAM_MIN_ABC=${OAM_MIN%.*} | ||
OAM_MAX_D=${OAM_MAX##*.} | ||
# Picking last two addresses and hoping they dont get used by Neutron. | ||
export OS_VIP00=${OAM_MIN_ABC}.$(($OAM_MAX_D - 1)) | ||
export OS_VIP01=${OAM_MIN_ABC}.$(($OAM_MAX_D - 2)) | ||
|
||
# More information on config https://github.com/openstack-charmers/zaza/blob/master/doc/source/runningcharmtests.rst | ||
export {,TEST_}NET_ID=$(openstack network show net_${OS_USERNAME}-psd-extra -f value -c id) | ||
export {,TEST_}FIP_RANGE=$FIP_MIN:$FIP_MAX | ||
export {,TEST_}GATEWAY=$(openstack subnet show subnet_${OS_USERNAME}-psd-extra -c gateway_ip -f value) | ||
export {,TEST_}NAME_SERVER=91.189.91.131 | ||
export {,TEST_}CIDR_PRIV=192.168.21.0/24 | ||
#export SWIFT_IP=10.140.56.22 | ||
export TEST_MODEL_SETTINGS="image-stream=released;default-series=jammy;test-mode=true;transmit-vendor-metrics=false" | ||
# We need to set TEST_JUJU3 as well as the constraints file | ||
# Ref: https://github.com/openstack-charmers/zaza/blob/e96ab098f00951079fccb34bc38d4ae6ebb38606/setup.py#L47 | ||
export TEST_JUJU3=1 | ||
|
||
# NOTE: this should not be necessary for > juju 2.x but since we still have a need for it we add it in | ||
export TEST_ZAZA_BUG_LP1987332=1 | ||
|
||
# Some charms point to an upstream constraints file that installs python-libjuju 2.x so we need to do this to ensure we get 3.x | ||
export TEST_CONSTRAINTS_FILE=https://raw.githubusercontent.com/openstack-charmers/zaza/master/constraints-juju34.txt | ||
|
||
# 2. Build | ||
if ! $SKIP_BUILD; then | ||
sudo snap refresh charmcraft --channel $(grep charmcraft_channel osci.yaml| sed -r 's/.+:\s+(\S+)/\1/') | ||
|
||
# ensure lxc initialised | ||
lxd init --auto || true | ||
|
||
tox -re build | ||
fi | ||
|
||
# 3. Run functional tests. | ||
|
||
# If a func test pr is provided switch to that pr. | ||
if [[ -n $FUNC_TEST_PR ]]; then | ||
( | ||
[[ -d src ]] && cd src | ||
# We use the zosci-config tools to do this. | ||
[[ -d ~/zosci-config ]] || ( cd; git clone https://github.com/openstack-charmers/zosci-config; ) | ||
(cd ~/zosci-config; git checkout master; git pull;) | ||
MSG=$(echo "Func-Test-Pr: https://github.com/openstack-charmers/zaza-openstack-tests/pull/$FUNC_TEST_PR"| base64) | ||
~/zosci-config/roles/handle-func-test-pr/files/process_func_test_pr.py -f ./test-requirements.txt "$MSG" | ||
) | ||
fi | ||
|
||
if [[ -n $FUNC_TEST_TARGET ]]; then | ||
func_targets=( $FUNC_TEST_TARGET ) | ||
else | ||
func_targets=( $(python3 $(realpath $(dirname $0))/identify_charm_func_tests.py) ) | ||
fi | ||
|
||
if $MODIFY_BUNDLE_CONSTRAINTS; then | ||
( | ||
[[ -d src ]] && cd src | ||
sed -i -r '/\s+nova-compute:$/{n;s/mem=[0-9]+M/root-disk=80G mem=8G/}' tests/bundles/*.yaml | ||
) | ||
fi | ||
|
||
for target in ${func_targets[@]}; do | ||
[[ -d src ]] && pushd src || true | ||
tox -re func-target -- $target | ||
|
||
read -p "Destroy model and run next test? [ENTER]" | ||
# cleanup before next run | ||
model=`juju list-models| egrep -o "^zaza-\S+"|tr -d '*'` | ||
juju destroy-model --no-prompt $model --force --no-wait --destroy-storage | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This will fail if you have multiple matching models. Ideally it would also print the name of all the models it will destroy before it does, in case you had created another model with a name starting with zaza. You can also just tell zaza to destroy the model itself automatically by passing an argument, perhaps we should use that by default and then have an option to switch to manual cleanup behaviour for trying to debug the tests? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. do you happen to know what the argument is? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we can fix this as a future patch |
||
done | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
# Get names of test targets that OSCI would run for the given charm. Should be | ||
# run from within the charm root. | ||
# | ||
# Outputs space seperated list of target names. | ||
# | ||
import os | ||
import yaml | ||
|
||
CLASSIC_TESTS_YAML = 'tests/tests.yaml' | ||
REACTIVE_TESTS_YAML = os.path.join('src', CLASSIC_TESTS_YAML) | ||
|
||
if os.path.exists(REACTIVE_TESTS_YAML): | ||
bundles = yaml.safe_load(open(REACTIVE_TESTS_YAML)) | ||
else: | ||
bundles = yaml.safe_load(open(CLASSIC_TESTS_YAML)) | ||
|
||
targets = set(bundles['smoke_bundles'] + bundles['gate_bundles'] + | ||
bundles['dev_bundles']) | ||
|
||
print(' '.join(sorted(targets))) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you call the script without any arguments and you're not inside a charm directory it eventually fails. It should check for the current directory being a charm somehow.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i will fix this as a followup patch but have put info in the help message about how to run the tool