Как я могу построить строку из значения и списка значений? - PullRequest
2 голосов
/ 23 мая 2019

[Первый раз спрашивающий. Я думаю , что я нацелил это на вопрос Ansible. В противном случае приветствуется легкое перенаправление!]

Дано:

gid: 80
ports: [80, 443]

где количество портов может варьироваться от 0 до многих

Я бы хотел создать строку, подобную этой:

"ГИД: 80: TCP: 80, GID: 80: TCP: 443"

(что является строкой правила FreeBSD mac_portacl)

Самое дальнее, что я получил:

portacl_rules: "{{ ports | zip_longest([], fillvalue='80') | list }}"

Что дает мне что-то вроде этого:

    "msg": [
        [
            80,
            "80"
        ],
        [
            443,
            "80"
        ]
    ]

но:

  • код жестко запрограммирован, я не могу понять, как интерполировать значение переменной; и
  • Я не могу перевести список в окончательную строку.

Я могу создать строку gid, gid:80, определив временную переменную:

gid: 80
_tmp_gid: "gid:{{ gid }}"

но так как я не могу вставить строку в значение заполнения, я застрял.

Я обошел вокруг фильтра format, но он, кажется, принимает выходную строку в качестве входных данных, а значения - в качестве аргументов, что противоположно моей ситуации.

Есть предложения?

1 Ответ

0 голосов
/ 23 мая 2019

Если вы не возражаете против пары set_fact задач, вы можете сделать это так:

- set_fact:
    rules_list: "{{ rules_list|default([]) + ['gid:{}:tcp:{}'.format(gid, item)] }}"
  loop: "{{ ports }}"

- set_fact:
    rules_str_1: "{{ ','.join(rules_list) }}"

- debug:
    var: rules_str_1

Первая задача создает список в форме:

[
  "gid:80:tcp:80",
  "gid:80:tcp:443"
]

Второе задание объединяет эти элементы, используя ,.

Вы можете выполнить это за одну операцию, используя выражение слегка хайриер, включающее фильтр regex_replace:

- set_fact:
    rules_str_2: '{{ ",".join(ports|map("regex_replace", "^(.*)$", "gid:{}:tcp:\1".format(gid))) }}'

- debug:
    var: rules_str_2

Чтобы эта задача set_fact работала так, как написано, вы должны использовать одинарные кавычки снаружи (это запрещает использование \ в качестве escape-символа). Вы можете поменять кавычки, но тогда вам нужно будет написать \\ вместо \. Напомним, что (...) в выражении соответствия создает группу захвата, а \1 в строке замены расширяется до значения первой группы захвата.


Собираем все вместе в сборнике пьес:

---
- hosts: localhost
  gather_facts: false
  vars:
    gid: 80
    ports: [80, 443]
  tasks:
    - set_fact:
        rules_list: "{{ rules_list|default([]) + ['gid:{}:tcp:{}'.format(gid, item)] }}"
      loop: "{{ ports }}"

    - set_fact:
        rules_str_1: "{{ ','.join(rules_list) }}"

    - debug:
        var: rules_str_1

    - set_fact:
        rules_str_2: '{{ ",".join(ports|map("regex_replace", "(.*)", "gid:{}:tcp:\1".format(gid))) }}'

    - debug:
        var: rules_str_2

Что даст следующий результат:

PLAY [localhost] ******************************************************************************************************************************************************************************

TASK [set_fact] *******************************************************************************************************************************************************************************
ok: [localhost] => (item=80)
ok: [localhost] => (item=443)

TASK [set_fact] *******************************************************************************************************************************************************************************
ok: [localhost]

TASK [debug] **********************************************************************************************************************************************************************************
ok: [localhost] => {
    "rules_str_1": "gid:80:tcp:80,gid:80:tcp:443"
}

TASK [set_fact] *******************************************************************************************************************************************************************************
ok: [localhost]

TASK [debug] **********************************************************************************************************************************************************************************
ok: [localhost] => {
    "rules_str_2": "gid:80:tcp:80,gid:80:tcp:443"
}

PLAY RECAP ************************************************************************************************************************************************************************************
localhost                  : ok=5    changed=0    unreachable=0    failed=0
...