Beispiel #1
0
def file(
    name,
    present=True, assume_present=False,
    user=None, group=None, mode=None, touch=False,
    create_remote_dir=True,
    state=None, host=None,
):
    '''
    Add/remove/update files.

    + name: name/path of the remote file
    + present: whether the file should exist
    + assume_present: whether to assume the file exists
    + TODO: user: user to own the files
    + TODO: group: group to own the files
    + TODO: mode: permissions of the files as an integer, eg: 755
    + touch: whether to touch the file
    + create_remote_dir: create the remote directory if it doesn't exist

    ``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.

    Example:

    .. code:: python

        files.file(
            name='Create c:\\temp\\hello.txt',
            path='c:\\temp\\hello.txt',
            touch=True,
        )
    '''

    if not isinstance(name, six.string_types):
        raise OperationTypeError('Name must be a string')

    # mode = ensure_mode_int(mode)
    info = host.fact.windows_file(name)

    # Not a file?!
    if info is False:
        raise OperationError('{0} exists and is not a file'.format(name))

    # Doesn't exist & we want it
    if not assume_present and info is None and present:
        if create_remote_dir:
            yield _create_remote_dir(state, host, name, user, group)

        yield 'New-Item -ItemType file {0}'.format(name)

#        if mode:
#            yield chmod(name, mode)
#        if user or group:
#            yield chown(name, user, group)

    # It exists and we don't want it
    elif (assume_present or info) and not present:
        yield 'Remove-Item {0}'.format(name)
Beispiel #2
0
def _validate_path(path):
    valid_path_types = six.string_types
    if pathlib:
        valid_path_types = six.string_types + (pathlib.Path, )

    if not isinstance(path, valid_path_types):
        raise OperationTypeError('`path` must be a string or `Path` object')
Beispiel #3
0
def _validate_path(path):
    try:
        path = fspath(path)
    except TypeError:
        raise OperationTypeError(
            '`path` must be a string or `os.PathLike` object')
Beispiel #4
0
def directory(
    state,
    host,
    name,
    present=True,
    assume_present=False,
    user=None,
    group=None,
    mode=None,
    recursive=False,
):
    '''
    Add/remove/update directories.

    + name: name/path of the remote folder
    + present: whether the folder should exist
    + assume_present: whether to assume the directory exists
    + user: user to own the folder
    + group: group to own the folder
    + mode: permissions of the folder
    + recursive: recursively apply user/group/mode

    Examples:

    .. code:: python

        files.directory(
            {'Ensure the /tmp/dir_that_we_want_removed is removed'},
            '/tmp/dir_that_we_want_removed',
            present=False,
        )

        files.directory(
            {'Ensure /web exists'},
            '/web',
            user='******',
            group='myweb',
        )

        # multiple directories
        dirs = ['/netboot/tftp', '/netboot/nfs']
        for dir in dirs:
            files.directory(
                {'Ensure the directory `{}` exists'.format(dir)},
                dir,
            )

    '''

    if not isinstance(name, six.string_types):
        raise OperationTypeError('Name must be a string')

    mode = ensure_mode_int(mode)
    info = host.fact.directory(name)

    # Not a directory?!
    if info is False:
        raise OperationError('{0} exists and is not a directory'.format(name))

    # Doesn't exist & we want it
    if not assume_present and info is None and present:
        yield 'mkdir -p {0}'.format(name)
        if mode:
            yield chmod(name, mode, recursive=recursive)
        if user or group:
            yield chown(name, user, group, recursive=recursive)

    # It exists and we don't want it
    elif (assume_present or info) and not present:
        yield 'rm -rf {0}'.format(name)

    # It exists & we want to ensure its state
    elif (assume_present or info) and present:
        # Check mode
        if mode and (not info or info['mode'] != mode):
            yield chmod(name, mode, recursive=recursive)

        # Check user/group
        if ((not info and (user or group)) or (user and info['user'] != user)
                or (group and info['group'] != group)):
            yield chown(name, user, group, recursive=recursive)
Beispiel #5
0
def file(
    state,
    host,
    name,
    present=True,
    assume_present=False,
    user=None,
    group=None,
    mode=None,
    touch=False,
    create_remote_dir=False,
):
    '''
    Add/remove/update files.

    + name: name/path of the remote file
    + present: whether the file should exist
    + assume_present: whether to assume the file exists
    + user: user to own the files
    + group: group to own the files
    + mode: permissions of the files as an integer, eg: 755
    + touch: whether to touch the file
    + create_remote_dir: create the remote directory if it doesn't exist

    ``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.

    Example:

    .. code:: python

        # Note: The directory /tmp/secret will get created with the default umask.
        files.file(
            {'Create /tmp/secret/file'},
            '/tmp/secret/file',
            mode='600',
            user='******',
            group='root',
            touch=True,
            create_remote_dir=True,
        )
    '''

    if not isinstance(name, six.string_types):
        raise OperationTypeError('Name must be a string')

    mode = ensure_mode_int(mode)
    info = host.fact.file(name)

    # Not a file?!
    if info is False:
        raise OperationError('{0} exists and is not a file'.format(name))

    # Doesn't exist & we want it
    if not assume_present and info is None and present:
        if create_remote_dir:
            yield _create_remote_dir(state, host, name, user, group)

        yield 'touch {0}'.format(name)

        if mode:
            yield chmod(name, mode)
        if user or group:
            yield chown(name, user, group)

    # It exists and we don't want it
    elif (assume_present or info) and not present:
        yield 'rm -f {0}'.format(name)

    # It exists & we want to ensure its state
    elif (assume_present or info) and present:
        if touch:
            yield 'touch {0}'.format(name)

        # Check mode
        if mode and (not info or info['mode'] != mode):
            yield chmod(name, mode)

        # Check user/group
        if ((not info and (user or group)) or (user and info['user'] != user)
                or (group and info['group'] != group)):
            yield chown(name, user, group)
Beispiel #6
0
def link(
    state,
    host,
    name,
    target=None,
    present=True,
    assume_present=False,
    user=None,
    group=None,
    symbolic=True,
    create_remote_dir=False,
):
    '''
    Add/remove/update links.

    + name: the name of the link
    + target: the file/directory the link points to
    + present: whether the link should exist
    + assume_present: whether to assume the link exists
    + user: user to own the link
    + group: group to own the link
    + symbolic: whether to make a symbolic link (vs hard link)
    + create_remote_dir: create the remote directory if it doesn't exist

    ``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.

    Source changes:
        If the link exists and points to a different target, pyinfra will remove it and
        recreate a new one pointing to then new target.

    Examples:

    .. code:: python

        # simple example showing how to link to a file
        files.link(
            {'Create link /etc/issue2 that points to /etc/issue'},
            '/etc/issue2',
            '/etc/issue',
        )


        # complex example demonstrating the assume_present option
        from pyinfra.modules import apt, files

        install_nginx = apt.packages(
            {'Install nginx'},
            'nginx',
        )

        files.link(
            {'Remove default nginx site'},
            '/etc/nginx/sites-enabled/default',
            present=False,
            assume_present=install_nginx.changed,
        )

    '''

    if not isinstance(name, six.string_types):
        raise OperationTypeError('Name must be a string')

    if present and not target:
        raise OperationError('If present is True target must be provided')

    info = host.fact.link(name)

    # Not a link?
    if info is False:
        raise OperationError('{0} exists and is not a link'.format(name))

    add_cmd = 'ln{0} {1} {2}'.format(
        ' -s' if symbolic else '',
        target,
        name,
    )

    remove_cmd = 'rm -f {0}'.format(name)

    # No link and we want it
    if not assume_present and info is None and present:
        if create_remote_dir:
            yield _create_remote_dir(state, host, name, user, group)

        yield add_cmd
        if user or group:
            yield chown(name, user, group, dereference=False)

    # It exists and we don't want it
    elif (assume_present or info) and not present:
        yield remove_cmd

    # Exists and want to ensure it's state
    elif (assume_present or info) and present:
        # If we have an absolute name - prepend to any non-absolute values from the fact
        # and/or the source.
        if path.isabs(name):
            link_dirname = path.dirname(name)

            if not path.isabs(target):
                target = path.normpath('/'.join((link_dirname, target)))

            if info and not path.isabs(info['link_target']):
                info['link_target'] = path.normpath(
                    '/'.join((link_dirname, info['link_target'])), )

        # If the target is wrong, remove & recreate the link
        if not info or info['link_target'] != target:
            yield remove_cmd
            yield add_cmd

        # Check user/group
        if ((not info and (user or group)) or (user and info['user'] != user)
                or (group and info['group'] != group)):
            yield chown(name, user, group, dereference=False)
Beispiel #7
0
def _validate_path(path):
    try:
        return os.fspath(path)
    except TypeError:
        raise OperationTypeError(
            "`path` must be a string or `os.PathLike` object")
Beispiel #8
0
def directory(
    name,
    present=True,
    assume_present=False,
    user=None,
    group=None,
    mode=None,
    recursive=False,
    state=None,
    host=None,
):
    '''
    Add/remove/update directories.

    + name: name/path of the remote folder
    + present: whether the folder should exist
    + assume_present: whether to assume the directory exists
    + TODO: user: user to own the folder
    + TODO: group: group to own the folder
    + TODO: mode: permissions of the folder
    + TODO: recursive: recursively apply user/group/mode

    Examples:

    .. code:: python

        files.directory(
            name='Ensure the c:\\temp\\dir_that_we_want_removed is removed',
            path='c:\\temp\\dir_that_we_want_removed',
            present=False,
        )

        files.directory(
            name='Ensure c:\\temp\\foo\\foo_dir exists',
            path='c:\\temp\\foo\\foo_dir',
            recursive=True,
        )

        # multiple directories
        dirs = ['c:\\temp\\foo_dir1', 'c:\\temp\\foo_dir2']
        for dir in dirs:
            files.directory(
                name='Ensure the directory `{}` exists'.format(dir),
                path=dir,
            )

    '''

    if not isinstance(name, six.string_types):
        raise OperationTypeError('Name must be a string')

    info = host.fact.windows_directory(name)

    # Not a directory?!
    if info is False:
        raise OperationError('{0} exists and is not a directory'.format(name))

    # Doesn't exist & we want it
    if not assume_present and info is None and present:
        yield 'New-Item -Path {0} -ItemType Directory'.format(name)
        #        if mode:
        #            yield chmod(name, mode, recursive=recursive)
        #        if user or group:
        #            yield chown(name, user, group, recursive=recursive)
        #
        # Somewhat bare fact, should flesh out more
        host.fact._create(
            'windows_directory',
            args=(name, ),
            data={'type': 'directory'},
        )

    # It exists and we don't want it
    elif (assume_present or info) and not present:
        # TODO: how to ensure we use 'ps'?
        # remove anything in the directory
        yield 'Get-ChildItem {0} -Recurse | Remove-Item'.format(name)
        # remove directory
        yield 'Remove-Item {0}'.format(name)
Beispiel #9
0
def directory(
    path,
    present=True,
    assume_present=False,
    user=None,
    group=None,
    mode=None,
    recursive=False,
):
    """
    Add/remove/update directories.

    + path: path of the remote folder
    + present: whether the folder should exist
    + assume_present: whether to assume the directory exists
    + TODO: user: user to own the folder
    + TODO: group: group to own the folder
    + TODO: mode: permissions of the folder
    + TODO: recursive: recursively apply user/group/mode

    **Examples:**

    .. code:: python

        files.directory(
            name="Ensure the c:\\temp\\dir_that_we_want_removed is removed",
            path="c:\\temp\\dir_that_we_want_removed",
            present=False,
        )

        files.directory(
            name="Ensure c:\\temp\\foo\\foo_dir exists",
            path="c:\\temp\\foo\\foo_dir",
            recursive=True,
        )

        # multiple directories
        dirs = ["c:\\temp\\foo_dir1", "c:\\temp\\foo_dir2"]
        for dir in dirs:
            files.directory(
                name="Ensure the directory `{}` exists".format(dir),
                path=dir,
            )

    """

    if not isinstance(path, str):
        raise OperationTypeError("Name must be a string")

    info = host.get_fact(Directory, path=path)

    # Not a directory?!
    if info is False:
        raise OperationError("{0} exists and is not a directory".format(path))

    # Doesn't exist & we want it
    if not assume_present and info is None and present:
        yield "New-Item -Path {0} -ItemType Directory".format(path)
        #        if mode:
        #            yield chmod(path, mode, recursive=recursive)
        #        if user or group:
        #            yield chown(path, user, group, recursive=recursive)
        #
        # Somewhat bare fact, should flesh out more
        host.create_fact(
            Date,
            kwargs={"path": path},
            data={"type": "directory"},
        )

    # It exists and we don't want it
    elif (assume_present or info) and not present:
        # TODO: how to ensure we use 'ps'?
        # remove anything in the directory
        yield "Get-ChildItem {0} -Recurse | Remove-Item".format(path)
        # remove directory
        yield "Remove-Item {0}".format(path)
Beispiel #10
0
def file(
    path,
    present=True,
    assume_present=False,
    user=None,
    group=None,
    mode=None,
    touch=False,
    create_remote_dir=True,
):
    """
    Add/remove/update files.

    + path: path of the remote file
    + present: whether the file should exist
    + assume_present: whether to assume the file exists
    + TODO: user: user to own the files
    + TODO: group: group to own the files
    + TODO: mode: permissions of the files as an integer, eg: 755
    + touch: whether to touch the file
    + create_remote_dir: create the remote directory if it doesn't exist

    ``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.

    **Example:**

    .. code:: python

        files.file(
            name="Create c:\\temp\\hello.txt",
            path="c:\\temp\\hello.txt",
            touch=True,
        )
    """

    if not isinstance(path, str):
        raise OperationTypeError("Name must be a string")

    # mode = ensure_mode_int(mode)
    info = host.get_fact(File, path=path)

    # Not a file?!
    if info is False:
        raise OperationError("{0} exists and is not a file".format(path))

    # Doesn't exist & we want it
    if not assume_present and info is None and present:
        if create_remote_dir:
            yield from _create_remote_dir(state, host, path, user, group)

        yield "New-Item -ItemType file {0}".format(path)

    #        if mode:
    #            yield chmod(path, mode)
    #        if user or group:
    #            yield chown(path, user, group)

    # It exists and we don't want it
    elif (assume_present or info) and not present:
        yield "Remove-Item {0}".format(path)