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)
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')
def _validate_path(path): try: path = fspath(path) except TypeError: raise OperationTypeError( '`path` must be a string or `os.PathLike` object')
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)
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)
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)
def _validate_path(path): try: return os.fspath(path) except TypeError: raise OperationTypeError( "`path` must be a string or `os.PathLike` object")
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)
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)
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)