#!/bin/sh # Copyright (c) 2017 Markus Weippert # GNU General Public License v3.0 (see https://www.gnu.org/licenses/gpl-3.0.txt) [ $# -le 1 ] || { _script="$1"; shift; } _params="$1" . /usr/share/libubox/jshn.sh _ANSIBLE_PARAMS=" _ansible_version/s _ansible_no_log/b _ansible_module_name/s _ansible_syslog_facility/s _ansible_socket/s _ansible_verbosity/i _ansible_diff/b _ansible_debug/b _ansible_check_mode/b " FILE_PARAMS="group/s mode/s owner/s follow/b" CHANGED="" FACT_VARS="" JSON_PREFIX="" MESSAGE="" NO_EXIT_JSON="" PARAMS="" RESPONSE_VARS="" SKIPPED="" SUPPORTS_CHECK_MODE="1" WANT_JSON="" N=" " T=" " init() { :; } main() { :; } cleanup() { :; } _exit_add_vars() { local _var _name _type _always _value _IFS for _var; do _IFS="$IFS"; IFS="/"; set -- $_var; IFS="$_IFS" _var="$1"; _type="$(_map_type "$2")"; _always="$3" _IFS="$IFS"; IFS="="; set -- $_var; IFS="$_IFS" _name="$1"; _var="${2:-$_name}" eval "_value=\"\$$_var\"" [ -z "$_value" -a -z "$_always" ] || eval "json_add_$_type \"\$_name\" \"\$_value\"" done } _init_done="" _exit() { local _rc="$?" local _v _k [ -z "$_init_done" ] || cleanup "$_rc" || : [ -z "$NO_EXIT_JSON" ] || return $_rc json_set_namespace result json_add_boolean changed $([ -z "$CHANGED" ]; echo $?) json_add_boolean failed $([ $_rc -eq 0 ]; echo $?) [ -z "$SKIPPED" ] || json_add_boolean skipped 1 [ -z "$MESSAGE" ] || json_add_string msg "$MESSAGE" [ -z "$_init_done" ] || { [ -z "$RESPONSE_VARS" ] || _exit_add_vars $RESPONSE_VARS [ -z "$FACT_VARS" ] || { json_add_object ansible_facts _exit_add_vars "$FACT_VARS" json_close_object } } [ -z "$_ansible_diff" -o -z "$_diff_set" ] || { json_add_object diff json_add_string before "$_diff_before${_diff_before:+$N}" json_add_string after "$_diff_after${_diff_after:+$N}" [ -z "$_diff_before_header" ] || json_add_string before_header "$_diff_before_header" [ -z "$_diff_after_header" ] || json_add_string after_header "$_diff_after_header" json_close_object } echo; json_dump json_cleanup return $_rc } trap _exit EXIT _map_type() { [ -n "$1" ] || { echo "string"; return 0; } case "$1" in any) echo "any";; s|str|string) echo "string";; i|int|integer) echo "int";; b|bool|boolean) echo "boolean";; f|d|float|double) echo "double";; l|a|list|array) echo "array";; o|h|obj|object|hash|map) echo "object";; *) fail "unknown type: $1";; esac } _verify_value_type() { local _value="$1" local _type="$2" case "$_type" in int) printf "%d" "$_value" >/dev/null 2>&1 || return 1;; double) printf "%f" "$_value" >/dev/null 2>&1 || return 1;; boolean) case "$_value" in yes|true|True|1) _value="1";; no|false|False|0) _value="";; *) return 1;; esac;; esac echo "$_value" } _parse_legacy_params() { local _var _type _required _default _alias local _param _value _IFS for _param in $PARAMS; do eval "${_param%%[/=]*}=\"\"" done eval "$(cat "$_params")" || fail "could not parse params" for _param in $PARAMS $_ANSIBLE_PARAMS; do _value=""; _IFS="$IFS"; IFS="/"; set -- $_param; IFS="$_IFS" _var="$1"; _type="$(_map_type "$2")"; _required="$3"; _default="$4" _IFS="$IFS"; IFS="="; set -- $_var; IFS="$_IFS"; _var="$1" for _alias; do eval "_value=\"\$$_alias\"" [ -z "$_value" ] || break done eval "export -- _orig_$_var=\"\$_value\"" [ -z "$_value" ] && { [ -z "$_required" ] || fail "$_var is required" [ -z "$_default" ] || _value="$(_verify_value_type "$_default" "$_type")" } || { _value="$(_verify_value_type "$_value" "$_type")" || fail "$_var must be $_type" } eval "export -- $_var=\"\$_value\" _type_$_var=\"\$_type\"" done return 0 } _parse_json_params() { local _var _type _required _default _alias local _param _value _found _is_type _IFS json_set_namespace params json_load "$(cat -- "$_params")" || fail "could not parse params" for _param in $PARAMS $_ANSIBLE_PARAMS; do _value=""; _IFS="$IFS"; IFS="/"; set -- $_param; IFS="$_IFS" _var="$1"; _type="$(_map_type "$2")"; _required="$3"; _default="$4" _IFS="$IFS"; IFS="="; set -- $_var; IFS="$_IFS"; _var="$1" _is_type=""; _found="" for _alias; do json_get_type _is_type "$_alias" && json_get_var _value "$_alias" || continue _found="1"; break done eval "export -- _orig_$_var=\"\$_value\" _defined_$_var=\"$_found\"" [ -n "$_found" ] || { [ -z "$_required" ] || fail "$_var is required" [ -z "$_default" ] || _value="$(_verify_value_type "$_default" "$_type")" } case "$_is_type" in array|object) [ "$_type" = "$_is_type" -o "$_type" = "any" ] || fail "$_var must be $_type" eval "export -- _type_${_var}=\"\$_is_type\"" json_add_string "_$_var" "$_alias";; *) [ -z "$_found" ] || _value="$(_verify_value_type "$_value" "$_type")" || fail "$_var must be $_type" eval "export -- $_var=\"\$_value\" _type_$_var=\"\$_type\"" json_add_string "$_var" "$_value";; esac done return 0 } _parse_params() { [ -n "$WANT_JSON" ] && _parse_json_params || _parse_legacy_params } _support_check_mode() { [ -n "$_ansible_check_mode" -a -z "$SUPPORTS_CHECK_MODE" ] || return 0 SKIPPED="1" MESSAGE="module does not support check mode" exit 0 } json_select_real() { local real_var json_get_var real_var "_$1" json_select "$real_var" } changed() { CHANGED="1" } fail() { MESSAGE="$*" exit 1 } _result="" try() { [ $# -eq 1 ] && { _result="$(eval "$1" 2>&1)" || fail "$*: $_result" } || { _result="$("$@" 2>&1)" || fail "$*: $_result" } } final() { try "$@" exit 0 } _diff_set="" _diff_before="" _diff_after="" _diff_before_header="" _diff_after_header="" set_diff() { _diff_before="${1:-$_diff_before}" _diff_after="${2:-$_diff_after}" _diff_before_header="${3:-$_diff_before_header}" _diff_after_header="${4:-$_diff_after_header}" _diff_set="1" } _get_file_attributes() { local R="${2:+Ra}" ls -l${R:-d} -- "$1" 2>/dev/null | md5 } set_file_attributes() { [ -z "$_ansible_check_mode" ] || return 0 [ "$mode" != "False" ] || mode="" [ -n "$owner" -o -n "$group" -o -n "$mode" ] || return 0 local file="$1" local R="${2:+-R }" local result h local before="$(_get_file_attributes "$@")" ! result="$(printf "%04o" "$mode" 2>/dev/null)" || mode="$result" [ -z "$follow" ] && h="-h " || h="" [ -z "$owner" ] || result="$(chown $h$R"$owner" -- "$file" 2>&1)" || fail "chown ($file) failed: $result" [ -z "$group" ] || result="$(chgrp $h$R"$group" -- "$file" 2>&1)" || fail "chgrp ($file) failed: $result" [ -z "$follow" -a -h "$file" ] || [ -z "$mode" ] || result="$(chmod $R"$mode" -- "$file" 2>&1)" || fail "chmod ($file) failed: $result" [ "$before" = "$(_get_file_attributes "$@")" ] || changed } is_abs() { [ "${1#/}" != "$1" ] } abspath() { local dir="$(dirname -- "$1")" local file="$(basename -- "$1")" local P="${2:+ -P}" [ -d "$dir" ] && dir="$(cd -- "$dir" && pwd$P)" || is_abs "$dir" || dir="$(pwd$P)/$dir" echo "${dir:+$dir/}$file" } realpath() { local f="$(abspath "$1" x)" local tmp while [ -h "$f" ]; do tmp="$(readlink -- "$f")" is_abs "$tmp" || tmp="$(dirname -- "$f")/$tmp" f="$(abspath "$tmp" x)" done echo "$f" } backup_local() { local src="$1" local dest [ ! -e "$src" ] || { dest="$src.$$.$(date "+%Y-%m-%d@%H:%M:%S~")" try cp -a -- "$src" "$dest" echo "$dest" } } dgst() { local alg="$1" local cmd checksum shift case "$alg" in sha1|sha224|sha256|sha384|sha512|md5) cmd="${alg}sum" ! type "$cmd" >/dev/null 2>&1 || { checksum="$($cmd -- "$@")" echo "${checksum%% *}" return 0 } ! type openssl >/dev/null 2>&1 || { checksum="$(openssl dgst -hex -$alg "$@")" echo "${checksum##*= }" return 0 } return 1;; *) fail "Unknown checksum algorithm '$alg'.";; esac } md5() { dgst md5 "$@" } base64() { ! which base64 >/dev/null 2>&1 || { try command base64 "$1"; echo "$_result"; return 0; } ! type openssl >/dev/null 2>&1 || { try openssl base64 -in "$1"; echo "$_result"; return 0; } hexdump -e '16/1 "%02x" "\n"' -- "$1" | awk ' BEGIN { b64="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" } { for(c=1; c<=length($0); c++) { d=index("0123456789abcdef",substr($0,c,1)); if(d--) { for(b=1; b<=4; b++) { o=o*2+int(d/8); d=(d*2)%16; if(!(++obc%6)) { line=line""substr(b64,o+1,1); o=0; if(++rc>75) { print line; line=""; rc=0; } } } } } } END { if(obc%6) { while(obc++%6) { o=o*2; } line=line""substr(b64,o+1,1); } while(obc%8||obc%6) { if(!(++obc%6)) { line=line"="; } } print line; } ' } json_set_namespace result json_init . "$_script" _parse_params _support_check_mode init || fail "module init failed" _init_done="1" main