-
Notifications
You must be signed in to change notification settings - Fork 14
Home
These are the coding conventions I adhere to when writing Ansible code. Michael De Haan will probably not be a fan of this. His point of view is that Ansible should be low entry, and coding rules heighten the barrier to entry. This is definitely a valid concern. Ansible's Yaml syntax is easy to understand and easy to write, so coding guidelines are unnecessary at first sight.
However, in a larger code base, consistency has its merits. "There is more than one way to do it," and if I do stuff in different ways within the same role (or over several roles that are combined into a single project), it will certainly confuse future me, and probably others that read my code.
So ever since starting to use Ansible, learning more about it, and acquiring experience in writing playbooks, I gathered a few 'best practices' that I will enumerate here. So, this is an opinionated list, and I'm not trying to impose it on anyone. I do hope it's of some value to someone, though, and feedback is greatly appreciated.
In what follows, ${ANSIBLE_HOME}
refers to the Ansible configuration root directory. On a server system, this would typically be /etc/ansible
. However, if you run Ansible from your own machine, it could be any directory.
-
The directory layout adheres to the Ansible Playbook Best Practices.
-
All files have an appropriate extension, e.g.
.yml
,.j2
.# bad ${ANSIBLE_HOME}/group_vars/all # good ${ANSIBLE_HOME}/group_vars/all.yml # bad ${ANSIBLE_HOME}/templates/some_file.conf # good ${ANSIBLE_HOME}/templates/some_file.conf.j2
-
The main playbook is called
site.yml
, and is located in${ANSIBLE_HOME}
.site.yml
manages the configuration of all hosts. -
Other playbooks that are not used to manage system configuration, but rather use Ansible as an orchestration tool, are stored in a directory
${ANSIBLE_HOME}/playbooks/
. -
Template files encode the target location in their name. In the path name, '/' is substituted with '_'
# bad ${ANSIBLE_HOME}/templates/ssl.conf.j2 # good ${ANSIBLE_HOME}/templates/etc_httpd_conf.d_ssl.conf.j2
-
All Yaml files start with a comment line with the file path relative to
${ANSIBLE_HOME}
, an optional comment on the purpose of the file, followed by the---
marker# roles/httpd/tasks/main.yml # Main playbook of the httpd role ---
-
Use two spaces per indentation level, no tabs.
-
Avoid trailing whitespace
-
Tasks within a role should be tagged with the name of the role
# bad - name: Ensure the service is started service: name: httpd state: started # good - name: Ensure the service is started service: name: httpd state: started tags: httpd
-
Playbooks are written in valid Yaml instead of the default Ansible
key=value
notation. Ansible'skey=value
notation confuses text editors (syntax colouring) and really long lines (which are common) become hard to read.# bad - name: Install mod_ssl configuration file template: src=ssl.conf.j2 dest=/etc/httpd/conf.d/ssl.conf owner=root group=root setype=httpd_config_t mode='0644' notify: restart httpd tags: httpd # good - name: Install mod_ssl configuration file template: src: ssl.conf.j2 dest: /etc/httpd/conf.d/ssl.conf owner: root group: root setype: httpd_config_t mode: '0644' notify: restart httpd tags: httpd
-
Don't use quotes, unless you have to
-
Prefer single quotes over double quotes
-
All role variables should start with the name of the role, followed by an underscore. This avoids name conflicts with variables defined in other roles.
# bad port_number: 80 # good httpd_port: 80
-
Variable defaults should not be specified in templates, but in
defaults/main.yml
. This makes the template more readable (less clutter). It is also more consistent to put all default values for role variables in a single place.# bad (templates/some_template.j2) listen-port={{ role_listen_port|default('1234') }} # good # templates/some_template.j2: listen-port={{ role_listen_port }} # defaults/main.yml role_listen_port: 1234