Skip to content

Commit

Permalink
add ability to record and replay module for testing purpose (ansible-…
Browse files Browse the repository at this point in the history
…collections#998)

add ability to record and replay module for testing purpose

Depends-On: ansible/ansible-zuul-jobs#1619
Use lib placebo (https://pypi.org/project/placebo/) to record the API
interaction. This allow us to replay later a previous interaction offline
and cover some cases that are hard to reproduce in a CI.

Reviewed-by: Mark Chappell <None>
Reviewed-by: Gonéri Le Bouder <[email protected]>
  • Loading branch information
goneri authored Sep 8, 2022
1 parent 14a4507 commit 4b5902b
Show file tree
Hide file tree
Showing 7 changed files with 85 additions and 0 deletions.
3 changes: 3 additions & 0 deletions changelogs/fragments/placebo_record.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
---
minor_changes:
- Ability to record and replay the API interaction of a module for testing purpose. Show case the feature with an example (https://github.com/ansible-collections/amazon.aws/pull/998).
31 changes: 31 additions & 0 deletions plugins/module_utils/botocore.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,8 @@ def _boto3_conn(conn_type=None, resource=None, region=None, endpoint=None, **par
profile_name=profile,
)

enable_placebo(session)

if conn_type == 'resource':
return session.resource(resource, config=config, region_name=region, endpoint_url=endpoint, **params)
elif conn_type == 'client':
Expand Down Expand Up @@ -365,3 +367,32 @@ def normalize_boto3_result(result):
datetime objects. Boto3 is happy to be passed ISO8601 format strings.
"""
return json.loads(json.dumps(result, default=_boto3_handler))


def enable_placebo(session):
"""
Helper to record or replay offline modules for testing purpose.
"""
if "_ANSIBLE_PLACEBO_RECORD" in os.environ:
import placebo
existing_entries = os.listdir(os.environ["_ANSIBLE_PLACEBO_RECORD"])
idx = len(existing_entries)
data_path = f"{os.environ['_ANSIBLE_PLACEBO_RECORD']}/{idx}"
os.mkdir(data_path)
pill = placebo.attach(session, data_path=data_path)
pill.record()
if "_ANSIBLE_PLACEBO_REPLAY" in os.environ:
import shutil
import placebo
existing_entries = sorted([int(i) for i in os.listdir(os.environ["_ANSIBLE_PLACEBO_REPLAY"])])
idx = str(existing_entries[0])
data_path = os.environ['_ANSIBLE_PLACEBO_REPLAY'] + "/" + idx
try:
shutil.rmtree("_tmp")
except FileNotFoundError:
pass
shutil.move(data_path, "_tmp")
if len(existing_entries) == 1:
os.rmdir(os.environ["_ANSIBLE_PLACEBO_REPLAY"])
pill = placebo.attach(session, data_path="_tmp")
pill.playback()
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
module_utils_botocore
12 changes: 12 additions & 0 deletions tests/integration/targets/module_utils_botocore_recorder/main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
---
- hosts: localhost
tasks:
- name: Call aws_az_info
amazon.aws.aws_az_info:
register: result
- name: Get called information
amazon.aws.aws_caller_info:
register: result
- assert:
that:
- lookup('ansible.builtin.env', '_ANSIBLE_PLACEBO_RECORD') or (lookup('ansible.builtin.env', '_ANSIBLE_PLACEBO_REPLAY') and result.user_id == "AWZBREIZHEOMABRONIFVGFS6GH")
23 changes: 23 additions & 0 deletions tests/integration/targets/module_utils_botocore_recorder/record.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#!/usr/bin/env bash
#
set -eux

if [ -d recording ]; then
echo "Please check and remove the 'recording' directory."
exit 1
fi
if [ -v ANSIBLE_TEST_PYTHON_VERSION ]; then
echo "Please call ./runme.sh directly without ansible-test"
exit 1
fi
export _ANSIBLE_PLACEBO_RECORD=recording

mkdir recording
ansible-playbook main.yml -vvv
account_id=$(aws sts get-caller-identity --query "Account" --output text)
user_id=$(aws sts get-caller-identity --query "UserId" --output text)
find recording -type f -exec sed -i "s,$account_id,1111111111111,g" "{}" \;
find recording -type f -exec sed -i "s,$user_id,AWZBREIZHEOMABRONIFVGFS6GH,g" "{}" \;
find recording -type f -exec sed -i "s,$USER,george,g" "{}" \;
tar cfzv recording.tar.gz recording
rm -r recording
Binary file not shown.
15 changes: 15 additions & 0 deletions tests/integration/targets/module_utils_botocore_recorder/runme.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#!/usr/bin/env bash
#

set -eux

export ANSIBLE_ROLES_PATH=../


tar xfzv recording.tar.gz
export _ANSIBLE_PLACEBO_REPLAY=${PWD}/recording
export AWS_ACCESS_KEY_ID=disabled
export AWS_SECRET_ACCESS_KEY=disabled
export AWS_SESSION_TOKEN=disabled
export AWS_DEFAULT_REGION=us-east-2
ansible-playbook main.yml -vvv

0 comments on commit 4b5902b

Please sign in to comment.