Skip to content

Repository files navigation

AAP Configuration as Code (CaC)

Export and import Ansible Automation Platform (AAP) 2.5+ configuration to/from Git using upstream infra.aap_configuration and infra.aap_configuration_extended.

Playbook Purpose
config-controller-export.yaml Export AAP → Git (aap-export/)
config-controller-filetree.yaml Import Git (aap-export/) → AAP

Both playbooks use the same tree: export writes aap-export/, import reads it. This public template ships an empty aap-export/ — run export against your AAP to populate it (prefer a private working repo for environment-specific data).

flowchart LR
    AAP["AAP Platform"]
    ExportPB["Export playbook"]
    Git["Git repo / aap-export"]
    ImportPB["Import playbook"]

    AAP -->|"filetree_create"| ExportPB
    ExportPB -->|"git push"| Git
    Git -->|"git clone"| ImportPB
    ImportPB -->|"filetree_read + dispatch"| AAP
Loading

Prerequisites

Platform

  • AAP 2.5+ (Gateway API: /api/gateway/v1/tokens/)
  • Admin user (or equivalent) that can manage Controller, Gateway, Hub, and EDA objects you intend to CaC
  • Network access from the Execution Environment to:
    • AAP Gateway URL
    • GitHub (HTTPS)

Collections (Execution Environment)

Install these into your EE (see collections/requirements.yml). Keep certified collection versions aligned with your AAP release.

Collection Version Role
infra.aap_configuration >=4.7.0 dispatch and object roles (Controller, Gateway, Hub, EDA)
infra.aap_configuration_extended 4.8.0 (pinned) filetree_create, filetree_read
ansible.platform >=2.5.0 Gateway / platform API modules (dependency of the infra collections)
ansible.controller >=4.6.0 Controller API modules
ansible.hub >=1.0.0 Automation Hub / PAH modules
ansible.eda >=2.5.0 Event-Driven Ansible modules

infra.aap_configuration declares ansible.platform, ansible.controller, ansible.hub, and ansible.eda as dependencies; list them explicitly in the EE so builds and air-gapped installs do not miss them.

Also ensure the EE has the git CLI.

Example EE requirements snippet:

collections:
  - name: infra.aap_configuration
    version: ">=4.7.0"
  - name: infra.aap_configuration_extended
    version: "4.8.0"
  - name: ansible.platform
    version: ">=2.5.0"
  - name: ansible.controller
    version: ">=4.6.0"
  - name: ansible.hub
    version: ">=1.0.0"
  - name: ansible.eda
    version: ">=2.5.0"

GitHub

  • A Git repository for this CaC content (this repo)
  • A Personal Access Token (PAT) with repo scope
    • Export needs write
    • Import needs read (write not required)

Ansible Vault (required for encrypted vars)

  • vars/aap_vars.yaml is expected to be ansible-vault encrypted (contains AAP password)
  • An AAP credential of type Vault with the same vault password, attached to both Job Templates
  • Optionally encrypt vars/vault_secrets.yaml when you enable vault-backed credential/user import

Without the Vault credential on the JT, jobs fail with:

Decryption failed (no vault secrets were found that could decrypt) on .../vars/aap_vars.yaml


One-time setup

1. Configure connection vars

cp vars/aap_vars.yaml.example vars/aap_vars.yaml
cp vars/git_vars.yaml.example vars/git_vars.yaml

Edit:

File Required settings
vars/aap_vars.yaml aap_hostname (full Gateway URL, e.g. https://aap.example.com), aap_username, aap_password, aap_validate_certs
vars/git_vars.yaml github_repo_url, github_branch (usually main), github_export_dir_name (aap-export)

Encrypt AAP credentials:

ansible-vault encrypt vars/aap_vars.yaml

git_vars.yaml does not need encryption unless you later store a PAT there. Git auth is normally supplied by the Job Template survey.

Keep vars/aap_vars.yaml, vars/git_vars.yaml, and filled vars/vault_secrets.yaml local (they are gitignored). For AAP Project sync, either use a private fork/working repo that holds your real aap-export/ and connection vars, or inject credentials via Job Template surveys / credentials instead of committing secrets.

2. Create an AAP Vault credential

  1. Automation Execution → Infrastructure → Credentials → Create
  2. Credential type: Vault
  3. Vault Password: the password used with ansible-vault encrypt
  4. Leave Vault Identifier empty (default vault)
  5. Save

3. Create the AAP Project

  1. Projects → Create
  2. SCM type Git → this repository URL
  3. SCM branch: main (or your working branch)
  4. Attach a Source Control credential if the repo is private
  5. Enable Update Revision on Launch
  6. If a force-push ever breaks sync (non-fast-forward on fetch), temporarily enable Delete on Update, sync once, then disable it again

4. Create Job Templates

Create two Job Templates on the Project from step 3. Both use the same credentials and survey; only the playbook differs.

Job Template (suggested name) Playbook Direction
CaC Export config-controller-export.yaml AAP → Git (aap-export/)
CaC Import config-controller-filetree.yaml Git (aap-export/) → AAP

Shared settings (both templates)

  1. Automation Execution → Templates → Create → Job Template
  2. Name: as in the table above (or your own names)
  3. Job type: Run
  4. Inventory: any inventory the job can run against (localhost / a dummy inventory is fine; the playbooks talk to AAP via API, not via inventory hosts)
  5. Project: the Project from step 3
  6. Execution Environment: an EE that includes infra.aap_configuration, infra.aap_configuration_extended, and the git CLI (see Prerequisites)
  7. Credentials: attach the Vault credential from step 2 (required to decrypt vars/aap_vars.yaml)
  8. Enable Survey (Prompt on launch) with these questions:
Variable name Question / prompt Type Required Notes
github_user GitHub username Text Yes Used in the HTTPS clone/push URL
github_password GitHub PAT Password Yes PAT with repo scope (write for Export, read for Import)
github_branch Git branch Text No Optional; overrides vars/git_vars.yaml
  1. Save

Export Job Template

  1. Create a Job Template with the shared settings above
  2. Set Playbook to config-controller-export.yaml
  3. Save
  4. Launch once to verify: enter survey values → job should push an updated aap-export/ (and regenerate vars/vault_secrets.yaml placeholders) to github_branch

Import Job Template

  1. Create a second Job Template with the same shared settings
  2. Set Playbook to config-controller-filetree.yaml
  3. Save
  4. Launch after aap-export/ has content: enter survey values → job applies the filetree to AAP (credentials / EDA credentials / Gateway users stay skipped until you enable vault-backed import)

Day-to-day usage

Export (AAP → Git)

  1. Sync/update the Project if needed
  2. Launch the Export Job Template
  3. Enter survey values (github_user / github_password)
  4. On success, the job:
    • Authenticates to AAP Gateway
    • Clones/updates the Git repo
    • Runs filetree_create into a temp dir
    • Copies into aap-export/
    • Filters out aap_operator_service_account
    • Regenerates vars/vault_secrets.yaml placeholders for any vaulted_* refs
    • Commits and pushes to github_branch

Import (Git → AAP)

  1. Launch the Import Job Template
  2. Enter survey values
  3. On success, the job:
    • Clones the Git repo
    • Discovers orgs from controller_organization.yaml (+ ORGANIZATIONLESS if present)
    • Runs filetree_read + dispatch per org, then at root

Default import behavior: Controller credentials, EDA credentials, and Gateway users are skipped until you fill/encrypt vars/vault_secrets.yaml and enable them (see below). Everything else in the export tree is applied, minus runtime/ephemeral exclusions.


Vaulted secrets (credentials & users)

Export writes secret fields as Jinja references, for example:

password: "{{ vaulted_controller_credentials_github_scm_password }}"

and generates placeholders in vars/vault_secrets.yaml (see vars/vault_secrets.yaml.example for the shape):

vaulted_controller_credentials_github_scm_password: "changeme"
vaulted_gateway_users_admin_password: "changeme"

Those objects are not imported until vault-backed import is enabled. They do not need to be pre-created manually in AAP once vault import is on — import creates/updates them from Git.

Enable vault-backed import

  1. Replace every "changeme" in vars/vault_secrets.yaml with real values
  2. Encrypt:
ansible-vault encrypt vars/vault_secrets.yaml
  1. Use the same AAP Vault credential password (or rekey everything to one password)
  2. Toggle the import paths with the helper (recommended):
bash helper/toggle_vault_import.sh

Or edit by hand in tasks/import_org.yml and tasks/import_root.yml:

  • Uncomment the filetree_* paths for credentials/users
  • Remove from aap_configuration_dispatcher_exclude_roles:
    • controller_credentials
    • controller_credential_input_sources
    • eda_credentials
    • gateway_users
  • Load vars/vault_secrets.yaml from config-controller-filetree.yaml vars_files
  1. Commit, push, sync the Project, run Import

Helper script: helper/toggle_vault_import.sh

Interactive script that comments / uncomments the vault-backed import wiring for you.

bash helper/toggle_vault_import.sh

It asks:

  1. ENABLE or DISABLE
  2. Which object groups to change:
    • Controller credentials (+ input sources)
    • EDA credentials
    • Gateway users
Mode What it does
Enable Uncomments filetree_* paths, removes roles from aap_configuration_dispatcher_exclude_roles, adds vars/vault_secrets.yaml to the import playbook vars_files
Disable Comments those paths (sets /dev/null), adds roles back to exclusions, stops loading vault_secrets.yaml

Always commit the script’s file changes before running Import from AAP.


Variables reference

Playbooks load:

vars_files:
  - vars/aap_vars.yaml
  - vars/git_vars.yaml
Variable Source Notes
aap_hostname vars/aap_vars.yaml Full Gateway URL with https://
aap_username / aap_password vars/aap_vars.yaml Encrypt this file
aap_validate_certs vars/aap_vars.yaml true in production with valid certs
github_repo_url vars/git_vars.yaml HTTPS clone/push URL
github_branch vars/git_vars.yaml or survey Target branch for clone/push
github_export_dir_name vars/git_vars.yaml Directory name in repo (aap-export)
github_user / github_password JT survey GitHub user + PAT

What is managed / excluded

Captured in aap-export/

Scope Resources
Controller Orgs, projects, inventories, sources, hosts, groups, job/workflow templates, credentials (vaulted_*), labels, teams, schedules, credential types, instance groups, EEs, settings, roles
Gateway Authenticators/maps, HTTP ports, services, settings, orgs, users (vaulted_*), teams, routes, service clusters/keys/nodes, role definitions/assignments
Hub Namespaces, collection remotes/repos, collection metadata, EE registries/repos/images
EDA Custom credential types, credentials (vaulted_*), decision environments, event streams, projects, rulebook activations

Always excluded from import dispatch

Role Reason
controller_inventory_source_update Runtime sync
controller_job_launch / controller_workflow_launch Launch actions
controller_instances / controller_instance_groups Ephemeral pod hostnames
hub_collection Content comes from remotes
hub_ee_registry_index / hub_ee_registry_sync Sync/index triggers
hub_collection_repository_sync / hub_ee_repository_sync Sync triggers
eda_controller_tokens Runtime tokens

Skipped until vault import is enabled

controller_credentials, controller_credential_input_sources, eda_credentials, gateway_users

Filtered automatically

  • Managed EDA credential types: Postgres, Red Hat Ansible Automation Platform
  • Gateway user aap_operator_service_account (operator-managed; never CaC’d)

Directory layout

aap-configuration-as-code/
├── config-controller-export.yaml      # Export playbook
├── config-controller-filetree.yaml    # Import playbook
├── collections/requirements.yml       # EE collection pins
├── tasks/
│   ├── aap_auth.yml
│   ├── aap_auth_cleanup.yml
│   ├── git_clone.yml
│   ├── filter_gateway_users.yml
│   ├── import_org.yml
│   └── import_root.yml
├── vars/
│   ├── *.example                      # Templates (tracked)
│   ├── aap_vars.yaml                  # Local only — vault-encrypt (AAP login)
│   ├── git_vars.yaml                  # Local only — repo URL / branch
│   └── vault_secrets.yaml             # Local / export-generated; fill to import secrets
├── helper/toggle_vault_import.sh      # Comment/uncomment vault import wiring
├── tests/                             # CI checks
└── aap-export/                        # Created by export (empty in this template)

Troubleshooting

Symptom What to check
Decryption failed ... vars/aap_vars.yaml Vault credential attached to JT; password matches ansible-vault encrypt
Project update non-fast-forward / fetch rejected Enable Delete on Update, sync once (common after force-push)
Git push/clone auth errors Survey PAT has repo scope; not expired
undefined variable: vaulted_* on import Vault-backed objects enabled without filled/loaded vault_secrets.yaml — run helper to disable, or complete vault setup
Missing modules / roles Rebuild EE from collections/requirements.yml
Import stops mid-dispatch Fail-fast by design; fix object data or add role to exclusions

Upstream references

About

Export and import Ansible Automation Platform (AAP) 2.5+ configuration to/from Git using infra.aap_configuration filetree roles.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages