[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
cdist/conf/type/__uci_section
|
@ -25,4 +25,24 @@ section=$("${__type_explorer:?}/match")
|
||||||
test -n "${section}" || exit 0
|
test -n "${section}" || exit 0
|
||||||
|
|
||||||
uci -s -N -d "${RS}" show "${section}" 2>/dev/null \
|
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"
|
{ 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() {
|
print_errors() {
|
||||||
awk -v prefix="${1:-Found errors:}" -v suffix="${2-}" '
|
awk -v prefix="${1:-Found errors:}" -v suffix="${2-}" '
|
||||||
BEGIN {
|
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
|
fi
|
||||||
|
|
||||||
# Make sure the section itself is present
|
# Make sure the section itself is present
|
||||||
if test "${state_is}" = absent
|
if test "${state_is}" = absent \
|
||||||
|
|| test "${type_is}" != "${type_should#*.}"
|
||||||
then
|
then
|
||||||
printf 'set %s\n' "${section}" >>"${__messages_out:?}"
|
printf 'set %s\n' "${section}" >>"${__messages_out:?}"
|
||||||
# shellcheck disable=SC2140
|
# shellcheck disable=SC2140
|
||||||
|
@ -78,7 +79,7 @@ in
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Delete options/lists not in "should"
|
# Delete options/lists not in "should"
|
||||||
sed -e 's/=.*$//;s/^.*\.//' "${__object:?}/explorer/options" \
|
sed -e 's/=.*$//' "${__object:?}/explorer/options" \
|
||||||
| while read -r _optname
|
| while read -r _optname
|
||||||
do
|
do
|
||||||
grep_line "${_optname}" "${listnames_should}" "${optnames_should}" || {
|
grep_line "${_optname}" "${listnames_should}" "${optnames_should}" || {
|
||||||
|
@ -87,18 +88,55 @@ in
|
||||||
} </dev/null
|
} </dev/null
|
||||||
done
|
done
|
||||||
|
|
||||||
# Set "should" options
|
opt_proc_error() {
|
||||||
prefix_lines option "${optnames_should}" list "${listnames_should}" \
|
printf 'An error occurred during processing of option %s\n' "${1:?}" >&2
|
||||||
| while read -r _type _optname
|
exit 1
|
||||||
do
|
}
|
||||||
test -n "${_type}${_optname}" || continue # ignore empty lines
|
|
||||||
|
|
||||||
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
|
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:?}"
|
printf 'set_list %s\n' "${section}.${_optname}" >>"${__messages_out:?}"
|
||||||
|
|
||||||
if grep -q -e "^${_optname}=" "${__object:?}/explorer/options"
|
if test "${_list_state}" != absent
|
||||||
then
|
then
|
||||||
uci_cmd delete "${section}.${_optname}"
|
uci_cmd delete "${section}.${_optname}"
|
||||||
fi
|
fi
|
||||||
|
@ -112,16 +150,6 @@ in
|
||||||
uci_cmd add_list "${section}.${_optname}"="${_value}"
|
uci_cmd add_list "${section}.${_optname}"="${_value}"
|
||||||
done
|
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
|
esac
|
||||||
done
|
done
|
||||||
;;
|
;;
|
||||||
|
|
Loading…
Reference in a new issue