#!/bin/bash # Filename: /usr/share/ngcp-ngcpcfg/helper/build_config # Purpose: builds output configuration file based on tt2 template file # using /usr/share/ngcp-ngcpcfg/helper/tt2-wrapper ################################################################################ set -e set -u if [ "${#:-}" -ne 3 ] ; then echo "Usage: /usr/share/ngcp-ngcpcfg/helper/build_config " >&2 exit 1 fi # support for testsuite, assume defaults if unset CONFIG_POOL="${CONFIG_POOL:-/etc}" FUNCTIONS="${FUNCTIONS:-/usr/share/ngcp-ngcpcfg/functions/}" HELPER="${HELPER:-/usr/share/ngcp-ngcpcfg/helper/}" if ! [ -r "${FUNCTIONS}"/logs ] ; then printf "Error: %s/logs could not be read. Exiting.\n" "${FUNCTIONS}" >&2 exit 1 fi . "${FUNCTIONS}"/logs # main script input_file="$1" # like /etc/ngcp-config/templates/etc/mysql/my.cnf.tt2 output_file="$2" # like /etc/mysql/my.cnf tmp_output_file="$3" # like /tmp/ngcpcfg.PID12345.KLJhiand/tmp_output_file if [ -z "${input_file}" ] ; then log_error "Missing parameter. Exiting." >&2 exit 1 fi if [ -z "${output_file}" ] ; then log_error "Missing parameter. Exiting." >&2 exit 1 fi if [ -z "${tmp_output_file}" ] ; then log_error "Missing parameter. Exiting." >&2 exit 1 fi # export variable for usage within {pre,post}build scripts, # OUTPUT_DIRECTORY is for customization during testing if [ -n "${OUTPUT_DIRECTORY:-}" ] ; then log_debug "Using output directory ${OUTPUT_DIRECTORY}" export output_file="${OUTPUT_DIRECTORY}/${output_file}" else export output_file fi output_file_dirname="$(dirname "${output_file}")" # like /etc/mysql # ensure we don't try to generate a file where a directory with same name exists already if [ -d "${output_file}" ] ; then log_error "Generating file ${output_file} not possible, it's an existing directory." >&2 exit 1 fi # pre-execution script in template store: if [ -r "${NGCPCTL_MAIN}/templates/${output_file}.prebuild" ] ; then log_info "Executing prebuild for ${output_file}" bash "${NGCPCTL_MAIN}/templates/${output_file}.prebuild" elif [ -r "${NGCPCTL_MAIN}/templates/${output_file_dirname}/ngcpcfg.prebuild" ] ; then log_info "Executing prebuild for ${output_file}" bash "${NGCPCTL_MAIN}/templates/${output_file_dirname}/ngcpcfg.prebuild" fi # if output directory does not exist yet, create it if ! [ -d "${output_file_dirname}" ] ; then umask 0022 # directory permissions should be '755' mkdir -p "${output_file_dirname}" fi # assume safe defaults umask 0077 # read host specific configuration file only if it exists [ -r "${HOST_CONFIG:-}" ] && host_conf="$HOST_CONFIG" # read local config only if it exists [ -r "${LOCAL_CONFIG:-}" ] && local_conf="$LOCAL_CONFIG" TT_WRAPPER="${HELPER}/tt2-wrapper" # XXX: Docker breaks sane Unix expectations when moving a file into /etc/hosts, # as it creates a bind mount on that pathname. We need to use an implementation # that will fallback to use copy semantics in that case, but will default to # use rename semantics to avoid races on ETXTBSY on executable files. # move() { local src="$1" local dst="$2" if [ -e /.dockerinit ] || [ -e /.dockerenv ] ; then perl -MFile::Copy=mv \ -E "mv('${src}', '${dst}') or die 'error: cannot move $src to $dst: \$!\n'" else mv "${src}" "${dst}" fi } log_debug "Output file ${output_file} based on ${input_file}" log_debug "Executing: $TT_WRAPPER ${input_file} > ${tmp_output_file}" log_debug " and: move ${tmp_output_file} ${output_file}" # 1) We need to use «readlink -f» so that we do not destroy any symlink pointing # to the real file, which we were previously preserving while using «cat». # 2) Care about ">" below, do not trust tmp file you receive. if "$TT_WRAPPER" "${input_file}" > "${tmp_output_file}" 2>/dev/null && ! grep -q -E '^file error' "${tmp_output_file}" 2>/dev/null && move "${tmp_output_file}" "$(readlink -f "${output_file}")" ; then log_info "Generating ${output_file}: OK" RC=0 else log_error "Generating ${output_file} based on ${input_file}: FAILED" RC=1 if [[ -r "${tmp_output_file}" ]] && grep -q -E '^file error' "${tmp_output_file}" ; then log_error "from generated file:" log_error " $(grep -E '^file error' "${tmp_output_file}")" fi log_info "NOTE: Check those files for valid syntax and encoding:" for f in "${input_file}" ${host_conf:-} ${local_conf:-} "$NGCPCTL_CONFIG" "${NETWORK_CONFIG:-}" "${EXTRA_CONFIG_FILES[@]}" "$CONSTANTS_CONFIG" ; do [ -r "$f" ] && log_info "$f" done log_info "Running /usr/share/ngcp-ngcpcfg/helper/tt2-wrapper " log_info "or inspecting temporary ${tmp_output_file}" log_info "should provide more details." fi if [ -L "$output_file" ] ; then log_warn "File $output_file is a symlink - NOT adjusting permissions" else # set permissions for generated config based on the ones of the template chmod --reference="${input_file}" "${output_file}" # finally drop all write permissions chmod a-w "${output_file}" fi # post-execution script in template store: if [ -r "${NGCPCTL_MAIN}/templates/${output_file}.postbuild" ] ; then log_info "Executing postbuild for ${output_file}" bash "${NGCPCTL_MAIN}/templates/${output_file}.postbuild" elif [ -r "${NGCPCTL_MAIN}/templates/${output_file_dirname}/ngcpcfg.postbuild" ] ; then log_info "Executing postbuild for ${output_file}" bash "${NGCPCTL_MAIN}/templates/${output_file_dirname}/ngcpcfg.postbuild" fi exit $RC ## END OF FILE #################################################################