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…
	
	Add table
		Add a link
		
	
		Reference in a new issue