Preserve file mode of template (#193)
Any processed templates will inherit the file mode of the source template.
This commit is contained in:
parent
6654e29c62
commit
102ba5d558
5 changed files with 120 additions and 4 deletions
53
test/test_unit_copy_perms.py
Normal file
53
test/test_unit_copy_perms.py
Normal 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
|
|
@ -1,4 +1,7 @@
|
||||||
"""Unit tests: template_default"""
|
"""Unit tests: template_default"""
|
||||||
|
import os
|
||||||
|
|
||||||
|
FILE_MODE = 0o754
|
||||||
|
|
||||||
# these values are also testing the handling of bizarre characters
|
# these values are also testing the handling of bizarre characters
|
||||||
LOCAL_CLASS = "default_Test+@-!^Class"
|
LOCAL_CLASS = "default_Test+@-!^Class"
|
||||||
|
@ -91,6 +94,7 @@ def test_template_default(runner, yadm, tmpdir):
|
||||||
|
|
||||||
input_file = tmpdir.join('input')
|
input_file = tmpdir.join('input')
|
||||||
input_file.write(TEMPLATE, ensure=True)
|
input_file.write(TEMPLATE, ensure=True)
|
||||||
|
input_file.chmod(FILE_MODE)
|
||||||
output_file = tmpdir.join('output')
|
output_file = tmpdir.join('output')
|
||||||
|
|
||||||
script = f"""
|
script = f"""
|
||||||
|
@ -107,6 +111,7 @@ def test_template_default(runner, yadm, tmpdir):
|
||||||
assert run.success
|
assert run.success
|
||||||
assert run.err == ''
|
assert run.err == ''
|
||||||
assert output_file.read() == EXPECTED
|
assert output_file.read() == EXPECTED
|
||||||
|
assert os.stat(output_file).st_mode == os.stat(input_file).st_mode
|
||||||
|
|
||||||
|
|
||||||
def test_source(runner, yadm, tmpdir):
|
def test_source(runner, yadm, tmpdir):
|
||||||
|
@ -114,6 +119,7 @@ def test_source(runner, yadm, tmpdir):
|
||||||
|
|
||||||
input_file = tmpdir.join('input')
|
input_file = tmpdir.join('input')
|
||||||
input_file.write('{{yadm.source}}', ensure=True)
|
input_file.write('{{yadm.source}}', ensure=True)
|
||||||
|
input_file.chmod(FILE_MODE)
|
||||||
output_file = tmpdir.join('output')
|
output_file = tmpdir.join('output')
|
||||||
|
|
||||||
script = f"""
|
script = f"""
|
||||||
|
@ -125,3 +131,4 @@ def test_source(runner, yadm, tmpdir):
|
||||||
assert run.success
|
assert run.success
|
||||||
assert run.err == ''
|
assert run.err == ''
|
||||||
assert output_file.read().strip() == str(input_file)
|
assert output_file.read().strip() == str(input_file)
|
||||||
|
assert os.stat(output_file).st_mode == os.stat(input_file).st_mode
|
||||||
|
|
|
@ -1,4 +1,7 @@
|
||||||
"""Unit tests: template_esh"""
|
"""Unit tests: template_esh"""
|
||||||
|
import os
|
||||||
|
|
||||||
|
FILE_MODE = 0o754
|
||||||
|
|
||||||
LOCAL_CLASS = "esh_Test+@-!^Class"
|
LOCAL_CLASS = "esh_Test+@-!^Class"
|
||||||
LOCAL_SYSTEM = "esh_Test+@-!^System"
|
LOCAL_SYSTEM = "esh_Test+@-!^System"
|
||||||
|
@ -80,6 +83,7 @@ def test_template_esh(runner, yadm, tmpdir):
|
||||||
|
|
||||||
input_file = tmpdir.join('input')
|
input_file = tmpdir.join('input')
|
||||||
input_file.write(TEMPLATE, ensure=True)
|
input_file.write(TEMPLATE, ensure=True)
|
||||||
|
input_file.chmod(FILE_MODE)
|
||||||
output_file = tmpdir.join('output')
|
output_file = tmpdir.join('output')
|
||||||
|
|
||||||
script = f"""
|
script = f"""
|
||||||
|
@ -95,6 +99,7 @@ def test_template_esh(runner, yadm, tmpdir):
|
||||||
assert run.success
|
assert run.success
|
||||||
assert run.err == ''
|
assert run.err == ''
|
||||||
assert output_file.read().strip() == str(EXPECTED).strip()
|
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):
|
def test_source(runner, yadm, tmpdir):
|
||||||
|
@ -102,6 +107,7 @@ def test_source(runner, yadm, tmpdir):
|
||||||
|
|
||||||
input_file = tmpdir.join('input')
|
input_file = tmpdir.join('input')
|
||||||
input_file.write('<%= $YADM_SOURCE %>', ensure=True)
|
input_file.write('<%= $YADM_SOURCE %>', ensure=True)
|
||||||
|
input_file.chmod(FILE_MODE)
|
||||||
output_file = tmpdir.join('output')
|
output_file = tmpdir.join('output')
|
||||||
|
|
||||||
script = f"""
|
script = f"""
|
||||||
|
@ -112,3 +118,4 @@ def test_source(runner, yadm, tmpdir):
|
||||||
assert run.success
|
assert run.success
|
||||||
assert run.err == ''
|
assert run.err == ''
|
||||||
assert output_file.read().strip() == str(input_file)
|
assert output_file.read().strip() == str(input_file)
|
||||||
|
assert os.stat(output_file).st_mode == os.stat(input_file).st_mode
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
"""Unit tests: template_j2cli & template_envtpl"""
|
"""Unit tests: template_j2cli & template_envtpl"""
|
||||||
|
import os
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
|
FILE_MODE = 0o754
|
||||||
|
|
||||||
LOCAL_CLASS = "j2_Test+@-!^Class"
|
LOCAL_CLASS = "j2_Test+@-!^Class"
|
||||||
LOCAL_SYSTEM = "j2_Test+@-!^System"
|
LOCAL_SYSTEM = "j2_Test+@-!^System"
|
||||||
LOCAL_HOST = "j2_Test+@-!^Host"
|
LOCAL_HOST = "j2_Test+@-!^Host"
|
||||||
|
@ -82,6 +85,7 @@ def test_template_j2(runner, yadm, tmpdir, processor):
|
||||||
|
|
||||||
input_file = tmpdir.join('input')
|
input_file = tmpdir.join('input')
|
||||||
input_file.write(TEMPLATE, ensure=True)
|
input_file.write(TEMPLATE, ensure=True)
|
||||||
|
input_file.chmod(FILE_MODE)
|
||||||
output_file = tmpdir.join('output')
|
output_file = tmpdir.join('output')
|
||||||
|
|
||||||
script = f"""
|
script = f"""
|
||||||
|
@ -97,6 +101,7 @@ def test_template_j2(runner, yadm, tmpdir, processor):
|
||||||
assert run.success
|
assert run.success
|
||||||
assert run.err == ''
|
assert run.err == ''
|
||||||
assert output_file.read() == EXPECTED
|
assert output_file.read() == EXPECTED
|
||||||
|
assert os.stat(output_file).st_mode == os.stat(input_file).st_mode
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize('processor', ('j2cli', 'envtpl'))
|
@pytest.mark.parametrize('processor', ('j2cli', 'envtpl'))
|
||||||
|
@ -105,6 +110,7 @@ def test_source(runner, yadm, tmpdir, processor):
|
||||||
|
|
||||||
input_file = tmpdir.join('input')
|
input_file = tmpdir.join('input')
|
||||||
input_file.write('{{YADM_SOURCE}}', ensure=True)
|
input_file.write('{{YADM_SOURCE}}', ensure=True)
|
||||||
|
input_file.chmod(FILE_MODE)
|
||||||
output_file = tmpdir.join('output')
|
output_file = tmpdir.join('output')
|
||||||
|
|
||||||
script = f"""
|
script = f"""
|
||||||
|
@ -115,3 +121,4 @@ def test_source(runner, yadm, tmpdir, processor):
|
||||||
assert run.success
|
assert run.success
|
||||||
assert run.err == ''
|
assert run.err == ''
|
||||||
assert output_file.read().strip() == str(input_file)
|
assert output_file.read().strip() == str(input_file)
|
||||||
|
assert os.stat(output_file).st_mode == os.stat(input_file).st_mode
|
||||||
|
|
50
yadm
50
yadm
|
@ -394,7 +394,11 @@ EOF
|
||||||
-v source="$input" \
|
-v source="$input" \
|
||||||
"$awk_pgm" \
|
"$awk_pgm" \
|
||||||
"$input" > "$temp_file"
|
"$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() {
|
function template_j2cli() {
|
||||||
|
@ -409,7 +413,11 @@ function template_j2cli() {
|
||||||
YADM_DISTRO="$local_distro" \
|
YADM_DISTRO="$local_distro" \
|
||||||
YADM_SOURCE="$input" \
|
YADM_SOURCE="$input" \
|
||||||
"$J2CLI_PROGRAM" "$input" -o "$temp_file"
|
"$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() {
|
function template_envtpl() {
|
||||||
|
@ -424,7 +432,11 @@ function template_envtpl() {
|
||||||
YADM_DISTRO="$local_distro" \
|
YADM_DISTRO="$local_distro" \
|
||||||
YADM_SOURCE="$input" \
|
YADM_SOURCE="$input" \
|
||||||
"$ENVTPL_PROGRAM" --keep-template "$input" -o "$temp_file"
|
"$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() {
|
function template_esh() {
|
||||||
|
@ -440,7 +452,10 @@ function template_esh() {
|
||||||
YADM_DISTRO="$local_distro" \
|
YADM_DISTRO="$local_distro" \
|
||||||
YADM_SOURCE="$input"
|
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 ******
|
# ****** yadm Commands ******
|
||||||
|
@ -1908,6 +1923,33 @@ function join_string {
|
||||||
printf "%s" "${*:2}"
|
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 ******
|
# ****** Prerequisites Functions ******
|
||||||
|
|
||||||
function require_archive() {
|
function require_archive() {
|
||||||
|
|
Loading…
Reference in a new issue