Запрос JSON Не возвращает значение в сборнике игр Ansible

#json #filter #ansible #json-query

Вопрос:

Используя Ansible, у меня есть большой файл JSON, из которого мне нужно добавить несколько значений. Упрощенная версия приведена здесь, но показывает основную структуру:

 {
   "metadata": { "version": "1.2.3.4" },
   "operations": [
      {
         "resourceType": "type1",
         "items": 
         [
            { "sometag1": "someval1" },
            { "sometag2": "someval2" }
         ]
      },
      {
         "resourceType": "/certificates/ca",
         "items": 
         [
            { 
               "fileData": "EncryptedCertFile1",
               "id": "trustedCerts_cert1"
            },
            { 
               "fileData": "EncryptedCertFile2",
               "id": "trustedCerts_cert2"
            },
            { 
               "fileData": "EncryptedCertFile3",
               "id": "trustedCerts_cert3"
            }
         ]
      }
   ]
}
 

Это две задачи, которые я использую, чтобы получить значение:

 - name: Get Source JSON Data
          set_fact:
            jsonExp: "{{ lookup('file', '/tmp/{{ src_file_name }}') | from_json }}"

- name: Get Cert Info
  set_fact:
    cert_data: "{{ jsonExp | json_query(jquery) }}"
  vars:
    jquery: "operations[?resourceType=='/certificates/ca'].items[?id=='trustedCerts_cert2')]"
 

Но мне возвращается пустой массив json. Я прошел уровень за уровнем, и с помощью этой строки запроса я могу полностью перейти к массиву элементов:

 operations[?resourceType=='/certificates/ca'].items[*]
 

Я даже могу получить список конкретных лабораторных работ:

 operations[?resourceType=='/certificates/ca'].items[*].id
 

или

 operations[?resourceType=='/certificates/ca'].items[*].fileData
 

Я также могу нацелиться на определенный элемент, используя массив индексов:

 operations[?resourceType=='/certificates/ca'].items[1]
 

Но я, похоже, не могу заставить запрос работать для получения определенного элемента путем фильтрации записи «идентификатор».

Есть какие-нибудь предложения?

Ответ №1:

Я все понял!! Этот сайт-отличный инструмент для решения сложных запросов, подобных этому(по крайней мере, для меня). Как только я добрался до элементов части запроса, мне нужно было передать это во второй запрос:

 operations[?resourceType=='/certificates/ca'].items[] | [?Id=='trustedCerts_cert2'].fileData
 

Комментарии:

1. «этот сайт» на самом деле является официальной jmespath документацией, языком запросов, используемым json_query

Ответ №2:

Отслеживание вашего автоматического ответа json_query действительно очень эффективно для сложных запросов.

Между тем, он не является частью ядра ansible, поэтому требуется установить дополнительную коллекцию и библиотеку python. Кроме того, были (и все еще есть ИМО) некоторые проблемы, связанные с обслуживанием jmespath. Вы можете найти краткое изложение некоторых примеров проблем здесь, и to_json | from_json , возможно, трюк, необходимый для некоторых сложных запросов, все еще необходим (хотя вас здесь это не касается).

Все вышесказанное объясняет, что, даже если я все еще большой json_query поклонник, в настоящее время я склонен ограничивать его использование ситуацией, когда core ansible вообще не справляется с работой. В вашем примере это определенно не так.

Используя ваш точно такой же пример файла , который я сохранил /tmp/somedata.json , в следующем сборнике:

 ---
- name: Search for elements
  hosts: localhost
  gather_facts: false

  vars:
    src_file_name: somedata.json
    json_exp: "{{ lookup('file', '/tmp/' ~ src_file_name) | from_json }}"
    search_type: "/certificates/ca"
    search_id: "trustedCerts_cert2"
    cert_list: >-
      {{
        json_exp.operations
        | selectattr('resourceType', '==', search_type)
        | map(attribute='items')
        | flatten
        | selectattr('id', '==', search_id)
        | map(attribute='fileData')
      }}

  tasks:
    - name: "Show Cert Info"
      debug:
        msg: "{{ cert_list }}"
 

дает:

 PLAY [Search for elements] *****************************************************************************

TASK [Show Cert Info] *****************************************************************************
ok: [localhost] => {
    "msg": [
        "EncryptedCertFile2"
    ]
}

PLAY RECAP *****************************************************************************
localhost                  : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0