Initial commit

This commit is contained in:
2024-10-30 01:50:38 +01:00
commit 587ca23374
147 changed files with 7521 additions and 0 deletions

View File

@@ -0,0 +1,384 @@
#!/bin/sh
# Copyright (c) 2017 Markus Weippert
# GNU General Public License v3.0 (see https://www.gnu.org/licenses/gpl-3.0.txt)
WANT_JSON="1"
PARAMS="
autocommit/bool
command=cmd/str
config/str
find=find_by=search/any
keep_keys=keep/any
key/str
merge/bool//false
name/str
option/str
replace/bool//false
section/str
set_find/bool//true
type/str
unique/bool//false
value/any
"
RESPONSE_VARS="result=_result command config section option"
init() {
state_path=""
[ -z "$_ansible_check_mode" ] || state_path="$(mktemp -d)" ||
fail "could not create state path"
changes="$(uci_change_hash)"
case "$_type_keep_keys" in
object) fail "keep_keys must be list or string";;
array) json_get_values keep_keys "$_keep_keys" || :;;
esac
[ -z "$key" ] &&
key="${config:+$config${section:+.$section${option:+.$option}}}" ||
{ oIFS="$IFS"; IFS="."; set -- $key; IFS="$oIFS"
config="$1"; section="$2"; option="$3"; }
[ -z "$_ansible_diff" -o -z "$config" ] ||
set_diff "$(uci export "$config")"
[ -n "$command" ] || { [ -z "$value" ] && command="get" || command="set"; }
}
uci() {
[ -z "$state_path" ] || set -- -P "$state_path" "$@"
command uci "$@"
}
uci_change_hash() {
uci changes | md5
}
uci_result_do() {
json_set_namespace result
"$@"
json_set_namespace params
}
uci_get_safe() {
local tmp opts
while [ "${1#-}" != "$1" ]; do opts="$opts $1"; shift; done
tmp="$(uci $opts show "$1")" || return $?
echo "${tmp#*=}"
}
uci_check_type() {
local key="$1"; local type="$2"; local t
t="$(uci -q get "$key")" || return 1
[ -n "$type" -a "$t" != "$type" ] || return 0
fail "$key exists with $t instead of $type"
}
uci_compare_list() {
local k="${1:-$key}"
local match="1"
local keys values v i
json_get_keys keys
! values="$(uci_get_safe -q "$k")" || {
eval "set -- $values"
for i in $keys; do
json_get_var v "$i"
[ $# -gt 0 -a "$v" = "$1" ] || { match=""; break; }
shift
done
[ $# -eq 0 ] || match=""
[ -z "$match" ] || return 0
}
return 1
}
uci_add() {
section="${section:-$value}"
[ -n "$name" -o -z "$type" ] || name="$section"
type="${type:-$section}"
[ -n "$type" ] || fail "type required for $command"
[ -n "$name" ] && {
uci_check_type "$config.$name" "$type" || {
try uci add "$config" "$type"
try uci rename "$config.$_result=$name"
}
} || try uci add "$config" "$type"
}
uci_set_list() {
local k="${1:-$key}"
local keys v i
! uci_compare_list "$k" || return 0
uci -q delete "$k" || :
json_get_keys keys
for i in $keys; do
json_get_var v "$i"
try uci add_list "$k=$v"
done
}
uci_set_dict() {
local keys k v t
json_get_keys keys
keep_keys="$keep_keys $keys"
for k in $keys; do
json_get_type t "$k"
case "$t" in
array)
json_select "$k"
uci_set_list "$key.$k"
json_select ..;;
object) fail "cannot set $k to dict";;
*)
json_get_var v "$k"
try uci set "$key.$k=$v";;
esac
done
}
uci_set() {
local var="${1:-value}"
local var_type
eval "var_type=\"\$_type_$var\""
[ -z "$option" ] || keep_keys="$keep_keys $option"
case "$var_type" in
array)
[ -n "$config" -a -n "$section" -a -n "$option" ] ||
fail "config, section and option required for $command"
json_select_real "$var"
uci_set_list
json_select ..;;
object)
[ -n "$config" -a -n "$section" -a -z "$option" ] ||
fail "config and section but not option required for $command"
json_select_real "$var"
uci_set_dict
json_select ..;;
*) try "uci set \"\$key=\$$var\"";;
esac
}
uci_get() {
local entry
try uci get "$key"
eval "set -- $(uci_get_safe -q "$key")"
json_set_namespace result
json_add_array result_list
for entry; do json_add_string . "$entry"; done
json_close_array
json_set_namespace params
}
uci_find() {
local keys i c v k tmp
case "$_type_find" in
array|object)
[ -n "$config" -a -n "$type" ] ||
fail "config and type required for $command"
json_select_real find
json_get_keys keys;;
*)
[ -n "$config" -a -n "$type" ] &&
[ -n "$option" -o "$command" = find_all ] ||
fail "config, type and option required for $command";;
esac
[ "$command" != "find_all" ] || uci_result_do json_add_array result
type="${type:-$section}"
section=""; i=0
while [ -n "$(uci -q get "$config.@$type[$i]")" ]; do
c="@$type[$((i++))]"
case "$_type_find" in
array)
[ -z "$option" ] && {
for k in $keys; do
json_get_var v "$k"
uci -q get "$config.$c.$v" >/dev/null || continue 2
done
} || {
uci_compare_list "$config.$c.$option" || continue
};;
object)
for k in $keys; do
json_get_type tmp "$k"
case "$tmp" in
array)
json_select "$k"
uci_compare_list "$config.$c.$k" &&
tmp="1" || tmp=""
json_select ..
[ -n "$tmp" ] || continue 2;;
object)
fail "cannot compare $k with dict";;
*)
json_get_var v "$k"
tmp="$(uci -q get "$config.$c.$k")" &&
[ "$tmp" = "$v" ] || continue 2
esac
done;;
*)
[ -z "$option" ] || {
v="$(uci -q get "$config.$c.$option")" &&
[ -z "$find" -o "$find" = "$v" ] || continue
};;
esac
[ "$command" = "find_all" ] || { section="$c"; break; }
uci_result_do json_add_string . "$c"
done
case "$_type_find" in
array|object) json_select ..;;
esac
case "$command" in
find_all)
uci_result_do json_close_array
_result="";;
*)
_result="$section"
[ -n "$section" ] && return 0 || return 1;;
esac
}
uci_ensure() {
local keys k v
[ -n "$name" -o -z "$type" ] || name="$section"
type="${type:-$section}"
[ -n "$config" -a -n "$type" ] ||
fail "config, type and name required for $command"
[ -n "$name" ] && uci_check_type "$config.$name" "$type" || {
[ "$_type_find" = "object" -o -n "$option" ] && uci_find && {
[ -z "$name" ] || try uci rename "$config.$section=$name"
} || {
[ "$command" = absent ] && return 0 || uci_add
}
}
section="${name:-$_result}"
key="$config.$section${option:+.$option}"
[ "$command" = "absent" ] && {
[ -z "$_defined_value" ] &&
{ uci -q delete "$key" || :; } ||
case "$_type_value" in
array|object)
json_select_real value
json_get_keys keys
for k in $keys; do
json_get_var v "$k"
case "$_type_value" in
array) uci -q delete "$config.$section.$v";;
object) uci -q delete "$config.$section.$k=$v";;
esac
done
json_select ..;;
*) uci -q delete "$config.$section.$value";;
esac
return 0
}
[ -z "$set_find" -o "$_type_find" != "object" -a -z "$option" ] || {
uci_set find
[ "$_type_value" != "object" ] || {
key="$config.$section"
option=""
}
}
[ -z "$_defined_value" ] || uci_set
_result="$section"
}
uci_cleanup_section() {
case "$command" in
set|ensure|section) :;;
*) return 0;;
esac
local k v
[ -n "$replace" -a -n "$config" -a -n "$section" ] || return 0
for k in $(uci -q show "$config.$section" |
sed -n 's/^..*\...*\.\([^.][^.]*\)=.*$/\1/p')
do
for v in $keep_keys; do
[ "$k" != "$v" ] || continue 2
done
uci -q delete "$config.$section.$k"
done
}
uci_revert() {
[ -z "$key" ] && rm -f -- "/tmp/.uci"/* 2>/dev/null || uci revert "$key"
}
uci_autocommit() {
[ -n "$autocommit" ] || return 0
case "$command" in
commit|revert) return 0;;
esac
[ "$1" -eq 0 ] && {
[ -n "$config" ] && uci commit "$config" || uci commit
} || uci_revert
}
main() {
case "$command" in
batch|import)
[ -n "$value" ] || fail "value required for $command";;
add_list|del_list|rename|reorder)
[ -n "$key" -a -n "$value" ] ||
fail "key and value required for $command";;
add|get|delete|ensure|absent)
[ -n "$key" ] || fail "key required for $command";;
esac
case "$command" in
batch)
echo "$value" | final uci $command;;
export|changes|show|commit)
local cmd="final uci $command"
[ -z "$key" ] && $cmd || $cmd "$key";;
import)
local cmd="final uci ${merge:+-m }$command"
[ -z "$key" ] && echo "$value" | $cmd ||
echo "$value" | $cmd "$key";;
add)
uci_add; exit 0;;
add_list)
[ -z "$unique" ] || {
eval "set -- $(uci_get_safe -q "$key")"
for entry; do [ "$entry" = "$value" ] && exit 0; done
}
final uci add_list "$key=$value";;
del_list|reorder)
final uci $command "$key=$value";;
get)
uci_get; exit 0;;
delete)
final uci $command "$key${value:+=$value}";;
rename)
final uci $command "$key=${name:-$value}";;
revert)
final uci_revert;;
set)
uci_set; exit 0;;
find|find_all)
uci_find; exit $?;;
ensure|section)
uci_ensure; exit 0;;
absent)
[ -n "$_defined_find" ] || {
uci -q delete "$key${value:+=$value}"; exit 0
}
uci_ensure; exit 0;;
*) fail "unknown command: $command";;
esac
}
cleanup() {
local ec="$1"
[ "$ec" -ne 0 ] || uci_cleanup_section
[ "$changes" = "$(uci_change_hash)" ] || {
changed
[ "$_ansible_verbosity" -lt 2 ] || {
local _IFS line
_IFS="$IFS"; IFS="$N"; set -- $(uci changes); IFS="$_IFS"
json_set_namespace result
json_add_array changes
for line; do json_add_string . "$line"; done
json_close_array
json_set_namespace params
}
uci_autocommit "$ec"
}
[ -z "$_ansible_diff" -o -z "$config" ] ||
set_diff "" "$(uci export "$config")"
[ -z "$_ansible_check_mode" -o -z "$state_path" -o ! -d "$state_path" ] ||
rm -rf "$state_path"
}