#!/bin/sh -e # # 2011-2013 Nico Schottelius (nico-cdist at schottelius.org) # 2021 Dennis Camera (cdist at dtnr.ch) # # This file is part of cdist. # # cdist is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # cdist is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with cdist. If not, see . # # # Manage packages on Debian and co. # if [ -f "$__object/parameter/name" ]; then name="$(cat "$__object/parameter/name")" else name="$__object_id" fi state_should=$(cat "${__object:?}/parameter/state") version_should=$(cat "${__object:?}/parameter/version" 2>/dev/null) || true if [ -f "$__object/parameter/target-release" ]; then target_release="--target-release $(cat "$__object/parameter/target-release")" else target_release="" fi if [ -f "$__object/parameter/install-recommends" ]; then # required if __apt_norecommends is used recommendsparam="-o APT::Install-Recommends=1" else recommendsparam="-o APT::Install-Recommends=0" fi if [ -f "$__object/parameter/purge-if-absent" ]; then purgeparam="--purge" else purgeparam="" fi read -r state_is auto_state name_is version_is <"${__object:?}/explorer/state" # Hint if we need to avoid questions at some point: # DEBIAN_PRIORITY=critical can reduce the number of questions aptget="DEBIAN_FRONTEND=noninteractive apt-get --quiet --yes -o Dpkg::Options::=\"--force-confdef\" -o Dpkg::Options::=\"--force-confold\"" case ${state_should} in present) if test -n "${version_should}" -a "${version_should}" != "${version_is}" then # other version should be installed name="${name}=${version_should}" aptget="${aptget:?} -o APT::Get::allow-downgrades=true" elif test "${state_is}" = 'present' then if test "${auto_state}" = 'auto' then # package is installed, but marked auto -> mark it manual so # that it doesn't get removed by apt-get autoremove. # NOTE: There are two implementations of apt-mark(8) with a # different API. Although the new implementation (C++) still # supports the API of the old implementation (Python), it is # marked as deprecated: # https://salsa.debian.org/apt-team/apt/-/blob/0.8.15/cmdline/apt-mark.cc#L105 # # Debian < 5 (without apt-mark) don't need to be supported, # because the state explorer will report all packages as manual # for those. echo 'if ! head -n1 "$(command -v apt-mark)" | grep -qF python' # new C++ implementation (Debian >= 7) echo "then apt-mark manual '${name_is}' >/dev/null" # old Python implementation (Debian 5-6) echo "else apt-mark unmarkauto '${name_is}'" echo 'fi' fi # package already installed -> exit exit 0 fi # There are special arguments to apt(8) to prevent aborts if apt woudn't been # updated after the 19th April 2021 till the bullseye release. The additional # arguments acknoledge the happend suite change (the apt(8) update does the # same by itself). # # Using '-o $config' instead of the --allow-releaseinfo-change-* parameter # allows backward compatablility to pre-buster Debian versions. # # See more: ticket #861 # https://code.ungleich.ch/ungleich-public/cdist/-/issues/861 apt_opts="-o Acquire::AllowReleaseInfoChange::Suite=true -o Acquire::AllowReleaseInfoChange::Version=true" # following is bit ugly, but important hack. # due to how cdist config run works, there isn't # currently better way to do it :( cat << EOF if [ ! -f /var/cache/apt/pkgcache.bin ] || [ "\$( stat --format %Y /var/cache/apt/pkgcache.bin )" -lt "\$( date +%s -d '-1 day' )" ] then echo apt-get $apt_opts update > /dev/null 2>&1 || true fi EOF echo "${aptget} ${recommendsparam} install ${target_release} '${name}'" echo 'installed' >>"${__messages_out:?}" ;; absent) test "${state_is}" != 'absent' || exit 0 echo "${aptget} remove ${purgeparam} '${name_is}'" echo 'removed' >>"${__messages_out:?}" ;; *) echo "Unknown state: $state_should" >&2 exit 1 ;; esac