Running an ansible task once in lifespan of a server
For some tasks, you want to run them only once on server creating.
For example create an empty database on server creating, or you can even restore the last known backup on creating a new database VM. Surely you do not want to run it on subsequent ansible runs to not to overwrite the latest changes to the database.
There are many ways in ansible to achieve this:
- create a custom fact on the first run
- touch some file to signal to the subsequent runs, that one run already happened
But I prefer behaviour-based checks, the same way I used to do it in JavaScript - never check for the browser agent-string, check for the desired behaviour.
So for this database case I do following:
- name: Check my_database database already exists
become: yes
become_user: postgres
shell: psql -l | grep my_database
ignore_errors: true
register: my_database_db_existence
- debug: var=my_database_db_existence
- name: Copy backup of the my-database database
shell: your-s3-command here
when: my_database_db_existence | failed
- name: Restore my_database database on first run
become_user: postgres
shell: createdb -O my_user my_database && psql -d my_database -f /path/to/my_dump.sql
when: my_database_db_existence | failed
Here in the first block psql -l
lists exisiting databases, like:
Name | Owner |Encoding| Collate | Ctype | Access privileges
-------------+-----------+--------+-------------+-------------+-----------------------
my_database | my_user | UTF8 | de_DE.UTF-8 | en_US.UTF-8 |
template0 | postgres | UTF8 | de_DE.UTF-8 | en_US.UTF-8 | =c/postgres +
| | | | | postgres=CTc/postgres
template1 | postgres | UTF8 | de_DE.UTF-8 | en_US.UTF-8 | =c/postgres +
| | | | | postgres=CTc/postgres
(3 rows)
grep
returns different exit codes dependent on if a matching string was found or not. If your database name is not long and unique enough, you can probably use awk
or cut
to extract only the first column and to be sure you do not match against other columns by accident.
The result (non-zero, failed
means not found) is saved to the variable my_database_db_existence
.
Next two blocks (transfer backup file, create DB + restore backup) are only run if the result was failed
(DB did not exist).