diff --git a/.gitignore b/.gitignore index ed8b453a..4b80b425 100644 --- a/.gitignore +++ b/.gitignore @@ -34,7 +34,7 @@ cdist/inventory/ # Python: cache, distutils, distribution in general __pycache__/ *.pyc -/MANIFEST +MANIFEST dist/ cdist/version.py cdist.egg-info/ diff --git a/Makefile b/Makefile index fa3327d1..b739ab1f 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/bin/build-helper b/bin/build-helper index 9a776491..00fe4ec7 100755 --- a/bin/build-helper +++ b/bin/build-helper @@ -23,8 +23,9 @@ # usage() { - printf "usage: %s TARGET [TARGET-ARGS...] + printf "usage: %s TARGET RUN-AS Available targets: + print-runas changelog-changes changelog-version check-date @@ -57,29 +58,64 @@ usage() { version target-version clean - distclean\n" "$1" + distclean + Run as: + nico + darko - default, if empty string specified\n" "$1" } basename="${0##*/}" -if [ $# -lt 1 ] +if [ $# -lt 2 ] then usage "${basename}" exit 1 fi option=$1; shift +run_as="$1"; shift + +case "$run_as" in + nico) + from_a=nico.schottelius + from_d=ungleich.ch + ml_name="Nico Schottelius" + ml_sig_name="Nico" + ;; + darko|'') + from_a=darko.poljak + from_d=gmail.com + ml_name="Darko Poljak" + ml_sig_name="Darko" + if [ -z "${run_as}" ] + then + run_as="darko" + fi + ;; + *) + printf "Unsupported RUN-AS value: '%s'.\n" "${run_as}" >&2 + usage "${basename}" + exit 1 + ;; +esac SHELLCHECKCMD="shellcheck -s sh -f gcc -x" # Skip SC2154 for variables starting with __ since such variables are cdist # environment variables. SHELLCHECK_SKIP=': __.*is referenced but not assigned.*\[SC2154\]' +to_a="cdist-configuration-management" +to_d="googlegroups.com" + # Change to checkout directory basedir="${0%/*}/../" cd "$basedir" case "$option" in + print-runas) + printf "run_as: '%s'\n" "$run_as" + ;; + changelog-changes) if [ "$#" -eq 1 ]; then start=$1 @@ -123,7 +159,7 @@ case "$option" in ;; check-unittest) - "$0" test + "$0" test "${run_as}" ;; ml-release) @@ -132,10 +168,20 @@ case "$option" in exit 1 fi + # Send mail only once - lock until new changelog things happened. + [ ! -f .lock-ml ] && touch .lock-ml + x=$(find 'docs' -name changelog -type f -newer .lock-ml) + [ -z "${x}" ] && exit 0 + version=$1; shift + to=${to_a}@${to_d} + from=${from_a}@${from_d} + ( cat << eof +From: ${ml_name} <$from> +To: cdist mailing list <$to> Subject: cdist $version has been released Hello .*, @@ -144,11 +190,23 @@ cdist $version has been released with the following changes: eof - "$0" changelog-changes "$version" + "$0" changelog-changes "${run_as}" "$version" cat << eof +Cheers, +${ml_sig_name} + +-- +Automatisation at its best level. With cdist. eof ) > mailinglist.tmp + + if [ "$run_as" = "nico" ] + then + /usr/sbin/sendmail -f "$from" "$to" < mailinglist.tmp && rm -f mailinglist.tmp + fi + + touch .lock-ml ;; archlinux-release) @@ -167,7 +225,7 @@ eof pypi-release) # Ensure that pypi release has the right version - "$0" version + "$0" version "${run_as}" make docs-clean make docs @@ -175,7 +233,7 @@ eof ;; release-git-tag) - target_version=$($0 changelog-version) + target_version=$($0 changelog-version "${run_as}") if git rev-parse --verify "refs/tags/${target_version}" 2>/dev/null; then printf "Tag for %s exists, aborting\n" "${target_version}" exit 1 @@ -229,7 +287,7 @@ eof git archive --prefix="cdist-${tag}/" -o "${archivename}" "${tag}" \ || exit 1 # make sure target version is generated - "$0" target-version + "$0" target-version "${run_as}" tar -x -f "${archivename}" || exit 1 cp cdist/version.py "cdist-${tag}/cdist/version.py" || exit 1 tar -c -f "${archivename}" "cdist-${tag}/" || exit 1 @@ -259,7 +317,7 @@ eof | sed "${sed_cmd}") || exit 1 # make release - changelog=$("$0" changelog-changes "$1" | sed 's/^[[:space:]]*//') + changelog=$("$0" changelog-changes "${run_as}" "$1" | sed 's/^[[:space:]]*//') release_notes=$( printf "%s\n\n%s\n\n**Changelog**\n\n%s\n" \ "${response_archive}" "${response_archive_sig}" "${changelog}" @@ -280,19 +338,19 @@ eof release) set -e - target_version=$($0 changelog-version) - target_branch=$($0 version-branch) + target_version=$($0 changelog-version "${run_as}") + target_branch=$($0 version-branch "${run_as}") printf "Beginning release process for %s\n" "${target_version}" # First check everything is sane - "$0" check-date - "$0" check-unittest - "$0" check-pycodestyle - "$0" check-shellcheck + "$0" check-date "${run_as}" + "$0" check-unittest "${run_as}" + "$0" check-pycodestyle "${run_as}" + "$0" check-shellcheck "${run_as}" # Generate version file to be included in packaging - "$0" target-version + "$0" target-version "${run_as}" # Ensure the git status is clean, else abort if ! git diff-index --name-only --exit-code HEAD ; then @@ -327,8 +385,8 @@ eof fi # Verify that after the merge everything works - "$0" check-date - "$0" check-unittest + "$0" check-date "${run_as}" + "$0" check-unittest "${run_as}" # Generate documentation (man and html) # First, clean old generated docs @@ -339,7 +397,7 @@ eof # Everything green, let's do the release # Tag the current commit - "$0" release-git-tag + "$0" release-git-tag "${run_as}" # Also merge back the version branch if [ "$masterbranch" = yes ]; then @@ -348,28 +406,37 @@ eof fi # Publish git changes - # if you want to have mirror locally then uncomment this and comment below + # if you want to have mirror locally then uncomment this support + # if [ "$run_as" = "nico" ] + # then # git push --mirror + # else + # if we are not Nico :) then just push, no mirror git push # push also new branch and set up tracking git push -u origin "${target_branch}" # fi # Create and publish package for pypi - "$0" pypi-release + "$0" pypi-release "${run_as}" + + if [ "$run_as" = "nico" ] + then + # Archlinux release is based on pypi + "$0" archlinux-release "${run_as}" + fi # sign git tag printf "Enter upstream repository authentication token: " read -r token - "$0" sign-git-release "${target_version}" "${token}" + "$0" sign-git-release "${run_as}" "${target_version}" "${token}" # Announce change on ML - "$0" ml-release "${target_version}" + "$0" ml-release "${run_as}" "${target_version}" cat << eof Manual steps post release: - cdist-web - - send mail body generated in mailinglist.tmp and inform Dmitry for deb - twitter eof ;; @@ -409,7 +476,7 @@ eof ;; check-pycodestyle) - "$0" pycodestyle + "$0" pycodestyle "${run_as}" printf "\\nPlease review pycodestyle report.\\n" while true do @@ -451,24 +518,24 @@ eof ;; shellcheck-scripts) - ${SHELLCHECKCMD} scripts/cdist-dump scripts/cdist-new-type || exit 0 + ${SHELLCHECKCMD} scripts/cdist-dump || exit 0 ;; shellcheck-gencodes) - "$0" shellcheck-local-gencodes - "$0" shellcheck-remote-gencodes + "$0" shellcheck-local-gencodes "${run_as}" + "$0" shellcheck-remote-gencodes "${run_as}" ;; shellcheck-types) - "$0" shellcheck-type-explorers - "$0" shellcheck-manifests - "$0" shellcheck-gencodes + "$0" shellcheck-type-explorers "${run_as}" + "$0" shellcheck-manifests "${run_as}" + "$0" shellcheck-gencodes "${run_as}" ;; shellcheck) - "$0" shellcheck-global-explorers - "$0" shellcheck-types - "$0" shellcheck-scripts + "$0" shellcheck-global-explorers "${run_as}" + "$0" shellcheck-types "${run_as}" + "$0" shellcheck-scripts "${run_as}" ;; shellcheck-type-files) @@ -476,8 +543,8 @@ eof ;; shellcheck-with-files) - "$0" shellcheck - "$0" shellcheck-type-files + "$0" shellcheck "${run_as}" + "$0" shellcheck-type-files "${run_as}" ;; shellcheck-build-helper) @@ -485,7 +552,7 @@ eof ;; check-shellcheck) - "$0" shellcheck + "$0" shellcheck "${run_as}" printf "\\nPlease review shellcheck report.\\n" while true do @@ -507,7 +574,7 @@ eof ;; version-branch) - "$0" changelog-version | cut -d. -f '1,2' + "$0" changelog-version "${run_as}" | cut -d. -f '1,2' ;; version) @@ -515,7 +582,7 @@ eof ;; target-version) - target_version=$($0 changelog-version) + target_version=$($0 changelog-version "${run_as}") printf "VERSION = \"%s\"\n" "${target_version}" > cdist/version.py ;; @@ -538,7 +605,7 @@ eof ;; distclean) - "$0" clean + "$0" clean "${run_as}" rm -f cdist/version.py ;; *) diff --git a/cdist/argparse.py b/cdist/argparse.py index ca69cdae..6c1ee02a 100644 --- a/cdist/argparse.py +++ b/cdist/argparse.py @@ -5,11 +5,12 @@ import logging import collections import functools import cdist.configuration +import cdist.trigger import cdist.preos # set of beta sub-commands -BETA_COMMANDS = set(('install', 'inventory', )) +BETA_COMMANDS = set(('install', 'inventory', 'preos', 'trigger', )) # set of beta arguments for sub-commands BETA_ARGS = { 'config': set(('tag', 'all_tagged_hosts', 'use_archiving', )), @@ -21,7 +22,6 @@ parser = None _verbosity_level_off = -2 _verbosity_level = { - None: logging.WARNING, _verbosity_level_off: logging.OFF, -1: logging.ERROR, 0: logging.WARNING, @@ -436,6 +436,28 @@ def get_parsers(): ' should be POSIX compatible shell.')) parser['shell'].set_defaults(func=cdist.shell.Shell.commandline) + # Trigger + parser['trigger'] = parser['sub'].add_parser( + 'trigger', parents=[parser['loglevel'], + parser['beta'], + parser['common'], + parser['config_main']]) + parser['trigger'].add_argument( + '-D', '--directory', action='store', required=False, + help=('Where to create local files')) + parser['trigger'].add_argument( + '-H', '--http-port', action='store', default=3000, required=False, + help=('Create trigger listener via http on specified port')) + parser['trigger'].add_argument( + '--ipv6', default=False, + help=('Listen to both IPv4 and IPv6 (instead of only IPv4)'), + action='store_true') + parser['trigger'].add_argument( + '-O', '--source', action='store', required=False, + help=('Which file to copy for creation')) + + parser['trigger'].set_defaults(func=cdist.trigger.Trigger.commandline) + for p in parser: parser[p].epilog = EPILOG diff --git a/cdist/conf/explorer/hostname b/cdist/conf/explorer/hostname index dca004d1..7715c6b0 100755 --- a/cdist/conf/explorer/hostname +++ b/cdist/conf/explorer/hostname @@ -1,6 +1,7 @@ #!/bin/sh # -# 2019 Dennis Camera (dennis.camera at ssrq-sds-fds.ch) +# 2010-2014 Nico Schottelius (nico-cdist at schottelius.org) +# 2012 Steven Armstrong (steven-cdist at armstrong.cc) # # This file is part of cdist. # @@ -18,12 +19,7 @@ # along with cdist. If not, see . # # -# Retrieve the running hostname -# -if command -v hostname >/dev/null -then - hostname -else - uname -n +if command -v uname >/dev/null; then + uname -n fi diff --git a/cdist/conf/explorer/interfaces b/cdist/conf/explorer/interfaces index aeb55ed0..55287971 100755 --- a/cdist/conf/explorer/interfaces +++ b/cdist/conf/explorer/interfaces @@ -18,11 +18,13 @@ # along with cdist. If not, see . # -if command -v ip >/dev/null +if command -v ip > /dev/null then - ip -o link show | sed -n 's/^[0-9]\+: \(.\+\): <.*/\1/p' -elif command -v ifconfig >/dev/null + ip -o link show | sed -n 's/^[0-9]\+: \(.\+\): <.*/\1/p' + +elif command -v ifconfig > /dev/null then - ifconfig -a | sed -n -E 's/^(.*)(:[[:space:]]*flags=|Link encap).*/\1/p' -fi \ - | sort -u + ifconfig -a \ + | sed -n -E 's/^(.*)(:[[:space:]]*flags=|Link encap).*/\1/p' \ + | sort -u +fi diff --git a/cdist/conf/explorer/os b/cdist/conf/explorer/os index 563fa4cf..d522300c 100755 --- a/cdist/conf/explorer/os +++ b/cdist/conf/explorer/os @@ -145,7 +145,7 @@ esac if [ -f /etc/os-release ]; then # already lowercase, according to: # https://www.freedesktop.org/software/systemd/man/os-release.html - awk -F= '/^ID=/ { if ($2 ~ /^'"'"'(.*)'"'"'$/ || $2 ~ /^"(.*)"$/) { print substr($2, 2, length($2) - 2) } else { print $2 } }' /etc/os-release + awk -F= '/^ID=/ {print $2;}' /etc/os-release exit 0 fi diff --git a/cdist/conf/type/__acl/explorer/checks b/cdist/conf/type/__acl/explorer/missing_users_groups similarity index 58% rename from cdist/conf/type/__acl/explorer/checks rename to cdist/conf/type/__acl/explorer/missing_users_groups index 70bb0412..b4af614c 100755 --- a/cdist/conf/type/__acl/explorer/checks +++ b/cdist/conf/type/__acl/explorer/missing_users_groups @@ -18,22 +18,30 @@ # along with cdist. If not, see . # -# TODO check if filesystem has ACL turned on etc +[ ! -e "/$__object_id" ] && exit 0 -if [ -f "$__object/parameter/acl" ] -then - grep -E '^(default:)?(user|group):' "$__object/parameter/acl" \ - | while read -r acl +for parameter in user group +do + if [ ! -f "$__object/parameter/$parameter" ] + then + continue + fi + + while read -r acl do - param="$( echo "$acl" | awk -F: '{print $(NF-2)}' )" - check="$( echo "$acl" | awk -F: '{print $(NF-1)}' )" + check="$( echo "$acl" | awk -F: '{print $1}' )" - [ "$param" = 'user' ] && db=passwd || db="$param" - - if ! getent "$db" "$check" > /dev/null + if [ "$parameter" = 'user' ] then - echo "missing $param '$check'" >&2 - exit 1 + getent_db=passwd + else + getent_db="$parameter" fi - done -fi + + if ! getent "$getent_db" "$check" > /dev/null + then + echo "missing $parameter '$check'" + fi + done \ + < "$__object/parameter/$parameter" +done diff --git a/cdist/conf/type/__acl/gencode-remote b/cdist/conf/type/__acl/gencode-remote index 6dab4d09..a0f25a15 100755 --- a/cdist/conf/type/__acl/gencode-remote +++ b/cdist/conf/type/__acl/gencode-remote @@ -20,65 +20,59 @@ file_is="$( cat "$__object/explorer/file_is" )" -[ "$file_is" = 'missing' ] && [ -z "$__cdist_dry_run" ] && exit 0 +[ "$file_is" = 'missing' ] && exit 0 -os="$( cat "$__global/explorer/os" )" +missing_users_groups="$( cat "$__object/explorer/missing_users_groups" )" -acl_path="/$__object_id" - -acl_is="$( cat "$__object/explorer/acl_is" )" - -if [ -f "$__object/parameter/acl" ] +if [ -n "$missing_users_groups" ] then - 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 - echo 'no parameters set' >&2 + echo "$missing_users_groups" >&2 exit 1 fi -if [ -f "$__object/parameter/default" ] +os="$( cat "$__global/explorer/os" )" + +acl_is="$( cat "$__object/explorer/acl_is" )" + +acl_path="/$__object_id" + +if [ -f "$__object/parameter/default" ] && [ "$file_is" = 'directory' ] then - acl_should="$( echo "$acl_should" \ - | sed 's/^default://' \ - | sort -u \ - | sed 's/\(.*\)/default:\1\n\1/' )" + set_default=1 +else + set_default=0 fi -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_should="$( for parameter in user group mask other +do + if [ ! -f "$__object/parameter/$parameter" ] + then + continue + fi -if echo "$acl_should" | awk -F: '{ print $NF }' | grep -Fq 'X' -then - [ "$file_is" = 'directory' ] && rep=x || rep=- + while read -r acl + do + if echo "$acl" | awk -F: '{ print $NF }' | grep -Fq 'X' + then + [ "$file_is" = 'directory' ] && rep=x || rep=- - acl_should="$( echo "$acl_should" | sed "s/\\(.*\\)X/\\1$rep/" )" -fi + acl="$( echo "$acl" | sed "s/\(.*\)X/\1$rep/" )" + fi + + 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 )" setfacl_exec='setfacl' if [ -f "$__object/parameter/recursive" ] then - if echo "$os" | grep -Fq 'freebsd' + if echo "$os" | grep -Eq 'macosx|freebsd' then echo "$os setfacl do not support recursive operations" >&2 else @@ -88,36 +82,44 @@ fi if [ -f "$__object/parameter/remove" ] then - 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 -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 - if echo "$os" | grep -Fq 'freebsd' - then - remove="$acl" - else - remove="$( echo "$acl" | sed 's/:...$//' )" - fi + if echo "$os" | grep -Eq 'macosx|freebsd' + then + remove="$acl" + else + remove="$( echo "$acl" | sed 's/:...$//' )" + fi - echo "$setfacl_exec -x \"$remove\" \"$acl_path\"" - echo "removed '$remove'" >> "$__messages_out" - done + echo "$setfacl_exec -x \"$remove\" \"$acl_path\"" + echo "removed '$remove'" >> "$__messages_out" + done + fi fi for acl in $acl_should do if ! echo "$acl_is" | grep -Eq "^$acl" then - if echo "$os" | grep -Fq 'freebsd' \ + if echo "$os" | grep -Eq 'macosx|freebsd' \ && echo "$acl" | grep -Eq '^default:' then - echo "setting default ACL in $os is currently not supported" >&2 + echo "setting default ACL in $os is currently not supported. sorry :(" >&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 85e946ce..092eb555 100644 --- a/cdist/conf/type/__acl/man.rst +++ b/cdist/conf/type/__acl/man.rst @@ -8,36 +8,46 @@ cdist-type__acl - Set ACL entries DESCRIPTION ----------- -Fully supported and tested on Linux (ext4 filesystem), partial support for FreeBSD. +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. See ``setfacl`` and ``acl`` manpages for more details. -REQUIRED MULTIPLE PARAMETERS +OPTIONAL MULTIPLE PARAMETERS ---------------------------- -acl - Set ACL entry following ``getfacl`` output syntax. +user + Add user ACL entry. + +group + Add group ACL entry. + + +OPTIONAL PARAMETERS +------------------- +mask + Add mask ACL entry. + +other + Add other ACL entry. 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. - ``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. + Remove undefined ACL entries (Solaris not supported). + ACL entries for ``mask`` and ``other`` can't be removed. EXAMPLES @@ -46,30 +56,15 @@ 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 \ - --acl group:secret-project:rwx \ - --acl user:alice:r-x + --user alice:rwx \ + --user bob:r-x \ + --group project-group:rwx \ + --group some-other-group:r-x \ + --mask r-x \ + --other r-x AUTHORS diff --git a/cdist/conf/type/__acl/parameter/deprecated/group b/cdist/conf/type/__acl/parameter/deprecated/group deleted file mode 100644 index 94e14159..00000000 --- a/cdist/conf/type/__acl/parameter/deprecated/group +++ /dev/null @@ -1 +0,0 @@ -see manual for details diff --git a/cdist/conf/type/__acl/parameter/deprecated/mask b/cdist/conf/type/__acl/parameter/deprecated/mask deleted file mode 100644 index 94e14159..00000000 --- a/cdist/conf/type/__acl/parameter/deprecated/mask +++ /dev/null @@ -1 +0,0 @@ -see manual for details diff --git a/cdist/conf/type/__acl/parameter/deprecated/other b/cdist/conf/type/__acl/parameter/deprecated/other deleted file mode 100644 index 94e14159..00000000 --- a/cdist/conf/type/__acl/parameter/deprecated/other +++ /dev/null @@ -1 +0,0 @@ -see manual for details diff --git a/cdist/conf/type/__acl/parameter/deprecated/user b/cdist/conf/type/__acl/parameter/deprecated/user deleted file mode 100644 index 94e14159..00000000 --- a/cdist/conf/type/__acl/parameter/deprecated/user +++ /dev/null @@ -1 +0,0 @@ -see manual for details diff --git a/cdist/conf/type/__acl/parameter/optional_multiple b/cdist/conf/type/__acl/parameter/optional_multiple index 95c25d55..22f5a52c 100644 --- a/cdist/conf/type/__acl/parameter/optional_multiple +++ b/cdist/conf/type/__acl/parameter/optional_multiple @@ -1,3 +1,2 @@ -acl user group diff --git a/cdist/conf/type/__apt_key/explorer/state b/cdist/conf/type/__apt_key/explorer/state index 38f1bd3c..f7940741 100755 --- a/cdist/conf/type/__apt_key/explorer/state +++ b/cdist/conf/type/__apt_key/explorer/state @@ -27,18 +27,6 @@ else keyid="$__object_id" fi -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 +apt-key export "$keyid" | head -n 1 | grep -Fqe "BEGIN PGP PUBLIC KEY BLOCK" \ + && echo present \ + || echo absent diff --git a/cdist/conf/type/__apt_key/gencode-remote b/cdist/conf/type/__apt_key/gencode-remote index 0c96ff67..9c4fa00c 100755 --- a/cdist/conf/type/__apt_key/gencode-remote +++ b/cdist/conf/type/__apt_key/gencode-remote @@ -31,82 +31,12 @@ 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")" - - if [ -f "$__object/parameter/uri" ]; then - uri="$(cat "$__object/parameter/uri")" - - if [ -d "$keydir" ]; then - cat << EOF - -curl -s -L \\ - -o "$keyfile" \\ - "$uri" - -key="\$( cat "$keyfile" )" - -if echo "\$key" | grep -Fq 'BEGIN PGP PUBLIC KEY BLOCK' -then - echo "\$key" | gpg --dearmor > "$keyfile" -fi - -EOF - else - # fallback to deprecated apt-key - echo "curl -s -L '$uri' | apt-key add -" - fi - elif [ -d "$keydir" ]; then - # 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 - -gpgtmphome="\$( mktemp -d )" - -if timeout 30s \\ - gpg --homedir "\$gpgtmphome" \\ - --keyserver "$keyserver" \\ - --recv-keys "$keyid" -then - gpg --homedir "\$gpgtmphome" \\ - --export "$keyid" \\ - > "$keyfile" -else - export GPG_GOT_STUCK=1 -fi - -GNUPGHOME="\$gpgtmphome" gpgconf --kill dirmngr - -rm -rf "\$gpgtmphome" - -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" + echo "apt-key adv --keyserver \"$keyserver\" --recv-keys \"$keyid\"" ;; absent) - if [ -f "$keyfile" ]; then - echo "rm '$keyfile'" - else - # fallback to deprecated apt-key - echo "apt-key del \"$keyid\"" - fi - - echo "removed '$keyid'" >> "$__messages_out" + echo "apt-key del \"$keyid\"" ;; esac diff --git a/cdist/conf/type/__apt_key/man.rst b/cdist/conf/type/__apt_key/man.rst index 234bc715..9009877e 100644 --- a/cdist/conf/type/__apt_key/man.rst +++ b/cdist/conf/type/__apt_key/man.rst @@ -28,12 +28,6 @@ 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 -------- @@ -53,20 +47,15 @@ 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-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 +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 License, or (at your option) any later version. diff --git a/cdist/conf/type/__apt_key/manifest b/cdist/conf/type/__apt_key/manifest deleted file mode 100755 index 010357cd..00000000 --- a/cdist/conf/type/__apt_key/manifest +++ /dev/null @@ -1,8 +0,0 @@ -#!/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 deleted file mode 100644 index 190eb2de..00000000 --- a/cdist/conf/type/__apt_key/parameter/default/keydir +++ /dev/null @@ -1 +0,0 @@ -/etc/apt/trusted.gpg.d diff --git a/cdist/conf/type/__apt_key/parameter/optional b/cdist/conf/type/__apt_key/parameter/optional index de647375..18cf2586 100644 --- a/cdist/conf/type/__apt_key/parameter/optional +++ b/cdist/conf/type/__apt_key/parameter/optional @@ -1,5 +1,3 @@ state keyid keyserver -keydir -uri diff --git a/cdist/conf/type/__cdist_preos_trigger/gencode-remote b/cdist/conf/type/__cdist_preos_trigger/gencode-remote new file mode 100644 index 00000000..d5e9fe5c --- /dev/null +++ b/cdist/conf/type/__cdist_preos_trigger/gencode-remote @@ -0,0 +1,12 @@ +#!/bin/sh + +os=$(cat "$__global/explorer/os") + +case "$os" in + devuan) + echo "update-rc.d cdist-preos-trigger defaults > /dev/null" + ;; + *) + ;; +esac + diff --git a/cdist/conf/type/__cdist_preos_trigger/man.rst b/cdist/conf/type/__cdist_preos_trigger/man.rst new file mode 100644 index 00000000..abbd553b --- /dev/null +++ b/cdist/conf/type/__cdist_preos_trigger/man.rst @@ -0,0 +1,45 @@ +cdist-type__cdist_preos_trigger(7) +================================== + +NAME +---- +cdist-type__cdist_preos_trigger - configure cdist preos trigger + + +DESCRIPTION +----------- +Create cdist PreOS trigger by creating systemd unit file that will be started +at boot and will execute trigger command - connect to specified host and port. + + +REQUIRED PARAMETERS +------------------- +trigger-command + Command that will be executed as a PreOS cdist trigger. + + +OPTIONAL PARAMETERS +------------------- +None + + +EXAMPLES +-------- + +.. code-block:: sh + + # Configure default curl trigger for host cdist.ungleich.ch at port 80. + __cdist_preos_trigger http --trigger-command '/usr/bin/curl cdist.ungleich.ch:80' + + +AUTHORS +------- +Darko Poljak + + +COPYING +------- +Copyright \(C) 2016 Darko Poljak. 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/__cdist_preos_trigger/manifest b/cdist/conf/type/__cdist_preos_trigger/manifest new file mode 100644 index 00000000..750a0548 --- /dev/null +++ b/cdist/conf/type/__cdist_preos_trigger/manifest @@ -0,0 +1,67 @@ +#!/bin/sh + +os="$(cat "$__global/explorer/os")" +trigger_command=$(cat "$__object/parameter/trigger-command") + +case "$os" in + devuan) + __file /etc/init.d/cdist-preos-trigger --owner root \ + --group root \ + --mode 755 \ + --source - << EOF +#!/bin/sh +# /etc/init.d/cdist-preos-trigger + +### BEGIN INIT INFO +# Provides: cdist-preos-trigger +# Required-Start: \$all +# Required-Stop: +# Default-Start: 2 3 4 5 S +# Default-Stop: 0 1 6 +# Short-Description: Execute cdist preos trigger command +# Description: Execute cdist preos trigger commnad. +### END INIT INFO + +case "\$1" in + start) + echo "Starting cdist-preos-trigger command" + ${trigger_command} & + ;; + stop) + # no-op + ;; + *) + echo "Usage: /etc/init.d/cdist-preos-trigger {start|stop}" + exit 1 + ;; +esac + +exit 0 +EOF + ;; + *) + __file /etc/systemd/system/cdist-preos-trigger.service --owner root \ + --group root \ + --mode 644 \ + --source - << EOF +[Unit] +Description=preos trigger +Wants=network-online.target +After=network.target network-online.target + +[Service] +Type=simple +Restart=no +# Broken systemd +ExecStartPre=/bin/sleep 5 +ExecStart=${trigger_command} + +[Install] +WantedBy=multi-user.target +EOF + + require="__file/etc/systemd/system/cdist-preos-trigger.service" \ + __start_on_boot cdist-preos-trigger + ;; +esac + diff --git a/cdist/conf/type/__cdist_preos_trigger/parameter/required b/cdist/conf/type/__cdist_preos_trigger/parameter/required new file mode 100644 index 00000000..3407a482 --- /dev/null +++ b/cdist/conf/type/__cdist_preos_trigger/parameter/required @@ -0,0 +1 @@ +trigger-command diff --git a/cdist/conf/type/__consul/files/versions/1.5.0/cksum b/cdist/conf/type/__consul/files/versions/1.5.0/cksum deleted file mode 100644 index efca9caa..00000000 --- a/cdist/conf/type/__consul/files/versions/1.5.0/cksum +++ /dev/null @@ -1 +0,0 @@ -886614099 103959898 consul diff --git a/cdist/conf/type/__consul/files/versions/1.5.0/source b/cdist/conf/type/__consul/files/versions/1.5.0/source deleted file mode 100644 index cafa9248..00000000 --- a/cdist/conf/type/__consul/files/versions/1.5.0/source +++ /dev/null @@ -1 +0,0 @@ -https://releases.hashicorp.com/consul/1.5.0/consul_1.5.0_linux_amd64.zip diff --git a/cdist/conf/type/__consul/gencode-remote b/cdist/conf/type/__consul/gencode-remote index 2a21054f..1d2244ea 100755 --- a/cdist/conf/type/__consul/gencode-remote +++ b/cdist/conf/type/__consul/gencode-remote @@ -42,7 +42,7 @@ source_file_name="${source##*/}" cksum_should=$(cut -d' ' -f1,2 "$version_dir/cksum") cat << eof - tmpdir=\$(mktemp -d -p /tmp "${__type##*/}.XXXXXXXXXX") + tmpdir=\$(mktemp -d --tmpdir="/tmp" "${__type##*/}.XXXXXXXXXX") curl -s -L "$source" > "\$tmpdir/$source_file_name" unzip -p "\$tmpdir/$source_file_name" > "${destination}.tmp" rm -rf "\$tmpdir" diff --git a/cdist/conf/type/__consul/manifest b/cdist/conf/type/__consul/manifest index 156eb667..0dd50f53 100755 --- a/cdist/conf/type/__consul/manifest +++ b/cdist/conf/type/__consul/manifest @@ -24,7 +24,7 @@ os=$(cat "$__global/explorer/os") case "$os" in - alpine|scientific|centos|redhat|ubuntu|debian|devuan|archlinux|gentoo) + scientific|centos|redhat|ubuntu|debian|devuan|archlinux|gentoo) # any linux should work : ;; @@ -47,7 +47,6 @@ fi if [ -f "$__object/parameter/direct" ]; then __package unzip - __package curl else __staged_file /usr/local/bin/consul \ --source "$(cat "$version_dir/source")" \ diff --git a/cdist/conf/type/__consul_agent/files/consul.sys-openrc b/cdist/conf/type/__consul_agent/files/consul.sys-openrc deleted file mode 100644 index 1dbe9375..00000000 --- a/cdist/conf/type/__consul_agent/files/consul.sys-openrc +++ /dev/null @@ -1,38 +0,0 @@ -#!/sbin/openrc-run -# 2019 Nico Schottelius (nico-cdist at schottelius.org) - -description="consul agent" - -pidfile="${CONSUL_PIDFILE:-"/var/run/$RC_SVCNAME/pidfile"}" -command="${CONSUL_BINARY:-"/usr/local/bin/consul"}" - - -checkconfig() { - if [ ! -d /var/run/consul ] ; then - mkdir -p /var/run/consul || return 1 - chown consul:consul /var/run/$NAME || return 1 - chmod 2770 /var/run/$NAME || return 1 - fi -} - -start() { - need net - - start-stop-daemon --start --quiet --oknodo \ - --pidfile "$pidfile" --background \ - --exec $command -- agent -pid-file="$pidfile" -config-dir /etc/consul/conf.d -} -start_pre() { - checkconfig -} - -stop() { - if [ "${RC_CMD}" = "restart" ] ; then - checkconfig || return 1 - fi - - ebegin "Stopping $RC_SVCNAME" - start-stop-daemon --stop --exec "$command" \ - --pidfile "$pidfile" --quiet - eend $? -} diff --git a/cdist/conf/type/__consul_agent/manifest b/cdist/conf/type/__consul_agent/manifest index a88d26ed..c48bfe85 100755 --- a/cdist/conf/type/__consul_agent/manifest +++ b/cdist/conf/type/__consul_agent/manifest @@ -1,7 +1,7 @@ #!/bin/sh -e # # 2015 Steven Armstrong (steven-cdist at armstrong.cc) -# 2015-2019 Nico Schottelius (nico-cdist at schottelius.org) +# 2015 Nico Schottelius (nico-cdist at schottelius.org) # # This file is part of cdist. # @@ -23,7 +23,7 @@ os=$(cat "$__global/explorer/os") case "$os" in - alpine|scientific|centos|debian|devuan|redhat|ubuntu) + scientific|centos|debian|devuan|redhat|ubuntu) # whitelist safeguard : ;; @@ -181,25 +181,22 @@ init_upstart() # Install init script to start on boot case "$os" in - alpine|devuan) - init_sysvinit debian - ;; - centos|redhat) - os_version="$(sed 's/[^0-9.]//g' "$__global/explorer/os_version")" - major_version="${os_version%%.*}" - case "$major_version" in - [456]) - init_sysvinit redhat - ;; - 7) - init_systemd - ;; - *) - echo "Unsupported CentOS/Redhat version: $os_version" >&2 - exit 1 - ;; - esac - ;; + centos|redhat) + os_version="$(sed 's/[^0-9.]//g' "$__global/explorer/os_version")" + major_version="${os_version%%.*}" + case "$major_version" in + [456]) + init_sysvinit redhat + ;; + 7) + init_systemd + ;; + *) + echo "Unsupported CentOS/Redhat version: $os_version" >&2 + exit 1 + ;; + esac + ;; debian) os_version=$(cat "$__global/explorer/os_version") @@ -217,9 +214,13 @@ case "$os" in exit 1 ;; esac - ;; + ;; + + devuan) + init_sysvinit debian + ;; ubuntu) init_upstart - ;; + ;; esac diff --git a/cdist/conf/type/__docker/manifest b/cdist/conf/type/__docker/manifest index 6a57d85a..04a9ff27 100755 --- a/cdist/conf/type/__docker/manifest +++ b/cdist/conf/type/__docker/manifest @@ -64,43 +64,6 @@ 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 2c9fd598..9c1bc32d 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: ' | awk '{print $2}' +docker info 2>/dev/null | grep "^Swarm: " | cut -d " " -f 2- diff --git a/cdist/conf/type/__file_py/__init__.py b/cdist/conf/type/__file_py/__init__.py new file mode 100644 index 00000000..06e3abf2 --- /dev/null +++ b/cdist/conf/type/__file_py/__init__.py @@ -0,0 +1,103 @@ +import os +import re +import sys +from cdist.core import PythonType + + +class FileType(PythonType): + def get_attribute(self, stat_file, attribute, value_should): + if os.path.exists(stat_file): + if re.match('[0-9]', value_should): + index = 1 + else: + index = 2 + with open(stat_file, 'r') as f: + for line in f: + if re.match(attribute + ":", line): + fields = line.split() + return fields[index] + return None + + def set_attribute(self, attribute, value_should, destination): + cmd = { + 'group': 'chgrp', + 'owner': 'chown', + 'mode': 'chmod', + } + self.send_message("{} '{}'".format(cmd[attribute], value_should)) + return "{} '{}' '{}'".format(cmd[attribute], value_should, destination) + + def type_manifest(self): + yield from () + + def type_gencode(self): + typeis = self.get_explorer('type') + state_should = self.get_parameter('state') + + if state_should == 'exists' and typeis == 'file': + return + + source = self.get_parameter('source') + if source == '-': + source = self.stdin_path + destination = '/' + self.object_id + if state_should == 'pre-exists': + if source is not None: + self.die('--source cannot be used with --state pre-exists') + if typeis == 'file': + return None + else: + self.die('File {} does not exist'.format(destination)) + + create_file = False + upload_file = False + set_attributes = False + code = [] + if state_should == 'present' or state_should == 'exists': + if source is None: + remote_stat = self.get_explorer('stat') + if not remote_stat: + create_file = True + else: + if os.path.exists(source): + if typeis == 'file': + local_cksum = self.run_local(['cksum', source, ]) + local_cksum = local_cksum.split()[0] + remote_cksum = self.get_explorer('cksum') + remote_cksum = remote_cksum.split()[0] + upload_file = local_cksum != remote_cksum + else: + upload_file = True + else: + self.die('Source {} does not exist'.format(source)) + if create_file or upload_file: + set_attributes = True + tempfile_template = '{}.cdist.XXXXXXXXXX'.format(destination) + destination_upload = self.run_remote( + ["mktemp", tempfile_template, ]) + if upload_file: + self.transfer(source, destination_upload) + code.append('rm -rf {}'.format(destination)) + code.append('mv {} {}'.format(destination_upload, destination)) + + if state_should in ('present', 'exists', 'pre-exists', ): + for attribute in ('group', 'owner', 'mode', ): + if attribute in self.parameters: + value_should = self.get_parameter(attribute) + if attribute == 'mode': + value_should = re.sub('^0', '', value_should) + stat_file = self.get_explorer_file('stat') + value_is = self.get_attribute(stat_file, attribute, + value_should) + if set_attributes or value_should != value_is: + code.append(self.set_attribute(attribute, + value_should, + destination)) + elif state_should == 'absent': + if typeis == 'file': + code.append('rm -f {}'.format(destination)) + self.send_message('remove') + else: + self.die('Unknown state {}'.format(state_should)) + + return "\n".join(code) diff --git a/cdist/conf/type/__xymon_config/gencode-remote b/cdist/conf/type/__file_py/explorer/cksum old mode 100644 new mode 100755 similarity index 62% rename from cdist/conf/type/__xymon_config/gencode-remote rename to cdist/conf/type/__file_py/explorer/cksum index b25a0fda..335e4e7a --- a/cdist/conf/type/__xymon_config/gencode-remote +++ b/cdist/conf/type/__file_py/explorer/cksum @@ -1,6 +1,6 @@ -#!/bin/sh -e +#!/bin/sh # -# 2018-2019 Thomas Eckert (tom at it-eckert.de) +# 2011-2012 Nico Schottelius (nico-cdist at schottelius.org) # # This file is part of cdist. # @@ -16,8 +16,19 @@ # # You should have received a copy of the GNU General Public License # along with cdist. If not, see . +# +# +# Retrieve the md5sum of a file to be created, if it is already existing. +# -## to speed up config-reload we send a HUP to the server process: -cat <<-EOT - pkill -HUP xymond || { echo "HUPing xymond failed" >&2; exit 1; } -EOT +destination="/$__object_id" + +if [ -e "$destination" ]; then + if [ -f "$destination" ]; then + cksum < "$destination" + else + echo "NO REGULAR FILE" + fi +else + echo "NO FILE FOUND, NO CHECKSUM CALCULATED." +fi diff --git a/cdist/conf/type/__xymon_apache/manifest b/cdist/conf/type/__file_py/explorer/stat similarity index 50% rename from cdist/conf/type/__xymon_apache/manifest rename to cdist/conf/type/__file_py/explorer/stat index bfd0af79..8a917556 100755 --- a/cdist/conf/type/__xymon_apache/manifest +++ b/cdist/conf/type/__file_py/explorer/stat @@ -1,6 +1,6 @@ -#!/bin/sh -e +#!/bin/sh # -# 2018-2019 Thomas Eckert (tom at it-eckert.de) +# 2013 Steven Armstrong (steven-cdist armstrong.cc) # # This file is part of cdist. # @@ -16,27 +16,41 @@ # # You should have received a copy of the GNU General Public License # along with cdist. If not, see . +# -state=$(cat "$__object/parameter/state") +destination="/$__object_id" -os=$(cat "$__global/explorer/os") +# nothing to work with, nothing we could do +[ -e "$destination" ] || exit 0 + +os=$("$__explorer/os") case "$os" in - debian|ubuntu) - : - ;; - *) - 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 - exit 1 - ;; + "freebsd"|"netbsd"|"openbsd") + # FIXME: should be something like this based on man page, but can not test + stat -f "type: %ST +owner: %Du %Su +group: %Dg %Sg +mode: %Op %Sp +size: %Dz +links: %Dl +" "$destination" + ;; + "macosx") + stat -f "type: %HT +owner: %Du %Su +group: %Dg %Sg +mode: %Lp %Sp +size: %Dz +links: %Dl +" "$destination" + ;; + *) + stat --printf="type: %F +owner: %u %U +group: %g %G +mode: %a %A +size: %s +links: %h +" "$destination" + ;; esac - -__package apache2 --state "$state" - -## edit xymon.conf IP-ranges -if [ -f "$__object/parameter/ipacl" ]; then - require="__package/xymon" __line /etc/apache2/conf-available/xymon.conf \ - --line " Require ip $(cat "$__object/parameter/ipacl")" \ - --after "^[[:space:]]*Require local" \ - --state "present" -fi diff --git a/cdist/conf/type/__podman_compose/gencode-remote b/cdist/conf/type/__file_py/explorer/type old mode 100644 new mode 100755 similarity index 67% rename from cdist/conf/type/__podman_compose/gencode-remote rename to cdist/conf/type/__file_py/explorer/type index 0f5cf9db..e723047c --- a/cdist/conf/type/__podman_compose/gencode-remote +++ b/cdist/conf/type/__file_py/explorer/type @@ -1,6 +1,6 @@ -#!/bin/sh -e +#!/bin/sh # -# 2019 Daniel Tschada +# 2013 Steven Armstrong (steven-cdist armstrong.cc) # # This file is part of cdist. # @@ -18,7 +18,16 @@ # along with cdist. If not, see . # -install="$(cat "$__object/parameter/install")" -state="$(cat "$__object/parameter/state")" -user="$(cat "$__object/parameter/user")" -version="$(cat "$__object/parameter/version")" \ No newline at end of file +destination="/$__object_id" + +if [ ! -e "$destination" ]; then + echo none +elif [ -h "$destination" ]; then + echo symlink +elif [ -f "$destination" ]; then + echo file +elif [ -d "$destination" ]; then + echo directory +else + echo unknown +fi diff --git a/cdist/conf/type/__podman_compose/parameter/default/state b/cdist/conf/type/__file_py/parameter/default/state similarity index 100% rename from cdist/conf/type/__podman_compose/parameter/default/state rename to cdist/conf/type/__file_py/parameter/default/state diff --git a/cdist/conf/type/__file_py/parameter/optional b/cdist/conf/type/__file_py/parameter/optional new file mode 100644 index 00000000..c696d592 --- /dev/null +++ b/cdist/conf/type/__file_py/parameter/optional @@ -0,0 +1,5 @@ +state +group +mode +owner +source diff --git a/cdist/conf/type/__git/gencode-remote b/cdist/conf/type/__git/gencode-remote index ab22655f..5a9e23fc 100755 --- a/cdist/conf/type/__git/gencode-remote +++ b/cdist/conf/type/__git/gencode-remote @@ -19,34 +19,32 @@ # # -state_is=$(cat "$__object/explorer/state") -owner_is=$(cat "$__object/explorer/owner") -group_is=$(cat "$__object/explorer/group") +state_is="$(cat "$__object/explorer/state")" +owner_is="$(cat "$__object/explorer/owner")" +group_is="$(cat "$__object/explorer/group")" -state_should=$(cat "$__object/parameter/state") +state_should="$(cat "$__object/parameter/state")" -branch=$(cat "$__object/parameter/branch") +branch="$(cat "$__object/parameter/branch")" -source=$(cat "$__object/parameter/source") +source="$(cat "$__object/parameter/source")" destination="/$__object_id" -owner=$(cat "$__object/parameter/owner") -group=$(cat "$__object/parameter/group") -mode=$(cat "$__object/parameter/mode") +owner="$(cat "$__object/parameter/owner")" +group="$(cat "$__object/parameter/group")" +mode="$(cat "$__object/parameter/mode")" -[ -f "$__object/parameter/recursive" ] && recursive='--recurse-submodules' || recursive='' -[ -f "$__object/parameter/shallow" ] && shallow='--depth 1 --shallow-submodules' || shallow='' - -[ "$state_should" = "$state_is" ] \ - && [ "$owner" = "$owner_is" ] \ - && [ "$group" = "$group_is" ] \ - && [ -n "$mode" ] && exit 0 +[ "$state_should" = "$state_is" ] && \ +[ "$owner" = "$owner_is" ] && \ +[ "$group" = "$group_is" ] && \ +[ -n "$mode" ] && exit 0 case $state_should in present) + if [ "$state_should" != "$state_is" ]; then - echo git clone --quiet "$recursive" "$shallow" --branch "$branch" "$source" "$destination" + echo git clone --quiet --branch "$branch" "$source" "$destination" fi if { [ -n "$owner" ] && [ "$owner_is" != "$owner" ]; } || \ { [ -n "$group" ] && [ "$group_is" != "$group" ]; }; then @@ -56,9 +54,8 @@ case $state_should in echo chmod -R "$mode" "$destination" fi ;; - + # Handled in manifest absent) - # Handled in manifest ;; *) diff --git a/cdist/conf/type/__git/man.rst b/cdist/conf/type/__git/man.rst index d3e15f25..130925c8 100644 --- a/cdist/conf/type/__git/man.rst +++ b/cdist/conf/type/__git/man.rst @@ -35,12 +35,6 @@ mode owner User to chown to. -recursive - Passes the --recurse-submodules flag to git when cloning the repository. - -shallow - Sets --depth=1 and --shallow-submodules for cloning repositories with big history. - EXAMPLES -------- diff --git a/cdist/conf/type/__git/parameter/boolean b/cdist/conf/type/__git/parameter/boolean deleted file mode 100644 index d600d4ca..00000000 --- a/cdist/conf/type/__git/parameter/boolean +++ /dev/null @@ -1,2 +0,0 @@ -recursive -shallow diff --git a/cdist/conf/type/__grafana_dashboard/manifest b/cdist/conf/type/__grafana_dashboard/manifest index d145c4c3..9cd1465d 100755 --- a/cdist/conf/type/__grafana_dashboard/manifest +++ b/cdist/conf/type/__grafana_dashboard/manifest @@ -8,16 +8,10 @@ case $os in debian|devuan) case $os_version in 8*|jessie) - # Differntation not needed anymore - apt_source_distribution=stable + apt_source_distribution=jessie ;; 9*|ascii/ceres|ascii) - # Differntation not needed anymore - apt_source_distribution=stable - ;; - 10*) - # Differntation not needed anymore - apt_source_distribution=stable + apt_source_distribution=stretch ;; *) echo "Don't know how to install Grafana on $os $os_version. Send us a pull request!" >&2 @@ -27,15 +21,16 @@ case $os in __apt_key_uri grafana \ --name 'Grafana Release Signing Key' \ - --uri https://packages.grafana.com/gpg.key + --uri https://packagecloud.io/gpg.key require="$require __apt_key_uri/grafana" __apt_source grafana \ - --uri https://packages.grafana.com/oss/deb \ + --uri https://packagecloud.io/grafana/stable/debian/ \ --distribution $apt_source_distribution \ --component main + __package apt-transport-https - require="$require __apt_source/grafana" __apt_update_index - require="$require __package/apt-transport-https __apt_update_index" __package grafana + + require="$require __apt_source/grafana __package/apt-transport-https" __package grafana require="$require __package/grafana" __start_on_boot grafana-server require="$require __start_on_boot/grafana-server" __process grafana-server --start "service grafana-server start" ;; diff --git a/cdist/conf/type/__group/explorer/group b/cdist/conf/type/__group/explorer/group index dc673f61..07f73a91 100755 --- a/cdist/conf/type/__group/explorer/group +++ b/cdist/conf/type/__group/explorer/group @@ -1,7 +1,6 @@ #!/bin/sh # # 2011-2015 Steven Armstrong (steven-cdist at armstrong.cc) -# 2019 Dennis Camera (dennis.camera at ssrq-sds-fds.ch) # # This file is part of cdist. # @@ -22,21 +21,7 @@ # Get an existing groups group entry. # -not_supported() { - echo "Your operating system ($("$__explorer/os")) is currently not supported." >&2 - echo "Cannot extract group information." >&2 - echo "Please contribute an implementation for it if you can." >&2 - exit 1 -} - name=$__object_id -if command -v getent >/dev/null -then - getent group "$name" || true -elif [ -f /etc/group ] -then - grep "^${name}:" /etc/group || true -else - not_supported -fi +getent group "$name" || true + diff --git a/cdist/conf/type/__group/explorer/gshadow b/cdist/conf/type/__group/explorer/gshadow index 05841d69..ef40b7bc 100755 --- a/cdist/conf/type/__group/explorer/gshadow +++ b/cdist/conf/type/__group/explorer/gshadow @@ -1,7 +1,6 @@ #!/bin/sh # # 2011-2015 Steven Armstrong (steven-cdist at armstrong.cc) -# 2019 Dennis Camera (dennis.camera at ssrq-sds-fds.ch) # # This file is part of cdist. # @@ -23,28 +22,13 @@ # name=$__object_id -os=$("$__explorer/os") +os="$("$__explorer/os")" -not_supported() { - echo "Your operating system ($os) is currently not supported." >&2 - echo "Cannot extract group information." >&2 - echo "Please contribute an implementation for it if you can." >&2 - exit 1 -} - -case $os in - "freebsd"|"netbsd") - echo "$os does not have getent gshadow" >&2 - exit 0 - ;; +case "$os" in + "freebsd"|"netbsd") + echo "$os does not have getent gshadow" + exit 0 + ;; esac -if command -v getent >/dev/null -then - getent gshadow "$name" || true -elif [ -f /etc/gshadow ] -then - grep "^${name}:" /etc/gshadow || true -else - not_supported -fi +getent gshadow "$name" || true diff --git a/cdist/conf/type/__hostname/explorer/has_hostnamectl b/cdist/conf/type/__hostname/explorer/has_hostnamectl index 2f531f30..9040023d 100755 --- a/cdist/conf/type/__hostname/explorer/has_hostnamectl +++ b/cdist/conf/type/__hostname/explorer/has_hostnamectl @@ -21,4 +21,4 @@ # Check whether system has hostnamectl # -command -v hostnamectl 2>/dev/null || true +command -v hostnamectl || true diff --git a/cdist/conf/type/__xymon_apache/explorer/active-conf b/cdist/conf/type/__hostname/explorer/hostname_file similarity index 72% rename from cdist/conf/type/__xymon_apache/explorer/active-conf rename to cdist/conf/type/__hostname/explorer/hostname_file index bd281e21..6a00aa9f 100755 --- a/cdist/conf/type/__xymon_apache/explorer/active-conf +++ b/cdist/conf/type/__hostname/explorer/hostname_file @@ -1,6 +1,6 @@ -#!/bin/sh -e +#!/bin/sh # -# 2018-2019 Thomas Eckert (tom at it-eckert.de) +# 2014 Nico Schottelius (nico-cdist at schottelius.org) # # This file is part of cdist. # @@ -16,7 +16,15 @@ # # You should have received a copy of the GNU General Public License # along with cdist. If not, see . +# +# +# Retrieve the contents of /etc/hostname +# -if [ -d /etc/apache2/mods-enabled ]; then - ls -1 /etc/apache2/conf-enabled/ +# Almost any distribution +if [ -f /etc/hostname ]; then + cat /etc/hostname +# SuSE +elif [ -f /etc/HOSTNAME ]; then + cat /etc/HOSTNAME fi diff --git a/cdist/conf/type/__user/manifest b/cdist/conf/type/__hostname/explorer/hostname_sysconfig old mode 100644 new mode 100755 similarity index 75% rename from cdist/conf/type/__user/manifest rename to cdist/conf/type/__hostname/explorer/hostname_sysconfig index 8f10b38c..d0d7b4e7 --- a/cdist/conf/type/__user/manifest +++ b/cdist/conf/type/__hostname/explorer/hostname_sysconfig @@ -1,6 +1,6 @@ -#!/bin/sh -e +#!/bin/sh # -# 2019 Nico Schottelius (nico-cdist at schottelius.org) +# 2014 Nico Schottelius (nico-cdist at schottelius.org) # # This file is part of cdist. # @@ -18,15 +18,9 @@ # along with cdist. If not, see . # # -# Manage users. +# Retrieve the contents of /etc/hostname +# -os=$(cat "$__global/explorer/os") - -case "$os" in - alpine) - __package shadow - ;; - *) - : - ;; -esac +if [ -f /etc/sysconfig/network ]; then + awk -F= '/^HOSTNAME=/ { print $2 }' /etc/sysconfig/network +fi diff --git a/cdist/conf/type/__hostname/explorer/max_len b/cdist/conf/type/__hostname/explorer/max_len deleted file mode 100644 index fb863949..00000000 --- a/cdist/conf/type/__hostname/explorer/max_len +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/sh -e - -command -v getconf >/dev/null || exit 0 - -val=$(getconf HOST_NAME_MAX 2>/dev/null) || exit 0 - -if test -n "${val}" -a "${val}" != 'undefined' -then - echo "${val}" -fi diff --git a/cdist/conf/type/__hostname/gencode-remote b/cdist/conf/type/__hostname/gencode-remote index ae224611..8b5797dd 100755 --- a/cdist/conf/type/__hostname/gencode-remote +++ b/cdist/conf/type/__hostname/gencode-remote @@ -2,7 +2,6 @@ # # 2014-2017 Steven Armstrong (steven-cdist at armstrong.cc) # 2014 Nico Schottelius (nico-cdist at schottelius.org) -# 2019 Dennis Camera (dennis.camera at ssrq-sds-fds.ch) # # This file is part of cdist. # @@ -20,81 +19,60 @@ # along with cdist. If not, see . # -os=$(cat "$__global/explorer/os") -name_running=$(cat "$__global/explorer/hostname") -has_hostnamectl=$(cat "$__object/explorer/has_hostnamectl") - - -if test -s "$__object/parameter/name" -then - name_should=$(cat "$__object/parameter/name") +if [ -f "$__object/parameter/name" ]; then + name_should="$(cat "$__object/parameter/name")" else - case $os - in - # RedHat-derivatives and BSDs - centos|fedora|redhat|scientific|freebsd|macosx|netbsd|openbsd) - # Hostname is FQDN - name_should="${__target_host}" - ;; - *) - # Hostname is only first component of FQDN - name_should="${__target_host%%.*}" - ;; - esac + name_should="${__target_host%%.*}" fi +os=$(cat "$__global/explorer/os") +name_running=$(cat "$__global/explorer/hostname") +name_config=$(cat "$__object/explorer/hostname_file") +name_sysconfig=$(cat "$__object/explorer/hostname_sysconfig") +has_hostnamectl=$(cat "$__object/explorer/has_hostnamectl") ################################################################################ -# Check if the (running) hostname is already correct +# If everything is ok -> exit # -test "$name_running" != "$name_should" || exit 0 - +case "$os" in + archlinux|debian|suse|ubuntu|devuan|coreos|alpine) + if [ "$name_config" = "$name_should" ] && [ "$name_running" = "$name_should" ]; then + exit 0 + fi + ;; + scientific|centos|freebsd|openbsd) + if [ "$name_sysconfig" = "$name_should" ] && [ "$name_running" = "$name_should" ]; then + exit 0 + fi + ;; + *) + echo "Unsupported os: $os" >&2 + exit 1 + ;; +esac ################################################################################ # Setup hostname # -echo 'changed' >>"$__messages_out" +echo changed >> "$__messages_out" -# Use the good old way to set the hostname. -case $os -in - alpine|debian|devuan|ubuntu) - echo 'hostname -F /etc/hostname' +# Use the good old way to set the hostname even on machines running systemd. +case "$os" in + archlinux|debian|ubuntu|devuan|centos|coreos|alpine) + printf "printf '%%s\\\\n' '$name_should' > /etc/hostname\\n" + echo "hostname -F /etc/hostname" ;; - archlinux) - echo 'command -v hostnamectl >/dev/null 2>&1' \ - "&& hostnamectl set-hostname '$name_should'" \ - "|| hostname '$name_should'" - ;; - centos|fedora|redhat|scientific|freebsd|netbsd|openbsd|gentoo|void) + freebsd|openbsd) echo "hostname '$name_should'" ;; - macosx) - echo "scutil --set HostName '$name_should'" - ;; - solaris) - echo "uname -S '$name_should'" - ;; - slackware|suse|opensuse-leap) - # We do not read from /etc/HOSTNAME, because the running - # hostname is the first component only while the file contains - # the FQDN. + suse) echo "hostname '$name_should'" - ;; - *) - # Fall back to set the hostname using hostnamectl, if available. - if test -n "$has_hostnamectl" - then - # Don't use hostnamectl as the primary means to set the hostname for - # systemd systems, because it cannot be trusted to work reliably and - # exit with non-zero when it fails (e.g. hostname too long, - # D-Bus failure, etc.). - - echo "hostnamectl set-hostname \"\$(cat /etc/hostname)\"" - echo "test \"\$(hostname)\" = \"\$(cat /etc/hostname)\"" \ - " || hostname -F /etc/hostname" - else - printf "echo 'Unsupported OS: %s' >&2\nexit 1\n" "$os" - fi + printf "printf '%%s\\\\n' '$name_should' > /etc/HOSTNAME\\n" ;; esac + +if [ "$has_hostnamectl" ]; then + # Allow hostnamectl set-hostname to fail silently. + # Who the fuck invented a tool that needs dbus to set the hostname anyway ... + echo "hostnamectl set-hostname '$name_should' || true" +fi diff --git a/cdist/conf/type/__hostname/man.rst b/cdist/conf/type/__hostname/man.rst index 72aefbab..d23a3b8a 100644 --- a/cdist/conf/type/__hostname/man.rst +++ b/cdist/conf/type/__hostname/man.rst @@ -8,10 +8,7 @@ cdist-type__hostname - Set the hostname DESCRIPTION ----------- -Sets the hostname on various operating systems. - -**Tip:** For advice on choosing a hostname, see -`RFC 1178 `_. +Set's the hostname on various operating systems. REQUIRED PARAMETERS @@ -21,7 +18,7 @@ None. OPTIONAL PARAMETERS ------------------- name - The hostname to set. Defaults to the first segment of __target_host + The hostname to set. Defaults to the first segment of __target_host (${__target_host%%.*}) diff --git a/cdist/conf/type/__hostname/manifest b/cdist/conf/type/__hostname/manifest index 75a90027..8f1adf12 100755 --- a/cdist/conf/type/__hostname/manifest +++ b/cdist/conf/type/__hostname/manifest @@ -2,7 +2,6 @@ # # 2012 Steven Armstrong (steven-cdist at armstrong.cc) # 2014 Nico Schottelius (nico-cdist at schottelius.org) -# 2019 Dennis Camera (dennis.camera at ssrq-sds-fds.ch) # # This file is part of cdist. # @@ -20,170 +19,50 @@ # along with cdist. If not, see . # -not_supported() { - 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 - exit 1 -} - -set_hostname_systemd() { - echo "$1" | __file /etc/hostname --source - -} - os=$(cat "$__global/explorer/os") -os_version=$(cat "$__global/explorer/os_version") -os_major=$(echo "$os_version" | grep -o '^[0-9][0-9]*') - -max_len=$(cat "$__object/explorer/max_len") -has_hostnamectl=$(cat "$__object/explorer/has_hostnamectl") - -if test -s "$__object/parameter/name" -then - name_should=$(cat "$__object/parameter/name") +if [ -f "$__object/parameter/name" ]; then + name_should="$(cat "$__object/parameter/name")" else - case $os - in - # RedHat-derivatives and BSDs - centos|fedora|redhat|scientific|freebsd|netbsd|openbsd|slackware) - # Hostname is FQDN - name_should="${__target_host}" - ;; - suse|opensuse-leap) - # Classic SuSE stores the FQDN in /etc/HOSTNAME, while - # systemd does not. The running hostname is the first - # component in both cases. - # In versions before 15.x, the FQDN is stored in /etc/hostname. - if test -n "$has_hostnamectl" && test "$os_major" -ge 15 \ - && test "$os_major" -ne 42 - then - name_should="${__target_host%%.*}" - else - name_should="${__target_host}" - fi - ;; - *) - # Hostname is only first component of FQDN on all other systems. - name_should="${__target_host%%.*}" - ;; + case "$os" in + openbsd) + name_should="${__target_host}" + ;; + *) + name_should="${__target_host%%.*}" + ;; esac fi -if test -n "$max_len" && test "$(printf '%s' "$name_should" | wc -c)" -gt "$max_len" -then - printf "Host name too long. Up to %u characters allowed.\n" "${max_len}" >&2 - exit 1 -fi -case $os -in - alpine|debian|devuan|ubuntu|void) - echo "$name_should" | __file /etc/hostname --source - - ;; - archlinux) - if test -n "$has_hostnamectl" - then - set_hostname_systemd "$name_should" - else - echo 'Ancient ArchLinux variants without hostnamectl are not supported.' >&2 - exit 1 - # Only for ancient ArchLinux, write to /etc/rc.conf on pre-systemd - # versions. There are some versions which use /etc/hostname but not - # systemd. It is unclear which ones these are. +not_supported() { + 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 + exit 1 +} - # __key_value '/etc/rc.conf:HOSTNAME' \ - # --file /etc/rc.conf \ - # --delimiter '=' --exact_delimiter \ - # --key 'HOSTNAME' \ - # --value "\"$name_should\"" - fi - ;; - centos|fedora|redhat|scientific) - if test -z "$has_hostnamectl" - then - # Only write to /etc/sysconfig/network on non-systemd versions. - # On systemd-based versions this entry is ignored. - __key_value '/etc/sysconfig/network:HOSTNAME' \ - --file /etc/sysconfig/network \ - --delimiter '=' --exact_delimiter \ - --key HOSTNAME \ - --value "\"$name_should\"" - else - set_hostname_systemd "$name_should" - fi - ;; - gentoo) - # Only write to /etc/conf.d/hostname on OpenRC-based installations. - # On systemd use hostnamectl(1) in gencode-remote. - if test -z "$has_hostnamectl" - then - __key_value '/etc/conf.d/hostname:hostname' \ - --file /etc/conf.d/hostname \ - --delimiter '=' --exact_delimiter \ - --key 'hostname' \ - --value "\"$name_should\"" - else - set_hostname_systemd "$name_should" - fi - ;; - freebsd) - __key_value '/etc/rc.conf:hostname' \ - --file /etc/rc.conf \ - --delimiter '=' --exact_delimiter \ - --key 'hostname' \ - --value "\"$name_should\"" - ;; - macosx) +case "$os" in + archlinux|debian|suse|ubuntu|devuan|coreos|alpine) # handled in gencode-remote : ;; - netbsd) - __key_value '/etc/rc.conf:hostname' \ + scientific|centos) + __key_value sysconfig-hostname \ + --file /etc/sysconfig/network \ + --delimiter '=' \ + --key HOSTNAME \ + --value "$name_should" --exact_delimiter + ;; + freebsd) + __key_value rcconf-hostname \ --file /etc/rc.conf \ - --delimiter '=' --exact_delimiter \ + --delimiter '=' \ --key 'hostname' \ - --value "\"$name_should\"" - - # To avoid confusion, ensure that the hostname is only stored once. - __file /etc/myname --state absent + --value "$name_should" ;; openbsd) echo "$name_should" | __file /etc/myname --source - ;; - slackware) - # We write the FQDN into /etc/HOSTNAME. But /etc/rc.d/rc.M will only - # read the first component from this file and set it as the running - # hostname on boot. - echo "$name_should" | __file /etc/HOSTNAME --source - - ;; - solaris) - echo "$name_should" | __file /etc/nodename --source - - ;; - suse|opensuse-leap) - # Modern SuSE provides /etc/HOSTNAME as a symlink for - # backwards-compatibility. Unfortunately it cannot be used - # here as __file does not follow the symlink. - # Therefore, we use the presence of the hostnamectl binary as - # an indication of which file to use. This unfortunately does - # not work correctly on openSUSE 12.x which provides - # hostnamectl but not /etc/hostname. - - if test -n "$has_hostnamectl" -a "$os_major" -gt 12 - then - hostname_file='/etc/hostname' - else - hostname_file='/etc/HOSTNAME' - fi - - echo "$name_should" | __file "$hostname_file" --source - - ;; *) - # On other operating systems we fall back to systemd's - # hostnamectl if available… - if test -n "$has_hostnamectl" - then - set_hostname_systemd "$name_should" - else - not_supported - fi + not_supported ;; esac diff --git a/cdist/conf/type/__letsencrypt_cert/manifest b/cdist/conf/type/__letsencrypt_cert/manifest index 68ecf9d4..d6892c9b 100755 --- a/cdist/conf/type/__letsencrypt_cert/manifest +++ b/cdist/conf/type/__letsencrypt_cert/manifest @@ -7,12 +7,6 @@ if [ -z "${certbot_fullpath}" ]; then os_version="$(cat "${__global}/explorer/os_version")" case "$os" in - archlinux) - __package certbot - ;; - alpine) - __package certbot - ;; debian) case "$os_version" in 8*) @@ -39,10 +33,6 @@ if [ -z "${certbot_fullpath}" ]; then require="__apt_source/stretch-backports" __package_apt certbot \ --target-release stretch-backports ;; - 10*) - __package_apt certbot - ;; - *) echo "Unsupported OS version: $os_version" >&2 exit 1 @@ -72,12 +62,11 @@ 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 ;; - beowulf*) - __package_apt certbot - ;; *) echo "Unsupported OS version: $os_version" >&2 exit 1 diff --git a/cdist/conf/type/__package_apk/explorer/state b/cdist/conf/type/__package_apk/explorer/state index b477ca7c..29ccf3a5 100755 --- a/cdist/conf/type/__package_apk/explorer/state +++ b/cdist/conf/type/__package_apk/explorer/state @@ -27,10 +27,6 @@ else name="$__object_id" fi -# Remove the @.. repo tag for finding out whether it is installed -# f.i. pass@testing => pass -name="$(echo "$name" | sed 's/@.*//')" - if [ "$(apk list -I "$name")" ]; then echo present else diff --git a/cdist/conf/type/__package_update_index/explorer/currage b/cdist/conf/type/__package_update_index/explorer/currage index cfb778d5..3539b8e1 100644 --- a/cdist/conf/type/__package_update_index/explorer/currage +++ b/cdist/conf/type/__package_update_index/explorer/currage @@ -34,9 +34,6 @@ case "$type" in echo 0 fi ;; - alpine) - echo 0 - ;; *) echo "Your specified type ($type) is currently not supported." >&2 echo "Please contribute an implementation for it if you can." >&2 ;; diff --git a/cdist/conf/type/__package_update_index/explorer/type b/cdist/conf/type/__package_update_index/explorer/type index c98e1e67..35254c5f 100644 --- a/cdist/conf/type/__package_update_index/explorer/type +++ b/cdist/conf/type/__package_update_index/explorer/type @@ -26,7 +26,6 @@ else amazon|scientific|centos|fedora|redhat) echo "yum" ;; debian|ubuntu|devuan) echo "apt" ;; archlinux) echo "pacman" ;; - alpine) echo "apk" ;; *) echo "Don't know how to manage packages on: $os" >&2 exit 1 diff --git a/cdist/conf/type/__package_update_index/gencode-remote b/cdist/conf/type/__package_update_index/gencode-remote index 9b2ecba2..738d38eb 100755 --- a/cdist/conf/type/__package_update_index/gencode-remote +++ b/cdist/conf/type/__package_update_index/gencode-remote @@ -47,10 +47,6 @@ case "$type" in echo "pacman --noprogressbar --sync --refresh" echo "pacman package database synced (age was: $currage)" >> "$__messages_out" ;; - alpine) - echo "apk update" - echo "apk package database updated." - ;; *) echo "Don't know how to manage packages for type: $type" >&2 exit 1 diff --git a/cdist/conf/type/__podman_compose/man.rst b/cdist/conf/type/__podman_compose/man.rst deleted file mode 100644 index fa98f443..00000000 --- a/cdist/conf/type/__podman_compose/man.rst +++ /dev/null @@ -1,61 +0,0 @@ -cdist-type__podman_compose(7) -============================= - -NAME ----- -cdist-type__podman_compose - install podman-compose - - -DESCRIPTION ------------ -Installs podman-compose package. -State 'absent' will not remove podman binary itself, -only podman-compose binary will be removed - - -REQUIRED PARAMETERS -------------------- -install - defaults to 'pip' - - -OPTIONAL PARAMETERS -------------------- -state - 'present' or 'absent', defaults to 'present' -user - the user who owns the file, defaults to 'root' - - -BOOLEAN PARAMETERS ------------------- -None. - - -EXAMPLES --------- - -.. code-block:: sh - - # Install podman-compose - __podman_compose - - # Install latest version via pip - __podman_compose --state present --install pip - - # Install latest version via pip and change user - __podman_compose --state present --install pip --user root - - # Remove podman-compose - __podman_compose --state absent - - -AUTHORS -------- -Daniel Tschada - - -COPYING -------- -Copyright \(C) 2019 Daniel Tschada. Free use of this software is -granted under the terms of the GNU General Public License version 3 or later (GPLv3+). diff --git a/cdist/conf/type/__podman_compose/manifest b/cdist/conf/type/__podman_compose/manifest deleted file mode 100755 index 2b06068d..00000000 --- a/cdist/conf/type/__podman_compose/manifest +++ /dev/null @@ -1,50 +0,0 @@ -#!/bin/sh -e -# -# 2019 Daniel Tschada -# -# 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 . -# - -# shellcheck disable=SC2154 -# shellcheck disable=SC2034 -install="$(cat "$__object/parameter/install")" -state="$(cat "$__object/parameter/state")" -user="$(cat "$__object/parameter/user")" -version="$(cat "$__object/parameter/version")" - -# install it with pip -if [ "${install}" = "pip" ]; then - - if [ "${state}" = "present" ]; then - __package_pip podman-compose --state present --pip /usr/local/bin/podman-compose --runas "${user}" - elif [ "${state}" = "absent" ]; then - __package_pip podman-compose --state absent - else - if [ "${state}" != "present" ] -a [ "${state}" != "absent" ]; then - echo "Unknown state: ${state}" >&2 - exit 1 - else - echo "Unknown user: ${user}" >&2 - exit 1 - fi - fi - -else - - echo "Unknown user: ${install}" >&2 - exit 1 - -fi \ No newline at end of file diff --git a/cdist/conf/type/__podman_compose/parameter/default/install b/cdist/conf/type/__podman_compose/parameter/default/install deleted file mode 100644 index a1b589e3..00000000 --- a/cdist/conf/type/__podman_compose/parameter/default/install +++ /dev/null @@ -1 +0,0 @@ -pip diff --git a/cdist/conf/type/__podman_compose/parameter/default/user b/cdist/conf/type/__podman_compose/parameter/default/user deleted file mode 100644 index d8649da3..00000000 --- a/cdist/conf/type/__podman_compose/parameter/default/user +++ /dev/null @@ -1 +0,0 @@ -root diff --git a/cdist/conf/type/__podman_compose/parameter/optional b/cdist/conf/type/__podman_compose/parameter/optional deleted file mode 100644 index 92913e56..00000000 --- a/cdist/conf/type/__podman_compose/parameter/optional +++ /dev/null @@ -1,4 +0,0 @@ -install -state -user -version diff --git a/cdist/conf/type/__podman_compose/parameter/required b/cdist/conf/type/__podman_compose/parameter/required deleted file mode 100644 index 7c32f559..00000000 --- a/cdist/conf/type/__podman_compose/parameter/required +++ /dev/null @@ -1 +0,0 @@ -install diff --git a/cdist/conf/type/__podman_compose/singleton b/cdist/conf/type/__podman_compose/singleton deleted file mode 100644 index e69de29b..00000000 diff --git a/cdist/conf/type/__postfix/manifest b/cdist/conf/type/__postfix/manifest index f3616979..1aea53a1 100755 --- a/cdist/conf/type/__postfix/manifest +++ b/cdist/conf/type/__postfix/manifest @@ -1,7 +1,6 @@ #!/bin/sh -e # # 2012-2014 Steven Armstrong (steven-cdist at armstrong.cc) -# 2019 Nico Schottelius (nico-cdist at schottelius.org) # # This file is part of cdist. # @@ -23,7 +22,7 @@ os=$(cat "$__global/explorer/os") case "$os" in - alpine|ubuntu|debian|archlinux|suse|scientific|centos|devuan) + ubuntu|debian|archlinux|suse|scientific|centos|devuan) __package postfix --state present ;; *) diff --git a/cdist/conf/type/__postfix_postconf/explorer/value b/cdist/conf/type/__postfix_postconf/explorer/value index 67dacad8..17126c94 100755 --- a/cdist/conf/type/__postfix_postconf/explorer/value +++ b/cdist/conf/type/__postfix_postconf/explorer/value @@ -22,7 +22,7 @@ os=$("$__explorer/os") case "$os" in - alpine|ubuntu|debian|archlinux|suse|scientific|centos|devuan) + ubuntu|debian|archlinux|suse|scientific|centos|devuan) : ;; *) diff --git a/cdist/conf/type/__postfix_postconf/gencode-remote b/cdist/conf/type/__postfix_postconf/gencode-remote index 279dddd4..6df0da7f 100755 --- a/cdist/conf/type/__postfix_postconf/gencode-remote +++ b/cdist/conf/type/__postfix_postconf/gencode-remote @@ -1,7 +1,6 @@ #!/bin/sh -e # # 2012-2014 Steven Armstrong (steven-cdist at armstrong.cc) -# 2019 Nico Schottelius (nico-cdist at schottelius.org) # # This file is part of cdist. # @@ -22,7 +21,7 @@ os=$(cat "$__global/explorer/os") case "$os" in - alpine|archlinux|centos|debian|devuan|suse|scientific|ubuntu) + ubuntu|debian|archlinux|suse|scientific|centos|devuan) : ;; *) diff --git a/cdist/conf/type/__prometheus_alertmanager/manifest b/cdist/conf/type/__prometheus_alertmanager/manifest index cf410c44..8ee818c3 100755 --- a/cdist/conf/type/__prometheus_alertmanager/manifest +++ b/cdist/conf/type/__prometheus_alertmanager/manifest @@ -30,7 +30,6 @@ if [ -f "$__object/parameter/install-from-backports" ]; then *) echo "--install-from-backports is only supported on Devuan -- ignoring." >&2 echo "Send a pull request if you require it." >&2 - exit 1 ;; esac else @@ -61,5 +60,5 @@ require="$require __directory/$storage_path $require_pkg" \ __config_file $CONF \ --source "$config" \ --group prometheus --mode 640 \ - --onchange "service prometheus-alertmanager restart" # TODO when a config-check tool is available, check config here + --onchange "service prometheus-alertmanager reload" # TODO when a config-check tool is available, check config here diff --git a/cdist/conf/type/__prometheus_exporter/manifest b/cdist/conf/type/__prometheus_exporter/manifest index f3930ac6..b9e14531 100644 --- a/cdist/conf/type/__prometheus_exporter/manifest +++ b/cdist/conf/type/__prometheus_exporter/manifest @@ -5,11 +5,9 @@ export GOBIN=/opt/gocode/bin # where to find go binaries exporter="$(cat "$__object/parameter/exporter")" [ -z "$exporter" ] && exporter="$__object_id" -__user prometheus -require="__user/prometheus" __group prometheus -require="__group/prometheus" __user_groups prometheus --group prometheus +__user prometheus --system -require="__user_groups/prometheus" +require="" case $exporter in node) TEXTFILES=/service/node-exporter/textfiles # path for the textfiles collector diff --git a/cdist/conf/type/__prometheus_server/manifest b/cdist/conf/type/__prometheus_server/manifest index 9756169e..8685130f 100755 --- a/cdist/conf/type/__prometheus_server/manifest +++ b/cdist/conf/type/__prometheus_server/manifest @@ -33,13 +33,11 @@ if [ -f "$__object/parameter/install-from-backports" ]; then *) echo "--install-from-backports is only supported on Devuan -- ignoring." >&2 echo "Send a pull request if you require it." >&2 - exit 1 ;; esac else __package prometheus - __package prometheus-blackbox-exporter - require_pkg="__package/prometheus __package/prometheus-blackbox-exporter" + require_pkg="__package/prometheus" fi ##### PREPARE PATHS AND SUCH ################################################ @@ -60,7 +58,7 @@ require="$require __directory/$storage_path $require_pkg" \ __config_file $CONF \ --source "$config" \ --group prometheus --mode 640 \ - --onchange "promtool check config $CONF && service prometheus restart" + --onchange "promtool check config $CONF && service prometheus reload" for file in $rule_files; do dest=$CONF_DIR/$(basename "$file") @@ -68,6 +66,6 @@ for file in $rule_files; do __config_file "$dest" \ --source "$file" \ --owner prometheus \ - --onchange "promtool check rules '$dest' && service prometheus restart" + --onchange "promtool check rules '$dest' && service prometheus reload" done diff --git a/cdist/conf/type/__sensible_editor/explorer/editor_path b/cdist/conf/type/__sensible_editor/explorer/editor_path deleted file mode 100644 index dcf63c9b..00000000 --- a/cdist/conf/type/__sensible_editor/explorer/editor_path +++ /dev/null @@ -1,131 +0,0 @@ -#!/bin/sh -e -# -# 2019 Dennis Camera (dennis.camera at ssrq-sds-fds.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 . -# -# -# Check if the given editor is present on the target system and determine its -# absolute path. -# - -die() { - echo "$@" >&2 - exit 1 -} - -editor_missing() { die "Editor '$1' is missing on the target system."; } -editor_no_alternative() { - die "Editor '$1' is not in the alternatives list of the target system." \ - "$(test -n "${editors}" && printf '\nPlease choose one of:\n\n%s\n' "${editors}")" -} - -# No need to check for the path if the file is supposed to be removed. -test "$(cat "${__object}/parameter/state")" != 'absent' || exit 0 - - -case $("${__explorer}/os") -in - debian|devuan|ubuntu) - has_alternatives=true - - # NOTE: Old versions do not support `--list`, in this case ignore the errors. - # This will require an absolute path to be provided, though. - editors=$(update-alternatives --list editor 2>/dev/null) - ;; - *) - # NOTE: RedHat has an alternatives system but it doesn't usually track - # editors and it is a pain to extract the list. - has_alternatives=false - ;; -esac - -# Read --editor parameter and check its value since it is "optional" -editor=$(cat "${__object}/parameter/editor" 2>/dev/null) || true -test -n "${editor}" || die 'Please provide an --editor to configure.' - -case $editor -in - /*) - is_abspath=true - ;; - */*) - die 'Relative editor paths are not supported' - ;; - *) - is_abspath=false - ;; -esac - - -if $has_alternatives && test -n "${editors}" -then - IFS=' -' - if ! $is_abspath - then - # First, try to resolve the absolute path using $editors. - while true - do - for e in $editors - do - if test "$(basename "${e}")" = "${editor}" - then - editor="${e}" - break 2 # break out of both loops - fi - done - - # Iterating through alternatives did not yield a result - editor_no_alternative "${editor}" - break - done - fi - - # Check if editor is present - test -f "${editor}" || editor_missing "${editor}" - - for e in $editors - do - if test "${editor}" = "${e}" - then - # Editor is part of the alternatives list -> use it! - echo "${editor}" - exit 0 - fi - done - - editor_no_alternative "${editor}" -else - # NOTE: This branch is mostly for RedHat-based systems which do - # not track editor alternatives. To make this type useful - # on RedHat at all we allow an absoloute path to be provided - # in any case. - - if $is_abspath - then - test -x "${editor}" || editor_missing "${editor}" - - echo "${editor}" - exit 0 - else - die "The target doesn't list any editor alternatives. " \ - "Please specify an absolute path or populate the alternatives list." - fi -fi - -# The script should never reach this statement! -exit 1 diff --git a/cdist/conf/type/__sensible_editor/explorer/group b/cdist/conf/type/__sensible_editor/explorer/group deleted file mode 100644 index 5d288189..00000000 --- a/cdist/conf/type/__sensible_editor/explorer/group +++ /dev/null @@ -1,26 +0,0 @@ -#!/bin/sh -e -# -# 2019 Dennis Camera (dennis.camera at ssrq-sds-fds.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 . -# -# -# Determines the primary group of the user. -# - -user=$__object_id - -id -gn "${user}" 2>/dev/null diff --git a/cdist/conf/type/__sensible_editor/explorer/user_home b/cdist/conf/type/__sensible_editor/explorer/user_home deleted file mode 100644 index b88243f7..00000000 --- a/cdist/conf/type/__sensible_editor/explorer/user_home +++ /dev/null @@ -1,33 +0,0 @@ -#!/bin/sh -e -# -# 2019 Dennis Camera (dennis.camera at ssrq-sds-fds.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 . -# -# -# Determines the home folder of the target user. -# - -user=$__object_id -home=$(getent passwd "${user}" | cut -d':' -f6) - -if ! test -d "${home}" -then - echo "Cannot find home directory of user ${user}" >&2 - exit 1 -fi - -echo "${home}" diff --git a/cdist/conf/type/__sensible_editor/man.rst b/cdist/conf/type/__sensible_editor/man.rst deleted file mode 100644 index 9b805e06..00000000 --- a/cdist/conf/type/__sensible_editor/man.rst +++ /dev/null @@ -1,78 +0,0 @@ -cdist-type__sensible_editor(7) -============================== - -NAME ----- -cdist-type__sensible_editor - Select the sensible-editor - - -DESCRIPTION ------------ -This cdist type allows you to select the :strong:`sensible-editor` for -a given user. - - -REQUIRED PARAMETERS -------------------- -editor - Name or path of the editor to be selected. - On systems other than Debian derivatives an absolute path is required. - - It is permissible to omit this parameter if --state is absent. - - -OPTIONAL PARAMETERS -------------------- -state - 'present', 'absent', or 'exists'. Defaults to 'present', where: - - present - the sensible-editor is exactly what is specified in --editor. - absent - no sensible-editor configuration is present. - exists - the sensible-editor will be set to what is specified in --editor, - unless there already is a configuration on the target system. - - -EXAMPLES --------- - -.. code-block:: sh - - __sensible_editor root --editor /bin/ed # ed(1) is the standard - __sensible_editor noob --editor nano - - -LIMITATIONS ------------ - -This type depends upon the :strong:`sensible-editor`\ (1) script which -is part of the sensible-utils package. - -Therefore, the following operating systems are supported: - * Debian 8 (jessie) or later - * Devuan - * Ubuntu 8.10 (intrepid) or later - * RHEL/CentOS 7 or later (EPEL repo required) - * Fedora 21 or later - -Note: on old versions of Ubuntu the sensible-* utils are part of the -debianutils package. - -SEE ALSO --------- -:strong:`select-editor`\ (1), :strong:`sensible-editor`\ (1). - - -AUTHOR -------- -Dennis Camera - - -COPYING -------- -Copyright \(C) 2019 Dennis Camera. -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/__sensible_editor/manifest b/cdist/conf/type/__sensible_editor/manifest deleted file mode 100644 index 1cdb0c2c..00000000 --- a/cdist/conf/type/__sensible_editor/manifest +++ /dev/null @@ -1,94 +0,0 @@ -#!/bin/sh -e -# -*- mode: sh; indent-tabs-mode: t -*- -# -# 2019 Dennis Camera (dennis.camera at ssrq-sds-fds.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 . -# - -version_ge() { - awk -F '[^0-9.]' -v target="${1:?}" ' - function max(x, y) { return x > y ? x : y; } - BEGIN { - getline; - nx = split($1, x, "."); - ny = split(target, y, "."); - for (i = 1; i <= max(nx, ny); ++i) { - diff = int(x[i]) - int(y[i]); - if (diff < 0) exit 1; - else if (diff > 0) exit 0; - else continue; - } - }' -} - -not_supported() { - echo "OS ${os} does not support __sensible_editor." >&2 - echo 'If it does, please provide a patch.' >&2 - exit 1 -} - -os=$(cat "${__global}/explorer/os") -os_version=$(cat "${__global}/explorer/os_version") - -state=$(cat "${__object}/parameter/state") -user=$__object_id - -if test "${state}" != 'present' && test "${state}" != 'exists' && test "${state}" != 'absent' -then - echo 'Only "present", "exists", and "absent" are allowed for --state' >&2 - exit 1 -fi - -package_name='sensible-utils' - -case $os -in - debian) - pkg_type='apt' - ;; - devuan) - pkg_type='apt' - ;; - ubuntu) - (echo "${os_version}" | version_ge 10.04) || package_name='debianutils' - pkg_type='apt' - ;; - centos|fedora|redhat|scientific) - pkg_type='yum' - ;; - *) - not_supported - ;; -esac - -if test "${state}" != 'absent' -then - __package "${package_name}" --state present \ - --type "${pkg_type}" - export require="__package/${package_name}" -fi - -editor_path=$(cat "${__object}/explorer/editor_path") -user_home=$(cat "${__object}/explorer/user_home") -group=$(cat "${__object}/explorer/group") - -__file "${user_home}/.selected_editor" --state "${state}" \ - --owner "${user}" --group "${group}" --mode 0644 \ - --source - </dev/null - then - owner_line=$(getent passwd "$owner") - elif [ -f /etc/passwd ] - then - case $owner - in - [0-9][0-9]*) - owner_line=$(awk -F: "\$3 == \"${owner}\" { print }" /etc/passwd) - ;; - *) - owner_line=$(awk -F: "\$1 == \"${owner}\" { print }" /etc/passwd) - ;; - esac - fi - - if [ "$owner_line" ] - then - home=$(echo "$owner_line" | cut -d':' -f6) - fi - - if [ ! -d "$home" ] - then - # Don't know how to determine user's home directory, fall back to ~ - home="~$owner" - command -v realpath >/dev/null && home=$(realpath "$home") - fi - - [ -d "$home" ] && echo "$home/.ssh/authorized_keys" + owner="$(cat "$__object/parameter/owner" 2>/dev/null || echo "$__object_id")" + home=$(getent passwd "$owner" | cut -d':' -f 6) + echo "$home/.ssh/authorized_keys" fi diff --git a/cdist/conf/type/__ssh_authorized_keys/explorer/group b/cdist/conf/type/__ssh_authorized_keys/explorer/group index d259050f..72a4e314 100755 --- a/cdist/conf/type/__ssh_authorized_keys/explorer/group +++ b/cdist/conf/type/__ssh_authorized_keys/explorer/group @@ -1,7 +1,6 @@ #!/bin/sh # # 2014 Steven Armstrong (steven-cdist at armstrong.cc) -# 2019 Dennis Camera (dennis.camera at ssrq-sds-fds.ch) # # This file is part of cdist. # @@ -19,28 +18,6 @@ # along with cdist. If not, see . # -if [ -s "$__object/parameter/owner" ] -then - owner=$(cat "$__object/parameter/owner") -else - owner="$__object_id" -fi - -if command -v getent >/dev/null -then - gid=$(getent passwd "$owner" | cut -d':' -f4) - getent group "$gid" || true -else - # Fallback to local file scanning - case $owner - in - [0-9][0-9]*) - gid=$(awk -F: "\$3 == \"${owner}\" { print \$4 }" /etc/passwd) - ;; - *) - gid=$(awk -F: "\$1 == \"${owner}\" { print \$4 }" /etc/passwd) - ;; - esac - - awk -F: "\$3 == \"$gid\" { print }" /etc/group -fi +owner="$(cat "$__object/parameter/owner" 2>/dev/null || echo "$__object_id")" +gid="$(getent passwd "$owner" | cut -d':' -f 4)" +getent group "$gid" || true diff --git a/cdist/conf/type/__ssh_authorized_keys/manifest b/cdist/conf/type/__ssh_authorized_keys/manifest index b9f0582e..b507c7ff 100755 --- a/cdist/conf/type/__ssh_authorized_keys/manifest +++ b/cdist/conf/type/__ssh_authorized_keys/manifest @@ -23,12 +23,6 @@ owner="$(cat "$__object/parameter/owner" 2>/dev/null || echo "$__object_id")" state="$(cat "$__object/parameter/state" 2>/dev/null)" file="$(cat "$__object/explorer/file")" -if [ ! -f "$__object/parameter/nofile" ] && [ -z "$file" ] -then - echo "Cannot determine path of authorized_keys file" >&2 - exit 1 -fi - if [ ! -f "$__object/parameter/noparent" ] || [ ! -f "$__object/parameter/nofile" ]; then group="$(cut -d':' -f 1 "$__object/explorer/group")" if [ -z "$group" ]; then diff --git a/cdist/conf/type/__ssh_dot_ssh/explorer/group b/cdist/conf/type/__ssh_dot_ssh/explorer/group index faf44cb8..cdea6fe7 100755 --- a/cdist/conf/type/__ssh_dot_ssh/explorer/group +++ b/cdist/conf/type/__ssh_dot_ssh/explorer/group @@ -1,7 +1,6 @@ #!/bin/sh # # 2014 Steven Armstrong (steven-cdist at armstrong.cc) -# 2019 Dennis Camera (dennis.camera at ssrq-sds-fds.ch) # # This file is part of cdist. # @@ -19,11 +18,5 @@ # along with cdist. If not, see . # -gid=$("$__type_explorer/passwd" | cut -d':' -f4) - -if command -v getent >/dev/null -then - getent group "$gid" || true -else - awk -F: "\$3 == \"$gid\" { print }" /etc/group -fi +gid="$("$__type_explorer/passwd" | cut -d':' -f 4)" +getent group "$gid" || true diff --git a/cdist/conf/type/__ssh_dot_ssh/explorer/passwd b/cdist/conf/type/__ssh_dot_ssh/explorer/passwd index 42686b20..3fbad06f 100755 --- a/cdist/conf/type/__ssh_dot_ssh/explorer/passwd +++ b/cdist/conf/type/__ssh_dot_ssh/explorer/passwd @@ -2,7 +2,6 @@ # # 2012 Steven Armstrong (steven-cdist at armstrong.cc) # 2014 Nico Schottelius (nico-cdist at schottelius.org) -# 2019 Dennis Camera (dennis.camera at ssrq-sds-fds.ch) # # This file is part of cdist. # @@ -22,16 +21,4 @@ owner="$__object_id" -if command -v getent >/dev/null -then - getent passwd "$owner" || true -else - case $owner in - [0-9][0-9]*) - awk -F: "\$3 == \"$owner\" { print }" /etc/passwd - ;; - *) - grep "^$owner:" /etc/passwd || true - ;; - esac -fi +getent passwd "$owner" || true diff --git a/cdist/conf/type/__sysctl/manifest b/cdist/conf/type/__sysctl/manifest index 71dea7f7..b4e2e902 100755 --- a/cdist/conf/type/__sysctl/manifest +++ b/cdist/conf/type/__sysctl/manifest @@ -2,7 +2,6 @@ # # 2014 Steven Armstrong (steven-cdist at armstrong.cc) # 2018 Takashi Yoshi (takashi at yoshi.email) -# 2019 Nico Schottelius (nico-cdist at schottelius.org) # # This file is part of cdist. # @@ -25,7 +24,7 @@ os=$(cat "$__global/explorer/os") case "$os" in # Linux - alpine|redhat|centos|ubuntu|debian|devuan|archlinux|coreos) + redhat|centos|ubuntu|debian|devuan|archlinux|coreos) : ;; # BSD diff --git a/cdist/conf/type/__user/explorer/group b/cdist/conf/type/__user/explorer/group index 0fd1471a..2aae2973 100755 --- a/cdist/conf/type/__user/explorer/group +++ b/cdist/conf/type/__user/explorer/group @@ -23,9 +23,11 @@ if [ -f "$__object/parameter/gid" ]; then gid=$(cat "$__object/parameter/gid") - if command -v getent >/dev/null; then - getent group "$gid" || true + getent=$(command -v getent) + if [ X != X"${getent}" ]; then + "${getent}" group "$gid" || true elif [ -f /etc/group ]; then grep -E "^(${gid}|([^:]+:){2}${gid}):" /etc/group || true fi fi + diff --git a/cdist/conf/type/__user/explorer/passwd b/cdist/conf/type/__user/explorer/passwd index b8391a6f..677e3ff0 100755 --- a/cdist/conf/type/__user/explorer/passwd +++ b/cdist/conf/type/__user/explorer/passwd @@ -23,8 +23,9 @@ name=$__object_id -if command -v getent >/dev/null; then - getent passwd "$name" || true +getent=$(command -v getent) +if [ X != X"${getent}" ]; then + "${getent}" passwd "$name" || true elif [ -f /etc/passwd ]; then grep "^${name}:" /etc/passwd || true fi diff --git a/cdist/conf/type/__user/explorer/shadow b/cdist/conf/type/__user/explorer/shadow index 73ce0e29..c49992d5 100755 --- a/cdist/conf/type/__user/explorer/shadow +++ b/cdist/conf/type/__user/explorer/shadow @@ -1,4 +1,4 @@ -#!/bin/sh -e +#!/bin/sh # # 2011 Steven Armstrong (steven-cdist at armstrong.cc) # @@ -22,19 +22,18 @@ # name=$__object_id +os="$("$__explorer/os")" +# Default to using shadow passwords +database="shadow" -case $("$__explorer/os") in - 'freebsd'|'netbsd'|'openbsd') - database='passwd' - ;; - # Default to using shadow passwords - *) - database='shadow' - ;; +case "$os" in + "freebsd"|"netbsd"|"openbsd") database="passwd";; esac + -if command -v getent >/dev/null; then - getent "$database" "$name" || true +getent=$(command -v getent) +if [ X != X"${getent}" ]; then + "${getent}" "$database" "$name" || true elif [ -f /etc/shadow ]; then grep "^${name}:" /etc/shadow || true fi diff --git a/cdist/conf/type/__xymon_apache/explorer/active-modules b/cdist/conf/type/__xymon_apache/explorer/active-modules deleted file mode 100755 index 4c745ced..00000000 --- a/cdist/conf/type/__xymon_apache/explorer/active-modules +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/sh -e - -if [ -d /etc/apache2/mods-enabled ]; then - /usr/sbin/apachectl -t -D DUMP_MODULES | awk '/.*_module/ { gsub(/_module.*$/, ""); gsub(/^ /, ""); print }' -fi diff --git a/cdist/conf/type/__xymon_apache/gencode-remote b/cdist/conf/type/__xymon_apache/gencode-remote deleted file mode 100755 index e7d8e344..00000000 --- a/cdist/conf/type/__xymon_apache/gencode-remote +++ /dev/null @@ -1,56 +0,0 @@ -#!/bin/sh -e -# -# 2018-2019 Thomas Eckert (tom at it-eckert.de) -# -# 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 . - -state=$(cat "$__object/parameter/state") - -os=$(cat "$__global/explorer/os") -case "$os" in - debian|ubuntu) - : - ;; - *) - 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 - exit 1 - ;; -esac - -if [ "$state" = "present" ]; then - if ! grep -q ^rewrite "$__object/explorer/active-modules"; then - echo "a2enmod rewrite >/dev/null" - echo "mod:rewrite enabled" >> "$__messages_out" - fi - if ! grep -q "^cgi$" "$__object/explorer/active-modules"; then - echo "a2enmod cgi >/dev/null" - echo "mod:cgi enabled" >> "$__messages_out" - fi - - if ! grep -q ^xymon.conf "$__object/explorer/active-conf"; then - echo "a2enconf xymon >/dev/null" - echo "conf:xymon enabled" >> "$__messages_out" - fi -fi - -if grep -q "^mod:.* enabled" "$__messages_out"; then - echo "systemctl restart apache2.service" - echo "apache restarted" >> "$__messages_out" -elif grep -q "^conf:xymon enabled" "$__messages_out"; then - echo "systemctl reload apache2.service" - echo "apache reloaded" >> "$__messages_out" -fi diff --git a/cdist/conf/type/__xymon_apache/man.rst b/cdist/conf/type/__xymon_apache/man.rst deleted file mode 100644 index 8358c821..00000000 --- a/cdist/conf/type/__xymon_apache/man.rst +++ /dev/null @@ -1,79 +0,0 @@ -cdist-type__xymon_apache(7) -=========================== - -NAME ----- -cdist-type__xymon_apache - Configure apache2-webserver for Xymon - - -DESCRIPTION ------------ -This cdist type installs and configures apache2 to be used "exclusively" (in -the sense that no other use is taken care of) with Xymon (the systems and -network monitor). - -It depends on `__xymon_server`. - - -REQUIRED PARAMETERS -------------------- -None. - - -OPTIONAL PARAMETERS -------------------- -state - 'present', 'absent', defaults to 'present'. - -ipacl - IP(-ranges) that have access to the Xymon webpages and CGIs. Apache2-style - syntax suitable for `Require ip ...`. Example: `192.168.1.0/24 10.0.0.0/8` - - -MESSAGES --------- -mod:rewrite enabled - apache module enabled -conf:xymon enabled - apache config for xymon enabled -apache restarted - apache2.service was reloaded -apache reloaded - apache2.service was restarted - - -EXPLORERS ---------- -active-conf - lists apache2 `conf-enabled` -active-modules - lists active apache2-modules - - -EXAMPLES --------- - -.. code-block:: sh - - # minmal, only localhost-access: - __xymon_apache - # allow more IPs to access the Xymon-webinterface: - __xymon_apache --ipacl "192.168.0.0/16 10.0.0.0/8" --state "present" - - -SEE ALSO --------- -:strong:`cdist__xymon_server`\ (7) - - -AUTHORS -------- -Thomas Eckert - - -COPYING -------- -Copyright \(C) 2018-2019 Thomas Eckert. 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/__xymon_apache/parameter/default/state b/cdist/conf/type/__xymon_apache/parameter/default/state deleted file mode 100644 index e7f6134f..00000000 --- a/cdist/conf/type/__xymon_apache/parameter/default/state +++ /dev/null @@ -1 +0,0 @@ -present diff --git a/cdist/conf/type/__xymon_apache/parameter/optional b/cdist/conf/type/__xymon_apache/parameter/optional deleted file mode 100644 index d374ec41..00000000 --- a/cdist/conf/type/__xymon_apache/parameter/optional +++ /dev/null @@ -1,2 +0,0 @@ -state -ipacl diff --git a/cdist/conf/type/__xymon_apache/singleton b/cdist/conf/type/__xymon_apache/singleton deleted file mode 100644 index e69de29b..00000000 diff --git a/cdist/conf/type/__xymon_client/gencode-remote b/cdist/conf/type/__xymon_client/gencode-remote deleted file mode 100755 index 49eed317..00000000 --- a/cdist/conf/type/__xymon_client/gencode-remote +++ /dev/null @@ -1,28 +0,0 @@ -#!/bin/sh -e -# -# 2018-2019 Thomas Eckert (tom at it-eckert.de) -# -# 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 . - -servers=$(cat "$__object/parameter/servers") - -if grep -q ^__key_value/CLIENTHOSTNAME "$__messages_in" || grep -q ^__key_value/XYMONSERVERS "$__messages_in" ; then - echo "systemctl restart xymon-client" - echo "restarted" >> "$__messages_out" - cat <<-EOT - echo "xymon-client xymon-client/XYMONSERVERS string $servers" | debconf-set-selections - EOT -fi diff --git a/cdist/conf/type/__xymon_client/man.rst b/cdist/conf/type/__xymon_client/man.rst deleted file mode 100644 index 05d085dc..00000000 --- a/cdist/conf/type/__xymon_client/man.rst +++ /dev/null @@ -1,66 +0,0 @@ -cdist-type__xymon_client(7) -=========================== - -NAME ----- -cdist-type__xymon_client - Install the Xymon client - - -DESCRIPTION ------------ -This cdist type installs the Xymon client and configures it to report with -FQDN. - - -REQUIRED PARAMETERS -------------------- -None. - - -OPTIONAL PARAMETERS -------------------- -state - 'present', 'absent', defaults to 'present'. - -servers - One or more IP addresses (space separated) of the Xymon server(s) to report - to. While DNS-names are ok it is discouraged, defaults to 127.0.0.1. - - -BOOLEAN PARAMETERS ------------------- -msgcache - Enable xymon `msgcache`. Note: XYMONSERVER has to be `127.0.0.1` for using - `msgcache` (see `msgcache (8)` of the xymon documentation for details). - -EXAMPLES --------- - -.. code-block:: sh - - # minimal, report to 127.0.0.1 - __xymon_client - - # specify server: - __xymon_client --servers "192.168.1.1" - - # activate `msgcache` for passive client: - __xymon_client --msgcache - - -SEE ALSO --------- -:strong:`cdist__xymon_server`\ (7), :strong:`xymon`\ (7), :strong:`msgcache`\ (8) - - -AUTHORS -------- -Thomas Eckert - - -COPYING -------- -Copyright \(C) 2018-2019 Thomas Eckert. 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/__xymon_client/manifest b/cdist/conf/type/__xymon_client/manifest deleted file mode 100755 index 88293a12..00000000 --- a/cdist/conf/type/__xymon_client/manifest +++ /dev/null @@ -1,54 +0,0 @@ -#!/bin/sh -e -# -# 2018-2019 Thomas Eckert (tom at it-eckert.de) -# -# 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 . - -state=$(cat "$__object/parameter/state") -servers=$(cat "$__object/parameter/servers") - -os=$(cat "$__global/explorer/os") -case "$os" in - debian|ubuntu) - : - ;; - *) - 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 - exit 1 - ;; -esac - -__package xymon-client --state "$state" - -if [ -f "$__object/parameter/msgcache" ]; then - require="__package/xymon-client" __line /etc/xymon/clientlaunch.cfg \ - --regex DISABLED --state absent -fi - -require="__package/xymon-client" __key_value CLIENTHOSTNAME \ - --file /etc/default/xymon-client \ - --value "'$__target_hostname'" \ - --delimiter '=' \ - --state "$state" -require="__package/xymon-client" __key_value XYMONSERVERS \ - --file /etc/default/xymon-client \ - --value "'$servers'" \ - --delimiter '=' \ - --state "$state" - -## CLI-usage often requires a shell: -require="__package/xymon-client" __user xymon --shell "/bin/bash" --state "$state" diff --git a/cdist/conf/type/__xymon_client/parameter/boolean b/cdist/conf/type/__xymon_client/parameter/boolean deleted file mode 100644 index 0dd7839d..00000000 --- a/cdist/conf/type/__xymon_client/parameter/boolean +++ /dev/null @@ -1 +0,0 @@ -msgcache diff --git a/cdist/conf/type/__xymon_client/parameter/default/servers b/cdist/conf/type/__xymon_client/parameter/default/servers deleted file mode 100644 index 7b9ad531..00000000 --- a/cdist/conf/type/__xymon_client/parameter/default/servers +++ /dev/null @@ -1 +0,0 @@ -127.0.0.1 diff --git a/cdist/conf/type/__xymon_client/parameter/default/state b/cdist/conf/type/__xymon_client/parameter/default/state deleted file mode 100644 index e7f6134f..00000000 --- a/cdist/conf/type/__xymon_client/parameter/default/state +++ /dev/null @@ -1 +0,0 @@ -present diff --git a/cdist/conf/type/__xymon_client/parameter/optional b/cdist/conf/type/__xymon_client/parameter/optional deleted file mode 100644 index 7c34489a..00000000 --- a/cdist/conf/type/__xymon_client/parameter/optional +++ /dev/null @@ -1,2 +0,0 @@ -state -servers diff --git a/cdist/conf/type/__xymon_client/singleton b/cdist/conf/type/__xymon_client/singleton deleted file mode 100644 index e69de29b..00000000 diff --git a/cdist/conf/type/__xymon_config/files/.keep b/cdist/conf/type/__xymon_config/files/.keep deleted file mode 100644 index e69de29b..00000000 diff --git a/cdist/conf/type/__xymon_config/man.rst b/cdist/conf/type/__xymon_config/man.rst deleted file mode 100644 index 8adfbe1f..00000000 --- a/cdist/conf/type/__xymon_config/man.rst +++ /dev/null @@ -1,78 +0,0 @@ -cdist-type__xymon_config(7) -=========================== - -NAME ----- -cdist-type__xymon_config - Deploy a Xymon configuration-directory - - -DESCRIPTION ------------ -This cdist type deploys a full Xymon configuration directory from the files-dir -to the host. This type requires an installed Xymon server, e.g. deployed by -`__xymon_server`. - -WARNING: This type _replaces_ the `/etc/xymon/`-directory! The previous -contents is replaced/deleted! - - -REQUIRED PARAMETERS -------------------- -confdir - The directory in `./files/` that contains the `/etc/xymon/`-content to be - deployed. - - -OPTIONAL PARAMETERS -------------------- -owner - passed as-is as `--owner` to `__rsync` - -group - passed as-is as `--group` to `__rsync` - - -OPTIONAL MULTIPLE PARAMETERS ----------------------------- -rsync-opts - identical to __rsync type, only `--`-options are supported - - -REQUIRED FILES --------------- -The directory specified by `confdir` has to contain a valid xymon-configuration -(`/etc/xymon/`) _plus_ the `ext/`-directory that normally resides in -`/usr/lib/xymon/server/`. - - -EXAMPLES --------- - -.. code-block:: sh - - __xymon_config --confdir=xymon.example.com - # this will replace /etc/xymon/ on the target host with - # the contents from __xymon_config/files/xymon.example.com/ - - ## the same but set ownership to `xymon:xymon` and exclude - ## the `netrc`-file: - __xymon_config --confdir=xymon.example.com \ - --owner xymon --group xymon \ - --rsync-opts "exclude=netrc" - - -SEE ALSO --------- -:strong:`cdist__xymon_server`\ (7), :strong:`cdist__rsync`\ (7), :strong:`xymon`\ (7) - -AUTHORS -------- -Thomas Eckert - - -COPYING -------- -Copyright \(C) 2018-2019 Thomas Eckert. 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/__xymon_config/manifest b/cdist/conf/type/__xymon_config/manifest deleted file mode 100644 index 4a5fb6c9..00000000 --- a/cdist/conf/type/__xymon_config/manifest +++ /dev/null @@ -1,43 +0,0 @@ -#!/bin/sh -e -# -# 2018-2019 Thomas Eckert (tom at it-eckert.de) -# -# 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 . - -confdir=$(cat "$__object/parameter/confdir") -set -- -if [ -f "$__object/parameter/owner" ]; then - owner=$(cat "$__object/parameter/owner") - set -- "$@" "--owner $owner" -fi -if [ -f "$__object/parameter/group" ]; then - group=$(cat "$__object/parameter/group") - set -- "$@" "--group $group" -fi - -## pass `--rsync-opts` as-is to `__rsync`: -if [ -f "$__object/parameter/rsync-opts" ]; then - while read -r opts; do - # shellcheck disable=SC2089 - set -- "$@" "--rsync-opts '$opts'" - done < "$__object/parameter/rsync-opts" -fi - -# shellcheck disable=SC2068,SC2090 -__rsync /etc/xymon/ \ - --source "$__type/files/$confdir/" \ - --rsync-opts "delete" \ - $@ diff --git a/cdist/conf/type/__xymon_config/parameter/optional b/cdist/conf/type/__xymon_config/parameter/optional deleted file mode 100644 index 866b4bde..00000000 --- a/cdist/conf/type/__xymon_config/parameter/optional +++ /dev/null @@ -1,2 +0,0 @@ -owner -group diff --git a/cdist/conf/type/__xymon_config/parameter/optional_multiple b/cdist/conf/type/__xymon_config/parameter/optional_multiple deleted file mode 100644 index fdb7cd88..00000000 --- a/cdist/conf/type/__xymon_config/parameter/optional_multiple +++ /dev/null @@ -1 +0,0 @@ -rsync-opts diff --git a/cdist/conf/type/__xymon_config/parameter/required b/cdist/conf/type/__xymon_config/parameter/required deleted file mode 100644 index 43222f13..00000000 --- a/cdist/conf/type/__xymon_config/parameter/required +++ /dev/null @@ -1 +0,0 @@ -confdir diff --git a/cdist/conf/type/__xymon_config/singleton b/cdist/conf/type/__xymon_config/singleton deleted file mode 100644 index e69de29b..00000000 diff --git a/cdist/conf/type/__xymon_server/gencode-remote b/cdist/conf/type/__xymon_server/gencode-remote deleted file mode 100755 index 0770e319..00000000 --- a/cdist/conf/type/__xymon_server/gencode-remote +++ /dev/null @@ -1,26 +0,0 @@ -#!/bin/sh -e -# -# 2018-2019 Thomas Eckert (tom at it-eckert.de) -# -# 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 . - -## "move" user-modified dirs to /etc/xymon to be managed by __xymon_config: -cat <<-EOT - if [ ! -L /usr/lib/xymon/server/ext ]; then - mv /usr/lib/xymon/server/ext /etc/xymon - ln -s /etc/xymon/ext /usr/lib/xymon/server/ - fi -EOT diff --git a/cdist/conf/type/__xymon_server/man.rst b/cdist/conf/type/__xymon_server/man.rst deleted file mode 100644 index a9a180e1..00000000 --- a/cdist/conf/type/__xymon_server/man.rst +++ /dev/null @@ -1,87 +0,0 @@ -cdist-type__xymon_server(7) -=========================== - -NAME ----- -cdist-type__xymon_server - Install a Xymon server - - -DESCRIPTION ------------ -This cdist type installs a Xymon (https://www.xymon.com/) server and (optional) -required helper packages. - -This includes the Xymon client as a dependency, so NO NEED to install -`__xymon_client` separately. - -To access the webinterface a webserver is required. The cdist-type -`__xymon_apache` can be used to install and configure the apache webserver for -the use with Xymon. - -Further and day-to-day configuration of Xymon can either be done manually in -`/etc/xymon/` or the directory can be deployed and managed by `__xymon_config`. - - -REQUIRED PARAMETERS -------------------- -None. - - -OPTIONAL PARAMETERS -------------------- -state - 'present', 'absent', defaults to 'present'. If '--install_helpers' is - specified for 'absent' the helper packages will be un-installed. - - -BOOLEAN PARAMETERS ------------------- -install_helpers - Install helper packages used by Xymon (fping, heirloom-mailx, traceroute, - ntpdate). - - -EXAMPLES --------- - -.. code-block:: sh - - # minmal - __xymon_server - - # the same - __xymon_server --state present - - # also install helper packages: - __xymon_server --install_helpers - - # examples to give a more complete picture: __xymon_server installed on - # `xymon.example.com` w/ IP 192.168.1.1: - # - # install webserver and grant 2 private subnets access to the webinterface: - __xymon_apache --ipacl "192.168.0.0/16 10.0.0.0/8" - # deploy server-configuration with __xymon_config: - __xymon_config --confdir=xymon.example.com - - # install xymon-client on other machines (not needed on the server): - __xymon_client --servers "192.168.1.1" - - - -SEE ALSO --------- -:strong:`cdist__xymon_apache`\ (7), :strong:`cdist__xymon_config`\ (7), -:strong:`cdist__xymon_client`\ (7), :strong:`xymon`\ (7) - - -AUTHORS -------- -Thomas Eckert - - -COPYING -------- -Copyright \(C) 2018-2019 Thomas Eckert. 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/__xymon_server/manifest b/cdist/conf/type/__xymon_server/manifest deleted file mode 100755 index 7cee0d23..00000000 --- a/cdist/conf/type/__xymon_server/manifest +++ /dev/null @@ -1,50 +0,0 @@ -#!/bin/sh -e -# -# 2018-2019 Thomas Eckert (tom at it-eckert.de) -# -# 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 . - -state=$(cat "$__object/parameter/state") -if [ -f "$__object/parameter/install_helpers" ]; then - install_helpers=1 -else - install_helpers=0 -fi - -os=$(cat "$__global/explorer/os") -case "$os" in - debian|ubuntu) - : - ;; - *) - 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 - exit 1 - ;; -esac - -__package xymon --state "$state" - -## install helper-packages/tools used by the xymon server if requested: -if [ "$install_helpers" = "1" ]; then - __package fping --state "$state" - __package heirloom-mailx --state "$state" - __package traceroute --state "$state" - __package ntpdate --state "$state" -fi - -## CLI-usage often requires a shell: -require="__package/xymon" __user xymon --shell "/bin/bash" --state "$state" diff --git a/cdist/conf/type/__xymon_server/parameter/boolean b/cdist/conf/type/__xymon_server/parameter/boolean deleted file mode 100644 index 56ebcb2c..00000000 --- a/cdist/conf/type/__xymon_server/parameter/boolean +++ /dev/null @@ -1 +0,0 @@ -install_helpers diff --git a/cdist/conf/type/__xymon_server/parameter/default/state b/cdist/conf/type/__xymon_server/parameter/default/state deleted file mode 100644 index e7f6134f..00000000 --- a/cdist/conf/type/__xymon_server/parameter/default/state +++ /dev/null @@ -1 +0,0 @@ -present diff --git a/cdist/conf/type/__xymon_server/parameter/optional b/cdist/conf/type/__xymon_server/parameter/optional deleted file mode 100644 index ff72b5c7..00000000 --- a/cdist/conf/type/__xymon_server/parameter/optional +++ /dev/null @@ -1 +0,0 @@ -state diff --git a/cdist/conf/type/__xymon_server/singleton b/cdist/conf/type/__xymon_server/singleton deleted file mode 100644 index e69de29b..00000000 diff --git a/cdist/config.py b/cdist/config.py index 26d07fc4..98bfbe55 100644 --- a/cdist/config.py +++ b/cdist/config.py @@ -90,13 +90,15 @@ class Config(object): shutil.rmtree(path) def __init__(self, local, remote, dry_run=False, jobs=None, - cleanup_cmds=None, remove_remote_files_dirs=False): + cleanup_cmds=None, remove_remote_files_dirs=False, + timestamp=False): self.local = local self.remote = remote self._open_logger() self.dry_run = dry_run self.jobs = jobs + self.timestamp = timestamp if cleanup_cmds: self.cleanup_cmds = cleanup_cmds else: @@ -104,12 +106,9 @@ class Config(object): self.remove_remote_files_dirs = remove_remote_files_dirs self.explorer = core.Explorer(self.local.target_host, self.local, - self.remote, jobs=self.jobs, - dry_run=self.dry_run) - self.manifest = core.Manifest(self.local.target_host, self.local, - dry_run=self.dry_run) - self.code = core.Code(self.local.target_host, self.local, self.remote, - dry_run=self.dry_run) + self.remote, jobs=self.jobs) + self.manifest = core.Manifest(self.local.target_host, self.local) + self.code = core.Code(self.local.target_host, self.local, self.remote) def _init_files_dirs(self): """Prepare files and directories for the run""" @@ -427,7 +426,8 @@ class Config(object): cleanup_cmds.append(cleanup_cmd) c = cls(local, remote, dry_run=args.dry_run, jobs=args.jobs, cleanup_cmds=cleanup_cmds, - remove_remote_files_dirs=remove_remote_files_dirs) + remove_remote_files_dirs=remove_remote_files_dirs, + timestamp=args.timestamp) c.run() cls._remove_paths() @@ -758,39 +758,50 @@ class Config(object): ("The requirements of the following objects could not be " "resolved:\n%s") % ("\n".join(info_string))) - def _handle_deprecation(self, cdist_object): - cdist_type = cdist_object.cdist_type - deprecated = cdist_type.deprecated - if deprecated is not None: - if deprecated: - self.log.warning("Type %s is deprecated: %s", cdist_type.name, - deprecated) + def _timeit(self, func, msg_prefix): + def wrapper_func(*args, **kwargs): + loglevel = self.log.getEffectiveLevel() + if loglevel >= logging.VERBOSE and self.timestamp: + start_time = time.time() + rv = func(*args, **kwargs) + end_time = time.time() + duration = end_time - start_time + self.log.verbose("%s duration: %.6f seconds", + msg_prefix, duration) 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) + rv = func(*args, **kwargs) + return rv + return wrapper_func def object_prepare(self, cdist_object, transfer_type_explorers=True): """Prepare object: Run type explorer + manifest""" - self._handle_deprecation(cdist_object) self.log.verbose("Preparing object {}".format(cdist_object.name)) self.log.verbose( "Running manifest and explorers for " + cdist_object.name) self.explorer.run_type_explorers(cdist_object, transfer_type_explorers) try: - self.manifest.run_type_manifest(cdist_object) + self.log.verbose("Preparing object {}".format(cdist_object.name)) + self.log.verbose( + "Running manifest and explorers for " + cdist_object.name) + self.explorer.run_type_explorers(cdist_object, + transfer_type_explorers) + if self.is_py_type(cdist_object): + self._timeit(self.manifest.run_py_type_manifest, + "Python type manifest for {}".format( + cdist_object.name))(cdist_object) + else: + self._timeit(self.manifest.run_type_manifest, + "Type manifest for {}".format( + cdist_object.name))(cdist_object) cdist_object.state = core.CdistObject.STATE_PREPARED except cdist.Error as e: raise cdist.CdistObjectError(cdist_object, e) + def is_py_type(self, cdist_object): + cdist_type = cdist_object.cdist_type + init_path = os.path.join(cdist_type.absolute_path, '__init__.py') + return os.path.exists(init_path) + def object_run(self, cdist_object): """Run gencode and code for an object""" try: @@ -801,9 +812,20 @@ class Config(object): # Generate self.log.debug("Generating code for %s" % (cdist_object.name)) - cdist_object.code_local = self.code.run_gencode_local(cdist_object) - cdist_object.code_remote = self.code.run_gencode_remote( - cdist_object) + if self.is_py_type(cdist_object): + cdist_object.code_local = '' + cdist_object.code_remote = self._timeit(self.code.run_py, + "Python type generate code for {}".format( + cdist_object.name))(cdist_object) + else: + cdist_object.code_local = self._timeit( + self.code.run_gencode_local, + "Type generate code local for {}".format( + cdist_object.name))(cdist_object) + cdist_object.code_remote = self._timeit( + self.code.run_gencode_remote, + "Type generate code remote for {}".format( + cdist_object.name))(cdist_object) if cdist_object.code_local or cdist_object.code_remote: cdist_object.changed = True @@ -814,12 +836,16 @@ class Config(object): if cdist_object.code_local: self.log.trace("Executing local code for %s" % (cdist_object.name)) - self.code.run_code_local(cdist_object) + self._timeit(self.code.run_code_local, + "Type run code local for {}".format( + cdist_object.name))(cdist_object) if cdist_object.code_remote: self.log.trace("Executing remote code for %s" % (cdist_object.name)) self.code.transfer_code_remote(cdist_object) - self.code.run_code_remote(cdist_object) + self._timeit(self.code.run_code_remote, + "Type run code remote for {}".format( + cdist_object.name))(cdist_object) # Mark this object as done self.log.trace("Finishing run of " + cdist_object.name) diff --git a/cdist/core/__init__.py b/cdist/core/__init__.py index b79cdb21..f44b7167 100644 --- a/cdist/core/__init__.py +++ b/cdist/core/__init__.py @@ -21,6 +21,7 @@ # from cdist.core.cdist_type import CdistType +from cdist.core.python_type import PythonType, ManifestEntry from cdist.core.cdist_type import InvalidTypeError from cdist.core.cdist_object import CdistObject from cdist.core.cdist_object import IllegalObjectIdError diff --git a/cdist/core/cdist_type.py b/cdist/core/cdist_type.py index 4500f50d..99e40e70 100644 --- a/cdist/core/cdist_type.py +++ b/cdist/core/cdist_type.py @@ -69,7 +69,6 @@ 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) @@ -134,17 +133,6 @@ class CdistType(object): cannot run in parallel.""" return os.path.isfile(os.path.join(self.absolute_path, "nonparallel")) - @property - def deprecated(self): - """Get type deprecation message. If message is None then type - is not deprecated.""" - deprecated_path = os.path.join(self.absolute_path, "deprecated") - try: - with open(deprecated_path, 'r') as f: - return f.read() - except FileNotFoundError: - return None - @property def explorers(self): """Return a list of available explorers""" @@ -276,23 +264,3 @@ 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/core/code.py b/cdist/core/code.py index 1550880a..11568b04 100644 --- a/cdist/core/code.py +++ b/cdist/core/code.py @@ -22,6 +22,10 @@ # import os +import importlib.util +import inspect +import cdist +from cdist.core import PythonType from . import util @@ -97,7 +101,7 @@ class Code(object): """ # target_host is tuple (target_host, target_hostname, target_fqdn) - def __init__(self, target_host, local, remote, dry_run=False): + def __init__(self, target_host, local, remote): self.target_host = target_host self.local = local self.remote = remote @@ -113,8 +117,43 @@ class Code(object): local.log), } - if dry_run: - self.env['__cdist_dry_run'] = '1' + def run_py(self, cdist_object): + cdist_type = cdist_object.cdist_type + module_name = cdist_type.name + file_path = os.path.join(cdist_type.absolute_path, '__init__.py') + + if os.path.isfile(file_path): + spec = importlib.util.spec_from_file_location(module_name, + file_path) + m = importlib.util.module_from_spec(spec) + spec.loader.exec_module(m) + classes = inspect.getmembers(m, inspect.isclass) + type_class = None + for _, cl in classes: + if cl != PythonType and issubclass(cl, PythonType): + if type_class: + raise cdist.Error("Only one python type class is " + "supported, but at least two " + "found: {}".format((type_class, + cl, ))) + else: + type_class = cl + env = os.environ.copy() + env.update(self.env) + message_prefix = cdist_object.name + type_obj = type_class(env=env, cdist_object=cdist_object, + local=self.local, remote=self.remote, + message_prefix=message_prefix) + if hasattr(type_obj, 'run') and inspect.ismethod(type_obj.run): + if self.local.save_output_streams: + which = 'gencode-py' + stderr_path = os.path.join(cdist_object.stderr_path, which) + stdout_path = os.path.join(cdist_object.stdout_path, which) + with open(stderr_path, 'a+') as stderr, \ + open(stdout_path, 'a+') as stdout: + return type_obj.run(stdout=stdout, stderr=stderr) + else: + return type_obj.run() def _run_gencode(self, cdist_object, which): cdist_type = cdist_object.cdist_type diff --git a/cdist/core/explorer.py b/cdist/core/explorer.py index 353d7681..acceacac 100644 --- a/cdist/core/explorer.py +++ b/cdist/core/explorer.py @@ -67,7 +67,7 @@ class Explorer(object): """Executes cdist explorers. """ - def __init__(self, target_host, local, remote, jobs=None, dry_run=False): + def __init__(self, target_host, local, remote, jobs=None): self.target_host = target_host self._open_logger() @@ -84,10 +84,6 @@ class Explorer(object): '__cdist_log_level_name': util.log_level_name_env_var_val( self.log), } - - if dry_run: - self.env['__cdist_dry_run'] = '1' - self._type_explorers_transferred = [] self.jobs = jobs diff --git a/cdist/core/manifest.py b/cdist/core/manifest.py index 07af0ef8..ec78d5b9 100644 --- a/cdist/core/manifest.py +++ b/cdist/core/manifest.py @@ -22,9 +22,13 @@ import logging import os - +import importlib.util +import inspect import cdist +import cdist.emulator from . import util +from cdist.core import PythonType, ManifestEntry + ''' common: @@ -96,7 +100,7 @@ class Manifest(object): """Executes cdist manifests. """ - def __init__(self, target_host, local, dry_run=False): + def __init__(self, target_host, local): self.target_host = target_host self.local = local @@ -117,9 +121,6 @@ class Manifest(object): self.log), } - if dry_run: - self.env['__cdist_dry_run'] = '1' - def _open_logger(self): self.log = logging.getLogger(self.target_host[0]) @@ -212,3 +213,73 @@ class Manifest(object): type_manifest, env=self.env_type_manifest(cdist_object), message_prefix=message_prefix) + + def env_py_type_manifest(self, cdist_object): + env = os.environ.copy() + env.update(self.env) + env.update({ + '__cdist_object_marker': self.local.object_marker_name, + '__cdist_manifest': cdist_object.cdist_type, + '__manifest': self.local.manifest_path, + '__object': cdist_object.absolute_path, + '__object_id': cdist_object.object_id, + '__object_name': cdist_object.name, + '__type': cdist_object.cdist_type.absolute_path, + }) + + return env + + def run_py_type_manifest(self, cdist_object): + cdist_type = cdist_object.cdist_type + module_name = cdist_type.name + file_path = os.path.join(cdist_type.absolute_path, '__init__.py') + message_prefix = cdist_object.name + if os.path.isfile(file_path): + self.log.verbose("Running python type manifest for object %s", + cdist_object.name) + spec = importlib.util.spec_from_file_location(module_name, + file_path) + m = importlib.util.module_from_spec(spec) + spec.loader.exec_module(m) + classes = inspect.getmembers(m, inspect.isclass) + type_class = None + for _, cl in classes: + if cl != PythonType and issubclass(cl, PythonType): + if type_class: + raise cdist.Error("Only one python type class is " + "supported, but at least two " + "found: {}".format((type_class, + cl, ))) + else: + type_class = cl + env = self.env_py_type_manifest(cdist_object) + type_obj = type_class(env=env, cdist_object=cdist_object, + local=self.local, remote=None, + message_prefix=message_prefix) + if self.local.save_output_streams: + which = 'manifest' + stderr_path = os.path.join(cdist_object.stderr_path, which) + stdout_path = os.path.join(cdist_object.stdout_path, which) + with open(stderr_path, 'a+') as stderr, \ + open(stdout_path, 'a+') as stdout: + self._process_py_type_manifest_entries( + type_obj, env, stdout=stdout, stderr=stderr) + else: + self._process_py_type_manifest_entries(type_obj, env) + + def _process_py_type_manifest_entries(self, type_obj, env, stdout=None, + stderr=None): + if hasattr(type_obj, 'manifest') and \ + inspect.ismethod(type_obj.manifest): + for entry in type_obj.manifest(stdout=stdout, stderr=stderr): + if not isinstance(entry, ManifestEntry): + raise TypeError("Manifest entry must be of " + "type ManifestEntry") + kwargs = { + 'argv': entry.cmd_line(), + 'env': env, + } + if entry.stdin: + kwargs['stdin'] = entry.stdin + emulator = cdist.emulator.Emulator(**kwargs) + emulator.run() diff --git a/cdist/core/python_type.py b/cdist/core/python_type.py new file mode 100644 index 00000000..85d4ad2e --- /dev/null +++ b/cdist/core/python_type.py @@ -0,0 +1,160 @@ +import logging +import os +import io +import sys +import re +from cdist import message, Error + + +class PythonType: + def __init__(self, env, cdist_object, local, remote, message_prefix=None): + self.env = env + self.cdist_object = cdist_object + self.object_id = cdist_object.object_id + self.object_name = cdist_object.name + self.cdist_type = cdist_object.cdist_type + self.local = local + self.remote = remote + self.object_path = cdist_object.absolute_path + self.type_path = cdist_object.cdist_type.absolute_path + self.explorer_path = os.path.join(self.object_path, 'explorer') + self.parameters = cdist_object.parameters + self.stdin_path = os.path.join(self.object_path, 'stdin') + self.log = logging.getLogger( + self.local.target_host[0] + ':' + self.object_name) + + self.message_prefix = message_prefix + self.message = None + + def get_parameter(self, name): + return self.parameters.get(name) + + def get_explorer_file(self, name): + path = os.path.join(self.explorer_path, name) + return path + + def get_explorer(self, name): + path = self.get_explorer_file(name) + with open(path, 'r') as f: + value = f.read() + if value: + value = value.strip() + return value + + def run_local(self, command, env=None): + rv = self.local.run(command, env=env, return_output=True) + if rv: + rv = rv.rstrip('\n') + return rv + + def run_remote(self, command, env=None): + rv = self.remote.run(command, env=env, return_output=True) + if rv: + rv = rv.rstrip('\n') + return rv + + def transfer(self, source, destination): + self.remote.transfer(source, destination) + + def die(self, msg): + raise Error("{}: {}".format(self.cdist_object, msg)) + + def type_manifest(self): + pass + + def type_gencode(self): + pass + + def manifest(self, stdout=None, stderr=None): + try: + if self.message_prefix: + self.message = message.Message(self.message_prefix, + self.local.messages_path) + self.env.update(self.message.env) + if stdout is not None: + stdout_save = sys.stdout + sys.stdout = stdout + if stderr is not None: + stderr_save = sys.stderr + sys.stderr = stderr + yield from self.type_manifest() + finally: + if self.message: + self.message.merge_messages() + if stdout is not None: + sys.stdout = stdout_save + if stderr is not None: + sys.stderr = stderr_save + + def run(self, stdout=None, stderr=None): + try: + if self.message_prefix: + self.message = message.Message(self.message_prefix, + self.local.messages_path) + if stdout is not None: + stdout_save = sys.stdout + sys.stdout = stdout + if stderr is not None: + stderr_save = sys.stderr + sys.stderr = stderr + return self.type_gencode() + finally: + if self.message: + self.message.merge_messages() + if stdout is not None: + sys.stdout = stdout_save + if stderr is not None: + sys.stderr = stderr_save + + def send_message(self, msg): + if self.message: + with open(self.message.messages_out, 'a') as f: + print(msg, file=f) + + def receive_message(self, pattern): + if self.message: + with open(self.message.messages_in, 'r') as f: + for line in f: + match = re.search(pattern, line) + if match: + return match + return None + + +class ManifestEntry: + def __init__(self, name, stdin=None, parameters=None): + self.name = name + if parameters is None: + self.parameters = {} + else: + self.parameters = parameters + self.set_stdin(stdin) + + def set_stdin(self, value): + # If file-like object then read its value. + if value is not None and isinstance(value, io.IOBase): + value = value.read() + + # Convert to bytes file-like object. + if value is None: + self.stdin = None + elif isinstance(value, str): + self.stdin = io.BytesIO(value.encode('utf-8')) + elif isinstance(value, bytes) or isinstance(value, bytearray): + self.stdin = io.BytesIO(value) + else: + raise TypeError("value must be str, bytes, bytearray, file-like " + "object or None") + + def cmd_line(self): + argv = [self.name, ] + for param in self.parameters: + argv.append(param) + val = self.parameters[param] + if val: + argv.append(val) + return argv + + def __repr__(self): + return ''.format( + self.name, self.parameters, self.stdin) diff --git a/cdist/inventory.py b/cdist/inventory.py index 138a2034..7da306fa 100644 --- a/cdist/inventory.py +++ b/cdist/inventory.py @@ -315,7 +315,7 @@ class InventoryHost(Inventory): hostpath = self._host_path(host) self.log.trace("hostpath: {}".format(hostpath)) if self.action == "add" and not os.path.exists(hostpath): - self._new_hostpath(hostpath) + self._new_hostpath(hostpath) else: if not os.path.isfile(hostpath): raise cdist.Error(("Host path \'{}\' is" diff --git a/cdist/preos/debootstrap/debootstrap.py b/cdist/preos/debootstrap/debootstrap.py index f53dd4a7..90f94111 100644 --- a/cdist/preos/debootstrap/debootstrap.py +++ b/cdist/preos/debootstrap/debootstrap.py @@ -127,6 +127,12 @@ class Debian(object): help="suite used for debootstrap, " "by default '{}'".format(defargs.suite), dest='suite', default=defargs.suite) + parser.add_argument( + '-t', '--trigger-command', + help=("trigger command that will be added to cdist config; " + "'__cdist_preos_trigger http ...' type is appended to " + "initial manifest"), + dest='trigger_command') parser.add_argument( '-y', '--remote-copy', help=("remote copy that cdist config will use, by default " @@ -145,6 +151,7 @@ class Debian(object): log = logging.getLogger(cls.__name__) parser = cls.get_parser() + cdist.argparse.add_beta_command(cls._preos_name) args = parser.parse_args(argv) if args.script and not args.mirror: raise cdist.Error("script option cannot be used without " @@ -172,7 +179,7 @@ class Debian(object): env = vars(args) new_env = {} for key in env: - if key == 'verbose' and env[key]: + if key == 'verbose': if env[key] >= 3: new_env['debug'] = "yes" elif env[key] == 2: diff --git a/cdist/preos/debootstrap/files/code b/cdist/preos/debootstrap/files/code index 9e37003b..50e73972 100755 --- a/cdist/preos/debootstrap/files/code +++ b/cdist/preos/debootstrap/files/code @@ -127,6 +127,13 @@ then exit 1 fi + if [ "${trigger_command}" ] + then + trigger_line="__cdist_preos_trigger http --trigger-command '${trigger_command}'\n" + else + trigger_line="" + fi + if [ "${keyfile_cnt}" -a "${keyfile_cnt}" -gt 0 ] then i="$((keyfile_cnt - 1))" @@ -174,7 +181,7 @@ then fi grub_lines="${grub_manifest_line}${grub_kern_params_line}" - printf "${ssh_auth_keys_line}${grub_lines}" \ + printf "${trigger_line}${ssh_auth_keys_line}${grub_lines}" \ | cat "${manifest}" - |\ cdist config \ ${cdist_params} -i - \ diff --git a/cdist/test/cdist_type/__init__.py b/cdist/test/cdist_type/__init__.py index a51a1e6f..ca961170 100644 --- a/cdist/test/cdist_type/__init__.py +++ b/cdist/test/cdist_type/__init__.py @@ -123,16 +123,6 @@ class TypeTestCase(test.CdistTestCase): cdist_type = core.CdistType(base_path, '__not_nonparallel') self.assertFalse(cdist_type.is_nonparallel) - def test_deprecated(self): - base_path = fixtures - cdist_type = core.CdistType(base_path, '__deprecated') - self.assertIsNotNone(cdist_type.deprecated) - - def test_not_deprecated(self): - base_path = fixtures - cdist_type = core.CdistType(base_path, '__not_deprecated') - self.assertIsNone(cdist_type.deprecated) - def test_install_is_install(self): base_path = fixtures cdist_type = core.CdistType(base_path, '__install') @@ -200,18 +190,3 @@ 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/__deprecated/deprecated b/cdist/test/cdist_type/fixtures/__deprecated/deprecated deleted file mode 100644 index e69de29b..00000000 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 deleted file mode 100644 index 69d9f456..00000000 --- a/cdist/test/cdist_type/fixtures/__with_deprecated_parameters/parameter/deprecated/eggs +++ /dev/null @@ -1 +0,0 @@ -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 deleted file mode 100644 index e69de29b..00000000 diff --git a/cdist/test/cdist_type/fixtures/__with_deprecated_parameters/parameter/optional b/cdist/test/cdist_type/fixtures/__with_deprecated_parameters/parameter/optional deleted file mode 100644 index bfe09199..00000000 --- a/cdist/test/cdist_type/fixtures/__with_deprecated_parameters/parameter/optional +++ /dev/null @@ -1,3 +0,0 @@ -spam -eggs -sausage diff --git a/cdist/trigger.py b/cdist/trigger.py new file mode 100644 index 00000000..58f98dca --- /dev/null +++ b/cdist/trigger.py @@ -0,0 +1,229 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +# +# 2016 Nico Schottelius (nico-cdist at schottelius.org) +# +# 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 . +# +# + +import ipaddress +import logging +import re +import socket +import http.server +import os +import socketserver +import shutil + +import cdist.config +import cdist.log +import cdist.util.ipaddr as ipaddr + + +class Trigger(): + """cdist trigger handling""" + + # Arguments that are only trigger specific + triggers_args = ["http_port", "ipv6", "directory", "source", ] + + def __init__(self, http_port=None, dry_run=False, ipv6=False, + directory=None, source=None, cdistargs=None): + self.dry_run = dry_run + self.http_port = int(http_port) + self.ipv6 = ipv6 + self.args = cdistargs + + self.directory = directory + self.source = source + + log.debug("IPv6: %s", self.ipv6) + + def run_httpd(self): + server_address = ('', self.http_port) + + if self.ipv6: + httpdcls = HTTPServerV6 + else: + httpdcls = HTTPServerV4 + httpd = httpdcls(self.args, self.directory, self.source, + server_address, TriggerHttp) + + log.debug("Starting server at port %d", self.http_port) + if self.dry_run: + log.debug("Running in dry run mode") + httpd.serve_forever() + + def run(self): + if self.http_port: + self.run_httpd() + + @classmethod + def commandline(cls, args): + global log + + # remove root logger default cdist handler and configure trigger's own + logging.getLogger().handlers = [] + logging.basicConfig(format='%(asctime)s %(levelname)s: %(message)s') + + log = logging.getLogger("trigger") + ownargs = {} + for targ in cls.triggers_args: + arg = getattr(args, targ) + ownargs[targ] = arg + + del arg + + t = cls(dry_run=args.dry_run, cdistargs=args, **ownargs) + t.run() + + +class TriggerHttp(http.server.BaseHTTPRequestHandler): + actions = { + "cdist": ["config", "install", ], + "file": ["present", "absent", ], + } + + def do_HEAD(self): + self.dispatch_request() + + def do_POST(self): + self.dispatch_request() + + def do_GET(self): + self.dispatch_request() + + def _actions_regex(self): + regex = ["^/(?P", ] + regex.extend("|".join(self.actions.keys())) + regex.append(")/(?P") + regex.extend("|".join("|".join(self.actions[x]) for x in self.actions)) + regex.append(")/") + + return "".join(regex) + + def dispatch_request(self): + host = self.client_address[0] + code = 200 + message = None + + self.cdistargs = self.server.cdistargs + + actions_regex = self._actions_regex() + m = re.match(actions_regex, self.path) + + if m: + subsystem = m.group('subsystem') + action = m.group('action') + handler = getattr(self, "handler_" + subsystem) + + if action not in self.actions[subsystem]: + code = 404 + else: + code = 404 + + if code == 200: + log.debug("Calling {} -> {}".format(subsystem, action)) + try: + handler(action, host) + except cdist.Error as e: + # cdist is not broken, cdist run is broken + code = 599 # use arbitrary unassigned error code + message = str(e) + except Exception as e: + # cdist/trigger server is broken + log.exception(e) + code = 500 + + self.send_response(code=code, message=message) + self.end_headers() + + def handler_file(self, action, host): + if not self.server.directory or not self.server.source: + log.info("Cannot serve file request: directory or source " + "not setup") + return + + try: + ipaddress.ip_address(host) + except ValueError: + log.error("Host is not a valid IP address - aborting") + return + + dst = os.path.join(self.server.directory, host) + + if action == "present": + shutil.copyfile(self.server.source, dst) + if action == "absent": + if os.path.exists(dst): + os.remove(dst) + + def handler_cdist(self, action, host): + log.debug("Running cdist action %s for %s", action, host) + + if self.server.dry_run: + log.info("Dry run, skipping cdist execution") + return + + cname = action.title() + module = getattr(cdist, action) + theclass = getattr(module, cname) + + if hasattr(self.cdistargs, 'out_path'): + out_path = self.cdistargs.out_path + else: + out_path = None + host_base_path, hostdir = theclass.create_host_base_dirs( + host, theclass.create_base_root_path(out_path)) + theclass.construct_remote_exec_copy_patterns(self.cdistargs) + host_tags = None + host_name = ipaddr.resolve_target_host_name(host) + log.debug('Resolved target host name: %s', host_name) + if host_name: + target_host = host_name + else: + target_host = host + log.debug('Using target_host: %s', target_host) + log.debug("Executing cdist onehost with params: %s, %s, %s, %s, %s, ", + target_host, host_tags, host_base_path, hostdir, + self.cdistargs) + cfg = cdist.configuration.Configuration(self.cdistargs) + configuration = cfg.get_config(section='GLOBAL') + theclass.onehost(target_host, host_tags, host_base_path, hostdir, + self.cdistargs, parallel=False, + configuration=configuration) + + +class HTTPServerV6(socketserver.ForkingMixIn, http.server.HTTPServer): + """ + Server that listens to both IPv4 and IPv6 requests. + """ + address_family = socket.AF_INET6 + + def __init__(self, cdistargs, directory, source, *args, **kwargs): + self.cdistargs = cdistargs + self.dry_run = cdistargs.dry_run + self.directory = directory + self.source = source + + http.server.HTTPServer.__init__(self, *args, **kwargs) + + +class HTTPServerV4(HTTPServerV6): + """ + Server that listens to IPv4 requests. + """ + address_family = socket.AF_INET diff --git a/completions/bash/cdist-completion.bash b/completions/bash/cdist-completion.bash index cdac7f29..ed5c6a55 100644 --- a/completions/bash/cdist-completion.bash +++ b/completions/bash/cdist-completion.bash @@ -6,7 +6,7 @@ _cdist() prev="${COMP_WORDS[COMP_CWORD-1]}" prevprev="${COMP_WORDS[COMP_CWORD-2]}" opts="-h --help -q --quiet -v --verbose -V --version" - cmds="banner config install inventory preos shell" + cmds="banner config install inventory preos shell trigger" case "${prevprev}" in shell) @@ -80,6 +80,14 @@ _cdist() COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) ) return 0 ;; + trigger) + opts="-h --help -d --debug -v --verbose -b --beta \ + -C --cache-path-pattern -c --conf-dir -i --initial-manifest \ + -j --jobs -n --dry-run -o --out-dir --remote-copy \ + --remote-exec -6 --ipv6 -H --http-port -D --directory -S --source" + COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) ) + return 0 + ;; inventory) cmds="list add-host del-host add-tag del-tag" opts="-h --help -q --quiet -v --verbose" diff --git a/completions/zsh/_cdist b/completions/zsh/_cdist index 1bd275ef..5d653095 100644 --- a/completions/zsh/_cdist +++ b/completions/zsh/_cdist @@ -11,7 +11,7 @@ _cdist() case $state in opts_cmds) - _arguments '1:Options and commands:(banner config install inventory preos shell -h --help -q --quiet -v --verbose -V --version)' + _arguments '1:Options and commands:(banner config install inventory preos shell trigger -h --help -q --quiet -v --verbose -V --version)' ;; *) case $words[2] in diff --git a/docs/changelog b/docs/changelog index 71509004..ea0e58a1 100644 --- a/docs/changelog +++ b/docs/changelog @@ -2,77 +2,8 @@ Changelog --------- next: - * Type __xymon_config: Add parameters for ownership and generic rsync options (Thomas Eckert) - * Type __xymon_client: Add msgcache parameter to support passive clients (Thomas Eckert) - * Type __apt_key: Use mktemp for unique temporary gpg home (Ander Punnar) - -6.1.0: 2019-11-19 - * Explorer hostname, type __hostname: Support more operating systems, rewrite type and hostname explorer (Dennis Camera) - -6.0.4: 2019-11-19 - * Doc: Fix typos (Kirill Miazine) - -6.0.3: 2019-10-31 - * Type __letsencrypt_cert: Add Alpine support (Nico Schottelius) - * Type __xymon_client: Fix spelling error in manpage (Dmitry Bogatov) - * Build: Support pip from git (Darko Poljak, Ľubomír Kučera) - * Type __package_update_index: Add Alpine support (Ahmed Bilal Khalid) - -6.0.2: 2019-10-17 - * New types: __xymon_server, __xymon_apache, __xymon_config, __xymon_client (Thomas Eckert) - * Type __letsencrypt_cert: Add Arch Linux support (Nico Schottelius) - * New type: __sensible_editor (Dennis Camera) - * Types __grafana_dashboard, __prometheus_alertmanager, __prometheus_exporter, __prometheus_server: Support Debian 10 (Ahmed Bilal Khalid) - -6.0.1: 2019-10-08 - * Type __group: Support OSes without getent (Dennis Camera) - * Type __user: Support OSes without getent (Dennis Camera) - * Type __ssh_authorized_keys: Support OSes without getent (Dennis Camera) - * Type __ssh_dot_ssh: Support OSes without getent (Dennis Camera) - * Explorer interfaces: Always sort output (Dennis Camera) - * Explorer os: Unquote value from os-release file (Dennis Camera) - * Type __letsencrypt_cert: Support Debian 10* (Ahmed Bilal Khalid) - * Type __prometheus_server: Add missing exit after unsupported error message (Dominique Roux) - * Type __git: Use --recurse-submodules instead of --recursive (Jonas Hagen) - * Type __git: Add --shallow option (Jonas Hagen) - -6.0.0: 2019-10-01 - * Type __letsencrypt_cert: Fix beowulf's spelling (Mondi Ravi) * Core: Add preos functionality (Darko Poljak) - * Type __sysctl: Add alpine support (Nico Schottelius) - * Type __git: Add recursive option (Dennis Camera) - * Type __apt_key: Fix key dearmor (Ander Punnar) - -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) - * New helper script: cdist-new-type (Steven Armstrong, Darko Poljak) - * Core: Add support for deprecated type marker (Darko Poljak) - -5.0.2: 2019-05-17 - * Type __package_apk: Fix @repo handling in explorer (Nico Schottelius) - * Type __postfix: Add alpine support (Nico Schottelius) - * Type __postfix_postconf: Add alpine support (Nico Schottelius) - * Type __user: Add alpine support (Nico Schottelius) - * Core: Set __cdist_dry_run env var (Ander Punnar) + * Core: Add trigger functionality (Nico Schottelius, Darko Poljak) 5.0.1: 2019-05-09 * Documentation: Add 'Perils of CDIST_ORDER_DEPENDENCY' sub-section (Darko Poljak) diff --git a/docs/dev/python-types/benchmark b/docs/dev/python-types/benchmark new file mode 100644 index 00000000..8fcf69f3 --- /dev/null +++ b/docs/dev/python-types/benchmark @@ -0,0 +1,376 @@ +# sh type, no file at remote +echo 'x=0; while [ $x -lt 50 ]; do head -c 102400 /dev/random | __file /root/foo${x}.bin --source - --mode 0640 --owner root --group root; x=$((x + 1)); done' | ./bin/cdist config -v -P -i - 185.203.112.26 + +INFO: [20181121125154.045799] 185.203.112.26: Starting configuration run +INFO: [20181121125237.029892] 185.203.112.26: Processing __file/root/foo0.bin +INFO: [20181121125239.881529] 185.203.112.26: Processing __file/root/foo1.bin +INFO: [20181121125243.265672] 185.203.112.26: Processing __file/root/foo2.bin +INFO: [20181121125246.929903] 185.203.112.26: Processing __file/root/foo3.bin +INFO: [20181121125251.811258] 185.203.112.26: Processing __file/root/foo4.bin +INFO: [20181121125257.784416] 185.203.112.26: Processing __file/root/foo5.bin +INFO: [20181121125302.686275] 185.203.112.26: Processing __file/root/foo6.bin +INFO: [20181121125306.394030] 185.203.112.26: Processing __file/root/foo7.bin +INFO: [20181121125308.610023] 185.203.112.26: Processing __file/root/foo8.bin +INFO: [20181121125310.868538] 185.203.112.26: Processing __file/root/foo9.bin +INFO: [20181121125313.017972] 185.203.112.26: Processing __file/root/foo10.bin +INFO: [20181121125315.201342] 185.203.112.26: Processing __file/root/foo11.bin +INFO: [20181121125317.333055] 185.203.112.26: Processing __file/root/foo12.bin +INFO: [20181121125319.463929] 185.203.112.26: Processing __file/root/foo13.bin +INFO: [20181121125321.595410] 185.203.112.26: Processing __file/root/foo14.bin +INFO: [20181121125323.689697] 185.203.112.26: Processing __file/root/foo15.bin +INFO: [20181121125325.768283] 185.203.112.26: Processing __file/root/foo16.bin +INFO: [20181121125327.814793] 185.203.112.26: Processing __file/root/foo17.bin +INFO: [20181121125329.873073] 185.203.112.26: Processing __file/root/foo18.bin +INFO: [20181121125331.953886] 185.203.112.26: Processing __file/root/foo19.bin +INFO: [20181121125334.118290] 185.203.112.26: Processing __file/root/foo20.bin +INFO: [20181121125336.390849] 185.203.112.26: Processing __file/root/foo21.bin +INFO: [20181121125338.576698] 185.203.112.26: Processing __file/root/foo22.bin +INFO: [20181121125340.819044] 185.203.112.26: Processing __file/root/foo23.bin +INFO: [20181121125343.680419] 185.203.112.26: Processing __file/root/foo24.bin +INFO: [20181121125346.044907] 185.203.112.26: Processing __file/root/foo25.bin +INFO: [20181121125348.179574] 185.203.112.26: Processing __file/root/foo26.bin +INFO: [20181121125350.314970] 185.203.112.26: Processing __file/root/foo27.bin +INFO: [20181121125352.447394] 185.203.112.26: Processing __file/root/foo28.bin +INFO: [20181121125354.586637] 185.203.112.26: Processing __file/root/foo29.bin +INFO: [20181121125356.722699] 185.203.112.26: Processing __file/root/foo30.bin +INFO: [20181121125358.883538] 185.203.112.26: Processing __file/root/foo31.bin +INFO: [20181121125401.020967] 185.203.112.26: Processing __file/root/foo32.bin +INFO: [20181121125403.160146] 185.203.112.26: Processing __file/root/foo33.bin +INFO: [20181121125405.289048] 185.203.112.26: Processing __file/root/foo34.bin +INFO: [20181121125407.423994] 185.203.112.26: Processing __file/root/foo35.bin +INFO: [20181121125409.530135] 185.203.112.26: Processing __file/root/foo36.bin +INFO: [20181121125411.659683] 185.203.112.26: Processing __file/root/foo37.bin +INFO: [20181121125413.786177] 185.203.112.26: Processing __file/root/foo38.bin +INFO: [20181121125415.919152] 185.203.112.26: Processing __file/root/foo39.bin +INFO: [20181121125418.051496] 185.203.112.26: Processing __file/root/foo40.bin +INFO: [20181121125420.204577] 185.203.112.26: Processing __file/root/foo41.bin +INFO: [20181121125422.339697] 185.203.112.26: Processing __file/root/foo42.bin +INFO: [20181121125424.450966] 185.203.112.26: Processing __file/root/foo43.bin +INFO: [20181121125426.487831] 185.203.112.26: Processing __file/root/foo44.bin +INFO: [20181121125428.585516] 185.203.112.26: Processing __file/root/foo45.bin +INFO: [20181121125430.749002] 185.203.112.26: Processing __file/root/foo46.bin +INFO: [20181121125432.865290] 185.203.112.26: Processing __file/root/foo47.bin +INFO: [20181121125435.004009] 185.203.112.26: Processing __file/root/foo48.bin +INFO: [20181121125437.228566] 185.203.112.26: Processing __file/root/foo49.bin +INFO: [20181121125439.429440] 185.203.112.26: Finished successful run in 165.38 seconds + +# sh type, files exist at remote but content changes +echo 'x=0; while [ $x -lt 50 ]; do head -c 102400 /dev/random | __file /root/foo${x}.bin --source - --mode 0640 --owner root --group root; x=$((x + 1)); done' | ./bin/cdist config -v -P -i - 185.203.112.26 + +INFO: [20181121125529.952800] 185.203.112.26: Starting configuration run +INFO: [20181121125541.175180] 185.203.112.26: Processing __file/root/foo0.bin +INFO: [20181121125543.219561] 185.203.112.26: Processing __file/root/foo1.bin +INFO: [20181121125545.116073] 185.203.112.26: Processing __file/root/foo2.bin +INFO: [20181121125547.011359] 185.203.112.26: Processing __file/root/foo3.bin +INFO: [20181121125548.916288] 185.203.112.26: Processing __file/root/foo4.bin +INFO: [20181121125550.821351] 185.203.112.26: Processing __file/root/foo5.bin +INFO: [20181121125552.723887] 185.203.112.26: Processing __file/root/foo6.bin +INFO: [20181121125554.635662] 185.203.112.26: Processing __file/root/foo7.bin +INFO: [20181121125556.568639] 185.203.112.26: Processing __file/root/foo8.bin +INFO: [20181121125558.508852] 185.203.112.26: Processing __file/root/foo9.bin +INFO: [20181121125600.464475] 185.203.112.26: Processing __file/root/foo10.bin +INFO: [20181121125602.429261] 185.203.112.26: Processing __file/root/foo11.bin +INFO: [20181121125604.428942] 185.203.112.26: Processing __file/root/foo12.bin +INFO: [20181121125606.442193] 185.203.112.26: Processing __file/root/foo13.bin +INFO: [20181121125608.474473] 185.203.112.26: Processing __file/root/foo14.bin +INFO: [20181121125610.535252] 185.203.112.26: Processing __file/root/foo15.bin +INFO: [20181121125612.609560] 185.203.112.26: Processing __file/root/foo16.bin +INFO: [20181121125614.708507] 185.203.112.26: Processing __file/root/foo17.bin +INFO: [20181121125616.824721] 185.203.112.26: Processing __file/root/foo18.bin +INFO: [20181121125618.924521] 185.203.112.26: Processing __file/root/foo19.bin +INFO: [20181121125621.007543] 185.203.112.26: Processing __file/root/foo20.bin +INFO: [20181121125623.133204] 185.203.112.26: Processing __file/root/foo21.bin +INFO: [20181121125625.333471] 185.203.112.26: Processing __file/root/foo22.bin +INFO: [20181121125627.396334] 185.203.112.26: Processing __file/root/foo23.bin +INFO: [20181121125629.526492] 185.203.112.26: Processing __file/root/foo24.bin +INFO: [20181121125631.628454] 185.203.112.26: Processing __file/root/foo25.bin +INFO: [20181121125633.743142] 185.203.112.26: Processing __file/root/foo26.bin +INFO: [20181121125635.952547] 185.203.112.26: Processing __file/root/foo27.bin +INFO: [20181121125637.986746] 185.203.112.26: Processing __file/root/foo28.bin +INFO: [20181121125640.020415] 185.203.112.26: Processing __file/root/foo29.bin +INFO: [20181121125642.081373] 185.203.112.26: Processing __file/root/foo30.bin +INFO: [20181121125644.174744] 185.203.112.26: Processing __file/root/foo31.bin +INFO: [20181121125646.286532] 185.203.112.26: Processing __file/root/foo32.bin +INFO: [20181121125648.396447] 185.203.112.26: Processing __file/root/foo33.bin +INFO: [20181121125650.460107] 185.203.112.26: Processing __file/root/foo34.bin +INFO: [20181121125652.557125] 185.203.112.26: Processing __file/root/foo35.bin +INFO: [20181121125654.667456] 185.203.112.26: Processing __file/root/foo36.bin +INFO: [20181121125656.746960] 185.203.112.26: Processing __file/root/foo37.bin +INFO: [20181121125658.854229] 185.203.112.26: Processing __file/root/foo38.bin +INFO: [20181121125700.968145] 185.203.112.26: Processing __file/root/foo39.bin +INFO: [20181121125703.109376] 185.203.112.26: Processing __file/root/foo40.bin +INFO: [20181121125705.318163] 185.203.112.26: Processing __file/root/foo41.bin +INFO: [20181121125707.440575] 185.203.112.26: Processing __file/root/foo42.bin +INFO: [20181121125709.551261] 185.203.112.26: Processing __file/root/foo43.bin +INFO: [20181121125711.657753] 185.203.112.26: Processing __file/root/foo44.bin +INFO: [20181121125713.774819] 185.203.112.26: Processing __file/root/foo45.bin +INFO: [20181121125715.887428] 185.203.112.26: Processing __file/root/foo46.bin +INFO: [20181121125717.995104] 185.203.112.26: Processing __file/root/foo47.bin +INFO: [20181121125720.110196] 185.203.112.26: Processing __file/root/foo48.bin +INFO: [20181121125722.232932] 185.203.112.26: Processing __file/root/foo49.bin +INFO: [20181121125724.451523] 185.203.112.26: Finished successful run in 114.50 seconds + +# py type, no file at remote +echo 'x=0; while [ $x -lt 50 ]; do head -c 102400 /dev/random | __file_py /root/foo${x}.bin --source - --mode 0640 --owner root --group root; x=$((x + 1)); done' | ./bin/cdist config -v -P -i - 185.203.112.26 + +INFO: [20181121125812.034197] 185.203.112.26: Starting configuration run +INFO: [20181121125823.927353] 185.203.112.26: Processing __file_py/root/foo0.bin +INFO: [20181121125825.715361] 185.203.112.26: Processing __file_py/root/foo1.bin +INFO: [20181121125827.511296] 185.203.112.26: Processing __file_py/root/foo2.bin +INFO: [20181121125829.293455] 185.203.112.26: Processing __file_py/root/foo3.bin +INFO: [20181121125831.086696] 185.203.112.26: Processing __file_py/root/foo4.bin +INFO: [20181121125832.867582] 185.203.112.26: Processing __file_py/root/foo5.bin +INFO: [20181121125834.652511] 185.203.112.26: Processing __file_py/root/foo6.bin +INFO: [20181121125836.450393] 185.203.112.26: Processing __file_py/root/foo7.bin +INFO: [20181121125838.255152] 185.203.112.26: Processing __file_py/root/foo8.bin +INFO: [20181121125840.065808] 185.203.112.26: Processing __file_py/root/foo9.bin +INFO: [20181121125841.889049] 185.203.112.26: Processing __file_py/root/foo10.bin +INFO: [20181121125843.719280] 185.203.112.26: Processing __file_py/root/foo11.bin +INFO: [20181121125845.560165] 185.203.112.26: Processing __file_py/root/foo12.bin +INFO: [20181121125847.416138] 185.203.112.26: Processing __file_py/root/foo13.bin +INFO: [20181121125849.289851] 185.203.112.26: Processing __file_py/root/foo14.bin +INFO: [20181121125851.180203] 185.203.112.26: Processing __file_py/root/foo15.bin +INFO: [20181121125853.074978] 185.203.112.26: Processing __file_py/root/foo16.bin +INFO: [20181121125855.086107] 185.203.112.26: Processing __file_py/root/foo17.bin +INFO: [20181121125857.041100] 185.203.112.26: Processing __file_py/root/foo18.bin +INFO: [20181121125859.025581] 185.203.112.26: Processing __file_py/root/foo19.bin +INFO: [20181121125901.072067] 185.203.112.26: Processing __file_py/root/foo20.bin +INFO: [20181121125903.026711] 185.203.112.26: Processing __file_py/root/foo21.bin +INFO: [20181121125904.994824] 185.203.112.26: Processing __file_py/root/foo22.bin +INFO: [20181121125906.956296] 185.203.112.26: Processing __file_py/root/foo23.bin +INFO: [20181121125908.929231] 185.203.112.26: Processing __file_py/root/foo24.bin +INFO: [20181121125910.882672] 185.203.112.26: Processing __file_py/root/foo25.bin +INFO: [20181121125912.839834] 185.203.112.26: Processing __file_py/root/foo26.bin +INFO: [20181121125914.789904] 185.203.112.26: Processing __file_py/root/foo27.bin +INFO: [20181121125916.743930] 185.203.112.26: Processing __file_py/root/foo28.bin +INFO: [20181121125918.698258] 185.203.112.26: Processing __file_py/root/foo29.bin +INFO: [20181121125920.657118] 185.203.112.26: Processing __file_py/root/foo30.bin +INFO: [20181121125922.618898] 185.203.112.26: Processing __file_py/root/foo31.bin +INFO: [20181121125924.567847] 185.203.112.26: Processing __file_py/root/foo32.bin +INFO: [20181121125926.524617] 185.203.112.26: Processing __file_py/root/foo33.bin +INFO: [20181121125928.396400] 185.203.112.26: Processing __file_py/root/foo34.bin +INFO: [20181121125930.209237] 185.203.112.26: Processing __file_py/root/foo35.bin +INFO: [20181121125931.998377] 185.203.112.26: Processing __file_py/root/foo36.bin +INFO: [20181121125933.786883] 185.203.112.26: Processing __file_py/root/foo37.bin +INFO: [20181121125935.579348] 185.203.112.26: Processing __file_py/root/foo38.bin +INFO: [20181121125937.366197] 185.203.112.26: Processing __file_py/root/foo39.bin +INFO: [20181121125939.155643] 185.203.112.26: Processing __file_py/root/foo40.bin +INFO: [20181121125941.052837] 185.203.112.26: Processing __file_py/root/foo41.bin +INFO: [20181121125942.953670] 185.203.112.26: Processing __file_py/root/foo42.bin +INFO: [20181121125944.781567] 185.203.112.26: Processing __file_py/root/foo43.bin +INFO: [20181121125946.622485] 185.203.112.26: Processing __file_py/root/foo44.bin +INFO: [20181121125948.470701] 185.203.112.26: Processing __file_py/root/foo45.bin +INFO: [20181121125950.356949] 185.203.112.26: Processing __file_py/root/foo46.bin +INFO: [20181121125952.232014] 185.203.112.26: Processing __file_py/root/foo47.bin +INFO: [20181121125954.128887] 185.203.112.26: Processing __file_py/root/foo48.bin +INFO: [20181121125956.037541] 185.203.112.26: Processing __file_py/root/foo49.bin +INFO: [20181121125957.514738] 185.203.112.26: Finished successful run in 105.48 seconds + +# py type, files exist at remote but content changes +echo 'x=0; while [ $x -lt 50 ]; do head -c 102400 /dev/random | __file_py /root/foo${x}.bin --source - --mode 0640 --owner root --group root; x=$((x + 1)); done' | ./bin/cdist config -v -P -i - 185.203.112.26 + +INFO: [20181121130056.484643] 185.203.112.26: Starting configuration run +INFO: [20181121130108.545059] 185.203.112.26: Processing __file_py/root/foo0.bin +INFO: [20181121130110.339217] 185.203.112.26: Processing __file_py/root/foo1.bin +INFO: [20181121130112.136448] 185.203.112.26: Processing __file_py/root/foo2.bin +INFO: [20181121130113.923820] 185.203.112.26: Processing __file_py/root/foo3.bin +INFO: [20181121130115.715667] 185.203.112.26: Processing __file_py/root/foo4.bin +INFO: [20181121130117.508696] 185.203.112.26: Processing __file_py/root/foo5.bin +INFO: [20181121130119.300839] 185.203.112.26: Processing __file_py/root/foo6.bin +INFO: [20181121130124.296312] 185.203.112.26: Processing __file_py/root/foo7.bin +INFO: [20181121130131.109195] 185.203.112.26: Processing __file_py/root/foo8.bin +INFO: [20181121130133.303817] 185.203.112.26: Processing __file_py/root/foo9.bin +INFO: [20181121130136.396440] 185.203.112.26: Processing __file_py/root/foo10.bin +INFO: [20181121130138.443128] 185.203.112.26: Processing __file_py/root/foo11.bin +INFO: [20181121130140.462868] 185.203.112.26: Processing __file_py/root/foo12.bin +INFO: [20181121130142.476196] 185.203.112.26: Processing __file_py/root/foo13.bin +INFO: [20181121130145.937900] 185.203.112.26: Processing __file_py/root/foo14.bin +INFO: [20181121130148.013672] 185.203.112.26: Processing __file_py/root/foo15.bin +INFO: [20181121130150.042588] 185.203.112.26: Processing __file_py/root/foo16.bin +INFO: [20181121130152.050793] 185.203.112.26: Processing __file_py/root/foo17.bin +INFO: [20181121130154.083089] 185.203.112.26: Processing __file_py/root/foo18.bin +INFO: [20181121130156.100091] 185.203.112.26: Processing __file_py/root/foo19.bin +INFO: [20181121130158.103005] 185.203.112.26: Processing __file_py/root/foo20.bin +INFO: [20181121130200.188390] 185.203.112.26: Processing __file_py/root/foo21.bin +INFO: [20181121130202.197574] 185.203.112.26: Processing __file_py/root/foo22.bin +INFO: [20181121130205.269102] 185.203.112.26: Processing __file_py/root/foo23.bin +INFO: [20181121130208.457011] 185.203.112.26: Processing __file_py/root/foo24.bin +INFO: [20181121130211.574321] 185.203.112.26: Processing __file_py/root/foo25.bin +INFO: [20181121130213.719894] 185.203.112.26: Processing __file_py/root/foo26.bin +INFO: [20181121130215.762977] 185.203.112.26: Processing __file_py/root/foo27.bin +INFO: [20181121130217.778624] 185.203.112.26: Processing __file_py/root/foo28.bin +INFO: [20181121130219.840477] 185.203.112.26: Processing __file_py/root/foo29.bin +INFO: [20181121130221.852389] 185.203.112.26: Processing __file_py/root/foo30.bin +INFO: [20181121130223.850898] 185.203.112.26: Processing __file_py/root/foo31.bin +INFO: [20181121130225.858812] 185.203.112.26: Processing __file_py/root/foo32.bin +INFO: [20181121130227.855295] 185.203.112.26: Processing __file_py/root/foo33.bin +INFO: [20181121130229.952673] 185.203.112.26: Processing __file_py/root/foo34.bin +INFO: [20181121130231.956904] 185.203.112.26: Processing __file_py/root/foo35.bin +INFO: [20181121130233.961954] 185.203.112.26: Processing __file_py/root/foo36.bin +INFO: [20181121130236.012158] 185.203.112.26: Processing __file_py/root/foo37.bin +INFO: [20181121130238.024422] 185.203.112.26: Processing __file_py/root/foo38.bin +INFO: [20181121130241.238800] 185.203.112.26: Processing __file_py/root/foo39.bin +INFO: [20181121130243.463237] 185.203.112.26: Processing __file_py/root/foo40.bin +INFO: [20181121130245.610314] 185.203.112.26: Processing __file_py/root/foo41.bin +INFO: [20181121130247.661385] 185.203.112.26: Processing __file_py/root/foo42.bin +INFO: [20181121130250.399845] 185.203.112.26: Processing __file_py/root/foo43.bin +INFO: [20181121130252.832133] 185.203.112.26: Processing __file_py/root/foo44.bin +INFO: [20181121130254.955658] 185.203.112.26: Processing __file_py/root/foo45.bin +INFO: [20181121130257.039587] 185.203.112.26: Processing __file_py/root/foo46.bin +INFO: [20181121130259.178847] 185.203.112.26: Processing __file_py/root/foo47.bin +INFO: [20181121130301.357922] 185.203.112.26: Processing __file_py/root/foo48.bin +INFO: [20181121130303.356299] 185.203.112.26: Processing __file_py/root/foo49.bin +INFO: [20181121130305.144393] 185.203.112.26: Finished successful run in 128.66 seconds + + + +# init test file content +head -c 102400 /dev/random > /tmp/test.file + +# sh type, no file at remote +echo 'x=0; while [ $x -lt 50 ]; do __file /root/foo${x}.bin --source /tmp/test.file --mode 0640 --owner root --group root; x=$((x + 1)); done' | ./bin/cdist config -v -P -i - 185.203.112.26 + +INFO: [20181121130612.519698] 185.203.112.26: Starting configuration run +INFO: [20181121130624.219344] 185.203.112.26: Processing __file/root/foo0.bin +INFO: [20181121130626.980052] 185.203.112.26: Processing __file/root/foo1.bin +INFO: [20181121130631.200669] 185.203.112.26: Processing __file/root/foo2.bin +INFO: [20181121130642.790229] 185.203.112.26: Processing __file/root/foo3.bin +INFO: [20181121130646.565599] 185.203.112.26: Processing __file/root/foo4.bin +INFO: [20181121130648.724875] 185.203.112.26: Processing __file/root/foo5.bin +INFO: [20181121130651.464686] 185.203.112.26: Processing __file/root/foo6.bin +INFO: [20181121130653.639581] 185.203.112.26: Processing __file/root/foo7.bin +INFO: [20181121130655.773987] 185.203.112.26: Processing __file/root/foo8.bin +INFO: [20181121130657.933136] 185.203.112.26: Processing __file/root/foo9.bin +INFO: [20181121130700.065158] 185.203.112.26: Processing __file/root/foo10.bin +INFO: [20181121130702.216456] 185.203.112.26: Processing __file/root/foo11.bin +INFO: [20181121130704.429030] 185.203.112.26: Processing __file/root/foo12.bin +INFO: [20181121130706.562114] 185.203.112.26: Processing __file/root/foo13.bin +INFO: [20181121130708.696584] 185.203.112.26: Processing __file/root/foo14.bin +INFO: [20181121130710.830002] 185.203.112.26: Processing __file/root/foo15.bin +INFO: [20181121130712.966631] 185.203.112.26: Processing __file/root/foo16.bin +INFO: [20181121130715.151833] 185.203.112.26: Processing __file/root/foo17.bin +INFO: [20181121130717.355196] 185.203.112.26: Processing __file/root/foo18.bin +INFO: [20181121130719.486316] 185.203.112.26: Processing __file/root/foo19.bin +INFO: [20181121130721.619933] 185.203.112.26: Processing __file/root/foo20.bin +INFO: [20181121130723.786670] 185.203.112.26: Processing __file/root/foo21.bin +INFO: [20181121130725.924736] 185.203.112.26: Processing __file/root/foo22.bin +INFO: [20181121130728.060224] 185.203.112.26: Processing __file/root/foo23.bin +INFO: [20181121130730.178729] 185.203.112.26: Processing __file/root/foo24.bin +INFO: [20181121130732.309264] 185.203.112.26: Processing __file/root/foo25.bin +INFO: [20181121130734.479895] 185.203.112.26: Processing __file/root/foo26.bin +INFO: [20181121130736.653085] 185.203.112.26: Processing __file/root/foo27.bin +INFO: [20181121130738.814291] 185.203.112.26: Processing __file/root/foo28.bin +INFO: [20181121130741.029646] 185.203.112.26: Processing __file/root/foo29.bin +INFO: [20181121130743.128717] 185.203.112.26: Processing __file/root/foo30.bin +INFO: [20181121130745.233272] 185.203.112.26: Processing __file/root/foo31.bin +INFO: [20181121130747.364681] 185.203.112.26: Processing __file/root/foo32.bin +INFO: [20181121130749.491793] 185.203.112.26: Processing __file/root/foo33.bin +INFO: [20181121130751.620492] 185.203.112.26: Processing __file/root/foo34.bin +INFO: [20181121130753.743519] 185.203.112.26: Processing __file/root/foo35.bin +INFO: [20181121130755.862169] 185.203.112.26: Processing __file/root/foo36.bin +INFO: [20181121130758.000172] 185.203.112.26: Processing __file/root/foo37.bin +INFO: [20181121130800.090405] 185.203.112.26: Processing __file/root/foo38.bin +INFO: [20181121130802.211849] 185.203.112.26: Processing __file/root/foo39.bin +INFO: [20181121130804.356363] 185.203.112.26: Processing __file/root/foo40.bin +INFO: [20181121130806.548412] 185.203.112.26: Processing __file/root/foo41.bin +INFO: [20181121130808.671279] 185.203.112.26: Processing __file/root/foo42.bin +INFO: [20181121130810.752813] 185.203.112.26: Processing __file/root/foo43.bin +INFO: [20181121130812.844502] 185.203.112.26: Processing __file/root/foo44.bin +INFO: [20181121130814.950501] 185.203.112.26: Processing __file/root/foo45.bin +INFO: [20181121130817.040587] 185.203.112.26: Processing __file/root/foo46.bin +INFO: [20181121130819.175850] 185.203.112.26: Processing __file/root/foo47.bin +INFO: [20181121130821.332900] 185.203.112.26: Processing __file/root/foo48.bin +INFO: [20181121130823.543119] 185.203.112.26: Processing __file/root/foo49.bin +INFO: [20181121130825.833163] 185.203.112.26: Finished successful run in 133.31 seconds + +# sh type, files exist at remote +echo 'x=0; while [ $x -lt 50 ]; do __file /root/foo${x}.bin --source /tmp/test.file --mode 0640 --owner root --group root; x=$((x + 1)); done' | ./bin/cdist config -v -P -i - 185.203.112.26 + +INFO: [20181121130854.980007] 185.203.112.26: Starting configuration run +INFO: [20181121130957.927705] 185.203.112.26: Finished successful run in 62.95 seconds + +# py type, no file at remote +echo 'x=0; while [ $x -lt 50 ]; do __file_py /root/foo${x}.bin --source /tmp/test.file --mode 0640 --owner root --group root; x=$((x + 1)); done' | ./bin/cdist config -v -P -i - 185.203.112.26 + +INFO: [20181121131110.179480] 185.203.112.26: Starting configuration run +INFO: [20181121131122.086849] 185.203.112.26: Processing __file_py/root/foo0.bin +INFO: [20181121131123.876029] 185.203.112.26: Processing __file_py/root/foo1.bin +INFO: [20181121131125.668664] 185.203.112.26: Processing __file_py/root/foo2.bin +INFO: [20181121131127.460721] 185.203.112.26: Processing __file_py/root/foo3.bin +INFO: [20181121131129.591229] 185.203.112.26: Processing __file_py/root/foo4.bin +INFO: [20181121131131.390379] 185.203.112.26: Processing __file_py/root/foo5.bin +INFO: [20181121131133.195275] 185.203.112.26: Processing __file_py/root/foo6.bin +INFO: [20181121131135.006282] 185.203.112.26: Processing __file_py/root/foo7.bin +INFO: [20181121131136.834448] 185.203.112.26: Processing __file_py/root/foo8.bin +INFO: [20181121131138.659301] 185.203.112.26: Processing __file_py/root/foo9.bin +INFO: [20181121131140.496856] 185.203.112.26: Processing __file_py/root/foo10.bin +INFO: [20181121131142.367813] 185.203.112.26: Processing __file_py/root/foo11.bin +INFO: [20181121131144.239817] 185.203.112.26: Processing __file_py/root/foo12.bin +INFO: [20181121131146.133314] 185.203.112.26: Processing __file_py/root/foo13.bin +INFO: [20181121131148.049380] 185.203.112.26: Processing __file_py/root/foo14.bin +INFO: [20181121131149.974696] 185.203.112.26: Processing __file_py/root/foo15.bin +INFO: [20181121131151.929083] 185.203.112.26: Processing __file_py/root/foo16.bin +INFO: [20181121131153.923590] 185.203.112.26: Processing __file_py/root/foo17.bin +INFO: [20181121131155.874910] 185.203.112.26: Processing __file_py/root/foo18.bin +INFO: [20181121131157.857904] 185.203.112.26: Processing __file_py/root/foo19.bin +INFO: [20181121131159.902006] 185.203.112.26: Processing __file_py/root/foo20.bin +INFO: [20181121131201.859840] 185.203.112.26: Processing __file_py/root/foo21.bin +INFO: [20181121131203.810875] 185.203.112.26: Processing __file_py/root/foo22.bin +INFO: [20181121131205.763291] 185.203.112.26: Processing __file_py/root/foo23.bin +INFO: [20181121131207.710932] 185.203.112.26: Processing __file_py/root/foo24.bin +INFO: [20181121131209.658154] 185.203.112.26: Processing __file_py/root/foo25.bin +INFO: [20181121131211.615374] 185.203.112.26: Processing __file_py/root/foo26.bin +INFO: [20181121131213.569721] 185.203.112.26: Processing __file_py/root/foo27.bin +INFO: [20181121131215.522624] 185.203.112.26: Processing __file_py/root/foo28.bin +INFO: [20181121131217.471128] 185.203.112.26: Processing __file_py/root/foo29.bin +INFO: [20181121131219.421712] 185.203.112.26: Processing __file_py/root/foo30.bin +INFO: [20181121131221.375699] 185.203.112.26: Processing __file_py/root/foo31.bin +INFO: [20181121131223.327672] 185.203.112.26: Processing __file_py/root/foo32.bin +INFO: [20181121131225.281373] 185.203.112.26: Processing __file_py/root/foo33.bin +INFO: [20181121131227.256711] 185.203.112.26: Processing __file_py/root/foo34.bin +INFO: [20181121131229.209255] 185.203.112.26: Processing __file_py/root/foo35.bin +INFO: [20181121131231.170170] 185.203.112.26: Processing __file_py/root/foo36.bin +INFO: [20181121131233.123407] 185.203.112.26: Processing __file_py/root/foo37.bin +INFO: [20181121131235.077713] 185.203.112.26: Processing __file_py/root/foo38.bin +INFO: [20181121131237.017138] 185.203.112.26: Processing __file_py/root/foo39.bin +INFO: [20181121131238.988189] 185.203.112.26: Processing __file_py/root/foo40.bin +INFO: [20181121131241.026849] 185.203.112.26: Processing __file_py/root/foo41.bin +INFO: [20181121131242.978335] 185.203.112.26: Processing __file_py/root/foo42.bin +INFO: [20181121131244.934562] 185.203.112.26: Processing __file_py/root/foo43.bin +INFO: [20181121131246.885320] 185.203.112.26: Processing __file_py/root/foo44.bin +INFO: [20181121131248.835008] 185.203.112.26: Processing __file_py/root/foo45.bin +INFO: [20181121131250.789727] 185.203.112.26: Processing __file_py/root/foo46.bin +INFO: [20181121131252.738686] 185.203.112.26: Processing __file_py/root/foo47.bin +INFO: [20181121131254.691465] 185.203.112.26: Processing __file_py/root/foo48.bin +INFO: [20181121131256.640896] 185.203.112.26: Processing __file_py/root/foo49.bin +INFO: [20181121131258.194372] 185.203.112.26: Finished successful run in 108.01 seconds + +# py type, files exist at remote +echo 'x=0; while [ $x -lt 50 ]; do __file_py /root/foo${x}.bin --source /tmp/test.file --mode 0640 --owner root --group root; x=$((x + 1)); done' | ./bin/cdist config -v -P -i - 185.203.112.26 + +INFO: [20181121131327.054523] 185.203.112.26: Starting configuration run +INFO: [20181121131428.031761] 185.203.112.26: Finished successful run in 60.98 seconds + + +# Summary + +# sh type, no file at remote +INFO: [20181121125439.429440] 185.203.112.26: Finished successful run in 165.38 seconds +# py type, no file at remote +INFO: [20181121125957.514738] 185.203.112.26: Finished successful run in 105.48 seconds + +# sh type, files exist at remote but content changes +INFO: [20181121125724.451523] 185.203.112.26: Finished successful run in 114.50 seconds +# py type, files exist at remote but content changes +INFO: [20181121130305.144393] 185.203.112.26: Finished successful run in 128.66 seconds + + +# sh type, no file at remote +INFO: [20181121130825.833163] 185.203.112.26: Finished successful run in 133.31 seconds +# py type, no file at remote +INFO: [20181121131258.194372] 185.203.112.26: Finished successful run in 108.01 seconds + +# sh type, files exist at remote +INFO: [20181121130957.927705] 185.203.112.26: Finished successful run in 62.95 seconds +# py type, files exist at remote +INFO: [20181121131428.031761] 185.203.112.26: Finished successful run in 60.98 seconds diff --git a/docs/dev/python-types/benchmark.sh b/docs/dev/python-types/benchmark.sh new file mode 100755 index 00000000..3e01941f --- /dev/null +++ b/docs/dev/python-types/benchmark.sh @@ -0,0 +1,43 @@ +#!/bin/sh + +# Addapt to your env. +CDIST_PATH="$CDIST_PATH:./docs/dev/python-types/conf" +export CDIST_PATH +TARGET_HOST=185.203.112.26 + +if [ $# -eq 0 ] +then + N=1 +else + N=$1 +fi + +manifest() { + bytes=$(echo "$1 * 1024" | bc) + echo "head -c ${bytes} /dev/random | __file$2 /root/foo$3.bin --source - --mode 0640 --owner root --group root" +} + +verbosity="-vv" #"-vvv" +i=0 +while [ "$i" -lt "$N" ] +do + if [ "$N" -ne 1 ] + then + printf "iteration %d\\n" "$i" + fi + printf "shinit clean state...\\n" + ssh root@${TARGET_HOST} 'rm foo$i.bin;' + manifest 50 "" $i | ./bin/cdist config "${verbosity}" -P -i - ${TARGET_HOST} + + printf "pyinit clean state...\\n" + ssh root@${TARGET_HOST} 'rm foo$i.bin;' + manifest 50 '_py' $i | ./bin/cdist config "${verbosity}" -P -i - ${TARGET_HOST} + + printf "shinit present state...\\n" + manifest 50 "" $i | ./bin/cdist config "${verbosity}" -P -i - ${TARGET_HOST} + + printf "pyinit present state...\\n" + manifest 50 '_py' $i | ./bin/cdist config "${verbosity}" -P -i - ${TARGET_HOST} + + i=$((i + 1)) +done diff --git a/docs/dev/python-types/conf/manifest/pyinit b/docs/dev/python-types/conf/manifest/pyinit new file mode 100644 index 00000000..53f15a97 --- /dev/null +++ b/docs/dev/python-types/conf/manifest/pyinit @@ -0,0 +1,7 @@ +#for x in 1; do +# echo xxx${x} | __file_py /root/foobar${x} --source - --mode 0640 --owner root --group root; +#done +#__dummy_config_py test1 + +echo xxx | __file_py /root/foobar --source - --mode 0640 --owner root --group root +__dummy_config_py test1 diff --git a/docs/dev/python-types/conf/manifest/shinit b/docs/dev/python-types/conf/manifest/shinit new file mode 100644 index 00000000..44129546 --- /dev/null +++ b/docs/dev/python-types/conf/manifest/shinit @@ -0,0 +1,7 @@ +#for x in 1; do +# echo xxx${x} | __file /root/foobar${x} --source - --mode 0640 --owner root --group root; +#done +#__dummy_config_sh test1 + +echo xxx | __file /root/foobar --source - --mode 0640 --owner root --group root +__dummy_config_sh test1 diff --git a/docs/dev/python-types/conf/type/__dummy_config/__init__.py b/docs/dev/python-types/conf/type/__dummy_config/__init__.py new file mode 100644 index 00000000..91108cc9 --- /dev/null +++ b/docs/dev/python-types/conf/type/__dummy_config/__init__.py @@ -0,0 +1,52 @@ +import os +import sys +from cdist.core import PythonType, ManifestEntry + + +class DummyConfig(PythonType): + def type_manifest(self): + print('dummy py manifest stdout') + print('dummy py manifest stderr', file=sys.stderr) + filepy = ManifestEntry(name='__file_py', stdin='dummy=py\n', + parameters={ + '/root/dummypy.conf': None, + '--mode': '0640', + '--owner': 'root', + '--group': 'root', + '--source': '-', + }) + self.log.info('Created manifest entry %s', filepy) + yield filepy + + self_path = os.path.dirname(os.path.realpath(__file__)) + conf_path = os.path.join(self_path, 'files', 'dummypy.conf') + filepy = ManifestEntry(name='__file_py', + parameters={ + '/root/dummypy2.conf': None, + '--mode': '0640', + '--owner': 'root', + '--group': 'root', + '--source': conf_path, + }) + yield filepy + + self_path = os.path.dirname(os.path.realpath(__file__)) + conf_path = os.path.join(self_path, 'files', 'dummysh.conf') + with open(conf_path, 'r') as f: + filepy = ManifestEntry(name='__file', stdin=f, + parameters={ + '/root/dummysh.conf': None, + '--mode': '0600', + '--owner': 'root', + '--group': 'root', + '--source': '-', + }) + yield filepy + + def type_gencode(self): + print('__dummy_config test stdout') + print('__dummy_config test stderr', file=sys.stderr) + pattern = "__file_py/root/dummypy2.conf:chgrp 'root'" + match = self.receive_message(pattern) + print('Received message:', match.string if match else None) + return None diff --git a/docs/dev/python-types/conf/type/__dummy_config/files/dummypy.conf b/docs/dev/python-types/conf/type/__dummy_config/files/dummypy.conf new file mode 100644 index 00000000..a7ea5e71 --- /dev/null +++ b/docs/dev/python-types/conf/type/__dummy_config/files/dummypy.conf @@ -0,0 +1 @@ +dummy=py2 diff --git a/docs/dev/python-types/conf/type/__dummy_config/files/dummysh.conf b/docs/dev/python-types/conf/type/__dummy_config/files/dummysh.conf new file mode 100644 index 00000000..518e9890 --- /dev/null +++ b/docs/dev/python-types/conf/type/__dummy_config/files/dummysh.conf @@ -0,0 +1 @@ +dummy=sh diff --git a/docs/dev/python-types/conf/type/__dummy_config_py/__init__.py b/docs/dev/python-types/conf/type/__dummy_config_py/__init__.py new file mode 100644 index 00000000..7e0a9acf --- /dev/null +++ b/docs/dev/python-types/conf/type/__dummy_config_py/__init__.py @@ -0,0 +1,30 @@ +import os +import sys +from cdist.core import PythonType, ManifestEntry + + +class DummyConfig(PythonType): + def type_manifest(self): + print('dummy manifest stdout') + print('dummy manifest stderr\n', file=sys.stderr) + filepy = ManifestEntry(name='__file_py', stdin='dummy=1\n', + parameters={ + '/root/dummy1.conf': None, + '--mode': '0640', + '--owner': 'root', + '--group': 'root', + '--source': '-', + }) + yield filepy + + self_path = os.path.dirname(os.path.realpath(__file__)) + conf_path = os.path.join(self_path, 'files', 'dummy.conf') + filepy = ManifestEntry(name='__file_py', + parameters={ + '/root/dummy2.conf': None, + '--mode': '0600', + '--owner': 'root', + '--group': 'root', + '--source': conf_path, + }) + yield filepy diff --git a/docs/dev/python-types/conf/type/__dummy_config_py/files/dummy.conf b/docs/dev/python-types/conf/type/__dummy_config_py/files/dummy.conf new file mode 100644 index 00000000..972d11ca --- /dev/null +++ b/docs/dev/python-types/conf/type/__dummy_config_py/files/dummy.conf @@ -0,0 +1 @@ +dummy=2 diff --git a/docs/dev/python-types/conf/type/__dummy_config_sh/files/dummy.conf b/docs/dev/python-types/conf/type/__dummy_config_sh/files/dummy.conf new file mode 100644 index 00000000..972d11ca --- /dev/null +++ b/docs/dev/python-types/conf/type/__dummy_config_sh/files/dummy.conf @@ -0,0 +1 @@ +dummy=2 diff --git a/docs/dev/python-types/conf/type/__dummy_config_sh/manifest b/docs/dev/python-types/conf/type/__dummy_config_sh/manifest new file mode 100644 index 00000000..d675d6a3 --- /dev/null +++ b/docs/dev/python-types/conf/type/__dummy_config_sh/manifest @@ -0,0 +1,6 @@ +printf 'dummy manifest stdout\n' +printf 'dummy manifest stderr\n' >&2 + +printf "dummy=1\\n" | __file /root/dummy1.conf --mode 0640 --owner root --group root --source - + +__file /root/dummy2.conf --mode 0600 --owner root --group root --source "$__type/files/dummy.conf" diff --git a/docs/dev/python-types/test.sh b/docs/dev/python-types/test.sh new file mode 100755 index 00000000..941ea264 --- /dev/null +++ b/docs/dev/python-types/test.sh @@ -0,0 +1,27 @@ +#!/bin/sh + +# Addapt to your env. +CDIST_PATH="$CDIST_PATH:./docs/dev/python-types/conf" +export CDIST_PATH +TARGET_HOST=185.203.112.26 +env | grep CDIST_PATH + +for streams in ' ' '-S' +do + for x in sh py + do + printf "[%s] Removing old foobar* files\\n" "$x" + printf -- "----------------\\n" + ssh root@${TARGET_HOST} 'rm foobar*; rm dummy*' + printf "[%s] Listing foobar* files\\n" "$x" + printf -- "----------------\\n" + ssh root@${TARGET_HOST} 'ls foobar* dummy*' + printf "[%s] Running cdist config, streams: %s\\n" "$x" "$streams" + printf -- "----------------\\n" + ./bin/cdist config -P ${streams} -v -i ./docs/dev/python-types/conf/manifest/${x}init -- ${TARGET_HOST} + printf "[%s] Listing foobar* files\\n" "$x" + printf -- "----------------\\n" + ssh root@${TARGET_HOST} 'ls foobar* dummy*' + ./bin/cdist config -P ${streams} -v -i ./docs/dev/python-types/conf/manifest/${x}init -- ${TARGET_HOST} + done +done diff --git a/docs/dev/python-types/timeit.sh b/docs/dev/python-types/timeit.sh new file mode 100755 index 00000000..f1b6c9fb --- /dev/null +++ b/docs/dev/python-types/timeit.sh @@ -0,0 +1,36 @@ +#!/bin/sh + +# Addapt to your env. +CDIST_PATH="$CDIST_PATH:./docs/dev/python-types/conf" +export CDIST_PATH +TARGET_HOST=185.203.112.26 + +if [ $# -eq 0 ] +then + N=1 +else + N=$1 +fi + +i=0 +while [ "$i" -lt "$N" ] +do + if [ "$N" -ne 1 ] + then + printf "iteration %d\\n" "$i" + fi + printf "shinit clean state...\\n" + ssh root@${TARGET_HOST} 'rm foobar*; rm dummy*;' + + time ./bin/cdist config -vv -P -i ./docs/dev/python-types/conf/manifest/shinit ${TARGET_HOST} + printf "pyinit clean state...\\n" + ssh root@$${TARGET_HOST} 'rm foobar*; rm dummy*;' + time ./bin/cdist config -vv -P -i ./docs/dev/python-types/conf/manifest/pyinit ${TARGET_HOST} + + printf "shinit present state...\\n" + time ./bin/cdist config -vv -P -i ./docs/dev/python-types/conf/manifest/shinit ${TARGET_HOST} + + printf "pyinit present state...\\n" + time ./bin/cdist config -vv -P -i ./docs/dev/python-types/conf/manifest/pyinit ${TARGET_HOST} + i=$((i + 1)) +done diff --git a/docs/src/cdist-preos.rst b/docs/src/cdist-preos.rst index e85af2de..74c86f37 100644 --- a/docs/src/cdist-preos.rst +++ b/docs/src/cdist-preos.rst @@ -24,14 +24,15 @@ For example, to create ubuntu PreOS: .. code-block:: sh - $ cdist preos ubuntu /preos/preos-ubuntu -B -C \ - -k ~/.ssh/id_rsa.pub -p /preos/pxe-ubuntu + $ cdist preos ubuntu /preos/preos-ubuntu -b -C \ + -k ~/.ssh/id_rsa.pub -p /preos/pxe-ubuntu \ + -t "/usr/bin/curl 192.168.111.5:3000/cdist/install/" For more info about available options see cdist manual page. -This will bootstrap (``-B``) ubuntu PreOS in ``/preos/preos-ubuntu`` directory, it +This will bootstrap (``-b``) ubuntu PreOS in ``/preos/preos-ubuntu`` directory, it will be configured (``-C``) using default built-in initial manifest and with -specified ssh authorized key (``-k``). +specified ssh authorized key (``-k``) and with specified trigger command (``-t``). After bootstrapping and configuration PXE boot directory will be created (``-p``) in ``/preos/pxe-ubuntu``. @@ -41,6 +42,15 @@ proper dhcp, tftp setting). Since PreOS is configured with ssh authorized key it can be accessed throguh ssh, i.e. it can be further installed and configured with cdist. +When installing and configuring new machines using cdist's PreOS concept +cdist can use triggering for host installation/configuration, which is described +in the previous chapter. + +When new machine is booted with PreOS then trigger command is executed. +Machine will connect to cdist trigger server. If the request is, for example, +for installation then cdist trigger server will start install command for the +client host using parameters specified at trigger server startup. + Implementing new PreOS sub-command ---------------------------------- preos command is implemented as a plugin system. This plugin system scans for @@ -135,3 +145,32 @@ When you try to run this new preos you will get: In the ``commandline`` function/method you have all the freedom to actually create PreOS. + +Simple tipical use case for using PreOS and trigger +--------------------------------------------------- +Tipical use case for using PreOS and trigger command include the following steps. + +#. Create PreOS PXE with ssh key and trigger command for installation. + + .. code-block:: sh + + $ cdist preos ubuntu /preos/ubuntu -b -C \ + -k ~/.ssh/id_rsa.pub -p /preos/pxe \ + -t "/usr/bin/curl 192.168.111.5:3000/cdist/install/" + +#. Configure dhcp server and tftp server. + +#. On cdist host (192.168.111.5 from above) start trigger command (it will use + default init manifest for installation). + + .. code-block:: sh + + $ cdist trigger -b -v + +#. After all is set up start new machines (PXE boot). + +#. New machine boots and executes trigger command, i.e. triggers installation. + +#. Cdist trigger server starts installing host that has triggered it. + +#. After cdist install is finished new host is installed. diff --git a/docs/src/cdist-real-world.rst b/docs/src/cdist-real-world.rst index ba118d63..8ccb0fc9 100644 --- a/docs/src/cdist-real-world.rst +++ b/docs/src/cdist-real-world.rst @@ -27,7 +27,7 @@ for that. This type will: - configure nginx. Our type will not create the actual python application. Its intention is only -to configure hosting for specified user and project. It is up to the user to +to configure hosing for specified user and project. It is up to the user to create his/her applications. So let's start. @@ -480,7 +480,7 @@ Creating python bottle application We now need to create Bottle application. As you remember from the beginning of this walkthrough our type does not create the actual python application, -its intention is only to configure hosting for specified user and project. +its intention is only to configure hosing for specified user and project. It is up to the user to create his/her applications. Become app user:: diff --git a/docs/src/cdist-reference.rst.sh b/docs/src/cdist-reference.rst.sh index 3ab12fe2..c561495c 100755 --- a/docs/src/cdist-reference.rst.sh +++ b/docs/src/cdist-reference.rst.sh @@ -222,10 +222,6 @@ __cdist_log_level, __cdist_log_level_name | TRACE | 5 | +----------------+-----------------+ - Available for: initial manifest, explorer, type manifest, type explorer, - type gencode. -__cdist_dry_run - Is set only when doing dry run (``-n`` flag). Available for: initial manifest, explorer, type manifest, type explorer, type gencode. __explorer diff --git a/docs/src/cdist-trigger.rst b/docs/src/cdist-trigger.rst new file mode 100644 index 00000000..93e9d920 --- /dev/null +++ b/docs/src/cdist-trigger.rst @@ -0,0 +1,35 @@ +Trigger +======= + +Description +----------- +cdist supports triggering for host installation/configuration using trigger command. +This command starts trigger server at management node, for example: + +.. code-block:: sh + + $ cdist trigger -b -v + +This will start cdist trigger server in verbose mode. cdist trigger server accepts +simple requests for configuration and for installation: + +* :strong:`/cdist/install/` for installation +* :strong:`/cdist/config/` for configuration. + +Other configuration parameters are the same as in like cdist config (See `cdist `_). + +Machines can then trigger cdist trigger server with appropriate requests. +If the request is, for example, for installation (:strong:`/cdist/install/`) +then cdist trigger server will start install command for the client host using +parameters specified at trigger server startup. For the above example that means +that client will be installed using default initial manifest. + +When triggered cdist will try to reverse DNS lookup for host name and if +host name is dervied then it is used for running cdist config. If no +host name is resolved then IP address is used. + +This command returns the following response codes to client requests: + +* 200 for success +* 599 for cdist run errors +* 500 for cdist/server errors. diff --git a/docs/src/cdist-troubleshooting.rst b/docs/src/cdist-troubleshooting.rst index e639aafd..6b7fb4af 100644 --- a/docs/src/cdist-troubleshooting.rst +++ b/docs/src/cdist-troubleshooting.rst @@ -47,8 +47,7 @@ you write to use the -e flag: Using debug dump helper script ------------------------------ Since cdist stores data to local cache that can be used for debugging there -is a helper script that dumps data from local cache, -`cdist-dump `_. +is a helper script that dumps data from local cache. For more info see: diff --git a/docs/src/cdist-type.rst b/docs/src/cdist-type.rst index 582c0938..7c0dab8d 100644 --- a/docs/src/cdist-type.rst +++ b/docs/src/cdist-type.rst @@ -71,31 +71,6 @@ when using -j option. Example of such a type is __package_dpkg type where dpkg i prevents to be run in more than one instance. -Deprecated types ------------------ -If a type is flagged with 'deprecated' marker then it is considered deprecated. -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 - - $ ls -l deprecated - -rw-r--r-- 1 darko darko 71 May 20 18:30 deprecated - $ cat deprecated - This type is deprecated. It will be removed in the next minor release. - $ echo '__foo foo' | ./bin/cdist config -i - 185.203.112.26 - WARNING: 185.203.112.26: Type __foo is deprecated: This type is deprecated. It will be removed in the next minor release. - -If 'deprecated' marker has no content then general message is printed, e.g.: - -.. code-block:: sh - - $ ls -l deprecated - -rw-r--r-- 1 darko darko 0 May 20 18:36 deprecated - $ echo '__bar foo' | ./bin/cdist config -i - 185.203.112.26 - WARNING: 185.203.112.26: Type __bar is deprecated. - - How to write a new type ----------------------- A type consists of @@ -118,9 +93,6 @@ they are written in shell so they are executed using '/bin/sh -e' or 'CDIST_LOCA For executable shell code it is suggested that shebang is '#!/bin/sh -e'. -For creating type skeleton you can use helper script -`cdist-new-type `_. - Defining parameters ------------------- @@ -186,31 +158,6 @@ 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. @@ -241,73 +188,6 @@ 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 @@ -491,15 +371,6 @@ It is available for initial manifest, explorer, type manifest, type explorer, type gencode. -Detecting dry run ------------------ - -If ``$__cdist_dry_run`` environment variable is set, then it's dry run. - -It is available for initial manifest, explorer, type manifest, -type explorer, type gencode. - - Hints for typewriters ---------------------- It must be assumed that the target is pretty dumb and thus does not have high diff --git a/docs/src/cdist-upgrade.rst b/docs/src/cdist-upgrade.rst index 67fd4934..e57ed63c 100644 --- a/docs/src/cdist-upgrade.rst +++ b/docs/src/cdist-upgrade.rst @@ -11,7 +11,7 @@ To upgrade cdist in the current branch use git pull # Also update the manpages - make man + ./build man export MANPATH=$MANPATH:$(pwd -P)/doc/man If you stay on a version branche (i.e. 1.0, 1.1., ...), nothing should break. diff --git a/docs/src/index.rst b/docs/src/index.rst index 5e54d8fc..41a37bb7 100644 --- a/docs/src/index.rst +++ b/docs/src/index.rst @@ -22,7 +22,6 @@ is being used in small up to enterprise grade environments. cdist-real-world man1/cdist man1/cdist-dump - man1/cdist-new-type cdist-bootstrap cdist-configuration cdist-manifest @@ -32,6 +31,7 @@ is being used in small up to enterprise grade environments. cdist-messaging cdist-parallelization cdist-inventory + cdist-trigger cdist-preos cdist-integration cdist-reference diff --git a/docs/src/man1/cdist-new-type.rst b/docs/src/man1/cdist-new-type.rst deleted file mode 100644 index f1a8b992..00000000 --- a/docs/src/man1/cdist-new-type.rst +++ /dev/null @@ -1,74 +0,0 @@ -cdist-new-type(1) -================= - -NAME ----- -cdist-new-type - Create new type skeleton - - -SYNOPSIS --------- - -:: - - cdist-new-type TYPE-NAME AUTHOR-NAME AUTHOR-EMAIL [TYPE-BASE-PATH] - - - -DESCRIPTION ------------ -cdist-new-type is a helper script that creates new type skeleton. -It is then up to the type author to finish the type. - -It creates skeletons for the following files: - -* man.rst -* manifest -* gencode-remote. - -Upon creation it prints the path to the newly created type directory. - - -ARGUMENTS ---------- -**TYPE-NAME** - Name of the new type. - -**AUTHOR-NAME** - Type author's full name. - -**AUTHOR-NAME** - Type author's email. - -**TYPE-BASE-PATH** - Path to the base directory of the type. If not set it defaults - to '$PWD/type'. - - -EXAMPLES --------- - -.. code-block:: sh - - # Create new type __foo in ~/.cdist directory. - $ cd ~/.cdist - $ cdist-new-type '__foo' 'Foo Bar' 'foo.bar at foobar.org' - /home/foo/.cdist/type/__foo - - -SEE ALSO --------- -:strong:`cdist`\ (1) - - -AUTHORS -------- - -| Steven Armstrong -| Darko Poljak - - -COPYING -------- -Copyright \(C) 2019 Steven Armstrong, Darko Poljak. Free use of this software is -granted under the terms of the GNU General Public License v3 or later (GPLv3+). diff --git a/docs/src/man1/cdist.rst b/docs/src/man1/cdist.rst index 7f368e68..927a92c1 100644 --- a/docs/src/man1/cdist.rst +++ b/docs/src/man1/cdist.rst @@ -11,7 +11,7 @@ SYNOPSIS :: - cdist [-h] [-V] {banner,config,install,inventory,preos,shell} ... + cdist [-h] [-V] {banner,config,install,inventory,preos,shell,trigger} ... cdist banner [-h] [-l LOGLEVEL] [-q] [-v] @@ -65,25 +65,35 @@ SYNOPSIS [-C] [-c CDIST_PARAMS] [-D DRIVE] [-e REMOTE_EXEC] [-i MANIFEST] [-k KEYFILE ] [-m MIRROR] [-P ROOT_PASSWORD] [-p PXE_BOOT_DIR] [-r] - [-S SCRIPT] [-s SUITE] [-y REMOTE_COPY] + [-S SCRIPT] [-s SUITE] [-t TRIGGER_COMMAND] + [-y REMOTE_COPY] target_dir cdist preos devuan [-h] [-l LOGLEVEL] [-q] [-v] [-b] [-a ARCH] [-B] [-C] [-c CDIST_PARAMS] [-D DRIVE] [-e REMOTE_EXEC] [-i MANIFEST] [-k KEYFILE ] [-m MIRROR] [-P ROOT_PASSWORD] [-p PXE_BOOT_DIR] [-r] - [-S SCRIPT] [-s SUITE] [-y REMOTE_COPY] + [-S SCRIPT] [-s SUITE] [-t TRIGGER_COMMAND] + [-y REMOTE_COPY] target_dir cdist preos ubuntu [-h] [-l LOGLEVEL] [-q] [-v] [-b] [-a ARCH] [-B] [-C] [-c CDIST_PARAMS] [-D DRIVE] [-e REMOTE_EXEC] [-i MANIFEST] [-k KEYFILE ] [-m MIRROR] [-P ROOT_PASSWORD] [-p PXE_BOOT_DIR] [-r] - [-S SCRIPT] [-s SUITE] [-y REMOTE_COPY] + [-S SCRIPT] [-s SUITE] [-t TRIGGER_COMMAND] + [-y REMOTE_COPY] target_dir cdist shell [-h] [-l LOGLEVEL] [-q] [-v] [-s SHELL] + cdist trigger [-h] [-l LOGLEVEL] [-q] [-v] [-b] [-g CONFIG_FILE] [-4] + [-6] [-C CACHE_PATH_PATTERN] [-c CONF_DIR] [-i MANIFEST] + [-j [JOBS]] [-n] [-o OUT_PATH] [-P] + [-R [{tar,tgz,tbz2,txz}]] [-r REMOTE_OUT_PATH] + [--remote-copy REMOTE_COPY] [--remote-exec REMOTE_EXEC] + [-S] [-D DIRECTORY] [-H HTTP_PORT] [--ipv6] [-O SOURCE] + DESCRIPTION ----------- @@ -519,6 +529,10 @@ PREOS DEBIAN/DEVUAN **-s SUITE, --suite SUITE** suite used for debootstrap, by default 'stable' +**-t TRIGGER_COMMAND, --trigger-command TRIGGER_COMMAND** + trigger command that will be added to cdist config; + '``__cdist_preos_trigger http ...``' type is appended to initial manifest + **-y REMOTE_COPY, --remote-copy REMOTE_COPY** remote copy that cdist config will use, by default internal script is used @@ -579,6 +593,10 @@ PREOS UBUNTU **-s SUITE, --suite SUITE** suite used for debootstrap, by default 'xenial' +**-t TRIGGER_COMMAND, --trigger-command TRIGGER_COMMAND** + trigger command that will be added to cdist config; + '``__cdist_preos_trigger http ...``' type is appended to initial manifest + **-y REMOTE_COPY, --remote-copy REMOTE_COPY** remote copy that cdist config will use, by default internal script is used @@ -596,6 +614,96 @@ usage. Its primary use is for debugging type parameters. be POSIX compatible shell. +TRIGGER +------- +Start trigger (simple http server) that waits for connections. When host +connects then it triggers config or install command and then cdist +config/install is executed which configures/installs host. +When triggered cdist will try to reverse DNS lookup for host name and if +host name is dervied then it is used for running cdist config. If no +host name is resolved then IP address is used. +Request path recognizes following requests: + +* :strong:`/cdist/config/.*` for config +* :strong:`/cdist/install/.*` for install. + +This command returns the following response codes to client requests: + +* 200 for success +* 599 for cdist run errors +* 500 for cdist/server errors. + +**-4, -force-ipv4** + Force to use IPv4 addresses only. No influence for + custom remote commands. + +**-6, --force-ipv6** + Force to use IPv6 addresses only. No influence for + custom remote commands. + +**-C CACHE_PATH_PATTERN, --cache-path-pattern CACHE_PATH_PATTERN** + Specify custom cache path pattern. If it is not set + then default hostdir is used. + +**-c CONF_DIR, --conf-dir CONF_DIR** + Add configuration directory (can be repeated, last one + wins). + +**-D DIRECTORY, --directory DIRECTORY** + Where to create local files + +**-g CONFIG_FILE, --config-file CONFIG_FILE** + Use specified custom configuration file. + +**-H HTTP_PORT, --http-port HTTP_PORT** + Create trigger listener via http on specified port + +**-i MANIFEST, --initial-manifest MANIFEST** + Path to a cdist manifest or '-' to read from stdin. + +**--ipv6** + Listen to both IPv4 and IPv6 (instead of only IPv4) + +**-j [JOBS], --jobs [JOBS]** + Operate in parallel in specified maximum number of + jobs. Global explorers, object prepare and object run + are supported. Without argument CPU count is used by + default. Currently in beta. + +**-n, --dry-run** + Do not execute code. + +**-O SOURCE, --source SOURCE** + Which file to copy for creation + +**-o OUT_PATH, --out-dir OUT_PATH** + Directory to save cdist output in. + +**-P, --timestamp** + Timestamp log messages with the current local date and + time in the format: YYYYMMDDHHMMSS.us. + +**-R [{tar,tgz,tbz2,txz}], --use-archiving [{tar,tgz,tbz2,txz}]** + Operate by using archiving with compression where + appropriate. Supported values are: tar - tar archive, + tgz - gzip tar archive (the default), tbz2 - bzip2 tar + archive and txz - lzma tar archive. Currently in beta. + +**-r REMOTE_OUT_PATH, --remote-out-dir REMOTE_OUT_PATH** + Directory to save cdist output in on the target host. + +**--remote-copy REMOTE_COPY** + Command to use for remote copy (should behave like + scp). + +**--remote-exec REMOTE_EXEC** + Command to use for remote execution (should behave + like ssh). + +**-S, --disable-saving-output-streams** + Disable saving output streams. + + CONFIGURATION ------------- cdist obtains configuration data from the following sources in the following @@ -734,7 +842,8 @@ EXAMPLES % cdist config -f loadbalancers # Configure hosts read from file web.hosts using 16 parallel jobs - % cdist config -j 16 -f web.hosts + # (beta functionality) + % cdist config -b -j 16 -f web.hosts # Display banner cdist banner @@ -790,20 +899,28 @@ EXAMPLES # Configure all hosts from inventory db $ cdist config -b -A - # Create default debian PreOS in debug mode - $ cdist preos debian /preos/preos-debian -vvvv -C \ - -k ~/.ssh/id_rsa.pub -p /preos/pxe-debian + # Create default debian PreOS in debug mode with config + # trigger command + $ cdist preos debian /preos/preos-debian -b -vvvv -C \ + -k ~/.ssh/id_rsa.pub -p /preos/pxe-debian \ + -t "/usr/bin/curl 192.168.111.5:3000/config/" - # Create ubuntu PreOS - $ cdist preos ubuntu /preos/preos-ubuntu -C \ - -k ~/.ssh/id_rsa.pub -p /preos/pxe-ubuntu + # Create ubuntu PreOS with install trigger command + $ cdist preos ubuntu /preos/preos-ubuntu -b -C \ + -k ~/.ssh/id_rsa.pub -p /preos/pxe-ubuntu \ + -t "/usr/bin/curl 192.168.111.5:3000/install/" - # Create ubuntu PreOS on drive /dev/sdb + # Create ubuntu PreOS on drive /dev/sdb with install trigger command # and set root password to 'password'. - $ cdist preos ubuntu /mnt -B -C \ + $ cdist preos ubuntu /mnt -b -B -C \ -k ~/.ssh/id_rsa.pub -D /dev/sdb \ + -t "/usr/bin/curl 192.168.111.5:3000/install/" \ -P password + # Start trigger in verbose mode that will configure host using specified + # init manifest + % cdist trigger -b -v -i ~/.cdist/manifest/init-for-triggered + ENVIRONMENT ----------- diff --git a/hacking/timing-tests/benchmark-files.sh b/hacking/timing-tests/benchmark-files.sh deleted file mode 100644 index c71d1c7e..00000000 --- a/hacking/timing-tests/benchmark-files.sh +++ /dev/null @@ -1,79 +0,0 @@ -#!/bin/sh - -num=50000 -dsthost=localhost - -tmp=$(mktemp -d) -remote_tmp=${tmp}-remote - -cd "$tmp" - -create_files() { - i=0 - while [ $i -lt $num ]; do - echo $i > file-${i} - i=$((i+1)) - done -} - -delete_remote() { - ssh "${dsthost}" "rm -rf ${remote_tmp}" -} - - -tar_remote() { - cd "${tmp}" - tar c . | ssh "${dsthost}" "mkdir ${remote_tmp}; cd ${remote_tmp}; tar x" -} - -cdist_remote() -{ - ( - while [ $i -lt $num ]; do - echo __file ${remote_tmp}/file-${i} --source "${tmp}/file-${i}" - i=$((i+1)) - done - ) | cdist config -i - -vv "${dsthost}" - -} - -cdist_remote_parallel() -{ - ( - while [ $i -lt $num ]; do - echo __file ${remote_tmp}/file-${i} --source "${tmp}/file-${i}" - i=$((i+1)) - done - ) | cdist config -j10 -i - -vv "${dsthost}" - -} - -echo "Creating ${num} files" -time create_files - -echo "scping files" -time scp -r "${tmp}" "${dsthost}:$remote_tmp" >/dev/null - -echo "delete remote" -time delete_remote - -echo "taring files" -time tar_remote - -echo "delete remote" -time delete_remote - -echo "cdisting files" -time cdist_remote - -echo "delete remote" -time delete_remote - -echo "cdisting files (parallel)!" -time cdist_remote - -echo "delete remote" -time delete_remote - -echo "delete local" -rm -rf "$tmp" diff --git a/scripts/cdist b/scripts/cdist index 7bf12c01..664504a0 100755 --- a/scripts/cdist +++ b/scripts/cdist @@ -60,7 +60,7 @@ def commandline(): if __name__ == "__main__": - cdistpythonversion = '3.2' + cdistpythonversion = '3.5' if sys.version < cdistpythonversion: print('Python >= {} is required on the source host.'.format( cdistpythonversion), file=sys.stderr) diff --git a/scripts/cdist-new-type b/scripts/cdist-new-type deleted file mode 100755 index 79dcfd90..00000000 --- a/scripts/cdist-new-type +++ /dev/null @@ -1,159 +0,0 @@ -#!/bin/sh - -basename="${0##*/}" - -if [ $# -lt 3 ] -then - printf "usage: %s TYPE-NAME AUTHOR-NAME AUTHOR-EMAIL [TYPE-BASE-PATH] - TYPE-NAME Name of the type. - AUTHOR-NAME Type author's full name. - AUTHOR-EMAIL Type author's email. - TYPE-BASE-PATH Path to the base directory of the type. If not set it defaults - to '\$PWD/type'.\n" "${basename}" - exit 1 -fi - -type_name="$1" -shift -author_name="$1" -shift -author_email="$1" -shift - -if [ $# -ge 1 ] -then - type_base_path="$1" - shift -else - #type_base_path=~/.cdist/type - type_base_path="$PWD/type" -fi - -error() { - printf "%s\n" "$*" >&2 -} - -die() { - error "$@" - exit 1 -} - -cd "$type_base_path" || die "Could not change to type directory: $type_base_path. -You have to specify type base path or run me from within a cdist conf directory, -e.g. ~/.cdist." - -year=$(date +%Y) -copyright="# $year $author_name ($author_email)" - -license="# 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 . -# -" - -set -e - -mkdir "$type_name" -cd "$type_name" - -### man page -header="cdist-type${type_name}(7)" -header_length="${#header}" -cat >> man.rst << DONE -$header -$(while [ "${header_length}" -gt 0 ]; do printf "="; header_length=$((header_length - 1)); done; printf "\n";) - -NAME ----- -cdist-type${type_name} - TODO - - -DESCRIPTION ------------ -This space intentionally left blank. - - -REQUIRED PARAMETERS -------------------- -None. - - -OPTIONAL PARAMETERS -------------------- -None. - - -BOOLEAN PARAMETERS ------------------- -None. - - -EXAMPLES --------- - -.. code-block:: sh - - # TODO - ${type_name} - - -SEE ALSO --------- -:strong:\`TODO\`\\ (7) - - -AUTHORS -------- -$author_name <$author_email> - - -COPYING -------- -Copyright \(C) $year $author_name. 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. -DONE - -### manifest -cat >> manifest << DONE -#!/bin/sh -e -# -${copyright} -# -${license} - -os=\$(cat "\$__global/explorer/os") - -case "\$os" in - *) - printf "Your operating system (%s) is currently not supported by this type (%s)\n" "\$os" "\${__type##*/}" >&2 - printf "Please contribute an implementation for it if you can.\n" >&2 - exit 1 - ;; -esac -DONE -chmod +x manifest - -# gencode-remote -cat >> gencode-remote << DONE -#!/bin/sh -e -# -${copyright} -# -${license} -DONE -chmod +x gencode-remote - -printf "%s/%s\n" "$type_base_path" "$type_name" diff --git a/setup.py b/setup.py index 2bb1e16d..5f14a2f4 100644 --- a/setup.py +++ b/setup.py @@ -1,27 +1,7 @@ from distutils.core import setup -from distutils.errors import DistutilsError +import cdist import os import re -import subprocess - - -# We have it only if it is a git cloned repo. -build_helper = os.path.join('bin', 'build-helper') -# Version file path. -version_file = os.path.join('cdist', 'version.py') -# If we have build-helper we could be a git repo. -if os.path.exists(build_helper): - # Try to generate version.py. - rv = subprocess.run([build_helper, 'version', ]) - if rv.returncode != 0: - raise DistutilsError("Failed to generate {}".format(version_file)) -else: - # Otherwise, version.py should be present. - if not os.path.exists(version_file): - raise DistutilsError("Missing version file {}".format(version_file)) - - -import cdist def data_finder(data_dir): @@ -56,7 +36,7 @@ setup( name="cdist", packages=["cdist", "cdist.core", "cdist.exec", "cdist.util", ], package_data={'cdist': package_data}, - scripts=["scripts/cdist", "scripts/cdist-dump", "scripts/cdist-new-type"], + scripts=["scripts/cdist", "scripts/cdist-dump"], version=cdist.version.VERSION, description="A Usable Configuration Management System", author="Nico Schottelius",