Configuration As Code for Organizations (Teams)
To take advantage of the ability to configure Ansible Automation Controller via code,
the following is necessary:
A provisioned git repository to store the configuration
A pipeline that handles the configuration
A user with the rights to customize everything within the organization
The knowledge of the configuration in this document
Our basic principle is that a configuration for a team (organization) is fully maintained by that team. As a result, the user who is allowed to make these changes must be an organization admin. They have the rights to change everything within the organization, but they have no rights outside of it. We don't give this to all users in the team, so it uses a pre-created user that is configured in the pipeline.
Git repository
The git repository is delivered in accordance with the standard for the organization. In this repository the following files and directory structure are delivered:
.
├── collections
│ └── requirements.yml
├── group_vars
│ ├── accp
│ │ ├── credentials.yaml
│ │ ├── inventory.yaml
│ │ ├── templates.yaml
│ │ ├── notifications.yaml
│ │ ├── organization.yaml
│ │ ├── projects.yaml
│ │ ├── roles.yaml
│ │ ├── teams.yaml
│ │ ├── organization.yaml
│ │ └── workflows.yaml
│ ├── all
│ │ ├── credentials.yaml
│ │ ├── inventory.yaml
│ │ ├── templates.yaml
│ │ ├── notifications.yaml
│ │ ├── organization.yaml
│ │ ├── projects.yaml
│ │ ├── roles.yaml
│ │ ├── teams.yaml
│ │ ├── users.yaml
│ │ └── workflows.yaml
│ └── dev
│ ├── credentials.yaml
│ ├── inventory.yaml
│ ├── templates.yaml
│ ├── notifications.yaml
│ ├── organization.yaml
│ ├── projects.yaml
│ ├── roles.yaml
│ ├── teams.yaml
│ ├── users.yaml
│ └── workflowss.yaml
├── host_vars
│ ├── controller_accp
│ │ └── controller_auth.yaml
│ └── controller_dev
│ └── controller_auth.yaml
├── inventory.yaml
├── main.yml
└── README.md
There are a number of files that are important to the pipeline and should NOT be modified.
The files that are of interest to the user of the organization are under the
directory /group_vars/
Where NEW_ORG will be the team name for the organization in Ansible Automation
Platform.
All other files are important for the proper functioning of Configuration As
Code and should not be modified/deleted!
Pipeline
The pipeline ensures that the changes made in GIT (to the branch for the
environment) are
applied to the platform's automation controller in the correct environment.
This uses standard scripting developed by the open source community.
The configuration created in GIT is added to the controller, existing items
that already exist in the controller and are not included in the git are not deleted.
However, with a complete reinstallation, these will no longer be created.
So make sure that everything is included in code so that it comes back even
after a reinstallation.
The configuration files
In order to properly populate an organization with objects, the following files are necessary:
credentials.yaml
notifications.yaml
organization.yaml
projects.yaml
inventory.yaml
templates.yaml
roles.yaml
schedules.yaml
teams.yaml
users.yaml
workflows.yaml
We will use these files to configure a new organization in the controller. For each file
we will indicate which options are important and how they should be filled,
so that a working configuration is created in AAP. Keep in mind that object names in
AAP must be unique, so we assume that the names
are prefixed to the organization name.
In each file, on the 2nd line, we find the controller_{item}_{environment}: This indicates which item will be configured here and for which environment it will apply.
- Item: the part of the configuration explained below
- Environment Which environment(s) is affected by this item?
The environment is indicated by the name of the directory in the group_vars directory.
Theorem:
We have a new team(NEW_ORG) that has developed ansible code and has to apply it via AAP to an environment with a number of machines. The code is in git and the list of systems to which it should be applied is maintained in a separate git repository (inventory). We are now going to load this configuration in AAP from CaC (configuration as code).
credentials.yaml
Credentials (access tokens) are essential to the operation of AAP, providing the automation with the right access to systems to retrieve and execute code. Credentials can be very diverse, we will name and configure some of them here, which are important for the basic operation.
---
controller_credentials_xx:
- name:
description:
credential_type:
organization:
inputs:
auth_url:
token:
url:
...
Data Structure
| Variable Name | Default Value | Required | Description |
|---|---|---|---|
| name | "" | yes | Name of Credential |
| ew_name | "" | no | Setting this option will change the existing name (looked up via the name field). |
| copy_from | "" | no | Name or id to copy the credential from. This will copy an existing credential and change any parameters supplied. |
| description | False | no | Description of of Credential. |
| organization | "" | no | Organization this Credential belongs to. If provided on creation, do not give either user or team. |
| credential_type | "" | no | Name of credential type. See below for list of options. More information in Ansible controller documentation. |
| inputs | "" | no | Credential inputs where the keys are var names used in templating. Refer to the Ansible controller documentation for example syntax. Individual examples can be found at /api/v2/credential_types/ on an controller. |
| user | "" | no | User that should own this credential. If provided, do not give either team or organization. |
| team | "" | no | Team that should own this credential. If provided, do not give either user or organization. |
| state | present | no | Desired state of the resource. |
| update_secrets | true | no | True will always change password if user specifies password, even if API gives encrypted for password. False will only set the password if other values change too. |
If we are going to fill it in for the new organization, the following possible configuration will follow:
First, the credentials that apply to all environments:
---
controller_credentials_all:
- name: NEW_ORG_automation_hub_token_published
description:
credential_type: Ansible Galaxy/Automation Hub API Token
organization: NEW_ORG
inputs:
auth_url: ''
Token: "{{ token }}"
url: hub url naar published repo's
- name: NEW_ORG_automation_hub_token_rh_certified
description:
credential_type: Ansible Galaxy/Automation Hub API Token
organization: NEW_ORG
inputs:
auth_url: ''
Token: "{{ token }}"
url: hub url naar rh_certified
- name: NEW_ORG_git
description:
credential_type: Source Control
organization: NEW_ORG
inputs:
ssh_key_data: !vault |
$ANSIBLE_VAULT; 1.1; AES256
-----BEGIN OPENSSH PRIVATE KEY-----
-- key data --
-----END OPENSSH PRIVATE KEY-----
username: AAP_user
...
2nd are the credentials that only apply to the co(development) environment:
---
controller_credentials_dev:
- name: NEW_ORG_ansible
description:
credential_type: Machine
organization: NEW_ORG
inputs:
become_method: sudo
become_username: ''
ssh_key_data: !vault |
$ANSIBLE_VAULT; 1.1; AES256
-----BEGIN OPENSSH PRIVATE KEY-----
-- key data --
-----END OPENSSH PRIVATE KEY-----
username: ansible
...
We see in the above, that the credentials for the automation hub will be the same in all environments, but that in the development environment a different ansible key will be used for the machines. In this way, we can ensure that the environments cannot influence each other. By including a different key for the ansible account in each folder, separation is possible.
notifications.yaml
The controller can send messages when certain plays have been made (configurable
in the job template).
The message will then contain the template name, the result, and any other information.
This can be done via email, as below, or through instant messaging channels.
Here we define a notification template, i.e. the framework that will be used to send a notification.
---
controller_notifications:
- name: Email notification
description: Send out emails for controller jobs
organization: Satellite
notification_type: email
notification_configuration:
username: '' # this is required even if there's no username
sender: controller0@example.com
recipients:
- admin@example.com
use_tls: false
host: smtp.example.com
use_ssl: false
password: '' # this is required even if there's no password
port: 25
Data Structure
| Variable Name | Default Value | Required | Type | Description |
|---|---|---|---|---|
| name | "" | yes | str | The name of the notification. |
| new_name | "" | yes | str | Setting this option will change the existing name (looked up via the name field). |
| copy_from | "" | no | str | Name or id to copy the Notification template from. This will copy an existing notification and change any parameters supplied. |
| description | "" | no | str | The description of the notification. |
| organization | "" | no | str | The organization applicable to the notification. |
| notification_type | "" | no | str | The type of notification to be sent. |
| notification_configuration | "" | no | str | The notification configuration file. Note providing this field would disable all depreciated notification-configuration-related fields. |
| messages | "" | no | list | Optional custom messages for notification template. Assumes any instance of two space __ are used for adding variables and removes them. Does not effect single space. |
| state | present | no | str | Desired state of the resource. |
organization.yaml
This file contains the definition of the team (organization within AAP). This file is easy to configure as there is not much in it.
---
controller_organizations_xxx:
- name:
description:
galaxy_credentials:
assign_galaxy_credentials_to_org:
...
Below is the list of parameters and their necessary filling: parameter Definition controller_organizations_ One of the options: dev, test, accp, prod of all If we are going to fill it in for the new organization, the following file will follow:
---
controller_organizations_all:
- name: NEW_ORG
description: New team in AAP
galaxy_credentials:
- NEW_ORG_automation_hub_token_rh_certified
- NEW_ORG_automation_hub_token_published
assign_galaxy_credentials_to_org: true
...
By keeping the names of the credentials the same, there is no need to deviate from one environment to another and an "all" configuration will suffice.
Organization Data Structure
| Variable Name | Default Value | Required | Type | Description |
|---|---|---|---|---|
| name | "" | yes | str | Name of Organization |
| description | False | no | str | Description of of Organization. |
| custom_virtualenv | "" | no | str | Local absolute file path containing a custom Python virtualenv to use. |
| max_hosts | "" | no | Int | The max hosts allowed in this organization. |
| instance_groups | "" | no | list | list of Instance Groups for this Organization to run on. |
| galaxy_credentials | "" | no | list | The credentials to use with private automationhub. |
| default_environment | "" | no | str | Default Execution Environment to use for jobs owned by the Organization. |
| notification_templates_started | "" | no | list | The notifications on started to use for this organization in a list. |
| notification_templates_success | "" | no | list | The notifications on success to use for this organization in a list. |
| notification_templates_error | "" | no | list | The notifications on error to use for this organization in a list. |
| notification_templates_approvals | "" | no | list | The notifications for approval to use for this organization in a list. |
| state | present | no | str | Desired state of the resource. |
projects.yaml
In this file, we create the link to the git repositories in AAP. These links define the projects on which templates and inventories are based, in order to be able to run code in AAP.
---
controller_projects_xxx:
- name:
description:
organization:
scm_type:
scm_url:
scm_credential:
scm_branch:
scm_clean:
scm_delete_on_update:
scm_update_on_launch:
scm_update_cache_timeout:
allow_override:
timeout:
As we can see above, there are quite a few parameters to fill, most of them are easy to set to a default, which we indicate here once. Below is the list of parameters and their necessary filling:
Data Structure
| Variable Name | Default Value | Required | Type | Description |
|---|---|---|---|---|
| name | "" | yes | str | Name of Project |
| new_name | "" | no | str | Setting this option will change the existing name (looked up via the name field). |
| copy_from | "" | no | str | Name or id to copy the project from. This will copy an existing project and change any parameters supplied. |
| description | False | no | str | Description of the Project. |
| organization | False | yes | str | Name of organization for project. |
| scm_type | "" | no | str | Type of SCM resource. |
| scm_url | "" | no | str | URL of SCM resource. |
| default_environment | "" | no | str | Default Execution Environment to use for jobs relating to the project. |
| local_path | "" | no | str | The server playbook directory for manual projects. |
| scm_branch | "" | no | str | The branch to use for the SCM resource. |
| scm_refspec | "" | no | str | The refspec to use for the SCM resource. |
| credential | "" | no | str | Name of the credential to use with this SCM resource. |
| signature_validation_credential | "" | no | str | Name of the credential to use for signature validation. If signature validation credential is provided, signature validation will be enabled. |
| scm_clean | "" | no | bool | Remove local modifications before updating. |
| scm_delete_on_update | "" | no | bool | Remove the repository completely before updating. |
| scm_track_submodules | "" | no | bool | Track submodules latest commit on specified branch. |
| scm_update_on_launch | "" | no | bool | Before an update to the local repository before launching a job with this project. |
| scm_update_cache_timeout | "" | no | str | Cache Timeout to cache prior project syncs for a certain number of seconds. Only valid if scm_update_on_launch is to True, otherwise ignored. |
| allow_override | "" | no | str | Allow changing the SCM branch or revision in a job template that uses this project. |
| timeout | "" | no | Int | The amount of time (in seconds) to run before the SCM Update is canceled. A value of 0 means no timeout. |
| custom_virtualenv | "" | no | str | Local absolute file path containing a custom Python virtualenv to use. |
| notification_templates_started | "" | no | list | The notifications on started to use for this organization in a list. |
| notification_templates_success | "" | no | list | The notifications on success to use for this organization in a list. |
| notification_templates_error | "" | no | list | The notifications on error to use for this organization in a list. |
| state | present | no | str | Desired state of the resource. |
| wait | "" | no | bool | Provides option to wait for completed project sync before returning. |
| update_project | False | no | bool | Force project to update after changes. Used in conjunction with wait, interval, and timeout. |
| interval | "" | no | float | The interval to request an update from controller. Requires wait. |
When we fill it in, the following file is created in which both an inventory and a code
inventory are included:
Of these, we will usually need 2, one in the all with the most projects and a separate
one in the environment for the inventory (which will be different for each
environment).
In the all you can find all the code projects:
---
controller_projects_all:
- name: NEW_ORG code install packages
Description: Installation of necessary packages on Linux
organization: NEW_ORG
scm_type: git
scm_url: git@server.... code_package_install.git
scm_credential: NEW_ORG_git
scm_branch: master
scm_clean: false
scm_delete_on_update: false
scm_update_on_launch: false
scm_update_cache_timeout: 0
allow_override: false
timeout: 0
...
The environments will contain the inventory projects, per environment:
---
controller_projects_dev:
- name: NEW_ORG inventory linux
Description: Inventory Project for Linux Systems
organization: NEW_ORG
scm_type: git
scm_url: git@server..... git
scm_credential: NEW_ORG_git
scm_branch: master
scm_clean: false
scm_delete_on_update: false
scm_update_on_launch: true
scm_update_cache_timeout: 0
allow_override: false
timeout: 0
...
We see here that there will now be 2 projects created within the organization NEW_ORG, an inventory and a code project in which ansible code for. system configuration is saved.
inventory.yaml
An inventory in AAP is a collection of variables for machines that need to be configured via ansible. The file has the following content, which will need to be modified:
---
controller_inventories_xx:
- name:
description:
organization:
controller_inventory_sources_xx:
- name:
description:
organization:
source:
source_project:
source_path:
inventory:
update_on_launch:
overwrite:
...
We go through the file step-by-step and fill in the various parameters to add a
working inventory.
The inventory.yaml file has 2 sections:
controller_inventories_xx
controller_inventory_sources_xx
The inventory is the part that becomes visible in the controller and that can be used in playbooks, the inventory_sources is the part that takes care of the filling of the inventory, there can be several per inventory, we assume 1 source per inventory.
Data Structure inventory
| Variable Name | Default Value | Required | Type | Description |
|---|---|---|---|---|
| name | "" | yes | str | Name of this inventory. |
| new_name | "" | no | str | Setting this option will change the existing name (looked up via the name field). |
| copy_from | "" | no | str | Name or id to copy the inventory from. This will copy an existing inventory and change any parameters supplied. |
| description | "" | no | str | Description of this inventory. |
| organization | "" | yes | str | Organization this inventory belongs to. |
| instance_groups | "" | no | list | List of Instance Groups for this Inventory to run on. |
| input_inventories | "" | no | list | List of Inventories to use as input for Constructed Inventory. |
| variables | {} | no | dict | Variables for the inventory. |
| kind | "" | no | str | The kind of inventory. Currently choices are '' and 'smart' |
| host_filter | "" | no | str | The host filter field, useful only when 'kind=smart' |
| prevent_instance_group_fallback | False | no | bool | Prevent falling back to instance groups set on the organization |
| state | present | no | str | Desired state of the resource. |
Data Structure inventory_sources
| Variable Name | Default Value | Required | Description |
|---|---|---|---|
| name | "" | yes | The name to use for the inventory source. |
| new_name | "" | no | A new name for this assets (will rename the asset). |
| description | False | no | The description to use for the inventory source. |
| inventory | "" | yes | Inventory the group should be made a member of. |
| organization | "" | no | Organization the inventory belongs to. |
| source | "" | no | The source to use for this group. If set to constructed this role will be skipped as they are not meant to be edited. |
| source_path | "" | no | For an SCM based inventory source, the source path points to the file within the repo to use as an inventory. |
| source_vars | "" | no | The variables or environment fields to apply to this source type. |
| enabled_var | "" | no | The variable to use to determine enabled state e.g., "status.power_state". |
| enabled_value | "" | no | Value when the host is considered enabled, e.g., "powered_on". |
| host_filter | "" | no | If specified, controller will only import hosts that match this regular expression. |
| limit | "" | no | Enter host, group or pattern match. |
| credential | "" | no | Credential to use for the source. |
| execution_environment | "" | no | Execution Environment to use for the source. |
| overwrite | "" | no | Delete child groups and hosts not found in source. |
| overwrite_vars | "" | no | Override vars in child groups and hosts with those from external source |
| custom_virtualenv | "" | no | Local absolute file path containing a custom Python virtualenv to use. |
| timeout | "" | no | The amount of time (in seconds) to run before the task is canceled. |
| verbosity | "" | no | The verbosity level to run this inventory source under. |
| update_on_launch | "" | no | Refresh inventory data from its source each time a job is run. |
| update_cache_timeout | "" | no | Time in seconds to consider an inventory sync to be current. |
| source_project | "" | no | Project to use as source with scm option. |
| scm_branch | "" | no | Project scm branch to use as source with scm option. Project must have branch override enabled. |
| state | present | no | Desired state of the resource. |
| notification_templates_started | "" | no | The notifications on started to use for this inventory source in a list. |
| notification_templates_success | "" | no | The notifications on success to use for this inventory source in a list. |
| notification_templates_error | "" | no | The notifications on error to use for this inventory source in a list. |
controller_inventories_xx
Below is the first section that we are going to fill:There are 3 parameters that ensure that the inventory is created.
controller_inventories_xx:
- name:
description:
organization:
- Name: The name in controller for the inventory, by always providing the name of the organization first, we keep things unique.
- Description: The description of the inventory, which becomes especially important when multiple inventories are created.
- organization: The name of the organization for which the inventory is being created.
When we go to fill these, the following section is created:
controller_inventories_all:
- name: NEW_ORG inventory
description: Linux inventory
organization: NEW_ORG
We see that where the names need to be created, we use the name of the team as a prefix, we have to do this to keep the naming unique within the entire AAP configuration. By doing this, we avoid naming conflicts if we open up a lot of teams in AAP.
controller_inventory_sources_xx
Then the 2nd section within the file:
For an inventory that is based on a git repository, reference should be made to a
project.
We fill in the link to that project here:
---
controller_inventory_sources_xx:
- name:
description:
organization:
source:
source_project:
source_path:
inventory:
update_on_launch:
overwrite:
...
By keeping the inventory project names the same in all environments, we can suffice with a configuration in _all.
controller_inventory_sources_all:
- name: New_ORG inventory
description: Inventory
organization: NEW_ORG
source: scm
source_project: NEW_ORG inventory linux
source_path: hosts.yml
inventory: NEW_ORG inventory
update_on_launch: true
overwrite: true
...
templates.yaml
Templates are the executable parts of the configuration within AAP.
Through templates, we can run code stored in git, against hosts that are also stored in git, this
is called inventories.
This is where the previous configurations come together to form a feasible unit.
---
controller_templates_xx:
- name:
description:
organization:
project:
inventory:
playbook:
job_type:
fact_caching_enabled:
credentials:
concurrent_jobs_enabled:
ask_scm_branch_on_launch:
ask_tags_on_launch:
ask_verbosity_on_launch:
ask_variables_on_launch:
extra_vars:
execution_environment:
survey_enabled:
survey_spec: {}
...
Below is the list of parameters and their necessary filling:
Data Structure
| Variable Name | Default Value | Required | Type | Description |
|---|---|---|---|---|
| name | "" | yes | str | Name of Job Template |
| new_name | "" | str | no | Setting this option will change the existing name (looked up via the name field). |
| copy_from | "" | no | str | Name or id to copy the job template from. This will copy an existing credential and change any parameters supplied. |
| description | False | no | str | Description to use for the job template. |
| execution_environment | "" | no | str | Execution Environment to use for the job template. |
| job_type | run | no | str | The job type to use for the job template(run, check). |
| inventory | "" | no | str | Name of the inventory to use for the job template. |
| organization | "" | no | str | Organization the job template exists in. Used to help lookup the object, cannot be modified using this module. The Organization is inferred from the associated project |
| project | "" | no | str | Name of the project to use for the job template. |
| playbook | "" | no | str | Path to the playbook to use for the job template within the project provided. |
| credentials | "" | no | list | List of credentials to use for the job template. |
| forks | "" | no | Int | The number of parallel or simultaneous processes to use while executing the playbook. |
| limit | "" | no | str | A host pattern to further constrain the list of hosts managed or affected by the playbook |
| verbosity | "" | no | Int | Control the output level Ansible produces as the playbook runs. 0 - Normal, 1 - Verbose, 2 - More Verbose, 3 - Debug, 4 - Connection Debug . |
| extra_vars | "" | no | dict | Specify extra_vars for the template. |
| job_tags | "" | no | str | Comma separated list of the tags to use for the job template. |
| force_handlers | "" | no | bool | Enable forcing playbook handlers to run even if a task fails. |
| skip_tags | "" | no | str | Comma separated list of the tags to skip for the job template. |
| start_at_task | "" | no | str | Start the playbook at the task matching this name. |
| diff_mode | "" | no | bool | Enable diff mode for the job template |
| use_fact_cache | "" | no | bool | Enable use of fact caching for the job template. |
| host_config_key | "" | no | str | Allow provisioning callbacks using this host config key. |
| ask_scm_branch_on_launch | "" | no | bool | Prompt user for scm branch on launch. |
| ask_diff_mode_on_launch | "" | no | bool | Prompt user to enable diff mode show changes to files when supported by modules. |
| ask_variables_on_launch | "" | no | bool | Prompt user for extra_vars on launch. |
| ask_limit_on_launch | "" | no | bool | Prompt user for a limit on launch. |
| ask_tags_on_launch | "" | no | bool | Prompt user for job tags on launch. |
| ask_skip_tags_on_launch | "" | no | bool | Prompt user for job tags to skip on launch. |
| ask_job_type_on_launch | "" | no | bool | Prompt user for job type on launch. |
| ask_verbosity_on_launch | "" | no | bool | Prompt user to choose a verbosity level on launch. |
| ask_inventory_on_launch | "" | no | bool | Prompt user for inventory on launch. |
| ask_credential_on_launch | "" | no | bool | Prompt user for credential on launch. |
| ask_execution_environment_on_launch | "" | no | bool | Prompt user for execution environment on launch. |
| ask_forks_on_launch | "" | no | bool | Prompt user for forks on launch. |
| ask_instance_groups_on_launch | "" | no | bool | Prompt user for instance groups on launch. |
| ask_job_slice_count_on_launch | "" | no | bool | Prompt user for job slice count on launch. |
| ask_labels_on_launch | "" | no | bool | Prompt user for labels on launch. |
| ask_timeout_on_launch | "" | no | bool | Prompt user for timeout on launch. |
| prevent_instance_group_fallback | "" | no | bool | Prevent falling back to instance groups set on the associated inventory or organization. |
| survey_enabled | "" | no | bool | Enable a survey on the job template. |
| survey_spec | "" | no | dict | JSON/YAML dict formatted survey definition. |
| survey | "" | no | dict | JSON/YAML dict formatted survey definition. Alias of survey_spec |
| become_enabled | "" | no | bool | Activate privilege escalation. |
| allow_simultaneous | "" | no | bool | Allow simultaneous runs of the job template. |
| timeout | "" | no | Int | Maximum time in seconds to wait for a job to finish (server-side). |
| instance_groups | "" | no | list | list of Instance Groups for this Job Template to run on. |
| job_slice_count | "" | no | Int | The number of jobs to slice into at runtime. Will cause the Job Template to launch a workflow if value is greater than 1. |
| webhook_service | "" | no | str | Service that webhook requests will be accepted from (github, gitlab) |
| webhook_credential | "" | no | str | Personal Access Token for posting back the status to the service API |
| scm_branch | "" | no | str | Branch to use in job run. Project default used if blank. Only allowed if project allow_override field is set to true. |
| labels | "" | no | list | The labels applied to this job template. NOTE: Labels must be created with the labels role first, an error will occur if the label supplied to this role does not exist. |
| custom_virtualenv | "" | no | str | Local absolute file path containing a custom Python virtualenv to use. |
| notification_templates_started | "" | no | list | The notifications on started to use for this organization in a list. |
| notification_templates_success | "" | no | list | The notifications on success to use for this organization in a list. |
| notification_templates_error | "" | no | list | The notifications on error to use for this organization in a list. |
| state | present | no | str | Desired state of the resource. |
If we are going to fill it in for the project we have created, the following file will follow:
---
controller_templates_all:
- name: NEW_ORG install packages
description: Install packages on servers
organization: NEW_ORG
project: NEW_ORG code install packages
inventory: NEW_ORG inventory linux
playbook: main.yml
job_type: run
fact_caching_enabled: false
credentials:
- NEW_ORG_ansible
concurrent_jobs_enabled: false
ask_scm_branch_on_launch: false
ask_tags_on_launch: false
ask_verbosity_on_launch: false
ask_variables_on_launch: false
extra_vars:
hosts: all
execution_environment: Default execution environment
survey_enabled: false
survey_spec: {}
As a result, if it is sent to AAP via the pipeline, the template will be created. However, this template will not be visible/executable for everyone in the organization, for that we are still missing a small piece of configuration, especially rights, we will come back to that later.
Surveys
Surveys deserve some extra attention because they are rather difficult to include in
the code. To add a survey to your job template, you must first set the key
"survey_enabled" to "true", otherwise there will be a survey, but you will never see it.
Surveys will often vary from environment to environment! The templates will
therefore have to be created per environment.
A survey is specified as a dict object, which is included as a dict under the
survey_spec. The specification of the options and items to be specified can be seen
below: A survey rule consists of the following keys:
| key | definition |
|---|---|
| name: | The name for the survey |
| description: | The description of the survey |
| spec: | The specification of the survey is provided below |
Most of these fields can be left '' (blank), except for the spec, which should contain
the questions to be asked in the survey.
So, a survey rule basically has the following structure:
survey_spec:
- name: ''
description: ''
spec:
In the "spec" field, the questions of the survey must be included, each survey question also has a defined format:
Data Structure
| Variable Name | Variable Description |
|---|---|
| name | Name of the survey |
| description | Description of the survey |
| spec | List of survey items, each a dictionary containing the following fields |
| question_name | Name of the field/item |
| question_description | Longer description |
| required | Boolean expressing if an answer is required |
| type | One of text, password, integer, float, multiplechoiceor multiselect |
| variable | Name of Ansible Variable where to put the answer |
| default | Default value for the variable |
| min | Minimum value for a number type |
| max | Maximum value for a number type |
| choices | List of choices for a "multi" type |
| new_question | Boolean |
Example 1:
If only 1 question is asked, the syntax of a survey spec is as follows:
survey_spec:
- name: ''
description: ''
spec:
- question_name: Give a value
question_description: ''
required: true
type: integer
variable: var_getal
min: 0
max: 1024
default: ''
choices: ''
new_question: true
Example 2
If a survey needs to ask multiple questions, simply add the extra
requirements as follows:
survey_spec:
- name: ''
description: ''
spec:
- question_name: Give a value
question_description: ''
required: true
type: integer
variable: var_getal
min: 0
max: 1024
default: ''
choices: ''
new_question: false
- question_name: Enter a second value
question_description: ''
required: true
type: multiplechoice
variable: var_keuze
min: 0
max: 1024
default: ''
choices:
- Option1
- Option2
- Option3
new_question: true
schedules.yaml
A task can be scheduled to run so that it runs at regular intervals. In the example below, the private automation hub synchronization is scheduled to run at 11 a.m. every Tuesday and Thursday. The tricky part here is the content of the RRULE, which is not well explained in the documentation, but there is plenty of information about it online. Example:
---
controller_schedules_all:
- name: Sync Private Hub
description: Sync Private hub repos
unified_job_template: sync_private_hub
rrule: "DTSTART:20230711T110000Z RRULE:FREQ=DAILY; INTERVAL=1; BYDAY=TU,TH"
...
Data Structure
| Variable Name | Default Value | Required | Type | Description |
|---|---|---|---|---|
| name | "" | yes | str | Name of Job Template |
| new_name | "" | str | no | Setting this option will change the existing name (looked up via the name field). |
| description | False | no | str | Description to use for the job template. |
| rrule | "" | yes | str | A value representing the schedules iCal recurrence rule. See the awx.awx.schedule plugin for help constructing this value |
| extra_data | {} | no | dict | Extra vars for the job template. Only allowed if prompt on launch |
| inventory | "" | no | str | Inventory applied to job template, assuming the job template prompts for an inventory. |
| credentials | "" | no | list | List of credentials applied as a prompt, assuming job template prompts for credentials |
| scm_branch | Project default | no | str | Branch to use in the job run. Project default used if not set. Only allowed if allow_override set to true on project |
| execution_environment | Job Template default | no | str | Execution Environment applied as a prompt. Job Template default used if not set. Only allowed if ask_execution_environment_on_launch set to true on Job Template |
| forks | Job Template default | no | str | Forks applied as a prompt. Job Template default used if not set. Only allowed if ask_forks_on_launch set to true on Job Template |
| instance_groups | Job Template default | no | str | List of Instance Groups applied as a prompt. Job Template default used if not set. Only allowed if ask_instance_groups_on_launch set to true on Job Template |
| job_slice_count | Job Template default | no | str | Job Slice Count to use in the job run. Job Template default used if not set. Only allowed if ask_job_slice_count_on_launch set to true on Job Template |
| labels | Job Template default | no | list | List of labels to use in the job run. Job Template default used if not set. Only allowed if ask_labels_on_launch set to true on Job Template |
| timeout | Job Template default | no | str | Timeout to use in the job run. Job Template default used if not set. Only allowed if ask_timeout_on_launch set to true on Job Template |
| job_type | Job template default | no | str | The job type used for the job template. |
| job_tags | "" | no | str | Comma separated list of tags to apply to the job |
| skip_tags | "" | no | str | Comma separated list of tags to skip for the job |
| limit | "" | no | str | A host pattern to constrain the list of hosts managed or affected by the playbook |
| diff_mode | Job template default | no | bool | Enable diff mode for the job template |
| verbosity | Job template default | no | Int | Level of verbosity for the job. Only allowed if configured to prompt on launch |
| unified_job_template | "" | no | string | The name of object that is being targeted by the schedule. Example objects include projects, inventory sources, and templates. Required if state='present. |
| organization | "" | no | str | The organization the unified job template exists in. Used for looking up the unified job template, not a direct model field. |
| enabled | true | no | bool | Enabled processing of this job template |
| state | present | no | str | Desired state of the resource. |
teams.yaml
The configuration tooling via the pipeline offers the possibility to add teams, but if LDAP or AD is used, no configuration is necessary. For the sake of completeness, this option will be included in the documentation.
---
controller_teams_xx:
- name:
description:
organization:
...
Below is the list of parameters and their necessary filling:
Data Structure
| Variable Name | Default Value | Required | Type | Description |
|---|---|---|---|---|
| name | yes | str | The desired team name to create or modify | |
| new_name | no | str | ||
| description | omitted | no | str | The team description |
| organization | yes | str | The organization in which team will be created | |
| state | present | no | str | Desired state of the resource. |
If we are going to add teams according to the above rules, the following file follows:
---
controller_teams_all:
- name: NEW_ORG developers
description: devel users
organization: NEW_ORG
- name: NEW_ORG admins
description: admin users
organization: NEW_ORG
...
roles.yaml
The users and teams are known, now it's time to give the various users rights to see,
implement or even change things. This is done through the roles, which are assigned
to each team.
This is the most important part of the configuration.
In the roles.yaml, all previous steps come together, here rights are linked to user
groups, without this link, you as a user in the created organization will not see
anything.
---
controller_roles_xx:
- team:
job_templates:
role:
- team:
credentials:
role:
- team:
inventory:
role:
- team:
projects:
role:
...
Below is the list of parameters and their necessary filling:
Data Structure
| Variable Name | Default Value | Required | Type | Description |
|---|---|---|---|---|
| user | "" | no | str | The user for which the role applies |
| users | "" | no | list | The users for which the role applies |
| team | "" | no | str | The team for which the role applies |
| teams | "" | no | list | The teams for which the role applies |
| roles | "" | no | str | (see note below) The roles which are applied to one of {target_team, inventory, job_template, target_team, inventory, job_template} for either user or team |
| role | "" | no | str | (see note below) The role which is applied to one of {target_team, inventory, job_template, target_team, inventory, job_template} for either user or team |
| target_team | "" | no | str | The team the role applies against |
| target_teams | "" | no | list | The teams the role applies against |
| inventory | "" | no | str | The inventory the role applies against |
| inventories | "" | no | list | The inventories the role applies against |
| job_template | "" | no | str | The job template the role applies against |
| job_templates | "" | no | list | The job templates the role applies against |
| workflow | "" | no | str | The workflow the role applies against |
| workflows | "" | no | list | The workflows the role applies against |
| credential | "" | no | str | The credential the role applies against |
| credentials | "" | no | list | The credentials the role applies against |
| organization | "" | no | str | The organization the role applies against |
| organizations | "" | no | list | The organizations the role applies against |
| lookup_organization | "" | no | str | Organization the inventories, job templates, projects, or workflows the items exists in. Used to help lookup the object, for organization roles see organization. If not provided, will lookup by name only, which does not work with duplicates. |
| project | "" | no | str | The project the role applies against |
| projects | "" | no | list | The project the role applies against |
| instance_groups | "" | no | list | The instance groups the role applies against |
| state | present | no | str | Desired state of the resource. |
Permissions are given by filling the role parameter with one of the following values:
| role | definition |
|---|---|
| read | Only read rights, may see it, but not execute/modify it |
| use | The team may use it to execute and read |
| execute | The team is allowed to carry it out (job templates) |
| adhoc | The team is allowed to use the inventory for ad hoc commands |
| update | The team is allowed to update the inventory (in AAP, don't use it!) |
| admin | All rights to run or modify |
If we are going to assign rights to Teams according to the above rules, the following file follows: Since many companies use an AD configuration, the "user" keys will be missing. At "team" the AD group name must be entered, after which assigning the rights will also work, see the example below:
---
controller_roles_all:
- team: L-LDAP-DEV
job_templates:
- NEW_ORG install packages
role: execute
- team: L-LDAP-DEV
credentials:
- NEW_ORG_git
- NEW_ORG_ansible
- NEW_ORG_automation_hub_token_rh_certified
- NEW_ORG_automation_hub_token_published
role: use
- team: L-LDAP-DEV
inventories:
- NEW_ORG inventory
role: use
- team: L-LDAP-DEV
projects:
- NEW_ORG NEW_ORG code install packages
role: use
...
The L-LDAP-DEV is the group name configured in AD or LDAP and associated with the organization NEW_ORG. Important, make sure that the groups are given rights on all related objects, which belong together, otherwise the configuration is not functional! So if a user needs to be able to perform a "template_x", they must also have rights for the following, related objects:
- credentials
- inventory
- project(s)
users.yaml
Create the users who have access to automation controller for the organization, in the case of an organization with an LDAP or AD link, this file will not be used and even if values are put in it, this should not lead to users. This may only be read into the base configuration. Make sure that the passwords in this file are always vault encrypted. Example:
---
controller_user_accounts_all:
- username: deploy
password: password
email:
first_name: deploy
last_name:
auditor: false
update_secrets: false
...
Data Structure
| Variable Name | Default Value | Required | Type | Description |
|---|---|---|---|---|
| username | "" | yes | str | The username of the user |
| new_username | "" | yes | str | Setting this option will change the existing username (looked up via the username field). |
| password | "{{ controller_user_default_password }}" | no | str | The password of the user |
| "" | yes | str | The email of the user | |
| first_name | "" | no | str | The first name of the user |
| last_name | "" | no | str | The last name of the user |
| is_superuser | false | no | bool | Whether the user is a superuser |
| is_system_auditor | false | no | bool | Whether the user is an auditor |
| organization | "" | no | str | The name of the organization the user belongs to. Added in awx.awx >= 20.0.0 DOES NOT exist in ansible.controller yet. |
| state | present | no | str | Desired state of the resource. |
| update_secrets | true | no | bool | True will always change password if user specifies password, even if API gives encrypted for password. False will only set the password if other values change too. |
workflows.yaml
With a workflow, we can have a number of job_templates executed in a structured way, whereby the execution of the next template can depend on the result of the current task. This can be very useful in very complex environments.
---
controller_workflows:
- name: Simple workflow schema
description: a basic workflow
extra_vars: ''
survey_enabled: false
allow_simultaneous: false
ask_variables_on_launch: false
inventory:
limit:
scm_branch:
ask_inventory_on_launch: false
ask_scm_branch_on_launch: false
ask_limit_on_launch: false
webhook_service: ''
webhook_credential:
organization: Default
schedules: []
simplified_workflow_nodes:
- all_parents_must_converge: false
identifier: node101
unified_job_template: RHVM-01
credentials: []
success_nodes:
- node201
failure_nodes: []
always_nodes: []
- identifier: node201
approval_node:
name: Simple approval node name
description: Approve this to proceed in workflow
timeout: 900 # 15 minutes
- all_parents_must_converge: false
identifier: node301
unified_job_template: test-template-1
credentials: []
success_nodes: []
failure_nodes: []
always_nodes: []
notification_templates_started: []
notification_templates_success: []
notification_templates_error: []
notification_templates_approvals: []
survey_spec: {}
Data Structure
| Variable Name | Default Value | Required | Type | Description |
|---|---|---|---|---|
| name | "" | yes | str | Name of Workflow Job Template |
| new_name | "" | str | no | Setting this option will change the existing name (looked up via the name field). |
| copy_from | "" | no | str | Name or id to copy the Workflow template from. This will copy an existing workflow and change any parameters supplied. |
| description | "" | no | str | Description to use for the job template. |
| organization | "" | no | list | Organization the workflow job template exists in. Used to lookup the object, cannot be changed with this module |
| ask_inventory_on_launch | "" | no | bool | Prompt user for inventory on launch. |
| ask_limit_on_launch | "" | no | bool | Prompt user for a limit on launch. |
| ask_scm_branch_on_launch | "" | no | boo | Prompt user for scm branch on launch. |
| ask_variables_on_launch | "" | no | bool | Prompt user for extra_vars on launch. |
| extra_vars | "" | no | dict | Specify extra_vars for the template. |
| allow_simultaneous | "" | no | bool | Allow simultaneous runs of the workflow job template. |
| inventory | "" | no | str | Inventory applied as a prompt, assuming job template prompts for inventory |
| limit | "" | no | str | Limit applied as a prompt, assuming job template prompts for limit |
| labels | "" | no | str | The labels applied to this job template. NOTE: Labels must be created with the labels role first, an error will occur if the label supplied to this role does not exist. |
| ask_labels_on_launch | "" | no | bool | Prompt user for labels on launch. |
| job_tags | "" | no | str | Comma separated list of the tags to use for the workflow job template. |
| skip_tags | "" | no | str | Comma separated list of the tags to skip for the workflow job template. |
| ask_tags_on_launch | "" | no | bool | Prompt user for job tags on launch. |
| ask_skip_tags_on_launch | "" | no | bool | Prompt user for job tags to skip on launch. |
| notification_templates_approvals | "" | no | list | The notifications on approval to use for this organization in a list. |
| notification_templates_error | "" | no | list | The notifications on error to use for this organization in a list. |
| notification_templates_started | "" | no | list | The notifications on started to use for this organization in a list. |
| notification_templates_success | "" | no | list | The notifications on success to use for this organization in a list. |
| scm_branch | "" | no | str | SCM branch applied as a prompt, assuming job template prompts for SCM branch |
| state | present | no | str | Desired state of the resource. |
| workflow_nodes | "" | no | dict | A json list of nodes and their corresponding options. The sub-options are in the module doc. |
| destroy_current_nodes | "" | no | dict | Set in order to destroy current schema on the workflow, used in cases where drastic changes to schema are happening. |
| survey_enabled | "" | no | bool | Enable a survey on the job template. |
| survey_spec | "" | no | dict | JSON/YAML dict formatted survey definition. |
| survey | "" | no | dict | JSON/YAML dict formatted survey definition. Alias of survey_spec |
| webhook_service | "" | no | str | Service that webhook requests will be accepted from (github, gitlab) |
| webhook_credential | "" | no | str | Personal Access Token for posting back the status to the service API |
Variables for Workflow Job Template Node
| Variable Name | Default Value | Required | Type | Description |
|---|---|---|---|---|
| workflow_job_template | "" | yes | str | The workflow job template the node exists in. Used for looking up the node, cannot be modified after creation. |
| identifier | "" | yes | str | An identifier for this node that is unique within its workflow. It is copied to workflow job nodes corresponding to this node. This functions the same as the name field for other resources, however if it is not set, it will be set to a random UUID4 value. Recommended to use Column and row numbers for identifiers such as Node401. |
| unified_job_template | "" | no | str | Name of unified job template to run in the workflow. Can be a job template, project, inventory source, etc. This parameter is mutually exclusive with approval_node. |
| lookup_organization | "" | no | str | Organization the inventories, job templates, projects, or workflows the items exists in. Used to help lookup the object, for organization roles see organization. If not provided, will lookup by name only, hich does not work with duplicates. |
| execution_environment | Job Template default | no | str | Execution Environment applied as a prompt. Job Template default used if not set. Only allowed if ask_execution_environment_on_launch set to true on Job Template |
| forks | Job Template default | no | str | Forks applied as a prompt. Job Template default used if not set. Only allowed if ask_forks_on_launch set to true on Job Template |
| instance_groups | Job Template default | no | str | List of Instance Groups applied as a prompt. Job Template default used if not set. Only allowed if ask_instance_groups_on_launch set to true on Job Template |
| job_slice_count | Job Template default | no | str | Job Slice Count to use in the job run. Job Template default used if not set. Only allowed if ask_job_slice_count_on_launch set to true on Job Template |
| labels | Job Template default | no | list | List of labels to use in the job run. Job Template default used if not set. Only allowed if ask_labels_on_launch set to true on Job Template. NOTE: Labels must be created with the labels role first, an error will occur if the label supplied to this role does not exist. |
| timeout | Job Template default | no | str | Timeout to use in the job run. Job Template default used if not set. Only allowed if ask_timeout_on_launch set to true on Job Template |
| approval_node | "" | no | str | A dictionary of Name, description, and timeout values for the approval node. This parameter is mutually exclusive with unified_job_template. |
| always_nodes | "" | no | list | Nodes that will run after this node completes. |
| failure_nodes | "" | no | list | Nodes that will run after this node completes. |
| success_nodes | "" | no | list | Nodes that will run after this node completes. |
| verbosity | "" | no | str | Verbosity applied as a prompt, if job template prompts for verbosity |
| state | "" | no | str | Desired state of the resource |
| credentials | "" | no | list | Credentials to be applied to job as launch-time prompts. |
| diff_mode | "" | no | bool | Run diff mode, applied as a prompt, if job template prompts for diff mode |
| extra_data | "" | no | dict | Variables to apply at launch time. Will only be accepted if job template prompts for vars or has a survey asking for those vars. extra_data are extra_vars at the node level and named so to match the module and the API. These are only for "ask extra vars on prompt" on a given job template. |
| inventory | "" | no | str | Inventory applied as a prompt, if job template prompts for inventory |
| job_tags | "" | no | str | Job tags applied as a prompt, if job template prompts for job tags |
| job_type | "" | no | str | Job type applied as a prompt, if job template prompts for job type |
| limit | "" | no | str | Limit to act on, applied as a prompt, if job template prompts for limit |
| scm_branch | "" | no | str | SCM branch applied as a prompt, if job template prompts for SCM branch |
| skip_tags | "" | no | str | Tags to skip, applied as a prompt, if job template prompts for job tags |
Approval node dictionary
| Variable Name | Default Value | Required | Type | Description |
|---|---|---|---|---|
| name | "" | yes | str | Name of this workflow approval template. |
| description | "" | no | str | Optional description of this workflow approval template. |
| timeout | 0 | no | Int | The amount of time (in seconds) before the approval node expires and fails. |
Surveys
Refer to the Controller Api Guide for more information about forming surveys
| Variable Name | Variable description |
|---|---|
| name | Name of the survey |
| description | Description of the survey |
| spec | List of survey items, each a dictionary containing the following fields |
| question_name | Name of the field/item |
| question_description | Longer description |
| required | Boolean expressing if an answer is required |
| type | One of text, password, integer, float, multiplechoiceor multiselect |
| variable | Name of Ansible Variable where to put the answer |
| default | Default value for the variable |
| min | Minimum value for a number type |
| max | Maximum value for a number type |
| choices | List of choices for a "multi" type |
| new_question | Boolean |