Выражение JMESpath для фильтрации объекта по свойству и возврата списка имен объектов, для которых установлено это свойство - PullRequest
0 голосов
/ 09 мая 2018

Можно ли написать выражение JMESPath, чтобы оно возвращало список имен объектов, для которых задано определенное значение подпроправления?В приведенном ниже примере я хотел бы получить список всех имен хостов, где fileexists.stat.exists имеет значение true.

Моя цель - использовать структуру Ansible hostvars для получения спискавсех хостов, где присутствует определенный файл.

{
"hostvars": {
    "oclab1n01.example.org": {
        "fileexists": {
            "changed": false, 
            "failed": false, 
            "stat": {
                "exists": false
            }
        }
    }, 
    "oclab1n02.example.org": {
        "fileexists": {
            "changed": false, 
            "failed": false, 
            "stat": {
                "exists": true
            }
        }
    }, 
    "oclab1n03.example.org": {
        "fileexists": {
            "changed": false, 
            "failed": false, 
            "stat": {
                "exists": true
            }
        }
    }
} }

В этом примере я хотел бы получить следующий вывод

["oclab1n02.example.org", "oclab1n03.example.org"]

1 Ответ

0 голосов
/ 23 марта 2019

Короткий ответ (TL; DR)

Да, это возможно, но это чрезвычайно громоздко, потому что исходный набор данных плохо нормализован для этого вида запроса общего назначения.

Контекст

  • язык запросов jmespath
  • запрос свойств объектов для глубоко вложенных объектов

Проблема

  • Как создать запрос jmespath с помощью выражений фильтра
  • Цель состоит в том, чтобы фильтровать объекты с произвольно вложенными свойствами объекта

Решение

  • Это может бытьсделано с jmespath, но операция будет громоздкой
  • Одна проблемная проблема: исходный набор данных плохо нормализован для такого типа запроса jmespath
  • Чтобы построить запрос jmespath, мы должны предположить, что все первичные ключи объекта известны заранее о создании запроса
  • В этом конкретном примере мы должны знать, чтоЕсть триd только три имени хоста перед построением запроса jmespath ... это не благоприятное обстоятельство, если мы хотим гибко указать любое произвольное количество имен хостов

Пример

Следующий (слишком большой) запрос jmespath ...

  [
    {
      "hostname": `oclab1n01.example.org`
      ,"fileexists_stat_exists":  @.hostvars."oclab1n01.example.org".fileexists.stat.exists
    }
    ,{
      "hostname": `oclab1n02.example.org`
      ,"fileexists_stat_exists":  @.hostvars."oclab1n02.example.org".fileexists.stat.exists
    }
    ,{
      "hostname": `oclab1n03.example.org`
      ,"fileexists_stat_exists":  @.hostvars."oclab1n02.example.org".fileexists.stat.exists
    }
  ]|[? @.fileexists_stat_exists == `true`]|[*].hostname

возвращает следующий желаемый результат

  [
    "oclab1n02.example.org",
    "oclab1n03.example.org"
  ]

Подводные камни

  • Один главныйПодводный камень в этом сценарии использования: исходный набор данных плохо нормализован для этого типа запроса
  • Более упорядоченная структура данных будет проще запрашивать
  • Следовательно, если возможнолучшим вариантом было бы сгладить исходный набор данных перед выполнением запросов jmespath к нему

Альтернативный пример с другим исходным набором данных

Если исходные данные былиорганизованный как список объектов, а не набор вложенных объектов внутри объектов, было бы легче искать, сортировать и фильтровать список, не зная заранее 1068 * сколько записей имен хостов.

{"hostvars": [
    {"hostname":"oclab1n01.example.org"
      ,"fileexists":        true
      ,"filechanged":       false
      ,"filefailed":        false
      ,"filestat_exists":   false
      ,"we_can_even_still_deeply_nest":{"however":
           {"im_only_doing":"it here","to":"prove a point"}
         }
     }
    ,{"hostname":"oclab1n02.example.org"
      ,"fileexists":        true
      ,"filechanged":       false
      ,"filefailed":        false
      ,"filestat_exists":   true
     }
    ,{"hostname":"oclab1n03.example.org"
      ,"fileexists":        true
      ,"filechanged":       false
      ,"filefailed":        false
      ,"filestat_exists":   true
     }
  ]
}

Вышеуказанный перенормированный набор данных теперь можно легко запросить

hostvars|[? @.filestat_exists == `true`]|[*].hostname
...