ansiblefest 2014 - role tips and tricks
DESCRIPTION
My presentation on Role Tips & Tricks from AnsibleFest San Francisco, 2014.TRANSCRIPT
WRITING ROLES: TIPS & TRICKSJames Cammarata
(github: jimi-c)
ABOUT MESTL Native, previously worked for Savvis/CenturyLink and
Scottrade
Started contributing to Cobbler in September of 2008, and tookover the project leadership in 2010
Joined Ansible in July, 2013
WHAT ARE ROLES?
GETTING STARTED
CREATING THE INITIAL ROLE LAYOUT
BAD!$ mkdir -p roles/myrole/{tasks,vars}$ touch roles/myrole/{tasks,vars}/main.yml
This is a very manual process, and completely unnecessary...
A MUCH BETTER WAY ™$ ansible-galaxy init roles/myrole
Benefits include:
Creates ALL of the directory structure for youStubs out some of the YAML files like `meta/main.yml`
USING ROLE DEPENDENCIES
SPECIFYING DEPENDENCIES IN METADATADependencies are specified in the `meta/main.yml` role file:
dependencies: - foo - { role: foo } - { role: /path/to/some/dir/bar } - { role: bam, some_var: "hello world!" }
TAGS & CONDITIONALS WITH ROLE DEPENDENCIES
When applying a tag or conditional statemtent to a roledefinition, they are appended to those specified on any tasks
within the role. For example:
# main yaml fileroles:- { role: foo, tags: 'foo', when: some_var == 'foo' }
# roles/foo/meta/main.ymldependencies:- { role: bar }
All tasks defined within 'bar' will also have the above tags and'when' statement applied to them, in addition to any other tags or
conditionals defined on the task.
CROSS-PLATFORM ROLESTIPS & TRICKS
USE GATHERED FACTS + INCLUDE TO TARGETPLATFORMS
# apache/tasks/main.yml- include: redhat.yml when: ansible_os_family == 'RedHat'- include: debian.yml when: ansible_os_family == 'Debian'
# apache/tasks/redhat.yml- name: install apache packages yum: name=httpd state=present
# apache/tasks/debian.yml- name: install apache packages apt: name=apache2 state=present
HANDLERS AND SERVICE NAME DIFFERENCESLets use the same method of conditional includes for handlers!
Results...
WHY DOESN'T THIS WORK?1. Handler names in Ansible must be unique.2. Included files are always read and parsed at load time, BUT the
conditionals are not evaluated until the task is executed...3. Result - the last handler defined with the name "wins", and the
wrong handler may be run.
THE SOLUTION: SET_FACT# apache/tasks/redhat.yml- name: install apache packages yum: name=httpd state=present- name: set the name of the service set_fact: apache_service_name=httpd
# apache/tasks/debian.yml- name: install apache packages apt: name=apache2 state=present- name: set the name of the service set_fact: apache_service_name=apache2
# apache/handlers/main.yml- name: restart apache service service: name={{apache_service_name}} state=restarted
DEALING WITH OTHER DIFFERENCES
We can use set_fact again in the platform-specific includes:
# apache/tasks/redhat.yml- name: set variables for this OS set_fact: apache_service_name: httpd apache_user: apache apache_httpd_conf_path: /etc/httpd/conf/httpd.conf apache_httpd_confd_path: /etc/httpd/conf.d ...
# apache/tasks/debian.yml- name: set the name of the service set_fact: apache_service_name: apache2 apache_user: www-data apache_httpd_conf_path: /etc/apache2/apache2.conf apache_httpd_confd_path: /etc/apache2/conf-available ...
And in our updated common tasks/main.yml:
# apache/tasks/main.yml# (continued)- name: deploy apache configuration template: src: httpd.conf.j2 dest: "{{apache_httpd_conf_path}}" owner: "{{apache_user}}" mode: "0640" notify: restart apache service
- name: make sure service is running and enabled service: name: "{{apache_service_name}}" state: running enabled: yes
ALTERNATIVE METHOD FOR VARIABLES
It is possible to use the include_vars and with_first_found lookupto include the distro-specific variables file, and to fall back to a
default set of variables:
# apache/tasks/main.yml- include_vars: "{{ item }}" with_first_found: - "{{ ansible_os_family }}.yml" - "default.yml"
GALAXY BEST PRACTICES
CREATING ACCURATE METADATA
When you use the ansible-galaxy CLI command to init a new role,a sample meta/main.yml is automatically created for you:
---galaxy_info: author: your name description: company: your company (optional) license: BSD min_ansible_version: 1.2 #platforms: #- name: EL # versions: # - all # - 5 # - 6 # - 7 ... #categories: #- cloud ... #- webdependencies: []
LISTING SANE DEPENDENCIESDependencies listed in the metadata should only point to other
Galaxy roles.
STEPS TO ADD YOUR ROLE TO GITHUB
AFTER CREATING YOUR REPO ON GITHUB:$ ansible-galaxy init foo$ cd foo/$ git init-(edit your files here)-$ git add *$ git commit -m "initial commit for my role"$ git remote add origin https://github.com/yourname/your-ansible-role$ git push origin master
QUESTIONS?
THANKS!