Skip to content

Instantly share code, notes, and snippets.

@swick
Last active October 4, 2023 20:08
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save swick/968453815a1e918f0f0f56faff310a80 to your computer and use it in GitHub Desktop.
Save swick/968453815a1e918f0f0f56faff310a80 to your computer and use it in GitHub Desktop.
silverblue-devel-utils
#!/bin/sh
set -euo pipefail
#set -x
MICRODNF_PACKAGES_F38="https://kojipkgs.fedoraproject.org//packages/microdnf/3.9.0/2.fc38/x86_64/microdnf-3.9.0-2.fc38.x86_64.rpm \
https://kojipkgs.fedoraproject.org//packages/libpeas/1.34.0/3.fc38/x86_64/libpeas-1.34.0-3.fc38.x86_64.rpm \
https://kojipkgs.fedoraproject.org//packages/dnf/4.14.0/2.fc38/noarch/dnf-data-4.14.0-2.fc38.noarch.rpm \
https://kojipkgs.fedoraproject.org//packages/libdnf/0.68.0/2.fc38/x86_64/libdnf-0.68.0-2.fc38.x86_64.rpm"
MICRODNF_PACKAGES_F39="https://kojipkgs.fedoraproject.org/packages/microdnf/3.9.0/3.fc39/x86_64/microdnf-3.9.0-3.fc39.x86_64.rpm \
https://kojipkgs.fedoraproject.org/packages/dnf/4.17.0/6.fc39/noarch/dnf-data-4.17.0-6.fc39.noarch.rpm \
https://kojipkgs.fedoraproject.org/packages/libdnf/0.71.0/2.fc39/x86_64/libdnf-0.71.0-2.fc39.x86_64.rpm"
MICRODNF_PACKAGES_VAR="MICRODNF_PACKAGES_F$(source /etc/os-release && echo $VERSION_ID)"
MICRODNF_PACKAGES=${!MICRODNF_PACKAGES_VAR}
OCI_ARCHIVE_STORAGE="/var/lib/development-images/"
SELF="$(basename "$(test -L "$0" && readlink "$0" || echo "$0")")"
tmpdir=$(mktemp -d)
function cleanup () {
rm -rf -- "$tmpdir"
}
trap cleanup EXIT
function fail() {
printf '%s\n' "$1" >&2
exit "${2-1}"
}
function usage ()
{
echo "Utils for developing on a Silverblue system"
echo
echo "Syntax:"
echo "$SELF make_mutable [--temporary]"
echo "$SELF unmake_mutable"
echo "$SELF cleanup_mutable"
echo "$SELF rebase_image <IMAGE>"
echo
}
function install_dnf ()
{
install=""
command -v dnf &> /dev/null && return
for url in $MICRODNF_PACKAGES; do
package="$tmpdir/$(basename $url)"
curl --silent --show-error --remote-name-all --output-dir $tmpdir "$url" || fail "Failed to download package $url"
package_name=$(rpm -q --qf '%{name}' "$package")
rpm --quiet -q "$package_name" || install="$install $package"
done
if [ "$install" != "" ] ; then
sudo rpm -i --oldpackage $install
fi
if ! sudo microdnf --assumeyes install dnf python3-dnf-plugins* ; then
fail "Failed installing dnf and dnf-plugins!"
fi
}
function make_mutable ()
{
persistent="${1-persistent}"
ostree_flags=""
unlocked=$(rpm-ostree status --json | jq -r '.deployments[] | select (.booted==true) | .unlocked')
if [ "$persistent" == "persistent" ] ; then
[ "$unlocked" == "hotfix" ] && return
[ "$unlocked" != "none" ] && fail "The system is in another mutable state!"
sudo ostree admin unlock --hotfix
else
[ "$unlocked" == "development" ] && return
[ "$unlocked" != "none" ] && fail "The system is in another mutable state!"
sudo ostree admin unlock
fi
}
function unmake_mutable ()
{
unlocked=$(rpm-ostree status --json | jq -r '.deployments[] | select (.booted==true) | .unlocked')
if [ "$unlocked" == "hotfix" ] ; then
needs_rollback=$(rpm-ostree status --json | jq -r '.deployments[0].unlocked=="hotfix"')
[ $needs_rollback == "true" ] && sudo rpm-ostree rollback
echo "Reboot now to return to the previous state and then run '$SELF cleanup'"
return
fi
if [ "$unlocked" == "development" ] ; then
echo "The system is only in a temporary mutable state. Reboot to return to the previous state."
return
fi
fail "The system is not in a mutable state!"
}
function cleanup_mutable ()
{
should_cleanup=$(rpm-ostree status --json | jq -r '.deployments[1].unlocked == "hotfix" and .deployments[0].unlocked != "hotfix"')
if [ "$should_cleanup" == "true" ]; then
sudo rpm-ostree cleanup -r
else
echo "Not cleaning up"
fi
}
function rebase_image ()
{
image=$1
id=$(podman image inspect --format '{{ .Id }}' "$image") || fail "Inspecting image failed!"
image_name="${image#*/}"
image_name="${image_name%:*}-${id:0:10}"
oci_archive="${OCI_ARCHIVE_STORAGE}/${image_name}"
sudo rm -rf "${oci_archive}"
sudo mkdir -p "${oci_archive}"
podman save --format=oci-archive "${image}" | sudo tar -x -C "${oci_archive}"
sudo rpm-ostree rebase "ostree-unverified-image:oci:${oci_archive}"
current_origin=$(rpm-ostree status --json | jq -r '.deployments[] | select (.booted==true) | .origin')
echo "You can now reboot into your image!"
echo "Return to the current system by running 'rpm-ostree rebase $current_origin'."
}
if [ "$#" -lt 1 ] || [ "$1" == "--help" ] ; then
usage
exit
fi
mode=$1
shift
if [ "$mode" == "make_mutable" ] ; then
if [ "$#" -eq 1 ] && [ "$1" == "--temporary" ] ; then
make_mutable temporary
install_dnf
elif [ "$#" -ge 1 ] ; then
usage
fail "Unknown parameters!"
else
make_mutable
install_dnf
fi
elif [ "$mode" == "unmake_mutable" ] ; then
unmake_mutable
elif [ "$mode" == "cleanup_mutable" ] ; then
cleanup_mutable
elif [ "$mode" == "rebase_image" ] ; then
if [ "$#" -lt 1 ] ; then
usage
fail "Image parameter missing!"
fi
rebase_image "$1"
else
usage
fail "Unknown operation '$mode'!"
fi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment