tests: speed up the prepare phase through a new tool to manage initial snapd env (#12707)

* New tool to manage initial env in spread tests

This is used to know in spread tests the initial value for the vars and
be able to repeat not needed steps

* test fixed

* Minor fixes con docs and env var removed

* improve tests.env tool
This commit is contained in:
Sergio Cazzolato
2023-07-07 12:17:41 -03:00
committed by GitHub
parent 4640067371
commit 7ba95e3a7a
6 changed files with 227 additions and 28 deletions

View File

@@ -15,6 +15,7 @@ environment:
TESTSLIB: $PROJECT_PATH/tests/lib
TESTSTOOLS: $PROJECT_PATH/tests/lib/tools
TESTSTMP: /var/tmp/snapd-tools
RUNTIME_STATE_PATH: $TESTSTMP/runtime-state
# turn debug off so that we don't get errant debug messages while running
# tests, and in some cases like on UC20 we have the kernel command line
# parameter, snapd.debug=1 turned on to enable early boot debugging before
@@ -73,6 +74,8 @@ environment:
# Use the installed snapd and reset the systems without removing snapd
REUSE_SNAPD: '$(HOST: echo "${SPREAD_REUSE_SNAPD:-0}")'
EXPERIMENTAL_FEATURES: '$(HOST: echo "${SPREAD_EXPERIMENTAL_FEATURES:-}")'
# set to 1 when the snapd memory limit has to be removed
SNAPD_NO_MEMORY_LIMIT: '$(HOST: echo "${SPREAD_SNAPD_NO_MEMORY_LIMIT:-}")'
SNAPD_PUBLISHED_VERSION: '$(HOST: echo "$SPREAD_SNAPD_PUBLISHED_VERSION")'
# Build and use snapd from current branch

1
tests/bin/tests.env Symbolic link
View File

@@ -0,0 +1 @@
../lib/tools/tests.env

View File

@@ -215,6 +215,14 @@ update_core_snap_for_classic_reexec() {
}
prepare_memory_limit_override() {
# First time it is needed to save the initial env var value
if not tests.env is-set initial SNAPD_NO_MEMORY_LIMIT; then
tests.env set initial SNAPD_NO_MEMORY_LIMIT "$SNAPD_NO_MEMORY_LIMIT"
# Then if the new value is the same than the initial, then no new configuration needed
elif [ "$(tests.env get initial SNAPD_NO_MEMORY_LIMIT)" = "$SNAPD_NO_MEMORY_LIMIT" ]; then
return
fi
# set up memory limits for snapd bu default unless explicit requested not to
# or the system is known to be problematic
local set_limit=1
@@ -232,7 +240,7 @@ prepare_memory_limit_override() {
set_limit=0
;;
*)
if [ -n "${SNAPD_NO_MEMORY_LIMIT:-}" ]; then
if [ "$SNAPD_NO_MEMORY_LIMIT" = 1 ]; then
set_limit=0
fi
;;
@@ -254,8 +262,7 @@ prepare_memory_limit_override() {
# systemd is backwards compatible so the limit is still set.
cat <<EOF > /etc/systemd/system/snapd.service.d/memory-max.conf
[Service]
# mvo: disabled because of many failures in restore, e.g. in PR#11014
#MemoryLimit=100M
MemoryLimit=150M
EOF
fi
# the service setting may have changed in the service so we need
@@ -264,38 +271,31 @@ EOF
systemctl restart snapd
}
create_reexec_file(){
local reexec_file=$1
cat <<EOF > "$reexec_file"
[Service]
Environment=SNAP_REEXEC=$SNAP_REEXEC
EOF
}
prepare_reexec_override() {
local reexec_file=/etc/systemd/system/snapd.service.d/reexec.conf
local updated=false
# First time it is needed to save the initial env var value
if not tests.env is-set initial SNAP_REEXEC; then
tests.env set initial SNAP_REEXEC "$SNAP_REEXEC"
# Then if the new value is the same than the initial, then no new configuration needed
elif [ "$(tests.env get initial SNAP_REEXEC)" = "$SNAP_REEXEC" ]; then
return
fi
# Just update reexec configuration when the SNAP_REEXEC var has been updated
# Otherwise it is used the configuration set during project preparation
mkdir -p /etc/systemd/system/snapd.service.d
if [ -z "${SNAP_REEXEC:-}" ] && [ -f "$reexec_file" ] ; then
if [ -z "${SNAP_REEXEC:-}" ]; then
rm -f "$reexec_file"
updated=true
elif [ -n "${SNAP_REEXEC:-}" ] && [ ! -f "$reexec_file" ]; then
create_reexec_file "$reexec_file"
updated=true
elif [ -n "${SNAP_REEXEC:-}" ] && NOMATCH "Environment=SNAP_REEXEC=$SNAP_REEXEC" < "$reexec_file"; then
create_reexec_file "$reexec_file"
updated=true
else
cat <<EOF > "$reexec_file"
[Service]
Environment=SNAP_REEXEC=$SNAP_REEXEC
EOF
fi
if [ "$updated" = true ]; then
# the re-exec setting may have changed in the service so we need
# to ensure snapd is reloaded
systemctl daemon-reload
systemctl restart snapd
fi
systemctl daemon-reload
systemctl restart snapd
}
prepare_each_classic() {
@@ -303,7 +303,9 @@ prepare_each_classic() {
echo "/etc/systemd/system/snapd.service.d/local.conf vanished!"
exit 1
fi
prepare_reexec_override
prepare_memory_limit_override
}
prepare_classic() {
@@ -360,6 +362,9 @@ prepare_classic() {
# Snapshot the state including core.
if ! is_snapd_state_saved; then
# Create the file with the initial environment before saving the state
tests.env start initial
# need to be seeded to proceed with snap install
# also make sure the captured state is seeded
snap wait system seed.loaded
@@ -1420,6 +1425,9 @@ prepare_ubuntu_core() {
# Snapshot the fresh state (including boot/bootenv)
if ! is_snapd_state_saved; then
# Create the file with the initial environment before saving the state
tests.env start initial
# important to remove disabled snaps before calling save_snapd_state
# or restore will break
remove_disabled_snaps

View File

@@ -2,10 +2,8 @@
SNAPD_STATE_PATH="$TESTSTMP/snapd-state"
SNAPD_STATE_FILE="$TESTSTMP/snapd-state/snapd-state.tar"
RUNTIME_STATE_PATH="$TESTSTMP/runtime-state"
SNAPD_ACTIVE_UNITS="$RUNTIME_STATE_PATH/snapd-active-units"
delete_snapd_state() {
rm -rf "$SNAPD_STATE_PATH"
}

View File

@@ -0,0 +1,59 @@
summary: tests for tests.env
restore: |
rm -f "$RUNTIME_STATE_PATH"/test1.env "$RUNTIME_STATE_PATH"/test2.env
execute: |
# Both -h and --help are also recognized.
tests.env --help | MATCH "usage: tests.env start <ENV_NAME>"
tests.env -h | MATCH "usage: tests.env start <ENV_NAME>"
# check start env file
tests.env start test1
test -f "$RUNTIME_STATE_PATH"/test1.env
# check commands is-set and set
not tests.env is-set test1 var1
tests.env set test1 var1 val1
tests.env is-set test1 var1
tests.env set test1 var3
tests.env set test1 var4 ""
# check command get
test "$(tests.env get test1 var1)" = "val1"
test "$(tests.env get test1 var3)" = ""
test "$(tests.env get test1 var4)" = ""
# check set another value
not tests.env is-set test1 var2
tests.env set test1 var2 val2
tests.env is-set test1 var2
test "$(tests.env get test1 var2)" = "val2"
test "$(tests.env get test1 var1)" = "val1"
# check update the value
tests.env set test1 var1 val3
test "$(tests.env get test1 var1)" = "val3"
# create another env
tests.env start test2
tests.env set test2 var1 val1
test "$(tests.env get test1 var1)" = "val3"
test "$(tests.env get test2 var1)" = "val1"
# check errors
tests.env test 2>&1 | MATCH "tests.env: no such command: test"
tests.env start 2>&1 | MATCH "tests.env: name for the env file is required"
tests.env is-set 2>&1 | MATCH "tests.env: name for the env file is required"
tests.env is-set test1 2>&1 | MATCH "tests.env: variable to check in env file is required"
tests.env is-set test10 var1 2>&1 | MATCH "tests.env: env file $RUNTIME_STATE_PATH/test10.env does not exist"
tests.env get 2>&1 | MATCH "tests.env: name for the env file is required"
tests.env get test1 2>&1 | MATCH "tests.env: variable to check in env file is required"
tests.env get test10 var1 2>&1 | MATCH "tests.env: env file $RUNTIME_STATE_PATH/test10.env does not exist"
tests.env set 2>&1 | MATCH "tests.env: name for the env file is required"
tests.env set test1 2>&1 | MATCH "tests.env: variable to set in env file is required"
tests.env set test10 var1 val1 2>&1 | MATCH "tests.env: env file $RUNTIME_STATE_PATH/test10.env does not exist"

130
tests/lib/tools/tests.env Executable file
View File

@@ -0,0 +1,130 @@
#!/bin/bash
show_help() {
echo "usage: tests.env start <ENV_NAME>"
echo " tests.env is-set <ENV_NAME> <VAR>"
echo " tests.env get <ENV_NAME> <VAR>"
echo " tests.env set <ENV_NAME> <VAR> <VAL>"
echo ""
echo "The tool is used to create an environment file"
echo " which can be shared across different tests and suites"
}
start() {
local NAME=$1
if [ -z "$NAME" ]; then
echo "tests.env: name for the env file is required"
exit 1
fi
if [ -f "$RUNTIME_STATE_PATH/$NAME.env" ]; then
echo "tests.env: env file $RUNTIME_STATE_PATH/$NAME.env already exists, deleting..."
rm -f "$RUNTIME_STATE_PATH/$NAME.env"
fi
mkdir -p "$RUNTIME_STATE_PATH"
touch "$RUNTIME_STATE_PATH/$NAME.env"
}
is_set() {
local NAME=$1
local VAR=$2
if [ -z "$NAME" ]; then
echo "tests.env: name for the env file is required"
exit 1
fi
if [ -z "$VAR" ]; then
echo "tests.env: variable to check in env file is required"
exit 1
fi
if [ ! -f "$RUNTIME_STATE_PATH/$NAME.env" ]; then
echo "tests.env: env file $RUNTIME_STATE_PATH/$NAME.env does not exist"
exit 1
fi
grep -Eq "^${VAR}=" "$RUNTIME_STATE_PATH/$NAME.env"
}
get() {
local NAME=$1
local VAR=$2
if [ -z "$NAME" ]; then
echo "tests.env: name for the env file is required"
exit 1
fi
if [ -z "$VAR" ]; then
echo "tests.env: variable to check in env file is required"
exit 1
fi
if [ ! -f "$RUNTIME_STATE_PATH/$NAME.env" ]; then
echo "tests.env: env file $RUNTIME_STATE_PATH/$NAME.env does not exist"
exit 1
fi
if is_set "$NAME" "$VAR"; then
grep -E "^${VAR}=" "$RUNTIME_STATE_PATH/$NAME.env" | cut -d "=" -f2-
fi
}
set() {
local NAME=$1
local VAR=$2
local VAL=$3
if [ -z "$NAME" ]; then
echo "tests.env: name for the env file is required"
exit 1
fi
if [ -z "$VAR" ]; then
echo "tests.env: variable to set in env file is required"
exit 1
fi
if [ ! -f "$RUNTIME_STATE_PATH/$NAME.env" ]; then
echo "tests.env: env file $RUNTIME_STATE_PATH/$NAME.env does not exist"
exit 1
fi
if is_set "$NAME" "$VAR"; then
sed -i -E "s/^${VAR}=.*/${VAR}=${VAL}/" "$RUNTIME_STATE_PATH/$NAME.env"
else
echo "${VAR}=${VAL}" >> "$RUNTIME_STATE_PATH/$NAME.env"
fi
}
main() {
if [ $# -eq 0 ]; then
show_help
exit 0
fi
local subcommand="$1"
local action=
while [ $# -gt 0 ]; do
case "$subcommand" in
-h|--help)
show_help
exit 0
;;
*)
action=$(echo "$subcommand" | tr '-' '_')
shift
break
;;
esac
done
if [ -z "$(declare -f "$action")" ]; then
echo "tests.env: no such command: $subcommand"
show_help
exit 1
fi
"$action" "$@"
}
main "$@"