Ansible Делает json_query/цикл условным с предложением when

У меня есть код, включающий json_query в цикле, который я пытаюсь сделать условным. Но я думаю, что есть что-то, чего я не понимаю в предложениях when и циклах.

Следующий код работает нормально, когда выполняется условие (IaC.status == 400), проблема в том, что когда условие не выполняется, 2-я задача все еще выполняется, цикл пытается обработать IaC2, которого не существует, и задача не выполняется с: "Invalid data passed to 'loop', it requires a list, got this instead:

Я думаю, что на самом деле это ожидаемое поведение для условных операторов и циклов: (https://docs.ansible.com/ansible/latest/user_guide/playbooks_conditionals.html#using-conditionals-in-loops), но описанное решение чтобы пропустить всю задачу, нужно использовать пустой итератор, но я понятия не имею, как объединить его с оператором json_query().

Кто-нибудь знает, как я могу действительно сделать вторую задачу ниже условной?

    # The preceding code has made a RESTful API call to create a gitlab group, if the group
    # exists the return status is 400, so I need to look it up instead. In which case the
    # following code works fine. The problem is when IaC.status = 201 for some reason the loop 
    # in the 2nd task below tries to run, despite the when clause, and fails 
    # because the variable IaC2 doesn't exist
    - name: or if IaC already exists
      when: IaC.status == 400
      uri: 
        url: https://{{new_hostname}}/api/v4/groups
        method: GET
        headers: 
          Authorization: "Bearer {{token.json.access_token}}"
        body_format: json
        body:
          name: "IaC"
          top_level_only: true
        status_code: 200 
        validate_certs: yes
      register:  IaC2

    - name: json_query to find the IaC group id when status = "{{IaC.status}}"
      when: IaC.status == 400
      debug:
        var: item
      loop: "{{ IaC2 | community.general.json_query(jmesquery) }}"
      vars:
        jmesquery: "json[?name=='IaC'].id"
      register: group_id

Ваше предложение цикла всегда будет интерпретироваться независимо от условия when. Более того, условие будет проверяться на каждой итерации, даже если оно всегда ложно. Я сомневаюсь, что IaC2 не существует, поскольку это регистр. Однако он может быть пустым (отладка была бы очень полезна). Вероятно, вы можете исправить это, назначив значение пустого списка по умолчанию ([]) для IaC2, когда оно равно нулю или пусто, чтобы ваше выражение цикла возвращало пустой список. См. фильтр default и его второй необязательный аргумент (true)

Zeitounator 24.12.2020 15:28
Как сделать HTTP-запрос в Javascript?
Как сделать HTTP-запрос в Javascript?
В JavaScript вы можете сделать HTTP-запрос, используя объект XMLHttpRequest или более новый API fetch. Вот пример для обоих методов:
0
1
1 825
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Вы должны обусловить свою вторую задачу первой задачей:

- name: json_query to find the IaC group id when status = "{{IaC.status}}"
  when: IaC2 is defined
  debug:
    var: item
  loop: "{{ IaC2 | community.general.json_query(jmesquery) }}"
  vars:
    jmesquery: "json[?name=='IaC'].id"
  register: group_id

Я не могу воспроизвести ваш случай на ansible 2.9.10, где задача пропускается, как и ожидалось. Но вы также можете помочь со значением по умолчанию. Я думаю, это сработает:

- name: json_query to find the IaC group id when status = "{{IaC.status}}"
  when: IaC2 is defined
  debug:
    var: item
  loop: "{{ IaC2 | community.general.json_query(jmesquery) | default([]) }}"
  vars:
    jmesquery: "json[?name=='IaC'].id"
  register: group_id

Привет, боюсь, ни один из них не сработал. Одна проблема заключается в том, что регистровая переменная всегда создается, даже если задача, которая ее создает, пропускается. Я использую ansible 2.10.4, если это имеет значение.

P Burke 24.12.2020 14:28

Это не сработает, потому что, как указано в комментарии OP, IaC2 всегда будет определено: существует регистр, независимо от того, выполнена ли задача успешно, неудачно или пропущена. Он просто не содержит той же информации => when: IaC2 is succeeded. docs.ansible.com/ansible/latest/user_guide/…

Zeitounator 24.12.2020 15:18

цель состояла в том, чтобы избежать ошибки «var не определен». Это все та же ошибка? Можете ли вы опубликовать вывод ansible-playbook с -vv?

Richard Sellam 24.12.2020 15:38
Ответ принят как подходящий

У меня есть своеобразный ответ. Во-первых, я не совсем понял две вещи;

  • переменная register (IaC2) всегда создается, даже если задача uri пропущена. И IaC2 имеет совершенно другую структуру в зависимости от того, выполняется эта задача или пропускается.
  • Цикл в следующей задаче выполняется всегда, поэтому предложение when во второй задаче довольно бессмысленно.

Настоящая проблема заключалась в том, что jmesquery искал переменную IaC2 с определенной структурой json, которой нет в случае, когда задача uri пропускается.

Таким образом, решение, которое кажется работающим, заключается в проверке того, была ли пропущена задача uri (when: IaC2.skipped is defined), и если она была пропущена, повторное определение IaC2 в форме пустого списка, что не прерывает цикл.

Примеры кода показаны ниже.

Итак, это работает, но я не могу отделаться от мысли, что должен быть более простой способ сделать это?

    - name: If IaC already exists (IaC.status == 400) then get the list of existing groups.
      when: IaC.status == 400
      uri: 
        url: https://{{new_hostname}}/api/v4/groups
        method: GET
        headers: 
          Authorization: "Bearer {{token.json.access_token}}"
        body_format: json
        body:
          name: "IaC"
          top_level_only: true
        status_code: 200 
        validate_certs: no
      register:  IaC2


    # To avoid breaking the following loop that searches the groups in the case that 
    # the group was created, re-define IaC2 into a form that won't break it.
    - name: Not created group "IaC", so redefine IaC2 var so as not to break the following loop
      when: IaC2.skipped is defined
      set_fact:
        IaC2: '{{ {"json": []} }}'

    - name: json_query to find the IaC group id when status = "{{IaC.status}}"
      #when: IaC.status == 400 << Leave in or comment out, makes no difference
      debug:
        var: item
      loop: "{{ (IaC2 | community.general.json_query(jmesquery)) }}"
      vars:
        jmesquery: "json[?name=='IaC'].id"
      register: group_id
    
    - name: record the IaC group's id (400)
      when: IaC.status == 400      
      set_fact:
        IaC_group_id: "{{group_id.results[0].item}}"

Другие вопросы по теме