Другое

Как извлекать серийные номера с помощью Ansible json_query

Изучите правильный синтаксис Ansible json_query для извлечения серийных номеров из JSON-данных при выполнении логических условий. Полное руководство с примерами и лучшими практиками.

Как извлечь серийный номер из JSON-данных при выполнении определенного условия с помощью фильтра json_query Ansible?

Я пытаюсь извлечь серийный номер из следующего JSON, когда значение Disabled равно true:

json
{
  "CertificateDetails": {
    "Serial": "1234ABCD",
    "SignatureAlgorithm": "sha256RSA"
  },
  "Disabled": true,
  "Guid": "{456767-546566-45676}"
}

Я могу получить значение Disabled с помощью этого запроса:

yaml
- name: store disabled value
  set_fact:
    Cert_Disabled: "{{ test.json | json_query('Disabled') }}"

Однако мне нужно получить серийный номер только тогда, когда логическое значение Disabled равно true. Я попробовал этот запрос, но он не дает желаемого результата:

yaml
- name: store disabled value
  set_fact:
    Cert_Disabled: "{{ test.json | json_query('[?Disabled].CertificateDetails.Serial') }}"

Какой правильный синтаксис Ansible json_query для извлечения серийного номера из CertificateDetails, когда Disabled равно true?

Правильный синтаксис Ansible json_query для извлечения серийного номера из CertificateDetails, когда Disabled равно true, использует синтаксис фильтрации массивов JMESPath с правильным сравнением булевых значений.

yaml
- name: store serial number when disabled
  set_fact:
    Cert_Serial: "{{ test.json | json_query('[?Disabled==`true`].CertificateDetails.Serial') }}"

Однако, поскольку ваша структура JSON имеет “Disabled” в качестве верхнеуровневого свойства, а не элемента массива, требуется немного другой подход. Вот правильные решения:

Содержание

Базовая фильтрация по булевым значениям

Для вашей конкретной структуры JSON, где “Disabled” является верхнеуровневым свойством, следует использовать:

yaml
- name: extract serial when disabled is true
  set_fact:
    Cert_Serial: "{{ test.json.CertificateDetails.Serial if test.json.Disabled else None }}"

Или с использованием json_query:

yaml
- name: extract serial using json_query
  set_fact:
    Cert_Serial: "{{ test.json | json_query('CertificateDetails.Serial') if test.json.Disabled | bool else None }}"

Работа с разными структурами данных

Если ваши данные JSON структурированы как массив сертификатов (что более характерно для реальных сценариев), синтаксис становится следующим:

yaml
- name: filter array and extract serial
  set_fact:
    Cert_Serial: "{{ certificates | json_query('[?Disabled==`true`].CertificateDetails.Serial') }}"

Где certificates будет массивом, например:

json
[
  {
    "CertificateDetails": {
      "Serial": "1234ABCD",
      "SignatureAlgorithm": "sha256RSA"
    },
    "Disabled": true,
    "Guid": "{456767-546566-45676}"
  },
  {
    "CertificateDetails": {
      "Serial": "5678EFGH",
      "SignatureAlgorithm": "sha256RSA"
    },
    "Disabled": false,
    "Guid": "{789012-345678-901234}"
  }
]

Расширенное условное извлечение

Для более сложных сценариев можно использовать булевы функции и операторы JMESPath:

yaml
- name: advanced filtering with multiple conditions
  set_fact:
    Cert_Serial: "{{ certificates | json_query('[?Disabled==`true` && CertificateDetails.SignatureAlgorithm==`sha256RSA`].CertificateDetails.Serial') }}"

Оператор == в JMESPath требует, чтобы литеральные значения в фильтрах заключались в обратные кавычки (`), как показано в документации Network to Code.

Практические примеры

Вот полный пример плейбука:

yaml
---
- name: Extract serial based on condition
  hosts: localhost
  gather_facts: false
  
  vars:
    certificates:
      - CertificateDetails:
          Serial: "1234ABCD"
          SignatureAlgorithm: "sha256RSA"
        Disabled: true
        Guid: "{456767-546566-45676}"
      - CertificateDetails:
          Serial: "5678EFGH"
          SignatureAlgorithm: "sha256RSA"
        Disabled: false
        Guid: "{789012-345678-901234}"
  
  tasks:
    - name: Extract serial numbers where disabled is true
      set_fact:
        disabled_serials: "{{ certificates | json_query('[?Disabled==`true`].CertificateDetails.Serial') }}"
    
    - name: Display results
      debug:
        msg: "Disabled certificates serials: {{ disabled_serials }}"

Распространенные ошибки

  1. Неправильное использование кавычек: Помните, что булевы литералы в фильтрах JMESPath требуют обратных кавычек: `true` и `false`

  2. Несоответствие типов: Убедитесь, что ваши булевы значения имеют правильный тип. Если “Disabled” приходит как строка “true”, сначала преобразуйте ее:

    yaml
    - name: handle string boolean values
      set_fact:
        Cert_Serial: "{{ certificates | json_query('[?Disabled==`true`].CertificateDetails.Serial') }}"
    
  3. Пустые результаты: Всегда обрабатывайте случаи, когда ни один сертификат не соответствует условию:

    yaml
    - name: safe extraction with fallback
      set_fact:
        Cert_Serial: "{{ certificates | json_query('[?Disabled==`true`].CertificateDetails.Serial') | first | default('No disabled certificates') }}"
    

Лучшие практики

  1. Используйте правильные булевы операторы: JMESPath поддерживает ==, !=, && (и), || (или) для сложных условий

  2. Комбинируйте с другими фильтрами: Фильтр json_query хорошо работает с другими фильтрами Ansible:

    yaml
    - name: extract and format serial
      set_fact:
        formatted_serial: "{{ certificates | json_query('[?Disabled==`true`].CertificateDetails.Serial') | join(', ') }}"
    
  3. Тестируйте ваши запросы: Используйте задачи debug для тестирования выражений JMESPath перед их внедрением в production:

    yaml
    - name: test query expression
      debug:
        msg: "{{ certificates | json_query('[?Disabled==`true`].CertificateDetails.Serial') }}"
    

Как указано в документации Ansible, фильтр json_query мощен для сложной манипуляции данными и может значительно улучшить читаемость и производительность ваших плейбуков по сравнению с использованием циклов Ansible.

Источники

  1. Using filters to manipulate data — Ansible Community Documentation
  2. Filter JSON Data in Ansible Using json_query - Network to Code
  3. Data manipulation in Ansible: json_query | Medium
  4. Ansible json-query path to select item by content - Stack Overflow

Заключение

Для извлечения серийного номера из данных JSON при выполнении определенного булевого условия в Ansible:

  1. Используйте правильный синтаксис JMESPath: [?PropertyName==true].TargetField
  2. Помните, что сравнения булевых значений в JMESPath требуют правильного заключения в кавычки и понимания структуры ваших данных
  3. Обрабатывайте разные структуры данных (верхнеуровневые свойства против элементов массива)
  4. Комбинируйте с другими фильтрами Ansible для более сложных операций
  5. Всегда тестируйте ваши запросы с помощью задач debug перед использованием в production

Ключевое понимание заключается в том, что сравнения булевых значений в JMESPath требуют правильного заключения в кавычки и понимания структуры данных для написания эффективных фильтрующих запросов.

Авторы
Проверено модерацией
Модерация