forked from ungleich-public/cdist
[type/__uci_section] Only generate UCI commands if state differs
This commit is contained in:
parent
9d40500570
commit
ade69729dd
4 changed files with 160 additions and 29 deletions
|
@ -25,4 +25,24 @@ section=$("${__type_explorer:?}/match")
|
|||
test -n "${section}" || exit 0
|
||||
|
||||
uci -s -N -d "${RS}" show "${section}" 2>/dev/null \
|
||||
| grep -v -e "^${section}=" || true
|
||||
| awk -v VSEP="${RS}" '
|
||||
{
|
||||
# Strip off the config and section parts
|
||||
is_opt = sub(/^([^.]*\.){2}/, "")
|
||||
|
||||
if (!is_opt) {
|
||||
# this line represents the section -> skip
|
||||
next
|
||||
}
|
||||
|
||||
if (index($0, VSEP)) {
|
||||
# Put values each on a line, like --option and --list parameters
|
||||
opt = substr($0, 1, index($0, "=") - 1)
|
||||
split(substr($0, length(opt) + 2), values, VSEP)
|
||||
for (i in values) {
|
||||
printf "%s=%s\n", opt, values[i]
|
||||
}
|
||||
} else {
|
||||
print
|
||||
}
|
||||
}'
|
||||
|
|
|
@ -6,14 +6,6 @@ grep_line() {
|
|||
{ shift; printf '%s\n' "$@"; } | grep -qxF "$1"
|
||||
}
|
||||
|
||||
prefix_lines() {
|
||||
while test $# -gt 0
|
||||
do
|
||||
echo "$2" | awk -v prefix="$1" '$0 { printf "%s %s\n", prefix, $0 }'
|
||||
shift; shift
|
||||
done
|
||||
}
|
||||
|
||||
print_errors() {
|
||||
awk -v prefix="${1:-Found errors:}" -v suffix="${2-}" '
|
||||
BEGIN {
|
||||
|
|
91
cdist/conf/type/__uci_section/files/option_state.awk
Normal file
91
cdist/conf/type/__uci_section/files/option_state.awk
Normal file
|
@ -0,0 +1,91 @@
|
|||
# -*- mode: awk; indent-tabs-mode:t -*-
|
||||
# Usage: awk -f option_state.awk option_type option_name
|
||||
# e.g. awk -f option_state.awk option title
|
||||
# awk -f option_state.awk list entry
|
||||
|
||||
function unquote(s) {
|
||||
# simplified dequoting of single quoted strings
|
||||
if (s ~ /^'.*'$/) {
|
||||
s = substr(s, 2, length(s) - 2)
|
||||
sub(/'\\''/, "'", s)
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
function valueof(line) {
|
||||
if (line !~ /^[[:alpha:]_]+=/) return 0
|
||||
return unquote(substr(line, index(line, "=") + 1))
|
||||
}
|
||||
|
||||
BEGIN {
|
||||
__object = ENVIRON["__object"]
|
||||
if (!__object) exit 1
|
||||
|
||||
opttype = ARGV[1]
|
||||
optname = ARGV[2]
|
||||
|
||||
if (opttype !~ /^(option|list)/ || !optname) {
|
||||
print "invalid"
|
||||
exit (e=1)
|
||||
}
|
||||
|
||||
ARGV[1] = __object "/parameter/" opttype
|
||||
ARGV[2] = __object "/explorer/options"
|
||||
|
||||
state = "present"
|
||||
}
|
||||
|
||||
NR == FNR {
|
||||
# memoize "should" state
|
||||
if (index($0, optname "=") == 1) {
|
||||
should[++should_count] = valueof($0)
|
||||
}
|
||||
|
||||
# go to next line (important!)
|
||||
next
|
||||
}
|
||||
|
||||
{
|
||||
# compare "is" state
|
||||
if (index($0, optname "=") != 1)
|
||||
next
|
||||
++is_count
|
||||
|
||||
v = valueof($0)
|
||||
|
||||
if (v == should[is_count]) {
|
||||
# looks good, but can't say definitely just from this line
|
||||
} else if (is_count > should_count) {
|
||||
# there are more "is" records than "should" -> definitely different
|
||||
state = "different"
|
||||
exit
|
||||
} else {
|
||||
# see if we can find the "is" value somewhere in "should"
|
||||
for (i in should) {
|
||||
if (v == should[i]) {
|
||||
# value found -> could be rearranged
|
||||
# FIXME: Duplicate values are not properly handled here. Do they matter?
|
||||
state = "rearranged"
|
||||
next
|
||||
}
|
||||
}
|
||||
|
||||
# "is" value could not be found in "should" -> definitely different
|
||||
state = "different"
|
||||
exit
|
||||
}
|
||||
}
|
||||
|
||||
END {
|
||||
if (e) exit
|
||||
|
||||
if (!is_count) {
|
||||
# no "is" values -> absent
|
||||
state = "absent"
|
||||
} else if (is_count < should_count) {
|
||||
# "is" was shorter than "should" -> different
|
||||
state = "different"
|
||||
}
|
||||
|
||||
print state
|
||||
}
|
|
@ -70,7 +70,8 @@ in
|
|||
fi
|
||||
|
||||
# Make sure the section itself is present
|
||||
if test "${state_is}" = absent
|
||||
if test "${state_is}" = absent \
|
||||
|| test "${type_is}" != "${type_should#*.}"
|
||||
then
|
||||
printf 'set %s\n' "${section}" >>"${__messages_out:?}"
|
||||
# shellcheck disable=SC2140
|
||||
|
@ -78,7 +79,7 @@ in
|
|||
fi
|
||||
|
||||
# Delete options/lists not in "should"
|
||||
sed -e 's/=.*$//;s/^.*\.//' "${__object:?}/explorer/options" \
|
||||
sed -e 's/=.*$//' "${__object:?}/explorer/options" \
|
||||
| while read -r _optname
|
||||
do
|
||||
grep_line "${_optname}" "${listnames_should}" "${optnames_should}" || {
|
||||
|
@ -87,18 +88,55 @@ in
|
|||
} </dev/null
|
||||
done
|
||||
|
||||
# Set "should" options
|
||||
prefix_lines option "${optnames_should}" list "${listnames_should}" \
|
||||
| while read -r _type _optname
|
||||
do
|
||||
test -n "${_type}${_optname}" || continue # ignore empty lines
|
||||
opt_proc_error() {
|
||||
printf 'An error occurred during processing of option %s\n' "${1:?}" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
case $_type
|
||||
# Set "should" options
|
||||
echo "${optnames_should}" \
|
||||
| grep -e . \
|
||||
| while read -r _optname
|
||||
do
|
||||
_opt_state=$(awk -f "${__type:?}/files/option_state.awk" option "${_optname}") \
|
||||
|| opt_proc_error "${_optname}"
|
||||
case ${_opt_state}
|
||||
in
|
||||
(list)
|
||||
(invalid)
|
||||
opt_proc_error "${_optname}"
|
||||
;;
|
||||
(present)
|
||||
;;
|
||||
(*)
|
||||
printf 'set %s\n' "${section}.${_optname}" >>"${__messages_out:?}"
|
||||
|
||||
# shellcheck disable=SC2140
|
||||
uci_cmd set "${section}.${_optname}"="$(
|
||||
grep -e "^${_optname}=" "${__object:?}/parameter/option" \
|
||||
| sed -e 's/^.*=//' \
|
||||
| unquote_lines \
|
||||
| head -n 1)"
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
echo "${listnames_should}" \
|
||||
| grep -e . \
|
||||
| while read -r _optname
|
||||
do
|
||||
_list_state=$(awk -f "${__type:?}/files/option_state.awk" list "${_optname}") \
|
||||
|| opt_proc_error "${_optname}"
|
||||
case ${_list_state}
|
||||
in
|
||||
(invalid)
|
||||
opt_proc_error "${_optname}"
|
||||
;;
|
||||
(present)
|
||||
;;
|
||||
(*)
|
||||
printf 'set_list %s\n' "${section}.${_optname}" >>"${__messages_out:?}"
|
||||
|
||||
if grep -q -e "^${_optname}=" "${__object:?}/explorer/options"
|
||||
if test "${_list_state}" != absent
|
||||
then
|
||||
uci_cmd delete "${section}.${_optname}"
|
||||
fi
|
||||
|
@ -112,16 +150,6 @@ in
|
|||
uci_cmd add_list "${section}.${_optname}"="${_value}"
|
||||
done
|
||||
;;
|
||||
(option)
|
||||
printf 'set %s\n' "${section}.${_optname}" >>"${__messages_out:?}"
|
||||
|
||||
# shellcheck disable=SC2140
|
||||
uci_cmd set "${section}.${_optname}"="$(
|
||||
grep "^${_optname}=" "${__object:?}/parameter/option" \
|
||||
| sed -e 's/^.*=//' \
|
||||
| unquote_lines \
|
||||
| head -n 1)"
|
||||
;;
|
||||
esac
|
||||
done
|
||||
;;
|
||||
|
|
Loading…
Reference in a new issue