我正在尝试为绑定建立反向查找(PTR)记录。

我有一个 CSV 文件,其中 IP 和主机名字段已加载到字典中(来自 read_csv),所以我猜它实际上是一个字典列表:

ok: [localhost] => {
    "msg": [
        {
            "changed": false,
            "dict": {},
            "failed": false,
            "list": [
                {
                    "hostname": "host1",
                    "ip": "10.32.1.32"                                                            
                },
                {
                    "hostname": "host2",
                    "ip": "10.50.6.71"                                                            
                },
                {                                                                                     
                    "hostname": "host3",
                    "ip": "10.36.254.41"                                                          
                },
                {
                    "hostname": "host4",
                    "ip": "10.36.254.42"
                }
            ]
        },
    ]
}

我有一个从上述字典中得出的唯一的反转最后两个八位字节列表:

ok: [localhost] => {
    "msg": [
        [
            "32.10",
            "50.10",
            "36.10"
        ],
    ]
}

我想要的是一个如下所示的新字典(格式可能不正确,请原谅):

{
   "32.10": 
          {
              "hostname": "host1",
              "ip": "10.32.1.32"                                                            
          },
   "50.10":
          {
              "hostname": "host2",
              "ip": "10.50.6.71"                                                            
          },
   "36.10":
          {                                                                                     
              "hostname": "host3",
              "ip": "10.36.254.41"                                                          
          },
          {
              "hostname": "host4",
              "ip": "10.36.254.42"
          }
}

新的“超级”字典应该只包含匹配网络的 IP + 主机名条目(例如,所有 10.36.xx 条目都应位于“36.10”下)。

从这个新的字典中,我应该能够在模板中循环它来生成 PTR 记录。

我不知道如何合并这两个数据结构。:-/

谢谢你!

1

  • 您想要的数据结构不合理。看起来您打算让每个键的值都是一个字典列表。请适当更新语法;您可以在各处找到 JSON 语法文档(例如)。


    – 


最佳答案
2

您可以使用来构建最终的词典。

像这样:

- hosts: localhost
  gather_facts: false
  vars:
    results:
      - hostname: host1
        ip: 10.32.1.32
      - hostname: host2
        ip: 10.50.6.71
      - hostname: host3
        ip: 10.36.254.41
      - hostname: host4
        ip: 10.36.254.42
  tasks:
    - loop: "{{ results }}"
      vars:
        reversed: {}
        key: >-
          {{"{}.{}".format(*((item.ip.split('.'))[:2]|reverse))}}
      set_fact:
        reversed: >-
          {{
          reversed|combine({key: reversed.get(key, []) + [item]}, list_merge='append_rp')
          }}

    - debug:
        var: "reversed"

我们使用以下表达式构造字典键:

{{"{}.{}".format(*((item.ip.split('.'))[:2]|reverse))}}

这会将“abcd”之类的内容转换为“ba”。我们使用它 + 过滤器combine+过滤器list_merge的选项combine来获取最终的数据结构;上述剧本产生了以下输出:

TASK [debug] *******************************************************************
ok: [localhost] => {
    "reversed": {
        "32.10": [
            {
                "hostname": "host1",
                "ip": "10.32.1.32"
            }
        ],
        "36.10": [
            {
                "hostname": "host3",
                "ip": "10.36.254.41"
            },
            {
                "hostname": "host4",
                "ip": "10.36.254.42"
            }
        ],
        "50.10": [
            {
                "hostname": "host2",
                "ip": "10.50.6.71"
            }
        ]
    }
}

1

  • larsks,我欠你太多了!非常感谢!它运行完美。唯一的问题是它不能与 ansible v2.9.6(Ubuntu 20.04)一起使用,我不得不升级到最新的 v2.12.2,它运行得很好。这正是我需要的。谢谢!


    – 

  • 有了钥匙
  keys: ['32.10', '50.10', '36.10']
  • 选择值
  vals: |
    {% for k in keys|map('split', '.')|map('reverse')|map('join', '.') %}
    - {{ results | selectattr('ip', 'match', k) }}
    {% endfor %}

给出

  vals: |-
    - [{'hostname': 'host1', 'ip': '10.32.1.32'}]
    - [{'hostname': 'host2', 'ip': '10.50.6.71'}]
    - [{'hostname': 'host3', 'ip': '10.36.254.41'}, {'hostname': 'host4', 'ip': '10.36.254.42'}]
  • 创建词典
  rev: "{{ dict(keys|zip(vals|from_yaml)) }}"

给出你想要的

  rev:
    '32.10':
    - {hostname: host1, ip: 10.32.1.32}
    '36.10':
    - {hostname: host3, ip: 10.36.254.41}
    - {hostname: host4, ip: 10.36.254.42}
    '50.10':
    - {hostname: host2, ip: 10.50.6.71}

笔记:

  • 完整测试剧本的示例
- hosts: localhost
  
  vars:

    keys: ['32.10', '50.10', '36.10']
    results:
      - {hostname: host1, ip: 10.32.1.32}
      - {hostname: host2, ip: 10.50.6.71}
      - {hostname: host3, ip: 10.36.254.41}
      - {hostname: host4, ip: 10.36.254.42}

    vals: |
      {% for k in keys|map('split', '.')|map('reverse')|map('join', '.') %}
      - {{ results | selectattr('ip', 'match', k) }}
      {% endfor %}
    rev: "{{ dict(keys|zip(vals|from_yaml)) }}"

  tasks:

    - debug:
        var: vals
    - debug:
        var: rev | to_yaml
  • (可选)将列表转换为字典
  rev: "{{ dict(keys |
                zip(vals |
                    from_yaml |
                    map('items2dict',
                        key_name='hostname',
                        value_name='ip'))) }}"

给出

  rev:
    '32.10':
      host1: 10.32.1.32
    '36.10':
      host3: 10.36.254.41
      host4: 10.36.254.42
    '50.10':
      host2: 10.50.6.71

, 或者

  rev: "{{ dict(keys |
                zip(vals |
                    from_yaml |
                    map('items2dict',
                        value_name='hostname',
                        key_name='ip'))) }}"

给出

  rev:
    '32.10':
      10.32.1.32: host1
    '36.10':
      10.36.254.41: host3
      10.36.254.42: host4
    '50.10':
      10.50.6.71: host2