Simplify the Seriatim role
This commit is contained in:
@@ -2,197 +2,26 @@
|
||||
set -euo pipefail
|
||||
|
||||
repository_root=$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)
|
||||
workspace_venv=$(cd "$repository_root/../.venv" && pwd)
|
||||
workspace_venv="$repository_root/../.venv"
|
||||
test_tmp=$(mktemp -d)
|
||||
trap 'rm -rf -- "$test_tmp"' EXIT
|
||||
|
||||
export ANSIBLE_COLLECTIONS_PATH="$repository_root/.ansible/collections"
|
||||
export ANSIBLE_COLLECTIONS_PATH="$test_tmp/collections"
|
||||
export ANSIBLE_ROLES_PATH="$(dirname "$repository_root")"
|
||||
|
||||
playbook="$workspace_venv/bin/ansible-playbook"
|
||||
inventory="$repository_root/tests/inventory"
|
||||
converge="$repository_root/tests/converge.yml"
|
||||
|
||||
run_converge() {
|
||||
"$playbook" -i "$inventory" "$converge" "$@"
|
||||
}
|
||||
|
||||
restore_default() {
|
||||
run_converge >/dev/null 2>&1
|
||||
}
|
||||
|
||||
cleanup() {
|
||||
exit_status=$?
|
||||
restore_default || true
|
||||
sudo rm -rf -- "$test_tmp"
|
||||
exit "$exit_status"
|
||||
}
|
||||
trap cleanup EXIT
|
||||
|
||||
require_clean_recap() {
|
||||
recap_file=$1
|
||||
grep -Eq 'changed=0 .*failed=0' "$recap_file"
|
||||
}
|
||||
|
||||
require_changed_recap() {
|
||||
recap_file=$1
|
||||
grep -Eq 'changed=[1-9][0-9]* .*failed=0' "$recap_file"
|
||||
}
|
||||
|
||||
binary_digest() {
|
||||
sha256sum /usr/local/bin/seriatim | awk '{print $1}'
|
||||
}
|
||||
|
||||
state_digest() {
|
||||
sudo sha256sum /usr/local/src/seriatim.ansible-build-state/* |
|
||||
sha256sum | awk '{print $1}'
|
||||
}
|
||||
verify="$repository_root/tests/verify.yml"
|
||||
|
||||
cd "$repository_root"
|
||||
"$workspace_venv/bin/ansible-galaxy" collection install \
|
||||
-p .ansible/collections -r collections/requirements.yml
|
||||
"$playbook" -i "$inventory" "$converge" --syntax-check
|
||||
"$workspace_venv/bin/ansible-lint" .
|
||||
-r collections/requirements.yml \
|
||||
-p "$ANSIBLE_COLLECTIONS_PATH"
|
||||
"$workspace_venv/bin/ansible-playbook" -i "$inventory" --syntax-check "$converge"
|
||||
"$workspace_venv/bin/ansible-lint" "$converge" "$verify"
|
||||
"$workspace_venv/bin/ansible-playbook" -i "$inventory" "$converge"
|
||||
"$workspace_venv/bin/ansible-playbook" -i "$inventory" "$verify"
|
||||
|
||||
run_converge
|
||||
"$playbook" -i "$inventory" tests/verify.yml
|
||||
run_converge | tee "$test_tmp/default-repeat.log"
|
||||
require_clean_recap "$test_tmp/default-repeat.log"
|
||||
|
||||
printf '%s\n' 'corrupt build inputs' |
|
||||
sudo tee /usr/local/src/seriatim.ansible-build-state/build-inputs.json >/dev/null
|
||||
run_converge | tee "$test_tmp/build-input-repair.log"
|
||||
require_changed_recap "$test_tmp/build-input-repair.log"
|
||||
"$playbook" -i "$inventory" tests/verify.yml
|
||||
run_converge | tee "$test_tmp/build-input-repair-repeat.log"
|
||||
require_clean_recap "$test_tmp/build-input-repair-repeat.log"
|
||||
|
||||
sudo chown "$(id -u):$(id -g)" /usr/local/bin/seriatim
|
||||
sudo chmod 0777 /usr/local/bin/seriatim
|
||||
sudo chown "$(id -u):$(id -g)" /usr/local/src/seriatim.ansible-build-state
|
||||
sudo chmod 0700 /usr/local/src/seriatim.ansible-build-state
|
||||
sudo chown "$(id -u):$(id -g)" /usr/local/src/seriatim.ansible-build-state/*
|
||||
sudo chmod 0600 /usr/local/src/seriatim.ansible-build-state/*
|
||||
run_converge | tee "$test_tmp/metadata-repair.log"
|
||||
require_changed_recap "$test_tmp/metadata-repair.log"
|
||||
"$playbook" -i "$inventory" tests/verify.yml
|
||||
run_converge | tee "$test_tmp/metadata-repair-repeat.log"
|
||||
require_clean_recap "$test_tmp/metadata-repair-repeat.log"
|
||||
|
||||
custom_binary="$test_tmp/missing-binary-parent/seriatim"
|
||||
custom_state="$test_tmp/custom-build-state"
|
||||
test ! -e "$(dirname "$custom_binary")"
|
||||
run_converge \
|
||||
-e "seriatim_binary_path=$custom_binary" \
|
||||
-e "seriatim_build_state_dir=$custom_state" |
|
||||
tee "$test_tmp/custom-path.log"
|
||||
require_changed_recap "$test_tmp/custom-path.log"
|
||||
test "$($custom_binary --version)" = 'seriatim version v1.5.0'
|
||||
test "$(stat -c '%U:%G %a' "$(dirname "$custom_binary")")" = 'root:root 755'
|
||||
run_converge \
|
||||
-e "seriatim_binary_path=$custom_binary" \
|
||||
-e "seriatim_build_state_dir=$custom_state" |
|
||||
tee "$test_tmp/custom-path-repeat.log"
|
||||
require_clean_recap "$test_tmp/custom-path-repeat.log"
|
||||
|
||||
sudo rm -rf -- "$custom_state"
|
||||
sudo install -o root -g root -m 0644 /dev/null "$custom_state"
|
||||
run_converge \
|
||||
-e "seriatim_binary_path=$custom_binary" \
|
||||
-e "seriatim_build_state_dir=$custom_state" |
|
||||
tee "$test_tmp/state-file-repair.log"
|
||||
require_changed_recap "$test_tmp/state-file-repair.log"
|
||||
test -d "$custom_state"
|
||||
test ! -L "$custom_state"
|
||||
run_converge \
|
||||
-e "seriatim_binary_path=$custom_binary" \
|
||||
-e "seriatim_build_state_dir=$custom_state" |
|
||||
tee "$test_tmp/state-file-repair-repeat.log"
|
||||
require_clean_recap "$test_tmp/state-file-repair-repeat.log"
|
||||
|
||||
redirected_state="$test_tmp/redirected-build-state"
|
||||
sudo rm -rf -- "$custom_state"
|
||||
sudo install -d -o root -g root -m 0755 "$redirected_state"
|
||||
sudo ln -s "$redirected_state" "$custom_state"
|
||||
run_converge \
|
||||
-e "seriatim_binary_path=$custom_binary" \
|
||||
-e "seriatim_build_state_dir=$custom_state" |
|
||||
tee "$test_tmp/state-link-repair.log"
|
||||
require_changed_recap "$test_tmp/state-link-repair.log"
|
||||
test -d "$custom_state"
|
||||
test ! -L "$custom_state"
|
||||
test -z "$(find "$redirected_state" -mindepth 1 -maxdepth 1 -print -quit)"
|
||||
run_converge \
|
||||
-e "seriatim_binary_path=$custom_binary" \
|
||||
-e "seriatim_build_state_dir=$custom_state" |
|
||||
tee "$test_tmp/state-link-repair-repeat.log"
|
||||
require_clean_recap "$test_tmp/state-link-repair-repeat.log"
|
||||
|
||||
baseline_binary=$(binary_digest)
|
||||
baseline_state=$(state_digest)
|
||||
for scenario in \
|
||||
'{"test_distribution":"Debian","test_distribution_version":"26.04","test_architecture":"x86_64"}' \
|
||||
'{"test_distribution":"Ubuntu","test_distribution_version":"24.04","test_architecture":"x86_64"}' \
|
||||
'{"test_distribution":"Ubuntu","test_distribution_version":"26.04","test_architecture":"riscv64"}'
|
||||
do
|
||||
if "$playbook" -i "$inventory" tests/unsupported.yml -e "$scenario"; then
|
||||
echo "unsupported platform scenario unexpectedly succeeded: $scenario" >&2
|
||||
exit 1
|
||||
fi
|
||||
test "$(binary_digest)" = "$baseline_binary"
|
||||
test "$(state_digest)" = "$baseline_state"
|
||||
done
|
||||
|
||||
sudo touch /usr/local/src/seriatim/ansible-untracked-test
|
||||
sudo sed -i '1s/^/ansible-test-change\n/' /usr/local/src/seriatim/go.mod
|
||||
run_converge
|
||||
"$playbook" -i "$inventory" tests/verify.yml
|
||||
|
||||
compiler_wrapper="$test_tmp/go-version-wrapper"
|
||||
sed 's|@GO@|/snap/bin/go|' >"$compiler_wrapper" <<'WRAPPER'
|
||||
#!/bin/sh
|
||||
if [ "${1:-}" = version ]; then
|
||||
echo 'go version go1.26.99 linux/amd64'
|
||||
exit 0
|
||||
fi
|
||||
exec @GO@ "$@"
|
||||
WRAPPER
|
||||
chmod 0755 "$compiler_wrapper"
|
||||
|
||||
run_converge -e "seriatim_go_binary=$compiler_wrapper" |
|
||||
tee "$test_tmp/compiler-change.log"
|
||||
require_changed_recap "$test_tmp/compiler-change.log"
|
||||
run_converge -e "seriatim_go_binary=$compiler_wrapper" |
|
||||
tee "$test_tmp/compiler-repeat.log"
|
||||
require_clean_recap "$test_tmp/compiler-repeat.log"
|
||||
run_converge | tee "$test_tmp/compiler-restore.log"
|
||||
require_changed_recap "$test_tmp/compiler-restore.log"
|
||||
run_converge | tee "$test_tmp/compiler-restored-repeat.log"
|
||||
require_clean_recap "$test_tmp/compiler-restored-repeat.log"
|
||||
|
||||
failure_wrapper="$test_tmp/go-failure-wrapper"
|
||||
sed 's|@GO@|/snap/bin/go|' >"$failure_wrapper" <<'WRAPPER'
|
||||
#!/bin/sh
|
||||
if [ "${1:-}" = version ]; then
|
||||
exec @GO@ version
|
||||
fi
|
||||
echo 'deliberate integration-test build failure' >&2
|
||||
exit 42
|
||||
WRAPPER
|
||||
chmod 0755 "$failure_wrapper"
|
||||
|
||||
baseline_binary=$(binary_digest)
|
||||
baseline_state=$(state_digest)
|
||||
if run_converge -e "seriatim_go_binary=$failure_wrapper"; then
|
||||
echo 'deliberate build failure unexpectedly succeeded' >&2
|
||||
exit 1
|
||||
fi
|
||||
test "$(binary_digest)" = "$baseline_binary"
|
||||
test "$(state_digest)" = "$baseline_state"
|
||||
test "$(/usr/local/bin/seriatim --version)" = 'seriatim version v1.5.0'
|
||||
|
||||
run_converge | tee "$test_tmp/final-restore.log"
|
||||
require_clean_recap "$test_tmp/final-restore.log"
|
||||
"$playbook" -i "$inventory" tests/verify.yml
|
||||
|
||||
trap - EXIT
|
||||
sudo rm -rf -- "$test_tmp"
|
||||
repeat_output="$test_tmp/repeat.log"
|
||||
"$workspace_venv/bin/ansible-playbook" -i "$inventory" "$converge" | tee "$repeat_output"
|
||||
grep -Eq 'changed=0 .*failed=0' "$repeat_output"
|
||||
|
||||
138
tests/verify.yml
138
tests/verify.yml
@@ -1,111 +1,73 @@
|
||||
---
|
||||
- name: Verify Seriatim installation
|
||||
hosts: seriatim
|
||||
gather_facts: true
|
||||
- name: Verify the Seriatim installation
|
||||
hosts: localhost
|
||||
connection: local
|
||||
gather_facts: false
|
||||
become: true
|
||||
vars:
|
||||
seriatim_expected_commit: 0fc92f364316c874d366b00cdc884a33e1900b25
|
||||
seriatim_expected_version: v1.5.0
|
||||
seriatim_verify_source_dir: /usr/local/src/seriatim
|
||||
seriatim_verify_binary_path: /usr/local/bin/seriatim
|
||||
seriatim_verify_state_dir: /usr/local/src/seriatim.ansible-build-state
|
||||
seriatim_source_dir: /usr/local/src/seriatim
|
||||
seriatim_binary_path: /usr/local/bin/seriatim
|
||||
tasks:
|
||||
- name: Inspect Seriatim source directory
|
||||
- name: Inspect the source directory
|
||||
ansible.builtin.stat:
|
||||
path: "{{ seriatim_verify_source_dir }}"
|
||||
register: seriatim_verify_source_stat
|
||||
path: "{{ seriatim_source_dir }}"
|
||||
register: seriatim_source
|
||||
|
||||
- name: Inspect installed Seriatim binary
|
||||
ansible.builtin.stat:
|
||||
path: "{{ seriatim_verify_binary_path }}"
|
||||
checksum_algorithm: sha256
|
||||
register: seriatim_verify_binary_stat
|
||||
|
||||
- name: Inspect Seriatim build state directory
|
||||
ansible.builtin.stat:
|
||||
path: "{{ seriatim_verify_state_dir }}"
|
||||
register: seriatim_verify_state_stat
|
||||
|
||||
- name: Inspect Seriatim build state files
|
||||
ansible.builtin.stat:
|
||||
path: "{{ seriatim_verify_state_dir }}/{{ item }}"
|
||||
loop:
|
||||
- build-inputs.json
|
||||
- fingerprint.sha256
|
||||
- binary.sha256
|
||||
register: seriatim_verify_state_file_stats
|
||||
|
||||
- name: Resolve installed Seriatim source commit
|
||||
- name: Find incorrectly owned source entries
|
||||
ansible.builtin.command:
|
||||
argv:
|
||||
- /usr/bin/git
|
||||
- find
|
||||
- "{{ seriatim_source_dir }}"
|
||||
- (
|
||||
- -not
|
||||
- -user
|
||||
- root
|
||||
- -or
|
||||
- -not
|
||||
- -group
|
||||
- root
|
||||
- )
|
||||
- -print
|
||||
- -quit
|
||||
register: seriatim_source_ownership
|
||||
changed_when: false
|
||||
|
||||
- name: Read the selected source commit
|
||||
ansible.builtin.command:
|
||||
argv:
|
||||
- git
|
||||
- -C
|
||||
- "{{ seriatim_verify_source_dir }}"
|
||||
- "{{ seriatim_source_dir }}"
|
||||
- rev-parse
|
||||
- HEAD
|
||||
register: seriatim_verify_commit
|
||||
register: seriatim_source_commit
|
||||
changed_when: false
|
||||
|
||||
- name: Inspect installed Seriatim source cleanliness
|
||||
ansible.builtin.command:
|
||||
argv:
|
||||
- /usr/bin/git
|
||||
- -C
|
||||
- "{{ seriatim_verify_source_dir }}"
|
||||
- status
|
||||
- --porcelain
|
||||
- --untracked-files=all
|
||||
- --ignored
|
||||
register: seriatim_verify_source_status
|
||||
changed_when: false
|
||||
- name: Inspect the installed binary
|
||||
ansible.builtin.stat:
|
||||
path: "{{ seriatim_binary_path }}"
|
||||
register: seriatim_binary
|
||||
|
||||
- name: Read installed Seriatim version
|
||||
- name: Read the installed version
|
||||
ansible.builtin.command:
|
||||
argv:
|
||||
- "{{ seriatim_verify_binary_path }}"
|
||||
- "{{ seriatim_binary_path }}"
|
||||
- --version
|
||||
register: seriatim_verify_version
|
||||
register: seriatim_version_output
|
||||
changed_when: false
|
||||
|
||||
- name: Read stored Seriatim build inputs
|
||||
ansible.builtin.slurp:
|
||||
src: "{{ seriatim_verify_state_dir }}/build-inputs.json"
|
||||
register: seriatim_verify_inputs
|
||||
|
||||
- name: Read stored Seriatim fingerprint
|
||||
ansible.builtin.slurp:
|
||||
src: "{{ seriatim_verify_state_dir }}/fingerprint.sha256"
|
||||
register: seriatim_verify_fingerprint
|
||||
|
||||
- name: Read stored Seriatim checksum
|
||||
ansible.builtin.slurp:
|
||||
src: "{{ seriatim_verify_state_dir }}/binary.sha256"
|
||||
register: seriatim_verify_checksum
|
||||
|
||||
- name: Require valid Seriatim installation state
|
||||
- name: Assert the installation contract
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- ansible_facts.distribution == 'Ubuntu'
|
||||
- ansible_facts.distribution_version is version('26.04', '==')
|
||||
- ansible_facts.architecture in ['x86_64', 'aarch64']
|
||||
- seriatim_verify_source_stat.stat.isdir
|
||||
- seriatim_verify_source_stat.stat.pw_name == 'root'
|
||||
- seriatim_verify_source_stat.stat.gr_name == 'root'
|
||||
- seriatim_verify_binary_stat.stat.isreg
|
||||
- seriatim_verify_binary_stat.stat.pw_name == 'root'
|
||||
- seriatim_verify_binary_stat.stat.gr_name == 'root'
|
||||
- seriatim_verify_binary_stat.stat.mode == '0755'
|
||||
- seriatim_verify_state_stat.stat.isdir
|
||||
- seriatim_verify_state_stat.stat.pw_name == 'root'
|
||||
- seriatim_verify_state_stat.stat.gr_name == 'root'
|
||||
- seriatim_verify_state_stat.stat.mode == '0755'
|
||||
- seriatim_verify_state_file_stats.results | map(attribute='stat.isreg') | unique | list == [true]
|
||||
- seriatim_verify_state_file_stats.results | map(attribute='stat.pw_name') | unique | list == ['root']
|
||||
- seriatim_verify_state_file_stats.results | map(attribute='stat.gr_name') | unique | list == ['root']
|
||||
- seriatim_verify_state_file_stats.results | map(attribute='stat.mode') | unique | list == ['0644']
|
||||
- seriatim_verify_commit.stdout == seriatim_expected_commit
|
||||
- seriatim_verify_source_status.stdout == ''
|
||||
- seriatim_verify_version.stdout == 'seriatim version ' ~ seriatim_expected_version
|
||||
- (seriatim_verify_inputs.content | b64decode | trim | hash('sha256')) == (seriatim_verify_fingerprint.content | b64decode | trim)
|
||||
- seriatim_verify_binary_stat.stat.checksum == (seriatim_verify_checksum.content | b64decode | trim)
|
||||
fail_msg: Installed Seriatim source, binary, or build state is inconsistent.
|
||||
- seriatim_source.stat.isdir
|
||||
- seriatim_source.stat.pw_name == "root"
|
||||
- seriatim_source.stat.gr_name == "root"
|
||||
- seriatim_source_ownership.stdout == ""
|
||||
- seriatim_source_commit.stdout == seriatim_expected_commit
|
||||
- seriatim_binary.stat.isreg
|
||||
- seriatim_binary.stat.pw_name == "root"
|
||||
- seriatim_binary.stat.gr_name == "root"
|
||||
- seriatim_binary.stat.mode == "0755"
|
||||
- seriatim_version_output.stdout == "seriatim version " ~ seriatim_expected_version
|
||||
|
||||
Reference in New Issue
Block a user