CaC for EDA (Event Driven Ansible)

EDA is the Event Driven Ansible controller, which enables you to import monitoring events and respond automatically, by running a remedial playbook.
Recently, it has become possible to create and maintain a configuration as code template and repository for the EDA as well. The necessary collection for this has received an important update from the community.

The collection required for this:
- infra.eda_configuration

If you're searching the web, you'll need to search for:
- redhat_cop.eda_configuration

Then you will also find all the accompanying documentation, which I have used here. Of course I used my trick to make things a bit easier. Because the trick is always the same, it is now easier to understand. Not much is recorded in the configuration as code for the EDA, because the most complex work is in the projects used by EDA. As usual, we start with a brief explanation of the pipeline.

The CaC pipeline

# Pull the ansible config as code image
image: localhost:5000/ansible-image:1.1

# List of pipeline stages
stages:
  - lint
  - Configure eda controller

lint_and_push:
  tags:
    - shared
  stage: lint
  rules:
    - if: '$CI_COMMIT_REF_NAME != "dev" 
           && $CI_COMMIT_REF_NAME != "test" 
           && $CI_COMMIT_REF_NAME != "accp" 
           && $CI_COMMIT_REF_NAME != "prod"'
  script:
    - echo "From pipeline - Start linting on '$CI_COMMIT_REF_NAME'"
    - ansible-lint

configure_from_merge:
  tags:
    - shared
  stage: Configure eda controller
rules:
    - if: '($CI_COMMIT_BRANCH == "dev" ||
            $CI_COMMIT_BRANCH == "test" ||
            $CI_COMMIT_BRANCH == "accp" ||
            $CI_COMMIT_BRANCH == "prod") &&
            $CI_PIPELINE_SOURCE == "push" &&
            $CI_COMMIT_MESSAGE =~ /Merge branch/i'
  script:
    - echo "Perform merge to '$CI_COMMIT_BRANCH' Environment"
    - TOKEN_VAR=$(echo "AUTOMATION_HUB_TOKEN_${CI_COMMIT_BRANCH}" | tr [:lower:] 
[:upper:])
    - ansible-playbook main.yml
      -i inventory.yaml
      -e instance=controller_$CI_COMMIT_BRANCH
      -e ahub_token=$(printenv $TOKEN_VAR)
      -e branch_name=$CI_COMMIT_BRANCH
      --vault-password-file <(echo ${VAULT_PASSWORD})

configure_from_trigger:
  tags:
    - shared
  stage: Configure eda controller
  rules:
    - if: '$CI_PIPELINE_SOURCE == "pipeline"'
  script:
    - echo "Pipeline triggered by '$CI_PIPELINE_SOURCE' ref"
    - echo "From pipeline - Start controller recovery on '$CI_COMMIT_REF_NAME' 
Environment"
    - ansible-playbook main.yml
      -i inventory.yaml
      -e instance=eda_$CI_COMMIT_REF_NAME
      -e branch_name=$CI_COMMIT_REF_NAME
      --vault-password-file <(echo ${VAULT_PASSWORD})

As can be read above, the pipeline is the most complex we have seen so far, this is the pipeline that we actually use. The pipelines in the previous chapters were evolutions to this version. By using "rules", we are pretty much in the future in gitlab, because the "only" tag is going to disappear. For the rest, we mainly make sure that when a feature branch is pushed, a linting of the code is always done. If the linting is successful, the update can be merged into the "dev" branch/environment, through a merge_request, which starts the configuration on the merge commit, by running the second part of the pipeline. If an update is made to a branch via a merge request, the second part of the pipeline will be executed. The last part of the pipeline is dedicated to the recovery from chapter 12, then this step of the pipeline will be executed. Because this configuration also contains secrets that give access to the environment, ansible-vault is also used. That is why a vault password must be provided in order to decrypt the secrets. This vault password is configured as a secret variable on the repository.

The git repository

The configuration as code of the eda also requires a git repository. This repository is similar in content and structure to the other repositories.

.
├── group_vars
│   ├── all
│   │   ├── credentials.yaml
│   │   ├── decision_environments.yaml
│   │   ├── projects.yaml
│   │   ├── rulebook_activations.yaml
│   │   ├── users.yaml
│   │   └── user_tokens.yaml
│   ├─ dev
│   │   ├── credentials.yaml
│   │   ├── decision_environments.yaml
│   │   ├── projects.yaml
│   │   ├── rulebook_activations.yaml
│   │   ├── users.yaml
│   │   └── user_tokens.yaml
│   └── test
│       ├── credentials.yaml
│       ├── decision_environments.yaml
│       ├── projects.yaml
│       ├── rulebook_activations.yaml
│       ├── users.yaml
│       └── user_tokens.yaml
├── host_vars
│   ├── hub_dev
│   │   └── eda_auth.yaml
│   └── hub_test
│       └── eda_auth.yaml
├── inventory.yaml
├── main.yml
└── README.md

You can see that not many files are used for an EDA configuration, the contents of which we will describe below.

credentials.yaml

An EDA installation only has a limited number of credential types, an option to authenticate with username and password is missing. Everything has to be authenticated with so-called tokens. This seems to be a great option, but it is limited in the number of sources that can be used.

---
eda_credentials_dev:
#   - name: my_github_user
#     description: my GitHub Credential
#     credential_type: 'GitHub Personal Access Token'
#     username: githubuser
#     secret: GITHUBTOKEN
#
  - name: superman
    description: 'Look mammy, no hands'
    credential_type: 'GitLab personal access token'
    username: superman
    secret: 'klfsk-450980498ba40328dc0d'

  - name: Image_cred
    description: 'Image pull credential'
    credential_type: 'Container Registry'
    username: image_pull_user
    secret: <vaulted-token>

Data Structure

Variable Name Default Value Required Type Description
name "" yes str Credential name. Must be lower case containing only alphanumeric characters and underscores.
new_name "" no str Setting this option will change the existing name (looked up via the name field.)
description "" no str Description to use for the credential.
username "" yes str The username of the credential.
secret "" yes str The token or password for the given username (depending upon the credential type).
credential_type "GitHub Personal Access Token" yes str The type of the credential.
state present no str Desired state of the credential.

decision_environments.yaml

If you are going to use EDA more, it may be necessary to use specific container images to perform certain checks, just like with a controller. Here, these images can be disclosed to EDA so that they can be retrieved as soon as it is used.

---
eda_decision_environments_dev:
#   - name: my_default_de
#     description: my default decision environment
#     image_url: "image_registry.example.com/default-de:latest"
#     credential: my_credential
  - name: secret_de_image
    description: 'some special check engine'
    image_url: "registry.example.com:5000/secret-image:latest"
    credential: Image_cred

Data Structure

Variable Name Default Value Required Type Description
name "" yes str Decision Environment name. Must be lower case containing only alphanumeric characters and underscores.
new_name "" no str Setting this option will change the existing name (looked up via the name field.)
description "" no str Description to use for the Project.
image_url "" yes str A URL to a a container image to use for the decision environment.
credential "" no str The credential used to access the container registry holding the image.
state present no str Desired state of the decision environment.

projects.yaml

A project in EDA is a reference to a git repository containing a directory rulebooks. This folder contains the rulebooks that are used to perform the event checks in the EDA. Rulebooks, are NOT playbooks and are treated differently here.

---
eda_projects_dev:
#   - name: my_project
#     description: my awesome project
#     url: https://github.com/ansible/ansible-rulebook.git
#     tls_validation: true
#     credential: test_token
#     validate_certs: false
#     wait: true
#     interval: 10
#     sync: true
  - name: webserver_checks
    description: 'rulebooks for webservers'
    url: https://gitlab.example.com/eda/webserver_ruleboks.git
    tls_validation: true
    credential: superman
    sync: true
    interval: 10
    wait: true

Data Structure

Variable Name Default Value Required Type Description
name "" Yes Str Project name. Must be lower case containing only alphanumeric characters and underscores.
new_name "" No Str Setting this option will change the existing name (looked up via the name field.)
description "" No Str Description to use for the Project.
url "" Yes Str A URL to a remote archive, such as a Github Release or a build artifact stored in Artifactory and unpacks it into the project path for use. (Alias: scm_url)
tls_validation True No Bool Whether the URL should validate using TLS.
validate_certs True No Bool Whether the certificate must be validated using SSL
credential "" No Str The token needed to utilize the SCM URL.
state present No str Desired state of the project.

rulebook_activations.yaml

EDA is all about executing rulebooks. These rulebooks include the steps that are performed to read events. And when these events are generated, they test whether they match the defined state and perform the corresponding actions.

---
eda_rulebook_activations_dev:
#   - name: Github Hook
#     description: Hook to listen for changes in GitHub
#     project: EDA_example
#     rulebook: git-hook-deploy-rules.yml
#     decision_environment: Automation Hub Default Decision Environment
#     extra_vars:
#      provider: github-local
#       repo_url: https://github.com/ansible/ansible-rulebook.git
#     enabled: false
#     state: present

  - name: webserver check
    description: check the webserver by url_check
    project: webserver_checks
    rulebook: check_website.yml
    decision_environment: Automation Hub Default Decision Environment
    enabled: true
    awx_token: ...
    state: present

A limitation in the configuration as code for the EDA is the content of the awx_token, which can be configured here, but it cannot be defined in the configuration as code for the controller. So there is a challenge in the event of a recovery, so it cannot be fully automated at the moment.

Data Structure

Variable Name Default Value Required Type Description
name "" Yes Str Rulebook activation name. Must be lower case containing only alphanumeric characters and underscores.
description "" No St Description to use for the Activation.
project "" No St Project to use for the Activation.
rulebook "" Yes Str rulebook to use for the Activation.
decision_environment "" Yes Str Decision_environment to use for the Activation.
restart_policy "always" No St Restart_policy to use for the Activation, choice of ["always", "never", "on-failure"]
extra_vars "" No Str Extra_vars to use for the Activation.
awx_token "" No Str The token used to authenticate to controller.
enabled "true" No Str Whether the rulebook activation is automatically enabled to run.
state Present No Str Desired state of the rulebook activation.

users.yaml

# - username: jane_doe
#   first_name: Jane
#   last_name: Doe
#   email: jdoe@example.com
#   password: my_password1
#   update_secrets: false
#   roles:
#     - Auditor
#     - Contributor
#     - Viewer
#     - Editor
#     - Operator
#     - Admin

Data Structure

Variable Name Default Value Required Type Description
username "" yes str Username. Must contain only letters, numbers, and @.+-_ characters.
new_username "" no str Setting this option will change the existing username (looked up via the name field.)
first_name "" no str First ame of the user.
last_name "" no str Last name of the user.
email "" no str User's email address.
password "" yes str Password to use for the user.
update_secrets true no bool Setting true will always change password if user specifies password. Password will only change if false if other fields change.
roles "" yes list Roles the user will have. Current acceptable values are: Viewer, Auditor, Editor, Contributor, Operator, Admin.
state present no str Desired state of the user.

user_tokens.yaml

---
eda_user_tokens_dev: []
#  - name: my_user_token
#    description: my descioption
#    token: my_token_value

Data Structure

Variable Name Default Value Required Type Description
name "" yes str User Token name. Must be lower case containing only alphanumeric characters and underscores.
new_name "" no str Setting this option will change the existing name (looked up via the name field.)
description "" no str Description to use for the Project.
token "" yes str The value of the token to associate with the user.

The tokens that are configured here can be created once in the automation controller and unfortunately cannot be included in the configuration as code, so in the event of a recovery, they are no longer valid and must be recreated and placed in this file. The pipeline then ensures that they become available again in EDA.

Back

Back to Site