set_fact создать список с элементами

#ansible #ansible-2.x

#ansible #ansible-2.x

Вопрос:

У меня есть задача, которая вызывает API, и я регистрирую o / p в переменной;

 - name: Get Object storage account ID
  uri:
    url: 'https://api.softlayer.com/rest/v3.1/SoftLayer_Network_Storage_Hub_Cleversafe_Account/getAllObjects.json?objectFilter={"username":{"operation":"{{ item }}"}}'
    method: GET
    user: abxc
    password: 66c94c447a6ed8a0cf058774fe38
    validate_certs: no
  register: old_existing_access_keys_sl
  with_items: '{{ info["personal"].sl_cos_accounts }}'
  

old_existing_access_keys_sl содержит:

 "old_existing_access_keys_sl.results": [
 {
            "json": [
                {
                    "accountId": 12345, 
                    "id": 70825621, 
                    "username": "xyz-11"
                }
            ]
},
{
            "json": [
                {
                    "accountId": 12345, 
                    "id": 70825621, 
                    "username": "abc-12"
                }
            ]
}
  

Я хочу составить список id для дальнейшей обработки и попробовал выполнить следующую задачу, но это не сработало:

 - name: Create a list of account ids
  set_fact: 
    admin_usernames = "{{ item.json[0].id | list }}"
  with_items: old_existing_access_keys_sl.results
  

Я не уверен, возможно ли это вообще. Я также пробовал это:

     - name: create a list
      set_fact:
         foo: "{% set foo = [] %}{% for i in old_existing_access_keys_sl.results %}{{ foo.append(i) }}{% endfor %}"
  

foo всегда отображается пустым и в виде строки:

 
TASK [result] *****************************************************************************************************************************************
ok: [localhost] => {
    "foo": ""
}
  

Ответ №1:

Учитывая данные вашего примера, вы можете извлечь список идентификаторов с помощью json_query фильтра, например:

 ---
- hosts: localhost
  gather_facts: false
  vars:
    old_existing_access_keys_sl:
      results:
        [
          {
            "json": [
              {
                "accountId": 12345,
                "id": 70825621,
                "username": "xyz-11"
              }
            ]
          },
          {
            "json": [
              {
                "accountId": 12345,
                "id": 70825621,
                "username": "abc-12"
              }
            ]
          }
        ]
  tasks:
    - debug:
        var: old_existing_access_keys_sl|json_query('results[*].json[0].id')
  

Это приведет к:

 TASK [debug] **********************************************************************************************************************************************************************************
ok: [localhost] => {
    "old_existing_access_keys_sl|json_query('results[*].json[0].id')": [
        70825621, 
        70825621
    ]
}
  

Если вы хотите сохранить их в новой переменной, вы можете заменить эту debug задачу на set_fact :

     - set_fact:
        admin_ids: "{{ old_existing_access_keys_sl|json_query('results[*].json[0].id') }}"
  

Обновить

Для списка словарей просто измените json_query выражение:

 - debug:
    var: "old_existing_access_keys_sl|json_query('results[*].json[0].{id: id, username: username}')"
  

Для получения дополнительной информации см. Документацию и примеры на веб-сайте jmespath.

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

1. Спасибо, это сработало, но я тоже получил это : {"msg": "You need to install "jmespath" prior to running json_query filter"} . Пришлось сначала установить это с помощью pip.

2. Правильно, некоторые модули и фильтры ansible имеют предварительные требования, которые могут быть установлены или могут быть установлены по умолчанию. Это зависит от того, как вы устанавливаете Ansible и какие зависимости настроены вашими инструментами установки.

3. Я добавил пример, который создает список словарей и ссылки на дополнительную информацию о языке запросов jmespath, используемом json_query фильтром.