diff --git a/src/pyinfra/operations/files.py b/src/pyinfra/operations/files.py index 44387d897..2d029bf7b 100644 --- a/src/pyinfra/operations/files.py +++ b/src/pyinfra/operations/files.py @@ -18,7 +18,6 @@ from jinja2 import TemplateRuntimeError, TemplateSyntaxError, UndefinedError from pyinfra import host, logger, state -from pyinfra.api.output import format_text from pyinfra.api import ( FileDownloadCommand, FileUploadCommand, @@ -31,6 +30,7 @@ operation, ) from pyinfra.api.command import make_formatted_string_command +from pyinfra.api.output import format_text from pyinfra.api.util import ( get_call_location, get_file_io, @@ -1484,10 +1484,19 @@ def move(src: str, dest: str, overwrite=False): """ if host.get_fact(File, src) is None: - raise OperationError(f"src {src} does not exist") - - if not host.get_fact(Directory, dest): - raise OperationError(f"dest {dest} is not an existing directory") + if state.is_executing: + raise OperationError(f"src {src} does not exist") + else: + logger.info(f"{host.print_prefix}src {src} does not exist yet") + + dest_info = host.get_fact(Directory, dest) + if dest_info is False: + raise OperationError(f"dest {dest} is not a directory") + elif dest_info is None: + if state.is_executing: + raise OperationError(f"dest directory {dest} does not exist") + else: + logger.info(f"{host.print_prefix}dest directory {dest} does not exist yet") full_dest_path = posixpath.join(dest, PurePosixPath(src).name) if host.get_fact(File, full_dest_path) is not None: @@ -1509,11 +1518,21 @@ def copy(src: str, dest: str, overwrite=False): + overwrite: whether to overwrite dest, if present """ src_is_dir = host.get_fact(Directory, src) - if not host.get_fact(File, src) and not src_is_dir: - raise OperationError(f"src {src} does not exist") - - if not host.get_fact(Directory, dest): - raise OperationError(f"dest {dest} is not an existing directory") + src_is_file = host.get_fact(File, src) + if not src_is_file and not src_is_dir: + if state.is_executing: + raise OperationError(f"src {src} does not exist") + else: + logger.info(f"{host.print_prefix}src {src} does not exist yet") + + dest_info = host.get_fact(Directory, dest) + if dest_info is False: + raise OperationError(f"dest {dest} is not a directory") + elif dest_info is None: + if state.is_executing: + raise OperationError(f"dest directory {dest} does not exist") + else: + logger.info(f"{host.print_prefix}dest directory {dest} does not exist yet") dest_file_path = posixpath.join(dest, PurePosixPath(src).name) dest_file_exists = host.get_fact(File, dest_file_path) @@ -2255,9 +2274,14 @@ def unarchive( yield FileUploadCommand(src, temp_archive) archive_path = temp_archive else: - # Validate the remote archive exists - if host.get_fact(File, path=src) is None: - raise OperationError(f"Remote archive {src} does not exist") + # Check if the remote archive exists + archive_info = host.get_fact(File, path=src) + if archive_info is False: + raise OperationError(f"Remote archive {src} is not a file") + elif archive_info is None: + if state.is_executing: + raise OperationError(f"Remote archive {src} does not exist") + logger.info(f"{host.print_prefix}Remote archive {src} does not exist") archive_path = src extras = list(extra_opts) if extra_opts else [] diff --git a/tests/operations/files.copy/invalid_dest.json b/tests/operations/files.copy/invalid_dest.json index 63399aeff..e76a6874f 100644 --- a/tests/operations/files.copy/invalid_dest.json +++ b/tests/operations/files.copy/invalid_dest.json @@ -6,16 +6,15 @@ }, "facts": { "files.File": { - "path=/tmp/src_dir/file": true, - "path=/tmp/dest_dir/file": null + "path=/tmp/src_dir/file": true }, "files.Directory": { - "path=/tmp/dest_dir": null, - "path=/tmp/src_dir/file": null + "path=/tmp/src_dir/file": false, + "path=/tmp/dest_dir": false } }, "exception": { "name": "OperationError", - "message": "dest /tmp/dest_dir is not an existing directory" + "message": "dest /tmp/dest_dir is not a directory" } } diff --git a/tests/operations/files.copy/invalid_src.json b/tests/operations/files.copy/invalid_src.json index b77a44170..03331b56c 100644 --- a/tests/operations/files.copy/invalid_src.json +++ b/tests/operations/files.copy/invalid_src.json @@ -1,4 +1,8 @@ { + "require_platform": [ + "Darwin", + "Linux" + ], "kwargs": { "src": "/tmp/src_dir/file", "dest": "/tmp/dest_dir", @@ -14,8 +18,7 @@ "path=/tmp/src_dir/file": null } }, - "exception": { - "name": "OperationError", - "message": "src /tmp/src_dir/file does not exist" - } + "commands": [ + "cp -r /tmp/src_dir/file /tmp/dest_dir" + ] } diff --git a/tests/operations/files.copy/missing_dest.json b/tests/operations/files.copy/missing_dest.json new file mode 100644 index 000000000..345c2dbd7 --- /dev/null +++ b/tests/operations/files.copy/missing_dest.json @@ -0,0 +1,20 @@ +{ + "kwargs": { + "src": "/tmp/src_dir/file", + "dest": "/tmp/dest_dir", + "overwrite": false + }, + "facts": { + "files.File": { + "path=/tmp/src_dir/file": true, + "path=/tmp/dest_dir/file": null + }, + "files.Directory": { + "path=/tmp/src_dir/file": false, + "path=/tmp/dest_dir": null + } + }, + "commands": [ + "cp -r /tmp/src_dir/file /tmp/dest_dir" + ] +} diff --git a/tests/operations/files.move/invalid_dest.json b/tests/operations/files.move/invalid_dest.json index 4c8acd7a0..03edfc232 100644 --- a/tests/operations/files.move/invalid_dest.json +++ b/tests/operations/files.move/invalid_dest.json @@ -1,6 +1,12 @@ { - "require_platform": ["Darwin", "Linux"], - "args": ["tmp/testfile", "tmp2"], + "require_platform": [ + "Darwin", + "Linux" + ], + "args": [ + "tmp/testfile", + "tmp2" + ], "facts": { "files.File": { "path=tmp/testfile": { @@ -8,11 +14,11 @@ } }, "files.Directory": { - "path=tmp2": null + "path=tmp2": false } }, "exception": { "name": "OperationError", - "message": "dest tmp2 is not an existing directory" + "message": "dest tmp2 is not a directory" } } diff --git a/tests/operations/files.move/invalid_src.json b/tests/operations/files.move/invalid_src.json index 121d0892e..4f64e6fc7 100644 --- a/tests/operations/files.move/invalid_src.json +++ b/tests/operations/files.move/invalid_src.json @@ -1,9 +1,16 @@ { - "require_platform": ["Darwin", "Linux"], - "args": ["tmp/testfile", "tmp2"], + "require_platform": [ + "Darwin", + "Linux" + ], + "args": [ + "tmp/testfile", + "tmp2" + ], "facts": { "files.File": { - "path=tmp/testfile": null + "path=tmp/testfile": null, + "path=tmp2/testfile": null }, "files.Directory": { "path=tmp2": { @@ -11,8 +18,7 @@ } } }, - "exception": { - "name": "OperationError", - "message": "src tmp/testfile does not exist" - } + "commands": [ + "mv tmp/testfile tmp2" + ] } diff --git a/tests/operations/files.move/missing_dest.json b/tests/operations/files.move/missing_dest.json new file mode 100644 index 000000000..0b34ebb7f --- /dev/null +++ b/tests/operations/files.move/missing_dest.json @@ -0,0 +1,19 @@ +{ + "kwargs": { + "src": "/tmp/src_dir/file", + "dest": "/tmp/dest_dir", + "overwrite": false + }, + "facts": { + "files.File": { + "path=/tmp/src_dir/file": true, + "path=/tmp/dest_dir/file": null + }, + "files.Directory": { + "path=/tmp/dest_dir": null + } + }, + "commands": [ + "mv /tmp/src_dir/file /tmp/dest_dir" + ] +} diff --git a/tests/operations/files.unarchive/remote_archive_missing.json b/tests/operations/files.unarchive/remote_archive_missing.json index 468bdbec2..f5ea60092 100644 --- a/tests/operations/files.unarchive/remote_archive_missing.json +++ b/tests/operations/files.unarchive/remote_archive_missing.json @@ -12,8 +12,5 @@ "path=/tmp/missing.tar.gz": null } }, - "exception": { - "name": "OperationError", - "message": "Remote archive /tmp/missing.tar.gz does not exist" - } + "commands": ["tar -xz -f /tmp/missing.tar.gz -C /opt/app"] }