From 205e256ef646d272bd8854eaed3d1761e8af3126 Mon Sep 17 00:00:00 2001 From: Daniel Heule Date: Mon, 24 Feb 2014 21:42:45 +0100 Subject: [PATCH 01/12] rewrite of __key_value, now support nerarly every value --- cdist/conf/type/__key_value/explorer/state | 70 +++++++++------- cdist/conf/type/__key_value/gencode-remote | 93 +++++++++++++++------- 2 files changed, 108 insertions(+), 55 deletions(-) diff --git a/cdist/conf/type/__key_value/explorer/state b/cdist/conf/type/__key_value/explorer/state index 94a5ea7f..071bc862 100755 --- a/cdist/conf/type/__key_value/explorer/state +++ b/cdist/conf/type/__key_value/explorer/state @@ -1,6 +1,7 @@ #!/bin/sh # # 2011 Steven Armstrong (steven-cdist at armstrong.cc) +# 2014 Daniel Heule (hda at sfs.biz) # # This file is part of cdist. # @@ -18,36 +19,49 @@ # along with cdist. If not, see . # -key="$(cat "$__object/parameter/key" 2>/dev/null \ +export key="$(cat "$__object/parameter/key" 2>/dev/null \ || echo "$__object_id")" -state="$(cat "$__object/parameter/state" 2>/dev/null \ +export state="$(cat "$__object/parameter/state" 2>/dev/null \ || echo "present")" file="$(cat "$__object/parameter/file")" -delimiter="$(cat "$__object/parameter/delimiter")" -value="$(cat "$__object/parameter/value" 2>/dev/null \ +export delimiter="$(cat "$__object/parameter/delimiter")" +export value="$(cat "$__object/parameter/value" 2>/dev/null \ || echo "__CDIST_NOTSET__")" -case "$state" in - absent) - if grep -q -E "^$key$delimiter+" "$file"; then - # if the key exists, with whatever value, we will have to remove it - # so report it as present - echo present - else - # key does not exist - echo absent - fi - ;; - present) - if grep -q -E "^$key$delimiter+$value$" "$file"; then - # key exists and value is same - echo present - elif grep -q -E "^$key$delimiter+" "$file"; then - # key exists, but value is empty or different - echo wrongvalue - else - # key does not exist - echo absent - fi - ;; -esac +awk -f - "$file" <<"AWK_EOF" +BEGIN { + state=ENVIRON["state"] + key=ENVIRON["key"] + delimiter=ENVIRON["delimiter"] + value=ENVIRON["value"] + keydel=key delimiter + line=keydel value + found=0 +} +# enter the main loop +{ + i = index($0,keydel) + if(i == 1) { + found=1 + if(state == "absent") { + # on state absent, only the ocurance is relevant, so exit here + print "present" + exit + } + # Key with separator found + if($0 == line) { + # exact match found, so state is present + print "present" + } + else { + # not value is wrong ... + print "wrongvalue" + } + exit + } +} +END { + if(found == 0) + print "absent" +} +AWK_EOF diff --git a/cdist/conf/type/__key_value/gencode-remote b/cdist/conf/type/__key_value/gencode-remote index b79d9688..0e963b7c 100755 --- a/cdist/conf/type/__key_value/gencode-remote +++ b/cdist/conf/type/__key_value/gencode-remote @@ -2,6 +2,7 @@ # # 2011 Steven Armstrong (steven-cdist at armstrong.cc) # 2012 Nico Schottelius (nico-cdist at schottelius.org) +# 2014 Daniel Heule (hda at sfs.biz) # # This file is part of cdist. # @@ -18,6 +19,7 @@ # You should have received a copy of the GNU General Public License # along with cdist. If not, see . # +#set -x key="$__object_id" [ -f "$__object/parameter/key" ] && key="$(cat "$__object/parameter/key")" @@ -25,39 +27,15 @@ key="$__object_id" state_should="$(cat "$__object/parameter/state")" file="$(cat "$__object/parameter/file")" -delimiter="$(cat "$__object/parameter/delimiter")" -# escape double quotes, as that is what we use ourself below -value_escaped="$(cat "$__object/parameter/value" | sed -e "s/\([\"]\)/\\\\\1/g")" state_is="$(cat "$__object/explorer/state")" [ "$state_is" = "$state_should" ] && exit 0 +# here we check only if the states are valid, let awk do the work ... case "$state_should" in - absent) - # remove lines starting with key - cat << DONE -tmpfile=\$(mktemp ${file}.cdist.XXXXXXXXXX) -# preserve ownership and permissions by copying existing file over tmpfile -cp -p "$file" "\$tmpfile" -sed '/^$key\($delimiter\+\)/d' "$file" > "\$tmpfile" -mv -f "\$tmpfile" "$file" -DONE - ;; - present) + absent|present) case "$state_is" in - absent) - # add new key and value - printf 'echo "%s%s%s" >> "%s"' "$key" "$delimiter" "$value_escaped" "$file" - ;; - wrongvalue) - # change exisiting value - cat << DONE -tmpfile=\$(mktemp ${file}.cdist.XXXXXXXXXX) -# preserve ownership and permissions by copying existing file over tmpfile -cp -p "$file" "\$tmpfile" -sed "s|^$key\($delimiter\+\).*|$key\\1$value_escaped|" "$file" > "\$tmpfile" -mv -f "\$tmpfile" "$file" -DONE + absent|wrongvalue|present) ;; *) echo "Unknown explorer state: $state_is" >&2 @@ -68,3 +46,64 @@ DONE echo "Unknown state: $state_should" >&2 exit 1 esac + +cat <"\$tmpfile" <<"AWK_EOF" +BEGIN { + # import variables in a secure way .. + state=ENVIRON["state"] + key=ENVIRON["key"] + delimiter=ENVIRON["delimiter"] + value=ENVIRON["value"] + keydel=key delimiter + line=keydel value + inserted=0 +} +# enter the main loop +{ + # I dont use regex, this is by design, so we can match against every value without special meanings of chars ... + i = index(\$0,keydel) + if(i == 1) { + if(state == "absent") { + # if absent, simple yump over this line + next + } + else { + inserted=1 + # state is present, so insert correct line here + print line + next + } + } + else { + print \$0 + } +} +END { + if(inserted == 0 && state == "present" ) { + print line + } +} +AWK_EOF +mv -f "\$tmpfile" "$file" +CDIST_HEREDOC_END_HERE_MARKER From 820ed5ae0c8cccc203db2c642af05c763eda0e87 Mon Sep 17 00:00:00 2001 From: Daniel Heule Date: Mon, 24 Feb 2014 23:27:42 +0100 Subject: [PATCH 02/12] added option comment_line to prefix key value with a comment line --- cdist/conf/type/__key_value/gencode-remote | 52 +++++++++++++++---- .../parameter/default/comment_line | 1 + .../conf/type/__key_value/parameter/optional | 1 + 3 files changed, 43 insertions(+), 11 deletions(-) create mode 100644 cdist/conf/type/__key_value/parameter/default/comment_line diff --git a/cdist/conf/type/__key_value/gencode-remote b/cdist/conf/type/__key_value/gencode-remote index 0e963b7c..2fa07f5c 100755 --- a/cdist/conf/type/__key_value/gencode-remote +++ b/cdist/conf/type/__key_value/gencode-remote @@ -47,22 +47,26 @@ case "$state_should" in exit 1 esac -cat < Date: Tue, 25 Feb 2014 11:35:14 +0100 Subject: [PATCH 03/12] updated the man page .... --- cdist/conf/type/__key_value/man.text | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/cdist/conf/type/__key_value/man.text b/cdist/conf/type/__key_value/man.text index 1423fc7d..82bb2fdf 100644 --- a/cdist/conf/type/__key_value/man.text +++ b/cdist/conf/type/__key_value/man.text @@ -25,12 +25,15 @@ delimiter:: OPTIONAL PARAMETERS ------------------- state:: - present or absent, defaults to present. If present, sets the key to value, - if absent, removes the key from the file. + present or absent, defaults to present. If present, sets the key to value, + if absent, removes the key from the file. key:: - The key to change. Defaults to object_id. + The key to change. Defaults to object_id. value:: - The value for the key. Optional if state=absent, required otherwise. + The value for the key. Optional if state=absent, required otherwise. +comment_line:: + If supplied, the comment line is inserted before the line with key and value, + but only if key or value is about to be changed. EXAMPLES @@ -46,13 +49,24 @@ __key_value my-fancy-id --file /etc/login.defs --key SYS_UID_MAX --value 666 \ # Enable packet forwarding __key_value net.ipv4.ip_forward --file /etc/sysctl.conf --value 1 \ - --delimiter '=' + --delimiter ' = ' --comment_line '# my linux kernel should act as a router' # Remove existing key/value __key_value LEGACY_KEY --file /etc/somefile --state absent --delimiter '=' -------------------------------------------------------------------------------- +MORE INFORMATION +---------------- +This type does not use regex to avoid quoting problems. +So you need to specify the key and delimiteri exactly. +Delimiter can be one or more characters. +Due to shell limitations, we have some values which can not be used. +These values are: +__CDIST_HEREDOC_END_HERE_MARKER +__CDIST_INPUT_END_HERE_MARKER + + SEE ALSO -------- - cdist-type(7) From 8d80e52de957c1a12cd48ff4cfe564b86dd21862 Mon Sep 17 00:00:00 2001 From: Daniel Heule Date: Thu, 27 Feb 2014 14:45:19 +0100 Subject: [PATCH 04/12] implemented some suggestions from steven --- cdist/conf/type/__key_value/explorer/state | 36 +++++++-- cdist/conf/type/__key_value/gencode-remote | 81 +++++++++++++++---- cdist/conf/type/__key_value/man.text | 33 ++++++-- cdist/conf/type/__key_value/parameter/boolean | 1 + .../__key_value/parameter/default/comment | 1 + .../conf/type/__key_value/parameter/optional | 2 +- 6 files changed, 124 insertions(+), 30 deletions(-) create mode 100644 cdist/conf/type/__key_value/parameter/boolean create mode 100644 cdist/conf/type/__key_value/parameter/default/comment diff --git a/cdist/conf/type/__key_value/explorer/state b/cdist/conf/type/__key_value/explorer/state index 071bc862..cb7578a5 100755 --- a/cdist/conf/type/__key_value/explorer/state +++ b/cdist/conf/type/__key_value/explorer/state @@ -27,6 +27,11 @@ file="$(cat "$__object/parameter/file")" export delimiter="$(cat "$__object/parameter/delimiter")" export value="$(cat "$__object/parameter/value" 2>/dev/null \ || echo "__CDIST_NOTSET__")" +if [ -f "$__object/parameter/exact_delimiter" ]; then + export exact_delimiter=1 +else + export exact_delimiter=0 +fi awk -f - "$file" <<"AWK_EOF" BEGIN { @@ -34,27 +39,48 @@ BEGIN { key=ENVIRON["key"] delimiter=ENVIRON["delimiter"] value=ENVIRON["value"] - keydel=key delimiter - line=keydel value + exact_delimiter=ENVIRON["exact_delimiter"] found=0 } # enter the main loop { - i = index($0,keydel) + i = index($0,key) if(i == 1) { + delval = substr($0,length(key)+1) + delpos = index(delval,delimiter) + if(delpos > 1) { + spaces = substr(delval,1,delpos-1) + sub(/[ \t]*/,"",spaces) + if( length(spaces) > 0 ) { + # if there are not only spaces between key and delimiter, + # continue since we we are on the wrong line + next + } + if( exact_delimiter == 1) { + # we have key and delimiter, but since additional spaces are not alowed + # return wrongformat + found=1 + print "wrongformat" + exit + } + } found=1 if(state == "absent") { # on state absent, only the ocurance is relevant, so exit here print "present" exit } + linevalue=substr(delval,delpos + length(delimiter)) + if(exact_delimiter == 0){ + #ok, now strip tabs and whitespaces at the beginning of the value + sub(/[ \t]*/,"",linevalue) + } # Key with separator found - if($0 == line) { + if(linevalue == value) { # exact match found, so state is present print "present" } else { - # not value is wrong ... print "wrongvalue" } exit diff --git a/cdist/conf/type/__key_value/gencode-remote b/cdist/conf/type/__key_value/gencode-remote index 2fa07f5c..dc01b645 100755 --- a/cdist/conf/type/__key_value/gencode-remote +++ b/cdist/conf/type/__key_value/gencode-remote @@ -21,21 +21,49 @@ # #set -x -key="$__object_id" -[ -f "$__object/parameter/key" ] && key="$(cat "$__object/parameter/key")" state_should="$(cat "$__object/parameter/state")" - -file="$(cat "$__object/parameter/file")" state_is="$(cat "$__object/explorer/state")" -[ "$state_is" = "$state_should" ] && exit 0 +if [ "$state_is" = "$state_should" ]; then + exit 0 +fi -# here we check only if the states are valid, let awk do the work ... +file="$(cat "$__object/parameter/file")" +key="$__object_id" +[ -f "$__object/parameter/key" ] && key="$(cat "$__object/parameter/key")" +if [ -f "$__object/parameter/exact_delimiter" ]; then + export exact_delimiter=1 +else + export exact_delimiter=0 +fi + +# here we check only if the states are valid, +# emmit messages and +# let awk do the work ... case "$state_should" in - absent|present) + absent) case "$state_is" in - absent|wrongvalue|present) + absent) + # nothing to do + ;; + wrongformat|wrongvalue|present) + echo removed >> "$__messages_out" + ;; + *) + echo "Unknown explorer state: $state_is" >&2 + exit 1 + esac + present) + case "$state_is" in + absent) + echo inserted >> "$__messages_out" + ;; + wrongformated|wrongvalue) + echo changed >> "$__messages_out" + ;; + present) + # nothing to do ;; *) echo "Unknown explorer state: $state_is" >&2 @@ -56,16 +84,20 @@ export key="\$(cat <<"__CDIST_INPUT_END_HERE_MARKER" $key __CDIST_INPUT_END_HERE_MARKER )" -export delimiter="\$(cat <<"__CDIST_INPUT_END_HERE_MARKER" -$(cat "$__object/parameter/delimiter") -__CDIST_INPUT_END_HERE_MARKER -)" export value="\$(cat <<"__CDIST_INPUT_END_HERE_MARKER" $(cat "$__object/parameter/value") __CDIST_INPUT_END_HERE_MARKER )" +export delimiter="\$(cat <<"__CDIST_INPUT_END_HERE_MARKER" +$(cat "$__object/parameter/delimiter") +__CDIST_INPUT_END_HERE_MARKER +)" +export exact_delimiter="\$(cat <<"__CDIST_INPUT_END_HERE_MARKER" +$exact_delimiter +__CDIST_INPUT_END_HERE_MARKER +)" export comment="\$(cat <<"__CDIST_INPUT_END_HERE_MARKER" -$(cat "$__object/parameter/comment_line") +$(cat "$__object/parameter/comment") __CDIST_INPUT_END_HERE_MARKER )" @@ -80,17 +112,33 @@ BEGIN { delimiter=ENVIRON["delimiter"] value=ENVIRON["value"] comment=ENVIRON["comment"] - keydel=key delimiter - line=keydel value + exact_delimiter=ENVIRON["exact_delimiter"] inserted=0 ll="" llpopulated=0 + line=key delimiter value } # enter the main loop { # I dont use regex, this is by design, so we can match against every value without special meanings of chars ... - i = index(\$0,keydel) + i = index(\$0,key) if(i == 1) { + delval = substr(\$0,length(key)+1) + delpos = index(delval,delimiter) + if(delpos > 1) { + spaces = substr(delval,1,delpos-1) + sub(/[ \t]*/,"",spaces) + if( length(spaces) > 0 ) { + # if there are not only spaces between key and delimiter, + # continue since we we are on the wrong line + if(llpopulated == 1) { + print ll + } + ll=\$0 + llpopulated=1 + next + } + } if(state == "absent") { if(ll == comment) { # if comment is present, clear llpopulated flag @@ -136,4 +184,5 @@ END { } AWK_EOF mv -f "\$tmpfile" "$file" +exit 1 __CDIST_HEREDOC_END_HERE_MARKER diff --git a/cdist/conf/type/__key_value/man.text b/cdist/conf/type/__key_value/man.text index 82bb2fdf..95e00ce9 100644 --- a/cdist/conf/type/__key_value/man.text +++ b/cdist/conf/type/__key_value/man.text @@ -31,9 +31,28 @@ key:: The key to change. Defaults to object_id. value:: The value for the key. Optional if state=absent, required otherwise. -comment_line:: - If supplied, the comment line is inserted before the line with key and value, - but only if key or value is about to be changed. +comment:: + If supplied, the value will be inserted before the line with the key, + but only if the key or value must be changed. + You need to ensure yourself that the line is prefixed with the correct + comment sign. (for example # or ; or wathever ..) + + +BOOLEAN PARAMETERS +------------------ +exact_delimiter:: + If supplied, thread additional whitespaces between key, delimiter and value + as wrong value. + + +MESSAGES +-------- +removed:: + Line with key was removed +inserted:: + A new line was inserted +changed:: + An existing line was changed EXAMPLES @@ -58,11 +77,9 @@ __key_value LEGACY_KEY --file /etc/somefile --state absent --delimiter '=' MORE INFORMATION ---------------- -This type does not use regex to avoid quoting problems. -So you need to specify the key and delimiteri exactly. -Delimiter can be one or more characters. -Due to shell limitations, we have some values which can not be used. -These values are: +This type try to handle as many values as possible, so it doen't use regexes. +So you need to exatly specify the key and delimiter. Delimiter can be of any lenght. +Due to shell limitations, we have some values which you can't use, this values are: __CDIST_HEREDOC_END_HERE_MARKER __CDIST_INPUT_END_HERE_MARKER diff --git a/cdist/conf/type/__key_value/parameter/boolean b/cdist/conf/type/__key_value/parameter/boolean new file mode 100644 index 00000000..190831c1 --- /dev/null +++ b/cdist/conf/type/__key_value/parameter/boolean @@ -0,0 +1 @@ +exact_delimiter diff --git a/cdist/conf/type/__key_value/parameter/default/comment b/cdist/conf/type/__key_value/parameter/default/comment new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/cdist/conf/type/__key_value/parameter/default/comment @@ -0,0 +1 @@ + diff --git a/cdist/conf/type/__key_value/parameter/optional b/cdist/conf/type/__key_value/parameter/optional index 8eeebd0c..666be2ae 100644 --- a/cdist/conf/type/__key_value/parameter/optional +++ b/cdist/conf/type/__key_value/parameter/optional @@ -1,4 +1,4 @@ key value state -comment_line +comment From 0198b99eb53819111ebb4362900a761f9c2bb091 Mon Sep 17 00:00:00 2001 From: Daniel Heule Date: Thu, 27 Feb 2014 15:47:19 +0100 Subject: [PATCH 05/12] corrected some debug codesnips --- cdist/conf/type/__key_value/explorer/state | 4 ++++ cdist/conf/type/__key_value/gencode-remote | 5 ++++- cdist/conf/type/__key_value/parameter/default/comment_line | 1 - 3 files changed, 8 insertions(+), 2 deletions(-) delete mode 100644 cdist/conf/type/__key_value/parameter/default/comment_line diff --git a/cdist/conf/type/__key_value/explorer/state b/cdist/conf/type/__key_value/explorer/state index cb7578a5..8bdd3a1d 100755 --- a/cdist/conf/type/__key_value/explorer/state +++ b/cdist/conf/type/__key_value/explorer/state @@ -48,6 +48,10 @@ BEGIN { if(i == 1) { delval = substr($0,length(key)+1) delpos = index(delval,delimiter) + if(delpos == 0) { + # in this case, the delimiter was not found + next + } if(delpos > 1) { spaces = substr(delval,1,delpos-1) sub(/[ \t]*/,"",spaces) diff --git a/cdist/conf/type/__key_value/gencode-remote b/cdist/conf/type/__key_value/gencode-remote index dc01b645..1e1d7c92 100755 --- a/cdist/conf/type/__key_value/gencode-remote +++ b/cdist/conf/type/__key_value/gencode-remote @@ -53,7 +53,9 @@ case "$state_should" in *) echo "Unknown explorer state: $state_is" >&2 exit 1 + ;; esac + ;; present) case "$state_is" in absent) @@ -68,11 +70,13 @@ case "$state_should" in *) echo "Unknown explorer state: $state_is" >&2 exit 1 + ;; esac ;; *) echo "Unknown state: $state_should" >&2 exit 1 + ;; esac cat <<__CDIST_HEREDOC_END_HERE_MARKER @@ -184,5 +188,4 @@ END { } AWK_EOF mv -f "\$tmpfile" "$file" -exit 1 __CDIST_HEREDOC_END_HERE_MARKER diff --git a/cdist/conf/type/__key_value/parameter/default/comment_line b/cdist/conf/type/__key_value/parameter/default/comment_line deleted file mode 100644 index 8b137891..00000000 --- a/cdist/conf/type/__key_value/parameter/default/comment_line +++ /dev/null @@ -1 +0,0 @@ - From 727c918f671620d5beb59da0cf7110a0b77b1e48 Mon Sep 17 00:00:00 2001 From: Daniel Heule Date: Thu, 27 Feb 2014 17:04:23 +0100 Subject: [PATCH 06/12] work around a bug in bash3, now tested with dash, bash, busybox --- cdist/conf/type/__key_value/gencode-remote | 25 ++++++++++------------ 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/cdist/conf/type/__key_value/gencode-remote b/cdist/conf/type/__key_value/gencode-remote index 1e1d7c92..62cc745d 100755 --- a/cdist/conf/type/__key_value/gencode-remote +++ b/cdist/conf/type/__key_value/gencode-remote @@ -80,30 +80,27 @@ case "$state_should" in esac cat <<__CDIST_HEREDOC_END_HERE_MARKER -export state="\$(cat <<"__CDIST_INPUT_END_HERE_MARKER" +IFS='\n' read -r state <<'__CDIST_INPUT_END_HERE_MARKER' $state_should __CDIST_INPUT_END_HERE_MARKER -)" -export key="\$(cat <<"__CDIST_INPUT_END_HERE_MARKER" +export state +IFS='\n' read -r key <<'__CDIST_INPUT_END_HERE_MARKER' $key __CDIST_INPUT_END_HERE_MARKER -)" -export value="\$(cat <<"__CDIST_INPUT_END_HERE_MARKER" +export key +IFS='\n' read -r value <<'__CDIST_INPUT_END_HERE_MARKER' $(cat "$__object/parameter/value") __CDIST_INPUT_END_HERE_MARKER -)" -export delimiter="\$(cat <<"__CDIST_INPUT_END_HERE_MARKER" +export value +IFS='\n' read -r delimiter <<'__CDIST_INPUT_END_HERE_MARKER' $(cat "$__object/parameter/delimiter") __CDIST_INPUT_END_HERE_MARKER -)" -export exact_delimiter="\$(cat <<"__CDIST_INPUT_END_HERE_MARKER" -$exact_delimiter -__CDIST_INPUT_END_HERE_MARKER -)" -export comment="\$(cat <<"__CDIST_INPUT_END_HERE_MARKER" +export delimiter +IFS='\n' read -r comment <<'__CDIST_INPUT_END_HERE_MARKER' $(cat "$__object/parameter/comment") __CDIST_INPUT_END_HERE_MARKER -)" +export comment +export exact_delimiter="$exact_delimiter" tmpfile=\$(mktemp "${file}.cdist.XXXXXXXXXX") # preserve ownership and permissions by copying existing file over tmpfile From fa55cd7d3bd391e16903f9ba930aa7842f8fea65 Mon Sep 17 00:00:00 2001 From: Daniel Heule Date: Thu, 27 Feb 2014 21:08:45 +0100 Subject: [PATCH 07/12] ups, typo ... thx to steven --- cdist/conf/type/__key_value/man.text | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cdist/conf/type/__key_value/man.text b/cdist/conf/type/__key_value/man.text index 95e00ce9..dabfe928 100644 --- a/cdist/conf/type/__key_value/man.text +++ b/cdist/conf/type/__key_value/man.text @@ -41,7 +41,7 @@ comment:: BOOLEAN PARAMETERS ------------------ exact_delimiter:: - If supplied, thread additional whitespaces between key, delimiter and value + If supplied, treat additional whitespaces between key, delimiter and value as wrong value. From 38c3d551baa512b0d6d56356f6ddd1920908ef5b Mon Sep 17 00:00:00 2001 From: Daniel Heule Date: Tue, 11 Mar 2014 21:05:31 +0100 Subject: [PATCH 08/12] bugfix, if file was absent and type is now tested on openwrt --- cdist/conf/type/__key_value/explorer/state | 6 ++++++ cdist/conf/type/__key_value/gencode-remote | 11 +++++++++-- cdist/conf/type/__key_value/man.text | 2 ++ 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/cdist/conf/type/__key_value/explorer/state b/cdist/conf/type/__key_value/explorer/state index 8bdd3a1d..6dfb2031 100755 --- a/cdist/conf/type/__key_value/explorer/state +++ b/cdist/conf/type/__key_value/explorer/state @@ -24,6 +24,12 @@ export key="$(cat "$__object/parameter/key" 2>/dev/null \ export state="$(cat "$__object/parameter/state" 2>/dev/null \ || echo "present")" file="$(cat "$__object/parameter/file")" + +if [ ! -f "$file" ]; then + echo "nosuchfile" + exit +fi + export delimiter="$(cat "$__object/parameter/delimiter")" export value="$(cat "$__object/parameter/value" 2>/dev/null \ || echo "__CDIST_NOTSET__")" diff --git a/cdist/conf/type/__key_value/gencode-remote b/cdist/conf/type/__key_value/gencode-remote index 62cc745d..ad216f51 100755 --- a/cdist/conf/type/__key_value/gencode-remote +++ b/cdist/conf/type/__key_value/gencode-remote @@ -44,7 +44,7 @@ fi case "$state_should" in absent) case "$state_is" in - absent) + absent|nosuchfile) # nothing to do ;; wrongformat|wrongvalue|present) @@ -58,6 +58,9 @@ case "$state_should" in ;; present) case "$state_is" in + nosuchfile) + echo created >> "$__messages_out" + ;; absent) echo inserted >> "$__messages_out" ;; @@ -104,7 +107,11 @@ export exact_delimiter="$exact_delimiter" tmpfile=\$(mktemp "${file}.cdist.XXXXXXXXXX") # preserve ownership and permissions by copying existing file over tmpfile -cp -p "$file" "\$tmpfile" +if [ -f "$file" ]; then + cp -p "$file" "\$tmpfile" +else + touch "$file" +fi awk -f - "$file" >"\$tmpfile" <<"AWK_EOF" BEGIN { # import variables in a secure way .. diff --git a/cdist/conf/type/__key_value/man.text b/cdist/conf/type/__key_value/man.text index dabfe928..de2d7d65 100644 --- a/cdist/conf/type/__key_value/man.text +++ b/cdist/conf/type/__key_value/man.text @@ -53,6 +53,8 @@ inserted:: A new line was inserted changed:: An existing line was changed +created:: + A new line was inserted in a new file EXAMPLES From 619076bd2da618d51c7a95afd8adcd5a009a0f5a Mon Sep 17 00:00:00 2001 From: Daniel Heule Date: Wed, 12 Mar 2014 20:16:33 +0100 Subject: [PATCH 09/12] corrected a small relict in example --- cdist/conf/type/__key_value/man.text | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cdist/conf/type/__key_value/man.text b/cdist/conf/type/__key_value/man.text index bbfd4d48..cf779037 100644 --- a/cdist/conf/type/__key_value/man.text +++ b/cdist/conf/type/__key_value/man.text @@ -70,7 +70,7 @@ __key_value my-fancy-id --file /etc/login.defs --key SYS_UID_MAX --value 666 \ # Enable packet forwarding __key_value net.ipv4.ip_forward --file /etc/sysctl.conf --value 1 \ - --delimiter ' = ' --comment_line '# my linux kernel should act as a router' + --delimiter ' = ' --comment '# my linux kernel should act as a router' # Remove existing key/value __key_value LEGACY_KEY --file /etc/somefile --state absent --delimiter '=' From b7fb973fa5de1e2fc2bdc8f1fdb46572b6416d10 Mon Sep 17 00:00:00 2001 From: Daniel Heule Date: Fri, 21 Mar 2014 09:35:47 +0100 Subject: [PATCH 10/12] bugfix for whitespace stripping, its no more simple --- cdist/conf/type/__key_value/explorer/state | 4 +- .../type/__key_value/files/remote_script.sh | 104 +++++++++++++++ cdist/conf/type/__key_value/gencode-remote | 121 +----------------- 3 files changed, 107 insertions(+), 122 deletions(-) create mode 100644 cdist/conf/type/__key_value/files/remote_script.sh diff --git a/cdist/conf/type/__key_value/explorer/state b/cdist/conf/type/__key_value/explorer/state index 6dfb2031..b990733d 100755 --- a/cdist/conf/type/__key_value/explorer/state +++ b/cdist/conf/type/__key_value/explorer/state @@ -21,8 +21,8 @@ export key="$(cat "$__object/parameter/key" 2>/dev/null \ || echo "$__object_id")" -export state="$(cat "$__object/parameter/state" 2>/dev/null \ - || echo "present")" +export state="$(cat "$__object/parameter/state")" + file="$(cat "$__object/parameter/file")" if [ ! -f "$file" ]; then diff --git a/cdist/conf/type/__key_value/files/remote_script.sh b/cdist/conf/type/__key_value/files/remote_script.sh new file mode 100644 index 00000000..2ed43366 --- /dev/null +++ b/cdist/conf/type/__key_value/files/remote_script.sh @@ -0,0 +1,104 @@ +#!/bin/sh + +export key="$(cat "$__object/parameter/key" 2>/dev/null \ + || echo "$__object_id")" +export state="$(cat "$__object/parameter/state")" + +file="$(cat "$__object/parameter/file")" + +export delimiter="$(cat "$__object/parameter/delimiter")" +export value="$(cat "$__object/parameter/value" 2>/dev/null \ + || echo "__CDIST_NOTSET__")" +if [ -f "$__object/parameter/exact_delimiter" ]; then + export exact_delimiter=1 +else + export exact_delimiter=0 +fi + +tmpfile=$(mktemp "${file}.cdist.XXXXXXXXXX") +# preserve ownership and permissions by copying existing file over tmpfile +if [ -f "$file" ]; then + cp -p "$file" "$tmpfile" +else + touch "$file" +fi +awk -f - "$file" >"$tmpfile" <<"AWK_EOF" +BEGIN { + # import variables in a secure way .. + state=ENVIRON["state"] + key=ENVIRON["key"] + delimiter=ENVIRON["delimiter"] + value=ENVIRON["value"] + comment=ENVIRON["comment"] + exact_delimiter=ENVIRON["exact_delimiter"] + inserted=0 + ll="" + llpopulated=0 + line=key delimiter value +} +# enter the main loop +{ + # I dont use regex, this is by design, so we can match against every value without special meanings of chars ... + i = index($0,key) + if(i == 1) { + delval = substr($0,length(key)+1) + delpos = index(delval,delimiter) + if(delpos > 1) { + spaces = substr(delval,1,delpos-1) + sub(/[ \t]*/,"",spaces) + if( length(spaces) > 0 ) { + # if there are not only spaces between key and delimiter, + # continue since we we are on the wrong line + if(llpopulated == 1) { + print ll + } + ll=$0 + llpopulated=1 + next + } + } + if(state == "absent") { + if(ll == comment) { + # if comment is present, clear llpopulated flag + llpopulated=0 + } + # if absent, simple yump over this line + next + } + else { + # if comment is present and not present in last line + if (llpopulated == 1) { + print ll + if( comment != "" && ll != comment) { + print comment + } + llpopulated=0 + } + inserted=1 + # state is present, so insert correct line here + print line + ll=line + next + } + } + else { + if(llpopulated == 1) { + print ll + } + ll=$0 + llpopulated=1 + } +} +END { + if(llpopulated == 1) { + print ll + } + if(inserted == 0 && state == "present" ) { + if(comment != "" && ll != comment){ + print comment + } + print line + } +} +AWK_EOF +mv -f "$tmpfile" "$file" diff --git a/cdist/conf/type/__key_value/gencode-remote b/cdist/conf/type/__key_value/gencode-remote index f1744ac1..e6815cb6 100755 --- a/cdist/conf/type/__key_value/gencode-remote +++ b/cdist/conf/type/__key_value/gencode-remote @@ -28,15 +28,6 @@ if [ "$state_is" = "$state_should" ]; then exit 0 fi -file="$(cat "$__object/parameter/file")" -key="$__object_id" -[ -f "$__object/parameter/key" ] && key="$(cat "$__object/parameter/key")" -if [ -f "$__object/parameter/exact_delimiter" ]; then - export exact_delimiter=1 -else - export exact_delimiter=0 -fi - # here we check only if the states are valid, # emmit messages and # let awk do the work ... @@ -81,114 +72,4 @@ case "$state_should" in ;; esac -cat <<__CDIST_HEREDOC_END_HERE_MARKER -IFS='\n' read -r state <<'__CDIST_INPUT_END_HERE_MARKER' -$state_should -__CDIST_INPUT_END_HERE_MARKER -export state -IFS='\n' read -r key <<'__CDIST_INPUT_END_HERE_MARKER' -$key -__CDIST_INPUT_END_HERE_MARKER -export key -IFS='\n' read -r value <<'__CDIST_INPUT_END_HERE_MARKER' -$(cat "$__object/parameter/value") -__CDIST_INPUT_END_HERE_MARKER -export value -IFS='\n' read -r delimiter <<'__CDIST_INPUT_END_HERE_MARKER' -$(cat "$__object/parameter/delimiter") -__CDIST_INPUT_END_HERE_MARKER -export delimiter -IFS='\n' read -r comment <<'__CDIST_INPUT_END_HERE_MARKER' -$(cat "$__object/parameter/comment") -__CDIST_INPUT_END_HERE_MARKER -export comment -export exact_delimiter="$exact_delimiter" - -tmpfile=\$(mktemp "${file}.cdist.XXXXXXXXXX") -# preserve ownership and permissions by copying existing file over tmpfile -if [ -f "$file" ]; then - cp -p "$file" "\$tmpfile" -else - touch "$file" -fi -awk -f - "$file" >"\$tmpfile" <<"AWK_EOF" -BEGIN { - # import variables in a secure way .. - state=ENVIRON["state"] - key=ENVIRON["key"] - delimiter=ENVIRON["delimiter"] - value=ENVIRON["value"] - comment=ENVIRON["comment"] - exact_delimiter=ENVIRON["exact_delimiter"] - inserted=0 - ll="" - llpopulated=0 - line=key delimiter value -} -# enter the main loop -{ - # I dont use regex, this is by design, so we can match against every value without special meanings of chars ... - i = index(\$0,key) - if(i == 1) { - delval = substr(\$0,length(key)+1) - delpos = index(delval,delimiter) - if(delpos > 1) { - spaces = substr(delval,1,delpos-1) - sub(/[ \t]*/,"",spaces) - if( length(spaces) > 0 ) { - # if there are not only spaces between key and delimiter, - # continue since we we are on the wrong line - if(llpopulated == 1) { - print ll - } - ll=\$0 - llpopulated=1 - next - } - } - if(state == "absent") { - if(ll == comment) { - # if comment is present, clear llpopulated flag - llpopulated=0 - } - # if absent, simple yump over this line - next - } - else { - # if comment is present and not present in last line - if (llpopulated == 1) { - print ll - if( comment != "" && ll != comment) { - print comment - } - llpopulated=0 - } - inserted=1 - # state is present, so insert correct line here - print line - ll=line - next - } - } - else { - if(llpopulated == 1) { - print ll - } - ll=\$0 - llpopulated=1 - } -} -END { - if(llpopulated == 1) { - print ll - } - if(inserted == 0 && state == "present" ) { - if(comment != "" && ll != comment){ - print comment - } - print line - } -} -AWK_EOF -mv -f "\$tmpfile" "$file" -__CDIST_HEREDOC_END_HERE_MARKER +cat "$__type/files/remote_script.sh" From bae472eb33095dcad9cd032cc3a19345155565bd Mon Sep 17 00:00:00 2001 From: Daniel Heule Date: Wed, 26 Mar 2014 10:41:00 +0100 Subject: [PATCH 11/12] fixed some typos in the man page --- cdist/conf/type/__key_value/man.text | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/cdist/conf/type/__key_value/man.text b/cdist/conf/type/__key_value/man.text index cf779037..d4c8e2cc 100644 --- a/cdist/conf/type/__key_value/man.text +++ b/cdist/conf/type/__key_value/man.text @@ -79,11 +79,8 @@ __key_value LEGACY_KEY --file /etc/somefile --state absent --delimiter '=' MORE INFORMATION ---------------- -This type try to handle as many values as possible, so it doen't use regexes. -So you need to exatly specify the key and delimiter. Delimiter can be of any lenght. -Due to shell limitations, we have some values which you can't use, this values are: -__CDIST_HEREDOC_END_HERE_MARKER -__CDIST_INPUT_END_HERE_MARKER +This type try to handle as many values as possible, so it doesn't use regexes. +So you need to exactly specify the key and delimiter. Delimiter can be of any lenght. SEE ALSO From 50316902e3d7fecbd39b4fa31b7aa5b3f5f4eaf2 Mon Sep 17 00:00:00 2001 From: Daniel Heule Date: Wed, 26 Mar 2014 13:58:29 +0100 Subject: [PATCH 12/12] renamed ll to lastline, hope its now clear what the var is for .. --- .../type/__key_value/files/remote_script.sh | 44 +++++++++---------- 1 file changed, 21 insertions(+), 23 deletions(-) diff --git a/cdist/conf/type/__key_value/files/remote_script.sh b/cdist/conf/type/__key_value/files/remote_script.sh index 2ed43366..282ba531 100644 --- a/cdist/conf/type/__key_value/files/remote_script.sh +++ b/cdist/conf/type/__key_value/files/remote_script.sh @@ -1,5 +1,3 @@ -#!/bin/sh - export key="$(cat "$__object/parameter/key" 2>/dev/null \ || echo "$__object_id")" export state="$(cat "$__object/parameter/state")" @@ -32,8 +30,8 @@ BEGIN { comment=ENVIRON["comment"] exact_delimiter=ENVIRON["exact_delimiter"] inserted=0 - ll="" - llpopulated=0 + lastline="" + lastlinepopulated=0 line=key delimiter value } # enter the main loop @@ -49,52 +47,52 @@ BEGIN { if( length(spaces) > 0 ) { # if there are not only spaces between key and delimiter, # continue since we we are on the wrong line - if(llpopulated == 1) { - print ll + if(lastlinepopulated == 1) { + print lastline } - ll=$0 - llpopulated=1 + lastline=$0 + lastlinepopulated=1 next } } if(state == "absent") { - if(ll == comment) { - # if comment is present, clear llpopulated flag - llpopulated=0 + if(lastline == comment) { + # if comment is present, clear lastlinepopulated flag + lastlinepopulated=0 } # if absent, simple yump over this line next } else { # if comment is present and not present in last line - if (llpopulated == 1) { - print ll - if( comment != "" && ll != comment) { + if (lastlinepopulated == 1) { + print lastline + if( comment != "" && lastline != comment) { print comment } - llpopulated=0 + lastlinepopulated=0 } inserted=1 # state is present, so insert correct line here print line - ll=line + lastline=line next } } else { - if(llpopulated == 1) { - print ll + if(lastlinepopulated == 1) { + print lastline } - ll=$0 - llpopulated=1 + lastline=$0 + lastlinepopulated=1 } } END { - if(llpopulated == 1) { - print ll + if(lastlinepopulated == 1) { + print lastline } if(inserted == 0 && state == "present" ) { - if(comment != "" && ll != comment){ + if(comment != "" && lastline != comment){ print comment } print line