diff --git a/Makefile b/Makefile index b739ab1f..fa3327d1 100644 --- a/Makefile +++ b/Makefile @@ -31,9 +31,9 @@ help: @echo "docs-clean clean documentation" @echo "clean clean" -DOCS_SRC_DIR=docs/src -SPEECHDIR=docs/speeches -TYPEDIR=cdist/conf/type +DOCS_SRC_DIR=./docs/src +SPEECHDIR=./docs/speeches +TYPEDIR=./cdist/conf/type SPHINXM=make -C $(DOCS_SRC_DIR) man SPHINXH=make -C $(DOCS_SRC_DIR) html diff --git a/cdist/conf/type/__acl/explorer/missing_users_groups b/cdist/conf/type/__acl/explorer/checks similarity index 58% rename from cdist/conf/type/__acl/explorer/missing_users_groups rename to cdist/conf/type/__acl/explorer/checks index b4af614c..70bb0412 100755 --- a/cdist/conf/type/__acl/explorer/missing_users_groups +++ b/cdist/conf/type/__acl/explorer/checks @@ -18,30 +18,22 @@ # along with cdist. If not, see . # -[ ! -e "/$__object_id" ] && exit 0 +# TODO check if filesystem has ACL turned on etc -for parameter in user group -do - if [ ! -f "$__object/parameter/$parameter" ] - then - continue - fi - - while read -r acl +if [ -f "$__object/parameter/acl" ] +then + grep -E '^(default:)?(user|group):' "$__object/parameter/acl" \ + | while read -r acl do - check="$( echo "$acl" | awk -F: '{print $1}' )" + param="$( echo "$acl" | awk -F: '{print $(NF-2)}' )" + check="$( echo "$acl" | awk -F: '{print $(NF-1)}' )" - if [ "$parameter" = 'user' ] - then - getent_db=passwd - else - getent_db="$parameter" - fi + [ "$param" = 'user' ] && db=passwd || db="$param" - if ! getent "$getent_db" "$check" > /dev/null + if ! getent "$db" "$check" > /dev/null then - echo "missing $parameter '$check'" + echo "missing $param '$check'" >&2 + exit 1 fi - done \ - < "$__object/parameter/$parameter" -done + done +fi diff --git a/cdist/conf/type/__acl/gencode-remote b/cdist/conf/type/__acl/gencode-remote index a0f25a15..6dab4d09 100755 --- a/cdist/conf/type/__acl/gencode-remote +++ b/cdist/conf/type/__acl/gencode-remote @@ -20,59 +20,65 @@ file_is="$( cat "$__object/explorer/file_is" )" -[ "$file_is" = 'missing' ] && exit 0 - -missing_users_groups="$( cat "$__object/explorer/missing_users_groups" )" - -if [ -n "$missing_users_groups" ] -then - echo "$missing_users_groups" >&2 - exit 1 -fi +[ "$file_is" = 'missing' ] && [ -z "$__cdist_dry_run" ] && exit 0 os="$( cat "$__global/explorer/os" )" -acl_is="$( cat "$__object/explorer/acl_is" )" - acl_path="/$__object_id" -if [ -f "$__object/parameter/default" ] && [ "$file_is" = 'directory' ] +acl_is="$( cat "$__object/explorer/acl_is" )" + +if [ -f "$__object/parameter/acl" ] then - set_default=1 + acl_should="$( cat "$__object/parameter/acl" )" +elif + [ -f "$__object/parameter/user" ] \ + || [ -f "$__object/parameter/group" ] \ + || [ -f "$__object/parameter/mask" ] \ + || [ -f "$__object/parameter/other" ] +then + acl_should="$( for param in user group mask other + do + [ ! -f "$__object/parameter/$param" ] && continue + + echo "$param" | grep -Eq 'mask|other' && sep=:: || sep=: + + echo "$param$sep$( cat "$__object/parameter/$param" )" + done )" else - set_default=0 + echo 'no parameters set' >&2 + exit 1 fi -acl_should="$( for parameter in user group mask other -do - if [ ! -f "$__object/parameter/$parameter" ] - then - continue - fi +if [ -f "$__object/parameter/default" ] +then + acl_should="$( echo "$acl_should" \ + | sed 's/^default://' \ + | sort -u \ + | sed 's/\(.*\)/default:\1\n\1/' )" +fi - while read -r acl - do - if echo "$acl" | awk -F: '{ print $NF }' | grep -Fq 'X' - then - [ "$file_is" = 'directory' ] && rep=x || rep=- +if [ "$file_is" = 'regular' ] \ + && echo "$acl_should" | grep -Eq '^default:' +then + # only directories can have default ACLs, + # but instead of error, + # let's just remove default entries + acl_should="$( echo "$acl_should" | grep -Ev '^default:' )" +fi - acl="$( echo "$acl" | sed "s/\(.*\)X/\1$rep/" )" - fi +if echo "$acl_should" | awk -F: '{ print $NF }' | grep -Fq 'X' +then + [ "$file_is" = 'directory' ] && rep=x || rep=- - echo "$parameter" | grep -Eq '(mask|other)' && sep=:: || sep=: - - echo "$parameter$sep$acl" - - [ "$set_default" = '1' ] && echo "default:$parameter$sep$acl" - done \ - < "$__object/parameter/$parameter" -done )" + acl_should="$( echo "$acl_should" | sed "s/\\(.*\\)X/\\1$rep/" )" +fi setfacl_exec='setfacl' if [ -f "$__object/parameter/recursive" ] then - if echo "$os" | grep -Eq 'macosx|freebsd' + if echo "$os" | grep -Fq 'freebsd' then echo "$os setfacl do not support recursive operations" >&2 else @@ -82,44 +88,36 @@ fi if [ -f "$__object/parameter/remove" ] then - if echo "$os" | grep -Fq 'solaris' - then - # Solaris setfacl behaves differently. - # We will not support Solaris for now, because no way to test it. - # But adding support should be easy (use -s instead of -m on modify). - echo "$os setfacl do not support -x flag for ACL remove" >&2 - else - echo "$acl_is" | while read -r acl - do - # Skip wanted ACL entries which already exist - # and skip mask and other entries, because we - # can't actually remove them, but only change. - if echo "$acl_should" | grep -Eq "^$acl" \ - || echo "$acl" | grep -Eq '^(default:)?(mask|other)' - then continue - fi + echo "$acl_is" | while read -r acl + do + # skip wanted ACL entries which already exist + # and skip mask and other entries, because we + # can't actually remove them, but only change. + if echo "$acl_should" | grep -Eq "^$acl" \ + || echo "$acl" | grep -Eq '^(default:)?(mask|other)' + then continue + fi - if echo "$os" | grep -Eq 'macosx|freebsd' - then - remove="$acl" - else - remove="$( echo "$acl" | sed 's/:...$//' )" - fi + if echo "$os" | grep -Fq 'freebsd' + then + remove="$acl" + else + remove="$( echo "$acl" | sed 's/:...$//' )" + fi - echo "$setfacl_exec -x \"$remove\" \"$acl_path\"" - echo "removed '$remove'" >> "$__messages_out" - done - fi + echo "$setfacl_exec -x \"$remove\" \"$acl_path\"" + echo "removed '$remove'" >> "$__messages_out" + done fi for acl in $acl_should do if ! echo "$acl_is" | grep -Eq "^$acl" then - if echo "$os" | grep -Eq 'macosx|freebsd' \ + if echo "$os" | grep -Fq 'freebsd' \ && echo "$acl" | grep -Eq '^default:' then - echo "setting default ACL in $os is currently not supported. sorry :(" >&2 + echo "setting default ACL in $os is currently not supported" >&2 else echo "$setfacl_exec -m \"$acl\" \"$acl_path\"" echo "added '$acl'" >> "$__messages_out" diff --git a/cdist/conf/type/__acl/man.rst b/cdist/conf/type/__acl/man.rst index 092eb555..85e946ce 100644 --- a/cdist/conf/type/__acl/man.rst +++ b/cdist/conf/type/__acl/man.rst @@ -8,46 +8,36 @@ cdist-type__acl - Set ACL entries DESCRIPTION ----------- -ACL must be defined as 3-symbol combination, using ``r``, ``w``, ``x`` and ``-``. - -Fully supported on Linux (tested on Debian and CentOS). - -Partial support for FreeBSD, OSX and Solaris. - -OpenBSD and NetBSD support is not possible. +Fully supported and tested on Linux (ext4 filesystem), partial support for FreeBSD. See ``setfacl`` and ``acl`` manpages for more details. -OPTIONAL MULTIPLE PARAMETERS +REQUIRED MULTIPLE PARAMETERS ---------------------------- -user - Add user ACL entry. - -group - Add group ACL entry. - - -OPTIONAL PARAMETERS -------------------- -mask - Add mask ACL entry. - -other - Add other ACL entry. +acl + Set ACL entry following ``getfacl`` output syntax. BOOLEAN PARAMETERS ------------------ +default + Set all ACL entries as default too. + Only directories can have default ACLs. + Setting default ACL in FreeBSD is currently not supported. + recursive Make ``setfacl`` recursive (Linux only), but not ``getfacl`` in explorer. -default - Add default ACL entries (FreeBSD not supported). - remove - Remove undefined ACL entries (Solaris not supported). - ACL entries for ``mask`` and ``other`` can't be removed. + Remove undefined ACL entries. + ``mask`` and ``other`` entries can't be removed, but only changed. + + +DEPRECATED PARAMETERS +--------------------- +Parameters ``user``, ``group``, ``mask`` and ``other`` are deprecated and they +will be removed in future versions. Please use ``acl`` parameter instead. EXAMPLES @@ -56,15 +46,30 @@ EXAMPLES .. code-block:: sh __acl /srv/project \ + --default \ --recursive \ + --remove \ + --acl user:alice:rwx \ + --acl user:bob:r-x \ + --acl group:project-group:rwx \ + --acl group:some-other-group:r-x \ + --acl mask::r-x \ + --acl other::r-x + + # give Alice read-only access to subdir, + # but don't allow her to see parent content. + + __acl /srv/project2 \ + --remove \ + --acl default:group:secret-project:rwx \ + --acl group:secret-project:rwx \ + --acl user:alice:--x + + __acl /srv/project2/subdir \ --default \ --remove \ - --user alice:rwx \ - --user bob:r-x \ - --group project-group:rwx \ - --group some-other-group:r-x \ - --mask r-x \ - --other r-x + --acl group:secret-project:rwx \ + --acl user:alice:r-x AUTHORS diff --git a/cdist/conf/type/__acl/parameter/deprecated/group b/cdist/conf/type/__acl/parameter/deprecated/group new file mode 100644 index 00000000..94e14159 --- /dev/null +++ b/cdist/conf/type/__acl/parameter/deprecated/group @@ -0,0 +1 @@ +see manual for details diff --git a/cdist/conf/type/__acl/parameter/deprecated/mask b/cdist/conf/type/__acl/parameter/deprecated/mask new file mode 100644 index 00000000..94e14159 --- /dev/null +++ b/cdist/conf/type/__acl/parameter/deprecated/mask @@ -0,0 +1 @@ +see manual for details diff --git a/cdist/conf/type/__acl/parameter/deprecated/other b/cdist/conf/type/__acl/parameter/deprecated/other new file mode 100644 index 00000000..94e14159 --- /dev/null +++ b/cdist/conf/type/__acl/parameter/deprecated/other @@ -0,0 +1 @@ +see manual for details diff --git a/cdist/conf/type/__acl/parameter/deprecated/user b/cdist/conf/type/__acl/parameter/deprecated/user new file mode 100644 index 00000000..94e14159 --- /dev/null +++ b/cdist/conf/type/__acl/parameter/deprecated/user @@ -0,0 +1 @@ +see manual for details diff --git a/cdist/conf/type/__acl/parameter/optional_multiple b/cdist/conf/type/__acl/parameter/optional_multiple index 22f5a52c..95c25d55 100644 --- a/cdist/conf/type/__acl/parameter/optional_multiple +++ b/cdist/conf/type/__acl/parameter/optional_multiple @@ -1,2 +1,3 @@ +acl user group diff --git a/cdist/conf/type/__apt_key/explorer/state b/cdist/conf/type/__apt_key/explorer/state index f7940741..38f1bd3c 100755 --- a/cdist/conf/type/__apt_key/explorer/state +++ b/cdist/conf/type/__apt_key/explorer/state @@ -27,6 +27,18 @@ else keyid="$__object_id" fi -apt-key export "$keyid" | head -n 1 | grep -Fqe "BEGIN PGP PUBLIC KEY BLOCK" \ - && echo present \ - || echo absent +keydir="$(cat "$__object/parameter/keydir")" +keyfile="$keydir/$__object_id.gpg" + +if [ -d "$keydir" ] +then + if [ -f "$keyfile" ] + then echo present + else echo absent + fi +else + # fallback to deprecated apt-key + apt-key export "$keyid" | head -n 1 | grep -Fqe "BEGIN PGP PUBLIC KEY BLOCK" \ + && echo present \ + || echo absent +fi diff --git a/cdist/conf/type/__apt_key/gencode-remote b/cdist/conf/type/__apt_key/gencode-remote index 9c4fa00c..47c8bb49 100755 --- a/cdist/conf/type/__apt_key/gencode-remote +++ b/cdist/conf/type/__apt_key/gencode-remote @@ -31,12 +31,84 @@ if [ "$state_should" = "$state_is" ]; then exit 0 fi +keydir="$(cat "$__object/parameter/keydir")" +keyfile="$keydir/$__object_id.gpg" + case "$state_should" in present) keyserver="$(cat "$__object/parameter/keyserver")" - echo "apt-key adv --keyserver \"$keyserver\" --recv-keys \"$keyid\"" + + if [ -f "$__object/parameter/uri" ]; then + uri="$(cat "$__object/parameter/uri")" + + if [ -d "$keydir" ]; then + cat << EOF + +curl -s -L \\ + -o "$keyfile" \\ + "$uri" + +if grep -Fq 'BEGIN PGP PUBLIC KEY BLOCK' \\ + "$keyfile" +then + cat "$keyfile" \\ + | gpg --export > "$keyfile" +fi + +EOF + else + # fallback to deprecated apt-key + echo "curl -s -L '$uri' | apt-key add -" + fi + elif [ -d "$keydir" ]; then + tmp='/tmp/cdist_apt_key_tmp' + + # we need to kill gpg after 30 seconds, because gpg + # can get stuck if keyserver is not responding. + # exporting env var and not exit 1, + # because we need to clean up and kill dirmngr. + cat << EOF + +mkdir -m 700 -p "$tmp" + +if timeout 30s \\ + gpg --homedir "$tmp" \\ + --keyserver "$keyserver" \\ + --recv-keys "$keyid" +then + gpg --homedir "$tmp" \\ + --export "$keyid" \\ + > "$keyfile" +else + export GPG_GOT_STUCK=1 +fi + +GNUPGHOME="$tmp" gpgconf --kill dirmngr + +rm -rf "$tmp" + +if [ -n "\$GPG_GOT_STUCK" ] +then + echo "GPG GOT STUCK - no response from keyserver after 30 seconds" >&2 + exit 1 +fi + +EOF + else + # fallback to deprecated apt-key + echo "apt-key adv --keyserver \"$keyserver\" --recv-keys \"$keyid\"" + fi + + echo "added '$keyid'" >> "$__messages_out" ;; absent) - echo "apt-key del \"$keyid\"" + if [ -f "$keyfile" ]; then + echo "rm '$keyfile'" + else + # fallback to deprecated apt-key + echo "apt-key del \"$keyid\"" + fi + + echo "removed '$keyid'" >> "$__messages_out" ;; esac diff --git a/cdist/conf/type/__apt_key/man.rst b/cdist/conf/type/__apt_key/man.rst index 9009877e..234bc715 100644 --- a/cdist/conf/type/__apt_key/man.rst +++ b/cdist/conf/type/__apt_key/man.rst @@ -28,6 +28,12 @@ keyserver the keyserver from which to fetch the key. If omitted the default set in ./parameter/default/keyserver is used. +keydir + key save location, defaults to ``/etc/apt/trusted.pgp.d`` + +uri + the URI from which to download the key + EXAMPLES -------- @@ -47,15 +53,20 @@ EXAMPLES # same thing with other keyserver __apt_key UbuntuArchiveKey --keyid 437D05B5 --keyserver keyserver.ubuntu.com + # download key from the internet + __apt_key rabbitmq \ + --uri http://www.rabbitmq.com/rabbitmq-signing-key-public.asc + AUTHORS ------- Steven Armstrong +Ander Punnar COPYING ------- -Copyright \(C) 2011-2014 Steven Armstrong. 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 +Copyright \(C) 2011-2019 Steven Armstrong and 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/__apt_key/manifest b/cdist/conf/type/__apt_key/manifest new file mode 100755 index 00000000..010357cd --- /dev/null +++ b/cdist/conf/type/__apt_key/manifest @@ -0,0 +1,8 @@ +#!/bin/sh -e + +__package gnupg + +if [ -f "$__object/parameter/uri" ] +then __package curl +else __package dirmngr +fi diff --git a/cdist/conf/type/__apt_key/parameter/default/keydir b/cdist/conf/type/__apt_key/parameter/default/keydir new file mode 100644 index 00000000..190eb2de --- /dev/null +++ b/cdist/conf/type/__apt_key/parameter/default/keydir @@ -0,0 +1 @@ +/etc/apt/trusted.gpg.d diff --git a/cdist/conf/type/__apt_key/parameter/optional b/cdist/conf/type/__apt_key/parameter/optional index 18cf2586..de647375 100644 --- a/cdist/conf/type/__apt_key/parameter/optional +++ b/cdist/conf/type/__apt_key/parameter/optional @@ -1,3 +1,5 @@ state keyid keyserver +keydir +uri diff --git a/cdist/conf/type/__docker/manifest b/cdist/conf/type/__docker/manifest index 04a9ff27..6a57d85a 100755 --- a/cdist/conf/type/__docker/manifest +++ b/cdist/conf/type/__docker/manifest @@ -64,6 +64,43 @@ case "$os" in require="__apt_source/docker" __package docker-ce --state "${state}" fi ;; + devuan) + os_version="$(cat "$__global/explorer/os_version")" + + case "$os_version" in + ascii) + distribution="stretch" + ;; + jessie) + distribution="jessie" + ;; + *) + echo "Your devuan release ($os_version) is currently not supported by this type (${__type##*/}).">&2 + echo "Please contribute an implementation for it if you can." >&2 + exit 1 + ;; + esac + + if [ "${state}" = "present" ]; then + __package apt-transport-https + __package ca-certificates + __package gnupg2 + fi + __apt_key_uri docker --name "Docker Release (CE deb) " \ + --uri "https://download.docker.com/linux/${os}/gpg" --state "${state}" + + require="__apt_key_uri/docker" __apt_source docker \ + --uri "https://download.docker.com/linux/${os}" \ + --distribution "${distribution}" \ + --state "${state}" \ + --component "stable" + if [ "$version" != "latest" ]; then + require="__apt_source/docker" __package docker-ce --version "${version}" --state "${state}" + else + require="__apt_source/docker" __package docker-ce --state "${state}" + fi + + ;; *) echo "Your operating system ($os) is currently not supported by this type (${__type##*/})." >&2 echo "Please contribute an implementation for it if you can." >&2 diff --git a/cdist/conf/type/__docker_swarm/explorer/swarm-state b/cdist/conf/type/__docker_swarm/explorer/swarm-state index 9c1bc32d..2c9fd598 100755 --- a/cdist/conf/type/__docker_swarm/explorer/swarm-state +++ b/cdist/conf/type/__docker_swarm/explorer/swarm-state @@ -18,4 +18,4 @@ # along with cdist. If not, see . # -docker info 2>/dev/null | grep "^Swarm: " | cut -d " " -f 2- +docker info 2>/dev/null | grep '^ *Swarm: ' | awk '{print $2}' diff --git a/cdist/conf/type/__grafana_dashboard/manifest b/cdist/conf/type/__grafana_dashboard/manifest index 9cd1465d..e652202b 100755 --- a/cdist/conf/type/__grafana_dashboard/manifest +++ b/cdist/conf/type/__grafana_dashboard/manifest @@ -8,10 +8,12 @@ case $os in debian|devuan) case $os_version in 8*|jessie) - apt_source_distribution=jessie + # Differntation not needed anymore + apt_source_distribution=stable ;; 9*|ascii/ceres|ascii) - apt_source_distribution=stretch + # Differntation not needed anymore + apt_source_distribution=stable ;; *) echo "Don't know how to install Grafana on $os $os_version. Send us a pull request!" >&2 @@ -21,10 +23,10 @@ case $os in __apt_key_uri grafana \ --name 'Grafana Release Signing Key' \ - --uri https://packagecloud.io/gpg.key + --uri https://packages.grafana.com/gpg.key require="$require __apt_key_uri/grafana" __apt_source grafana \ - --uri https://packagecloud.io/grafana/stable/debian/ \ + --uri https://packages.grafana.com/oss/deb \ --distribution $apt_source_distribution \ --component main diff --git a/cdist/conf/type/__letsencrypt_cert/manifest b/cdist/conf/type/__letsencrypt_cert/manifest index d6892c9b..d598949e 100755 --- a/cdist/conf/type/__letsencrypt_cert/manifest +++ b/cdist/conf/type/__letsencrypt_cert/manifest @@ -62,11 +62,12 @@ if [ -z "${certbot_fullpath}" ]; then --distribution ascii-backports \ --component main - require="__apt_source/ascii-backports" __package_apt python-certbot \ - --target-release ascii-backports require="__apt_source/ascii-backports" __package_apt certbot \ --target-release ascii-backports ;; + bewoulf*) + __package_apt certbot + ;; *) echo "Unsupported OS version: $os_version" >&2 exit 1 diff --git a/cdist/config.py b/cdist/config.py index 1a0ab4d5..26d07fc4 100644 --- a/cdist/config.py +++ b/cdist/config.py @@ -767,6 +767,16 @@ class Config(object): deprecated) else: self.log.warning("Type %s is deprecated.", cdist_type.name) + for param in cdist_object.parameters: + if param in cdist_type.deprecated_parameters: + msg = cdist_type.deprecated_parameters[param] + if msg: + format = "%s parameter of type %s is deprecated: %s" + args = [param, cdist_type.name, msg] + else: + format = "%s parameter of type %s is deprecated." + args = [param, cdist_type.name] + self.log.warning(format, *args) def object_prepare(self, cdist_object, transfer_type_explorers=True): """Prepare object: Run type explorer + manifest""" diff --git a/cdist/core/cdist_type.py b/cdist/core/cdist_type.py index 7cabd72f..4500f50d 100644 --- a/cdist/core/cdist_type.py +++ b/cdist/core/cdist_type.py @@ -69,6 +69,7 @@ class CdistType(object): self.__optional_multiple_parameters = None self.__boolean_parameters = None self.__parameter_defaults = None + self.__deprecated_parameters = None def __hash__(self): return hash(self.name) @@ -275,3 +276,23 @@ class CdistType(object): finally: self.__parameter_defaults = defaults return self.__parameter_defaults + + @property + def deprecated_parameters(self): + if not self.__deprecated_parameters: + deprecated = {} + try: + deprecated_dir = os.path.join(self.absolute_path, + "parameter", + "deprecated") + for name in cdist.core.listdir(deprecated_dir): + try: + with open(os.path.join(deprecated_dir, name)) as fd: + deprecated[name] = fd.read().strip() + except EnvironmentError: + pass # Swallow errors raised by open() or read() + except EnvironmentError: + pass # Swallow error raised by os.listdir() + finally: + self.__deprecated_parameters = deprecated + return self.__deprecated_parameters diff --git a/cdist/test/cdist_type/__init__.py b/cdist/test/cdist_type/__init__.py index ac84d874..a51a1e6f 100644 --- a/cdist/test/cdist_type/__init__.py +++ b/cdist/test/cdist_type/__init__.py @@ -200,3 +200,18 @@ class TypeTestCase(test.CdistTestCase): self.assertEqual( list(sorted(cdist_type.parameter_defaults.keys())), ['bar', 'foo']) + + def test_without_deprecated_parameters(self): + base_path = fixtures + cdist_type = core.CdistType(base_path, + '__without_deprecated_parameters') + self.assertEqual(cdist_type.deprecated_parameters, {}) + + def test_with_deprecated_parameters(self): + base_path = fixtures + cdist_type = core.CdistType(base_path, '__with_deprecated_parameters') + self.assertTrue('eggs' in cdist_type.deprecated_parameters) + self.assertTrue('spam' in cdist_type.deprecated_parameters) + self.assertEqual(cdist_type.deprecated_parameters['eggs'], + 'Deprecated') + self.assertEqual(cdist_type.deprecated_parameters['spam'], '') diff --git a/cdist/test/cdist_type/fixtures/__with_deprecated_parameters/parameter/deprecated/eggs b/cdist/test/cdist_type/fixtures/__with_deprecated_parameters/parameter/deprecated/eggs new file mode 100644 index 00000000..69d9f456 --- /dev/null +++ b/cdist/test/cdist_type/fixtures/__with_deprecated_parameters/parameter/deprecated/eggs @@ -0,0 +1 @@ +Deprecated diff --git a/cdist/test/cdist_type/fixtures/__with_deprecated_parameters/parameter/deprecated/spam b/cdist/test/cdist_type/fixtures/__with_deprecated_parameters/parameter/deprecated/spam new file mode 100644 index 00000000..e69de29b diff --git a/cdist/test/cdist_type/fixtures/__with_deprecated_parameters/parameter/optional b/cdist/test/cdist_type/fixtures/__with_deprecated_parameters/parameter/optional new file mode 100644 index 00000000..bfe09199 --- /dev/null +++ b/cdist/test/cdist_type/fixtures/__with_deprecated_parameters/parameter/optional @@ -0,0 +1,3 @@ +spam +eggs +sausage diff --git a/docs/changelog b/docs/changelog index ba092840..7594a6d4 100644 --- a/docs/changelog +++ b/docs/changelog @@ -1,7 +1,24 @@ Changelog --------- -next: +5.1.3: 2019-08-30 + * Build: Overcome bash CDPATH when building docs (Dmitry Bogatov) + * Type __grafana_dashboard: Update distribution name, package signing key URI and repository URI (Dominique Roux) + * Type __letsencrypt_cert: Add Devuan Beowulf support (Nico Schottelius) + * Type __letsencrypt_cert: Fix Devuan Ascii: support (Nico Schottelius) + * Type __docker: Add devuan support (Dominique Roux) + * Type __docker_swarm: Fix for Docker 19.03 (Ľubomír Kučera) + +5.1.2: 2019-06-21 + * Core: Add support for type parameters deprecation (Darko Poljak) + * Type __acl: Rewrite and improve (Ander Punnar) + +5.1.1: 2019-05-28 + * Type __apt_key: Use gpg key, fallback to deprecated apt-key (Ander Punnar) + * Type __acl: Fix and improve (Ander Punnar) + * Documentation: Document type stdin inside loop caveats (Darko Poljak) + +5.1.0: 2019-05-22 * Type __consul: Add alpine support (Nico Schottelius) * Type __consul: Add version 1.5.0 (Nico Schottelius) * Type __consul_agent: Add alpine support (Nico Schottelius) diff --git a/docs/src/cdist-type.rst b/docs/src/cdist-type.rst index dfad6fa0..582c0938 100644 --- a/docs/src/cdist-type.rst +++ b/docs/src/cdist-type.rst @@ -74,7 +74,7 @@ prevents to be run in more than one instance. Deprecated types ----------------- If a type is flagged with 'deprecated' marker then it is considered deprecated. -Upon it's usage cdist writes warning line. If 'deprecated' marker has content +When it is used cdist writes warning line. If 'deprecated' marker has content then this content is printed as a deprecation messages, e.g.: .. code-block:: sh @@ -186,6 +186,31 @@ Example: (e.g. in cdist/conf/type/__nginx_vhost/manifest) fi +Deprecated parameters +--------------------- +To deprecate type parameters one can declare a file for each deprecated +parameter under **parameter/deprecated** directory. + +When such parameter is used cdist writes warning line with deprecation message. +If such file has content then this content is printed as deprecation message. +If there is no content then generic parameter deprecation message is printed. + +Example: + +.. code-block:: sh + + $ ls parameter/deprecated/ + eggs spam + $ cat parameter/deprecated/eggs + eggs parameter is deprecated, please use multiple egg parameter. + $ cat parameter/deprecated/spam + $ echo '__foo foo --foo foo --eggs eggs' | ./bin/cdist config -i - 185.203.112.26 + WARNING: 185.203.112.26: eggs parameter of type __foo is deprecated: eggs parameter is deprecated, please use multiple egg parameter. + $ echo '__foo foo --foo foo --eggs eggs --spam spam' | ./bin/cdist config -i - 185.203.112.26 + WARNING: 185.203.112.26: spam parameter of type __foo is deprecated. + WARNING: 185.203.112.26: eggs parameter of type __foo is deprecated: eggs parameter is deprecated, please use multiple egg parameter. + + Input from stdin ---------------- Every type can access what has been written on stdin when it has been called. @@ -216,6 +241,73 @@ In the __file type, stdin is used as source for the file, if - is used for sourc .... +Stdin inside a loop +~~~~~~~~~~~~~~~~~~~ +Since cdist saves type's stdin content in the object as **$__object/stdin**, +so it can be accessed in manifest and gencode-* scripts, this can lead to +unexpected behavior. For example, suppose you have some type with the following +in its manifest: + +.. code-block:: sh + + if [ -f "$__object/parameter/foo" ] + then + while read -r l + do + __file "$l" + echo "$l" >&2 + done < "$__object/parameter/foo" + fi + +and init manifest: + +.. code-block:: sh + + __foo foo --foo a --foo b --foo c + +You expect that manifest stderr content is: + +.. code-block:: sh + + a + b + c + +and that files *a*, *b* and *c* are created. But all you get in manifest stderr +is: + +.. code-block:: sh + + a + +and only *a* file is created. + +When redirecting parameter *foo* file content to while's stdin that means that all +commands in while body have this same stdin. So when *__file* type gets executed, +cdist saves its stdin which means it gets the remaining content of parameter *foo* +file, i.e.: + +.. code-block:: sh + + b + c + +The solution is to make sure that your types inside such loops get their stdin +from somewhere else, e.g. for the above problem *__file* type can get empty +stdin from */dev/null*: + +.. code-block:: sh + + if [ -f "$__object/parameter/foo" ] + then + while read -r l + do + __file "$l" < /dev/null + echo "$l" >&2 + done < "$__object/parameter/foo" + fi + + Writing the manifest -------------------- In the manifest of a type you can use other types, so your type extends