Preserve file mode of template (#193)

Any processed templates will inherit the file mode of the source
template.
This commit is contained in:
Tim Byrne 2020-07-11 14:13:24 -05:00
parent 6654e29c62
commit 102ba5d558
No known key found for this signature in database
GPG Key ID: 14DB4FC2465A4B12
5 changed files with 120 additions and 4 deletions

View File

@ -0,0 +1,53 @@
"""Unit tests: copy_perms"""
import os
import pytest
OCTAL = '7654'
NON_OCTAL = '9876'
@pytest.mark.parametrize(
'stat_broken', [True, False], ids=['normal', 'stat broken'])
def test_copy_perms(runner, yadm, tmpdir, stat_broken):
"""Test function copy_perms"""
src_mode = 0o754
dst_mode = 0o644
source = tmpdir.join('source')
source.write('test', ensure=True)
source.chmod(src_mode)
dest = tmpdir.join('dest')
dest.write('test', ensure=True)
dest.chmod(dst_mode)
override_stat = ''
if stat_broken:
override_stat = 'function stat() { echo broken; }'
script = f"""
YADM_TEST=1 source {yadm}
{override_stat}
copy_perms "{source}" "{dest}"
"""
run = runner(command=['bash'], inp=script)
assert run.success
assert run.err == ''
assert run.out == ''
expected = dst_mode if stat_broken else src_mode
assert oct(os.stat(dest).st_mode)[-3:] == oct(expected)[-3:]
@pytest.mark.parametrize(
'stat_output', [OCTAL, NON_OCTAL], ids=['octal', 'non-octal'])
def test_get_mode(runner, yadm, stat_output):
"""Test function get_mode"""
script = f"""
YADM_TEST=1 source {yadm}
function stat() {{ echo {stat_output}; }}
mode=$(get_mode abc)
echo "MODE:$mode"
"""
run = runner(command=['bash'], inp=script)
assert run.success
assert run.err == ''
expected = OCTAL if stat_output == OCTAL else ""
assert f'MODE:{expected}\n' in run.out

View File

@ -1,4 +1,7 @@
"""Unit tests: template_default"""
import os
FILE_MODE = 0o754
# these values are also testing the handling of bizarre characters
LOCAL_CLASS = "default_Test+@-!^Class"
@ -91,6 +94,7 @@ def test_template_default(runner, yadm, tmpdir):
input_file = tmpdir.join('input')
input_file.write(TEMPLATE, ensure=True)
input_file.chmod(FILE_MODE)
output_file = tmpdir.join('output')
script = f"""
@ -107,6 +111,7 @@ def test_template_default(runner, yadm, tmpdir):
assert run.success
assert run.err == ''
assert output_file.read() == EXPECTED
assert os.stat(output_file).st_mode == os.stat(input_file).st_mode
def test_source(runner, yadm, tmpdir):
@ -114,6 +119,7 @@ def test_source(runner, yadm, tmpdir):
input_file = tmpdir.join('input')
input_file.write('{{yadm.source}}', ensure=True)
input_file.chmod(FILE_MODE)
output_file = tmpdir.join('output')
script = f"""
@ -125,3 +131,4 @@ def test_source(runner, yadm, tmpdir):
assert run.success
assert run.err == ''
assert output_file.read().strip() == str(input_file)
assert os.stat(output_file).st_mode == os.stat(input_file).st_mode

View File

@ -1,4 +1,7 @@
"""Unit tests: template_esh"""
import os
FILE_MODE = 0o754
LOCAL_CLASS = "esh_Test+@-!^Class"
LOCAL_SYSTEM = "esh_Test+@-!^System"
@ -80,6 +83,7 @@ def test_template_esh(runner, yadm, tmpdir):
input_file = tmpdir.join('input')
input_file.write(TEMPLATE, ensure=True)
input_file.chmod(FILE_MODE)
output_file = tmpdir.join('output')
script = f"""
@ -95,6 +99,7 @@ def test_template_esh(runner, yadm, tmpdir):
assert run.success
assert run.err == ''
assert output_file.read().strip() == str(EXPECTED).strip()
assert os.stat(output_file).st_mode == os.stat(input_file).st_mode
def test_source(runner, yadm, tmpdir):
@ -102,6 +107,7 @@ def test_source(runner, yadm, tmpdir):
input_file = tmpdir.join('input')
input_file.write('<%= $YADM_SOURCE %>', ensure=True)
input_file.chmod(FILE_MODE)
output_file = tmpdir.join('output')
script = f"""
@ -112,3 +118,4 @@ def test_source(runner, yadm, tmpdir):
assert run.success
assert run.err == ''
assert output_file.read().strip() == str(input_file)
assert os.stat(output_file).st_mode == os.stat(input_file).st_mode

View File

@ -1,6 +1,9 @@
"""Unit tests: template_j2cli & template_envtpl"""
import os
import pytest
FILE_MODE = 0o754
LOCAL_CLASS = "j2_Test+@-!^Class"
LOCAL_SYSTEM = "j2_Test+@-!^System"
LOCAL_HOST = "j2_Test+@-!^Host"
@ -82,6 +85,7 @@ def test_template_j2(runner, yadm, tmpdir, processor):
input_file = tmpdir.join('input')
input_file.write(TEMPLATE, ensure=True)
input_file.chmod(FILE_MODE)
output_file = tmpdir.join('output')
script = f"""
@ -97,6 +101,7 @@ def test_template_j2(runner, yadm, tmpdir, processor):
assert run.success
assert run.err == ''
assert output_file.read() == EXPECTED
assert os.stat(output_file).st_mode == os.stat(input_file).st_mode
@pytest.mark.parametrize('processor', ('j2cli', 'envtpl'))
@ -105,6 +110,7 @@ def test_source(runner, yadm, tmpdir, processor):
input_file = tmpdir.join('input')
input_file.write('{{YADM_SOURCE}}', ensure=True)
input_file.chmod(FILE_MODE)
output_file = tmpdir.join('output')
script = f"""
@ -115,3 +121,4 @@ def test_source(runner, yadm, tmpdir, processor):
assert run.success
assert run.err == ''
assert output_file.read().strip() == str(input_file)
assert os.stat(output_file).st_mode == os.stat(input_file).st_mode

50
yadm
View File

@ -394,7 +394,11 @@ EOF
-v source="$input" \
"$awk_pgm" \
"$input" > "$temp_file"
[ -f "$temp_file" ] && mv -f "$temp_file" "$output"
if [ -f "$temp_file" ] ; then
copy_perms "$input" "$temp_file"
mv -f "$temp_file" "$output"
fi
}
function template_j2cli() {
@ -409,7 +413,11 @@ function template_j2cli() {
YADM_DISTRO="$local_distro" \
YADM_SOURCE="$input" \
"$J2CLI_PROGRAM" "$input" -o "$temp_file"
[ -f "$temp_file" ] && mv -f "$temp_file" "$output"
if [ -f "$temp_file" ] ; then
copy_perms "$input" "$temp_file"
mv -f "$temp_file" "$output"
fi
}
function template_envtpl() {
@ -424,7 +432,11 @@ function template_envtpl() {
YADM_DISTRO="$local_distro" \
YADM_SOURCE="$input" \
"$ENVTPL_PROGRAM" --keep-template "$input" -o "$temp_file"
[ -f "$temp_file" ] && mv -f "$temp_file" "$output"
if [ -f "$temp_file" ] ; then
copy_perms "$input" "$temp_file"
mv -f "$temp_file" "$output"
fi
}
function template_esh() {
@ -440,7 +452,10 @@ function template_esh() {
YADM_DISTRO="$local_distro" \
YADM_SOURCE="$input"
[ -f "$temp_file" ] && mv -f "$temp_file" "$output"
if [ -f "$temp_file" ] ; then
copy_perms "$input" "$temp_file"
mv -f "$temp_file" "$output"
fi
}
# ****** yadm Commands ******
@ -1908,6 +1923,33 @@ function join_string {
printf "%s" "${*:2}"
}
function get_mode {
local filename="$1"
local mode
# most *nixes
mode=$(stat -c '%a' "$filename" 2>/dev/null)
if [ -z "$mode" ] ; then
# BSD-style
mode=$(stat -f '%A' "$filename" 2>/dev/null)
fi
# only accept results if they are octal
if [[ ! $mode =~ ^[0-7]+$ ]] ; then
mode=""
fi
echo "$mode"
}
function copy_perms {
local source="$1"
local dest="$2"
mode=$(get_mode "$source")
[ -n "$mode" ] && chmod "$mode" "$dest"
return 0
}
# ****** Prerequisites Functions ******
function require_archive() {