Вопрос вообще возник из того, что при клонировании крупных репозиториев вижу, что порядок вывода на экран меняется.
Ну, чтобы не быть голословным, - конкретный пример для ansible 2.1
Набор данных:
repositories:
mediawiki_core1:
repo: https://gerrit.wikimedia.org/r/p/mediawiki/core.git
path: w1
mediawiki_core2:
repo: https://gerrit.wikimedia.org/r/p/mediawiki/core.git
path: w2
version: REL1_25
mediawiki_core3:
repo: https://gerrit.wikimedia.org/r/p/mediawiki/core.git
path: w3
Обработчик:
- name: clone repositories
git:
repo: "{{ item.value.repo }}"
dest: "/root/tests/{{ item.value.path }}/"
version: "{{ item.value.version | default('HEAD') }}"
become: true
become_user: apache
with_dict: "{{ repositories }}"
Вывод окажется таким:
TASK [abcdef : clone repositories]
changed: [server.domain.ru] => (item={'value': {u'repo':
u'https://gerrit.wikimedia.org/r/p/mediawiki/core.git', u'path':
u'w1'}, 'key': u'mediawiki_core1'})
changed: [server.domain.ru] => (item={'value': {u'repo':
u'https://gerrit.wikimedia.org/r/p/mediawiki/core.git', u'path':
u'w3'}, 'key': u'mediawiki_core3'})
changed: [server.domain.ru] => (item={'value': {u'repo':
u'https://gerrit.wikimedia.org/r/p/mediawiki/core.git', u'path':
u'w2', u'version': u'REL1_25'}, 'key': u'mediawiki_core2'})
Нужно сделать так, чтобы гарантированно выполнить последовательно задачи одну за другой -- вне зависимости от того, сколько длится её выполнение.
Типичный пример: после того, как клонируется движок вики (очень длительная задача), можно приступать к клонированию множества мелких репозиториев со скринами и экстеншнами.
Дополнительно, хочется навести порядок в голове и разобраться, как управлять порядком выполнения, чтобы уметь распараллеливать задачи, если нужно, но и если нужно гарантировать, что задачи выполнятся одна за другой в указанном порядке, то уметь выполнять их последовательно.
P.S. Что самое странное: именно в приведённом примере проблема с порядком возникает, а вот когда запускаешь разные репозитории (первым -- тяжёлый медиавики, вторым -- небольшой собственный репозиторий), проблема перестаёт воспроизводиться: сначала долго отрабатывает первый таск, потом быстро пролетает второй.
В мистику не верю: это просто говорит о непонимании, как оно всё работает под капотом.
Ответ
Насколько я понял гоняя допонительные тесты, дело вообще не в том, сколько по времени выполняется задача внутри dict -- а в том, что сортировка для dict не гарантирована. Об этом было в этом вопросе на большом СО.
Точнее, обход with_dict проходит по dict не в том порядке, в котором я указываю элементы: идёт внутренняя сортировка по значению хеша.
Для того, чтобы обходить элементы в том порядке, в котором я записал их - нужно заменять dict на items и обход делать не with_dict, а with_items
vars:
with_dict_test:
- { key: 'one', value: 1 }
- { key: 'two', value: 2 }
- { key: 'three', value: 3 }
- { key: 'four', value: 4 }
- { key: 'five', value: 5 }
tasks:
- name: with_dict test
debug: msg="{{item.key}} --> {{item.value}}"
with_items: "{{ with_dict_test }}"
Или, точный пример, как у меня в вопросе:
vars:
with_dict_test:
- { repo: 'url1', path: 'A', version: 'REL1_25' }
- { repo: 'url2', path: 'B' }
tasks:
- name: with_dict test
debug: msg="{{item.repo}} --> {{item.path}} -- {{ item.version | default ('HEAD') }}"
with_items: "{{ with_dict_test }}"
И что-то мне такая форма сильно напоминает ;) Открываем документацию, раздел Standard Loops и видим:
Note that the types of items you iterate over with ‘with_items’ do not
have to be simple lists of strings. If you have a list of hashes, you
can reference subkeys using things like:
- name: add several users
user: name={{ item.name }} state=present groups={{ item.groups }}
with_items:
- { name: 'testuser1', groups: 'wheel' }
- { name: 'testuser2', groups: 'root' }
Вот так совсем хорошо:
with_dict_test:
- { repo: 'url1'
, version: 'REL1_25'
, path: 'A' }
- { repo: 'url2'
, path: 'B' }
Комментариев нет:
Отправить комментарий