Как использовать Ansible для автоматизации разовых задач?

Я использую Ansible для автоматизации настройки виртуальных машин для некоторых наших сред сборки, например. настройка переменных среды PATH и прокси, установка глобальных инструментов Node.js и т. д. Это прекрасно работает, и можно легко автоматизировать общие задачи настройки на нескольких хостах. Все задачи разделены по Ansible roles для разделения обязанностей и дополнительного повторного использования.

Теперь я столкнулся со следующим: с новым установленным пакетом мне нужно изменить переменную среды PATH — ей больше не нужна запись, которую я ранее добавил как часть установки Ansible.

Поэтому, естественно, я пошел дальше и обновил задачу Ansible, которую я использую для настройки переменной PATH для новых сред, и удалил пользовательскую запись (я использовал задачу lineinfile для создания записи PATH).

lineinfile:
    dest: ~/.profile
    regexp: "^export {{ item.regexp }}"
    line: "export {{ item.line }}"
    create: yes
  with_items:
    - { regexp: 'PATH', line: 'PATH=:~/bin:~/node_modules/.bin:$PATH' }

Я удалил одну запись из приведенной выше line части элемента. Как видите, задача lineinfile только проверяет наличие записи export PATH в файле, а если нет, то создает ее с export PATH=:~/bin:~/node_modules/.bin:$PATH.

Теперь мой вопрос: поскольку задача lineinfile только проверяет существование записи, но не проверяет полное значение, мне нужно убедиться, что все существующие среды обновлены. Как мне это сделать?

Есть ли способ сделать оператор lineinfile достаточно умным, чтобы также проверить содержимое строки, т.е. убедиться, что именно та строка, которую я хочу, присутствует (в то же время избегая дублирования записей PATH)? Или это слишком сложно?

Еще одна вещь, о которой я подумал (и, наконец, сделал), — это создать одноразовый плейбук, который обновляет переменную PATH во всех средах:

lineinfile:
    dest: ~/.profile
    backrefs: yes
    regexp: "^export PATH=(.*)/opt/foo/bar/baz/bin[\\:]*(.*)"
    line: "export PATH=\\1\\2"

Является ли это распространенным сценарием — создание плейбуков для разовых задач? Преимущество заключается в том, что playbook запускается на всех хостах и ​​позволяет избежать ручной работы. Возможность повторного использования за пределами этого минимальна, так как я ожидаю сделать это только один раз.

Это правильный способ сделать это, или есть лучший, более разумный способ для выполнения таких задач?


person nwinkler    schedule 28.04.2015    source источник


Ответы (2)


Какую версию Ansible вы используете? Так как то, что вы описываете, похоже на баг, потому что модуль lineinfile должен определить, что строка изменилась, и обновить ее. Я просто скопипастил тебе первое задание (просто изменил путь к файлу) и все работает как надо.

Вот первый запуск:

➜  ~  % ansible-playbook test.yml

PLAY [all] ********************************************************************

TASK: [lineinfile ] ***********************************************************
changed: [localhost] => (item={'regexp': 'PATH', 'line': 'PATH=:~/bin:~/node_modules/.bin:$PATH'})

PLAY RECAP ********************************************************************
localhost                  : ok=1    changed=1    unreachable=0    failed=0

Затем я удалил ~/bin из пути и снова запустил все это:

➜  ~  % ansible-playbook test.yml

PLAY [all] ********************************************************************

TASK: [lineinfile ] ***********************************************************
changed: [localhost] => (item={'regexp': 'PATH', 'line': 'PATH=:~/node_modules/.bin:$PATH'})

PLAY RECAP ********************************************************************
localhost                  : ok=1    changed=1    unreachable=0    failed=0

Как видите, модуль обнаружил, что я изменил переменную, и обновил файл. Так что все работает как надо.

person Strahinja Kustudic    schedule 28.04.2015
comment
Спасибо! Я идиот - не знаю, что я делал не так. Вы правы, это работает так, как ожидалось. Я просмотрел свой реальный код (выше был пример), сделал пару модификаций, и он начал работать. - person nwinkler; 29.04.2015

Я не совсем уверен, что полностью понимаю ваш вопрос, но сработает ли любой из них...

(1) Имейте одну выделенную строку в .profile для пути, который вы добавляете для удаления. Таким образом, в дополнение ко всем вашим другим PATH материалам в .profile, у вас есть линия

export PATH=~/foo/removable:$PATH  # ANSIBLE MANAGED

что вы используете модуль line_in_file для добавления и удаления.

(2) Используйте каталог /etc/profile.d, а затем добавьте (через оператор copy или template) and remove a file/etc/profile.d/temporary-path.shthat contains your temporaryexport`.

person kalefranz    schedule 28.04.2015