Есть ли способ в Ansible заменить значение словаря на основе поиска k: v на другой словарь?

У меня есть словарь k: v имени хоста: IP, который я хочу использовать при поиске из другого словаря, чтобы заменить записи, соответствующие ключу из 1-го словаря, и заменить его соответствующим значением во 2-м словаре;

1st:

"nb_console_ip": {
    "office-con01": "10.20.30.100",

2nd:

"nb_console_port": [
        {
            "console": "office-con01", 
            "hostname": "office-core01", 
            "port": "con1"
        }, 
        {
            "console": "office-con01", 
            "hostname": "office-core02", 
            "port": "con2"
        }, 
        {
            "console": "office-con01", 
            "hostname": "office-fw01", 
            "port": "con5"
        }, 
        {
            "console": "office-con01", 
            "hostname": "office-fw02", 
            "port": "con6"
        }, 
        {
            "console": "office-con01", 
            "hostname": "office-vpn01", 
            "port": "con3"
        }, 
        {
            "console": "office-con01", 
            "hostname": "office-vpn02", 
            "port": "con4"
        }
    ]

По сути, я пытаюсь установить_fact для 2-го dict с помощью поиска и замены office-con01 на 10.20.30.100, но для списка из 30+ хостов. Причина в том, что у меня есть шаблон jinja, который будет использовать 3 значения console_ip, hostname и port. Я подумал, может быть, есть более подходящие фильтры для поиска, поиска, замены и т. Д. Оба набора данных являются результатами json_query при возврате из вызова API.


person Niall    schedule 06.03.2020    source источник


Ответы (1)


Можно зацикливать include_tasks и заменять k:v на каждой итерации. Например, создать файл с задачей, заменяющей outer_item.key: outer_item.value, отправленный из внешнего цикла.

shell> cat test-task.yml
- set_fact:
    nb_console_port: "{{ nb_console_port|difference([item]) +
                         [dict(my_keys|zip(my_values2))] }}"
  vars:
    my_keys: "{{ item.keys()|list }}"
    my_values: "{{ item.values()|list }}"
    my_values2: "{{ my_values|
                   map('regex_replace', outer_item.key, outer_item.value)|
                   list }}"
  loop: "{{ nb_console_port }}"

Тогда пьеса, представленная ниже, сделает свою работу. Переменная nb_console_port хранится в файле test-data.yml

shell> cat test.yml
- hosts: localhost

  vars:

    nb_console_ip:
      office-con01: "10.20.30.100"
      office-con02: "10.20.30.101"
      office-con03: "10.20.30.102"

  tasks:

    - include_vars: test-data.yml

    - include_tasks: test-task.yml
      loop: "{{ nb_console_ip|dict2items }}"
      loop_control:
        loop_var: outer_item

    - debug:
        var: nb_console_port
person Vladimir Botka    schedule 06.03.2020
comment
Я просто пытался применить ту же логику к другому regex_replace, но разница в моем новом состоит в том, что я хочу найти строку и заменить ее целым числом, но как бы я ни работал, он выплевывает: object of type 'int' has no len() - поиск по этим строкам показывает, как Python обрабатывает строки и целые числа, и рекомендации по преобразованию int в str для использования - но мне нужен int на другом конце .. - person Niall; 13.03.2020
comment
Возможно, вы захотите открыть новый вопрос. - person Vladimir Botka; 13.03.2020
comment
Круто, добавлено здесь: stackoverflow.com/questions/60671583 - person Niall; 13.03.2020