Giter Site home page Giter Site logo

ansible-assertive's Introduction

Making assert more useful for infrastructure testing

This project contains two Ansible plugins:

  • A replacement for the core library assert action plugin.
  • The assertive stdout callback plugin

Supported Ansible versions

These plugins are tested with Ansible versions 2.2.3.0 and 2.3.1.0 and with the current devel branch.

About the assert module

The assert module operates very much like the one in the core library, with two key differences:

  • By default, a failed assert will be marked as changed rather than failed. You can enable the stock behavior by specifying fatal: true.

  • The plugin will always evaluate all the tests in your that array (that is, it will continue to evaluate tests even after one has failed). The individual tests and their results are returned in the assertions key.

  • The plugin takes advantage of Ansible's custom statistics functionality to count the number of failed/passed/total assertions.

Example 1

Here is a simple playbook that contains two assertions:

- hosts: localhost
  name: example 001.1
  vars:
    fruit:
      - apples
      - oranges
  tasks:
    - name: check that we have lemons
      assert:
        that:
          - "'lemons' in fruit"
        msg: we are missing lemons

    - name: check that we have apples
      assert:
        that:
          - "'apples' in fruit"
        msg: we are missing apples

If we run this using the stock behavior, we will see the following:


PLAY [example 001.1] ********************************************************************

TASK [Gathering Facts] ******************************************************************
ok: [localhost]

TASK [check that we have lemons] ********************************************************
fatal: [localhost]: FAILED! => {
    "assertion": "'lemons' in fruit", 
    "changed": false, 
    "evaluated_to": false, 
    "failed": true, 
    "msg": "we are missing lemons"
}

PLAY RECAP ******************************************************************************
localhost                  : ok=1    changed=0    unreachable=0    failed=1   

That is, playbook execution will abort after the first assertion failure. If we activate the replacement assert plugin with the following ansible.cfg:

[defaults]
action_plugins = ../../action_plugins

# we don't need retry files for running examples
retry_files_enabled = no

Then we will see that an assertion failure shows up as changed rather than failed, allowing playbook execution to continue:


PLAY [example 001.2] ********************************************************************

TASK [Gathering Facts] ******************************************************************
ok: [localhost]

TASK [check that we have lemons] ********************************************************
changed: [localhost]

TASK [check that we have apples] ********************************************************
ok: [localhost]

PLAY RECAP ******************************************************************************
localhost                  : ok=3    changed=1    unreachable=0    failed=0   

Example 2

The return value from the assert action includes information about the assertions as well as metadata that can be consumed by the custom statistics support in recent versions of Ansible. We could see the return value by instrumenting an assert task with a register directive and following it with a debug task, or we can enable the fail_verbose option by setting the ASSERTIVE_FAIL_VERBOSE environment variable.

export ASSERTIVE_FAIL_VERBOSE=1

Running the playbook from our earlier examples yields:


PLAY [example 002] **********************************************************************

TASK [Gathering Facts] ******************************************************************
ok: [localhost]

TASK [check that we have lemons] ********************************************************
changed: [localhost] => {
    "ansible_stats": {
        "aggregate": true, 
        "data": {
            "assertions": 1, 
            "assertions_failed": 1, 
            "assertions_passed": 0
        }, 
        "per_host": true
    }, 
    "assertions": [
        {
            "assertion": "'lemons' in fruit", 
            "evaluated_to": false
        }
    ], 
    "changed": true, 
    "failed": false, 
    "msg": "we are missing lemons"
}

TASK [check that we have apples] ********************************************************
ok: [localhost]

PLAY RECAP ******************************************************************************
localhost                  : ok=3    changed=1    unreachable=0    failed=0   

About the assertive callback plugin

The assertive callback plugin operates very much like the default stdout callback plugin, but contains special support for the assert module:

  • It modifies the output of assert tasks to be more readable to provide more detail, and

  • It gathers per-host, per-play, and per-playbook-run assertion statistics, and

  • It can write assertion results to a YAML file.

Example 3

If we have a task similar to that in the first example:

- hosts: localhost
  name: example 003
  vars:
    fruit:
      - apples
      - oranges
  tasks:
    - name: check that we have lemons
      assert:
        that:
          - "'lemons' in fruit"
        msg: we are missing lemons

    - name: check that we have apples
      assert:
        that:
          - "'apples' in fruit"
        msg: we are missing apples

And we activate the assertive callback plugin using the following ansible.cfg:

[defaults]
action_plugins = ../../action_plugins
callback_plugins = ../../callback_plugins

stdout_callback = assertive
show_custom_stats = yes

# we don't need retry files for running examples
retry_files_enabled = no

We see the following output:


PLAY [example 003] **********************************************************************

TASK [Gathering Facts] ******************************************************************
ok: [localhost]

TASK [check that we have lemons] ********************************************************
failed: [localhost]  ASSERT('lemons' in fruit)
failed: we are missing lemons

TASK [check that we have apples] ********************************************************
passed: [localhost]  ASSERT('apples' in fruit)

PLAY RECAP ******************************************************************************
localhost                  : ok=3    changed=1    unreachable=0    failed=0   


CUSTOM STATS: ***************************************************************************
	localhost: { "assertions": 2,  "assertions_failed": 1,  "assertions_passed": 1}

Writing test results to testresult.yml

As you can see, the assertion tasks now show details about both passed and failed assertions. There are custom statistics available that show details about passed, failed, and total assertions.

We can record the results to a file by setting the ANSIBLE_RECORD environment variable, as in:

export ASSERTIVE_RECORD=testresult.yml

The YAML file written out by the assertive plugin looks like this:

groups:
- hosts:
    localhost:
      stats:
        assertions: 2
        assertions_failed: 1
        assertions_passed: 1
        assertions_skipped: 0
      tests:
      - assertions:
        - test: '''lemons'' in fruit'
          testresult: failed
        msg: we are missing lemons
        name: check that we have lemons
        testresult: failed
        testtime: '2017-08-11T13:28:02.895874'
      - assertions:
        - test: '''apples'' in fruit'
          testresult: passed
        msg: All assertions passed
        name: check that we have apples
        testresult: passed
        testtime: '2017-08-11T13:28:02.915915'
  name: example 003
  stats:
    assertions: 2
    assertions_failed: 1
    assertions_passed: 1
    assertions_skipped: 0
stats:
  assertions: 2
  assertions_failed: 1
  assertions_passed: 1
  assertions_skipped: 0
timing:
  test_finished_at: '2017-08-11T13:28:02.917628'
  test_started_at: '2017-08-11T13:28:02.204369'

Build status

Build Status

ansible-assertive's People

Contributors

larsks avatar

Stargazers

 avatar

Watchers

Steve Arnold avatar James Cloos avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.