Страницы

Поиск по вопросам

понедельник, 24 февраля 2020 г.

Параллельная и последовательная обработка в ansible

#ansible


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

Ну, чтобы не быть голословным, - конкретный пример для 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. Что самое странное: именно в приведённом примере проблема с порядком возникает,
а вот когда запускаешь разные репозитории (первым -- тяжёлый медиавики, вторым -- небольшой
собственный репозиторий), проблема перестаёт воспроизводиться: сначала долго отрабатывает
первый таск, потом быстро пролетает второй. 
В мистику не верю: это просто говорит о непонимании, как оно всё работает под капотом.
    


Ответы

Ответ 1



Насколько я понял гоняя допонительные тесты, дело вообще не в том, сколько по времени выполняется задача внутри 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' }

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

Отправить комментарий