You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
ngcpcfg/scripts/set

170 lines
4.2 KiB

#!/bin/bash
# Purpose: set config value
################################################################################
set -e
set -u
# support testsuite
FUNCTIONS="${FUNCTIONS:-/usr/share/ngcp-ngcpcfg/functions/}"
HELPER="${HELPER:-/usr/share/ngcp-ngcpcfg/helper/}"
SCRIPTS="${SCRIPTS:-/usr/share/ngcp-ngcpcfg/scripts/}"
if ! [ -r "${FUNCTIONS}"/main ] ; then
printf "Error: %s/main could not be read. Exiting.\n" "${FUNCTIONS}">&2
exit 1
fi
# shellcheck disable=SC1090
. "${FUNCTIONS}"/main
## functions {{{
help() {
echo "Usage: ngcpcfg set [<options>] <file> <key>"
echo "Example: ngcpcfg set /etc/ngcp-config/config.yml general.maintenance=yes"
echo "Options:"
echo " --diff: show difference(s) for the applied changes"
}
## }}}
RC=0
b_show_diff=false
while [ -n "${1:-}" ]; do
case "$1" in
--diff)
b_show_diff=true
shift
;;
--*)
log_error "unsupported option '$1'. Exiting."
help >&2
exit 1
;;
*)
break
;;
esac
done
if [ "${#:-}" != "2" ]; then
help >&2
exit 1
fi
file="$1"
data="$2"
[ -f "${file}" ] || (log_error "missing ${file}. Exiting." ; exit 1)
[ -z "${data}" ] && (log_error "missing data to set. Exiting." ; exit 1)
# Check whether we should use different permissions when creating the file.
CREATEFILE=no
if [ ! -f "${file}" ]; then
CREATEFILE=yes
if [ "${file}" = "${NETWORK_CONFIG:-}" ]; then
MODE="${NETWORK_CONFIG_CHMOD}"
USER="${NETWORK_CONFIG_USER}"
GROUP="${NETWORK_CONFIG_GROUP}"
else
MODE="${CONFIG_CHMOD}"
USER="${CONFIG_USER}"
GROUP="${CONFIG_GROUP}"
fi
fi
log_debug "Received data: ${data}"
option="${data%%=*}"
value="${data#*=}"
log_debug "Parsed option: ${option}"
log_debug "Parsed value: ${value}"
[ -z "${option}" ] && ( log_error "missing option to set. Exiting." ; exit 1)
[ -z "${value}" ] && ( log_error "missing value to set. Exiting." ; exit 1)
log_debug "Saving option '${option}' value '${value}' into '${file}'"
if [[ ${value} =~ ^\'.*\'$ ]] ; then
log_debug "\$value is already quoted."
elif [[ ${value} =~ ^[0-9]*$ ]] ; then
log_debug "Not quoting \$value for integers."
elif [[ ${value} =~ ^\[.*\]$ ]] ; then
log_debug "Not quoting \$value for arrays."
elif [[ ${value} =~ ^\{.*\}$ ]] ; then
log_debug "Not quoting \$value for hashes."
else
log_debug "Quoting \$value to prevent further Perl errors."
value="\"${value}\""
fi
tmp=$(mktemp -t ngcpcfg-set.XXXXXXXXXX)
log_debug "Temporary perl file: ${tmp}"
cat > "${tmp}" << EOF
use strict;
use warnings;
use YAML::XS;
my \$file="${file}";
my \$yaml = YAML::XS::LoadFile("\$file");
my \$valref = \\\$yaml;
for my \$component (split(/\\./, "${option}")) {
if (ref(\$valref) eq 'SCALAR' && defined(\$\$valref)) {
print STDERR ("Key resolved to a SCALAR at '\$component'; cannot continue.\n");
exit(1);
}
elsif (\$component =~ /^\\d+\$/ && (!defined(\$\$valref) || ref(\$\$valref) eq 'ARRAY')) {
\$valref = \\\$\$valref->[\$component];
}
elsif (\$component eq 'APPEND' && ref(\$\$valref) eq 'ARRAY') {
\$valref = \\\$\$valref->[\$#{\$\$valref}+1];
}
elsif (!defined(\$\$valref) || ref(\$\$valref) eq 'HASH') {
\$valref = \\\$\$valref->{\$component};
}
else {
print STDERR ("Key resolved to a " . ref(\$\$valref) . " reference; refusing to overwrite.\n");
exit(1);
}
}
if (!defined(\$\$valref) || ref(\$valref) eq 'SCALAR') {
\$\$valref = ${value};
}
elsif (ref(\$\$valref) eq 'ARRAY' && ref(${value}) eq 'ARRAY') {
\$\$valref = ${value};
}
elsif (ref(\$\$valref) eq 'HASH' && ref(${value}) eq 'HASH') {
\$\$valref = ${value};
}
else {
print STDERR ("Key resolved to a " . ref(\$\$valref) . " reference; refusing to overwrite.\n");
exit(1);
}
YAML::XS::DumpFile(\$file, \$yaml);
EOF
log_debug "perl -wCSD \"${tmp}\" || RC=$?"
perl -wCSD "${tmp}" || RC=$?
if [ "${CREATEFILE}" = "yes" ]; then
chmod "${MODE}" "${file}"
chown "${USER}" "${file}"
chgrp "${GROUP}" "${file}"
fi
if [ "${RC}" = "0" ] && "${b_show_diff:-false}"; then
log_debug "${SCRIPTS}/diff || true"
"${SCRIPTS}"/diff || true
fi
if [ -n "${DEBUG:-}" ] ; then
log_debug "Not removing temporary file ${tmp}"
else
rm -f "${tmp}"
fi
exit ${RC}
## END OF FILE #################################################################