From c1e2d8d3195ebce3d42cf5b771e4f85f16d5288d Mon Sep 17 00:00:00 2001 From: Konstantin Demin Date: Tue, 16 Jul 2024 11:33:20 +0300 Subject: [PATCH] improve template expansion --- image-entry.d/53-expand-templates.sh | 19 +++++++++++--- jinja2/j2common.py | 39 +++++++++++++++------------- scripts/j2-multi | 4 ++- scripts/j2-single | 4 ++- 4 files changed, 43 insertions(+), 23 deletions(-) diff --git a/image-entry.d/53-expand-templates.sh b/image-entry.d/53-expand-templates.sh index df7acd3..2489088 100755 --- a/image-entry.d/53-expand-templates.sh +++ b/image-entry.d/53-expand-templates.sh @@ -1,8 +1,21 @@ #!/bin/sh -set -ef +set -f . /image-entry.d/00-common.envsh +[ "${NGX_STRICT_LOAD}" = 0 ] || set -e + +expand_error() { + [ "${expand_error_seen:-}" = 1 ] || log_always 'template expansion has failed' + expand_error_seen=1 + if [ "${NGX_STRICT_LOAD}" = 1 ] ; then + t=10 + log_always "injecting delay for $t seconds" + sleep $t + exit 1 + fi +} + dirs='conf mod modules njs site snip' [ "${NGX_PROCESS_STATIC}" = 0 ] || dirs="${dirs} static" @@ -10,8 +23,8 @@ for n in ${dirs} ; do merged_dir="${merged_root}/$n" [ -d "${merged_dir}" ] || continue - expand_dir_envsubst "${merged_dir}/" - expand_dir_jinja "${merged_dir}/" + expand_dir_envsubst "${merged_dir}/" || expand_error + expand_dir_jinja "${merged_dir}/" || expand_error done exit 0 diff --git a/jinja2/j2common.py b/jinja2/j2common.py index 5a05177..09fd2d0 100755 --- a/jinja2/j2common.py +++ b/jinja2/j2common.py @@ -40,7 +40,7 @@ J2_KWARGS = {} def merge_dict_from_file(filename): - if (not filename) or (filename == ''): + if (not filename) or (str(filename) == ''): return False if not os.path.exists(filename): return False @@ -81,7 +81,7 @@ def render_error(msg, fail=True) -> bool: def render_file(file_in, file_out=None, fail=True): - if (not file_in) or (file_in == ''): + if (not file_in) or (str(file_in) == ''): return render_error( 'argument "file_in" is empty', fail) @@ -94,24 +94,14 @@ def render_file(file_in, file_out=None, fail=True): f'not a file: {file_in}', fail) - if file_out: - if str(file_in) == str(file_out): - return render_error( - f'unable to process template inplace: {file_in}', - fail) - f_out = file_out - else: + f_out = file_out + if not f_out: if not file_in.endswith(J2_SUFFIX): return render_error( f'input file name extension mismatch: {file_in}', fail) f_out = os.path.splitext(file_in)[0] - if os.path.exists(f_out): - return render_error( - f'output file already exists: {f_out}', - fail) - dirs = J2_SEARCH_PATH.copy() for d in [os.path.dirname(file_in), os.getcwd()]: if d not in dirs: @@ -132,16 +122,29 @@ def render_file(file_in, file_out=None, fail=True): j2_template = j2_environ.get_template(file_in) j2_stream = j2_template.stream(**J2_KWARGS) j2_stream.disable_buffering() + + if os.path.lexists(f_out): + if os.path.islink(f_out) or (not os.path.isfile(f_out)): + return render_error( + f'output file is not safely writable: {f_out}', + fail) + if os.path.exists(f_out): + if os.path.samefile(file_in, f_out): + return render_error( + f'unable to process template inplace: {file_in}', + fail) j2_stream.dump(f_out, encoding='utf-8') return True def init(): - global J2_KWARGS + kwa = {} for m in J2_MODULES: - J2_KWARGS[m] = importlib.import_module(m) - J2_KWARGS['env'] = os.environ - J2_KWARGS['cfg'] = {} + kwa[m] = importlib.import_module(m) + kwa['env'] = os.environ + kwa['cfg'] = {} + global J2_KWARGS + J2_KWARGS = kwa if J2_CONFIG != '': if os.path.isfile(J2_CONFIG): diff --git a/scripts/j2-multi b/scripts/j2-multi index 4970288..4bfcbb8 100755 --- a/scripts/j2-multi +++ b/scripts/j2-multi @@ -1,6 +1,8 @@ #!/bin/sh [ "${IEP_VERBOSE}" = 0 ] || { - echo "Running ${0##*/}:" >&2 + pfx= + [ "${IEP_TRACE}" = 0 ] || pfx="$(date +'%Y-%m-%d %H:%M:%S.%03N %z'): " + echo "# ${pfx}${0##*/}:" >&2 printf ' - %s\n' "$@" >&2 } exec python3 "/usr/local/lib/jinja2/${0##*/}.py" "$@" \ No newline at end of file diff --git a/scripts/j2-single b/scripts/j2-single index 45907e2..076b5a7 100755 --- a/scripts/j2-single +++ b/scripts/j2-single @@ -1,5 +1,7 @@ #!/bin/sh [ "${IEP_VERBOSE}" = 0 ] || { - echo "Running ${0##*/}: $*" >&2 + pfx= + [ "${IEP_TRACE}" = 0 ] || pfx="$(date +'%Y-%m-%d %H:%M:%S.%03N %z'): " + echo "# ${pfx}${0##*/}:${*:+ $*}" >&2 } exec python3 "/usr/local/lib/jinja2/${0##*/}.py" "$@" \ No newline at end of file