LINUX.ORG.RU

Ansible по условию When

 ,


1

1

Доброго времени суток. Необходимо выяснить присутствует ли слово в переменной регистра. Вроде бы все тривиально, но правило не работает. Пишет skipping - условие не выполнилось. Хотя далее вывожу debug и все есть...


---
- name: Run show commands on routers
  hosts: cisco-asa
  gather_facts: false
  connection: local

  tasks:
    - name: sh int
      asa_command:
        commands: sh int ip brief
        provider: "{{ cli }}"
      register: sh_int_status

    - name: When
      debug:
        msg: "YES"
      when: "'Ethernet0/0' in sh_int_status"
    - name: debug
      debug: var=sh_int_status.stdout_lines

Если

sh_int_status.stdout_lines
выводит правильно, то надо

when: "'Ethernet0/0' in sh_int_status.stdout"

vrutkovs ★★ ()
Ответ на: комментарий от vrutkovs

Вроде сделал, но не работает.

---
- name: Run show commands on routers
  hosts: cisco-sw
  gather_facts: false
  connection: local

  tasks:
    - name: int shutdown
      ios_command:
        commands: sh int status
        provider: "{{ cli }}"
      register: sh_int_status

    - name: When
      debug:
        msg: "ОК"
      when: "'Gi0/1' in sh_int_status.stdout"
    - name: debug
      debug: var=sh_int_status.stdout_lines

Вот вывод:

PLAY [Run show commands on routers] ************************************************************

TASK [int shutdown] ****************************************************************************
ok: [10.1.1.10]

TASK [When] ************************************************************************************
skipping: [10.1.1.10]

TASK [debug] ***********************************************************************************
ok: [10.1.1.10] => {
    "sh_int_status.stdout_lines": [
        [
            "Port      Name               Status       Vlan       Duplex  Speed Type",
            "Gi0/1     not_used           connected    10         a-full a-1000 10/100/1000BaseTX",
            "Gi0/2     not_used           notconnect   10           auto   auto 10/100/1000BaseTX",
            "Gi0/3     not_used           notconnect   10           auto   auto 10/100/1000BaseTX",

vadim55_242 ()
Ответ на: комментарий от kernelpanic

Кавычки обязательно нужны, без них ошибку выдает. Как я понял там два варианта синтаксиса:

when: "'Gi0/1' in sh_int_status.stdout"

или так

when: '"Gi0/1" in sh_int_status.stdout'

vadim55_242 ()
Ответ на: комментарий от vadim55_242

вот что выяснил: если у меня в регистре одна строка и я запускаю поиск по слову, то работает. Если много строк как в примере выше, то почему правило не отрабатывает. Не пойму, тогда как осуществлять поиск...?!

vadim55_242 ()
Ответ на: комментарий от vadim55_242

Если много строк как в примере выше, то почему правило не отрабатывает.

сколько строк? какой версии ansible? у меня всё работает.

---
- name: Run show commands on routers
  hosts: localhost
  gather_facts: false
  connection: local

  tasks:
    - name: int shutdown
      shell: 'ls -lha /'
      register: sh_int_status

    - name: When
      debug:
        msg: "ОК"
      when: '"initrd.img" in sh_int_status.stdout'
    - name: debug
      debug: var=sh_int_status.stdout_lines
$ ansible-playbook test.yml 
Vault password: 

PLAY [Run show commands on routers]

TASK [int shutdown]
changed: [localhost]

TASK [When]
ok: [localhost] => {
    "msg": "ОК"
}

TASK [debug]
ok: [localhost] => {
    "sh_int_status.stdout_lines": [
        "total 2.1G", 
                                 ...
        "drwxr-xr-x   3 root   root    4.0K Nov 21 01:03 home", 
        "lrwxrwxrwx   1 root   root      33 Nov 21 20:17 initrd.img -> boot/initrd.img-4.13.0-17-generic", 
        "lrwxrwxrwx   1 root   root      33 Nov 21 01:00 initrd.img.old -> boot/initrd.img-4.13.0-16-generic", 
        "drwxr-xr-x  22 root   root    4.0K Nov 23 03:37 lib", 
                                 ...
        "lrwxrwxrwx   1 root   root      30 Nov 21 01:00 vmlinuz.old -> boot/vmlinuz-4.13.0-16-generic"
    ]
}

PLAY RECAP
localhost                  : ok=3    changed=1    unreachable=0    failed=0   

$ ansible --version
ansible 2.4.1.0
                                 ...
  python version = 2.7.14 (default, Sep 23 2017, 22:06:14) [GCC 7.2.0]

system-root ★★★★ ()
Ответ на: комментарий от system-root
ansible 2.4.1.0
  config file = /etc/ansible/ansible.cfg
  configured module search path = [u'/home/ubuntu/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/lib/python2.7/dist-packages/ansible
  executable location = /usr/bin/ansible
  python version = 2.7.6 (default, Oct 26 2016, 20:30:19) [GCC 4.8.4]

Строк мало, вот к примеру

TASK [debug] *******************************************************************
ok: [10.1.1.10] => {
    "ansible_net_interfaces['GigabitEthernet0/1']": {
        "bandwidth": 1000000,
        "description": "not_used",
        "duplex": null,
        "ipv4": [],
        "lineprotocol": "up (connected) ",
        "macaddress": "d072.dcf4.5801",
        "mediatype": "10/100/1000BaseTX",
        "mtu": 1500,
        "operstatus": "up",
        "type": "Gigabit Ethernet"
Просто если пытаюсь найти слово, когда в переменной одна строка, то сразу находит)))

vadim55_242 ()
Ответ на: комментарий от vadim55_242

Полная ерунда какая-то получается... Начал эксперименты, запустил поиск по слову, как в примере выше:

---
- name: Run show commands on routers
  hosts: localhost
  gather_facts: false
  connection: local

  tasks:
    - name: int shutdown
      shell: 'ls -lha /'
      register: sh_int_status

    - name: When
      debug:
        msg: "ОК"
      when: '"initrd.img" in sh_int_status.stdout'
    - name: debug
      debug: var=sh_int_status.stdout_lines
Так все работает. Тут же беру делаю поиск по слову из регистра полученного от cisco, то не может найти))))

vadim55_242 ()
Ответ на: комментарий от vadim55_242

Решил результат сначала сохранить в файл, потом в этом файле найти слово, тоже самое....)))

---
- name: Run show commands on routers
  hosts: cisco-sw
  gather_facts: false
  connection: local

  tasks:
    - name: int status
      ios_command:
        commands: sh int status
        provider: "{{ cli }}"
      register: sh_int_status

    - name: Copy
      copy:
        content: "{{ sh_int_status.stdout_lines | to_nice_json }}"
        dest: "./sh_int_status.json"

- name: Shell
  hosts: localhost
  gather_facts: false
  connection: local

  tasks:
    - name: Shell
      shell: 'cat ./sh_int_status.json'
      register: test_shell

    - name: When
      debug:
        msg: "OK"
      when: '"Gi0/1" in  test_shell'

vadim55_242 ()
Ответ на: комментарий от vadim55_242

покажи полное содержимое sh_int_status или выложи на пастбин если большое. включая все скобки.

system-root ★★★★ ()
Ответ на: комментарий от system-root
ubuntu@ubuntu:~/.ansible$ cat sh_int_status.json
[
    [
        "Port      Name               Status       Vlan       Duplex  Speed Type",
        "Gi0/1     not_used           connected    10         a-full a-1000 10/100/1000BaseTX",
        "Gi0/2     not_used           notconnect   10           auto   auto 10/100/1000BaseTX",
        "Gi0/3     not_used           notconnect   10           auto   auto 10/100/1000BaseTX",
        "Gi0/4     not_used           notconnect   100          auto   auto 10/100/1000BaseTX",
        "Gi0/5     not_used           notconnect   100          auto   auto 10/100/1000BaseTX",
        "Gi0/6     not_used           notconnect   100          auto   auto 10/100/1000BaseTX",
        "Gi0/7     not_used           notconnect   100          auto   auto 10/100/1000BaseTX",
        "Gi0/8     not_used           notconnect   100          auto   auto 10/100/1000BaseTX",
        "Gi0/9     not_used           notconnect   100          auto   auto 10/100/1000BaseTX",
        "Gi0/10    not_used           notconnect   3            auto   auto 10/100/1000BaseTX",
        "Gi0/11    not_used           notconnect   3            auto   auto 10/100/1000BaseTX",
        "Gi0/12    not_used           notconnect   1            auto   auto 10/100/1000BaseTX",
        "Gi0/13    not_used           notconnect   101          auto   auto 10/100/1000BaseTX",
        "Gi0/14    not_used           notconnect   10           auto   auto 10/100/1000BaseTX",
        "Gi0/15    not_used           notconnect   10           auto   auto 10/100/1000BaseTX",
        "Gi0/16    not_used           notconnect   20           auto   auto 10/100/1000BaseTX",
        "Gi0/17    not_used           notconnect   20           auto   auto 10/100/1000BaseTX",
        "Gi0/18    not_used           notconnect   102          auto   auto 10/100/1000BaseTX",
        "Gi0/19    not_used           notconnect   102          auto   auto 10/100/1000BaseTX",
        "Gi0/20    not_used           notconnect   102          auto   auto 10/100/1000BaseTX",
        "Gi0/21    not_used           notconnect   103          auto   auto 10/100/1000BaseTX",
        "Gi0/22    not_used           notconnect   10           auto   auto 10/100/1000BaseTX",
        "Gi0/23    not_used           notconnect   5            auto   auto 10/100/1000BaseTX",
        "Gi0/24    not_used           notconnect   20           auto   auto 10/100/1000BaseTX",
        "Fa0                          notconnect   routed       auto   auto 10/100BaseTX"
    ]
]ubuntu@ubuntu:~/.ansible$
vadim55_242 ()
Ответ на: комментарий от vadim55_242

А почему ты ищешь в stdout а на дебаг выводишь stdout_lines? Вдруг модуль для циски особенный и stdout пустой.

А если по делу, попробуй:

when: sh_int_status.stdout.find('Gi0/1') != -1

Deleted ()
Последнее исправление: MyLittleLoli (всего исправлений: 1)
Ответ на: комментарий от vadim55_242

посмотри какую структуру данных тебе выдаёт:

  tasks:
    - name: Shell
      shell: 'cat ~/sh_int_status.json'
      register: test_shell
    - set_fact: res="{{ test_shell.stdout | from_json }}"

    - name: debug
      debug: var=res
это многоуровневый list, вроде res=[["item1", "item2", "item3"]]
можешь посмотреть как это выглядит например через res[0][1]
    - name: debug
      debug: var=res[0][1]
это значит — нельзя просто так взять и искать в нём, его или нужно перевести в строку или словарь или итерироваться по всем элементам и искать в каждом res[0][1], res[0][2], res[0][N+1]

system-root ★★★★ ()
Последнее исправление: system-root (всего исправлений: 1)
Ответ на: комментарий от Deleted

Спасибо, вот это работает.

when: sh_int_status.stdout.find('Gi0/1') != -1
Если не затруднит, подскажите что значит != -1, не равно -1?!

vadim55_242 ()
Ответ на: комментарий от system-root

Вот так ничего не выводит:

   
 - name: debug
   debug: var=res
ничего не выводит:
TASK [debug] ************************************************************************************
ok: [localhost] => {
    "res": ""
}
Если честно мало понял про res. Начал гуглить тоже мало инфы, как и опыта))) Понял, что вложенная структура вывода, но не понял как разобрать вложенную структуру??!

vadim55_242 ()
Ответ на: комментарий от vadim55_242

Хотя понимание многоуровневой структуры тоже очень важно, так как в конфигурации cisco, много где многоуровневая. А на juniper тем более...

vadim55_242 ()
Ответ на: комментарий от vadim55_242

Да.

Ради инетерса, покажи, что выведет:

- name: debug
  debug: var=sh_int_status.stdout

Deleted ()
Ответ на: комментарий от vadim55_242

взял скопировал из твоего сообщения Ansible по условию When (комментарий) в файл ~/sh_int_status.json
к твоему примеру добавил «переменную» res в которой результат вывода cat перевёл в json
и всё.
если в этом Ansible по условию When (комментарий) заменить when: '"Gi0/1" in test_shell' на when: '"Gi0/1" in test_shell.stdout' — всё отлично ищется, потому, что это не json а текст.
на самом деле, если ты не знаешь что такое set_fact, возникает вопрос: а вообще зачем тебе условия в ansible? ты уверен, что погромировать на yml это хорошая идея с учётом, что в самом ansible ты плаваешь?
мне кажется, ты пытаешся решить некую проблему не совсем правильно.

system-root ★★★★ ()
Последнее исправление: system-root (всего исправлений: 1)
Ответ на: комментарий от Deleted

Вот, что выводит:

TASK [debug] ****************************************************************************
ok: [10.1.1.10] => {
    "sh_int_status.stdout": [
        "GigabitEthernet0/2 is down, line protocol is down (notconnect) \n  Hardware is Gigabit Ethernet, address is d072.dcf4.5802 (bia d072.dcf4.5802)\n  Description: not_used\n  MTU 1500 bytes, BW 10000 Kbit/sec, DLY 1000 usec, \n     reliability 255/255, txload 1/255, rxload 1/255\n  Encapsulation ARPA, loopback not set\n  Keepalive set (10 sec)\n  Auto-duplex, Auto-speed, media type is 10/100/1000BaseTX\n  input flow-control is off, output flow-control is unsupported \n  ARP type: ARPA, ARP Timeout 04:00:00\n  Last input never, output never, output hang never\n  Last clearing of \"show interface\" counters never\n  Input queue: 0/75/0/0 (size/max/drops/flushes); Total output drops: 0\n  Queueing strategy: fifo\n  Output queue: 0/40 (size/max)\n  5 minute input rate 0 bits/sec, 0 packets/sec\n  5 minute output rate 0 bits/sec, 0 packets/sec\n     0 packets input, 0 bytes, 0 no buffer\n     Received 0 broadcasts (0 multicasts)\n     0 runts, 0 giants, 0 throttles\n     0 input errors, 0 CRC, 0 frame, 0 overrun, 0 ignored\n     0 watchdog, 0 multicast, 0 pause input\n     0 input packets with dribble condition detected\n     0 packets output, 0 bytes, 0 underruns\n     0 output errors, 0 collisions, 1 interface resets\n     0 unknown protocol drops\n     0 babbles, 0 late collision, 0 deferred\n     0 lost carrier, 0 no carrier, 0 pause output\n     0 output buffer failures, 0 output buffers swapped out"
    ]
}

vadim55_242 ()
Ответ на: комментарий от system-root

Ну про set_fact понимание есть. Не понятно было про многоуровневую структуру. Опыта действительно с ansible маловато. Но желание постигнуть есть... Понимаю, что задаю иногда глупые вопросы)))

Да, сейчас ищется нормально

when: '"Gi0/1" in  test_shell.stdout' 

vadim55_242 ()
Ответ на: комментарий от vadim55_242

Получается, чтобы мне найти слово нужно выгружать переменную регистра в файл, к примеру, а только потом делать поиск.

Потому что если делаю так, то не работает:

when: '"Gi0/1" in  sh_int_status.stdout'
Только так
when: '"Gi0/1" in  test_shell.stdout'
Это конечно капец как неудобно...

vadim55_242 ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.