设为首页 收藏本站
查看: 907|回复: 0

[经验分享] SaltStack源码分析之file状态模块

[复制链接]

尚未签到

发表于 2018-8-1 07:43:53 | 显示全部楼层 |阅读模式
def managed(name,  
            source=None,
  
            source_hash='',
  
            user=None,
  
            group=None,
  
            mode=None,
  
            template=None,
  
            makedirs=False,
  
            dir_mode=None,
  
            context=None,
  
            replace=True,
  
            defaults=None,
  
            env=None,
  
            backup='',
  
            show_diff=True,
  
            create=True,
  
            contents=None,
  
            contents_pillar=None,
  
            contents_grains=None,
  
            contents_newline=True,
  
            follow_symlinks=True,
  
            check_cmd=None,
  
            **kwargs):
  

  

  

  
            '''
  
    Manage a given file, this function allows for a file to be downloaded from
  
    the salt master and potentially run through a templating system.
  

  
    name
  
        The location of the file to manage
  

  
    source
  
        The source file to download to the minion, this source file can be
  
        hosted on either the salt master server, or on an HTTP or FTP server.
  
        Both HTTPS and HTTP are supported as well as downloading directly
  
        from Amazon S3 compatible URLs with both pre-configured and automatic
  
        IAM credentials. (see s3.get state documentation)
  
        File retrieval from Openstack Swift object storage is supported via
  
        swift://container/object_path URLs, see swift.get documentation.
  
        For files hosted on the salt file server, if the file is located on
  
        the master in the directory named spam, and is called eggs, the source
  
        string is salt://spam/eggs. If source is left blank or None
  
        (use ~ in YAML), the file will be created as an empty file and
  
        the content will not be managed
  

  
        If the file is hosted on a HTTP or FTP server then the source_hash
  
        argument is also required
  

  
        A list of sources can also be passed in to provide a default source and
  
        a set of fallbacks. The first source in the list that is found to exist
  
        will be used and subsequent entries in the list will be ignored.
  

  
        .. code-block:: yaml
  

  
            file_override_example:
  
              file.managed:
  
                - source:
  
                  - salt://file_that_does_not_exist
  
                  - salt://file_that_exists
  

  
    source_hash
  
        This can be one of the following:
  
            1. a source hash string
  
            2. the URI of a file that contains source hash strings
  

  
        The function accepts the first encountered long unbroken alphanumeric
  
        string of correct length as a valid hash, in order from most secure to
  
        least secure:
  

  
        .. code-block:: text
  

  
            Type    Length
  
            ======  ======
  
            sha512     128
  
            sha384      96
  
            sha256      64
  
            sha224      56
  
            sha1        40
  
            md5         32
  

  
        The file can contain several checksums for several files. Each line
  
        must contain both the file name and the hash.  If no file name is
  
        matched, the first hash encountered will be used, otherwise the most
  
        secure hash with the correct source file name will be used.
  

  
        Debian file type ``*.dsc`` is supported.
  

  
        Examples:
  

  
        .. code-block:: text
  

  
            /etc/rc.conf ef6e82e4006dee563d98ada2a2a80a27
  
            sha254c8525aee419eb649f0233be91c151178b30f0dff8ebbdcc8de71b1d5c8bcc06a  /etc/resolv.conf
  
            ead48423703509d37c4a90e6a0d53e143b6fc268
  

  
        Known issues:
  
            If the remote server URL has the hash file as an apparent
  
            sub-directory of the source file, the module will discover that it
  
            has already cached a directory where a file should be cached. For
  
            example:
  

  
            .. code-block:: yaml
  

  
                tomdroid-src-0.7.3.tar.gz:
  
                  file.managed:
  
                    - name: /tmp/tomdroid-src-0.7.3.tar.gz
  
                    - source: https://launchpad.net/tomdroid/beta/0.7.3/+download/tomdroid-src-0.7.3.tar.gz
  
                    - source_hash: https://launchpad.net/tomdroid/beta/0.7.3/+download/tomdroid-src-0.7.3.tar.gz/+md5
  

  

  
    user
  
        The user to own the file, this defaults to the user salt is running as
  
        on the minion
  

  
    group
  
        The group ownership set for the file, this defaults to the group salt
  
        is running as on the minion On Windows, this is ignored
  

  
    mode
  
        The permissions to set on this file, aka 644, 0775, 4664. Not supported
  
        on Windows
  

  
    template
  
        If this setting is applied then the named templating engine will be
  
        used to render the downloaded file, currently jinja, mako, and wempy
  
        are supported
  

  
    makedirs
  
        If the file is located in a path without a parent directory, then
  
        the state will fail. If makedirs is set to True, then the parent
  
        directories will be created to facilitate the creation of the named
  
        file.
  

  
    dir_mode
  
        If directories are to be created, passing this option specifies the
  
        permissions for those directories. If this is not set, directories
  
        will be assigned permissions from the 'mode' argument.
  

  
    replace
  
        If this file should be replaced.  If false, this command will
  
        not overwrite file contents but will enforce permissions if the file
  
        exists already.  Default is True.
  

  
    context
  
        Overrides default context variables passed to the template.
  

  
    defaults
  
        Default context passed to the template.
  

  
    backup
  
        Overrides the default backup mode for this specific file.
  

  
    show_diff
  
        If set to False, the diff will not be shown.
  

  
    create
  
        Default is True, if create is set to False then the file will only be
  
        managed if the file already exists on the system.
  

  
    contents
  
        Default is None.  If specified, will use the given string as the
  
        contents of the file.  Should not be used in conjunction with a source
  
        file of any kind.  Ignores hashes and does not use a templating engine.
  

  
    contents_pillar
  
        .. versionadded:: 0.17.0
  

  
        Operates like ``contents``, but draws from a value stored in pillar,
  
        using the pillar path syntax used in :mod:`pillar.get
  
        <salt.modules.pillar.get>`. This is useful when the pillar value
  
        contains newlines, as referencing a pillar variable using a jinja/mako
  
        template can result in YAML formatting issues due to the newlines
  
        causing indentation mismatches.
  

  
        For example, the following could be used to deploy an SSH private key:
  

  
        .. code-block:: yaml
  

  
            /home/deployer/.ssh/id_rsa:
  
              file.managed:
  
                - user: deployer
  
                - group: deployer
  
                - mode: 600
  
                - contents_pillar: userdata:deployer:id_rsa
  

  
        This would populate ``/home/deployer/.ssh/id_rsa`` with the contents of
  
        ``pillar['userdata']['deployer']['id_rsa']``. An example of this pillar
  
        setup would be like so:
  

  
        .. code-block:: yaml
  

  
            userdata:
  
              deployer:
  
                id_rsa: |
  
                  -----BEGIN RSA PRIVATE KEY-----
  
                  MIIEowIBAAKCAQEAoQiwO3JhBquPAalQF9qP1lLZNXVjYMIswrMe2HcWUVBgh+vY
  
                  U7sCwx/dH6+VvNwmCoqmNnP+8gTPKGl1vgAObJAnMT623dMXjVKwnEagZPRJIxDy
  
                  B/HaAre9euNiY3LvIzBTWRSeMfT+rWvIKVBpvwlgGrfgz70m0pqxu+UyFbAGLin+
  
                  GpxzZAMaFpZw4sSbIlRuissXZj/sHpQb8p9M5IeO4Z3rjkCP1cxI
  
                  -----END RSA PRIVATE KEY-----
  

  
        .. note::
  

  
            The private key above is shortened to keep the example brief, but
  
            shows how to do multiline string in YAML. The key is followed by a
  
            pipe character, and the mutliline string is indented two more
  
            spaces.
  

  
    contents_grains
  
        .. versionadded:: 2014.7.0
  

  
        Same as contents_pillar, but with grains
  

  
    contents_newline
  
        .. versionadded:: 2014.7.0
  

  
        When using contents, contents_pillar, or contents_grains, this option
  
        ensures the file will have a newline at the end.
  
        When loading some data this newline is better left off. Setting
  
        contents_newline to False will omit this final newline.
  

  
    follow_symlinks : True
  
        .. versionadded:: 2014.7.0
  

  
        If the desired path is a symlink follow it and make changes to the
  
        file to which the symlink points.
  

  
    check_cmd
  
        .. versionadded:: 2014.7.0
  

  
        The specified command will be run with the managed file as an argument.
  
        If the command exits with a nonzero exit code, the command will not be
  
        run.
  
    '''
  
    # Make sure that leading zeros stripped by YAML loader are added back
  
    mode = __salt__['config.manage_mode'](mode)
  

  
    # If no source is specified, set replace to False, as there is nothing
  
    # to replace the file with.
  
    src_defined = source or contents or contents_pillar or contents_grains
  
    if not src_defined and replace:
  
        replace = False
  
        log.warning(
  
            'Neither \'source\' nor \'contents\' nor \'contents_pillar\' nor \'contents_grains\' '
  
            'was defined, yet \'replace\' was set to \'True\'. As there is '
  
            'no source to replace the file with, \'replace\' has been set '
  
            'to \'False\' to avoid reading the file unnecessarily'
  
        )
  

  
    user = _test_owner(kwargs, user=user)
  
    if salt.utils.is_windows():
  
        if group is not None:
  
            log.warning(
  
                'The group argument for {0} has been ignored as this '
  
                'is a Windows system.'.format(name)
  
            )
  
        group = user
  
    ret = {'changes': {},
  
           'comment': '',
  
           'name': name,
  
           'result': True}
  
    if not create:
  
        if not os.path.isfile(name):
  
            # Don't create a file that is not already present
  
            ret['comment'] = ('File {0} is not present and is not set for '
  
                              'creation').format(name)
  
            return ret
  
    u_check = _check_user(user, group)
  
    if u_check:
  
        # The specified user or group do not exist
  
        return _error(ret, u_check)
  
    if not os.path.isabs(name):
  
        return _error(
  
            ret, 'Specified file {0} is not an absolute path'.format(name))
  

  
    if isinstance(env, salt._compat.string_types):
  
        msg = (
  
            'Passing a salt environment should be done using \'saltenv\' not '
  
            '\'env\'. This warning will go away in Salt Boron and this '
  
            'will be the default and expected behavior. Please update your '
  
            'state files.'
  
        )
  
        salt.utils.warn_until('Boron', msg)
  
        ret.setdefault('warnings', []).append(msg)
  
        # No need to set __env__ = env since that's done in the state machinery
  

  
    if os.path.isdir(name):
  
        ret['comment'] = 'Specified target {0} is a directory'.format(name)
  
        ret['result'] = False
  
        return ret
  

  
    if context is None:
  
        context = {}
  
    elif not isinstance(context, dict):
  
        return _error(
  
            ret, 'Context must be formed as a dict')
  
    if defaults and not isinstance(defaults, dict):
  
        return _error(
  
            ret, 'Defaults must be formed as a dict')
  

  
    if len(filter(None, [contents, contents_pillar, contents_grains])) > 1:
  
        return _error(
  
            ret, 'Only one of contents, contents_pillar, and contents_grains is permitted')
  

  
    # If contents_pillar was used, get the pillar data
  
    if contents_pillar:
  
        contents = __salt__['pillar.get'](contents_pillar)
  

  
    if contents_grains:
  
        contents = __salt__['grains.get'](contents_grains)
  

  
    if contents_newline:
  
        # Make sure file ends in newline
  
        if contents and not contents.endswith('\n'):
  
            contents += '\n'
  

  
    if not replace and os.path.exists(name):
  
        # Check and set the permissions if necessary
  
        ret, _ = __salt__['file.check_perms'](name, ret, user, group, mode, follow_symlinks)
  
        if __opts__['test']:
  
            ret['comment'] = 'File {0} not updated'.format(name)
  
        elif not ret['changes'] and ret['result']:
  
            ret['comment'] = ('File {0} exists with proper permissions. '
  
                              'No changes made.'.format(name))
  
        return ret
  

  
    if name in _ACCUMULATORS:
  
        if not context:
  
            context = {}
  
        context['accumulator'] = _ACCUMULATORS[name]
  

  
    try:
  
        if __opts__['test']:
  
            ret['result'], ret['comment'] = __salt__['file.check_managed'](
  
                name,
  
                source,
  
                source_hash,
  
                user,
  
                group,
  
                mode,
  
                template,
  
                context,
  
                defaults,
  
                __env__,
  
                contents,
  
                **kwargs
  
            )
  
            return ret
  

  
        # If the source is a list then find which file exists
  
        source, source_hash = __salt__['file.source_list'](
  
            source,
  
            source_hash,
  
            __env__
  
        )
  
    except CommandExecutionError as exc:
  
        ret['result'] = False
  
        ret['comment'] = 'Unable to manage file: {0}'.format(exc)
  
        return ret
  

  
    # Gather the source file from the server
  
    try:
  
        sfn, source_sum, comment_ = __salt__['file.get_managed'](
  
            name,
  
            template,
  
            source,
  
            source_hash,
  
            user,
  
            group,
  
            mode,
  
            __env__,
  
            context,
  
            defaults,
  
            **kwargs
  
        )
  
    except Exception as exc:
  
        ret['changes'] = {}
  
        log.debug(traceback.format_exc())
  
        return _error(ret, 'Unable to manage file: {0}'.format(exc))
  

  
    if check_cmd:
  
        tmp_filename = salt.utils.mkstemp()
  

  
        # if exists copy existing file to tmp to compare
  
        if __salt__['file.file_exists'](name):
  
            try:
  
                __salt__['file.copy'](name, tmp_filename)
  
            except Exception as exc:
  
                return _error(ret, 'Unable to copy file {0} to {1}: {2}'.format(name, tmp_filename, exc))
  

  
        try:
  
            ret = __salt__['file.manage_file'](
  
                tmp_filename,
  
                sfn,
  
                ret,
  
                source,
  
                source_sum,
  
                user,
  
                group,
  
                mode,
  
                __env__,
  
                backup,
  
                makedirs,
  
                template,
  
                show_diff,
  
                contents,
  
                dir_mode,
  
                follow_symlinks)
  
        except Exception as exc:
  
            ret['changes'] = {}
  
            log.debug(traceback.format_exc())
  
            return _error(ret, 'Unable to check_cmd file: {0}'.format(exc))
  

  
        # file being updated to verify using check_cmd
  
        if ret['changes']:
  
            # Reset ret
  
            ret = {'changes': {},
  
                   'comment': '',
  
                   'name': name,
  
                   'result': True}
  

  
            check_cmd_opts = {}
  
            if 'shell' in __grains__:
  
                check_cmd_opts['shell'] = __grains__['shell']
  

  
            cret = mod_run_check_cmd(check_cmd, tmp_filename, **check_cmd_opts)
  
            if isinstance(cret, dict):
  
                ret.update(cret)
  
                return ret
  
        else:
  
            ret = {'changes': {},
  
                   'comment': '',
  
                   'name': name,
  
                   'result': True}
  

  
    if comment_ and contents is None:
  
        return _error(ret, comment_)
  
    else:
  
        try:
  
            return __salt__['file.manage_file'](
  
                name,
  
                sfn,
  
                ret,
  
                source,
  
                source_sum,
  
                user,
  
                group,
  
                mode,
  
                __env__,
  
                backup,
  
                makedirs,
  
                template,
  
                show_diff,
  
                contents,
  
                dir_mode,
  
                follow_symlinks)
  
        except Exception as exc:
  
            ret['changes'] = {}
  
            log.debug(traceback.format_exc())
  
            return _error(ret, 'Unable to manage file: {0}'.format(exc))

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-544411-1-1.html 上篇帖子: saltstack 之job-cache管理 下篇帖子: SaltStack的grains学习
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表