web-dev-qa-db-fra.com

La liste de filtres Jinja2 utilisant une chaîne contient un test

J'essaie de filtrer une liste en ansible dans Jinja2 lorsque les éléments contiennent une chaîne, mais la documentation de Jinja ne semble pas assez claire pour que je puisse la comprendre.

Voici ce que j'ai jusqu'à présent:

- name: run script
  command: /usr/tmp/run_script.py
  register: script_results

- name: display run info
  debug:
    var: "{{script_results.stdout_lines | select(\"'running script' in script_results.stdout_lines\") }}"

Mais tout ce que je reçois est l'erreur:

"<generator object _select_or_reject at 0x13851e0>": "VARIABLE IS NOT DEFINED!"

Ainsi, par exemple, si stdout_lines contient ["apples","running script one","oranges","running script two"], Je veux imprimer

running script one
running script two

Ils ont documentation pour select et documentation pour les tests intégrés , mais ils n'affichent pas le test "in", et je ne sais pas comment ils fonctionnent dans le contexte de cette variable ansible.

J'ai essayé de le résoudre comme ceci:

- name: display run info
  debug:
    var: item
  with_items: "{{script_results.stdout_lines}}"
  when: "'running script' in item"

Mais cela affiche "sauter" pour chaque ligne qui ne réussit pas le test ... un peu contre le but!

10
CorayThan

Le filtre select prendrait un autre filtre. Comme dans la documentation odd, qui ne renverra que les éléments impairs de la liste. Le filtre avec lequel vous souhaitez combiner select est equalto.

Maintenant, voici la chose. Ansible regroupe une très ancienne version de Jinja2, qui ne contient tout simplement pas le filtre equalto. Oui, cela le rend inutile, sauf si vous souhaitez filtrer les éléments impairs. (Ce que personne n'a jamais voulu dans l'histoire ...)

De plus, je n'ai pas encore réussi à faire fonctionner les plugins de filtre personnalisés dans Ansible 2. Vous êtes donc à peu près obligé de pirater quelque chose de laid ensemble.

helloV a déjà montré une option. Voici une autre idée:

- name: run script
  Shell: /usr/tmp/run_script.py | grep "running script"
  register: script_results

Mettre à jour:

J'ai récemment découvert que vous pouvez utiliser match (pas un filtre Jinja2 standard mais ajouté par Ansible) avec select. C'est un bon remplacement pour le filtre eualto et vous pouvez utiliser des expressions régulières. Cela devrait fonctionner:

{{ script_results.stdout_lines | select("match", ".*running script.*") }}
15
udondan

Je comprends qu'il peut y avoir plus d'une façon de procéder. Est-ce que cela fonctionnera pour vous?

  - debug: var={{item}}
    when: item.find('running script') > -1
    with_items: script_results.stdout_lines
4
helloV

J'ai fini par écrire un script python pour le faire, car je n'ai pas pu obtenir ansible ou ancient-jinja2 pour faire la coupe.

Tâches possibles:

- name: gather run info
  command: "{{role_path}}/files/print_results.py {{script_results.stdout_lines}}"
  register: script_print_results
  delegate_to: 127.0.0.1
  run_once: true

- name: display run info
  debug:
    var: script_print_results.stdout_lines
  delegate_to: 127.0.0.1
  run_once: true

Script Python:

for result_line in sys.argv[1:]:
    if "running script:" in result_line:
        print result_line[1:-1]
1
CorayThan

Vous pouvez créer une nouvelle liste avec set_fact et imprimer les éléments d'une nouvelle liste.

- hosts: localhost
  gather_facts: false
  vars:
    script_stdout_lines:
      - apples
      - running script one
      - oranges
      - running script two
  tasks:
    - set_fact:
        new_list: "{{ new_list | default([]) + [item] }}"
      with_items: "{{ script_stdout_lines }}"
      when: '"running script" in item'
    - debug: var=new_list

Résultat:

TASK [set_fact] *********************************************************************************************************************
skipping: [localhost] => (item=apples) 
ok: [localhost] => (item=running script one)
skipping: [localhost] => (item=oranges) 
ok: [localhost] => (item=running script two)

TASK [debug] ************************************************************************************************************************
ok: [localhost] => {
    "new_list": [
        "running script one",
        "running script two"
    ]
}

Il imprime skipping pendant set_fact opération mais à la fin il fournit une nouvelle liste avec les seuls éléments correspondants.

1
Akif