Skip to content
Apr 20 / Greg

Config As Code With The Ansible Automation Platform Controller


A question we get off and on is how to automate the configuration of the Ansible Automation Platform(AAP) in the same way we would any other product. This could be for a lot of reasons, but the one I hear most often is “We need to have change control associated with AAP for compliance…so how do we do that?”

To solve this problem I created a quick bit of automation to demonstrate using AAP to automate its own configuration…a bit meta. In short I create some variable files in my git repository that represent how my AAP controller should be configured. I then have automation that will take those files and idempotently apply them to the controller.

Video Demo

Playbooks And Files

All files can be found in my github repo here.

Variable Files

I’ve got all of my settings stored in separate files in a data model I’ve created. This could technically be in a single file, I just chose to break it out for readability for this demo. Each file really just contains variables in whatever format I chose to put them in.
Here’s the inventory variable file for example(inventory.yml):

1
2
3
4
5
---
inv_var:
  - name: AWS Inventory
    state: present
    org: Default

^^ It’s really just a simple set of variables that define the inventory name, its state, and the org it’s associated to.

Playbook

I built this simple demo into a single playbook. The idea being that I created this idempotently, so I can rerun it multiple times and only the necessary adjustments will be made.
My playbook is as follows(main.yml):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
---
- name: config as code demo for AAP
  hosts: controller
  gather_facts: false
  vars:
    controller_user: code
    controller_pass: codepassword
  tasks:
  - name: bring in credentials variables
    include_vars:
      file: cred.yml
    run_once: true
 
  - name: manage credentials
    ansible.controller.credential:
      controller_host: "https://{{ ansible_host }}"
      controller_username: "{{ controller_user }}"
      controller_password: "{{ controller_pass }}"
      name: "{{ item.name }}"
      organization: "{{ item.org }}"
      description: Added by automation
      credential_type: "{{ item.type }}"
      state: "{{ item.state }}"
      inputs:
      # secret key
        password: "{{ item.password }}"
      # access key
        username: "{{ item.username }}"
      validate_certs: false
    loop: "{{ creds }}"
 
  - name: bring in inventory variables
    include_vars:
      file: inventory.yml
    run_once: true
 
  - name: manage inventories
    ansible.controller.inventory:
      controller_host: "https://{{ ansible_host }}"
      controller_username: "{{ controller_user }}"
      controller_password: "{{ controller_pass }}"
      name: "{{ item.name }}"
      description: Added by automation
      state: "{{ item.state }}"
      organization: "{{ item.org }}"
      validate_certs: false
    loop: "{{ inv_var }}"
 
  - name: bring in inventory source variables
    include_vars:
      file: inventory_source.yml
    run_once: true
 
  - name: manage inventory sources
    ansible.controller.inventory_source:
      controller_host: "https://{{ ansible_host }}"
      controller_username: "{{ controller_user }}"
      controller_password: "{{ controller_pass }}"
      name: "{{ item.name }}"
      description: Added via automation
      inventory: "{{ item.inventory_name }}"
      credential: "{{ item.inventory_credential }}"
      overwrite: True
      update_on_launch: True
      source: "{{ item.source }}"
#      source_vars:
#        private: false
      validate_certs: false
    loop: "{{ inv_source }}"

I won’t walk through it completely, as each small section is really a copy and paste of the previous.
First I load in the variables:

1
2
3
4
  - name: bring in credentials variables
    include_vars:
      file: cred.yml
    run_once: true

It just simply grabs the file and brings in the variables. It does this only once(that way if I’m updating a cluster of controllers it doesn’t waste time).

Next I use the ansible.controller collection to start placing my configurations. In this case I’m updating credentials so I use the ansible.controller.credential module:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
  - name: manage credentials
    ansible.controller.credential:
      controller_host: "https://{{ ansible_host }}"
      controller_username: "{{ controller_user }}"
      controller_password: "{{ controller_pass }}"
      name: "{{ item.name }}"
      organization: "{{ item.org }}"
      description: Added by automation
      credential_type: "{{ item.type }}"
      state: "{{ item.state }}"
      inputs:
      # secret key
        password: "{{ item.password }}"
      # access key
        username: "{{ item.username }}"
      validate_certs: false
    loop: "{{ creds }}"

Here you can see that I’m just quickly looping through the variable that was imported and adding in my configurations.

Conclusion

Once you have an example laid out in front of you, it really is pretty simple. The best options for this is to have as many components as external queryable systems as possible(secrets engines and dynamic inventories). Using these methods you could start treating your AAP configurations just like any other infrastructure as code project.

If you have any questions or comments, please let me know. Thanks and happy automating!

Leave a Comment

 

*