-
Notifications
You must be signed in to change notification settings - Fork 34
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
integration-test: add test scenarios #32
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,59 @@ | ||
#!/usr/bin/env bats | ||
|
||
load test_helper | ||
|
||
@test "meta: docker is installed" { | ||
run docker version | ||
echo "$output">&2 | ||
[ "$status" -eq 0 ] | ||
} | ||
|
||
@test "meta: can build the test container image" { | ||
run build_docker_image | ||
echo "$output" | ||
[ "$status" -eq 0 ] | ||
} | ||
|
||
@test "meta: can start the test container" { | ||
run in_tmp_container fake-waagent | ||
echo "$output" | ||
[ "$output" = "Usage: /sbin/fake-waagent <handlerCommand>" ] | ||
[ "$status" -eq 1 ] | ||
} | ||
|
||
@test "meta: can create vm private/public keys" { | ||
run mk_certs | ||
echo "$output" | ||
[ "$status" -eq 0 ] | ||
|
||
thumbprint="$output" | ||
[ -f "$certs_dir/$thumbprint.prv" ] | ||
[ -f "$certs_dir/$thumbprint.crt" ] | ||
} | ||
|
||
@test "meta: encrypt a protected settings" { | ||
run mk_certs | ||
echo "$output" | ||
[ "$status" -eq 0 ] | ||
|
||
tp="$output" | ||
run encrypt_settings "$tp" "`seq 0 1000`" | ||
echo "$output" | ||
[ "$status" -eq 0 ] | ||
[ -n "$output" ] | ||
} | ||
|
||
@test "meta: can create a .settings json with public/protected config" { | ||
tp="$mk_certs" | ||
run mk_settings_json '' '{"commandToExecute":"touch /a.txt"}' "$tp" | ||
echo "$output" | ||
[ "$status" -eq 0 ] | ||
} | ||
|
||
@test "meta: can create a temporary file" { | ||
run save_tmp_file "foobar" | ||
echo "$output" | ||
[ "$status" -eq 0 ] | ||
[ -f "$output" ] | ||
[[ "$(cat "$output")" == "foobar" ]] | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,120 @@ | ||
#!/usr/bin/env bats | ||
|
||
load test_helper | ||
|
||
setup(){ | ||
build_docker_image | ||
} | ||
|
||
teardown(){ | ||
rm -rf "$certs_dir" | ||
} | ||
|
||
@test "handler command: install - creates the data dir" { | ||
run in_container fake-waagent install | ||
echo "$output" | ||
[ "$status" -eq 0 ] | ||
[[ "$output" = *event=installed* ]] | ||
|
||
diff="$(container_diff)" | ||
echo "$diff" | ||
[[ "$diff" = *"A /var/lib/azure/custom-script"* ]] | ||
} | ||
|
||
@test "handler command: enable - can process empty settings, but fails" { | ||
mk_container sh -c "fake-waagent install && fake-waagent enable" | ||
push_settings '' '' | ||
|
||
run start_container | ||
echo "$output" | ||
[ "$status" -eq 1 ] | ||
[[ "$output" == *"invalid configuration: 'commandToExecute' is not specified"* ]] | ||
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. How valuable is it to verify the error message in detail at this stage. I feel like you have numerous tests to catch this already, so why do it again. Is error code sufficient? 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. @boumenot maybe I should reduce to |
||
|
||
# Validate .status file says enable failed | ||
diff="$(container_diff)"; echo "$diff" | ||
[[ "$diff" = *"A /var/lib/waagent/Extension/status/0.status"* ]] | ||
status_file="$(container_read_file /var/lib/waagent/Extension/status/0.status)" | ||
echo "$status_file"; [[ "$status_file" = *'Enable failed'* ]] | ||
} | ||
|
||
@test "handler command: enable - validates json schema" { | ||
mk_container sh -c "fake-waagent install && fake-waagent enable" | ||
push_settings '{"badElement":null, "commandToExecute":"date"}' '' | ||
|
||
run start_container | ||
echo "$output" | ||
[ "$status" -eq 1 ] | ||
[[ "$output" == *"json validation error: invalid public settings JSON: badElement"* ]] | ||
} | ||
|
||
|
||
@test "handler command: enable - captures stdout/stderr into file" { | ||
mk_container sh -c "fake-waagent install && fake-waagent enable" | ||
push_settings ' | ||
{ | ||
"commandToExecute": "echo HelloStdout>&1; echo HelloStderr>&2" | ||
}' '' | ||
run start_container | ||
echo "$output" | ||
[ "$status" -eq 0 ] | ||
|
||
# Validate contents of stdout/stderr files | ||
stdout="$(container_read_file /var/lib/azure/custom-script/download/0/stdout)" | ||
echo "stdout=$stdout" && [[ "$stdout" = "HelloStdout" ]] | ||
stderr="$(container_read_file /var/lib/azure/custom-script/download/0/stderr)" | ||
echo "stderr=$stderr" && [[ "$stderr" = "HelloStderr" ]] | ||
} | ||
|
||
@test "handler command: enable - doesn't process the same sequence number again" { | ||
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. I like this one. |
||
mk_container sh -c \ | ||
"fake-waagent install && fake-waagent enable && fake-waagent enable" | ||
push_settings '{"commandToExecute": "date"}' '' | ||
|
||
run start_container | ||
echo "$output" | ||
[ "$status" -eq 0 ] | ||
enable_count="$(echo "$output" | grep -c 'event=enabled')" | ||
echo "Enable count=$enable_count" | ||
[ "$enable_count" -eq 1 ] | ||
[[ "$output" == *"this script configuration is already processed, will not run again"* ]] # not processed again | ||
} | ||
|
||
@test "handler command: enable - parses protected settings" { | ||
mk_container sh -c "fake-waagent install && fake-waagent enable" | ||
push_settings '' '{"commandToExecute":"touch /a.txt"}' | ||
run start_container | ||
echo "$output" | ||
[ "$status" -eq 0 ] | ||
|
||
diff="$(container_diff)"; echo "$diff" | ||
[[ "$diff" == *"A /a.txt"* ]] | ||
} | ||
|
||
@test "handler command: enable - downloads files" { | ||
mk_container sh -c "fake-waagent install && fake-waagent enable" | ||
# download an external script and run it | ||
push_settings '{ | ||
"fileUris": [ | ||
"https://gist.github.com/anonymous/8c83af2923ec8dd4a92309594a6c90d7/raw/f26c2cbf68e22d42f703b78f8a4562c5c8e43ba7/script.sh" | ||
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. How long do gists last? Can you just check this into the repo instead? 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. @boumenot until they shut down the gist service (or change its url schema), I guess we can do what you said. |
||
], | ||
"commandToExecute":"./script.sh" | ||
}' | ||
run start_container | ||
echo "$output" | ||
[ "$status" -eq 0 ] | ||
|
||
diff="$(container_diff)"; echo "$diff" | ||
[[ "$diff" == *"A /var/lib/azure/custom-script/download/0/script.sh"* ]] # file downloaded | ||
[[ "$diff" == *"A /b.txt"* ]] # created by script.sh | ||
} | ||
|
||
@test "handler command: uninstall - deletes the data dir" { | ||
run in_container sh -c \ | ||
"fake-waagent install && fake-waagent uninstall" | ||
echo "$output" | ||
[ "$status" -eq 0 ] | ||
|
||
echo "$output"; [ "$status" -eq 0 ] | ||
diff="$(container_diff)" && echo "$diff" | ||
[[ "$diff" != */var/lib/azure/custom-script* ]] | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,126 @@ | ||
# Test helpers for BATS tests | ||
|
||
IMAGE=custom-script | ||
DOCKERFILE=test.Dockerfile | ||
TEST_CONTAINER=test | ||
|
||
certs_dir="$BATS_TEST_DIRNAME/certs" | ||
|
||
build_docker_image() { | ||
echo "Building test image..." | ||
docker build -q -f $DOCKERFILE -t $IMAGE . 1>&2 | ||
} | ||
|
||
in_tmp_container() { | ||
docker run --rm $IMAGE "$@" | ||
} | ||
|
||
rm_container() { | ||
docker rm -f $TEST_CONTAINER &>/dev/null && \ | ||
echo "Deleted test container." || true | ||
} | ||
|
||
mk_container() { | ||
rm_container && echo "Creating test container with commands: $@">&2 && \ | ||
docker create --name=$TEST_CONTAINER $IMAGE "$@" 1>/dev/null | ||
} | ||
|
||
in_container() { | ||
set -e | ||
rm_container | ||
mk_container "$@" | ||
echo "Starting test container...">&2 | ||
start_container | ||
} | ||
|
||
start_container() { | ||
docker start --attach $TEST_CONTAINER | ||
} | ||
|
||
container_diff() { | ||
docker diff $TEST_CONTAINER | ||
} | ||
|
||
container_read_file() { # reads the file at container path $1 | ||
set -eo pipefail | ||
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. Why is this scoped to this method? 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. I believe setting -e globally has issues with bats sstephenson/bats#171 |
||
docker cp $TEST_CONTAINER:"$1" - | tar x --to-stdout | ||
} | ||
|
||
mk_certs() { # creates certs/{THUMBPRINT}.(crt|key) files under ./certs/ and prints THUMBPRINT | ||
set -eo pipefail | ||
mkdir -p "$certs_dir" && cd "$certs_dir" && rm -f "$certs_dir/*" | ||
openssl req -x509 -newkey rsa:2048 -keyout key.pem -out cert.pem -days 365 -nodes -batch &>/dev/null | ||
thumbprint=$(openssl x509 -in cert.pem -fingerprint -noout| sed 's/.*=//g' | sed 's/://g') | ||
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. 😁 The variable is called thumbprint, but the command is fingerprint. You've been here too long! 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. @boumenot I'm just preserving the terminology of waagent (authored by people stayed here too long as well) |
||
mv cert.pem $thumbprint.crt && \ | ||
mv key.pem $thumbprint.prv | ||
echo $thumbprint | ||
} | ||
|
||
push_certs() { # pushes certs/{$1}.(crt|key) files to container | ||
set -e | ||
docker cp "$certs_dir/$1.crt" $TEST_CONTAINER:/var/lib/waagent/ | ||
docker cp "$certs_dir/$1.prv" $TEST_CONTAINER:/var/lib/waagent/ | ||
echo "Pushed certs to container.">&2 | ||
} | ||
|
||
encrypt_settings(){ # encrypts the message ($2) with the key with given cert thumbprint ($1) | ||
set -eo pipefail | ||
tp="$1"; msg="$2" | ||
echo "$(openssl smime -inkey "$certs_dir/$tp.prv" -encrypt -outform DER "$certs_dir/$tp.crt" < <(echo "$msg") | base64 -w0)" | ||
} | ||
|
||
mk_settings_json() { # turns json public settings ($1) and ($2) into a json encrypted with "$3".(crt|prv) | ||
set -e | ||
pub="$1" | ||
prot="$2" | ||
cert_tp="$3" | ||
if [ -z "$pub" ]; then pub="null"; fi | ||
if [ -n "$prot" ]; then | ||
prot="\"$(encrypt_settings "$cert_tp" "$prot")\"" | ||
else | ||
cert_tp="null" | ||
prot="null" | ||
fi | ||
|
||
cat <<-EOF | ||
{ | ||
"runtimeSettings": [ | ||
{ | ||
"handlerSettings": { | ||
"protectedSettingsCertThumbprint": "$cert_tp", | ||
"publicSettings": $pub, | ||
"protectedSettings": $prot | ||
} | ||
} | ||
] | ||
} | ||
EOF | ||
} | ||
|
||
push_settings() { # creates and copies 0.settings file with given public settings ($1) and ($2) values. | ||
set -e | ||
|
||
if [ -n "$2" ]; then | ||
cert_tp="$(mk_certs)" | ||
push_certs "$cert_tp" | ||
fi | ||
|
||
cfg_file="$(save_tmp_file "$(mk_settings_json "$1" "$2" "$cert_tp") ")" | ||
echo ".settings: $(cat "$cfg_file")" >&2 | ||
copy_config "$cfg_file" | ||
echo ".settings file pushed to container." >&2 | ||
} | ||
|
||
save_tmp_file(){ # saves $1 into a temporary file and returns its path | ||
fp="$(mktemp)" | ||
touch "$fp" | ||
cat <<< "$1" > "$fp" | ||
echo "$fp" | ||
} | ||
|
||
copy_config() { # places specified settings file ($1) into container as 0.settings | ||
set -e | ||
echo "Copying $1 to container as 0.settings." >&2 | ||
docker cp "$1" "$TEST_CONTAINER:/var/lib/waagent/Extension/config/0.settings" | ||
echo "Copied settings into container.">&2 | ||
} |
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.
Should you check status before running echo? Won't that corrupt "run docker version", which I assume is the intent.
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.
@boumenot nope
$status
contains the exitcode of the command that is last executed by prefixrun ...
thanks to bats. I type output here because if it fails on the[ "$status" -eq 0 ]
status line, we'll see the output of the command and tell why it failed.