|
| 1 | +# Exercise 3 - Running Collections from Roles |
| 2 | + |
| 3 | +## Table of Contents |
| 4 | + |
| 5 | +- [Objective](#objective) |
| 6 | +- [Guide](#guide) |
| 7 | + - [Step 1: Understand collections lookup](#step-1-understand-collections-lookup) |
| 8 | + - [Step 2: Running collections from a role](step-2-running-collections-from-a-role) |
| 9 | +- [Takeaways](#takeaways) |
| 10 | + |
| 11 | +# Objective |
| 12 | + |
| 13 | +This exercise will help users understand how collections are used from within roles. |
| 14 | + |
| 15 | +Covered topics: |
| 16 | + |
| 17 | +- Explain collection resolution logic |
| 18 | + |
| 19 | +- Demonstrate how to call collections from roles using collection fully qualified collection name (FQCN) |
| 20 | + |
| 21 | +# Guide |
| 22 | + |
| 23 | +## Step 1: Understand collections lookup |
| 24 | + |
| 25 | +Ansible Collections use a simple method to define collection namespaces. Anyway, if |
| 26 | +your playbook loads collections using the `collections` key and one or more roles, then |
| 27 | +the roles will not inherit the collections set by the playbook. |
| 28 | + |
| 29 | +This leads to the main topic of this exercise: roles have an independent collection |
| 30 | +loading method based on the role's metadata. |
| 31 | +To control collections search for the tasks inside the role, users can choose between |
| 32 | +two approaches: |
| 33 | + |
| 34 | +- **Approach 1**: Pass a list of collections in the `collections` field inside the `meta/main.yml` file within the role. |
| 35 | + This will ensure that the collections list searched by the role will have higher priority than |
| 36 | + the collections list in the playbook. Ansible will use the collections list defined inside the role |
| 37 | + even if the playbook that calls the role defines different collections in a separate `collections` keyword entry. |
| 38 | + |
| 39 | + ```yaml |
| 40 | + # myrole/meta/main.yml |
| 41 | + collections: |
| 42 | + - my_namespace.first_collection |
| 43 | + - my_namespace.second_collection |
| 44 | + - other_namespace.other_collection |
| 45 | + ``` |
| 46 | +
|
| 47 | +- **Approach 2**: Use the collection fully qualified collection name (FQCN) directly from a task in the role. |
| 48 | + In this way the collection will always be called with its unique FQCN, and override any other |
| 49 | + lookup in the playbook |
| 50 | +
|
| 51 | + ```yaml |
| 52 | + - name: Create an EC2 instance using collection by FQCN |
| 53 | + amazon.aws.ec2: |
| 54 | + key_name: mykey |
| 55 | + instance_type: t2.micro |
| 56 | + image: ami-123456 |
| 57 | + wait: yes |
| 58 | + group: webserver |
| 59 | + count: 3 |
| 60 | + vpc_subnet_id: subnet-29e63245 |
| 61 | + assign_public_ip: yes |
| 62 | + ``` |
| 63 | +
|
| 64 | +Roles defined **within** a collection always implicitly search their own collection |
| 65 | +first, so there is no need to use the `collections` keyword in the role metadata to access modules, plugins, or other roles. |
| 66 | + |
| 67 | +## Step 2: Running collections from a role |
| 68 | + |
| 69 | +Create the exercise folder: |
| 70 | + |
| 71 | +```bash |
| 72 | +mkdir exercise-03 |
| 73 | +cd esercise--3 |
| 74 | +``` |
| 75 | + |
| 76 | +For this lab, we will use the `ansible.posix` collection, which contains a series of POSIX |
| 77 | +oriented modules and plugins for systems management. |
| 78 | + |
| 79 | +```bash |
| 80 | +ansible-galaxy collection install ansible.posix |
| 81 | +``` |
| 82 | + |
| 83 | +### Approach 1: Collections loaded as metadata |
| 84 | + |
| 85 | +> **TIP**: You can go though the exercise steps or copy the finished role from `solutions/selinux_manage_meta`. |
| 86 | + |
| 87 | +Create a new role using the `ansible-galaxy init` command: |
| 88 | + |
| 89 | +```bash |
| 90 | +ansible-galaxy init --init-path roles selinux_manage_meta |
| 91 | +``` |
| 92 | + |
| 93 | +Edit the `roles/selinux_manage_meta/meta/main.yml` file and append the following lines at the end of the file, beginning at column 1: |
| 94 | + |
| 95 | +```yaml |
| 96 | +# Collections list |
| 97 | +collections: |
| 98 | + - ansible.posix |
| 99 | +``` |
| 100 | + |
| 101 | +Edit the `roles/selinux_manage_meta/tasks/main.yml` file and add the following tasks: |
| 102 | + |
| 103 | +```yaml |
| 104 | +--- |
| 105 | +# tasks file for selinux_manage_meta |
| 106 | +- name: Enable SELinux enforcing mode |
| 107 | + selinux: |
| 108 | + policy: targeted |
| 109 | + state: "{{ selinux_mode }}" |
| 110 | +
|
| 111 | +- name: Enable booleans |
| 112 | + seboolean: |
| 113 | + name: "{{ item }}" |
| 114 | + state: true |
| 115 | + persistent: true |
| 116 | + loop: "{{ sebooleans_enable }}" |
| 117 | +
|
| 118 | +- name: Disable booleans |
| 119 | + seboolean: |
| 120 | + name: "{{ item }}" |
| 121 | + state: false |
| 122 | + persistent: true |
| 123 | + loop: "{{ sebooleans_disable }}" |
| 124 | +``` |
| 125 | + |
| 126 | +> **NOTE:** We're using the simple module name. Ansible uses the information from the |
| 127 | +> `collections` list in the metadata file to locate the collection(s) used. |
| 128 | + |
| 129 | +Edit the `roles/selinux_manage_meta/defaults/main.yml` to define default values for role variables: |
| 130 | + |
| 131 | +```yaml |
| 132 | +--- |
| 133 | +# defaults file for selinux_manage_meta |
| 134 | +selinux_mode: enforcing |
| 135 | +sebooleans_enable: [] |
| 136 | +sebooleans_disable: [] |
| 137 | +``` |
| 138 | + |
| 139 | +Cleanup unused folders in the role: |
| 140 | + |
| 141 | +```bash |
| 142 | +rm -rf roles/selinux_manage_meta/{tests,vars,handlers,files,templates} |
| 143 | +``` |
| 144 | + |
| 145 | +We can now test the new role with a basic playbook. Create the `playbook.yml` file |
| 146 | +in the current folder with the following content: |
| 147 | + |
| 148 | +```yaml |
| 149 | +--- |
| 150 | +- hosts: localhost |
| 151 | + become: true |
| 152 | + vars: |
| 153 | + sebooleans_enable: |
| 154 | + - httpd_can_network_connect |
| 155 | + - httpd_mod_auth_pam |
| 156 | + sebooleans_disable: |
| 157 | + - httpd_enable_cgi |
| 158 | + roles: |
| 159 | + - selinux_manage_meta |
| 160 | +``` |
| 161 | + |
| 162 | +Run the playbook and check the results: |
| 163 | + |
| 164 | +```bash |
| 165 | +$ ansible-playbook playbook.yml |
| 166 | +[WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all' |
| 167 | +
|
| 168 | +PLAY [localhost] ****************************************************************************************************** |
| 169 | +
|
| 170 | +TASK [Gathering Facts] ************************************************************************************************ |
| 171 | +ok: [localhost] |
| 172 | +
|
| 173 | +TASK [selinux_manage_meta : Enable SELinux enforcing mode] ************************************************************ |
| 174 | +ok: [localhost] |
| 175 | +
|
| 176 | +TASK [selinux_manage_meta : Enable booleans] ************************************************************************** |
| 177 | +changed: [localhost] => (item=httpd_can_network_connect) |
| 178 | +changed: [localhost] => (item=httpd_mod_auth_pam) |
| 179 | +
|
| 180 | +TASK [selinux_manage_meta : Disable booleans] ************************************************************************* |
| 181 | +changed: [localhost] => (item=httpd_can_network_connect) |
| 182 | +
|
| 183 | +PLAY RECAP ************************************************************************************************************ |
| 184 | +localhost : ok=4 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 |
| 185 | +``` |
| 186 | + |
| 187 | +### Approach 2: Collections loaded with FQCN |
| 188 | + |
| 189 | +The second approach uses the collection FQCN to call the related modules and plugins. To better demonstrate the differences, we will implement a new version of the previous role with the FQCN approach without changing the inner logic. |
| 190 | + |
| 191 | +> **TIP**: You can go though the exercise steps or copy the finished role from `solutions/selinux_manage_fqcn`. |
| 192 | + |
| 193 | +Create a new role using the `ansible-galaxy init` command: |
| 194 | + |
| 195 | +```bash |
| 196 | +ansible-galaxy init --init-path roles selinux_manage_fqcn |
| 197 | +``` |
| 198 | + |
| 199 | +Edit the `roles/selinux_manage_fqcn/tasks/main.yml` file and add the following tasks: |
| 200 | + |
| 201 | +```yaml |
| 202 | +--- |
| 203 | +# tasks file for selinux_manage_fqcn |
| 204 | +- name: Enable SELinux enforcing mode |
| 205 | + ansible.posix.selinux: |
| 206 | + policy: targeted |
| 207 | + state: "{{ selinux_mode }}" |
| 208 | +
|
| 209 | +- name: Enable booleans |
| 210 | + ansible.posix.seboolean: |
| 211 | + name: "{{ item }}" |
| 212 | + state: true |
| 213 | + persistent: true |
| 214 | + loop: "{{ sebooleans_enable }}" |
| 215 | +
|
| 216 | +- name: Disable booleans |
| 217 | + ansible.posix.seboolean: |
| 218 | + name: "{{ item }}" |
| 219 | + state: false |
| 220 | + persistent: true |
| 221 | + loop: "{{ sebooleans_disable }}" |
| 222 | +``` |
| 223 | + |
| 224 | +> **NOTE**: Notice the usage of the modules FQCN in the role tasks. Ansible will directly |
| 225 | +> look for the installed collection from within the role task, no matter if |
| 226 | +> the `collections` keyword is defined at playbook level. |
| 227 | + |
| 228 | +Edit the `roles/selinux_manage_fqcn/defaults/main.yml` to define default values for role variables: |
| 229 | + |
| 230 | +```yaml |
| 231 | +--- |
| 232 | +# defaults file for selinux_manage_fqcn |
| 233 | +selinux_mode: enforcing |
| 234 | +sebooleans_enable: [] |
| 235 | +sebooleans_disable: [] |
| 236 | +``` |
| 237 | + |
| 238 | +Cleanup unused folders in the role: |
| 239 | + |
| 240 | +```bash |
| 241 | +rm -rf roles/selinux_manage_meta/{tests,vars,handlers,files,templates} |
| 242 | +``` |
| 243 | + |
| 244 | +Modify the previous `playbook.yml` file to use the new role: |
| 245 | + |
| 246 | +```yaml |
| 247 | +--- |
| 248 | +- hosts: localhost |
| 249 | + become: true |
| 250 | + vars: |
| 251 | + sebooleans_enable: |
| 252 | + - httpd_can_network_connect |
| 253 | + - httpd_mod_auth_pam |
| 254 | + sebooleans_disable: |
| 255 | + - httpd_enable_cgi |
| 256 | + roles: |
| 257 | + - selinux_manage_FQCN |
| 258 | +``` |
| 259 | + |
| 260 | +Run the playbook again and check the results: |
| 261 | + |
| 262 | +```bash |
| 263 | +$ ansible-playbook playbook.yml |
| 264 | +[WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all' |
| 265 | +
|
| 266 | +PLAY [localhost] ****************************************************************************************************** |
| 267 | +
|
| 268 | +TASK [Gathering Facts] ************************************************************************************************ |
| 269 | +ok: [localhost] |
| 270 | +
|
| 271 | +TASK [selinux_manage_meta : Enable SELinux enforcing mode] ************************************************************ |
| 272 | +ok: [localhost] |
| 273 | +
|
| 274 | +TASK [selinux_manage_meta : Enable booleans] ************************************************************************** |
| 275 | +changed: [localhost] => (item=httpd_can_network_connect) |
| 276 | +ok: [localhost] => (item=httpd_mod_auth_pam) |
| 277 | +
|
| 278 | +TASK [selinux_manage_meta : Disable booleans] ************************************************************************* |
| 279 | +changed: [localhost] => (item=httpd_can_network_connect) |
| 280 | +
|
| 281 | +PLAY RECAP ************************************************************************************************************ |
| 282 | +localhost : ok=4 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 |
| 283 | +``` |
| 284 | + |
| 285 | +This concludes the guided exercise. |
| 286 | + |
| 287 | +# Takeaways |
| 288 | + |
| 289 | +- Collections can be called from roles using the `collections` list defined in `meta/main.yml`. |
| 290 | + |
| 291 | +- Collections can be called from roles using their FQCN directly from the role task. |
| 292 | + |
| 293 | +---- |
| 294 | +**Navigation** |
| 295 | +<br> |
| 296 | +[Previous Exercise](../2-collections-from-playbook/) - [Next Exercise](../4-collections-from-tower) |
| 297 | + |
| 298 | +[Click here to return to the Ansible for Red Hat Enterprise Linux Workshop](../README.md) |
0 commit comments