Hello, in this post, I want to show a small example of how to use external files in the playbook in Ansible:

  • External variable file in Playbook
  • External variable file in the Task
  • External file for copying to the Task
  • External template file in the Task.
  • External task file in the Task

What is the intention of this example? I want to have a structure in the project’s GitLab in which I have variable files, files that will be copied to the VMs (for example, certificates and keys) or template files, which are common to all the environment so that reuse is easy and the inclusion of only what is necessary. This way, I have no versioning problems, wrong data or maintenance.

To simulate this example, I will have 4 folders in the root, external to the playbooks:

  • global_files – Where the files that will be copied to the VMs are located, for example certificates.
  • global_hosts – Files with hosts, separated by group, technology, etc.
  • global_templates – Where all templates are located, organized by folders, themes, etc. For example, the secrets file is used for Mount.
  • global_vars – Files with global variables or those used by more than one task/playbook.
  • PlayBooks
    • certificate – Copies the certificate from the encrypted file to the host.
    • ldap – Creates the LDAP configuration file from a Jinja template and variables.
    • secrets – Main playbook of the example, runs its own tasks that show some variable contents, creates a secrets file on the host from a template and encrypted variables, runs the ldap task and runs the external certificate playbook.

Example structure:

.
|-- global_files
|   `-- certificates
|       `-- ldapcacert.crt
|-- global_hosts
|   `-- hosts_secrets
|-- global_templates
|   |-- ldap
|   |   `-- ldap.conf.j2
|   `-- secrets
|       `-- secrets.j2
|-- global_vars
|   |-- global_access.yaml
|   |-- global_database.yaml
|   `-- global_ldap.yaml
`-- playbooks
    |-- certificate
    |   |-- certificate.yaml
    |   `-- roles
    |       `-- copy_certificate
    |           `-- tasks
    |               `-- main.yaml
    |-- ldap
    |   |-- ldap.yaml
    |   `-- roles
    |       `-- configure_ldap
    |           `-- tasks
    |               `-- main.yaml
    `-- secrets
        |-- roles
        |   `-- test_secret
        |       |-- tasks
        |       |   `-- main.yaml
        |       `-- vars
        |           `-- main.yaml
        `-- secrets.yaml

Here are some more details that I plan for the project.

I don’t want to have very complex playbooks, unless they are tasks that are really only used for one purpose. Other than that, I want small, simple playbooks that only do small tasks. So, in a playbook that has more complex processes, I can call these external, smaller playbooks or tasks, and once again, reuse, facilitate maintenance, etc.

Returning to the example. See that I have global variables, files, templates, etc., which are accessible to everyone who needs them in the files/folders. In playbook, I have 3 different playbooks.

One of them, secrets, which will be the main playbook in this example, has the function of showing the use of external files, creating a secret file from a template and calling a second playbook, which will only be responsible for copying a certificate, and run only one external task (ldap).

What is the purpose of this separation? I want to show more practical examples of Playbooks with different purposes, for example, the certificate can only be called from a maintenance action, from an exchange of certificates, or from another playbook, be it installation of GitLab, Cassandra, Mongo, Consul, etc… the LDAP, only in a reconfiguration or maintenance, etc. They have different purposes and can be run separately. The secrets playbook is dependent on these other playbooks, which is why it makes the external call.

The main playbook will be simple, you can see that there is an “import_playbook” instruction, with the call to the certificate playbook and passing the same “cluster_group” variable that I use to filter some hosts.

- hosts: "{{ cluster_group | default('none') }}"
  become: true
  roles:
   - test_secret
  vars_files:
    - /work/external/global_vars/global_access.yaml
  gather_facts: True
#  
- import_playbook: /work/external/playbooks/certificate/certificate.yaml
  vars:
    cluster_group: { cluster_group }
 

There is also the option of calling only one external task or roles, as demonstrated in the secrets playbook task file.

The Ansible page has all the syntaxes for the import commands:

- name: Include vars files.
  ansible.builtin.include_vars: "{{ item }}"
  with_items:
    - /work/external/global_vars/global_database.yaml
    - /work/external/global_vars/global_ldap.yaml 

[...]

- name: Configure LDAP  
  include_tasks: /work/external/playbooks/ldap/roles/configure_ldap/tasks/main.yaml

Call:

ansible-playbook -i /work/external/global_hosts/hosts_secrets /work/external/playbooks/secrets/secrets.yaml --vault-id prod@/root/.vault_password.sec --extra-vars='cluster_group=tests_Hosts'

Result:

PLAY [tests_Hosts] ***********************************************************************************************************************************************************************************************************************************************************************************************************

TASK [Gathering Facts] *******************************************************************************************************************************************************************************************************************************************************************************************************
ok: [srv-infrastructure-test-master-01]

TASK [test_secret : Include vars files.] *************************************************************************************************************************************************************************************************************************************************************************************
ok: [srv-infrastructure-test-master-01] => (item=/work/external/global_vars/global_database.yaml)
ok: [srv-infrastructure-test-master-01] => (item=/work/external/global_vars/global_ldap.yaml)

TASK [test_secret : output the global playbook 'ansible_ssh_user' variable] **************************************************************************************************************************************************************************************************************************************************
ok: [srv-infrastructure-test-master-01] => {
    "ansible_ssh_user": "usr_linuxadmin"
}

TASK [test_secret : output the global playbook 'ansible_ssh_pass' variable] **************************************************************************************************************************************************************************************************************************************************
ok: [srv-infrastructure-test-master-01] => {
    "ansible_ssh_pass": "sg8BnHlWpkoQlLwmAZPePZ9JnLgwDffjIKTcLwP1NXCN5L2tms"
}

TASK [test_secret : output the global playbook 'ansible_ssh_common_args' variable] *******************************************************************************************************************************************************************************************************************************************
ok: [srv-infrastructure-test-master-01] => {
    "ansible_ssh_common_args": "-o StrictHostKeyChecking=no"
}

TASK [test_secret : output the global playbook 'global_database.username' variable] ******************************************************************************************************************************************************************************************************************************************
ok: [srv-infrastructure-test-master-01] => {
    "global_database.username": "usr_database_admin"
}

TASK [test_secret : output the global playbook 'global_database.password' variable] ******************************************************************************************************************************************************************************************************************************************
ok: [srv-infrastructure-test-master-01] => {
    "global_database.password": "IgzuZ2MSOsdtOT9JMovkrQATACla3ro6xtL2BHcvNOhr9BohJI"
}

TASK [test_secret : Create secrets dir] **************************************************************************************************************************************************************************************************************************************************************************************
ok: [srv-infrastructure-test-master-01]

TASK [test_secret : Add secrets mount with local variables - jinja] **********************************************************************************************************************************************************************************************************************************************************
ok: [srv-infrastructure-test-master-01]

TASK [test_secret : Configure LDAP] ******************************************************************************************************************************************************************************************************************************************************************************************
included: /work/external/playbooks/ldap/roles/configure_ldap/tasks/main.yaml for srv-infrastructure-test-master-01

TASK [test_secret : Copy ldap.conf] ******************************************************************************************************************************************************************************************************************************************************************************************
changed: [srv-infrastructure-test-master-01]

PLAY [tests_Hosts] ***********************************************************************************************************************************************************************************************************************************************************************************************************

TASK [Gathering Facts] *******************************************************************************************************************************************************************************************************************************************************************************************************
ok: [srv-infrastructure-test-master-01]

TASK [copy_certificate : Copy certificates] **********************************************************************************************************************************************************************************************************************************************************************************
ok: [srv-infrastructure-test-master-01]

PLAY RECAP *******************************************************************************************************************************************************************************************************************************************************************************************************************
srv-infrastructure-test-master-01 : ok=13   changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.