diff --git a/src/pyinfra/api/host.py b/src/pyinfra/api/host.py index ab8497c56..ea1520745 100644 --- a/src/pyinfra/api/host.py +++ b/src/pyinfra/api/host.py @@ -328,6 +328,9 @@ def _get_temp_directory(self): return temp_directory + def get_temp_dir_config(self): + return self.state.config.TEMP_DIR or self.state.config.DEFAULT_TEMP_DIR + def get_temp_filename( self, hash_key: Optional[str] = None, diff --git a/src/pyinfra/connectors/util.py b/src/pyinfra/connectors/util.py index abe46f7e9..bcd21e11a 100644 --- a/src/pyinfra/connectors/util.py +++ b/src/pyinfra/connectors/util.py @@ -22,17 +22,17 @@ SUDO_ASKPASS_ENV_VAR = "PYINFRA_SUDO_PASSWORD" + + SUDO_ASKPASS_COMMAND = r""" -temp=$(mktemp "${{TMPDIR:=/tmp}}/pyinfra-sudo-askpass-XXXXXXXXXXXX") +temp=$(mktemp "${{TMPDIR:={0}}}/pyinfra-sudo-askpass-XXXXXXXXXXXX") cat >"$temp"<<'__EOF__' #!/bin/sh -printf '%s\n' "${0}" +printf '%s\n' "${1}" __EOF__ chmod 755 "$temp" echo "$temp" -""".format( - SUDO_ASKPASS_ENV_VAR, -) +""" def run_local_process( @@ -264,7 +264,9 @@ def extract_control_arguments(arguments: "ConnectorArguments") -> "ConnectorArgu def _ensure_sudo_askpass_set_for_host(host: "Host"): if host.connector_data.get("sudo_askpass_path"): return - _, output = host.run_shell_command(SUDO_ASKPASS_COMMAND) + _, output = host.run_shell_command( + SUDO_ASKPASS_COMMAND.format(host.get_temp_dir_config(), SUDO_ASKPASS_ENV_VAR) + ) host.connector_data["sudo_askpass_path"] = shlex.quote(output.stdout_lines[0]) diff --git a/src/pyinfra/operations/files.py b/src/pyinfra/operations/files.py index 08f9ebe84..2d59cc85e 100644 --- a/src/pyinfra/operations/files.py +++ b/src/pyinfra/operations/files.py @@ -1803,6 +1803,8 @@ def block( current = host.get_fact(Block, path=path, marker=marker, begin=begin, end=end) cmd = None + tmp_dir = host.get_temp_dir_config() + # standard awk doesn't have an "in-place edit" option so we write to a tempfile and # if edits were successful move to dest i.e. we do: ... do some work ... q_path = QuoteString(path) @@ -1818,7 +1820,7 @@ def block( ) ) out_prep = StringCommand( - 'OUT="$(TMPDIR=/tmp mktemp -t pyinfra.XXXXXX)" && ', + f'OUT="$(TMPDIR={tmp_dir} mktemp -t pyinfra.XXXXXX)" && ', *mode_get, 'OWNER="$(stat -c "%u:%g"', q_path, diff --git a/tests/operations/files.block/add_existing_block_different_content.json b/tests/operations/files.block/add_existing_block_different_content.json index 6f8217452..87e26676f 100644 --- a/tests/operations/files.block/add_existing_block_different_content.json +++ b/tests/operations/files.block/add_existing_block_different_content.json @@ -1,6 +1,11 @@ { - "require_platform": ["Darwin", "Linux"], - "args": ["/home/someone/something"], + "require_platform": [ + "Darwin", + "Linux" + ], + "args": [ + "/home/someone/something" + ], "kwargs": { "content": "should be this", "line": "before this", @@ -8,10 +13,12 @@ }, "facts": { "files.Block": { - "begin=None, end=None, marker=None, path=/home/someone/something": ["previously was something else"] + "begin=None, end=None, marker=None, path=/home/someone/something": [ + "previously was something else" + ] } }, "commands": [ - "OUT=\"$(TMPDIR=/tmp mktemp -t pyinfra.XXXXXX)\" && MODE=\"$(stat -c %a /home/someone/something 2>/dev/null || stat -f %Lp /home/someone/something 2>/dev/null)\" && OWNER=\"$(stat -c \"%u:%g\" /home/someone/something 2>/dev/null || stat -f \"%u:%g\" /home/someone/something 2>/dev/null || echo $(id -un):$(id -gn))\" && awk 'BEGIN {{f=1; x=ARGV[2]; ARGV[2]=\"\"}}/# BEGIN PYINFRA BLOCK/ {print; print x; f=0} /# END PYINFRA BLOCK/ {print; f=1; next} f' /home/someone/something \"should be this\" > \"$OUT\" && mv \"$OUT\" /home/someone/something && chown \"$OWNER\" /home/someone/something && chmod \"$MODE\" /home/someone/something" + "OUT=\"$(TMPDIR=_tempdir_ mktemp -t pyinfra.XXXXXX)\" && MODE=\"$(stat -c %a /home/someone/something 2>/dev/null || stat -f %Lp /home/someone/something 2>/dev/null)\" && OWNER=\"$(stat -c \"%u:%g\" /home/someone/something 2>/dev/null || stat -f \"%u:%g\" /home/someone/something 2>/dev/null || echo $(id -un):$(id -gn))\" && awk 'BEGIN {{f=1; x=ARGV[2]; ARGV[2]=\"\"}}/# BEGIN PYINFRA BLOCK/ {print; print x; f=0} /# END PYINFRA BLOCK/ {print; f=1; next} f' /home/someone/something \"should be this\" > \"$OUT\" && mv \"$OUT\" /home/someone/something && chown \"$OWNER\" /home/someone/something && chmod \"$MODE\" /home/someone/something" ] -} +} \ No newline at end of file diff --git a/tests/operations/files.block/add_existing_block_different_content_and_backup.json b/tests/operations/files.block/add_existing_block_different_content_and_backup.json index 055340c56..f61c9e9a2 100644 --- a/tests/operations/files.block/add_existing_block_different_content_and_backup.json +++ b/tests/operations/files.block/add_existing_block_different_content_and_backup.json @@ -1,6 +1,11 @@ { - "require_platform": ["Darwin", "Linux"], - "args": ["/home/someone/something"], + "require_platform": [ + "Darwin", + "Linux" + ], + "args": [ + "/home/someone/something" + ], "kwargs": { "content": "should be this", "line": "before this", @@ -9,10 +14,12 @@ }, "facts": { "files.Block": { - "begin=None, end=None, marker=None, path=/home/someone/something": ["previously was something else"] + "begin=None, end=None, marker=None, path=/home/someone/something": [ + "previously was something else" + ] } }, "commands": [ - "cp /home/someone/something /home/someone/something.a-timestamp && OUT=\"$(TMPDIR=/tmp mktemp -t pyinfra.XXXXXX)\" && MODE=\"$(stat -c %a /home/someone/something 2>/dev/null || stat -f %Lp /home/someone/something 2>/dev/null)\" && OWNER=\"$(stat -c \"%u:%g\" /home/someone/something 2>/dev/null || stat -f \"%u:%g\" /home/someone/something 2>/dev/null || echo $(id -un):$(id -gn))\" && awk 'BEGIN {{f=1; x=ARGV[2]; ARGV[2]=\"\"}}/# BEGIN PYINFRA BLOCK/ {print; print x; f=0} /# END PYINFRA BLOCK/ {print; f=1; next} f' /home/someone/something \"should be this\" > \"$OUT\" && mv \"$OUT\" /home/someone/something && chown \"$OWNER\" /home/someone/something && chmod \"$MODE\" /home/someone/something" + "cp /home/someone/something /home/someone/something.a-timestamp && OUT=\"$(TMPDIR=_tempdir_ mktemp -t pyinfra.XXXXXX)\" && MODE=\"$(stat -c %a /home/someone/something 2>/dev/null || stat -f %Lp /home/someone/something 2>/dev/null)\" && OWNER=\"$(stat -c \"%u:%g\" /home/someone/something 2>/dev/null || stat -f \"%u:%g\" /home/someone/something 2>/dev/null || echo $(id -un):$(id -gn))\" && awk 'BEGIN {{f=1; x=ARGV[2]; ARGV[2]=\"\"}}/# BEGIN PYINFRA BLOCK/ {print; print x; f=0} /# END PYINFRA BLOCK/ {print; f=1; next} f' /home/someone/something \"should be this\" > \"$OUT\" && mv \"$OUT\" /home/someone/something && chown \"$OWNER\" /home/someone/something && chmod \"$MODE\" /home/someone/something" ] -} +} \ No newline at end of file diff --git a/tests/operations/files.block/add_existing_block_different_content_multiple_lines.json b/tests/operations/files.block/add_existing_block_different_content_multiple_lines.json index 42f05c77e..6bc1e7f63 100644 --- a/tests/operations/files.block/add_existing_block_different_content_multiple_lines.json +++ b/tests/operations/files.block/add_existing_block_different_content_multiple_lines.json @@ -1,17 +1,28 @@ { - "require_platform": ["Darwin", "Linux"], - "args": ["/home/someone/something"], + "require_platform": [ + "Darwin", + "Linux" + ], + "args": [ + "/home/someone/something" + ], "kwargs": { - "content": ["should be this", "and this", "and even this"], + "content": [ + "should be this", + "and this", + "and even this" + ], "line": "before this", "before": true }, "facts": { "files.Block": { - "begin=None, end=None, marker=None, path=/home/someone/something": ["previously was something else"] + "begin=None, end=None, marker=None, path=/home/someone/something": [ + "previously was something else" + ] } }, "commands": [ - "OUT=\"$(TMPDIR=/tmp mktemp -t pyinfra.XXXXXX)\" && MODE=\"$(stat -c %a /home/someone/something 2>/dev/null || stat -f %Lp /home/someone/something 2>/dev/null)\" && OWNER=\"$(stat -c \"%u:%g\" /home/someone/something 2>/dev/null || stat -f \"%u:%g\" /home/someone/something 2>/dev/null || echo $(id -un):$(id -gn))\" && awk 'BEGIN {{f=1; x=ARGV[2]; ARGV[2]=\"\"}}/# BEGIN PYINFRA BLOCK/ {print; print x; f=0} /# END PYINFRA BLOCK/ {print; f=1; next} f' /home/someone/something \"should be this\nand this\nand even this\" > \"$OUT\" && mv \"$OUT\" /home/someone/something && chown \"$OWNER\" /home/someone/something && chmod \"$MODE\" /home/someone/something" + "OUT=\"$(TMPDIR=_tempdir_ mktemp -t pyinfra.XXXXXX)\" && MODE=\"$(stat -c %a /home/someone/something 2>/dev/null || stat -f %Lp /home/someone/something 2>/dev/null)\" && OWNER=\"$(stat -c \"%u:%g\" /home/someone/something 2>/dev/null || stat -f \"%u:%g\" /home/someone/something 2>/dev/null || echo $(id -un):$(id -gn))\" && awk 'BEGIN {{f=1; x=ARGV[2]; ARGV[2]=\"\"}}/# BEGIN PYINFRA BLOCK/ {print; print x; f=0} /# END PYINFRA BLOCK/ {print; f=1; next} f' /home/someone/something \"should be this\nand this\nand even this\" > \"$OUT\" && mv \"$OUT\" /home/someone/something && chown \"$OWNER\" /home/someone/something && chmod \"$MODE\" /home/someone/something" ] -} +} \ No newline at end of file diff --git a/tests/operations/files.block/add_no_existing_block_and_no_line.json b/tests/operations/files.block/add_no_existing_block_and_no_line.json index c6413d568..75b2c62f1 100644 --- a/tests/operations/files.block/add_no_existing_block_and_no_line.json +++ b/tests/operations/files.block/add_no_existing_block_and_no_line.json @@ -1,6 +1,11 @@ { - "require_platform": ["Darwin", "Linux"], - "args": ["/home/someone/something"], + "require_platform": [ + "Darwin", + "Linux" + ], + "args": [ + "/home/someone/something" + ], "kwargs": { "content": "please add this", "before": true, @@ -12,6 +17,6 @@ } }, "commands": [ - "OUT=\"$(TMPDIR=/tmp mktemp -t pyinfra.XXXXXX)\" && OWNER=\"$(stat -c \"%u:%g\" /home/someone/something 2>/dev/null || stat -f \"%u:%g\" /home/someone/something 2>/dev/null || echo $(id -un):$(id -gn))\" && ( awk '{{print}}' - /dev/null > \"$OUT\" </dev/null || stat -f \"%u:%g\" /home/someone/something 2>/dev/null || echo $(id -un):$(id -gn))\" && ( awk '{{print}}' - /dev/null > \"$OUT\" </dev/null || stat -f %Lp /home/someone/something 2>/dev/null)\" && OWNER=\"$(stat -c \"%u:%g\" /home/someone/something 2>/dev/null || stat -f \"%u:%g\" /home/someone/something 2>/dev/null || echo $(id -un):$(id -gn))\" && awk 'BEGIN {x=ARGV[2]; ARGV[2]=\"\"} f!=1 && /^.*before this.*$/ { print x; f=1} END {if (f==0) print x } { print }' /home/someone/something \"# BEGIN PYINFRA BLOCK\nplease add this\n# END PYINFRA BLOCK\" > \"$OUT\" && mv \"$OUT\" /home/someone/something && chown \"$OWNER\" /home/someone/something && chmod \"$MODE\" /home/someone/something" + "OUT=\"$(TMPDIR=_tempdir_ mktemp -t pyinfra.XXXXXX)\" && MODE=\"$(stat -c %a /home/someone/something 2>/dev/null || stat -f %Lp /home/someone/something 2>/dev/null)\" && OWNER=\"$(stat -c \"%u:%g\" /home/someone/something 2>/dev/null || stat -f \"%u:%g\" /home/someone/something 2>/dev/null || echo $(id -un):$(id -gn))\" && awk 'BEGIN {x=ARGV[2]; ARGV[2]=\"\"} f!=1 && /^.*before this.*$/ { print x; f=1} END {if (f==0) print x } { print }' /home/someone/something \"# BEGIN PYINFRA BLOCK\nplease add this\n# END PYINFRA BLOCK\" > \"$OUT\" && mv \"$OUT\" /home/someone/something && chown \"$OWNER\" /home/someone/something && chmod \"$MODE\" /home/someone/something" ] -} +} \ No newline at end of file diff --git a/tests/operations/files.block/add_no_existing_block_line_provided_escape_regex.json b/tests/operations/files.block/add_no_existing_block_line_provided_escape_regex.json index 1f8c468d8..7c21c57dd 100644 --- a/tests/operations/files.block/add_no_existing_block_line_provided_escape_regex.json +++ b/tests/operations/files.block/add_no_existing_block_line_provided_escape_regex.json @@ -1,6 +1,11 @@ { - "require_platform": ["Darwin", "Linux"], - "args": ["/home/someone/something"], + "require_platform": [ + "Darwin", + "Linux" + ], + "args": [ + "/home/someone/something" + ], "kwargs": { "content": "please add this", "line": "before this *", @@ -13,6 +18,6 @@ } }, "commands": [ - "OUT=\"$(TMPDIR=/tmp mktemp -t pyinfra.XXXXXX)\" && MODE=\"$(stat -c %a /home/someone/something 2>/dev/null || stat -f %Lp /home/someone/something 2>/dev/null)\" && OWNER=\"$(stat -c \"%u:%g\" /home/someone/something 2>/dev/null || stat -f \"%u:%g\" /home/someone/something 2>/dev/null || echo $(id -un):$(id -gn))\" && awk 'BEGIN {x=ARGV[2]; ARGV[2]=\"\"} f!=1 && /^.*before this \\*.*$/ { print x; f=1} END {if (f==0) print x } { print }' /home/someone/something \"# BEGIN PYINFRA BLOCK\nplease add this\n# END PYINFRA BLOCK\" > \"$OUT\" && mv \"$OUT\" /home/someone/something && chown \"$OWNER\" /home/someone/something && chmod \"$MODE\" /home/someone/something" + "OUT=\"$(TMPDIR=_tempdir_ mktemp -t pyinfra.XXXXXX)\" && MODE=\"$(stat -c %a /home/someone/something 2>/dev/null || stat -f %Lp /home/someone/something 2>/dev/null)\" && OWNER=\"$(stat -c \"%u:%g\" /home/someone/something 2>/dev/null || stat -f \"%u:%g\" /home/someone/something 2>/dev/null || echo $(id -un):$(id -gn))\" && awk 'BEGIN {x=ARGV[2]; ARGV[2]=\"\"} f!=1 && /^.*before this \\*.*$/ { print x; f=1} END {if (f==0) print x } { print }' /home/someone/something \"# BEGIN PYINFRA BLOCK\nplease add this\n# END PYINFRA BLOCK\" > \"$OUT\" && mv \"$OUT\" /home/someone/something && chown \"$OWNER\" /home/someone/something && chmod \"$MODE\" /home/someone/something" ] -} +} \ No newline at end of file diff --git a/tests/operations/files.block/add_no_existing_file.json b/tests/operations/files.block/add_no_existing_file.json index 2d55b9eac..e20948ff1 100644 --- a/tests/operations/files.block/add_no_existing_file.json +++ b/tests/operations/files.block/add_no_existing_file.json @@ -1,6 +1,11 @@ { - "require_platform": ["Darwin", "Linux"], - "args": ["/home/someone/something"], + "require_platform": [ + "Darwin", + "Linux" + ], + "args": [ + "/home/someone/something" + ], "kwargs": { "content": "please add this", "line": "after this", @@ -12,6 +17,6 @@ } }, "commands": [ - "OUT=\"$(TMPDIR=/tmp mktemp -t pyinfra.XXXXXX)\" && OWNER=\"$(stat -c \"%u:%g\" /home/someone/something 2>/dev/null || stat -f \"%u:%g\" /home/someone/something 2>/dev/null || echo $(id -un):$(id -gn))\" && ( awk '{{print}}' /dev/null - > \"$OUT\" </dev/null || stat -f \"%u:%g\" /home/someone/something 2>/dev/null || echo $(id -un):$(id -gn))\" && ( awk '{{print}}' /dev/null - > \"$OUT\" </dev/null || stat -f %Lp /home/someone/something 2>/dev/null)\" && OWNER=\"$(stat -c \"%u:%g\" /home/someone/something 2>/dev/null || stat -f \"%u:%g\" /home/someone/something 2>/dev/null || echo $(id -un):$(id -gn))\" && awk '/# BEGIN PYINFRA BLOCK/,/# END PYINFRA BLOCK/ {next} 1' /home/someone/something > $OUT && mv \"$OUT\" /home/someone/something && chown \"$OWNER\" /home/someone/something && chmod \"$MODE\" /home/someone/something" + "OUT=\"$(TMPDIR=_tempdir_ mktemp -t pyinfra.XXXXXX)\" && MODE=\"$(stat -c %a /home/someone/something 2>/dev/null || stat -f %Lp /home/someone/something 2>/dev/null)\" && OWNER=\"$(stat -c \"%u:%g\" /home/someone/something 2>/dev/null || stat -f \"%u:%g\" /home/someone/something 2>/dev/null || echo $(id -un):$(id -gn))\" && awk '/# BEGIN PYINFRA BLOCK/,/# END PYINFRA BLOCK/ {next} 1' /home/someone/something > $OUT && mv \"$OUT\" /home/someone/something && chown \"$OWNER\" /home/someone/something && chmod \"$MODE\" /home/someone/something" ] -} +} \ No newline at end of file diff --git a/tests/operations/files.block/remove_existing_block.json b/tests/operations/files.block/remove_existing_block.json index da406a168..b0221c054 100644 --- a/tests/operations/files.block/remove_existing_block.json +++ b/tests/operations/files.block/remove_existing_block.json @@ -1,15 +1,22 @@ { - "require_platform": ["Darwin", "Linux"], - "args": ["/home/someone/something"], + "require_platform": [ + "Darwin", + "Linux" + ], + "args": [ + "/home/someone/something" + ], "kwargs": { "present": false }, "facts": { "files.Block": { - "begin=None, end=None, marker=None, path=/home/someone/something": ["existing content"] + "begin=None, end=None, marker=None, path=/home/someone/something": [ + "existing content" + ] } }, "commands": [ - "OUT=\"$(TMPDIR=/tmp mktemp -t pyinfra.XXXXXX)\" && MODE=\"$(stat -c %a /home/someone/something 2>/dev/null || stat -f %Lp /home/someone/something 2>/dev/null)\" && OWNER=\"$(stat -c \"%u:%g\" /home/someone/something 2>/dev/null || stat -f \"%u:%g\" /home/someone/something 2>/dev/null || echo $(id -un):$(id -gn))\" && awk '/# BEGIN PYINFRA BLOCK/,/# END PYINFRA BLOCK/ {next} 1' /home/someone/something > $OUT && mv \"$OUT\" /home/someone/something && chown \"$OWNER\" /home/someone/something && chmod \"$MODE\" /home/someone/something" + "OUT=\"$(TMPDIR=_tempdir_ mktemp -t pyinfra.XXXXXX)\" && MODE=\"$(stat -c %a /home/someone/something 2>/dev/null || stat -f %Lp /home/someone/something 2>/dev/null)\" && OWNER=\"$(stat -c \"%u:%g\" /home/someone/something 2>/dev/null || stat -f \"%u:%g\" /home/someone/something 2>/dev/null || echo $(id -un):$(id -gn))\" && awk '/# BEGIN PYINFRA BLOCK/,/# END PYINFRA BLOCK/ {next} 1' /home/someone/something > $OUT && mv \"$OUT\" /home/someone/something && chown \"$OWNER\" /home/someone/something && chmod \"$MODE\" /home/someone/something" ] -} +} \ No newline at end of file diff --git a/tests/util.py b/tests/util.py index 9157e0041..15bb2aadb 100644 --- a/tests/util.py +++ b/tests/util.py @@ -198,6 +198,9 @@ def get_file( ): return True + def get_temp_dir_config(*args, **kwargs): + return "_tempdir_" + @staticmethod def _get_fact_key(fact_cls): return "{0}.{1}".format(fact_cls.__module__.split(".")[-1], fact_cls.__name__)