diff --git a/cdist/conf/type/__apt_pin/manifest b/cdist/conf/type/__apt_pin/manifest
index e72a8fdd..983b2b42 100755
--- a/cdist/conf/type/__apt_pin/manifest
+++ b/cdist/conf/type/__apt_pin/manifest
@@ -57,6 +57,11 @@ __file "/etc/apt/preferences.d/$name" \
--owner root --group root --mode 0644 \
--state "$state" \
--source - << EOF
+# Created by cdist ${__type##*/}
+# Do not change. Changes will be overwritten.
+#
+
+# $name
Package: $package
Pin: $pin
Pin-Priority: $priority
diff --git a/cdist/conf/type/__apt_pin/parameter/default/priority b/cdist/conf/type/__apt_pin/parameter/default/priority
new file mode 100644
index 00000000..1b79f38e
--- /dev/null
+++ b/cdist/conf/type/__apt_pin/parameter/default/priority
@@ -0,0 +1 @@
+500
diff --git a/cdist/conf/type/__apt_pin/parameter/optional b/cdist/conf/type/__apt_pin/parameter/optional
index 52f01fd2..847e703d 100644
--- a/cdist/conf/type/__apt_pin/parameter/optional
+++ b/cdist/conf/type/__apt_pin/parameter/optional
@@ -1,2 +1,3 @@
state
package
+priority
diff --git a/cdist/conf/type/__apt_pin/parameter/required b/cdist/conf/type/__apt_pin/parameter/required
index 4b4e9741..c8572d92 100644
--- a/cdist/conf/type/__apt_pin/parameter/required
+++ b/cdist/conf/type/__apt_pin/parameter/required
@@ -1,2 +1 @@
distribution
-priority
diff --git a/cdist/conf/type/__apt_source/gencode-remote b/cdist/conf/type/__apt_source/gencode-remote
index 1e8592c6..973b0f6c 100755
--- a/cdist/conf/type/__apt_source/gencode-remote
+++ b/cdist/conf/type/__apt_source/gencode-remote
@@ -22,7 +22,21 @@
name="$__object_id"
destination="/etc/apt/sources.list.d/${name}.list"
+# 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"
+
+# run 'apt-get update' only if something changed with our sources.list file
+# it will be run a second time on error as a redundancy messure to success
if grep -q "^__file${destination}" "$__messages_in"; then
- printf 'apt-get update || apt-get update\n'
+ printf 'apt-get %s update || apt-get %s update\n' "$apt_opts" "$apt_opts"
fi
diff --git a/cdist/conf/type/__apt_update_index/gencode-remote b/cdist/conf/type/__apt_update_index/gencode-remote
index 70b59710..2d7f9030 100755
--- a/cdist/conf/type/__apt_update_index/gencode-remote
+++ b/cdist/conf/type/__apt_update_index/gencode-remote
@@ -18,9 +18,23 @@
# along with cdist. If not, see .
#
+
+# 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"
+
# run 'apt-get update' if anything in /etc/apt is newer then /var/lib/apt/lists
+# it will be run a second time on error as a redundancy messure to success
cat << DONE
if find /etc/apt -mindepth 1 -cnewer /var/lib/apt/lists | grep . > /dev/null; then
- apt-get update || apt-get update
+ apt-get $apt_opts update || apt-get $apt_opts update
fi
DONE
diff --git a/cdist/conf/type/__debconf_set_selections/parameter/deprecated/file b/cdist/conf/type/__debconf_set_selections/parameter/deprecated/file
new file mode 100644
index 00000000..09db545a
--- /dev/null
+++ b/cdist/conf/type/__debconf_set_selections/parameter/deprecated/file
@@ -0,0 +1 @@
+'file' has been deprecated in favour of 'line' in order to provide idempotency.
diff --git a/cdist/conf/type/__debconf_set_selections/parameter/deprecated b/cdist/conf/type/__debconf_set_selections/parameter/optional
similarity index 100%
rename from cdist/conf/type/__debconf_set_selections/parameter/deprecated
rename to cdist/conf/type/__debconf_set_selections/parameter/optional
diff --git a/cdist/conf/type/__file/gencode-local b/cdist/conf/type/__file/gencode-local
index 231b6927..bea3d79c 100755
--- a/cdist/conf/type/__file/gencode-local
+++ b/cdist/conf/type/__file/gencode-local
@@ -1,7 +1,7 @@
#!/bin/sh -e
#
# 2011-2012 Nico Schottelius (nico-cdist at schottelius.org)
-# 2013 Steven Armstrong (steven-cdist armstrong.cc)
+# 2013-2022 Steven Armstrong (steven-cdist armstrong.cc)
#
# This file is part of cdist.
#
@@ -89,10 +89,26 @@ if [ "$state_should" = "present" ] || [ "$state_should" = "exists" ]; then
touch "$__object/files/set-attributes"
# upload file to temp location
- tempfile_template="${destination}.cdist.XXXXXXXXXX"
+ upload_destination="$(mktemp -u "${destination}.cdist.XXXXXXXXXX")"
+ # Yes, we are aware that this is a race condition.
+ # However:
+ # a) cdist usually writes to directories that are not user writable
+ # (probably > 99.9%)
+ # b) if they are user owned, the user / attacker always wins
+ # (probably < 0.1%)
+ # c) the only case which we could improve are tmp directories and we
+ # don't think managing tmp directories with cdist is a typical case
+ # ("the rest %)"
cat << DONE
-destination_upload="\$($__remote_exec $__target_host "mktemp $tempfile_template")"
+$__remote_exec $__target_host test -e $upload_destination && {
+ echo "Refusing to upload file to existing destination: $upload_destination" >&2
+ exit 1
+}
DONE
+ # Tell gencode-remote to where we uploaded the file so it can move
+ # it to its final destination.
+ echo "$upload_destination" > "$__object/files/upload-destination"
+
if [ "$upload_file" ]; then
echo upload >> "$__messages_out"
# IPv6 fix
@@ -103,12 +119,8 @@ DONE
my_target_host="${__target_host}"
fi
cat << DONE
-$__remote_copy "$source" "${my_target_host}:\$destination_upload"
+$__remote_copy "$source" "${my_target_host}:${upload_destination}"
DONE
fi
-# move uploaded file into place
-cat << DONE
-$__remote_exec $__target_host "rm -rf \"$destination\"; mv \"\$destination_upload\" \"$destination\""
-DONE
fi
fi
diff --git a/cdist/conf/type/__file/gencode-remote b/cdist/conf/type/__file/gencode-remote
index f7a528fd..136520a7 100755
--- a/cdist/conf/type/__file/gencode-remote
+++ b/cdist/conf/type/__file/gencode-remote
@@ -1,7 +1,7 @@
#!/bin/sh -e
#
# 2011-2013 Nico Schottelius (nico-cdist at schottelius.org)
-# 2013 Steven Armstrong (steven-cdist armstrong.cc)
+# 2013-2022 Steven Armstrong (steven-cdist armstrong.cc)
#
# This file is part of cdist.
#
@@ -62,6 +62,13 @@ set_mode() {
case "$state_should" in
present|exists)
+ if [ -f "$__object/files/upload-destination" ]; then
+ final_destination="$destination"
+ # We change the 'global' $destination variable here so we can
+ # change attributes of the new/uploaded file before moving it
+ # to it's final destination.
+ destination="$(cat "$__object/files/upload-destination")"
+ fi
# Note: Mode - needs to happen last as a chown/chgrp can alter mode by
# clearing S_ISUID and S_ISGID bits (see chown(2))
for attribute in group owner mode; do
@@ -81,6 +88,11 @@ case "$state_should" in
fi
fi
done
+ if [ -f "$__object/files/upload-destination" ]; then
+ # move uploaded file into place
+ printf 'rm -rf "%s"\n' "$final_destination"
+ printf 'mv -T "%s" "%s"\n' "$destination" "$final_destination"
+ fi
if [ -f "$__object/files/set-attributes" ]; then
# set-attributes is created if file is created or uploaded in gencode-local
fire_onchange=1
diff --git a/cdist/conf/type/__grafana_dashboard/manifest b/cdist/conf/type/__grafana_dashboard/manifest
index d145c4c3..0d944482 100755
--- a/cdist/conf/type/__grafana_dashboard/manifest
+++ b/cdist/conf/type/__grafana_dashboard/manifest
@@ -15,7 +15,7 @@ case $os in
# Differntation not needed anymore
apt_source_distribution=stable
;;
- 10*)
+ 10*|11*)
# Differntation not needed anymore
apt_source_distribution=stable
;;
diff --git a/cdist/conf/type/__haproxy_dualstack/files/http b/cdist/conf/type/__haproxy_dualstack/files/http
new file mode 100644
index 00000000..0508a465
--- /dev/null
+++ b/cdist/conf/type/__haproxy_dualstack/files/http
@@ -0,0 +1,8 @@
+frontend http
+ bind BIND@:80
+ mode http
+ option httplog
+ default_backend http
+
+backend http
+ mode http
diff --git a/cdist/conf/type/__haproxy_dualstack/files/https b/cdist/conf/type/__haproxy_dualstack/files/https
new file mode 100644
index 00000000..73deac46
--- /dev/null
+++ b/cdist/conf/type/__haproxy_dualstack/files/https
@@ -0,0 +1,10 @@
+frontend https
+ bind BIND@:443
+ mode tcp
+ option tcplog
+ tcp-request inspect-delay 5s
+ tcp-request content accept if { req_ssl_hello_type 1 }
+ default_backend https
+
+backend https
+ mode tcp
diff --git a/cdist/conf/type/__haproxy_dualstack/files/imaps b/cdist/conf/type/__haproxy_dualstack/files/imaps
new file mode 100644
index 00000000..b1ec3793
--- /dev/null
+++ b/cdist/conf/type/__haproxy_dualstack/files/imaps
@@ -0,0 +1,12 @@
+frontend imaps
+ bind BIND@:143
+ bind BIND@:993
+
+ mode tcp
+ option tcplog
+ tcp-request inspect-delay 5s
+ tcp-request content accept if { req_ssl_hello_type 1 }
+ default_backend imaps
+
+backend imaps
+ mode tcp
diff --git a/cdist/conf/type/__haproxy_dualstack/files/smtps b/cdist/conf/type/__haproxy_dualstack/files/smtps
new file mode 100644
index 00000000..dce6ed4a
--- /dev/null
+++ b/cdist/conf/type/__haproxy_dualstack/files/smtps
@@ -0,0 +1,12 @@
+frontend smtps
+ bind BIND@:25
+ bind BIND@:465
+
+ mode tcp
+ option tcplog
+ tcp-request inspect-delay 5s
+ tcp-request content accept if { req_ssl_hello_type 1 }
+ default_backend smtps
+
+backend smtps
+ mode tcp
diff --git a/cdist/conf/type/__haproxy_dualstack/man.rst b/cdist/conf/type/__haproxy_dualstack/man.rst
new file mode 100644
index 00000000..6c131cbe
--- /dev/null
+++ b/cdist/conf/type/__haproxy_dualstack/man.rst
@@ -0,0 +1,121 @@
+cdist-type__haproxy_dualstack(7)
+================================
+
+
+NAME
+----
+cdist-type__haproxy_dualstack - Proxy services from a dual-stack server
+
+
+DESCRIPTION
+-----------
+This (singleton) type installs and configures haproxy to act as a dual-stack
+proxy for single-stack services.
+
+This can be useful to add IPv4 support to IPv6-only services while only using
+one IPv4 for many such services.
+
+By default this type uses the plain TCP proxy mode, which means that there is no
+need for TLS termination on this host when SNI is supported.
+This also means that proxied services will not receive the client's IP address,
+but will see the proxy's IP address instead (that of `$__target_host`).
+
+This can be solved by using the PROXY protocol, but do take into account that,
+e.g. nginx cannot serve both regular HTTP(S) and PROXY protocols on the same
+port, so you will need to use other ports for that.
+
+As a recommendation in this type: use TCP ports 8080 and 591 respectively to
+serve HTTP and HTTPS using the PROXY protocol.
+
+See the EXAMPLES for more details.
+
+
+OPTIONAL PARAMETERS
+-------------------
+v4proxy
+ Proxy incoming IPv4 connections to the equivalent IPv6 endpoint.
+ In its simplest use, it must be a NAME with an `AAAA` DNS entry, which is
+ the IP address actually providing the proxied services.
+ The full format of this argument is:
+ `[proxy:]NAME[[:PROTOCOL_1=PORT_1]...[:PROTOCOL_N=PORT_N]]`
+ Where starting with `proxy:` determines that the PROXY protocol must be
+ used and each `:PROTOCOL=PORT` (e.g. `:http=8080` or `:https=591`) is a PORT
+ override for the given PROTOCOL (see `--protocol`), if not present the
+ PROTOCOL's default port will be used.
+
+
+v6proxy
+ Proxy incoming IPv6 connections to the equivalent IPv4 endpoint.
+ In its simplest use, it must be a NAME with an `A` DNS entry, which is
+ the IP address actually providing the proxied services.
+ See `--v4proxy` for more options and details.
+
+protocol
+ Can be passed multiple times or as a space-separated list of protocols.
+ Currently supported protocols are: `http`, `https`, `imaps`, `smtps`.
+ This defaults to: `http https imaps smtps`.
+
+
+EXAMPLES
+--------
+
+.. code-block:: sh
+
+ # Proxy the IPv6-only services so IPv4-only clients can access them
+ # This uses HAProxy's TCP mode for http, https, imaps and smtps
+ __haproxy_dualstack \
+ --v4proxy ipv6.chat \
+ --v4proxy matrix.ungleich.ch
+
+ # Proxy the IPv6-only HTTP(S) services so IPv4-only clients can access them
+ # Note this means that the backend IPv6-only server will only see
+ # the IPv6 address of the haproxy host managed by cdist, which can be
+ # troublesome if this information is relevant for analytics/security/...
+ # See the PROXY example below
+ __haproxy_dualstack \
+ --protocol http --protocol https \
+ --v4proxy ipv6.chat \
+ --v4proxy matrix.ungleich.ch
+
+ # Use the PROXY protocol to proxy the IPv6-only HTTP(S) services enabling
+ # IPv4-only clients to access them while maintaining the client's IP address
+ __haproxy_dualstack \
+ --protocol http --protocol https \
+ --v4proxy proxy:ipv6.chat:http=8080:https=591 \
+ --v4proxy proxy:matrix.ungleich.ch:http=8080:https=591
+ # Note however that the PROXY protocol is not compatible with regular
+ # HTTP(S) protocols, so your nginx will have to listen on different ports
+ # with the PROXY settings.
+ # Note that you will need to restrict access to the 8080 port to prevent
+ # Client IP spoofing.
+ # This can be something like:
+ # server {
+ # # listen for regular HTTP connections
+ # listen [::]:80 default_server;
+ # listen 80 default_server;
+ # # listen for PROXY HTTP connections
+ # listen [::]:8080 proxy_protocol;
+ # # Accept the Client's IP from the PROXY protocol
+ # real_ip_header proxy_protocol;
+ # }
+
+
+SEE ALSO
+--------
+- https://www.haproxy.com/blog/enhanced-ssl-load-balancing-with-server-name-indication-sni-tls-extension/
+- https://www.haproxy.com/blog/haproxy/proxy-protocol/
+- https://docs.nginx.com/nginx/admin-guide/load-balancer/using-proxy-protocol/
+
+
+AUTHORS
+-------
+ungleich
+Evilham
+
+
+COPYING
+-------
+Copyright \(C) 2021 ungleich glarus ag. 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.
diff --git a/cdist/conf/type/__haproxy_dualstack/manifest b/cdist/conf/type/__haproxy_dualstack/manifest
new file mode 100644
index 00000000..d110eea6
--- /dev/null
+++ b/cdist/conf/type/__haproxy_dualstack/manifest
@@ -0,0 +1,155 @@
+#!/bin/sh -eu
+
+__package haproxy
+require="__package/haproxy" __start_on_boot haproxy
+
+tmpdir="$__object/files"
+mkdir "$tmpdir"
+configtmp="$__object/files/haproxy.cfg"
+
+os=$(cat "$__global/explorer/os")
+case $os in
+ freebsd)
+ CONFIG_FILE="/usr/local/etc/haproxy.conf"
+ cat < "$configtmp"
+global
+ maxconn 4000
+ user nobody
+ group nogroup
+ daemon
+
+EOF
+
+ ;;
+ *)
+ CONFIG_FILE="/etc/haproxy/haproxy.cfg"
+ cat < "$configtmp"
+global
+ log [::1] local2
+ chroot /var/lib/haproxy
+ pidfile /var/run/haproxy.pid
+ maxconn 4000
+ user haproxy
+ group haproxy
+ daemon
+
+ # turn on stats unix socket
+ stats socket /var/lib/haproxy/stats
+
+EOF
+ ;;
+esac
+
+cat <> "$configtmp"
+defaults
+ retries 3
+ log global
+ timeout http-request 10s
+ timeout queue 1m
+ timeout connect 10s
+ timeout client 1m
+ timeout server 1m
+ timeout http-keep-alive 10s
+ timeout check 10s
+EOF
+
+dig_cmd="$(command -v dig || true)"
+get_ip() {
+ # Usage: get_ip (ipv4|ipv6) NAME
+ # uses "dig" if available, else fallback to "host"
+ case $1 in
+ ipv4)
+ if [ -n "${dig_cmd}" ]; then
+ ${dig_cmd} +short A "$2"
+ else
+ host -t A "$2" | cut -d ' ' -f 4 | grep -v 'found:'
+ fi
+ ;;
+ ipv6)
+ if [ -n "${dig_cmd}" ]; then
+ ${dig_cmd} +short AAAA "$2"
+ else
+ host -t AAAA "$2" | cut -d ' ' -f 5 | grep -v 'NXDOMAIN'
+ fi
+ ;;
+ esac
+}
+
+PROTOCOLS="$(cat "$__object/parameter/protocol")"
+
+for proxy in v4proxy v6proxy; do
+ param=$__object/parameter/$proxy
+ # no backend? skip generating code
+ if [ ! -f "$param" ]; then
+ continue
+ fi
+
+ # turn backend name into bind parameter: v4backend -> ipv4@
+ bind=$(echo $proxy | sed -e 's/^/ip/' -e 's/proxy//')
+
+ case $bind in
+ ipv4)
+ backendproto=ipv6
+ ;;
+ ipv6)
+ backendproto=ipv4
+ ;;
+ esac
+
+ for proto in ${PROTOCOLS}; do
+ # Add protocol "header"
+ printf "\n# %s %s \n" "${bind}" "${proto}" >> "$configtmp"
+
+ sed -e "s/BIND/$bind/" \
+ -e "s/\(frontend[[:space:]].*\)/\1$bind/" \
+ -e "s/\(backend[[:space:]].*\)/\\1$bind/" \
+ "$__type/files/$proto" >> "$configtmp"
+
+ while read -r hostdefinition; do
+ if echo "$hostdefinition" | grep -qE '^proxy:'; then
+ # Proxy protocol was requested
+ host="$(echo "$hostdefinition" | sed -E 's/^proxy:([^:]+).*$/\1/')"
+ send_proxy=" send-proxy"
+ else
+ # Just use tcp proxy mode
+ host="$hostdefinition"
+ send_proxy=""
+ fi
+ if echo "$hostdefinition" | grep -qE ":${proto}="; then
+ # Use custom port definition if requested
+ port="$(echo "$hostdefinition" | sed -E "s/^(.*:)?${proto}=([0-9]+).*$/:\2/")"
+ else
+ # Else use the default
+ port=""
+ fi
+ servername=$host
+
+ res=$(get_ip "$bind" "$servername")
+
+ if [ -z "$res" ]; then
+ echo "$servername does not resolve - aborting config" >&2
+ exit 1
+ fi
+
+ # Treat protocols without TLS+SNI specially
+ if [ "$proto" = http ]; then
+ echo " use-server $servername if { hdr(host) -i $host }" >> "$configtmp"
+ else
+ echo " use-server $servername if { req_ssl_sni -i $host }" >> "$configtmp"
+ fi
+
+ # Create the "server" itself.
+ # Note that port and send_proxy will be empty unless
+ # they were requested by the type user
+ echo " server $servername ${backendproto}@${host}${port}${send_proxy}" >> "$configtmp"
+
+ done < "$param"
+ done
+done
+
+# Create config file
+require="__package/haproxy" __file ${CONFIG_FILE} --source "$configtmp" --mode 0644
+
+require="__file${CONFIG_FILE}" __check_messages "haproxy_reload" \
+ --pattern "^__file${CONFIG_FILE}" \
+ --execute "service haproxy reload || service haproxy restart"
diff --git a/cdist/conf/type/__haproxy_dualstack/parameter/default/protocol b/cdist/conf/type/__haproxy_dualstack/parameter/default/protocol
new file mode 100644
index 00000000..dc8bb7bf
--- /dev/null
+++ b/cdist/conf/type/__haproxy_dualstack/parameter/default/protocol
@@ -0,0 +1 @@
+http https imaps smtps
diff --git a/cdist/conf/type/__haproxy_dualstack/parameter/optional_multiple b/cdist/conf/type/__haproxy_dualstack/parameter/optional_multiple
new file mode 100644
index 00000000..8c482bd4
--- /dev/null
+++ b/cdist/conf/type/__haproxy_dualstack/parameter/optional_multiple
@@ -0,0 +1,3 @@
+protocol
+v4proxy
+v6proxy
diff --git a/cdist/conf/type/__ini_value/nonparallel b/cdist/conf/type/__haproxy_dualstack/singleton
similarity index 100%
rename from cdist/conf/type/__ini_value/nonparallel
rename to cdist/conf/type/__haproxy_dualstack/singleton
diff --git a/cdist/conf/type/__ini_value/explorer/state b/cdist/conf/type/__ini_value/explorer/state
deleted file mode 100755
index 507cabe9..00000000
--- a/cdist/conf/type/__ini_value/explorer/state
+++ /dev/null
@@ -1,165 +0,0 @@
-#!/bin/sh -e
-# __ini_value/explorer/state
-
-# Check the state of the key-value pair in the ini file
-#
-# There are following states:
-# - present
-# - wrongvalue
-# - wrongformat
-# - commented
-# - absent
-# - nosuchfile
-
-# Using ' \t' for matching spaces as char classes not implemented in mawk
-# see https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=65617#40
-
-# Parameters
-# (maybe multi-variable object id for this ..)
-#state_should="$(cat "$__object/parameter/state")"
-file="$(cat "$__object/parameter/file")"
-
-# abort if no file exist
-if ! [ -f "$file" ]; then
- echo absent
- exit
-fi
-
-# run awk
-awk -f - "$file" <<'AWK'
-function trim(var) {
- sub(/^[ \t]*/, "", var)
- sub(/[ \t]*$/, "", var)
- return var
-}
-function check_spaces(var) {
- return match(var, /^[ \t]*$/) == 1
-}
-function state(val) {
- print val
- exit
-}
-
-BEGIN {
- _param = (ENVIRON["__object"] "/parameter/")
- getline state_should < (_param "state")
- getline section < (_param "section")
- getline key < (_param "key")
- getline delimiter < (_param "delimiter")
- getline value < (_param "value")
- getline indentation < (_param "indentation")
- getline delimiter_space < (_param "delimiter-space")
-
- do_normalization = (system("test -f " (_param "normalize")) == 0)
-
- i=0; _comm_param = (_param "comment-sign");
- while((getline tmp < _comm_param) > 0) {
- comment_signs[i++] = tmp
- }
-
- if(system("test -f " (_param "quote")) == 0) {
- # quote it now that it only wins checks against quoted values
- value = ("\"" value "\"")
- }
-
- found=0
- curr_section=""
- if(section == "")
- found_section=1
- else
- found_section=0
-}
-
-# catch sections
-/^[ \t]*\[.*\][ \t]*$/ {
- curr_section = trim($0)
- if(found_section)
- exit # game over, section ends
- if(section == curr_section)
- found_section=1
- next
-}
-
-# only interesting if a delimiter was found
-found_section {
- line = $0
-
- # index 1 cause of trimmed string
- if((idel = index(line, delimiter)) && (ikey = index(line, key))) {
- is_com=0
- if(ikey > 1) {
- # maybe comment character or only spaces
- start_string = substr(line, 1, ikey - 1)
-
- # something inside rather than a space -> comment
- if((icom = match(start_string, /[^ \t]+/)) > 0) {
- # icom = RSTART
- # only one free-standing char or directly before the key
- if(RLENGTH == 1 || icom == ikey - 1) {
- start_sign = substr(line, RSTART, 1)
- for(i in comment_signs) {
- if(start_sign == comment_signs[i]) {
- is_com = 1; break;
- }
- }
- if(!is_com) next
- else {
- aftercom_length = ikey - icom - 1
- if(!check_spaces(substr(line, icom + 1, aftercom_length))) next
- start_spaces = (icom - 1) + aftercom_length
- }
- }
- else next
- }
- # must only contain spaces
- else start_spaces = ikey - 1
- }
-
- idelspace_start = ikey + length(key)
- idelspace_length = idel - idelspace_start
- # check for delimiter is only preceded with spaces
- if(idelspace_length == 0 || check_spaces(substr(line, idelspace_start, idelspace_length))) {
- found = 1
-
- # short-circuit on state absent to just delete
- if(state_should == "absent") state("present");
-
-
- # extract the value
- found_value = substr(line, idel + length(delimiter))
- is_value = trim(found_value)
-
- # check if value is incorrect
- if(value != is_value) state("wrongvalue")
- else {
- # check if the format is important
- if(do_normalization) {
- if(match(found_value, /^[ \t]+/) == 1) {
- found_value = substr(found_value, 1 + RLENGTH)
- del_val_spacelen = RLENGTH
- }
- else
- del_val_spacelen = 0
-
- # the format must exactly match, else it is incorrect
- if(start_spaces != indentation || found_value != is_value ||
- idelspace_length != delimiter_space || del_val_spacelen != delimiter_space)
- state("wrongformat")
- }
-
- if(is_com)
- state("commented")
- else
- state("present")
- }
- # this will never be reached
- }
- }
-}
-
-# in the end, check if it is absent
-END {
- if(!found)
- state("absent")
-}
-AWK
diff --git a/cdist/conf/type/__ini_value/files/base.awk b/cdist/conf/type/__ini_value/files/base.awk
deleted file mode 100644
index ddc52949..00000000
--- a/cdist/conf/type/__ini_value/files/base.awk
+++ /dev/null
@@ -1,138 +0,0 @@
-BEGIN {
- bufindex = -1
- buflen = 0
- maxbuflen = 10
-
- # no section means the start to the first section
- if(section == "") {
- is_curr_section = 1
- found_section = 1
- }
-}
-
-# controls the line buffer
-function flush_buffer() {
- while(buflen > 0)
- _pop_line()
-}
-function flush_lines(n) {
- while(buflen > 0 && n-- > 0)
- _pop_line()
-}
-function push_line() {
- linebuf[++bufindex] = $0
- buflen++
- while(buflen > maxbuflen) _pop_line()
-}
-function revert_line() {
- # no delete, because it will be overwritten by the next line if any ..
- bufindex--
- buflen--
-}
-function lastline() {
- if(buflen > 0) return linebuf[bufindex]
-}
-function pop_line() {
- if(buflen > 0) _pop_line()
-}
-function _pop_line() {
- _index = bufindex - (--buflen)
- print linebuf[_index]
- delete linebuf[_index]
-}
-
-# excepts the first character is the sign to check (string is trimmed)
-function is_comment(line) {
- # get character and check
- line_sign = substr(line, 1, 1)
- for(c in comment_signs)
- if(line_sign == comment_signs[c])
- return 1
-
- # nothing found
- return 0
-}
-function was_comment(line, comment) {
- line = trim(line)
- if(is_comment(line)) {
- return trim(substr(line, 2)) == comment
- }
-}
-
-# print everything if line found instead of processing it
-# maybe just a function to loop through getline for lightest overhead
-found {print; next}
-
-# main loop (til the line was found)
-!found {
- line = trim($0)
- # process if the line is not empty (or only contains spaces)
- if(line != "") {
- # check for a ini section
- if(substr(line, 1, 1) == "[" && substr(line, length(line), 1) == "]") {
- is_section = 1
- curr_section = line
-
- if(curr_section == section) {
- found_section = 1
- is_curr_section = 1
- }
- else {
- # if nothing found, print it in the valid section before the next one
- if(is_curr_section) {
- if(!found) {
- # set found as it is there now
- found=1
-
- # %codeblock_insert%
-
- # print line as it would else only be populated below
- print
- next
- }
- is_curr_section = 0
- }
- }
- }
- else {
- # only current session is interessting
- if(is_curr_section) {
- # check for a comment
- is_com = is_comment(line)
- if(is_com) {
- line = trim(substr(line, 2))
- }
-
- # check for a delimiter and a key (must be at first position due to trimming)
- if((idel = index(line, delimiter)) && (ikey = index(line, key)) == 1) {
- # check there are only spaces between the key and delimiter
- if(check_spaces(substr(line, ikey + length(key), idel - (length(key) + 1)))) {
- found = 1
-
- # %codeblock_found%
-
- next
- }
- }
- }
- }
- }
-
- # works cause no next statement from above *structual programming*
- push_line()
-}
-
-END {
- # if not found, it's not already printed
- if(!found) {
- flush_buffer()
-
- # print with section if not found
- if(!found_section) {
- # TODO check via buffer if a empty line is necessary
- print section
-
- # %codeblock_insert%
- }
- }
-}
diff --git a/cdist/conf/type/__ini_value/files/comment.awk b/cdist/conf/type/__ini_value/files/comment.awk
deleted file mode 100644
index 1d3c04b7..00000000
--- a/cdist/conf/type/__ini_value/files/comment.awk
+++ /dev/null
@@ -1,57 +0,0 @@
-# We try to find a comment block -- how?
-# check how much paragraphs it has
-# check if
-#
-# this code is crap - at least not well written
-
-# Check the buffer if the comment was found
-function check_comments() {
- _lastline = bufindex - (buflen - 1)
- _comm_size = length(comments)
-
- lastfreeline = 0
- lastfreecommline = 0
- comm_index = 0
-
- # go through all lines
- for(i = bufindex; i < _lastline; i++) {
- _line = trim(linebuf[i])
-
- # empty line?
- if(_line == "") {
- lastfreeline = i
- continue
- }
-
- # line start matched
- if(_line == trim(comments[comm_index])) {
- # end? else continue
- if(comm_index < _comm_size) {
- continue
- }
- else {
-
- }
- }
- # reset again cause not matched
- else comm_index = 0
-
- # empty comment line
- if(is_comment(_line)) {
- _comment = trim(substr(_line, 2))
-
- # check if empty comment
- if(_comment == "") {
- lastfreecommline = i
- }
- }
-
- # check if comments fit in or is too big
- if((_lastline - bufindex) < _comm_size) {
- # too short
- }
- else {
- #if()
- }
- }
-}
diff --git a/cdist/conf/type/__ini_value/files/common.awk b/cdist/conf/type/__ini_value/files/common.awk
deleted file mode 100644
index bc51e0b8..00000000
--- a/cdist/conf/type/__ini_value/files/common.awk
+++ /dev/null
@@ -1,68 +0,0 @@
-BEGIN {
- # parameter variables
- section = get_param_string("section")
- key = get_param_string("key")
- delimiter = get_param_string("delimiter")
- value = get_param_string("value")
- comment = get_param_string("comment")
- indentation = get_param_string("indentation")
- delimiter_space = get_param_string("delimiter-space")
-
- get_param_array("comment-sign", comment_signs)
- comment_sign = comment_signs[0]
-
- if(system("test -f " (ENVIRON["__object"] "/parameter/quote")) == 0) {
- # quote it now that it only wins checks against quoted values
- value = ("\"" value "\"")
- }
-
- base_spaces = spaces(indentation)
- delimiter_spaces = spaces(delimiter_space)
- delimiter_w_spaces = (delimiter_spaces delimiter delimiter_spaces)
-}
-
-function trim(var) {
- sub(/^[ \t]*/, "", var)
- sub(/[ \t]*$/, "", var)
- return var
-}
-function spaces(a) {
- rspaces = ""
- for(b = 0; b < a; b++)
- rspaces = (rspaces " ")
- return rspaces
-}
-function check_spaces(part) {
- return match(part, /^[ \t]*$/) == 1
-}
-
-function get_param_string(name) {
- _paramfile = (ENVIRON["__object"] "/parameter/" name)
- if((getline tmp < _paramfile) > 0) {
- close(_paramfile)
- return tmp
- }
- else return ""
-}
-function get_param_array(name, arr) {
- _paramfile = (ENVIRON["__object"] "/parameter/" name)
- i=0
- split("", arr) # portable clear, like `delete arr`
- while((getline tmp < _paramfile) > 0) {
- arr[i++] = tmp
- }
- close(_paramfile)
-}
-
-# print value
-function v_print() {
- printf "%s%s%s%s%s", base_spaces, key, delimiter_w_spaces, value, ORS
-}
-# print commented value
-function v_print_commented() {
- printf "%s%s%s%s%s%s", base_spaces, comment_sign, key, delimiter_w_spaces, value, ORS
-}
-# print comment
-function c_print() {
- printf "%s%s %s%s", base_spaces, comment_sign, comment, ORS
-}
diff --git a/cdist/conf/type/__ini_value/files/parts/absent/found.awk b/cdist/conf/type/__ini_value/files/parts/absent/found.awk
deleted file mode 100644
index 0f907b54..00000000
--- a/cdist/conf/type/__ini_value/files/parts/absent/found.awk
+++ /dev/null
@@ -1,5 +0,0 @@
-# revert line if it was a comment
-if(was_comment(lastline, comment)) revert_line()
-
-# value line was not pushed to the buffer yet
-flush_buffer()
diff --git a/cdist/conf/type/__ini_value/files/parts/commented b/cdist/conf/type/__ini_value/files/parts/commented
deleted file mode 120000
index 568612b9..00000000
--- a/cdist/conf/type/__ini_value/files/parts/commented
+++ /dev/null
@@ -1 +0,0 @@
-present
\ No newline at end of file
diff --git a/cdist/conf/type/__ini_value/files/parts/present/found.awk b/cdist/conf/type/__ini_value/files/parts/present/found.awk
deleted file mode 100644
index 4e456bbb..00000000
--- a/cdist/conf/type/__ini_value/files/parts/present/found.awk
+++ /dev/null
@@ -1,8 +0,0 @@
-# check if last line was the comment
-was_com_there = was_comment(lastline(), comment)
-
-# print + comment if not there
-flush_buffer()
-if(comment && !was_com_there) c_print()
-
-# %code_print%
diff --git a/cdist/conf/type/__ini_value/files/parts/present/insert.awk b/cdist/conf/type/__ini_value/files/parts/present/insert.awk
deleted file mode 100644
index 9cb70327..00000000
--- a/cdist/conf/type/__ini_value/files/parts/present/insert.awk
+++ /dev/null
@@ -1,56 +0,0 @@
-# check if there is a comment block before the section
-firstline_index = bufindex - (buflen - 1)
-insertpoint = -1 # the insertpoint marks the point before the insert
-lastfreespace = -1
-for(i = bufindex; i >= firstline_index; i--) {
- _line = trim(linebuf[i])
- if(_line == "") {
- lastfreespace = i
- continue
- }
- if(comment && was_comment(_line, comment)) {
- insertpoint = i + 1
- no_insert_comment = 1
- if(lastfreespace != insertpoint)
- insert_line_after = 1
- break
- }
- if(!is_comment(_line) || index(_line, delimiter) > 0) {
- insertpoint = i + 1
-
- # only insert a line before if we do not have a space around
- if(lastfreespace == insertpoint)
- insertpoint++
- else
- insert_line_before = 1
- # check for empty line after the insert point
- # use absolute boundary cause the insertpoint can be changed
- if(trim(linebuf[i + 2]) != "")
- insert_line_after = 1
- break
- }
-}
-
-# insert into the last free space
-if(insertpoint == -1) {
- if(lastfreespace != -1) {
- insertpoint = lastfreespace
- insert_line_before = 1
- }
- else {
- insertpoint = firstline_index
- insert_line_after = 1
- }
-}
-
-# print lines before
-flush_lines(insertpoint - firstline_index)
-
-
-# print before and comment
-if(insert_line_before) print ""
-if(comment && !no_insert_comment) c_print()
-# %code_print%
-if(insert_line_after) print ""
-
-flush_buffer()
diff --git a/cdist/conf/type/__ini_value/gencode-remote b/cdist/conf/type/__ini_value/gencode-remote
deleted file mode 100755
index ab93077e..00000000
--- a/cdist/conf/type/__ini_value/gencode-remote
+++ /dev/null
@@ -1,82 +0,0 @@
-#!/bin/sh -e
-# __ini_value/gencode-remote
-#
-# Generates the code. It will generate an AWK script to add, modify or remove
-# the line. The script differ in some points depend on the state. If the file
-# does not exist, it will only generate the script without the awk overhead.
-
-# strip comments and newlines for a tighter script
-strip_comments() {
- grep -v '^[[:space:]]*\($\|#\)'
-}
-
-
-state_is="$(cat "$__object/explorer/state")"
-state_should="$(cat "$__object/parameter/state")"
-
-# short-circuit if nothing to do
-if [ "$state_is" = "$state_should" ]; then exit; fi
-
-# file to change
-file="$(cat "$__object/parameter/file")"
-
-
-# validation check
-case "$state_should" in
- present|commented|absent)
- # Generate the basic awk struct if a file already exists
- cat < "\$tmpfile" <<'AWK'
-SHELL
-
- # generate the awk script and strip unnecessary things
- {
- # basic functions which everyone needs
- cat "$__type/files/common.awk"
-
- # generate the script
- awk -v state="$state_should" '
- function parse(line) {
- if(match(line, /^[ \t]*# %code_print%$/) > 0) {
- if(state == "present")
- print "v_print()"
- else if(state == "commented")
- print "v_print_commented()"
- else
- print "print \"script compile error! cdist state " state " unkown!\" > /dev/stderr"
- }
- else print line
- }
- {
- if(match($0, /^[ \t]*# %codeblock_([^%]+)%$/) > 0) {
- split($2, result, "_"); type = substr(result[2], 1, length(result[2]) - 1)
- file = (ENVIRON["__type"] "/files/parts/" state "/" type ".awk")
- while((getline line < file) > 0)
- parse(line)
- close(file)
- }
- else print
- }' "$__type/files/base.awk"
- } | strip_comments
-
- # end of here-doc
- cat <&2
- exit 1
- ;;
-esac
diff --git a/cdist/conf/type/__ini_value/man.rst b/cdist/conf/type/__ini_value/man.rst
deleted file mode 100644
index 38a8d67c..00000000
--- a/cdist/conf/type/__ini_value/man.rst
+++ /dev/null
@@ -1,139 +0,0 @@
-cdist-type__ini_value(7)
-========================
-
-NAME
-----
-cdist-type__ini_value - Handles ini- and conf-style configuration options
-
-
-DESCRIPTION
------------
-This cdist type allow changes to more advanced key-value based configurations.
-Most commonly this would be ini- or conf-style configurations.
-
-The type can have following states:
-
- present
- The line exists with the correct value.
-
- commented
- The key-value is outcommented.
-
- absent
- The key-value line does not exist in the given section.
-
-
-REQUIRED PARAMETERS
--------------------
-file
- The file to modify.
-
-delimiter
- The delimiter which seperates each key-value pair.
-
-
-OPTIONAL PARAMETERS
--------------------
-state
- One of the states defined in the above section. Defaults to `present`.
-
-section
- The section where the value is located at. It always need to be surrounded
- by square brackets as common for ini files. If not, the section will not be
- found. If no section is specified, the block before any section is meant.
-
-key
- The key to identify the key-value pair. Must be set if the state is not
- absent.
-
-value
- The value assigned to the key. Must be set if the state is not absent.
- Else, an empty value is assigned to the given key.
-
-comment
- The comment which should be placed above the configuration line.
-
-indentation
- The indentation the key-value pair should have. Will be applied on inserts,
- but also be enforced if ``--normalize`` is set.
-
-comment-sign
- This declares the comment signs that are valid to use in the configuration
- file. Each parameter must declare a single character only; multiple
- parameters are possible. It uses the first specified sign as comment
- character if this type needs to insert comments.
-
-delimiter-space
- The number of spaces before and after the delimiter which should be free.
- This number applies to each site of the delimiter separately, so one space
- means one space to the left and right side of the delimiter.
-
- The delimiter will be matched independendtly of this parameter and will
- only be corrected if ``--normalize`` is set.
-
-
-BOOLEAN PARAMETERS
-------------------
-normalize
- This parameter enforces that the parameter is always pretty in the
- configuration file. Even if a key-value pair is correct as-is, it will
- correct the line to be pretty and perfect.
-
-quote
- Wrap double quotes (``"``) around the value. If the value is previously
- unquoted, the file will be modified to quote the value.
-
-
-MESSAGES
---------
-The type currently fails to give a correct information of what he did cause of
-the following construct. It has two `awk` scripts which do the job:
-
-1. The explorer script which will outputs a single state of the given
- key-value. Because the current state can contain much more states than the
- state that should be, one state is returned like `wrongvalue` even if
- `commented` is correct, too. Therefor, it vanishes the information that the
- line is commented, too, even this could be a nice information that the
- messaging system could emit.
-
-2. The `code-remote` script also goes through the whole file and print out the
- same file except the line line that should be changed. This is done because
- it can not be garanteed that an other type already modifed the file, which
- may moved the key-value to an other position. Then, the script replaces the
- line which a pretty-printed key-value pair.
-
-So the detected state is not important for the remote script, as it only needs
-to know that it must be run cause of differences and what the state should be.
-So if there are a state like `wrongvalue`, it triggers to correction of the
-line, but it do not care if it was `wrongvalue`, `wrongformat` or `commented`
-which trigged the run. Because of this need, the explorer retuns only an
-easy-to-use value to detect if something needs to be changed.
-
-Therefor, it is unable to correctly emit messages with the current base.
-
-
-EXAMPLES
---------
-
-.. code-block:: sh
-
- # set a value in a configuration
- __ini_value fancy-id --file /etc/foo/bar.ini --section '[welcome]' \
- --key hi --value baz --delimiter ' = '
-
- # outcomment a value
- __ini_value foo --file /etc/bar/foo.conf --state commented \
- --key noop --value true --delimiter ' = ' --comment 'not this time!'
-
-
-AUTHORS
--------
-Matthias Stecher
-
-
-COPYING
--------
-Copyright \(C) 2021 Matthias Stecher. 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.
diff --git a/cdist/conf/type/__ini_value/parameter/boolean b/cdist/conf/type/__ini_value/parameter/boolean
deleted file mode 100644
index 5b7d2b39..00000000
--- a/cdist/conf/type/__ini_value/parameter/boolean
+++ /dev/null
@@ -1,2 +0,0 @@
-normalize
-quote
diff --git a/cdist/conf/type/__ini_value/parameter/default/comment-sign b/cdist/conf/type/__ini_value/parameter/default/comment-sign
deleted file mode 100644
index 406ac1cc..00000000
--- a/cdist/conf/type/__ini_value/parameter/default/comment-sign
+++ /dev/null
@@ -1,2 +0,0 @@
-;
-#
diff --git a/cdist/conf/type/__ini_value/parameter/default/indentation b/cdist/conf/type/__ini_value/parameter/default/indentation
deleted file mode 100644
index 573541ac..00000000
--- a/cdist/conf/type/__ini_value/parameter/default/indentation
+++ /dev/null
@@ -1 +0,0 @@
-0
diff --git a/cdist/conf/type/__ini_value/parameter/default/state b/cdist/conf/type/__ini_value/parameter/default/state
deleted file mode 100644
index e7f6134f..00000000
--- a/cdist/conf/type/__ini_value/parameter/default/state
+++ /dev/null
@@ -1 +0,0 @@
-present
diff --git a/cdist/conf/type/__ini_value/parameter/optional b/cdist/conf/type/__ini_value/parameter/optional
deleted file mode 100644
index 6acbf8e5..00000000
--- a/cdist/conf/type/__ini_value/parameter/optional
+++ /dev/null
@@ -1,7 +0,0 @@
-section
-key
-state
-value
-indentation
-comment
-delimiter-space
diff --git a/cdist/conf/type/__ini_value/parameter/optional_multiple b/cdist/conf/type/__ini_value/parameter/optional_multiple
deleted file mode 100644
index bac05165..00000000
--- a/cdist/conf/type/__ini_value/parameter/optional_multiple
+++ /dev/null
@@ -1 +0,0 @@
-comment-sign
diff --git a/cdist/conf/type/__ini_value/parameter/required b/cdist/conf/type/__ini_value/parameter/required
deleted file mode 100644
index 3ae10da3..00000000
--- a/cdist/conf/type/__ini_value/parameter/required
+++ /dev/null
@@ -1,2 +0,0 @@
-file
-delimiter
diff --git a/cdist/conf/type/__letsencrypt_cert/manifest b/cdist/conf/type/__letsencrypt_cert/manifest
index 6394f629..638a99e0 100644
--- a/cdist/conf/type/__letsencrypt_cert/manifest
+++ b/cdist/conf/type/__letsencrypt_cert/manifest
@@ -41,7 +41,7 @@ if [ -z "${certbot_fullpath}" ]; then
require="__apt_source/stretch-backports" __package_apt certbot \
--target-release stretch-backports
;;
- 10*)
+ 10*|11*)
__package_apt certbot
;;
diff --git a/cdist/conf/type/__package_apt/gencode-remote b/cdist/conf/type/__package_apt/gencode-remote
index fbfca330..79c0d9d3 100755
--- a/cdist/conf/type/__package_apt/gencode-remote
+++ b/cdist/conf/type/__package_apt/gencode-remote
@@ -81,12 +81,24 @@ aptget="DEBIAN_FRONTEND=noninteractive apt-get --quiet --yes -o Dpkg::Options::=
case "$state_should" in
present)
+ # 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 update > /dev/null 2>&1 || true
+then echo apt-get $apt_opts update > /dev/null 2>&1 || true
fi
EOF
if [ -n "$version" ]; then
diff --git a/cdist/conf/type/__package_update_index/gencode-remote b/cdist/conf/type/__package_update_index/gencode-remote
index 803468b5..a10c16d3 100755
--- a/cdist/conf/type/__package_update_index/gencode-remote
+++ b/cdist/conf/type/__package_update_index/gencode-remote
@@ -41,7 +41,19 @@ fi
case "$type" in
yum) ;;
apt)
- echo "apt-get --quiet update"
+ # 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"
+
+ echo "apt-get --quiet $apt_opts update"
echo "apt-cache updated (age was: $currage)" >> "$__messages_out"
;;
pacman)
diff --git a/cdist/conf/type/__package_upgrade_all/gencode-remote b/cdist/conf/type/__package_upgrade_all/gencode-remote
index 38aa001e..d332e851 100755
--- a/cdist/conf/type/__package_upgrade_all/gencode-remote
+++ b/cdist/conf/type/__package_upgrade_all/gencode-remote
@@ -28,6 +28,10 @@ apt_clean="$__object/parameter/apt-clean"
apt_dist_upgrade="$__object/parameter/apt-dist-upgrade"
+if [ -f "$__object/parameter/apt-with-new-pkgs" ]; then
+ apt_with_new_pkgs="--with-new-pkgs"
+fi
+
if [ -f "$type" ]; then
type="$(cat "$type")"
else
@@ -54,7 +58,7 @@ case "$type" in
apt)
if [ -f "$apt_dist_upgrade" ]
then echo "$aptget dist-upgrade"
- else echo "$aptget upgrade"
+ else echo "$aptget $apt_with_new_pkgs upgrade"
fi
if [ -f "$apt_clean" ]
diff --git a/cdist/conf/type/__package_upgrade_all/man.rst b/cdist/conf/type/__package_upgrade_all/man.rst
index e9e2b8ce..0c116bac 100644
--- a/cdist/conf/type/__package_upgrade_all/man.rst
+++ b/cdist/conf/type/__package_upgrade_all/man.rst
@@ -33,6 +33,14 @@ BOOLEAN PARAMETERS
apt-dist-upgrade
Do dist-upgrade instead of upgrade.
+apt-with-new-pkg
+ Allow installing new packages when used in conjunction with
+ upgrade. This is useful if the update of an installed package
+ requires new dependencies to be installed. Instead of holding the
+ package back upgrade will upgrade the package and install the new
+ dependencies. Note that upgrade with this option will never remove
+ packages, only allow adding new ones.
+
apt-clean
Clean out the local repository of retrieved package files.
diff --git a/cdist/conf/type/__package_upgrade_all/parameter/boolean b/cdist/conf/type/__package_upgrade_all/parameter/boolean
index 7a56a34b..cd22eb90 100644
--- a/cdist/conf/type/__package_upgrade_all/parameter/boolean
+++ b/cdist/conf/type/__package_upgrade_all/parameter/boolean
@@ -1,2 +1,3 @@
apt-clean
apt-dist-upgrade
+apt-with-new-pkgs
diff --git a/cdist/conf/type/__sed/explorer/file b/cdist/conf/type/__sed/explorer/file
new file mode 100755
index 00000000..ec3d0fe8
--- /dev/null
+++ b/cdist/conf/type/__sed/explorer/file
@@ -0,0 +1,16 @@
+#!/bin/sh -e
+
+if [ -f "$__object/parameter/file" ]
+then
+ file="$( cat "$__object/parameter/file" )"
+else
+ file="/$__object_id"
+fi
+
+if [ ! -e "$file" ]
+then
+ echo "$file does not exist" >&2
+ exit 1
+fi
+
+cat "$file"
diff --git a/cdist/conf/type/__sed/gencode-remote b/cdist/conf/type/__sed/gencode-remote
new file mode 100755
index 00000000..f99c5a88
--- /dev/null
+++ b/cdist/conf/type/__sed/gencode-remote
@@ -0,0 +1,58 @@
+#!/bin/sh -e
+
+if [ -f "$__object/parameter/file" ]
+then
+ file="$( cat "$__object/parameter/file" )"
+else
+ file="/$__object_id"
+fi
+
+script="$( cat "$__object/parameter/script" )"
+
+if [ "$script" = '-' ]
+then
+ script="$( cat "$__object/stdin" )"
+fi
+
+# since stdin is not available in explorer, we pull file from target with explorer
+
+file_from_target="$__object/explorer/file"
+
+sed_cmd='sed'
+
+if [ -f "$__object/parameter/regexp-extended" ]
+then
+ sed_cmd="$sed_cmd -E"
+fi
+
+# do sed dry run, diff result and if no change, then there's nothing to do
+# also redirect diff's output to stderr for debugging purposes
+
+if echo "$script" | "$sed_cmd" -f - "$file_from_target" | diff -u "$file_from_target" - >&2
+then
+ exit 0
+fi
+
+# we can't use -i, because it's not posix, so we fly with tempfile and cp
+# and we use cp because we want to preserve destination file's attributes
+
+# shellcheck disable=SC2016
+echo 'tmp="$__object/tempfile"'
+
+echo "$sed_cmd -f - '$file' > \"\$tmp\" << EOF"
+
+echo "$script"
+
+echo 'EOF'
+
+echo "cp \"\$tmp\" '$file'"
+
+# shellcheck disable=SC2016
+echo 'rm -f "$tmp"'
+
+echo 'change' >> "$__messages_out"
+
+if [ -f "$__object/parameter/onchange" ]
+then
+ cat "$__object/parameter/onchange"
+fi
diff --git a/cdist/conf/type/__sed/man.rst b/cdist/conf/type/__sed/man.rst
new file mode 100644
index 00000000..86789363
--- /dev/null
+++ b/cdist/conf/type/__sed/man.rst
@@ -0,0 +1,57 @@
+cdist-type__sed(7)
+==================
+
+NAME
+----
+cdist-type__sed - Transform text files with ``sed``
+
+
+DESCRIPTION
+-----------
+Transform text files with ``sed``.
+
+
+REQUIRED MULTIPLE PARAMETERS
+----------------------------
+script
+ ``sed`` script.
+ If ``-`` then the script is read from ``stdin``.
+
+
+OPTIONAL PARAMETERS
+-------------------
+file
+ Path to the file. Defaults to ``$__object_id``.
+
+onchange
+ Execute this command if ``sed`` changes file.
+
+
+BOOLEAN PARAMETERS
+------------------
+regexp-extended
+ Use extended regular expressions in the script.
+ Might not be supported with every ``sed`` version.
+
+
+EXAMPLES
+--------
+
+.. code-block:: sh
+
+ __sed /tmp/foobar --script 's/foo/bar/'
+
+ echo 's/foo/bar/' | __sed foobar --file /tmp/foobar --script -
+
+
+AUTHORS
+-------
+Ander Punnar
+
+
+COPYING
+-------
+Copyright \(C) 2021 Ander Punnar. 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.
diff --git a/cdist/conf/type/__sed/parameter/boolean b/cdist/conf/type/__sed/parameter/boolean
new file mode 100644
index 00000000..1ad75c5d
--- /dev/null
+++ b/cdist/conf/type/__sed/parameter/boolean
@@ -0,0 +1 @@
+regexp-extended
diff --git a/cdist/conf/type/__sed/parameter/optional b/cdist/conf/type/__sed/parameter/optional
new file mode 100644
index 00000000..fa86f917
--- /dev/null
+++ b/cdist/conf/type/__sed/parameter/optional
@@ -0,0 +1,2 @@
+file
+onchange
diff --git a/cdist/conf/type/__sed/parameter/required_multiple b/cdist/conf/type/__sed/parameter/required_multiple
new file mode 100644
index 00000000..84f7e31d
--- /dev/null
+++ b/cdist/conf/type/__sed/parameter/required_multiple
@@ -0,0 +1 @@
+script
diff --git a/cdist/conf/type/__ssh_authorized_key/gencode-remote b/cdist/conf/type/__ssh_authorized_key/gencode-remote
index 61c77fb9..cbffde94 100755
--- a/cdist/conf/type/__ssh_authorized_key/gencode-remote
+++ b/cdist/conf/type/__ssh_authorized_key/gencode-remote
@@ -40,6 +40,7 @@ if [ -f "$file" ]; then
grep -v -F -x '$line' '$file' >\$tmpfile
fi
cat "\$tmpfile" >"$file"
+rm -f "\$tmpfile"
DONE
}
diff --git a/cdist/integration.py b/cdist/integration.py
index 17b65f09..04470ea7 100644
--- a/cdist/integration.py
+++ b/cdist/integration.py
@@ -84,7 +84,7 @@ def _process_hosts_simple(action, host, manifest, verbose,
"""
if isinstance(host, str):
hosts = [host, ]
- elif isinstance(host, collections.Iterable):
+ elif isinstance(host, collections.abc.Iterable):
hosts = host
else:
raise cdist.Error('Invalid host argument: {}'.format(host))
diff --git a/cdist/util/fsproperty.py b/cdist/util/fsproperty.py
index 09e9cc19..6bf935e8 100644
--- a/cdist/util/fsproperty.py
+++ b/cdist/util/fsproperty.py
@@ -33,7 +33,7 @@ class AbsolutePathRequiredError(cdist.Error):
return 'Absolute path required, got: {}'.format(self.path)
-class FileList(collections.MutableSequence):
+class FileList(collections.abc.MutableSequence):
"""A list that stores it's state in a file.
"""
@@ -102,7 +102,7 @@ class FileList(collections.MutableSequence):
self.__write(lines)
-class DirectoryDict(collections.MutableMapping):
+class DirectoryDict(collections.abc.MutableMapping):
"""A dict that stores it's items as files in a directory.
"""
diff --git a/docs/changelog b/docs/changelog
index 693d028f..81be51f6 100644
--- a/docs/changelog
+++ b/docs/changelog
@@ -3,6 +3,17 @@ Changelog
next:
* Explorer machine_type: Rewrite (Dennis Camera)
+ * New type: __sed (Ander Punnar)
+ * New type: __haproxy_dualstack (Evilham and ungleich)
+ * Type __apt_update_index: Fix complaint about suite change (Matthias Stecher)
+ * Type __package_update_index: Fix complaint about suite change (Matthias Stecher)
+ * Type __package_upgrade_all: Add new --apt-with-new-pkgs argument (Evilham)
+ * Type __apt_source: Fix complaint about suite change (Matthias Stecher)
+ * Type __package_apt: Fix complaint about suite change (Matthias Stecher)
+ * Type __debconf_set_selections: Fix bug where --file was unsupported (Evilham)
+ * Types __letsencrypt_cert, __grafana_dashboard: Improve bullseye support (Evilham)
+ * Type __ssh_authorized_key: Also remove tmpfile if removing line (Mark Verboom)
+ * Type __apt_pin: Add default priority, add comment in generated files (Daniel Fancsali)
6.9.8: 2021-08-24
* Type __rsync: Rewrite (Ander Punnar)