ci: add test for the various new sysupdate features
This commit is contained in:
@@ -918,8 +918,9 @@ test -f "$COMPALL/target-b/comp-b-v1.bin"
|
||||
test -d /var/lib/systemd/sysupdate/installdb.comp-a
|
||||
test -d /var/lib/systemd/sysupdate/installdb.comp-b
|
||||
|
||||
# --component-all is only supported for the "cleanup" verb, refuse it elsewhere.
|
||||
(! "$SYSUPDATE" --component-all --verify=no update)
|
||||
# --component-all is not supported for every verb, so it must be refused where it isn't (e.g. "vacuum").
|
||||
# (It *is* supported for update/acquire/cleanup/enable-*/disable-*, which is exercised further down.)
|
||||
(! "$SYSUPDATE" --component-all --verify=no vacuum)
|
||||
|
||||
# With the transfer files still in place "cleanup --component-all" is a no-op:
|
||||
# nothing is orphaned.
|
||||
@@ -1449,4 +1450,375 @@ rm -rf "$CONFIGDIR/01-manifest-yes-and-retry.transfer" \
|
||||
"$SYSUPDATE" components |& grep "No components defined." >/dev/null
|
||||
[[ $(varlinkctl call "$VARLINK_SOCKET" io.systemd.SysUpdate.ListTargets | jq -r '.targets') == "[]" ]]
|
||||
|
||||
# ============================================================================
|
||||
# Components & features: enable/disable verbs, the --component-{all,suggested}
|
||||
# and --feature-{all,suggested} switches, plus the Suggest=/SuggestOn…=
|
||||
# settings. Everything below operates on freshly minted throw-away components
|
||||
# and features, and cleans up after itself.
|
||||
#
|
||||
# Layout used throughout:
|
||||
# * a component <c> is defined by a transfer directory /run/sysupdate.<c>.d/
|
||||
# (which is what makes it show up in the 'components' list) plus an optional
|
||||
# metadata file /run/sysupdate.<c>.component carrying Description=/Suggest=/…
|
||||
# * the enable-component/disable-component verbs write their Enabled= override
|
||||
# into a drop-in below /etc/sysupdate.<c>.component.d/
|
||||
# * the enable-feature/disable-feature verbs write their Enabled= override into
|
||||
# a drop-in below /etc/sysupdate.d/<f>.feature.d/ (default component) or
|
||||
# /etc/sysupdate.<c>.d/<f>.feature.d/ (named component)
|
||||
# ============================================================================
|
||||
CF="$WORKDIR/compfeat"
|
||||
|
||||
# The Suggest…MachineTag= tests below drive the machine tags via /etc/machine-info
|
||||
# (which the condition logic reads directly); back up any pre-existing file so we
|
||||
# can restore it afterwards, mirroring TEST-74-AUX-UTILS.machine-tags.sh.
|
||||
MI_BAK="$WORKDIR/machine-info.orig"
|
||||
rm -f "$MI_BAK"
|
||||
[[ -e /etc/machine-info ]] && cp -a /etc/machine-info "$MI_BAK"
|
||||
|
||||
set_machine_tags() {
|
||||
if [[ -n "${1:-}" ]]; then
|
||||
echo "TAGS=$1" >/etc/machine-info
|
||||
else
|
||||
rm -f /etc/machine-info
|
||||
fi
|
||||
}
|
||||
|
||||
restore_machine_info() {
|
||||
if [[ -e "$MI_BAK" ]]; then
|
||||
cp -a "$MI_BAK" /etc/machine-info
|
||||
else
|
||||
rm -f /etc/machine-info
|
||||
fi
|
||||
}
|
||||
|
||||
compfeat_cleanup() {
|
||||
rm -rf /run/sysupdate.d \
|
||||
/run/sysupdate.compx.d /run/sysupdate.compx.component /run/sysupdate.compx.component.d \
|
||||
/run/sysupdate.compy.d /run/sysupdate.compy.component /run/sysupdate.compy.component.d \
|
||||
/run/sysupdate.compz.d /run/sysupdate.compz.component /run/sysupdate.compz.component.d \
|
||||
/etc/sysupdate.d \
|
||||
/etc/sysupdate.compx.d /etc/sysupdate.compx.component.d \
|
||||
/etc/sysupdate.compy.d /etc/sysupdate.compy.component.d \
|
||||
/etc/sysupdate.compz.d /etc/sysupdate.compz.component.d
|
||||
rm -rf "$CF"
|
||||
}
|
||||
|
||||
compfeat_reset() {
|
||||
compfeat_cleanup
|
||||
mkdir -p "$CF/source" \
|
||||
"$CF/target-default" "$CF/target-compx" "$CF/target-compy" "$CF/target-compz"
|
||||
}
|
||||
|
||||
# (Re)generate the source payloads + SHA256SUMS for a given version. We create a
|
||||
# payload for every component/feature so a single SHA256SUMS covers them all;
|
||||
# individual transfers only ever match their own pattern.
|
||||
compfeat_source() {
|
||||
local v="${1:?}"
|
||||
local n
|
||||
for n in base compx compy compz feata featb featc; do
|
||||
echo "$n-$v-$RANDOM" >"$CF/source/$n-$v.bin"
|
||||
done
|
||||
(cd "$CF/source" && sha256sum -- *.bin >SHA256SUMS)
|
||||
}
|
||||
|
||||
# Write a regular-file transfer; optional 4th argument gates it behind a feature.
|
||||
compfeat_transfer() {
|
||||
local file="${1:?}" pat="${2:?}" tgt="${3:?}" feature="${4:-}"
|
||||
{
|
||||
if [[ -n "$feature" ]]; then
|
||||
printf '[Transfer]\nFeatures=%s\n\n' "$feature"
|
||||
fi
|
||||
printf '[Source]\nType=regular-file\nPath=%s\nMatchPattern=%s-@v.bin\n\n' "$CF/source" "$pat"
|
||||
printf '[Target]\nType=regular-file\nPath=%s\nMatchPattern=%s-@v.bin\nInstancesMax=2\n' "$tgt" "$pat"
|
||||
} >"$file"
|
||||
}
|
||||
|
||||
comp_enable_dropin() { echo "/etc/sysupdate.$1.component.d/50-systemd-sysupdate-enabled.conf"; }
|
||||
feat_enable_dropin_default() { echo "/etc/sysupdate.d/$1.feature.d/50-systemd-sysupdate-enabled.conf"; }
|
||||
feat_enable_dropin_comp() { echo "/etc/sysupdate.$1.d/$2.feature.d/50-systemd-sysupdate-enabled.conf"; }
|
||||
|
||||
# Assert a generated Enabled= drop-in exists and carries the expected value.
|
||||
assert_dropin() {
|
||||
local file="${1:?}" val="${2:?}"
|
||||
test -f "$file"
|
||||
grep "^Enabled=$val$" "$file" >/dev/null
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# enable-component / disable-component: explicit selection + observable effect
|
||||
# ---------------------------------------------------------------------------
|
||||
compfeat_reset
|
||||
compfeat_source v1
|
||||
mkdir -p /run/sysupdate.compx.d
|
||||
compfeat_transfer /run/sysupdate.compx.d/01-compx.transfer compx "$CF/target-compx"
|
||||
# A metadata file carrying a human-readable description (exercises loading of the
|
||||
# per-component *.component file from the search dirs).
|
||||
cat >/run/sysupdate.compx.component <<EOF
|
||||
[Component]
|
||||
Description=CompXDescription
|
||||
EOF
|
||||
|
||||
# The description from the *.component file must surface in the 'components' listing.
|
||||
"$SYSUPDATE" --no-legend components | grep -F "CompXDescription" >/dev/null
|
||||
|
||||
# A brand new component (no Enabled= override anywhere) is enabled by default and
|
||||
# can be updated.
|
||||
"$SYSUPDATE" --component=compx --verify=no update
|
||||
test -f "$CF/target-compx/compx-v1.bin"
|
||||
|
||||
# Disable it: this must drop an Enabled=no override next to the definition, and
|
||||
# subsequent updates for that component must be refused.
|
||||
"$SYSUPDATE" disable-component compx
|
||||
assert_dropin "$(comp_enable_dropin compx)" no
|
||||
(! "$SYSUPDATE" --component=compx --verify=no update) |& grep -F "Component is disabled" >/dev/null
|
||||
|
||||
# Re-enable via the "--component= + no positional argument" form and verify the
|
||||
# update works again.
|
||||
"$SYSUPDATE" --component=compx enable-component
|
||||
assert_dropin "$(comp_enable_dropin compx)" yes
|
||||
rm -f "$CF/target-compx/compx-v1.bin"
|
||||
"$SYSUPDATE" --component=compx --verify=no update
|
||||
test -f "$CF/target-compx/compx-v1.bin"
|
||||
|
||||
# Enabling a component must not conjure a bogus "<c>.component" pseudo-component
|
||||
# out of the freshly created sysupdate.compx.component.d/ drop-in directory.
|
||||
(! "$SYSUPDATE" --json=short components | grep -F '"compx.component"' >/dev/null)
|
||||
"$SYSUPDATE" --json=short components | grep -F '"compx"' >/dev/null
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# enable-component / disable-component: argument validation & error handling
|
||||
# ---------------------------------------------------------------------------
|
||||
# Positional argument and --component= are mutually exclusive.
|
||||
(! "$SYSUPDATE" --component=compx enable-component compx) |& grep -F "not both" >/dev/null
|
||||
# Syntactically invalid component name.
|
||||
(! "$SYSUPDATE" enable-component ../nope) |& grep -F "Component name invalid" >/dev/null
|
||||
# Unknown component.
|
||||
(! "$SYSUPDATE" enable-component doesnotexist) |& grep -F "Component not found" >/dev/null
|
||||
# --definitions= is incompatible with component enablement.
|
||||
(! "$SYSUPDATE" --definitions="$CF" enable-component compx) |& grep -F "may not be combined" >/dev/null
|
||||
# The feature-selection switches make no sense here.
|
||||
(! "$SYSUPDATE" --feature-all enable-component compx) |& grep -F "not supported" >/dev/null
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# --component-all for enable-component / disable-component
|
||||
# ---------------------------------------------------------------------------
|
||||
compfeat_reset
|
||||
compfeat_source v1
|
||||
mkdir -p /run/sysupdate.compx.d /run/sysupdate.compy.d
|
||||
compfeat_transfer /run/sysupdate.compx.d/01-compx.transfer compx "$CF/target-compx"
|
||||
compfeat_transfer /run/sysupdate.compy.d/01-compy.transfer compy "$CF/target-compy"
|
||||
|
||||
# Disable *all* components in one go, then re-enable them all.
|
||||
"$SYSUPDATE" --component-all disable-component
|
||||
assert_dropin "$(comp_enable_dropin compx)" no
|
||||
assert_dropin "$(comp_enable_dropin compy)" no
|
||||
(! "$SYSUPDATE" --component=compx --verify=no update) |& grep -F "Component is disabled" >/dev/null
|
||||
(! "$SYSUPDATE" --component=compy --verify=no update) |& grep -F "Component is disabled" >/dev/null
|
||||
|
||||
"$SYSUPDATE" --component-all enable-component
|
||||
assert_dropin "$(comp_enable_dropin compx)" yes
|
||||
assert_dropin "$(comp_enable_dropin compy)" yes
|
||||
"$SYSUPDATE" --component=compx --verify=no update
|
||||
"$SYSUPDATE" --component=compy --verify=no update
|
||||
test -f "$CF/target-compx/compx-v1.bin"
|
||||
test -f "$CF/target-compy/compy-v1.bin"
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# --component-suggested driven by Suggest= (compx suggested, compy not)
|
||||
# ---------------------------------------------------------------------------
|
||||
compfeat_reset
|
||||
compfeat_source v1
|
||||
mkdir -p /run/sysupdate.compx.d /run/sysupdate.compy.d
|
||||
compfeat_transfer /run/sysupdate.compx.d/01-compx.transfer compx "$CF/target-compx"
|
||||
compfeat_transfer /run/sysupdate.compy.d/01-compy.transfer compy "$CF/target-compy"
|
||||
cat >/run/sysupdate.compx.component <<EOF
|
||||
[Component]
|
||||
Suggest=yes
|
||||
EOF
|
||||
cat >/run/sysupdate.compy.component <<EOF
|
||||
[Component]
|
||||
Suggest=no
|
||||
EOF
|
||||
|
||||
# 'enable-component --component-suggested' acts on the suggested components only.
|
||||
"$SYSUPDATE" --component-suggested enable-component
|
||||
assert_dropin "$(comp_enable_dropin compx)" yes
|
||||
test ! -e "$(comp_enable_dropin compy)"
|
||||
|
||||
# 'disable-component --component-suggested' reconciles the other way around: it
|
||||
# acts on the components that are *not* suggested (i.e. compy).
|
||||
"$SYSUPDATE" --component-suggested disable-component
|
||||
assert_dropin "$(comp_enable_dropin compy)" no
|
||||
# compx must be left as it was (still enabled from above).
|
||||
assert_dropin "$(comp_enable_dropin compx)" yes
|
||||
|
||||
# --component-suggested is not supported for the update verb.
|
||||
(! "$SYSUPDATE" --component-suggested --verify=no update) |& grep -F "not supported" >/dev/null
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# SuggestOnMachineTag= for a component
|
||||
# ---------------------------------------------------------------------------
|
||||
compfeat_reset
|
||||
compfeat_source v1
|
||||
mkdir -p /run/sysupdate.compz.d
|
||||
compfeat_transfer /run/sysupdate.compz.d/01-compz.transfer compz "$CF/target-compz"
|
||||
cat >/run/sysupdate.compz.component <<EOF
|
||||
[Component]
|
||||
SuggestOnMachineTag=sysupdate-test-tag
|
||||
EOF
|
||||
|
||||
# Without the matching machine tag the component is not suggested, so
|
||||
# --component-suggested selects nothing.
|
||||
set_machine_tags some-other-tag
|
||||
"$SYSUPDATE" --component-suggested enable-component
|
||||
test ! -e "$(comp_enable_dropin compz)"
|
||||
|
||||
# With the matching tag present it becomes suggested and gets enabled.
|
||||
set_machine_tags sysupdate-test-tag:another
|
||||
"$SYSUPDATE" --component-suggested enable-component
|
||||
assert_dropin "$(comp_enable_dropin compz)" yes
|
||||
set_machine_tags ""
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# enable-feature / disable-feature on the default component + observable effect
|
||||
# ---------------------------------------------------------------------------
|
||||
compfeat_reset
|
||||
compfeat_source v1
|
||||
mkdir -p /run/sysupdate.d
|
||||
compfeat_transfer /run/sysupdate.d/01-base.transfer base "$CF/target-default"
|
||||
compfeat_transfer /run/sysupdate.d/50-feata.transfer feata "$CF/target-default" feata
|
||||
cat >/run/sysupdate.d/feata.feature <<EOF
|
||||
[Feature]
|
||||
Description=Feature A
|
||||
EOF
|
||||
|
||||
# The feature is listed and disabled by default, so its transfer is not installed.
|
||||
"$SYSUPDATE" features | grep -F "feata" >/dev/null
|
||||
"$SYSUPDATE" --verify=no update
|
||||
test -f "$CF/target-default/base-v1.bin"
|
||||
test ! -e "$CF/target-default/feata-v1.bin"
|
||||
|
||||
# Enabling the feature must drop an Enabled=yes override and cause the gated
|
||||
# transfer to be installed on the next update.
|
||||
"$SYSUPDATE" enable-feature feata
|
||||
assert_dropin "$(feat_enable_dropin_default feata)" yes
|
||||
"$SYSUPDATE" --verify=no update
|
||||
test -f "$CF/target-default/feata-v1.bin"
|
||||
|
||||
# Disabling it again + vacuum must remove the now-orphaned feature resource.
|
||||
"$SYSUPDATE" disable-feature feata
|
||||
assert_dropin "$(feat_enable_dropin_default feata)" no
|
||||
"$SYSUPDATE" --verify=no vacuum
|
||||
test ! -e "$CF/target-default/feata-v1.bin"
|
||||
|
||||
# Argument validation for the feature verbs.
|
||||
(! "$SYSUPDATE" enable-feature --feature-all feata) |& grep -F "not both" >/dev/null
|
||||
(! "$SYSUPDATE" enable-feature 'bad/name') |& grep -F "Feature name invalid" >/dev/null
|
||||
(! "$SYSUPDATE" --component-suggested enable-feature feata) |& grep -F "not supported" >/dev/null
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# --feature-all / --feature-suggested (default component)
|
||||
# ---------------------------------------------------------------------------
|
||||
compfeat_reset
|
||||
compfeat_source v1
|
||||
mkdir -p /run/sysupdate.d
|
||||
compfeat_transfer /run/sysupdate.d/01-base.transfer base "$CF/target-default"
|
||||
# feata: suggested (Suggest=yes); featb: not suggested (Suggest=no);
|
||||
# featc: suggested on a machine tag we will set below.
|
||||
cat >/run/sysupdate.d/feata.feature <<EOF
|
||||
[Feature]
|
||||
Suggest=yes
|
||||
EOF
|
||||
cat >/run/sysupdate.d/featb.feature <<EOF
|
||||
[Feature]
|
||||
Suggest=no
|
||||
EOF
|
||||
cat >/run/sysupdate.d/featc.feature <<EOF
|
||||
[Feature]
|
||||
SuggestOnMachineTag=sysupdate-test-tag
|
||||
EOF
|
||||
|
||||
# --feature-all operates on every known feature.
|
||||
"$SYSUPDATE" enable-feature --feature-all
|
||||
assert_dropin "$(feat_enable_dropin_default feata)" yes
|
||||
assert_dropin "$(feat_enable_dropin_default featb)" yes
|
||||
assert_dropin "$(feat_enable_dropin_default featc)" yes
|
||||
|
||||
# --feature-suggested (no machine tag): only the Suggest=yes feature is picked.
|
||||
rm -rf /etc/sysupdate.d
|
||||
set_machine_tags unrelated
|
||||
"$SYSUPDATE" enable-feature --feature-suggested
|
||||
assert_dropin "$(feat_enable_dropin_default feata)" yes
|
||||
test ! -e "$(feat_enable_dropin_default featb)"
|
||||
test ! -e "$(feat_enable_dropin_default featc)"
|
||||
|
||||
# --feature-suggested with the machine tag set: feata + featc are picked.
|
||||
rm -rf /etc/sysupdate.d
|
||||
set_machine_tags sysupdate-test-tag
|
||||
"$SYSUPDATE" enable-feature --feature-suggested
|
||||
assert_dropin "$(feat_enable_dropin_default feata)" yes
|
||||
assert_dropin "$(feat_enable_dropin_default featc)" yes
|
||||
test ! -e "$(feat_enable_dropin_default featb)"
|
||||
set_machine_tags ""
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Features scoped to a named component, and across all components at once
|
||||
# ---------------------------------------------------------------------------
|
||||
compfeat_reset
|
||||
compfeat_source v1
|
||||
mkdir -p /run/sysupdate.d /run/sysupdate.compx.d
|
||||
compfeat_transfer /run/sysupdate.d/01-base.transfer base "$CF/target-default"
|
||||
compfeat_transfer /run/sysupdate.compx.d/01-compx.transfer compx "$CF/target-compx"
|
||||
cat >/run/sysupdate.d/feata.feature <<EOF
|
||||
[Feature]
|
||||
Description=Default feature A
|
||||
EOF
|
||||
cat >/run/sysupdate.compx.d/featx.feature <<EOF
|
||||
[Feature]
|
||||
Description=Component X feature
|
||||
EOF
|
||||
|
||||
# --component= scopes feature operations to that component: the drop-in must land
|
||||
# next to the component's definitions, and the default component is untouched.
|
||||
"$SYSUPDATE" --component=compx enable-feature --feature-all
|
||||
assert_dropin "$(feat_enable_dropin_comp compx featx)" yes
|
||||
test ! -e "$(feat_enable_dropin_default feata)"
|
||||
|
||||
# --component-all --feature-all fans out over the default component *and* every
|
||||
# named component.
|
||||
rm -rf /etc/sysupdate.d /etc/sysupdate.compx.d
|
||||
"$SYSUPDATE" --component-all enable-feature --feature-all
|
||||
assert_dropin "$(feat_enable_dropin_default feata)" yes
|
||||
assert_dropin "$(feat_enable_dropin_comp compx featx)" yes
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# update --component-all installs every component's update in one invocation
|
||||
# ---------------------------------------------------------------------------
|
||||
compfeat_reset
|
||||
compfeat_source v1
|
||||
mkdir -p /run/sysupdate.compx.d /run/sysupdate.compy.d
|
||||
compfeat_transfer /run/sysupdate.compx.d/01-compx.transfer compx "$CF/target-compx"
|
||||
compfeat_transfer /run/sysupdate.compy.d/01-compy.transfer compy "$CF/target-compy"
|
||||
|
||||
"$SYSUPDATE" --component-all --verify=no update
|
||||
test -f "$CF/target-compx/compx-v1.bin"
|
||||
test -f "$CF/target-compy/compy-v1.bin"
|
||||
|
||||
# A second version must likewise be rolled out to every component at once.
|
||||
compfeat_source v2
|
||||
"$SYSUPDATE" --component-all --verify=no update
|
||||
test -f "$CF/target-compx/compx-v2.bin"
|
||||
test -f "$CF/target-compy/compy-v2.bin"
|
||||
|
||||
# A disabled component must not turn "update --component-all" into a failure:
|
||||
# it is skipped, while the remaining enabled components are still updated.
|
||||
"$SYSUPDATE" disable-component compy
|
||||
compfeat_source v3
|
||||
"$SYSUPDATE" --component-all --verify=no update
|
||||
test -f "$CF/target-compx/compx-v3.bin"
|
||||
test ! -e "$CF/target-compy/compy-v3.bin"
|
||||
|
||||
compfeat_cleanup
|
||||
restore_machine_info
|
||||
|
||||
touch /testok
|
||||
|
||||
Reference in New Issue
Block a user