问题
I am using ansible
to deploy my django App
using
- name: Upgrade the virtualenv.
pip: requirements={{project_root}}/www/requirements.txt virtualenv={{project_root}}/www/virtualenv
But i only want to run that if requirements.txt changed since last run
回答1:
We need to determine if any of the requirement files have changed. The steps are as follows:
- Touch the temp requirement files. (If they didn't exist, the md5 will be different for the new blank file)
- Calculate the md5 hash of the previous requirement files
- Caclulate the md5 hash of the current requirement files (the ones just pulled down from GIT)
- Iterate through the results of these stat commands in-step, comparing the md5 hash, register the output of the comparison
- Only if ANY of the results in #4 changed will we install the pip packages
- Copy the current requirement files to the tmp location.
Here's my playbook, {{virtualenv.requirements}} is a list of requirement files, eg: ['/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
回答2:
Here are two options:
put your requirements.txt under Ansible control and use 'copy' or 'template' module, then invoke 'pip' module with 'notify:' statement
second way is more complex:
- 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)
- retrieve pre-saved md5 sum of requirements.txt
- if current md5 is not equal to presaved, then invoke pip task ('when:' statement)
- save new md5 somewhere on the server for next Ansible run
回答3:
I use this pretty short workaround for git repository.
- 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
It's not universal and not cross-platform recipe, but works well for many situations.
来源:https://stackoverflow.com/questions/22395733/how-can-i-run-ansible-command-if-certain-file-changed