IT 3110: System Automation

Ansible Reusable Playbooks

Modes of operation

Playbooks can be written in one very large file, but modularity allows us to reuse files.

  • import will utilize the static mode of operation
  • include will utilize the dynamic mode of operation

Modes of operation

  • Static : everything preprocessed when playbook is parsed (import)
  • Dynamic : everything processed when task is encountered during runtime. (include)

Importing playbooks

You could create master playbook from which you call a bunch of other playbooks like:

    ---
    - import_playbook: foo.yml
    - import_playbook: bar.yml

Ansible runs the plays and tasks in each imported playbook in the order they are listed, just as if they had been defined directly in the master playbook.

Importing task files

Perhaps you have a set of tasks that you want to share among multiple playbooks:

   #common_tasks.yml
   ---
   - name: some task
     command: /bin/echo
   - name: other task
     command: /bin/ifconfig

In other playbook, you can then:

   tasks:
   - import_tasks: common_tasks.yml
   or
   - include_tasks: common_tasks.yml

Pass variables to import and include

In the example below, we can re-run the wordpress.yml file more than once, but we can only do it if we are passing in a variable.

    tasks:
    - import_tasks: wordpress.yml
      vars:
        wp_user: timmy
    
    - import_tasks: wordpress.yml
      vars:
        wp_user: alice
    
    - import_tasks: wordpress.yml
      vars:
        wp_user: bob

Summary of dynamic and static

See the table here

Variables

  • While automation exists to make it easier to make things repeatable, all of your systems are likely not exactly alike.
  • Variable naming:
    • foo_port is a great variable. foo5 is fine too.
    • foo-port, foo port, foo.port and 12 are not valid variable names.
    • Could also create a dictionary-based variable
    • cannot begin with a number
    • cannot use python or playbook keywords

Variables

Simple variables using standard YAML syntax:

    remote_install_path: /opt/my_app_config

referenced in a playbook like:

    ansible.builtin.template:
      src: foo.cfg.j2
      dest: '{{ remote_install_path }}/foo.cfg'

Variables

  • Variables can be defined in inventory like this:

      [atlanta]
      host1 http_port=80 maxRequestsPerChild=808
    

or putting the correct lines in your group_vars file. (i.e. /etc/ansible/group_vars/atlanta) could have the following content:

    ---
    http_port: 80
    maxRequestsPerChild: 808

Variables

Can also be defined in a playbook

    - hosts: webservers
      vars:
        http_port: 80

How to use variables

    template: src=foo.cfg.j2 dest={{ remote_install_path }}/foo.cfg

How to use variables

You can get a bunch of information about systems by gathering_facts. Then you can use any of those variables in a playbook like:

    {{ ansible_devices.sda.model }}

or

    {{ ansible_nodename }}

Variables

  • YAML syntax requires that if you start a value with {{ foo }} you quote the whole line, since it wants to be sure you aren’t trying to start a YAML dictionary.
  • Another major use of variables is running a command and using the result of that command to save the result into a variable. Results will vary from module to module.

How to save results of previous command

    ---
    
    - hosts: all
      gather_facts: no
      tasks:
        - name: do shell math
          shell: cat /etc/passwd | wc -l
          register: foovar
          ignore_errors: True
    
        - debug:
            msg: "The foo var is {{ foovar.stdout_lines }} "

Registered variables

As in the aforementioned slide. Those registered variables are then available for the remainder of the playbook run (on that host).

Other reserved variables

    ---
    
    - hosts: all
      gather_facts: no
      tasks:
        - debug:
            msg: "The hostvars are {{ hostvars }}"
        - debug:
            msg: "The group_names are {{ group_names }}"
        - debug:
            msg: "The groups are {{ groups }}"

Pass variables at command line

   ---
   
   - hosts: all
     gather_facts: no
     tasks:
       - debug:
           msg: "The command line vars are {{ fooman }}"

Run like so,

    ansible-playbook -i ../gummi_hosts vars2.yml --extra-vars "fooman=222"

Variable scope

Ansible has 3 main scopes:

  • Global: this is set by config, environment variables and the command line
  • Play: each play and contained structures, vars entries (vars; vars_files; vars_prompt), role defaults and vars.
  • Host: variables directly associated to a host, like inventory, include_vars, facts or registered task outputs

Lists

    region:
      - northeast
      - southeast
      - midwest

How to use:

   region: "{{ region[0] }}"

Dictionaries

    foo:
      field1: one
      field2: two

How to use:

    foo['field1']
    foo.field1