Exemple #1
0
def remove(path):
    '''
    Get matches for path expression

    CLI Example:

    .. code-block:: bash

        salt '*' augeas.remove /files/etc/sysctl.conf/net.ipv4.conf.all.log_martians
    '''
    aug = _Augeas()
    ret = {'retval': False}
    try:
        count = aug.remove(path)
        aug.save()
        if count == -1:
            ret['error'] = 'Invalid node'
        else:
            ret['retval'] = True
    except (RuntimeError, IOError) as err:
        ret['error'] = str(err)

    ret['count'] = count

    return ret
Exemple #2
0
def get(path, value=''):
    '''
    Get a value for a specific augeas path

    CLI Example:

    .. code-block:: bash

        salt '*' augeas.get /files/etc/hosts/1/ ipaddr
    '''
    aug = _Augeas()
    ret = {}

    path = path.rstrip('/')
    if value:
        path += '/{0}'.format(value.strip('/'))

    try:
        _match = aug.match(path)
    except RuntimeError as err:
        return {'error': str(err)}

    if _match:
        ret[path] = aug.get(path)
    else:
        ret[path] = ''  # node does not exist

    return ret
Exemple #3
0
def tree(path, load_path=None):
    """
    Returns recursively the complete tree of a node

    CLI Example:

    .. code-block:: bash

        salt '*' augeas.tree /files/etc/

    path
        The base of the recursive listing

    .. versionadded:: 2016.3.0

    load_path
        A colon-spearated list of directories that modules should be searched
        in. This is in addition to the standard load path and the directories
        in AUGEAS_LENS_LIB.
    """
    load_path = _check_load_paths(load_path)

    aug = _Augeas(loadpath=load_path)

    path = path.rstrip("/") + "/"
    match_path = path
    return dict([i for i in _recurmatch(match_path, aug)])
Exemple #4
0
def get(path, value=''):
    '''
    Get a value for a specific augeas path

    CLI Example:

    .. code-block:: bash

        salt '*' augeas.get /files/etc/hosts/1/ ipaddr
    '''
    aug = _Augeas()
    ret = {}

    path = path.rstrip('/')
    if value:
        path += '/{0}'.format(value.strip('/'))

    try:
        _match = aug.match(path)
    except RuntimeError as err:
        return {'error': str(err)}

    if _match:
        ret[path] = aug.get(path)
    else:
        ret[path] = ''  # node does not exist

    return ret
Exemple #5
0
def remove(path):
    '''
    Get matches for path expression

    CLI Example:

    .. code-block:: bash

        salt '*' augeas.remove /files/etc/sysctl.conf/net.ipv4.conf.all.log_martians
    '''
    aug = _Augeas()
    ret = {'retval': False}
    try:
        count = aug.remove(path)
        aug.save()
        if count == -1:
            ret['error'] = 'Invalid node'
        else:
            ret['retval'] = True
    except (RuntimeError, IOError) as err:
        ret['error'] = str(err)

    ret['count'] = count

    return ret
Exemple #6
0
def ls(path, load_path=None):  # pylint: disable=C0103
    """
    List the direct children of a node

    CLI Example:

    .. code-block:: bash

        salt '*' augeas.ls /files/etc/passwd

    path
        The path to list

    .. versionadded:: 2016.3.0

    load_path
        A colon-spearated list of directories that modules should be searched
        in. This is in addition to the standard load path and the directories
        in AUGEAS_LENS_LIB.
    """

    def _match(path):
        """ Internal match function """
        try:
            matches = aug.match(salt.utils.stringutils.to_str(path))
        except RuntimeError:
            return {}

        ret = {}
        for _ma in matches:
            ret[_ma] = aug.get(_ma)
        return ret

    load_path = _check_load_paths(load_path)

    aug = _Augeas(loadpath=load_path)

    path = path.rstrip("/") + "/"
    match_path = path + "*"

    matches = _match(match_path)
    ret = {}

    for key, value in six.iteritems(matches):
        name = _lstrip_word(key, path)
        if _match(key + "/*"):
            ret[name + "/"] = value  # has sub nodes, e.g. directory
        else:
            ret[name] = value
    return ret
Exemple #7
0
def tree(path):
    '''
    Returns recursively the complete tree of a node

    CLI Example:

    .. code-block:: bash

        salt '*' augeas.tree /files/etc/
    '''
    aug = _Augeas()

    path = path.rstrip('/') + '/'
    match_path = path
    return dict([i for i in _recurmatch(match_path, aug)])
Exemple #8
0
def tree(path):
    '''
    Returns recursively the complete tree of a node

    CLI Example:

    .. code-block:: bash

        salt '*' augeas.tree /files/etc/
    '''
    aug = _Augeas()

    path = path.rstrip('/') + '/'
    match_path = path
    return dict([i for i in _recurmatch(match_path, aug)])
Exemple #9
0
def get(path, value="", load_path=None):
    """
    Get a value for a specific augeas path

    CLI Example:

    .. code-block:: bash

        salt '*' augeas.get /files/etc/hosts/1/ ipaddr

    path
        The path to get the value of

    value
        The optional value to get

    .. versionadded:: 2016.3.0

    load_path
        A colon-spearated list of directories that modules should be searched
        in. This is in addition to the standard load path and the directories
        in AUGEAS_LENS_LIB.
    """
    load_path = _check_load_paths(load_path)

    aug = _Augeas(loadpath=load_path)
    ret = {}

    path = path.rstrip("/")
    if value:
        path += "/{0}".format(value.strip("/"))

    try:
        _match = aug.match(path)
    except RuntimeError as err:
        return {"error": six.text_type(err)}

    if _match:
        ret[path] = aug.get(path)
    else:
        ret[path] = ""  # node does not exist

    return ret
Exemple #10
0
def match(path, value="", load_path=None):
    """
    Get matches for path expression

    CLI Example:

    .. code-block:: bash

        salt '*' augeas.match /files/etc/services/service-name ssh

    path
        The path to match

    value
        The value to match on

    .. versionadded:: 2016.3.0

    load_path
        A colon-spearated list of directories that modules should be searched
        in. This is in addition to the standard load path and the directories
        in AUGEAS_LENS_LIB.
    """
    load_path = _check_load_paths(load_path)

    aug = _Augeas(loadpath=load_path)
    ret = {}

    try:
        matches = aug.match(path)
    except RuntimeError:
        return ret

    for _match in matches:
        if value and aug.get(_match) == value:
            ret[_match] = value
        elif not value:
            ret[_match] = aug.get(_match)
    return ret
Exemple #11
0
def remove(path, load_path=None):
    """
    Get matches for path expression

    CLI Example:

    .. code-block:: bash

        salt '*' augeas.remove \\
        /files/etc/sysctl.conf/net.ipv4.conf.all.log_martians

    path
        The path to remove

    .. versionadded:: 2016.3.0

    load_path
        A colon-spearated list of directories that modules should be searched
        in. This is in addition to the standard load path and the directories
        in AUGEAS_LENS_LIB.
    """
    load_path = _check_load_paths(load_path)

    aug = _Augeas(loadpath=load_path)
    ret = {"retval": False}
    try:
        count = aug.remove(path)
        aug.save()
        if count == -1:
            ret["error"] = "Invalid node"
        else:
            ret["retval"] = True
    except (RuntimeError, IOError) as err:
        ret["error"] = six.text_type(err)

    ret["count"] = count

    return ret
def remove(path, load_path=None):
    '''
    Get matches for path expression

    CLI Example:

    .. code-block:: bash

        salt '*' augeas.remove \\
        /files/etc/sysctl.conf/net.ipv4.conf.all.log_martians

    path
        The path to remove

    .. versionadded:: Boron

    load_path
        A colon-spearated list of directories that modules should be searched
        in. This is in addition to the standard load path and the directories
        in AUGEAS_LENS_LIB.
    '''
    load_path = _check_load_paths(load_path)

    aug = _Augeas(loadpath=load_path)
    ret = {'retval': False}
    try:
        count = aug.remove(path)
        aug.save()
        if count == -1:
            ret['error'] = 'Invalid node'
        else:
            ret['retval'] = True
    except (RuntimeError, IOError) as err:
        ret['error'] = str(err)

    ret['count'] = count

    return ret
Exemple #13
0
def ls(path):  # pylint: disable=C0103
    '''
    List the direct children of a node

    CLI Example:

    .. code-block:: bash

        salt '*' augeas.ls /files/etc/passwd
    '''
    def _match(path):
        ''' Internal match function '''
        try:
            matches = aug.match(path)
        except RuntimeError:
            return {}

        ret = {}
        for _ma in matches:
            ret[_ma] = aug.get(_ma)
        return ret

    aug = _Augeas()

    path = path.rstrip('/') + '/'
    match_path = path + '*'

    matches = _match(match_path)
    ret = {}

    for key, value in six.iteritems(matches):
        name = _lstrip_word(key, path)
        if _match(key + '/*'):
            ret[name + '/'] = value  # has sub nodes, e.g. directory
        else:
            ret[name] = value
    return ret
Exemple #14
0
def ls(path):  # pylint: disable=C0103
    '''
    List the direct children of a node

    CLI Example:

    .. code-block:: bash

        salt '*' augeas.ls /files/etc/passwd
    '''
    def _match(path):
        ''' Internal match function '''
        try:
            matches = aug.match(path)
        except RuntimeError:
            return {}

        ret = {}
        for _ma in matches:
            ret[_ma] = aug.get(_ma)
        return ret

    aug = _Augeas()

    path = path.rstrip('/') + '/'
    match_path = path + '*'

    matches = _match(match_path)
    ret = {}

    for key, value in six.iteritems(matches):
        name = _lstrip_word(key, path)
        if _match(key + '/*'):
            ret[name + '/'] = value  # has sub nodes, e.g. directory
        else:
            ret[name] = value
    return ret
Exemple #15
0
def match(path, value=''):
    '''
    Get matches for path expression

    CLI Example:

    .. code-block:: bash

        salt '*' augeas.match /files/etc/services/service-name ssh
    '''
    aug = _Augeas()
    ret = {}

    try:
        matches = aug.match(path)
    except RuntimeError:
        return ret

    for _match in matches:
        if value and aug.get(_match) == value:
            ret[_match] = value
        elif not value:
            ret[_match] = aug.get(_match)
    return ret
Exemple #16
0
def match(path, value=''):
    '''
    Get matches for path expression

    CLI Example:

    .. code-block:: bash

        salt '*' augeas.match /files/etc/services/service-name ssh
    '''
    aug = _Augeas()
    ret = {}

    try:
        matches = aug.match(path)
    except RuntimeError:
        return ret

    for _match in matches:
        if value and aug.get(_match) == value:
            ret[_match] = value
        elif not value:
            ret[_match] = aug.get(_match)
    return ret
Exemple #17
0
def execute(context=None, lens=None, commands=()):
    '''
    Execute Augeas commands

    .. versionadded:: 2014.7.0

    CLI Example:

    .. code-block:: bash

        salt '*' augeas.execute /files/etc/redis/redis.conf commands='["set bind 0.0.0.0", "set maxmemory 1G"]'
    '''
    ret = {'retval': False}

    method_map = {
        'set':    'set',
        'mv':     'move',
        'move':   'move',
        'ins':    'insert',
        'insert': 'insert',
        'rm':     'remove',
        'remove': 'remove',
    }

    flags = _Augeas.NO_MODL_AUTOLOAD if lens else _Augeas.NONE
    aug = _Augeas(flags=flags)

    if lens:
        aug.add_transform(lens, re.sub('^/files', '', context))
        aug.load()

    for command in commands:
        # first part up to space is always the command name (i.e.: set, move)
        cmd, arg = command.split(' ', 1)
        if cmd not in method_map:
            ret['error'] = 'Command {0} is not supported (yet)'.format(cmd)
            return ret

        method = method_map[cmd]

        try:
            if method == 'set':
                path, value, remainder = re.split('([^\'" ]+|"[^"]+"|\'[^\']+\')$', arg, 1)
                if context:
                    path = os.path.join(context.rstrip('/'), path.lstrip('/'))
                value = value.strip('"').strip("'")
                args = {'path': path, 'value': value}
            elif method == 'move':
                path, dst = arg.split(' ', 1)
                if context:
                    path = os.path.join(context.rstrip('/'), path.lstrip('/'))
                args = {'src': path, 'dst': dst}
            elif method == 'insert':
                label, where, path = re.split(' (before|after) ', arg)
                if context:
                    path = os.path.join(context.rstrip('/'), path.lstrip('/'))
                args = {'path': path, 'label': label, 'before': where == 'before'}
            elif method == 'remove':
                path = arg
                if context:
                    path = os.path.join(context.rstrip('/'), path.lstrip('/'))
                args = {'path': path}
        except ValueError as err:
            log.error(str(err))
            ret['error'] = 'Invalid formatted command, ' \
                           'see debug log for details: {0}'.format(arg)
            return ret

        log.debug('{0}: {1}'.format(method, args))

        func = getattr(aug, method)
        func(**args)

    try:
        aug.save()
        ret['retval'] = True
    except IOError as err:
        ret['error'] = str(err)

        if lens and not lens.endswith('.lns'):
            ret['error'] += '\nLenses are normally configured as "name.lns". ' \
                            'Did you mean "{0}.lns"?'.format(lens)

    aug.close()
    return ret
Exemple #18
0
def execute(context=None, lens=None, commands=()):
    '''
    Execute Augeas commands

    .. versionadded:: 2014.7.0

    CLI Example:

    .. code-block:: bash

        salt '*' augeas.execute /files/etc/redis/redis.conf commands='["set bind 0.0.0.0", "set maxmemory 1G"]'
    '''
    ret = {'retval': False}

    arg_map = {
        'set':    (1, 2),
        'setm':   (2, 3),
        'move':   (2,),
        'insert': (3,),
        'remove': (1,),
    }

    def make_path(path):
        '''
        Return correct path
        '''
        if not context:
            return path

        if path.lstrip('/'):
            if path.startswith(context):
                return path

            path = path.lstrip('/')
            return os.path.join(context, path)
        else:
            return context

    flags = _Augeas.NO_MODL_AUTOLOAD if lens and context else _Augeas.NONE
    aug = _Augeas(flags=flags)

    if lens and context:
        aug.add_transform(lens, re.sub('^/files', '', context))
        aug.load()

    for command in commands:
        try:
            # first part up to space is always the command name (i.e.: set, move)
            cmd, arg = command.split(' ', 1)

            if cmd not in METHOD_MAP:
                ret['error'] = 'Command {0} is not supported (yet)'.format(cmd)
                return ret

            method = METHOD_MAP[cmd]
            nargs = arg_map[method]

            parts = salt.utils.shlex_split(arg)

            if len(parts) not in nargs:
                err = '{0} takes {1} args: {2}'.format(method, nargs, parts)
                raise ValueError(err)
            if method == 'set':
                path = make_path(parts[0])
                value = parts[1] if len(parts) == 2 else None
                args = {'path': path, 'value': value}
            elif method == 'setm':
                base = make_path(parts[0])
                sub = parts[1]
                value = parts[2] if len(parts) == 3 else None
                args = {'base': base, 'sub': sub, 'value': value}
            elif method == 'move':
                path = make_path(parts[0])
                dst = parts[1]
                args = {'src': path, 'dst': dst}
            elif method == 'insert':
                label, where, path = parts
                if where not in ('before', 'after'):
                    raise ValueError('Expected "before" or "after", not {0}'.format(where))
                path = make_path(path)
                args = {'path': path, 'label': label, 'before': where == 'before'}
            elif method == 'remove':
                path = make_path(parts[0])
                args = {'path': path}
        except ValueError as err:
            log.error(str(err))
            # if command.split fails arg will not be set
            if 'arg' not in locals():
                arg = command
            ret['error'] = 'Invalid formatted command, ' \
                           'see debug log for details: {0}'.format(arg)
            return ret

        log.debug('{0}: {1}'.format(method, args))

        func = getattr(aug, method)
        func(**args)

    try:
        aug.save()
        ret['retval'] = True
    except IOError as err:
        ret['error'] = str(err)

        if lens and not lens.endswith('.lns'):
            ret['error'] += '\nLenses are normally configured as "name.lns". ' \
                            'Did you mean "{0}.lns"?'.format(lens)

    aug.close()
    return ret
Exemple #19
0
def execute(context=None, lens=None, commands=(), load_path=None):
    """
    Execute Augeas commands

    .. versionadded:: 2014.7.0

    CLI Example:

    .. code-block:: bash

        salt '*' augeas.execute /files/etc/redis/redis.conf \\
        commands='["set bind 0.0.0.0", "set maxmemory 1G"]'

    context
        The Augeas context

    lens
        The Augeas lens to use

    commands
        The Augeas commands to execute

    .. versionadded:: 2016.3.0

    load_path
        A colon-spearated list of directories that modules should be searched
        in. This is in addition to the standard load path and the directories
        in AUGEAS_LENS_LIB.
    """
    ret = {"retval": False}

    arg_map = {
        "set": (1, 2),
        "setm": (2, 3),
        "move": (2,),
        "insert": (3,),
        "remove": (1,),
    }

    def make_path(path):
        """
        Return correct path
        """
        if not context:
            return path

        if path.lstrip("/"):
            if path.startswith(context):
                return path

            path = path.lstrip("/")
            return os.path.join(context, path)
        else:
            return context

    load_path = _check_load_paths(load_path)

    flags = _Augeas.NO_MODL_AUTOLOAD if lens and context else _Augeas.NONE
    aug = _Augeas(flags=flags, loadpath=load_path)

    if lens and context:
        aug.add_transform(lens, re.sub("^/files", "", context))
        aug.load()

    for command in commands:
        try:
            # first part up to space is always the
            # command name (i.e.: set, move)
            cmd, arg = command.split(" ", 1)

            if cmd not in METHOD_MAP:
                ret["error"] = "Command {0} is not supported (yet)".format(cmd)
                return ret

            method = METHOD_MAP[cmd]
            nargs = arg_map[method]

            parts = salt.utils.args.shlex_split(arg)

            if len(parts) not in nargs:
                err = "{0} takes {1} args: {2}".format(method, nargs, parts)
                raise ValueError(err)
            if method == "set":
                path = make_path(parts[0])
                value = parts[1] if len(parts) == 2 else None
                args = {"path": path, "value": value}
            elif method == "setm":
                base = make_path(parts[0])
                sub = parts[1]
                value = parts[2] if len(parts) == 3 else None
                args = {"base": base, "sub": sub, "value": value}
            elif method == "move":
                path = make_path(parts[0])
                dst = parts[1]
                args = {"src": path, "dst": dst}
            elif method == "insert":
                label, where, path = parts
                if where not in ("before", "after"):
                    raise ValueError(
                        'Expected "before" or "after", not {0}'.format(where)
                    )
                path = make_path(path)
                args = {"path": path, "label": label, "before": where == "before"}
            elif method == "remove":
                path = make_path(parts[0])
                args = {"path": path}
        except ValueError as err:
            log.error(err)
            # if command.split fails arg will not be set
            if "arg" not in locals():
                arg = command
            ret["error"] = (
                "Invalid formatted command, "
                "see debug log for details: {0}".format(arg)
            )
            return ret

        args = salt.utils.data.decode(args, to_str=True)
        log.debug("%s: %s", method, args)

        func = getattr(aug, method)
        func(**args)

    try:
        aug.save()
        ret["retval"] = True
    except IOError as err:
        ret["error"] = six.text_type(err)

        if lens and not lens.endswith(".lns"):
            ret["error"] += (
                '\nLenses are normally configured as "name.lns". '
                'Did you mean "{0}.lns"?'.format(lens)
            )

    aug.close()
    return ret
Exemple #20
0
def setvalue(*args):
    """
    Set a value for a specific augeas path

    CLI Example:

    .. code-block:: bash

        salt '*' augeas.setvalue /files/etc/hosts/1/canonical localhost

    This will set the first entry in /etc/hosts to localhost

    CLI Example:

    .. code-block:: bash

        salt '*' augeas.setvalue /files/etc/hosts/01/ipaddr 192.168.1.1 \\
                                 /files/etc/hosts/01/canonical test

    Adds a new host to /etc/hosts the ip address 192.168.1.1 and hostname test

    CLI Example:

    .. code-block:: bash

        salt '*' augeas.setvalue prefix=/files/etc/sudoers/ \\
                 "spec[user = '******']/user" "%wheel" \\
                 "spec[user = '******']/host_group/host" 'ALL' \\
                 "spec[user = '******']/host_group/command[1]" 'ALL' \\
                 "spec[user = '******']/host_group/command[1]/tag" 'PASSWD' \\
                 "spec[user = '******']/host_group/command[2]" '/usr/bin/apt-get' \\
                 "spec[user = '******']/host_group/command[2]/tag" NOPASSWD

    Ensures that the following line is present in /etc/sudoers::

        %wheel ALL = PASSWD : ALL , NOPASSWD : /usr/bin/apt-get , /usr/bin/aptitude
    """
    load_path = None
    load_paths = [x for x in args if six.text_type(x).startswith("load_path=")]
    if load_paths:
        if len(load_paths) > 1:
            raise SaltInvocationError("Only one 'load_path=' value is permitted")
        else:
            load_path = load_paths[0].split("=", 1)[1]
    load_path = _check_load_paths(load_path)

    aug = _Augeas(loadpath=load_path)
    ret = {"retval": False}

    tuples = [
        x
        for x in args
        if not six.text_type(x).startswith("prefix=")
        and not six.text_type(x).startswith("load_path=")
    ]
    prefix = [x for x in args if six.text_type(x).startswith("prefix=")]
    if prefix:
        if len(prefix) > 1:
            raise SaltInvocationError("Only one 'prefix=' value is permitted")
        else:
            prefix = prefix[0].split("=", 1)[1]

    if len(tuples) % 2 != 0:
        raise SaltInvocationError("Uneven number of path/value arguments")

    tuple_iter = iter(tuples)
    for path, value in zip(tuple_iter, tuple_iter):
        target_path = path
        if prefix:
            target_path = os.path.join(prefix.rstrip("/"), path.lstrip("/"))
        try:
            aug.set(target_path, six.text_type(value))
        except ValueError as err:
            ret["error"] = "Multiple values: {0}".format(err)

    try:
        aug.save()
        ret["retval"] = True
    except IOError as err:
        ret["error"] = six.text_type(err)
    return ret
Exemple #21
0
def setvalue(*args):
    '''
    Set a value for a specific augeas path

    CLI Example:

    .. code-block:: bash

        salt '*' augeas.setvalue /files/etc/hosts/1/canonical localhost

    This will set the first entry in /etc/hosts to localhost

    CLI Example:

    .. code-block:: bash

        salt '*' augeas.setvalue /files/etc/hosts/01/ipaddr 192.168.1.1 \\
                                 /files/etc/hosts/01/canonical test

    Adds a new host to /etc/hosts the ip address 192.168.1.1 and hostname test

    CLI Example:

    .. code-block:: bash

        salt '*' augeas.setvalue prefix=/files/etc/sudoers/ \\
                 "spec[user = '******']/user" "%wheel" \\
                 "spec[user = '******']/host_group/host" 'ALL' \\
                 "spec[user = '******']/host_group/command[1]" 'ALL' \\
                 "spec[user = '******']/host_group/command[1]/tag" 'PASSWD' \\
                 "spec[user = '******']/host_group/command[2]" '/usr/bin/apt-get' \\
                 "spec[user = '******']/host_group/command[2]/tag" NOPASSWD

    Ensures that the following line is present in /etc/sudoers::

        %wheel ALL = PASSWD : ALL , NOPASSWD : /usr/bin/apt-get , /usr/bin/aptitude
    '''
    aug = _Augeas()
    ret = {'retval': False}

    tuples = [x for x in args if not str(x).startswith('prefix=')]
    prefix = [x for x in args if str(x).startswith('prefix=')]
    if prefix:
        if len(prefix) > 1:
            raise SaltInvocationError(
                'Only one \'prefix=\' value is permitted'
            )
        else:
            prefix = prefix[0].split('=', 1)[1]

    if len(tuples) % 2 != 0:
        raise SaltInvocationError('Uneven number of path/value arguments')

    tuple_iter = iter(tuples)
    for path, value in zip(tuple_iter, tuple_iter):
        target_path = path
        if prefix:
            target_path = os.path.join(prefix.rstrip('/'), path.lstrip('/'))
        try:
            aug.set(target_path, str(value))
        except ValueError as err:
            ret['error'] = 'Multiple values: {0}'.format(err)

    try:
        aug.save()
        ret['retval'] = True
    except IOError as err:
        ret['error'] = str(err)
    return ret
Exemple #22
0
def setvalue(*args):
    '''
    Set a value for a specific augeas path

    CLI Example:

    .. code-block:: bash

        salt '*' augeas.setvalue /files/etc/hosts/1/canonical localhost

    This will set the first entry in /etc/hosts to localhost

    CLI Example:

    .. code-block:: bash

        salt '*' augeas.setvalue /files/etc/hosts/01/ipaddr 192.168.1.1 \\
                                 /files/etc/hosts/01/canonical test

    Adds a new host to /etc/hosts the ip address 192.168.1.1 and hostname test

    CLI Example:

    .. code-block:: bash

        salt '*' augeas.setvalue prefix=/files/etc/sudoers/ \\
                 "spec[user = '******']/user" "%wheel" \\
                 "spec[user = '******']/host_group/host" 'ALL' \\
                 "spec[user = '******']/host_group/command[1]" 'ALL' \\
                 "spec[user = '******']/host_group/command[1]/tag" 'PASSWD' \\
                 "spec[user = '******']/host_group/command[2]" '/usr/bin/apt-get' \\
                 "spec[user = '******']/host_group/command[2]/tag" NOPASSWD

    Ensures that the following line is present in /etc/sudoers::

        %wheel ALL = PASSWD : ALL , NOPASSWD : /usr/bin/apt-get , /usr/bin/aptitude
    '''
    aug = _Augeas()
    ret = {'retval': False}

    tuples = [x for x in args if not str(x).startswith('prefix=')]
    prefix = [x for x in args if str(x).startswith('prefix=')]
    if prefix:
        if len(prefix) > 1:
            raise SaltInvocationError(
                'Only one \'prefix=\' value is permitted')
        else:
            prefix = prefix[0].split('=', 1)[1]

    if len(tuples) % 2 != 0:
        raise SaltInvocationError('Uneven number of path/value arguments')

    tuple_iter = iter(tuples)
    for path, value in zip(tuple_iter, tuple_iter):
        target_path = path
        if prefix:
            target_path = os.path.join(prefix.rstrip('/'), path.lstrip('/'))
        try:
            aug.set(target_path, str(value))
        except ValueError as err:
            ret['error'] = 'Multiple values: {0}'.format(err)

    try:
        aug.save()
        ret['retval'] = True
    except IOError as err:
        ret['error'] = str(err)
    return ret
Exemple #23
0
def execute(context=None, lens=None, commands=()):
    '''
    Execute Augeas commands

    .. versionadded:: 2014.7.0

    CLI Example:

    .. code-block:: bash

        salt '*' augeas.execute /files/etc/redis/redis.conf commands='["set bind 0.0.0.0", "set maxmemory 1G"]'
    '''
    ret = {'retval': False}

    method_map = {
        'set': 'set',
        'mv': 'move',
        'move': 'move',
        'ins': 'insert',
        'insert': 'insert',
        'rm': 'remove',
        'remove': 'remove',
    }

    flags = _Augeas.NO_MODL_AUTOLOAD if lens else _Augeas.NONE
    aug = _Augeas(flags=flags)

    if lens:
        aug.add_transform(lens, re.sub('^/files', '', context))
        aug.load()

    for command in commands:
        # first part up to space is always the command name (i.e.: set, move)
        cmd, arg = command.split(' ', 1)
        if cmd not in method_map:
            ret['error'] = 'Command {0} is not supported (yet)'.format(cmd)
            return ret

        method = method_map[cmd]

        try:
            if method == 'set':
                path, value, remainder = re.split(
                    '([^\'" ]+|"[^"]+"|\'[^\']+\')$', arg, 1)
                if context:
                    path = os.path.join(context.rstrip('/'), path.lstrip('/'))
                value = value.strip('"').strip("'")
                args = {'path': path, 'value': value}
            elif method == 'move':
                path, dst = arg.split(' ', 1)
                if context:
                    path = os.path.join(context.rstrip('/'), path.lstrip('/'))
                args = {'src': path, 'dst': dst}
            elif method == 'insert':
                path, where, label = re.split(' (before|after) ', arg)
                if context:
                    path = os.path.join(context.rstrip('/'), path.lstrip('/'))
                args = {
                    'path': path,
                    'label': label,
                    'before': where == 'before'
                }
            elif method == 'remove':
                path = arg
                if context:
                    path = os.path.join(context.rstrip('/'), path.lstrip('/'))
                args = {'path': path}
        except ValueError as err:
            log.error(str(err))
            ret['error'] = 'Invalid formatted command, ' \
                           'see debug log for details: {0}'.format(arg)
            return ret

        log.debug('{0}: {1}'.format(method, args))

        func = getattr(aug, method)
        func(**args)

    try:
        aug.save()
        ret['retval'] = True
    except IOError as err:
        ret['error'] = str(err)

        if lens and not lens.endswith('.lns'):
            ret['error'] += '\nLenses are normally configured as "name.lns". ' \
                            'Did you mean "{0}.lns"?'.format(lens)

    aug.close()
    return ret
Exemple #24
0
def execute(context=None, lens=None, commands=()):
    '''
    Execute Augeas commands

    .. versionadded:: 2014.7.0

    CLI Example:

    .. code-block:: bash

        salt '*' augeas.execute /files/etc/redis/redis.conf commands='["set bind 0.0.0.0", "set maxmemory 1G"]'
    '''
    ret = {'retval': False}

    method_map = {
        'set':    'set',
        'setm':    'setm',
        'mv':     'move',
        'move':   'move',
        'ins':    'insert',
        'insert': 'insert',
        'rm':     'remove',
        'remove': 'remove',
    }

    arg_map = {
        'set':    (1, 2),
        'setm':   (2, 3),
        'move':   (2,),
        'insert': (3,),
        'remove': (1,),
    }

    def make_path(path):
        if not context:
            return path
        path = path.lstrip('/')
        if path:
            return os.path.join(context, path)
        else:
            return context

    flags = _Augeas.NO_MODL_AUTOLOAD if lens else _Augeas.NONE
    aug = _Augeas(flags=flags)

    if lens:
        aug.add_transform(lens, re.sub('^/files', '', context))
        aug.load()

    for command in commands:
        # first part up to space is always the command name (i.e.: set, move)
        cmd, arg = command.split(' ', 1)
        if cmd not in method_map:
            ret['error'] = 'Command {0} is not supported (yet)'.format(cmd)
            return ret

        method = method_map[cmd]
        nargs = arg_map[method]

        try:
            parts = salt.utils.shlex_split(arg)
            if len(parts) not in nargs:
                err = '{0} takes {1} args: {2}'.format(method, nargs, parts)
                raise ValueError(err)
            if method == 'set':
                path = make_path(parts[0])
                value = parts[1] if len(parts) == 2 else None
                args = {'path': path, 'value': value}
            elif method == 'setm':
                base = make_path(parts[0])
                sub = parts[1]
                value = parts[2] if len(parts) == 3 else None
                args = {'base': base, 'sub': sub, 'value': value}
            elif method == 'move':
                path = make_path(parts[0])
                dst = parts[1]
                args = {'src': path, 'dst': dst}
            elif method == 'insert':
                label, where, path = parts
                if where not in ('before', 'after'):
                    raise ValueError('Expected "before" or "after", not {0}'.format(where))
                path = make_path(path)
                args = {'path': path, 'label': label, 'before': where == 'before'}
            elif method == 'remove':
                path = make_path(parts[0])
                args = {'path': path}
        except ValueError as err:
            log.error(str(err))
            ret['error'] = 'Invalid formatted command, ' \
                           'see debug log for details: {0}'.format(arg)
            return ret

        log.debug('{0}: {1}'.format(method, args))

        func = getattr(aug, method)
        func(**args)

    try:
        aug.save()
        ret['retval'] = True
    except IOError as err:
        ret['error'] = str(err)

        if lens and not lens.endswith('.lns'):
            ret['error'] += '\nLenses are normally configured as "name.lns". ' \
                            'Did you mean "{0}.lns"?'.format(lens)

    aug.close()
    return ret