{"id":7235,"date":"2022-04-20T09:15:26","date_gmt":"2022-04-20T15:15:26","guid":{"rendered":"https:\/\/gregsowell.com\/?p=7235"},"modified":"2022-04-20T09:15:26","modified_gmt":"2022-04-20T15:15:26","slug":"config-as-code-with-the-ansible-automation-platform-controller","status":"publish","type":"post","link":"https:\/\/gregsowell.com\/?p=7235","title":{"rendered":"Config As Code With The Ansible Automation Platform Controller"},"content":{"rendered":"<p><a href=\"https:\/\/gregsowell.com\/wp-content\/uploads\/2022\/04\/Untitled-1-1.jpg\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/gregsowell.com\/wp-content\/uploads\/2022\/04\/Untitled-1-1-300x169.jpg\" alt=\"\" width=\"300\" height=\"169\" class=\"aligncenter size-medium wp-image-7238\" srcset=\"https:\/\/gregsowell.com\/wp-content\/uploads\/2022\/04\/Untitled-1-1-300x169.jpg 300w, https:\/\/gregsowell.com\/wp-content\/uploads\/2022\/04\/Untitled-1-1-768x432.jpg 768w, https:\/\/gregsowell.com\/wp-content\/uploads\/2022\/04\/Untitled-1-1-1024x576.jpg 1024w, https:\/\/gregsowell.com\/wp-content\/uploads\/2022\/04\/Untitled-1-1.jpg 1280w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/a><br \/>\nA 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 &#8220;We need to have change control associated with AAP for compliance&#8230;so how do we do that?&#8221;  <\/p>\n<p>To solve this problem I created a quick bit of automation to demonstrate using AAP to automate its own configuration&#8230;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.  <\/p>\n<h2>Video Demo<\/h2>\n<p><iframe loading=\"lazy\" width=\"560\" height=\"315\" src=\"https:\/\/www.youtube.com\/embed\/UIHLXIczLjg\" title=\"YouTube video player\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen><\/iframe><\/p>\n<h2>Playbooks And Files<\/h2>\n<p>All files can be <a href=\"https:\/\/github.com\/gregsowell\/aap-config-as-code\">found in my github repo here<\/a>.<\/p>\n<h3>Variable Files<\/h3>\n<p>I&#8217;ve got all of my settings stored in separate files in a data model I&#8217;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.<br \/>\nHere&#8217;s the inventory variable file for example(inventory.yml):<\/p>\n<pre class=\"gs-code\"><code class=\"language-plaintext\">---\r\ninv_var:\r\n  - name: AWS Inventory\r\n    state: present\r\n    org: Default<\/code><\/pre>\n<p>^^ It&#8217;s really just a simple set of variables that define the inventory name, its state, and the org it&#8217;s associated to.<\/p>\n<h3>Playbook<\/h3>\n<p>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.<br \/>\nMy playbook is as follows(main.yml):<\/p>\n<pre class=\"gs-code\"><code class=\"language-plaintext\">---\r\n- name: config as code demo for AAP\r\n  hosts: controller\r\n  gather_facts: false\r\n  vars:\r\n    controller_user: code\r\n    controller_pass: codepassword\r\n  tasks:\r\n  - name: bring in credentials variables\r\n    include_vars:\r\n      file: cred.yml\r\n    run_once: true\r\n\r\n  - name: manage credentials\r\n    ansible.controller.credential:\r\n      controller_host: &quot;https:\/\/{{ ansible_host }}&quot;\r\n      controller_username: &quot;{{ controller_user }}&quot;\r\n      controller_password: &quot;{{ controller_pass }}&quot;\r\n      name: &quot;{{ item.name }}&quot;\r\n      organization: &quot;{{ item.org }}&quot;\r\n      description: Added by automation\r\n      credential_type: &quot;{{ item.type }}&quot;\r\n      state: &quot;{{ item.state }}&quot;\r\n      inputs:\r\n      # secret key\r\n        password: &quot;{{ item.password }}&quot;\r\n      # access key\r\n        username: &quot;{{ item.username }}&quot;\r\n      validate_certs: false\r\n    loop: &quot;{{ creds }}&quot;\r\n\r\n  - name: bring in inventory variables\r\n    include_vars:\r\n      file: inventory.yml\r\n    run_once: true\r\n\r\n  - name: manage inventories\r\n    ansible.controller.inventory:\r\n      controller_host: &quot;https:\/\/{{ ansible_host }}&quot;\r\n      controller_username: &quot;{{ controller_user }}&quot;\r\n      controller_password: &quot;{{ controller_pass }}&quot;\r\n      name: &quot;{{ item.name }}&quot;\r\n      description: Added by automation\r\n      state: &quot;{{ item.state }}&quot;\r\n      organization: &quot;{{ item.org }}&quot;\r\n      validate_certs: false\r\n    loop: &quot;{{ inv_var }}&quot;\r\n\r\n  - name: bring in inventory source variables\r\n    include_vars:\r\n      file: inventory_source.yml\r\n    run_once: true\r\n\r\n  - name: manage inventory sources\r\n    ansible.controller.inventory_source:\r\n      controller_host: &quot;https:\/\/{{ ansible_host }}&quot;\r\n      controller_username: &quot;{{ controller_user }}&quot;\r\n      controller_password: &quot;{{ controller_pass }}&quot;\r\n      name: &quot;{{ item.name }}&quot;\r\n      description: Added via automation\r\n      inventory: &quot;{{ item.inventory_name }}&quot;\r\n      credential: &quot;{{ item.inventory_credential }}&quot;\r\n      overwrite: True\r\n      update_on_launch: True\r\n      source: &quot;{{ item.source }}&quot;\r\n#      source_vars:\r\n#        private: false\r\n      validate_certs: false\r\n    loop: &quot;{{ inv_source }}&quot;<\/code><\/pre>\n<p>I won&#8217;t walk through it completely, as each small section is really a copy and paste of the previous.<br \/>\nFirst I load in the variables:<\/p>\n<pre class=\"gs-code\"><code class=\"language-plaintext\">  - name: bring in credentials variables\r\n    include_vars:\r\n      file: cred.yml\r\n    run_once: true<\/code><\/pre>\n<p>It just simply grabs the file and brings in the variables.  It does this only once(that way if I&#8217;m updating a cluster of controllers it doesn&#8217;t waste time).<\/p>\n<p>Next I use the <a href=\"https:\/\/console.redhat.com\/ansible\/automation-hub\/repo\/published\/ansible\/controller\">ansible.controller collection<\/a> to start placing my configurations.  In this case I&#8217;m updating credentials so I use the ansible.controller.credential module:<\/p>\n<pre class=\"gs-code\"><code class=\"language-plaintext\">  - name: manage credentials\r\n    ansible.controller.credential:\r\n      controller_host: &quot;https:\/\/{{ ansible_host }}&quot;\r\n      controller_username: &quot;{{ controller_user }}&quot;\r\n      controller_password: &quot;{{ controller_pass }}&quot;\r\n      name: &quot;{{ item.name }}&quot;\r\n      organization: &quot;{{ item.org }}&quot;\r\n      description: Added by automation\r\n      credential_type: &quot;{{ item.type }}&quot;\r\n      state: &quot;{{ item.state }}&quot;\r\n      inputs:\r\n      # secret key\r\n        password: &quot;{{ item.password }}&quot;\r\n      # access key\r\n        username: &quot;{{ item.username }}&quot;\r\n      validate_certs: false\r\n    loop: &quot;{{ creds }}&quot;<\/code><\/pre>\n<p>Here you can see that I&#8217;m just quickly looping through the variable that was imported and adding in my configurations.<\/p>\n<h2>Conclusion<\/h2>\n<p>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.<\/p>\n<p>If you have any questions or comments, please let me know.  Thanks and happy automating!  <\/p>\n","protected":false},"excerpt":{"rendered":"<p>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\u2026<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[49],"tags":[],"class_list":["post-7235","post","type-post","status-publish","format-standard","hentry","category-ansible"],"_links":{"self":[{"href":"https:\/\/gregsowell.com\/index.php?rest_route=\/wp\/v2\/posts\/7235","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/gregsowell.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/gregsowell.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/gregsowell.com\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/gregsowell.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=7235"}],"version-history":[{"count":3,"href":"https:\/\/gregsowell.com\/index.php?rest_route=\/wp\/v2\/posts\/7235\/revisions"}],"predecessor-version":[{"id":7239,"href":"https:\/\/gregsowell.com\/index.php?rest_route=\/wp\/v2\/posts\/7235\/revisions\/7239"}],"wp:attachment":[{"href":"https:\/\/gregsowell.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=7235"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/gregsowell.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=7235"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/gregsowell.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=7235"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}