Bookmark this page

Guided Exercise: Creating and Using Roles

In this exercise, you will create and use a role.

Outcomes

You should be able to:

  • Define data using a variable named interfaces.

  • Compose a play that uses the interfaces variable to set interface descriptions for members of the cloud-services group.

  • Convert the original play into a role.

  • Create a new play that uses the role.

  • Verify that the new play works as desired.

Open a terminal window on the workstation VM and change to your ~/proj/ directory.

Procedure 3.4. Instructions

  1. Define data using variables.

    Create an interfaces variable, associated with the cloud-services group. The group_vars/cloud-services file should have the following contents:

    interfaces:
    - { name: GigabitEthernet1, description: Management }
    - { name: GigabitEthernet2, description: Outside Primary }
    - { name: GigabitEthernet3, description: Outside Secondary }
    - { name: GigabitEthernet4, description: Server Link1 }
  2. Compose a play that sets interface descriptions for members of the cloud-services group.

    1. Create a playbook named cs-ifdescr.yml for members of the cloud-services group, containing a play that sets interface descriptions. All members of the cloud-services group happen to be IOS devices.

      ---
      - name: set interface descriptions for cloud-services devices
        hosts: cloud-services
        # interface description data for this group
        # is set in its group variables file
        tasks:
        - name: set interface description
          ios_interface:
            aggregate: "{{ interfaces }}"
      
        - name: get interface descriptions
          ios_command:
            commands:
            - show interfaces | include Description
          register: results
      
        - name: show results
          debug:
            var: results.stdout
    2. Test the play to determine if it does what it is intended to do:

      [student@workstation proj]$ ansible-playbook --syntax-check cs-ifdescr.yml
      
      playbook: cs-ifdescr.yml
      [student@workstation proj]$ ansible-playbook --check cs-ifdescr.yml
      SSH password: student
      
      PLAY [set interface descriptions for cloud-services devices] *******************
      
      TASK [set interface description] ***********************************************
      changed: [cs01]
      
      TASK [get interface descriptions] **********************************************
      ok: [cs01]
      
      TASK [show results] ************************************************************
      ok: [cs01] => {
          "results.stdout": [
              ""
          ]
      }
      
      PLAY RECAP *********************************************************************
      cs01                       : ok=3    changed=1    unreachable=0    failed=0

      No results are shown because the --check option does not make any changes. It predicts some of the changes that may occur when the playbook is executed.

  3. Convert the original play into a role.

    Why take the trouble to convert a working playbook into a role? Here is a partial list of reasons:

    • Modularity in service of reusability.

    • Converting something that is useful and has value in a specific context (being applied to a particular set of hosts) into something that is generic, and is therefore useful and has value in a much broader range of contexts.

    • Converting something that is relatively complicated, and carries with it the baggage of being mapped to a particular host or group of hosts, into something slimmer and more flexible; a named sequence of tasks.

    • Creating the possibility of partitioning a large, flat task space into a hierarchical tasks space, consisting of much simpler modular units at each level.

    • Converting something relatively untidy into something relatively neat and orderly.

    Compare the number of lines in the original playbook to the playbook that uses a role. There are 19 lines, not counting empty lines and comments, in the original playbook. There are just six lines in cs-ifdescr2.yml.

    1. Create an ios-cs-ifdescr role directory structure using ansible-galaxy:

      [student@workstation proj]$ mkdir roles && ansible-galaxy init roles/ios-cs-ifdescr
    2. Show all the directories and files created when you initialized the new role:

      [student@workstation proj]$ tree roles/
      roles/
      └── ios-cs-ifdescr
             ├── defaults
             │   └── main.yml
             ├── files
             ├── handlers
             │   └── main.yml
             ├── meta
             │   └── main.yml
             ├── README.md
             ├── tasks
             │   └── main.yml
             ├── templates
             ├── tests
             │   ├── inventory
             │   └── test.yml
             ├── vars
             └── main.yml
      
      9 directories, 8 files
    3. Get the initial information about your new role.

      [student@workstation proj]$ ansible-galaxy info \
      > --offline --roles-path roles ios-cs-ifdescr
      
      Role: ios-cs-ifdescr
              description:
              dependencies: []
              galaxy_info:
                      author: your name
                      company: your company (optional)
                      galaxy_tags: []
                      license: license (GPLv2, CC-BY, etc)
                      min_ansible_version: 1.2
      ...output omitted...
  4. Assign the metadata for the role, and take credit for it, by populating the meta/main.yml file.

    1. Look over the choices that are available for describing your new role:

      [student@workstation proj]$ less roles/ios-cs-ifdescr/meta/main.yml

      At the very least, consider providing values for keys that are not commented out. By specifying role dependencies, you can automatically pull in other roles when using your role. Our role has no dependencies on other roles.

    2. Back up the original meta/main.yml file in case you would like to consult it in the future:

      [student@workstation proj]$ mv roles/ios-cs-ifdescr/meta/main.yml \
      > roles/ios-cs-ifdescr/meta/main.yml.orig
    3. Create a meta/main.yml file that describes the role. Edit the file and assign the following values:

      ---
      galaxy_info:
        author: DO457 Student
        description: Interface descriptions for example.com devices
        company: Examples, Ltd.
        license: ASL 2.0
        min_ansible_version: 2.5
        galaxy_tags:
          - acme
          - network
          - interface
      dependencies: []
  5. Populate the tasks/main.yml task file in the new role with the tasks from the cs-ifdescr.yml playbook:

    ---
    # tasks file for ios-cs-ifdescr
    - name: set interface description
      ios_interface:
        aggregate: "{{ interfaces }}"
    
    - name: get interface descriptions
      ios_command:
        commands:
        - show interfaces | include Description
      register: results
    
    - name: show results
      debug:
        var: results.stdout
  6. Create a new playbook named cs-ifdescr2.yml that uses the role:

    ---
    - name: manages interface descriptions for cloud services
    # use the ios-cs-ifdescr role
      hosts: cloud-services
    
      roles:
        - ios-cs-ifdescr
  7. Verify that the new play works as desired:

    [student@workstation proj]$ ansible-playbook cs-ifdescr2.yml
    SSH password: student

This concludes the guided exercise.

Revision: do457-2.5-4693601