如何手动调用并改造Ansible的f5networks bigip_device_info模块
实现方案
核心原理说明
- ArgumentSpec作用:f5networks集合里的ArgumentSpec类是预封装的参数规则集合,
spec.argument_spec返回的就是符合AnsibleModule要求的入参定义(包括参数类型、必填校验、互斥规则等),你之前的代码里直接传spec而非spec.argument_spec是第一个错误点。 - 手动给模块传参的合法方式:AnsibleModule实例化后,所有入参都存在
mock_module.params字典里,你可以直接给这个字典赋值,不需要依赖Ansible从playbook注入参数,这个是模块开发的标准玩法,不属于hack。 - 你原有代码的其他问题:
- 没有把
get_device_info接收的参数写入mock_module.params,ModuleManager只会读取绑定module对象的params属性,参数为空自然无法运行 - 结果拼接用了
extend,每个设备返回的是字典,应该用append方法
- 没有把
修正后的完整实现
#!/usr/bin/python from ansible.module_utils.basic import AnsibleModule from ansible_collections.f5networks.f5_modules.plugins.modules.bigip_device_info import ( ArgumentSpec, ModuleManager, F5ModuleError ) class BigipDeviceInfo: @staticmethod def get_device_info(common_args: dict, server_addr: str): # 初始化参数规则 spec = ArgumentSpec() # 实例化mock模块,关闭额外参数校验避免报错 mock_module = AnsibleModule( argument_spec=spec.argument_spec, supports_check_mode=spec.supports_check_mode, check_invalid_arguments=False ) # 手动注入参数 mock_module.params = common_args.copy() mock_module.params['server'] = server_addr try: mm = ModuleManager(module=mock_module) results = mm.exec_module() # 补充设备地址方便结果匹配 results['server'] = server_addr results['success'] = True return results except F5ModuleError as e: return { 'server': server_addr, 'success': False, 'msg': str(e) } @staticmethod def run(server_array: list, common_args: dict): res = [] for server in server_array: res.append(BigipDeviceInfo.get_device_info(common_args, server)) return res if __name__ == "__main__": # 定义外层模块入参 module_args = dict( server_array=dict(type='list', required=True, elements='str'), user=dict(type='str', required=True), password=dict(type='str', required=True, no_log=True), validate_certs=dict(type='bool', default=False) ) # 实例化外层模块 module = AnsibleModule( argument_spec=module_args, supports_check_mode=True ) # 提取公共参数 common_args = { 'user': module.params['user'], 'password': module.params['password'], 'validate_certs': module.params['validate_certs'] } # 执行批量查询 output = BigipDeviceInfo.run( server_array=module.params['server_array'], common_args=common_args ) # 返回结果 module.exit_json(output=output, changed=False)
使用说明
在playbook里调用你自己封装的这个模块时,直接传以下参数即可:
- name: 批量获取F5设备信息 my_custom_bigip_device_info: server_array: - 192.168.1.10 - 192.168.1.11 - 192.168.1.12 user: admin password: your_password validate_certs: no register: f5_info
最佳实践建议
- 敏感参数(比如password)加
no_log=True避免参数被打印到日志 - 每个设备的返回结果里加
success标识和对应server地址,后续在playbook里处理结果不用做地址匹配 - 外层模块设置
changed=False,因为信息查询不会修改设备配置,符合Ansible幂等性要求
内容的提问来源于stack exchange,提问作者TristenHarr
相关产品推荐
相关产品推荐

