You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在自定义Ansible模块中访问ansible_all_ipv4_addresses等事实?

问题:自定义Ansible模块中无需显式传递即可访问ansible_all_ipv4_addresses事实?

我正在开发自定义Ansible模块,需要直接在模块代码中访问ansible_all_ipv4_addresses这类事实,但不确定如何无需从playbook显式传递就能获取这些信息。

比如在SaltStack中可以通过grains访问系统信息,但我没找到Ansible自定义模块里的等效方式。我的需求是:在自定义模块内获取ansible_all_ipv4_addresses事实,不需要在playbook里手动将其作为参数传递。

以下是我尝试的示例代码:

from ansible.module_utils.basic import AnsibleModule

def run_module():
    module = AnsibleModule(
        argument_spec={},
        supports_check_mode=True
    )

    # 如何在这里访问ansible_all_ipv4_addresses?
    ipv4_addresses = ???

    module.exit_json(changed=False, ipv4=ipv4_addresses)

if __name__ == '__main__':
    run_module()

是否存在类似SaltStack grains的方式,能在自定义模块内直接访问ansible_all_ipv4_addresses这类事实?如果没有,在自定义模块中访问这些事实的推荐方案是什么?


答案

核心结论

Ansible自定义模块没有类似SaltStack Grains的内置机制,可以直接访问控制节点预收集的ansible_all_ipv4_addresses这类事实。原因是:Ansible的事实是在控制节点通过setup模块收集并存储的,而自定义模块是在目标节点上独立运行的进程,两者之间没有自动的事实传递通道。

推荐方案

方案1:通过Playbook显式传递事实(最常用)

这是Ansible生态中标准的做法,仅需在调用模块时将需要的事实作为参数传入,模块通过argument_spec定义参数接收即可。

修改后的模块代码:

from ansible.module_utils.basic import AnsibleModule

def run_module():
    module = AnsibleModule(
        argument_spec={
            'ipv4_addresses': {'type': 'list', 'required': True}
        },
        supports_check_mode=True
    )

    # 从模块参数中获取传递的事实
    ipv4_addresses = module.params['ipv4_addresses']

    module.exit_json(changed=False, ipv4=ipv4_addresses)

if __name__ == '__main__':
    run_module()

对应的Playbook调用示例:

- name: 调用自定义模块
  hosts: all
  tasks:
    - name: 传递IPv4地址事实给自定义模块
      custom_module:
        ipv4_addresses: "{{ ansible_all_ipv4_addresses }}"

方案2:模块内自行收集系统信息(完全独立)

如果不想依赖Playbook传递事实,可以让模块直接在目标节点上执行系统命令或调用Python库获取IPv4地址,脱离Ansible预收集事实的依赖。

示例代码(通过系统命令解析):

from ansible.module_utils.basic import AnsibleModule

def get_all_ipv4_addresses(module):
    """在目标节点上直接收集非回环IPv4地址"""
    rc, out, err = module.run_command(['ip', '-4', 'addr', 'show'])
    if rc != 0:
        module.fail_json(msg='获取IPv4地址失败', error=err)
    
    addresses = []
    for line in out.splitlines():
        if 'inet ' in line:
            ip = line.split()[1].split('/')[0]
            if not ip.startswith('127.'):
                addresses.append(ip)
    return addresses

def run_module():
    module = AnsibleModule(
        argument_spec={},
        supports_check_mode=True
    )

    # 自行收集IPv4地址
    ipv4_addresses = get_all_ipv4_addresses(module)

    module.exit_json(changed=False, ipv4=ipv4_addresses)

if __name__ == '__main__':
    run_module()

注:该方案兼容性强,无需额外安装Python依赖库,适合大多数Linux节点。

内容的提问来源于stack exchange,提问作者Tony

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 08:08:25