Files
snapd/tests/lib/tools/snaps-state
Valentin David b1dc3c675d tests: properly build snapd snap (#14141)
* tests: properly build snapd snap

Now we build also the test version of snapd snap in `snap-builds`
workflow job. We copy this into the spread tests. And we use that
snap, which we only instrument instead of copying the snapd deb build.

If the snap is not available, then we build it in spread. On CI, this
happens on arm since the workflow does not build it. It will also
happen when triggering test manually.

* tests: couple of small improvements to test syntax, move WORK_DIR into script scope, use PWD instead of dot notation

---------

Co-authored-by: Philip Meulengracht <the_meulengracht@hotmail.com>
2024-07-03 13:36:31 +02:00

241 lines
7.3 KiB
Bash
Executable File

#!/bin/bash -e
show_help() {
echo "usage: pack-local <snap-name>"
echo " install-local <snap-name> [OPTIONS]"
echo " install-local-as <snap-name> <dest-name> [OPTIONS]"
echo " show-name <snap>"
echo " show-revision <snap>"
echo " is-confinement-supported <classic|devmode|strict>"
echo " repack-snapd-deb-into-snap <snapd|core>"
echo " repack-core-snap-into-snapd-snap"
echo ""
echo "Available options:"
echo " --devmode --jailmode --classic"
echo "Supported names:"
echo " core kernel gadget"
echo ""
echo "Pack and install commands save the packed snap for future uses,"
echo "which is reused on the following calls."
echo "The paths for locating the sources of the snaps to either pack or"
echo "install are the local path and then 'tests/lib/snaps/'"
}
pack_local() {
local SNAP_NAME="$1"
local SNAP_DIR="${2:-$TESTSLIB/snaps/${SNAP_NAME}}"
local SNAP_VERSION="${3:-1.0}"
# Use local snap in case it exists
if [ -d "$SNAP_NAME" ]; then
SNAP_DIR="$PWD/$SNAP_NAME"
fi
if [ ! -d "$SNAP_DIR" ]; then
echo "snaps-state: can't pack $SNAP_NAME, snap directory not found"
exit 1
fi
local META_FILE META_NAME SNAP_FILE
META_FILE="$SNAP_DIR/meta/snap.yaml"
if [ ! -f "$META_FILE" ]; then
echo "snap.yaml file not found for $SNAP_NAME snap"
return 1
fi
META_NAME="$(grep '^name:' "$META_FILE" | awk '{ print $2 }' | tr -d ' ')"
SNAP_FILE="${SNAP_DIR}/${META_NAME}_${SNAP_VERSION}_all.snap"
# assigned in a separate step to avoid hiding a failure
if [ ! -f "$SNAP_FILE" ]; then
snap pack "$SNAP_DIR" "$SNAP_DIR" >/dev/null
fi
# echo the snap name
if [ -f "$SNAP_FILE" ]; then
echo "$SNAP_FILE"
else
find "$SNAP_DIR" -name "${META_NAME}_*.snap"| head -n1
fi
}
install_local() {
local SNAP_NAME="$1"
local SNAP_DIR="$TESTSLIB/snaps/${SNAP_NAME}"
shift
if [ -d "$SNAP_NAME" ]; then
SNAP_DIR="$PWD/$SNAP_NAME"
fi
SNAP_FILE=$(pack_local "$SNAP_NAME" "$SNAP_DIR")
snap install --dangerous "$@" "$SNAP_FILE"
}
install_local_as() {
local snap="$1"
local name="$2"
shift 2
install_local "$snap" --name "$name" "$@"
}
show_name() {
case "${1:-}" in
core)
local core_name
core_name="$(snap model --verbose | grep -Po "^base:\\s+\\K.*" || true)"
if [ -z "$core_name" ]; then
core_name="core"
fi
echo "$core_name"
;;
kernel)
snap list | grep 'kernel$' | awk '{ print $1 }'
;;
gadget)
snap list | grep 'gadget$' | awk '{ print $1 }'
;;
*)
echo "snaps-state: unsupported snap $1" >&2
show_help
exit 1
;;
esac
}
show_revision() {
local snap="$1"
if not snap list "$snap" &>/dev/null; then
echo "snaps-state: the snap $snap is not installed" >&2
exit 1
fi
snap info "$snap" | awk "/installed: / {print(\$3)}" | sed -e 's/(\(.*\))/\1/'
}
is_confinement_supported() {
local confinement="$1"
if [ -z "$confinement" ]; then
echo "snaps-state: a confinement is required"
show_help
exit 1
fi
snap debug sandbox-features --required=confinement-options:"$confinement"
}
# The function will re-pack either core or snapd snap using the assets
# from the snapd deb installed on the system
repack_snapd_deb_into_snap() {
local snap_name="$1"
local target_dir="${2:-$PWD}"
local deb_file="${3:-$(ls "$SPREAD_PATH"/../snapd_*.deb)}"
if [ ! -e "$deb_file" ]; then
echo "snaps-state: deb file used to repack not found: $deb_file"
exit 1
fi
case "$snap_name" in
core)
# use snapd from edge as a recent snap that should be close to what we will
# have in the snapd deb
snap download core --basename=core --edge
unsquashfs -d ./core-unpacked core.snap
rm core.snap
# extract all the files from the snapd deb
dpkg-deb -x "$deb_file" ./core-unpacked
# repack into the target dir specified
snap pack --filename=core-from-snapd-deb.snap core-unpacked "$target_dir"
# cleanup
rm -rf core-unpacked
;;
*)
echo "snaps-state: use either core or snapd snaps for repack, snapd $snap_name not supported"
show_help
exit 1
;;
esac
}
# This function will re-pack the current core snap as the snapd snap,
# using the snapd snap from edge as the set of files to use from the core snap.
# This is primarily meant to be used in UC16 tests that need to use the snapd
# snap because neither the snapd snap, nor the snapd deb built for the spread
# run are seeded on the image
# The built snap is located in the current working directory with the
# filename snapd-from-core.snap.
repack_core_snap_into_snapd_snap() {
# FIXME: maybe build the snapd snap from the deb in prepare_ubuntu_core /
# setup_reflash_magic and include it somewhere in the image so we don't need
# to do this hack here?
# get the snap.yaml and a list of all the snapd snap files using edge
# NOTE: this may break if a spread run adds files to the snapd snap that
# don't exist in the snapd snap on edge and those files are necessary
# for snapd to run or revert, etc.
local core_snap current
if [ $# -eq 0 ]; then
current="$(readlink /snap/core/current)"
core_snap="${1:-/var/lib/snapd/snaps/core_"$current".snap}"
else
core_snap=$1
if [ ! -e "$core_snap" ]; then
echo "snaps-state: core snap used to repack not found: $core_snap"
exit 1
fi
fi
snap download snapd --basename=snapd-upstream --edge
unsquashfs -d ./snapd-upstream snapd-upstream.snap
rm snapd-upstream.snap
(
cd snapd-upstream || exit 1
# find all files and symlinks - not directories because when unsquashfs
# is provided a directory it will extract all the files in that directory
find . \( -type l -o -type f \) | cut -c3- > ../files.txt
)
# only unpack files from the core snap that are in the snapd snap - this
# is kosher because the set of files in the core snap is a superset of
# all the files in the snapd snap
#shellcheck disable=2046
unsquashfs -d ./snapd-local "$core_snap" $(cat files.txt)
# replace snap.yaml from the core snap with the snapd snap, and pack the snap
cp snapd-upstream/meta/snap.yaml snapd-local/meta/snap.yaml
snap pack snapd-local --filename=snapd-from-core.snap
# cleanup the snaps we downloaded and built
rm -rf snapd-local snapd-upstream* files.txt
}
main() {
if [ $# -eq 0 ]; then
show_help
exit 0
fi
local subcommand="$1"
local action=
while [ $# -gt 0 ]; do
case "$1" in
-h|--help)
show_help
exit 0
;;
*)
action=$(echo "$subcommand" | tr '-' '_')
shift
break
;;
esac
done
if [ -z "$(declare -f "$action")" ]; then
echo "snaps-state: no such command: $subcommand"
show_help
exit 1
fi
"$action" "$@"
}
main "$@"