Exemplo n.º 1
0
 def test_file_upload_command_repr(self):
     cmd = FileUploadCommand("src", "dest")
     assert repr(cmd) == "FileUploadCommand(src, dest)"
Exemplo n.º 2
0
def put(
    src,
    dest,
    user=None,
    group=None,
    mode=None,
    add_deploy_dir=True,
    create_remote_dir=True,
    force=False,
    assume_exists=False,
    state=None,
    host=None,
):
    '''
    Upload a local file to the remote system.

    + src: local filename to upload
    + dest: remote filename to upload to
    + user: user to own the files
    + group: group to own the files
    + mode: permissions of the files
    + add_deploy_dir: src is relative to the deploy directory
    + create_remote_dir: create the remote directory if it doesn't exist
    + force: always upload the file, even if the remote copy matches
    + assume_exists: whether to assume the local file exists

    ``create_remote_dir``:
        If the remote directory does not exist it will be created using the same
        user & group as passed to ``files.put``. The mode will *not* be copied over,
        if this is required call ``files.directory`` separately.

    Note:
        This operation is not suitable for large files as it may involve copying
        the file before uploading it.

    Examples:

    .. code:: python

        # Note: This requires a 'files/motd' file on the local filesystem
        files.put(
            name='Update the message of the day file',
            src='files/motd',
            dest='/etc/motd',
            mode='644',
        )
    '''

    dest = escape_unix_path(dest)

    # Upload IO objects as-is
    if hasattr(src, 'read'):
        local_file = src

    # Assume string filename
    else:
        # Add deploy directory?
        if add_deploy_dir and state.deploy_dir:
            src = os_path.join(state.deploy_dir, src)

        local_file = src

        if not assume_exists and not os_path.isfile(local_file):
            raise IOError('No such file: {0}'.format(local_file))

    mode = ensure_mode_int(mode)
    remote_file = host.fact.file(dest)

    if create_remote_dir:
        yield _create_remote_dir(state, host, dest, user, group)

    # No remote file, always upload and user/group/mode if supplied
    if not remote_file or force:
        yield FileUploadCommand(local_file, dest)

        if user or group:
            yield chown(dest, user, group)

        if mode:
            yield chmod(dest, mode)

    # File exists, check sum and check user/group/mode if supplied
    else:
        local_sum = get_file_sha1(src)
        remote_sum = host.fact.sha1_file(dest)

        # Check sha1sum, upload if needed
        if local_sum != remote_sum:
            yield FileUploadCommand(local_file, dest)

            if user or group:
                yield chown(dest, user, group)

            if mode:
                yield chmod(dest, mode)

        else:
            changed = False

            # Check mode
            if mode and remote_file['mode'] != mode:
                yield chmod(dest, mode)
                changed = True

            # Check user/group
            if ((user and remote_file['user'] != user)
                    or (group and remote_file['group'] != group)):
                yield chown(dest, user, group)
                changed = True

            if not changed:
                host.noop('file {0} is already uploaded'.format(dest))
Exemplo n.º 3
0
    def test_file_upload_op(self):
        inventory = make_inventory()

        state = State(inventory, Config())
        connect_all(state)

        with patch('pyinfra.operations.files.os_path.isfile',
                   lambda *args, **kwargs: True):
            # Test normal
            add_op(
                state,
                files.put,
                name='First op name',
                src='files/file.txt',
                dest='/home/vagrant/file.txt',
            )

            # And with sudo
            add_op(
                state,
                files.put,
                src='files/file.txt',
                dest='/home/vagrant/file.txt',
                sudo=True,
                sudo_user='******',
            )

            # And with su
            add_op(
                state,
                files.put,
                src='files/file.txt',
                dest='/home/vagrant/file.txt',
                sudo=True,
                su_user='******',
            )

        op_order = state.get_op_order()

        # Ensure we have all ops
        assert len(op_order) == 3

        first_op_hash = op_order[0]

        # Ensure first op is the right one
        assert state.op_meta[first_op_hash]['names'] == {'First op name'}

        somehost = inventory.get_host('somehost')
        anotherhost = inventory.get_host('anotherhost')

        # Ensure first op has the right (upload) command
        assert state.ops[somehost][first_op_hash]['commands'] == [
            StringCommand('mkdir -p /home/vagrant'),
            FileUploadCommand('files/file.txt', '/home/vagrant/file.txt'),
        ]

        # Ensure second op has sudo/sudo_user
        assert state.op_meta[op_order[1]]['sudo'] is True
        assert state.op_meta[op_order[1]]['sudo_user'] == 'pyinfra'

        # Ensure third has su_user
        assert state.op_meta[op_order[2]]['su_user'] == 'pyinfra'

        # Check run ops works
        with patch('pyinfra.api.util.open',
                   mock_open(read_data='test!'),
                   create=True):
            run_ops(state)

        # Ensure ops completed OK
        assert state.results[somehost]['success_ops'] == 3
        assert state.results[somehost]['ops'] == 3
        assert state.results[anotherhost]['success_ops'] == 3
        assert state.results[anotherhost]['ops'] == 3

        # And w/o errors
        assert state.results[somehost]['error_ops'] == 0
        assert state.results[anotherhost]['error_ops'] == 0
Exemplo n.º 4
0
 def test_file_upload_command_repr(self):
     cmd = FileUploadCommand('src', 'dest')
     assert repr(cmd) == 'FileUploadCommand(src, dest)'
Exemplo n.º 5
0
def put(
    src,
    dest,
    user=None,
    group=None,
    mode=None,
    add_deploy_dir=True,
    create_remote_dir=True,
    force=False,
    assume_exists=False,
):
    """
    Upload a local file, or file-like object, to the remote system.

    + src: filename or IO-like object to upload
    + dest: remote filename to upload to
    + user: user to own the files
    + group: group to own the files
    + mode: permissions of the files, use ``True`` to copy the local file
    + add_deploy_dir: src is relative to the deploy directory
    + create_remote_dir: create the remote directory if it doesn't exist
    + force: always upload the file, even if the remote copy matches
    + assume_exists: whether to assume the local file exists

    ``dest``:
        If this is a directory that already exists on the remote side, the local
        file will be uploaded to that directory with the same filename.

    ``mode``:
        When set to ``True`` the permissions of the local file are applied to the
        remote file after the upload is complete.

    ``create_remote_dir``:
        If the remote directory does not exist it will be created using the same
        user & group as passed to ``files.put``. The mode will *not* be copied over,
        if this is required call ``files.directory`` separately.

    Note:
        This operation is not suitable for large files as it may involve copying
        the file before uploading it.

    **Examples:**

    .. code:: python

        files.put(
            name="Update the message of the day file",
            src="files/motd",
            dest="/etc/motd",
            mode="644",
        )

        files.put(
            name="Upload a StringIO object",
            src=StringIO("file contents"),
            dest="/etc/motd",
        )
    """

    # Upload IO objects as-is
    if hasattr(src, "read"):
        local_file = src
        local_sum = get_file_sha1(src)

    # Assume string filename
    else:
        # Add deploy directory?
        if add_deploy_dir and state.cwd:
            src = os.path.join(state.cwd, src)

        local_file = src

        if os.path.isfile(local_file):
            local_sum = get_file_sha1(local_file)
        elif assume_exists:
            local_sum = None
        else:
            raise IOError("No such file: {0}".format(local_file))

    if mode is True:
        if os.path.isfile(local_file):
            mode = get_path_permissions_mode(local_file)
        else:
            logger.warning((
                "No local file exists to get permissions from with `mode=True` ({0})"
            ).format(get_call_location(), ), )
    else:
        mode = ensure_mode_int(mode)

    remote_file = host.get_fact(File, path=dest)

    if not remote_file and host.get_fact(Directory, path=dest):
        dest = unix_path_join(dest, os.path.basename(src))
        remote_file = host.get_fact(File, path=dest)

    if create_remote_dir:
        yield from _create_remote_dir(state, host, dest, user, group)

    # No remote file, always upload and user/group/mode if supplied
    if not remote_file or force:
        yield FileUploadCommand(
            local_file,
            dest,
            remote_temp_filename=state.get_temp_filename(dest),
        )

        if user or group:
            yield file_utils.chown(dest, user, group)

        if mode:
            yield file_utils.chmod(dest, mode)

    # File exists, check sum and check user/group/mode if supplied
    else:
        remote_sum = host.get_fact(Sha1File, path=dest)

        # Check sha1sum, upload if needed
        if local_sum != remote_sum:
            yield FileUploadCommand(
                local_file,
                dest,
                remote_temp_filename=state.get_temp_filename(dest),
            )

            if user or group:
                yield file_utils.chown(dest, user, group)

            if mode:
                yield file_utils.chmod(dest, mode)

        else:
            changed = False

            # Check mode
            if mode and remote_file["mode"] != mode:
                yield file_utils.chmod(dest, mode)
                changed = True

            # Check user/group
            if (user and remote_file["user"] != user) or (
                    group and remote_file["group"] != group):
                yield file_utils.chown(dest, user, group)
                changed = True

            if not changed:
                host.noop("file {0} is already uploaded".format(dest))

    # Now we've uploaded the file and ensured user/group/mode, update the relevant fact data
    host.create_fact(Sha1File, kwargs={"path": dest}, data=local_sum)
    host.create_fact(
        File,
        kwargs={"path": dest},
        data={
            "user": user,
            "group": group,
            "mode": mode
        },
    )
Exemplo n.º 6
0
    def test_file_upload_op(self):
        inventory = make_inventory()

        state = State(inventory, Config())
        connect_all(state)

        # Test normal
        add_op(
            state,
            files.put,
            name="First op name",
            src="files/file.txt",
            dest="/home/vagrant/file.txt",
        )

        # And with sudo
        add_op(
            state,
            files.put,
            src="files/file.txt",
            dest="/home/vagrant/file.txt",
            sudo=True,
            sudo_user="******",
        )

        # And with su
        add_op(
            state,
            files.put,
            src="files/file.txt",
            dest="/home/vagrant/file.txt",
            sudo=True,
            su_user="******",
        )

        op_order = state.get_op_order()

        # Ensure we have all ops
        assert len(op_order) == 3

        first_op_hash = op_order[0]
        second_op_hash = op_order[1]

        # Ensure first op is the right one
        assert state.op_meta[first_op_hash]["names"] == {"First op name"}

        somehost = inventory.get_host("somehost")
        anotherhost = inventory.get_host("anotherhost")

        # Ensure first op has the right (upload) command
        assert state.ops[somehost][first_op_hash]["commands"] == [
            StringCommand("mkdir -p /home/vagrant"),
            FileUploadCommand("files/file.txt", "/home/vagrant/file.txt"),
        ]

        # Ensure second op has sudo/sudo_user
        assert state.ops[somehost][second_op_hash]["global_kwargs"][
            "sudo"] is True
        assert state.ops[somehost][second_op_hash]["global_kwargs"][
            "sudo_user"] == "pyinfra"

        # Ensure third has su_user
        assert state.ops[somehost][
            op_order[2]]["global_kwargs"]["su_user"] == "pyinfra"

        # Check run ops works
        run_ops(state)

        # Ensure ops completed OK
        assert state.results[somehost]["success_ops"] == 3
        assert state.results[somehost]["ops"] == 3
        assert state.results[anotherhost]["success_ops"] == 3
        assert state.results[anotherhost]["ops"] == 3

        # And w/o errors
        assert state.results[somehost]["error_ops"] == 0
        assert state.results[anotherhost]["error_ops"] == 0
Exemplo n.º 7
0
def put(
    src,
    dest,
    user=None,
    group=None,
    mode=None,
    add_deploy_dir=True,
    create_remote_dir=True,
    force=False,
    assume_exists=False,
):
    """
    Upload a local file to the remote system.

    + src: local filename to upload
    + dest: remote filename to upload to
    + user: user to own the files
    + group: group to own the files
    + mode: permissions of the files
    + add_deploy_dir: src is relative to the deploy directory
    + create_remote_dir: create the remote directory if it doesn't exist
    + force: always upload the file, even if the remote copy matches
    + assume_exists: whether to assume the local file exists

    ``create_remote_dir``:
        If the remote directory does not exist it will be created using the same
        user & group as passed to ``files.put``. The mode will *not* be copied over,
        if this is required call ``files.directory`` separately.

    Note:
        This operation is not suitable for large files as it may involve copying
        the file before uploading it.

    **Examples:**

    .. code:: python

        # Note: This requires a 'files/motd' file on the local filesystem
        files.put(
            name="Update the message of the day file",
            src="data/content.json",
            dest="C:\\data\\content.json",
        )
    """

    # Upload IO objects as-is
    if hasattr(src, "read"):
        local_file = src

    # Assume string filename
    else:
        # Add deploy directory?
        if add_deploy_dir and state.cwd:
            src = os.path.join(state.cwd, src)

        local_file = src

        if not assume_exists and not os.path.isfile(local_file):
            raise IOError("No such file: {0}".format(local_file))

    mode = ensure_mode_int(mode)
    remote_file = host.get_fact(File, path=dest)

    if create_remote_dir:
        yield from _create_remote_dir(state, host, dest, user, group)

    # No remote file, always upload and user/group/mode if supplied
    if not remote_file or force:
        yield FileUploadCommand(
            local_file,
            dest,
            remote_temp_filename=state.get_temp_filename(dest),
        )

        # if user or group:
        #    yield chown(dest, user, group)

        # if mode:
        #    yield chmod(dest, mode)

    # File exists, check sum and check user/group/mode if supplied
    else:
        local_sum = get_file_sha1(src)
        remote_sum = host.get_fact(Sha1File, path=dest)

        # Check sha1sum, upload if needed
        if local_sum != remote_sum:
            yield FileUploadCommand(
                local_file,
                dest,
                remote_temp_filename=state.get_temp_filename(dest),
            )

            # if user or group:
            #    yield chown(dest, user, group)

            # if mode:
            #    yield chmod(dest, mode)

        else:
            changed = False

            # Check mode
            # if mode and remote_file['mode'] != mode:
            #    yield chmod(dest, mode)
            #    changed = True

            # Check user/group
            # if (
            #    (user and remote_file['user'] != user)
            #    or (group and remote_file['group'] != group)
            # ):
            #    yield chown(dest, user, group)
            #    changed = True

            if not changed:
                host.noop("file {0} is already uploaded".format(dest))