Skip to content

Commit e11a905

Browse files
committed
tests: add functional tests for integrated hooks
1 parent 37422fd commit e11a905

File tree

5 files changed

+158
-3
lines changed

5 files changed

+158
-3
lines changed

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
"mock~=2.0",
2828
"moto~=1.3.7",
2929
"testfixtures~=4.10.0",
30-
"flake8-future-import",
30+
"flake8-future-import"
3131
]
3232

3333
scripts = [

stacker/tests/factories.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,6 @@ def __init__(self, outputs=None, region=None, profile=None):
3939
"Outputs": stack_outputs,
4040
"StackStatus": "CREATED"
4141
}
42-
self._sessions = {}
4342

4443
def get_stack(self, stack_name, **kwargs):
4544
try:
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
AWSTemplateFormatVersion: 2010-09-09
2+
Resources:
3+
Bucket:
4+
Type: AWS::S3::Bucket
5+
Properties:
6+
BucketName: {{ variables.BucketName }}
7+
AccessControl: Private
8+
Outputs:
9+
BucketName:
10+
Value: !Ref Bucket

tests/test_helper.bash

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,23 @@ assert() {
3636

3737
# Checks that the given line is in $output.
3838
assert_has_line() {
39-
echo "$output" | grep "$@" 1>/dev/null
39+
echo "$output" | grep -q "$@"
40+
}
41+
42+
assert_has_lines_in_order() {
43+
local search_line
44+
read -r search_line || return $?
45+
46+
for line in "${lines[@]}"; do
47+
if grep -q "$@" "$search_line" <<< "$line"; then
48+
if ! read -r search_line && [ -z "$search_line" ]; then
49+
return 0
50+
fi
51+
fi
52+
done
53+
54+
echo "Error: did not match line in correct order: '$search_line'" >&2
55+
return 1
4056
}
4157

4258
# This helper wraps "stacker" with bats' "run" and also outputs debug
Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
#!/usr/bin/env bats
2+
3+
# This test will exercise the integration of hooks among the execution of stacks
4+
# making use of the fact that S3 buckets cannot be deleted when not empty.
5+
# The test will create the bucket and populate it during build, and erase the
6+
# objects before destruction. If the hooks are not executed in the proper order,
7+
# the destruction will fail, and so will the tst.
8+
9+
load ../test_helper
10+
11+
@test "stacker build - integrated hooks" {
12+
needs_aws
13+
14+
config() {
15+
echo "namespace: ${STACKER_NAMESPACE}-integrated-hooks"
16+
cat <<'EOF'
17+
stacks:
18+
- name: bucket
19+
profile: stacker
20+
template_path: fixtures/blueprints/bucket.yaml.j2
21+
variables:
22+
BucketName: "stacker-${envvar STACKER_NAMESPACE}-integrated-hooks-${awsparam AccountId}"
23+
24+
build_hooks:
25+
- name: write-hello
26+
path: stacker.hooks.command.run_command
27+
args:
28+
command: 'echo "Hello from Stacker!" > /tmp/hello.txt'
29+
shell: true
30+
31+
- name: send-hello
32+
path: stacker.hooks.command.run_command
33+
requires:
34+
- write-hello
35+
args:
36+
command: 'aws s3 cp /tmp/hello.txt "s3://$BUCKET/hello.txt"'
37+
shell: true
38+
env:
39+
BUCKET: "${output bucket::BucketName}"
40+
AWS_PROFILE: stacker
41+
42+
- name: send-world
43+
path: stacker.hooks.command.run_command
44+
requires:
45+
- send-hello
46+
args:
47+
command: 'aws s3 cp "s3://$BUCKET/hello.txt" "s3://$BUCKET/world.txt"'
48+
shell: true
49+
env:
50+
BUCKET: "${output bucket::BucketName}"
51+
AWS_PROFILE: stacker
52+
53+
destroy_hooks:
54+
- name: remove-world
55+
path: stacker.hooks.command.run_command
56+
args:
57+
command: 'aws s3 rm "s3://$BUCKET/world.txt"'
58+
shell: true
59+
env:
60+
BUCKET: "${output bucket::BucketName}"
61+
AWS_PROFILE: stacker
62+
63+
- name: remove-hello
64+
path: stacker.hooks.command.run_command
65+
required_by:
66+
- remove-world
67+
args:
68+
command: 'aws s3 rm "s3://$BUCKET/hello.txt"'
69+
shell: true
70+
env:
71+
BUCKET: "${output bucket::BucketName}"
72+
AWS_PROFILE: stacker
73+
74+
- name: clean-hello
75+
path: stacker.hooks.command.run_command
76+
required_by:
77+
- bucket
78+
args:
79+
command: [rm, -f, /tmp/hello.txt]
80+
EOF
81+
}
82+
83+
teardown() {
84+
stacker destroy --force <(config)
85+
}
86+
87+
stacker build -t --recreate-failed <(config)
88+
assert "$status" -eq 0
89+
assert_has_line "Using default AWS provider mode"
90+
assert_has_lines_in_order -E <<'EOF'
91+
pre_build_hooks: complete
92+
write-hello: complete
93+
bucket: submitted \(creating new stack\)
94+
bucket: complete \(creating new stack\)
95+
upload: [^ ]*/hello.txt to s3://[^ ]*/hello.txt
96+
send-hello: complete
97+
copy: s3://[^ ]*/hello.txt to s3://[^ ]*/world.txt
98+
send-world: complete
99+
post_build_hooks: complete
100+
EOF
101+
102+
stacker destroy --force <(config)
103+
assert "$status" -eq 0
104+
assert_has_line "Using default AWS provider mode"
105+
assert_has_lines_in_order -E <<'EOF'
106+
pre_destroy_hooks: complete
107+
delete: s3://[^ ]*/world.txt
108+
remove-world: complete
109+
delete: s3://[^ ]*/hello.txt
110+
remove-hello: complete
111+
bucket: submitted \(submitted for destruction\)
112+
bucket: complete \(stack destroyed\)
113+
clean-hello: complete
114+
post_destroy_hooks: complete
115+
EOF
116+
assert ! -e /tmp/hello.txt
117+
118+
# Check that hooks that use lookups from stacks that do not exist anymore are
119+
# not run
120+
stacker destroy --force <(config)
121+
assert "$status" -eq 0
122+
assert_has_lines_in_order <<'EOF'
123+
pre_destroy_hooks: complete
124+
remove-world: skipped
125+
remove-hello: skipped
126+
bucket: skipped
127+
clean-hello: complete
128+
post_destroy_hooks: complete
129+
EOF
130+
}

0 commit comments

Comments
 (0)