Как я могу запустить команду ansible, если определенный файл изменился

Я использую ansible для развертывания моего django App

с использованием

- name: Upgrade the virtualenv.
  pip: requirements={{project_root}}/www/requirements.txt virtualenv={{project_root}}/www/virtualenv

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


person user1994660    schedule 14.03.2014    source источник


Ответы (3)


Нам нужно определить, изменились ли какие-либо файлы требований. Шаги следующие:

  1. Коснитесь временных файлов требований. (Если их не было, md5 будет другим для нового пустого файла)
  2. Вычислить хэш md5 предыдущих файлов требований
  3. Вычислите хэш md5 текущих файлов требований (только что вытащенных из GIT)
  4. Поэтапно перебирать результаты этих команд статистики, сравнивая хэш md5, регистрировать результат сравнения.
  5. Только если ЛЮБОЙ из результатов в # 4 изменится, мы установим пакеты pip.
  6. Скопируйте текущие файлы требований в папку tmp.

Вот мой плейбук, {{virtualenv.requirements}} — это список файлов требований, например: ['/work/project/requirements.txt', '/work/project/requirements-prod.txt']:

- name: Assures temp requirements directory exists
  file: path="/tmp{{ virtualenv.path }}" state=directory
  sudo: yes
  when: install_pip_packages

- name: Assures temp requirements files exists
  file: path="/tmp{{ item }}" state=touch
  sudo: yes
  with_items: virtualenv.requirements_files
  when: install_pip_packages

- name: Calculate md5 of temp requirements
  stat: path="/tmp{{ item }}"
  with_items: virtualenv.requirements_files
  register: temp_requirements_stat
  when: install_pip_packages

- name: Calculate md5 of current requirements
  stat: path="{{ item }}"
  with_items: virtualenv.requirements_files
  register: current_requirements_stat
  when: install_pip_packages

- name: Check requirement files for changes
  command: test {{ temp_requirements_stat.results[item.0].stat.md5 }} = {{ current_requirements_stat.results[item.0].stat.md5 }}
  changed_when: "requirements_check.rc != 0"
  failed_when: requirements_check.stderr
  with_indexed_items: virtualenv.requirements_files
  register: requirements_check
  when: install_pip_packages

- name: Install packages required by the Django app inside virtualenv
  pip: virtualenv={{ virtualenv.path }} extra_args='-U' requirements="{{ virtualenv.requirements_files | join(' -r ') }}"
  when: install_pip_packages and requirements_check.changed

- name: Copy requirements to /tmp
  command: cp "{{ item }}" "/tmp{{ item }}"
  sudo: yes
  with_items: virtualenv.requirements_files
  when: install_pip_packages
person burroughs06    schedule 16.12.2014
comment
Просто интересно, есть ли лучшие варианты для версии 2.1? - person zr.; 13.10.2016
comment
На что ссылается этот install_pip_packages? - person Carl in 't Veld; 10.11.2020

Вот два варианта:

  • поместите ваш файл requirements.txt под контроль Ansible и используйте модуль «копировать» или «шаблон», затем вызовите модуль «pip» с оператором «notify:»

  • второй способ более сложный:

    • retrieve md5 sum of requirements.txt on each Ansible run and compare it with saved md5 somewhere on the server ('stat' module could be used)
    • получить предварительно сохраненную сумму требований md5.txt
    • если текущий md5 не равен предварительно сохраненному, то вызовите задачу pip (инструкция «когда:»)
    • сохраните новый md5 где-нибудь на сервере для следующего запуска Ansible
person ghloogh    schedule 14.03.2014
comment
Правильный способ справиться с этим — передать файл requirements.txt под контроль ansible. Требования.txt — это требование установки, а не требование пакета (которое входит в setup.py). Таким образом, вам не следует распространять файл requirements.txt вместе с пакетами, а следует распространять его с помощью системы управления конфигурацией: ansible. Попросите Ansible сгенерировать файл requirements.txt из шаблона, а затем вы можете настроить обработчик, когда эта задача изменится. (См. уведомление в документах ansible.) - person Chris Cogdon; 22.02.2017

Я использую этот довольно короткий обходной путь для репозитория git.

  - name: get requirements changes since last pull
    shell: "cd {{ project_root }}; git log --name-status --oneline origin/master
           {{ git_result.before }}..{{ git_result.after }} | grep requirements.txt"
    register: pip_check
    failed_when: false

  - name: update pip requirements
    pip: requirements={{ project_root }}/requirements.txt
         virtualenv=~/.virtualenvs/www/
    when: pip_check.stdout_lines

Это не универсальный и не кроссплатформенный рецепт, но он хорошо работает для многих ситуаций.

person g1zmo    schedule 18.08.2016