浅聊ansible的幂等 file模块源码解析

2024-01-26 16:20

本文主要是介绍浅聊ansible的幂等 file模块源码解析,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

描述#

  幂等性是在实际应用中经常需要考虑的概念,尤其是运维中。相较于将幂等性理解为各种异常情况的综合处理,将其理解为执行时需要考虑到在前次执行产生的影响的情况下能够正常执行则会更加容易接近业务需求。
  ansible包含众多的模块,大部分内置模块都能够保证操作的幂等性,即相关操作的多次执行能够达到相同结果这一特性,不会出现多次执行带来副作用的影响。但是也有不满足幂等原则的,比如shell模块、raw模块、command模块。

幂等操作和非幂等操作的对比

场景说明:
比如实现删除一个临时性的文件/root/testfile的操作,如果希望其在相同的条件下,多次执行能够保持相同的结果和不会带来其它副作用,至少需要保证此操作在/root/testfile文件存在和不存在的情况下都能正常动作。

# 当采用raw模块执行shell命令删除文件,第一次删除是成功,当执行第二次删除也是成功的,但是在生产环境这结果是不理想的,比如重启一个服务,你会随便重启服务吗?

[root@Server-1~]# touch /root/testfile
[root@Server-1~]# ansible localhost -m shell -a "rm -rf testfile"
localhost | CHANGED | rc=0 >>
[root@Server-1~]# ansible localhost -m shell -a "rm -rf testfile"
localhost | CHANGED | rc=0 >>

# 当采用file 模块执行删除文件,第一次执行删除文件成功changed: true,多次执行删除文件都是同一样的结果,不会带来副作用的影响changed: Fasle

[root@Server-1~]# touch /root/testfile
[root@Server-1~]# ansible localhost -m file -a "path=/root/testfile state=absent"
localhost | CHANGED => {"changed": true, "path": "/root/testfile", "state": "absent"
}
[root@Server-1~]# ansible localhost -m file -a "path=/root/testfile state=absent"
localhost | SUCCESS => {"changed": false, "path": "/root/testfile", "state": "absent"
}
那file模块是如何实现幂等的呢?如下是file模块执行absent文件时的代码(有中文注释)

vim /usr/lib/python2.7/site-packages/ansible/modules/files/file.py
.....
def get_state(path):''' Find out current state '''b_path = to_bytes(path, errors='surrogate_or_strict')try:if os.path.lexists(b_path): # 如果文件存在返回file,文件不存在返回absentif os.path.islink(b_path):return 'link'elif os.path.isdir(b_path):return 'directory'elif os.stat(b_path).st_nlink > 1:return 'hard'# could be many other things, but defaulting to filereturn 'file' return 'absent'except OSError as e:if e.errno == errno.ENOENT:  # It may already have been removedreturn 'absent'else:raisedef ensure_absent(path):b_path = to_bytes(path, errors='surrogate_or_strict')prev_state = get_state(b_path) # 获取文件的状态result = {}if prev_state != 'absent': # 当prev_state='directory' or 'file' 为真diff = initial_diff(path, 'absent', prev_state)if not module.check_mode:if prev_state == 'directory': # 如果prev_state='directory', 则删除目录try:shutil.rmtree(b_path, ignore_errors=False)except Exception as e:raise AnsibleModuleError(results={'msg': "rmtree failed: %s" % to_native(e)})else:try:os.unlink(b_path) # 如果prev_state='file', 则删除文件except OSError as e:if e.errno != errno.ENOENT:  # It may already have been removedraise AnsibleModuleError(results={'msg': "unlinking failed: %s " % to_native(e),'path': path})result.update({'path': path, 'changed': True, 'diff': diff, 'state': 'absent'}) # 删除文件成功,动作有改变,changed=Trueelse:result.update({'path': path, 'changed': False, 'state': 'absent'}) # 如果prev_state='absent', 动作没有改变,changed=False, 实现多次操作执行不会有任何改变。return resultdef main():global modulemodule = AnsibleModule(argument_spec=dict(state=dict(type='str', choices=['absent', 'directory', 'file', 'hard', 'link', 'touch']),path=dict(type='path', required=True, aliases=['dest', 'name']),_original_basename=dict(type='str'),  # Internal use only, for recursive opsrecurse=dict(type='bool', default=False),force=dict(type='bool', default=False),  # Note: Should not be in file_common_args in futurefollow=dict(type='bool', default=True),  # Note: Different default than file_common_args_diff_peek=dict(type='bool'),  # Internal use only, for internal checks in the action pluginssrc=dict(type='path'),  # Note: Should not be in file_common_args in futuremodification_time=dict(type='str'),modification_time_format=dict(type='str', default='%Y%m%d%H%M.%S'),access_time=dict(type='str'),access_time_format=dict(type='str', default='%Y%m%d%H%M.%S'),),add_file_common_args=True,supports_check_mode=True,)# When we rewrite basic.py, we will do something similar to this on instantiating an AnsibleModulesys.excepthook = _ansible_excepthookadditional_parameter_handling(module.params)params = module.paramsstate = params['state']recurse = params['recurse']force = params['force']follow = params['follow']path = params['path']src = params['src']timestamps = {}timestamps['modification_time'] = keep_backward_compatibility_on_timestamps(params['modification_time'], state)timestamps['modification_time_format'] = params['modification_time_format']timestamps['access_time'] = keep_backward_compatibility_on_timestamps(params['access_time'], state)timestamps['access_time_format'] = params['access_time_format']# short-circuit for diff_peekif params['_diff_peek'] is not None:appears_binary = execute_diff_peek(to_bytes(path, errors='surrogate_or_strict'))module.exit_json(path=path, changed=False, appears_binary=appears_binary)if state == 'file':result = ensure_file_attributes(path, follow, timestamps)elif state == 'directory':result = ensure_directory(path, follow, recurse, timestamps)elif state == 'link':result = ensure_symlink(path, src, follow, force, timestamps)elif state == 'hard':result = ensure_hardlink(path, src, follow, force, timestamps)elif state == 'touch':result = execute_touch(path, follow, timestamps)elif state == 'absent': result = ensure_absent(path) # 执行删除文件时,调用方法 def ensure_absentmodule.exit_json(**result)if __name__ == '__main__':main()

这篇关于浅聊ansible的幂等 file模块源码解析的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/647364

相关文章

PostgreSQL的扩展dict_int应用案例解析

《PostgreSQL的扩展dict_int应用案例解析》dict_int扩展为PostgreSQL提供了专业的整数文本处理能力,特别适合需要精确处理数字内容的搜索场景,本文给大家介绍PostgreS... 目录PostgreSQL的扩展dict_int一、扩展概述二、核心功能三、安装与启用四、字典配置方法

深度解析Java DTO(最新推荐)

《深度解析JavaDTO(最新推荐)》DTO(DataTransferObject)是一种用于在不同层(如Controller层、Service层)之间传输数据的对象设计模式,其核心目的是封装数据,... 目录一、什么是DTO?DTO的核心特点:二、为什么需要DTO?(对比Entity)三、实际应用场景解析

深度解析Java项目中包和包之间的联系

《深度解析Java项目中包和包之间的联系》文章浏览阅读850次,点赞13次,收藏8次。本文详细介绍了Java分层架构中的几个关键包:DTO、Controller、Service和Mapper。_jav... 目录前言一、各大包1.DTO1.1、DTO的核心用途1.2. DTO与实体类(Entity)的区别1

Java中的雪花算法Snowflake解析与实践技巧

《Java中的雪花算法Snowflake解析与实践技巧》本文解析了雪花算法的原理、Java实现及生产实践,涵盖ID结构、位运算技巧、时钟回拨处理、WorkerId分配等关键点,并探讨了百度UidGen... 目录一、雪花算法核心原理1.1 算法起源1.2 ID结构详解1.3 核心特性二、Java实现解析2.

Python中re模块结合正则表达式的实际应用案例

《Python中re模块结合正则表达式的实际应用案例》Python中的re模块是用于处理正则表达式的强大工具,正则表达式是一种用来匹配字符串的模式,它可以在文本中搜索和匹配特定的字符串模式,这篇文章主... 目录前言re模块常用函数一、查看文本中是否包含 A 或 B 字符串二、替换多个关键词为统一格式三、提

使用Python绘制3D堆叠条形图全解析

《使用Python绘制3D堆叠条形图全解析》在数据可视化的工具箱里,3D图表总能带来眼前一亮的效果,本文就来和大家聊聊如何使用Python实现绘制3D堆叠条形图,感兴趣的小伙伴可以了解下... 目录为什么选择 3D 堆叠条形图代码实现:从数据到 3D 世界的搭建核心代码逐行解析细节优化应用场景:3D 堆叠图

深度解析Python装饰器常见用法与进阶技巧

《深度解析Python装饰器常见用法与进阶技巧》Python装饰器(Decorator)是提升代码可读性与复用性的强大工具,本文将深入解析Python装饰器的原理,常见用法,进阶技巧与最佳实践,希望可... 目录装饰器的基本原理函数装饰器的常见用法带参数的装饰器类装饰器与方法装饰器装饰器的嵌套与组合进阶技巧

解析C++11 static_assert及与Boost库的关联从入门到精通

《解析C++11static_assert及与Boost库的关联从入门到精通》static_assert是C++中强大的编译时验证工具,它能够在编译阶段拦截不符合预期的类型或值,增强代码的健壮性,通... 目录一、背景知识:传统断言方法的局限性1.1 assert宏1.2 #error指令1.3 第三方解决

全面解析MySQL索引长度限制问题与解决方案

《全面解析MySQL索引长度限制问题与解决方案》MySQL对索引长度设限是为了保持高效的数据检索性能,这个限制不是MySQL的缺陷,而是数据库设计中的权衡结果,下面我们就来看看如何解决这一问题吧... 目录引言:为什么会有索引键长度问题?一、问题根源深度解析mysql索引长度限制原理实际场景示例二、五大解决

深度解析Spring Boot拦截器Interceptor与过滤器Filter的区别与实战指南

《深度解析SpringBoot拦截器Interceptor与过滤器Filter的区别与实战指南》本文深度解析SpringBoot中拦截器与过滤器的区别,涵盖执行顺序、依赖关系、异常处理等核心差异,并... 目录Spring Boot拦截器(Interceptor)与过滤器(Filter)深度解析:区别、实现