В Ansible, как получить доступ к определенному элементу регистровой переменной в цикле?

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

- name: Generate pw's for users
  command: "/some_path/generate_hashed_pw.sh -u {{ item }}"
  register: hashed_pws
  with_items:
  - joe
  - sally
  - john

регистр hashed_pws — это хэш, содержащий ключ results[], представляющий собой массив хэшей, например

{
  "hashed_pws" : {
    "changed" : true,
    "some_other_key" : "some_other_value",
    "results" : [
      {
        "item" : "joe",
        "stdout": "joes_hashed_pw",
        "some_other_key" : "some_other_value"
      },
      {
        "item" : "sally",
        "stdout": "sallys_hashed_pw",
        "some_other_key" : "some_other_value"
      },
      {
        "item" : "john",
        "stdout": "johns_hashed_pw",
        "some_other_key" : "some_other_value"
      }
    ]
  }
}

Итак, каков синтаксис для прямого доступа к элементу «stdout» в каждом из хэш-элементов в массиве? Другими словами, я хочу:

- debug: msg="Sallys hashed pw is {{ hashed_pws.results[SOME_KEY_TO_DIRECTLY_GET_SALLYS_STDOUT_VALUE] }}"

Это, вероятно, вопрос о питоне в той же мере, в какой это вопрос об Ansible.


person Chris F    schedule 26.09.2016    source источник
comment
Также может быть полезен этот ответ: stackoverflow.com/a/39175309/2795592   -  person Konstantin Suvorov    schedule 26.09.2016
comment
Спасибо @KonstantinSuvorov, вторая ссылка дала правильное представление о том, что я хочу сделать.   -  person Chris F    schedule 26.09.2016
comment
Ссылка Константина, Перебрать зарегистрированную переменную with_dict в Ansible дал правильный ключ.   -  person Chris F    schedule 26.09.2016


Ответы (2)


Получить один легко, если вы знаете, какой вы хотите:

print(hashed_pws['results'][1]['stdout'])

Но если вы хотите их все, я недостаточно хорошо знаю ansible, чтобы знать, сколько циклов вы можете сделать. Можете ли вы использовать понимание списка?

print([x['stdout'] for x in hashed_pws['results']])

Изменить на основе вашего ответа ниже:

print([x['stdout'] for x in hashed_pws['results'] if x['item'] == "sally"])
person Danielle M.    schedule 26.09.2016
comment
Ваш первый print() близок к тому, что я хочу, но мне нужно знать значение индекса, которого я не знаю. Итак, мне нужно как-то получить индекс с элементом: Салли - это индекс 1. Да, я могу зацикливаться, но я НЕ хочу зацикливаться. - person Chris F; 26.09.2016
comment
Я добавил пример, который, я думаю, делает то, что вы просите, дайте мне знать! - person Danielle M.; 26.09.2016
comment
спасибо, но вы все еще зацикливаетесь на отредактированном ответе. - person Chris F; 26.09.2016
comment
Но, не зная, по какому индексу он находится, нам нужно проверить все индексы. Я не думаю, что есть способ обойти это. Если вы посмотрите на свой массив хэшей, и я спрошу вас, что такое хешированный пароль Джона, сможете ли вы ответить, не просматривая каждую запись? Даже лямбда-функция будет зацикливаться. Даже преобразование этого в индексированный словарь и доступ к паролю Салли потребовали бы перебора существующего списка. Я подумаю, не пропустил ли я какие-либо варианты, но я совершенно уверен, что вы не сможете избежать цикла. - person Danielle M.; 26.09.2016
comment
На самом деле должен быть ответ Ansible на этот вопрос, а не ответ Python. - person MillerGeek; 26.09.2016

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

- debug: msg="{{item.item}}'s hashed pw is {{item.stdout}}"
  with_items: "{{hashed_pws.results}}"

Вывод выглядит так:

TASK [debug] 
*******************************************************************
ok: [localhost] => (item={'some_other_key': 'some_other_value', 'stdout': 'joes_hashed_pw', 'item': 'joe'}) => {
    "item": {
        "item": "joe",
        "some_other_key": "some_other_value",
        "stdout": "joes_hashed_pw"
    },
    "msg": "joe's hashed pw is joes_hashed_pw"
}
ok: [localhost] => (item={'some_other_key': 'some_other_value', 'stdout': 'sallys_hashed_pw', 'item': 'sally'}) => {
    "item": {
        "item": "sally",
        "some_other_key": "some_other_value",
        "stdout": "sallys_hashed_pw"
    },
    "msg": "sally's hashed pw is sallys_hashed_pw"
}
ok: [localhost] => (item={'some_other_key': 'some_other_value', 'stdout': 'johns_hashed_pw', 'item': 'john'}) => {
    "item": {
        "item": "john",
        "some_other_key": "some_other_value",
        "stdout": "johns_hashed_pw"
    },
    "msg": "john's hashed pw is johns_hashed_pw"
}
person MillerGeek    schedule 26.09.2016
comment
Зацикливание занимает много времени. В моем примере у меня всего 3 пользователя, но что, если их десятки? Ссылка Константина в его втором комментарии в моем ОП - это ответ. - person Chris F; 27.09.2016
comment
Зацикливание не занимает много времени, и я очень смущен тем, как вы решили это без цикла. Ссылка, по которой вы говорите, помогла конкретно поговорить о цикле над диктовкой. Вы создаете отдельную задачу для каждого пользователя? Это не было бы хорошей практикой здесь и означает, что вам придется изменять сам плейбук каждый раз, когда изменяется список пользователей, а не только изменять список пользователей. - person MillerGeek; 27.09.2016
comment
@ChrisF Ваше редактирование не имело никакого смысла как часть ответа. Я очень ценю, что вы хотели сохранить вопрос 2 года спустя и, однако, отменить ошибочное отрицательное голосование. Я проголосовал за ответ от вашего имени, хотя я думаю, что smiler171 был бы признателен за комментарий больше, чем за несколько очков репутации, которые он, возможно, потерял. - person jpaugh; 05.02.2018