Skip to content
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 --cleanup-yml to provide cleanup playbooks #135

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 26 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -469,6 +469,15 @@ You must provide one of `--image-file` or `--image-name`.
applied to the snapshot if using `--use-snapshot`. If you have playbooks
which do other types of per-test setup, do not use `--setup-yml`. Just specify
them in order on the command line after all of the arguments.
* `--cleanup-yml` - You can specify one or more of your own cleanup playbooks to
use. The cleanup playbooks are run no matter if the main playbooks succeeded
or failed. This is really useful if you want to ensure some resources are
restored after the playbooks run, or if you want to gather some information
from the VM when the playbooks fail e.g. a handler fails and you want to get
the systemd journal from the VM. The variable `main_success` boolean can be
used to tell if the main playbooks succeeded or failed. The corresponding
environment variable is `LSR_QEMU_CLEANUP_YML`, which is a comma-delimited
list of playbook files.
* `--write-inventory` - Specify a file to write the generated inventory to. The
filename must be simply `inventory`, or must end in `.yml`. Examples:
`/path/to/inventory` or `/tmp/inventory.xxx.yml`. The user is responsible for
Expand Down Expand Up @@ -584,35 +593,36 @@ line is an invocation of `ansible-playbook`. The contents of the line are the
same as the command line arguments to `runqemu`. You can use almost all of the
same command-line parameters. For example:
```
--log-file /path/to/test1.log --artifacts /path/to/test1-artifacts --setup-yml /path/to/setup-snapshot.yml --tests-dir /path/to/tests -e some_ansible_var="some ansible value" --batch-id tests_test1.yml -- _setup.yml save.yml /path/to/tests/tests_test1.yml restore.yml cleanup.yml
--log-file /path/to/test2.log --artifacts /path/to/test2-artifacts --setup-yml /path/to/setup-snapshot.yml --tests-dir /path/to/tests -e some_ansible_var="some ansible value" --batch-id tests_test2.yml -- _setup.yml save.yml /path/to/tests/tests_test2.yml restore.yml cleanup.yml
--log-file /path/to/test1.log --artifacts /path/to/test1-artifacts --setup-yml /path/to/setup-snapshot.yml --tests-dir /path/to/tests -e some_ansible_var="some ansible value" --batch-id tests_test1.yml -- _setup.yml save.yml /path/to/tests/tests_test1.yml --cleanup-yml restore.yml --cleanup-yml cleanup.yml
--log-file /path/to/test2.log --artifacts /path/to/test2-artifacts --setup-yml /path/to/setup-snapshot.yml --tests-dir /path/to/tests -e some_ansible_var="some ansible value" --batch-id tests_test2.yml -- _setup.yml save.yml /path/to/tests/tests_test2.yml --cleanup-yml restore.yml --cleanup-yml cleanup.yml
...
```
if you pass this as `runqemu.py --batch-file this-file.txt` it will start a VM
and create an inventory, then run
```
ansible-playbook --inventory inventory -e some_ansible_var="some ansible value" -- _setup.yml save.yml /path/to/tests/tests_test1.yml restore.yml cleanup.yml >> /path/to/test1.log 2>&1
ansible-playbook --inventory inventory -e some_ansible_var="some ansible value" -- _setup.yml save.yml /path/to/tests/tests_test1.yml --cleanup-yml restore.yml --cleanup-yml cleanup.yml >> /path/to/test1.log 2>&1
# artifacts such as default_provisioner.log and the vm logs will go to /path/to/test1-artifacts
ansible-playbook --inventory inventory -e some_ansible_var="some ansible value" -- _setup.yml save.yml /path/to/tests/tests_test2.yml restore.yml cleanup.yml >> /path/to/test2.log 2>&1
ansible-playbook --inventory inventory -e some_ansible_var="some ansible value" -- _setup.yml save.yml /path/to/tests/tests_test2.yml --cleanup-yml restore.yml --cleanup-yml cleanup.yml >> /path/to/test2.log 2>&1
# artifacts such as default_provisioner.log and the vm logs will go to /path/to/test2-artifacts
```
then it will shutdown the VM. If you want to leave the VM running for
debugging, use `--debug` in the *last* entry in the batch file e.g.
`--debug --log-file /path/to/testN.log ...`

Only the following `runqemu` arguments are supported in batch files:
`--log-file`, `--artifacts`, `--setup-yml`, `--tests-dir`, and `--debug` (only
on last line). In addition, there is an argument used only in batch files -
`--batch-id` - which you can use as an identifier to correlate lines in your
batch file with the corresponding line in your batch report file. You can use
many/most `ansible-playbook` arguments. Arguments passed in on the `runqemu`
command line will be the default values. Specifying arguments in the batch file
will override the `runqemu` command line arguments. NOTE: With batch file, you
can use `runqemu` without providing any playbooks on the command line. However,
if you want to provide Ansible arguments on the `runqemu` command line, you will
need to add `--` to the end of the `runqemu` command line, because `runqemu`
cannot tell the difference between an Ansible argument and a playbook. Also, it
is recommended to put any Ansible arguments *after* any `runqemu` arguments.
`--log-file`, `--artifacts`, `--setup-yml`, `--tests-dir`, `--cleanup-yml`, and
`--debug` (only on last line). In addition, there is an argument used only in
batch files - `--batch-id` - which you can use as an identifier to correlate
lines in your batch file with the corresponding line in your batch report file.
You can use many/most `ansible-playbook` arguments. Arguments passed in on the
`runqemu` command line will be the default values. Specifying arguments in the
batch file will override the `runqemu` command line arguments. NOTE: With batch
file, you can use `runqemu` without providing any playbooks on the command line.
However, if you want to provide Ansible arguments on the `runqemu` command line,
you will need to add `--` to the end of the `runqemu` command line, because
`runqemu` cannot tell the difference between an Ansible argument and a playbook.
Also, it is recommended to put any Ansible arguments *after* any `runqemu`
arguments.
Example:
```
runqemu.py --log-level info --batch-file batch.txt --batch-report report.txt \
Expand Down
55 changes: 54 additions & 1 deletion src/tox_lsr/test_scripts/runqemu.py
Original file line number Diff line number Diff line change
Expand Up @@ -611,10 +611,12 @@ def internal_run_ansible_playbooks(
cwd,
wait_on_qemu=False,
log_file=None,
cleanup_yml=None,
):
"""Run ansible-playbook with the LOCK_ON_FILE if wait_on_qemu is True."""
if wait_on_qemu:
test_env["LOCK_ON_FILE"] = tempfile.NamedTemporaryFile().name
success = False
try:
with file_or_stdout(log_file) as (stdout, stderr):
subprocess.check_call( # nosec
Expand All @@ -630,7 +632,25 @@ def internal_run_ansible_playbooks(
stdout=stdout,
stderr=stderr,
)
success = True
finally:
if cleanup_yml is not None:
with file_or_stdout(log_file) as (stdout, stderr):
subprocess.check_call( # nosec
[
"ansible-playbook",
"-vv",
"--inventory=" + inventory,
"-e",
"main_success=" + str(success),
]
+ ansible_args
+ cleanup_yml,
env=test_env,
cwd=cwd,
stdout=stdout,
stderr=stderr,
)
if wait_on_qemu:
stop_qemu(test_env)

Expand Down Expand Up @@ -782,6 +802,7 @@ def handle_vault(tests_dir, ansible_args, playbooks, test_env):
def run_ansible_playbooks( # noqa: C901
image,
setup_yml,
cleanup_yml,
test_env,
debug,
image_alias,
Expand Down Expand Up @@ -873,6 +894,12 @@ def run_ansible_playbooks( # noqa: C901
if args and args.setup_yml:
local_setup_yml.extend(args.setup_yml)
local_setup_yml = [os.path.abspath(setup) for setup in local_setup_yml]
local_cleanup_yml = list(cleanup_yml)
if args and args.cleanup_yml:
local_cleanup_yml.extend(args.cleanup_yml)
local_cleanup_yml = [
os.path.abspath(cleanup) for cleanup in local_cleanup_yml
]
if args and args.tests_dir:
cwd = args.tests_dir
elif tests_dir:
Expand Down Expand Up @@ -912,6 +939,7 @@ def run_ansible_playbooks( # noqa: C901
cwd,
wait_on_qemu,
local_log_file,
local_cleanup_yml,
)
if local_log_file:
logging.info("Playbook run was successful")
Expand Down Expand Up @@ -977,6 +1005,7 @@ def install_requirements(sourcedir, collection_path, test_env, collection):
force_flag = "--force"
coll_rqf = os.path.join(sourcedir, "meta", "collection-requirements.yml")
tests_rqf = os.path.join(sourcedir, "tests", "collection-requirements.yml")
galaxy_env = {"ANSIBLE_COLLECTIONS_PATHS": collection_path}
for reqfile in [coll_rqf, tests_rqf]:
if os.path.isfile(reqfile):
ag_cmd = [
Expand All @@ -985,7 +1014,7 @@ def install_requirements(sourcedir, collection_path, test_env, collection):
"install",
"-p",
collection_path,
"-vvv",
"-vv",
"-r",
reqfile,
]
Expand All @@ -995,6 +1024,7 @@ def install_requirements(sourcedir, collection_path, test_env, collection):
ag_cmd,
stdout=sys.stdout,
stderr=sys.stderr,
env=galaxy_env,
)
test_env["ANSIBLE_COLLECTIONS_PATHS"] = collection_path
if collection_save_file:
Expand Down Expand Up @@ -1024,6 +1054,9 @@ def setup_callback_plugins(pretty, profile, profile_task_limit, test_env):
)
if not os.path.isdir(callback_plugin_dir):
os.makedirs(callback_plugin_dir)
galaxy_env = {
"ANSIBLE_COLLECTIONS_PATHS": os.environ["LSR_TOX_ENV_TMP_DIR"]
}
debug_py = os.path.join(callback_plugin_dir, "debug.py")
profile_py = os.path.join(callback_plugin_dir, "profile_tasks.py")
if (pretty and not os.path.isfile(debug_py)) or (
Expand All @@ -1041,6 +1074,7 @@ def setup_callback_plugins(pretty, profile, profile_task_limit, test_env):
],
stdout=sys.stdout,
stderr=sys.stderr,
env=galaxy_env,
)
tmp_debug_py = os.path.join(
os.environ["LSR_TOX_ENV_TMP_DIR"],
Expand Down Expand Up @@ -1102,6 +1136,7 @@ def runqemu(
use_snapshot=False,
use_ansible_log=False,
setup_yml=None,
cleanup_yml=None,
wait_on_qemu=False,
write_inventory=None,
erase_old_snapshot=False,
Expand Down Expand Up @@ -1134,6 +1169,9 @@ def runqemu(
local_setup_yml.extend(setup_yml)
if post_setup_yml:
local_setup_yml.append(post_setup_yml)
local_cleanup_yml = []
if cleanup_yml:
local_cleanup_yml.extend(cleanup_yml)
if collection_path is None and "TOX_WORK_DIR" in os.environ:
collection_path = os.environ["TOX_WORK_DIR"]
test_env = dict(image.get("env", {}))
Expand All @@ -1152,6 +1190,7 @@ def runqemu(
run_ansible_playbooks(
image,
local_setup_yml,
local_cleanup_yml,
test_env,
debug,
image_alias,
Expand Down Expand Up @@ -1310,6 +1349,17 @@ def get_arg_parser():
default=[],
help="one or more setup.yml to use in addition to config.",
)
parser.add_argument(
"--cleanup-yml",
action="append",
default=[],
help=(
"one or more cleanup.yml playbooks. These will be run even "
"if the main playbooks fail. The status will be passed to "
"the playbooks so they can take action depending on if the main "
"playbooks succeeded or failed."
),
)
parser.add_argument(
"--wait-on-qemu",
action="store_true",
Expand Down Expand Up @@ -1427,6 +1477,8 @@ def main():
args.ansible_args = ansible_args
if not args.setup_yml and "LSR_QEMU_SETUP_YML" in os.environ:
args.setup_yml = os.environ["LSR_QEMU_SETUP_YML"].split(",")
if not args.cleanup_yml and "LSR_QEMU_CLEANUP_YML" in os.environ:
args.cleanup_yml = os.environ["LSR_QEMU_CLEANUP_YML"].split(",")
logging.getLogger().setLevel(getattr(logging, args.log_level.upper()))
# either image-name or image-file must be given
if not any([args.image_name, args.image_file]) or all(
Expand Down Expand Up @@ -1459,6 +1511,7 @@ def main():
use_snapshot=args.use_snapshot,
use_ansible_log=True,
setup_yml=args.setup_yml,
cleanup_yml=args.cleanup_yml,
wait_on_qemu=args.wait_on_qemu,
write_inventory=args.write_inventory,
erase_old_snapshot=args.erase_old_snapshot,
Expand Down