From 3adc4f160998776033934d65ba22f1666c9e0b4b Mon Sep 17 00:00:00 2001 From: Dennis Camera Date: Sat, 30 May 2020 17:24:26 +0200 Subject: [PATCH] [type/__mail_alias] Implement type --- type/__mail_alias/explorer/aliases | 59 ++++++++++ .../{manifest => explorer/aliases_file} | 38 ++++-- type/__mail_alias/gencode-remote | 108 ++++++++++++++++++ type/__mail_alias/man.rst | 21 +++- type/__mail_alias/parameter/default/state | 1 + type/__mail_alias/parameter/optional | 1 + type/__mail_alias/parameter/optional_multiple | 1 + 7 files changed, 215 insertions(+), 14 deletions(-) create mode 100755 type/__mail_alias/explorer/aliases rename type/__mail_alias/{manifest => explorer/aliases_file} (56%) mode change 100755 => 100644 create mode 100644 type/__mail_alias/parameter/default/state create mode 100644 type/__mail_alias/parameter/optional create mode 100644 type/__mail_alias/parameter/optional_multiple diff --git a/type/__mail_alias/explorer/aliases b/type/__mail_alias/explorer/aliases new file mode 100755 index 0000000..ce1a439 --- /dev/null +++ b/type/__mail_alias/explorer/aliases @@ -0,0 +1,59 @@ +#!/bin/sh -e +# +# 2020 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 . +# +# Find aliases for a given name and print the aliases line separated + +aliases_file=$("${__type_explorer}/aliases_file") +test -r "${aliases_file}" || exit 0 + +name=$__object_id + +awk -F ':[[:blank:]]*' ' +function print_aliases (aliases, matches) { + split(aliases, matches, /,[[:blank:]]*/) + for (i in matches) { + gsub(/^[[:blank:]]*|[[:blank:]]*$/, "", matches[i]) + print matches[i] + } +} + +/^#/ { + # comment + select = 0; cont = 0; next +} + +{ + cont = ($0 ~ /\\$/) + if (cont) sub(/[[:blank:]]*\\$/, "", $0) +} + +/^[[:blank:]]/ || cont { + # continuation line + if (select) print_aliases($0) + next +} + +$1 == ENVIRON["__object_id"] { + select = 1 + print_aliases($2) + next +} + +{ select = 0 } +' "${aliases_file}" diff --git a/type/__mail_alias/manifest b/type/__mail_alias/explorer/aliases_file old mode 100755 new mode 100644 similarity index 56% rename from type/__mail_alias/manifest rename to type/__mail_alias/explorer/aliases_file index e0c809a..f7c4596 --- a/type/__mail_alias/manifest +++ b/type/__mail_alias/explorer/aliases_file @@ -1,6 +1,6 @@ #!/bin/sh -e # -# 2020 Dennis Camera (dennis.camera@ssrq-sds-fds.ch) +# 2020 Dennis Camera (dennis.camera at ssrq-sds-fds.ch) # # This file is part of cdist. # @@ -17,14 +17,36 @@ # You should have received a copy of the GNU General Public License # along with cdist. If not, see . # +# This explorer tries to find the correct aliases file. +found() { echo "$*"; exit 0; } -os=$(cat "$__global/explorer/os") +check_file() { + if test -f "$1" + then + found "$1" + fi +} -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 - ;; +case $("$__explorer/os") +in + (freebsd|openbsd|solaris) + check_file /etc/mail/aliases + + # default + found /etc/mail/aliases + ;; + (debian|devuan|ubuntu) + check_file /etc/aliases + + # default + found /etc/aliases + ;; + (*) + check_file /etc/mail/aliases + check_file /etc/aliases + + # default + found /etc/mail/aliases + ;; esac diff --git a/type/__mail_alias/gencode-remote b/type/__mail_alias/gencode-remote index 77ad9d2..a93dff2 100755 --- a/type/__mail_alias/gencode-remote +++ b/type/__mail_alias/gencode-remote @@ -18,3 +18,111 @@ # along with cdist. If not, see . # +state_should=$(cat "${__object}/parameter/state") + +case $state_should +in + (present) + if cmp "${__object}/explorer/aliases" "${__object}/parameter/alias" + then + # all good! + exit 0 + fi + + echo "set aliases" >>"$__messages_out" + mode=1 + ;; + (absent) + # nothing to do if no aliases found. + test -s "${__object}/explorer/aliases" || exit 0 + + echo "delete aliases" >>"$__messages_out" + mode=0 + ;; + (*) + printf 'Invalid --state given: %s\n' "$state_should" >&2 + exit 1 +esac + +aliases_file=$(cat "${__object}/explorer/aliases_file") + +if test -z "${aliases_file}" +then + echo 'Could not determine aliases file path.' >&2 + exit 1 +fi + +# "export" variables to remote +printf 'mode=%u\n' "${mode}" +printf "aliases_file='%s'\n" "${aliases_file}" + +cat <<'EOF' +awk -F ':[[:blank:]]*' -v mode="${mode}" ' +function sepafter(f, default, _) { + _ = substr($0, length($f) + 1, index(substr($0, length($f)+1), $(f+1)) - 1) + if (_) return _ + else return default +} + +function write_aliases() { + if (aliases_written) return + + printf "%s%s", ENVIRON["__object_id"], sepafter(1, ": ") + while ((getline < aliases_should_file) > 0) { + if (aliases_written) printf ", " + printf "%s", $0 + aliases_written = 1 + } + printf "\n" + close(aliases_should_file) +} + +BEGIN { + aliases_should_file = (ENVIRON["__object"] "/parameter/alias") +} + +/^#/ { + # comment + select = 0; cont = 0 + print + next +} + +{ + cont = ($0 ~ /\\$/) + if (cont) sub(/[[:blank:]]*\\$/, "", $0) +} + +/^[[:blank:]]/ || cont { + # continuation line + if (select) next +} + +$1 == ENVIRON["__object_id"] { + in_list = 1 + if (mode) write_aliases() + next +} + +{ + in_list = 0 + print +} + +END { + # if the last line as an alias definition, the separator will be reused + if (mode && !aliases_written) write_aliases() +} +' <"${aliases_file}" >"${aliases_file}.tmp" || { + echo 'Generating new aliases file failed!' >&2 + exit 1 +} + +if ! cmp "${aliases_file}" "${aliases_file}.tmp" +then + mv "${aliases_file}.tmp" "${aliases_file}" + newaliases +else + rm "${aliases_file}.tmp" +fi +EOF diff --git a/type/__mail_alias/man.rst b/type/__mail_alias/man.rst index d9563a6..d6c7873 100644 --- a/type/__mail_alias/man.rst +++ b/type/__mail_alias/man.rst @@ -3,12 +3,12 @@ cdist-type__mail_alias(7) NAME ---- -cdist-type__mail_alias - TODO +cdist-type__mail_alias - Manage mail aliases. DESCRIPTION ----------- -This space intentionally left blank. +This cdist type allows you to configure mail aliases (/etc/mail/aliases). REQUIRED PARAMETERS @@ -18,7 +18,14 @@ None. OPTIONAL PARAMETERS ------------------- -None. +state + 'present' or 'absent', defaults to 'present' +alias + the aliases where mail for the given user should be redirected to. + This parameter can be specified multiple times to redirect to more than one + recipient. + See the `aliases(5)` man page for the different forms this parameter can + take.. BOOLEAN PARAMETERS @@ -31,13 +38,15 @@ EXAMPLES .. code-block:: sh - # TODO - __mail_alias + # Redirect root mail to a "real" email address + __mail_alias root --alias admin@example.com + # Disable redirection of mail for joe + __mail_alias joe --state absent SEE ALSO -------- -:strong:`TODO`\ (7) +:strong:`aliases`\ (5) AUTHORS diff --git a/type/__mail_alias/parameter/default/state b/type/__mail_alias/parameter/default/state new file mode 100644 index 0000000..e7f6134 --- /dev/null +++ b/type/__mail_alias/parameter/default/state @@ -0,0 +1 @@ +present diff --git a/type/__mail_alias/parameter/optional b/type/__mail_alias/parameter/optional new file mode 100644 index 0000000..ff72b5c --- /dev/null +++ b/type/__mail_alias/parameter/optional @@ -0,0 +1 @@ +state diff --git a/type/__mail_alias/parameter/optional_multiple b/type/__mail_alias/parameter/optional_multiple new file mode 100644 index 0000000..d077ed8 --- /dev/null +++ b/type/__mail_alias/parameter/optional_multiple @@ -0,0 +1 @@ +alias