Ansible plugins and use cases

ara_default callback: recording playbooks from Ansible

The ara_default Ansible callback plugin can be enabled by configuring Ansible with the ANSIBLE_CALLBACK_PLUGINS environment variable or the callback_plugins setting in an ansible.cfg file.

The callback is the component that recovers data during playbook execution and sends it to the API.

By default, the callback is configured up to use the local API server with the offline API client but it can be set up to use a remote API server, authenticate with credentials and more:

callback: ara
callback_type: notification
requirements:
  - ara
short_description: Sends playbook execution data to the ARA API internally or over HTTP
description:
  - Sends playbook execution data to the ARA API internally or over HTTP
options:
  api_client:
    description: The client to use for communicating with the API
    default: offline
    env:
      - name: ARA_API_CLIENT
    ini:
      - section: ara
        key: api_client
    choices: ['offline', 'http']
  api_server:
    description: When using the HTTP client, the base URL to the ARA API server
    default: http://127.0.0.1:8000
    env:
      - name: ARA_API_SERVER
    ini:
      - section: ara
        key: api_server
  api_username:
    description: If authentication is required, the username to authenticate with
    default: null
    env:
      - name: ARA_API_USERNAME
    ini:
      - section: ara
        key: api_username
  api_password:
    description: If authentication is required, the password to authenticate with
    default: null
    env:
      - name: ARA_API_PASSWORD
    ini:
      - section: ara
        key: api_password
  api_cert:
    description: If a client certificate is required, the path to the certificate to use.
    default: null
    env:
      - name: ARA_API_CERT
    ini:
      - section: ara
        key: api_cert
  api_key:
    description: If a client certificate is required, the path to the private key to use.
    default: null
    env:
      - name: ARA_API_KEY
    ini:
      - section: ara
        key: api_key
  api_ca:
    description: The path to a CA bundle.
    default: null
    env:
      - name: ARA_API_CA
    ini:
      - section: ara
        key: api_ca
  api_insecure:
    description: Can be enabled to ignore SSL certification of the API server
    type: bool
    default: false
    env:
      - name: ARA_API_INSECURE
    ini:
      - section: ara
        key: api_insecure
  api_timeout:
    description: Timeout, in seconds, before giving up on HTTP requests
    type: integer
    default: 30
    env:
      - name: ARA_API_TIMEOUT
    ini:
      - section: ara
        key: api_timeout
  argument_labels:
    description: |
        A list of CLI arguments that, if set, will be automatically applied to playbooks as labels.
        Note that CLI arguments are not always named the same as how they are represented by Ansible.
        For example, --limit is "subset", --user is "remote_user" but --check is "check".
    type: list
    default:
      - remote_user
      - check
      - tags
      - skip_tags
      - subset
    env:
      - name: ARA_ARGUMENT_LABELS
    ini:
      - section: ara
        key: argument_labels
  callback_threads:
    description:
      - The number of threads to use in API client thread pools (maximum 4)
      - When set to 0, no threading will be used (default) which is appropriate for usage with sqlite
      - Using threads is recommended when the server is using MySQL or PostgreSQL
    type: integer
    default: 0
    env:
      - name: ARA_CALLBACK_THREADS
    ini:
      - section: ara
        key: callback_threads
  default_labels:
    description: A list of default labels that will be applied to playbooks
    type: list
    default: []
    env:
      - name: ARA_DEFAULT_LABELS
    ini:
      - section: ara
        key: default_labels
  ignored_facts:
    description: List of host facts that will not be saved by ARA
    type: list
    default: ["ansible_env"]
    env:
      - name: ARA_IGNORED_FACTS
    ini:
      - section: ara
        key: ignored_facts
  ignored_arguments:
    description: List of Ansible arguments that will not be saved by ARA
    type: list
    default: ["extra_vars"]
    env:
      - name: ARA_IGNORED_ARGUMENTS
    ini:
      - section: ara
        key: ignored_arguments
  ignored_files:
    description:
      - List of file path patterns that will not be saved by ARA
      - Note that the default pattern ('.ansible/tmp') gets dynamically set to the value of ANSIBLE_LOCAL_TEMP
      - The configuration for ANSIBLE_LOCAL_TEMP is typically ~/.ansible/tmp unless it is changed.
    type: list
    default: [".ansible/tmp"]
    env:
      - name: ARA_IGNORED_FILES
    ini:
      - section: ara
        key: ignored_files
  localhost_as_hostname:
    description:
        - Associates results to the hostname (or fqdn) instead of localhost when the inventory name is localhost
        - Defaults to false for backwards compatibility, set to true to enable
        - This can be useful when targetting localhost, using ansible-pull or ansible-playbook -i 'localhost,'
        - This helps differentiating results between hosts, otherwise everything would be recorded under localhost.
    type: boolean
    default: false
    env:
      - name: ARA_LOCALHOST_AS_HOSTNAME
    ini:
      - section: ara
        key: localhost_as_hostname
  localhost_as_hostname_format:
    description:
      - The format to use when recording the hostname for localhost
      - This is used when recording the controller hostname or when ARA_LOCALHOST_TO_HOSTNAME is true
      - There are different formats to choose from based on the full (or short) configured hostname and fqdn
      - Defaults to 'fqdn' (i.e, server.example.org) but can be set to 'fqdn_short' (server)
      - Other options include 'hostname' and 'hostname_short' which may be suitable depending on server configuration
    default: fqdn
    env:
      - name: ARA_LOCALHOST_AS_HOSTNAME_FORMAT
    ini:
      - section: ara
        key: localhost_as_hostname_format
    choices: ['fqdn', 'fqdn_short', 'hostname', 'hostname_short']
  record_controller:
    description:
      - Whether ara should record the controller hostname on which the playbook ran
      - Defaults to true but may be optionally set to false for privacy or other use cases
    type: boolean
    default: true
    env:
      - name: ARA_RECORD_CONTROLLER
    ini:
      - section: ara
        key: record_controller
  record_controller_name:
    description:
      - The name to use when recording the controller hostname.
      - Defaults to the system hostname.
    type: string
    env:
      - name: ARA_RECORD_CONTROLLER_NAME
    ini:
      - section: ara
        key: record_controller_name
  record_user:
    description:
      - Whether ara should record the user that ran a playbook
      - Defaults to true but may be optionally set to false for privacy or other use cases
    type: boolean
    default: true
    env:
      - name: ARA_RECORD_USER
    ini:
      - section: ara
        key: record_user
  record_user_name:
    description:
      - The name to use when recording the user that ran a playbook.
      - Defaults to the OS user which ran the playbook.
    type: string
    env:
      - name: ARA_RECORD_USER_NAME
    ini:
      - section: ara
        key: record_user_name
  record_task_content:
    description:
      - Whether ara should record the content of a task
      - Defaults to true, set to false for privacy or other use cases
    type: boolean
    default: true
    env:
      - name: ARA_RECORD_TASK_CONTENT
    ini:
      - section: ara
        key: record_task_content

For example, a customized callback plugin configuration might look like this in an ansible.cfg file:

[ara]
api_client = http
api_server = https://demo.recordsansible.org
api_username = user
api_password = password
api_timeout = 15
callback_threads = 4
argument_labels = check,tags,subset
default_labels = prod,deploy
ignored_facts = ansible_env,ansible_all_ipv4_addresses
ignored_files = .ansible/tmp,vault.yaml,vault.yml
ignored_arguments = extra_vars,vault_password_files
localhost_as_hostname = true
localhost_as_hostname_format = fqdn

or as environment variables:

export ARA_API_CLIENT=http
export ARA_API_SERVER="https://demo.recordsansible.org"
export ARA_API_USERNAME=user
export ARA_API_PASSWORD=password
export ARA_API_TIMEOUT=15
export ARA_CALLBACK_THREADS=4
export ARA_ARGUMENT_LABELS=check,tags,subset
export ARA_DEFAULT_LABELS=prod,deploy
export ARA_IGNORED_FACTS=ansible_env,ansible_all_ipv4_addresses
export ARA_IGNORED_FILES=.ansible/tmp,vault.yaml,vault.yml
export ARA_IGNORED_ARGUMENTS=extra_vars,vault_password_files
export ARA_LOCALHOST_AS_HOSTNAME=true
export ARA_LOCALHOST_AS_HOSTNAME_FORMAT=fqdn

Recording ad-hoc commands

It is possible to record ad-hoc commands in addition to playbooks since ara 1.4.1 and Ansible 2.9.7.

Ad-hoc command recording can be enabled by setting to true the ANSIBLE_LOAD_CALLBACK_PLUGINS environment variable or bin_ansible_callbacks in an ansible.cfg file.

Playbook names and labels

Playbooks recorded by the ara callback can be given names or labels in order to make them easier to find and identify later.

They are set as ordinary Ansible variables and are evaluated at the beginning of each play. They can be provided directly in playbook files:

- name: Deploy prod environment
  hosts: prod
  vars:
    ara_playbook_name: deploy prod
    ara_playbook_labels:
      - deploy
      - prod
  roles:
    - application

or as extra-vars:

ansible-playbook -i hosts playbook.yaml \
    -e ara_playbook_name="deploy prod" \
    -e ara_playbook_labels=deploy,prod

Once set, they can be searched for in the UI, the API:

  • /api/v1/playbooks?name=prod
  • /api/v1/playbooks?label=prod

or the CLI:

  • ara playbook list --name prod
  • ara playbook list --label prod

Default labels

Default labels will be applied to every playbook recorded by the callback plugin and can be specified with an ansible.cfg file:

[defaults]
# ...
[ara]
default_labels = deploy,prod

or through the environment variable ARA_DEFAULT_LABELS:

export ARA_DEFAULT_LABELS=deploy,prod

CLI argument labels

CLI argument labels will automatically apply labels to playbooks when specified CLI arguments are used.

For example, if --check is used and set up as an argument label, the playbook will be tagged with check:True if --check was used or check:False if it wasn’t.

Note

Some CLI arguments are not always named the same as how they are represented by Ansible. For example, --limit is “subset”, --user is “remote_user” but --check is “check”.

Argument labels can be configured through an ansible.cfg file:

[defaults]
# ...
[ara]
argument_labels = check,subset,tags

or through the environment variable ARA_ARGUMENT_LABELS:

export ARA_ARGUMENT_LABELS=check,subset,tags

ara_api: free-form API queries

The ara_api Ansible lookup plugin can be enabled by configuring Ansible with the ANSIBLE_LOOKUP_PLUGINS environment variable or the lookup_plugins setting in an ansible.cfg file.

It can be used to do free-form queries to the ara API while the playbook is running:

- name: Test playbook
  hosts: localhost
  tasks:
    - name: Get failed results
      set_fact:
        failed: "{{ lookup('ara_api', '/api/v1/results?status=failed') }}"

    - name: Print task data from failed results
      vars:
        task_id: "{{ item.task | string }}"
        task: "{{ lookup('ara_api', '/api/v1/tasks/' + task_id ) }}"
        host_id: "{{ item.host | string }}"
        host: "{{ lookup('ara_api', '/api/v1/hosts/' + host_id) }}"
      debug:
        msg: "{{ host.name }} failed | {{ task.name }} ({{ task.path }}:{{ task.lineno }})"
      loop: "{{ failed.results }}"

ara_playbook: get the running playbook or one in specific

The ara_playbook Ansible action plugin can be enabled by configuring Ansible with the ANSIBLE_ACTION_PLUGINS environment variable or the action_plugins setting in an ansible.cfg file.

Without any arguments, it can be used to return data about the playbook from which it is running:

- name: Test playbook
  hosts: localhost
  tasks:
    - name: Get the currently running playbook
      ara_playbook:
      register: query

    - name: Retrieve playbook id
      set_fact:
        playbook_id: "{{ query.playbook.id | string }}"

    # With the playbook id we can create a link to the playbook report
    - name: Recover base url from ara
      set_fact:
        api_base_url: "{{ lookup('ara_api', '/api/') }}"

    - name: Print link to playbook report
      vars:
        ui_base_url: "{{ api_base_url.api[0] | regex_replace('/api/v1/', '') }}"
      debug:
        msg: "{{ ui_base_url }}/playbooks/{{ playbook_id }}.html"

With an argument, it can retrieve data from a specific playbook:

- name: Test playbook
  hosts: localhost
  tasks:
    - name: Get a specific playbook
      ara_playbook:
        playbook: 9001
      register: query

    - name: Print data about the playbook
      debug:
        msg: "Playbook {{ query.playbook.status }} in {{ query.playbook.duration }}"

ara_record: arbitrary key/values in playbook reports

The ara_record Ansible action plugin can be enabled by configuring Ansible with the ANSIBLE_ACTION_PLUGINS environment variable or the action_plugins setting in an ansible.cfg file.

It can be used to attach data or metadata to playbook reports so they are available later:

- name: Test playbook
  hosts: localhost
  tasks:
    - name: Get git version of playbooks
      command: git rev-parse HEAD
      register: git_version

    - name: Record git version
      ara_record:
        key: "git_version"
        value: "{{ git_version.stdout }}"
      register: version

    - name: Print recorded data
      debug:
        msg: "{{ version.playbook_id }} - {{ version.key }}: {{ version.value }}"

It is possible to declare a type which can be used to render the data appropriately later:

- name: Record different things
  ara_record:
    key: "{{ item.key }}"
    value: "{{ item.value }}"
    type: "{{ item.type }}"
  loop:
    - { key: "log", value: "error", type: "text" }
    - { key: "website", value: "http://domain.tld", type: "url" }
    - { key: "data", value: '{ "key": "value" }', type: "json" }
    - { key: "somelist", value: ['one', 'two'], type: "list" }
    - { key: "somedict", value: {'key': 'value' }, type: "dict" }

Adding records to playbooks after their completion

ara_record can attach data to a specific playbook by providing a playbook id. This can be useful for attaching data that might only be available once a playbook has been completed:

- name: Attach data to a specific playbook
  ara_record:
    playbook: 9001
    key: logs
    value: "{{ lookup('file', '/var/log/ansible.log') }}"
    type: text

Or as an ad-hoc command:

ansible localhost -m ara_record \
        -a "playbook=14 key=logs value={{ lookup('file', '/var/log/ansible.log') }}"