mirror of
https://github.com/ansible-collections/community.general.git
synced 2024-09-14 20:13:21 +02:00
Add the start of an integration test structure using Ansible playbooks, also added an assert action plugin to make writing those easier.
This commit is contained in:
parent
6c3b4570d7
commit
c91ceddfac
20 changed files with 290 additions and 2 deletions
|
@ -17,7 +17,7 @@ Major features/changes:
|
||||||
* play_hosts is a new magic variable to provide a list of hosts in scope for the current play.
|
* play_hosts is a new magic variable to provide a list of hosts in scope for the current play.
|
||||||
* ec2 module now accepts 'exact_count' and 'count_tag' as a way to enforce a running number of nodes by tags.
|
* ec2 module now accepts 'exact_count' and 'count_tag' as a way to enforce a running number of nodes by tags.
|
||||||
* all ec2 modules that work with Eucalyptus also now support a 'validate_certs' option, which can be set to 'off' for installations using self-signed certs.
|
* all ec2 modules that work with Eucalyptus also now support a 'validate_certs' option, which can be set to 'off' for installations using self-signed certs.
|
||||||
|
* Start of new integration test infrastructure (WIP, more details TBD)
|
||||||
|
|
||||||
New modules:
|
New modules:
|
||||||
|
|
||||||
|
@ -31,7 +31,7 @@ New modules:
|
||||||
* cloud: rax_queue
|
* cloud: rax_queue
|
||||||
* messaging: rabbitmq_policy
|
* messaging: rabbitmq_policy
|
||||||
* system: at
|
* system: at
|
||||||
|
* utilities: assert
|
||||||
|
|
||||||
Misc:
|
Misc:
|
||||||
|
|
||||||
|
|
56
lib/ansible/runner/action_plugins/assert.py
Normal file
56
lib/ansible/runner/action_plugins/assert.py
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
# Copyright 2012, Dag Wieers <dag@wieers.com>
|
||||||
|
#
|
||||||
|
# This file is part of Ansible
|
||||||
|
#
|
||||||
|
# Ansible is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# Ansible is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
import ansible
|
||||||
|
|
||||||
|
from ansible import utils
|
||||||
|
from ansible.runner.return_data import ReturnData
|
||||||
|
|
||||||
|
class ActionModule(object):
|
||||||
|
''' Fail with custom message '''
|
||||||
|
|
||||||
|
TRANSFERS_FILES = False
|
||||||
|
|
||||||
|
def __init__(self, runner):
|
||||||
|
self.runner = runner
|
||||||
|
|
||||||
|
def run(self, conn, tmp, module_name, module_args, inject, complex_args=None, **kwargs):
|
||||||
|
|
||||||
|
# note: the fail module does not need to pay attention to check mode
|
||||||
|
# it always runs.
|
||||||
|
|
||||||
|
args = {}
|
||||||
|
if complex_args:
|
||||||
|
args.update(complex_args)
|
||||||
|
args.update(utils.parse_kv(module_args))
|
||||||
|
|
||||||
|
msg = ''
|
||||||
|
|
||||||
|
if 'msg' in args:
|
||||||
|
msg = args['msg']
|
||||||
|
|
||||||
|
if not 'that' in args:
|
||||||
|
raise errors.AnsibleError('conditional required in "that" string')
|
||||||
|
|
||||||
|
result = utils.check_conditional(args['that'], self.runner.basedir, inject, fail_on_undefined=True)
|
||||||
|
|
||||||
|
if not result:
|
||||||
|
result = dict(failed=True, assertion=args['that'], evaluated_to=result)
|
||||||
|
else:
|
||||||
|
result = dict(msg='ok', assertion=args['that'], evaluated_to=result)
|
||||||
|
|
||||||
|
return ReturnData(conn=conn, result=result)
|
39
library/utilities/assert
Normal file
39
library/utilities/assert
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
#!/usr/bin/python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
# Copyright 2012 Dag Wieers <dag@wieers.com>
|
||||||
|
#
|
||||||
|
# This file is part of Ansible
|
||||||
|
#
|
||||||
|
# Ansible is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# Ansible is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
DOCUMENTATION = '''
|
||||||
|
---
|
||||||
|
module: assert
|
||||||
|
short_description: Fail with custom message
|
||||||
|
description:
|
||||||
|
- This module asserts that a given expression is true and can be a simpler alternative to the 'fail' module in some cases.
|
||||||
|
version_added: "1.5"
|
||||||
|
options:
|
||||||
|
that:
|
||||||
|
description:
|
||||||
|
- "A string expression of the same form that can be passed to the 'when' statement"
|
||||||
|
required: true
|
||||||
|
author: Michael DeHaan
|
||||||
|
'''
|
||||||
|
|
||||||
|
EXAMPLES = '''
|
||||||
|
- assert: ansible_os_family != "RedHat"
|
||||||
|
- assert: "'foo' in some_command_result.stdout"
|
||||||
|
'''
|
7
test/README.md
Normal file
7
test/README.md
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
Legacy tests
|
||||||
|
============
|
||||||
|
|
||||||
|
These tests are active but are being refactored.
|
||||||
|
|
||||||
|
See 'new_tests' directory for what will soon replace them.
|
||||||
|
|
22
tests_new/README.md
Normal file
22
tests_new/README.md
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
Ansible Test System
|
||||||
|
===================
|
||||||
|
|
||||||
|
Folders
|
||||||
|
|
||||||
|
unit
|
||||||
|
----
|
||||||
|
|
||||||
|
New and approved unit tests, that test small pieces of code not suited for the integration test layer
|
||||||
|
|
||||||
|
Not yet ready for pull requests. Opening this up soon.
|
||||||
|
|
||||||
|
integration
|
||||||
|
-----------
|
||||||
|
|
||||||
|
New integration test layer, constructed using playbooks.
|
||||||
|
|
||||||
|
Not yet ready for pull requests. Opening this up soon.
|
||||||
|
|
||||||
|
Some tests may require cloud credentials, others will not, and destructive tests will be seperated from non-destructive so a subset
|
||||||
|
can be run on development machines.
|
||||||
|
|
13
tests_new/integration/README.md
Normal file
13
tests_new/integration/README.md
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
Integration tests
|
||||||
|
=================
|
||||||
|
|
||||||
|
The ansible integration system.
|
||||||
|
|
||||||
|
Tests for playbooks, by playbooks.
|
||||||
|
|
||||||
|
Some tests may require cloud credentials.
|
||||||
|
|
||||||
|
Instructions
|
||||||
|
============
|
||||||
|
|
||||||
|
Pending
|
6
tests_new/integration/all.yml
Normal file
6
tests_new/integration/all.yml
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
- include: test_setup.yml
|
||||||
|
- include: non_destructive.yml
|
||||||
|
- include: destructive.yml
|
||||||
|
- include: rackspace.yml
|
||||||
|
- include: amazon.yml
|
||||||
|
|
4
tests_new/integration/amazon.yml
Normal file
4
tests_new/integration/amazon.yml
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
- hosts: testhost
|
||||||
|
gather_facts: True
|
||||||
|
roles: []
|
||||||
|
|
4
tests_new/integration/destructive.yml
Normal file
4
tests_new/integration/destructive.yml
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
- hosts: testhost
|
||||||
|
gather_facts: True
|
||||||
|
roles: []
|
||||||
|
|
2
tests_new/integration/inventory
Normal file
2
tests_new/integration/inventory
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
[local]
|
||||||
|
testhost ansible_ssh_host=127.0.0.1 ansible_connection=local
|
5
tests_new/integration/non_destructive.yml
Normal file
5
tests_new/integration/non_destructive.yml
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
- hosts: testhost
|
||||||
|
gather_facts: True
|
||||||
|
roles:
|
||||||
|
- { role: test_copy, tags: test_copy }
|
||||||
|
|
4
tests_new/integration/rackspace.yml
Normal file
4
tests_new/integration/rackspace.yml
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
- hosts: testhost
|
||||||
|
gather_facts: True
|
||||||
|
roles: []
|
||||||
|
|
26
tests_new/integration/roles/prepare_tests/tasks/main.yml
Normal file
26
tests_new/integration/roles/prepare_tests/tasks/main.yml
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
# test code for the copy module and action plugin
|
||||||
|
# (c) 2014, Michael DeHaan <michael.dehaan@gmail.com>
|
||||||
|
|
||||||
|
# This file is part of Ansible
|
||||||
|
#
|
||||||
|
# Ansible is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# Ansible is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
|
||||||
|
- name: clean out the test directory
|
||||||
|
file: name={{output_dir|mandatory}} state=absent
|
||||||
|
|
||||||
|
- name: create the test directory
|
||||||
|
file: name={{output_dir}} state=directory
|
||||||
|
|
||||||
|
|
1
tests_new/integration/roles/test_copy/files/foo.txt
Normal file
1
tests_new/integration/roles/test_copy/files/foo.txt
Normal file
|
@ -0,0 +1 @@
|
||||||
|
foo.txt
|
1
tests_new/integration/roles/test_copy/foo.txt
Normal file
1
tests_new/integration/roles/test_copy/foo.txt
Normal file
|
@ -0,0 +1 @@
|
||||||
|
foo.txt
|
3
tests_new/integration/roles/test_copy/meta/main.yml
Normal file
3
tests_new/integration/roles/test_copy/meta/main.yml
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
dependencies:
|
||||||
|
- prepare_tests
|
||||||
|
|
84
tests_new/integration/roles/test_copy/tasks/main.yml
Normal file
84
tests_new/integration/roles/test_copy/tasks/main.yml
Normal file
|
@ -0,0 +1,84 @@
|
||||||
|
# test code for the copy module and action plugin
|
||||||
|
# (c) 2014, Michael DeHaan <michael.dehaan@gmail.com>
|
||||||
|
|
||||||
|
# This file is part of Ansible
|
||||||
|
#
|
||||||
|
# Ansible is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# Ansible is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
# FIXME: replace all fail_when's with asserts
|
||||||
|
|
||||||
|
- set_fact: output_file={{output_dir}}/foo.txt
|
||||||
|
|
||||||
|
- name: initiate a basic copy
|
||||||
|
copy: src=foo.txt dest={{output_file}}
|
||||||
|
register: copy_result
|
||||||
|
|
||||||
|
- assert: { that: "'changed' in copy_result" }
|
||||||
|
- assert: { that: "'dest' in copy_result" }
|
||||||
|
- assert: { that: "'group' in copy_result" }
|
||||||
|
- assert: { that: "'gid' in copy_result" }
|
||||||
|
- assert: { that: "'md5sum' in copy_result" }
|
||||||
|
- assert: { that: "'owner' in copy_result" }
|
||||||
|
- assert: { that: "'size' in copy_result" }
|
||||||
|
- assert: { that: "'src' in copy_result" }
|
||||||
|
- assert: { that: "'state' in copy_result" }
|
||||||
|
- assert: { that: "'uid' in copy_result" }
|
||||||
|
|
||||||
|
|
||||||
|
- name: verify that the file was marked as changed
|
||||||
|
assert: { that: "copy_result.changed == true" }
|
||||||
|
|
||||||
|
- name: verify that the file md5sum is correct
|
||||||
|
assert: { that: "copy_result.md5sum == 'c47397529fe81ab62ba3f85e9f4c71f2'" }
|
||||||
|
|
||||||
|
- name: check the stat results of the file
|
||||||
|
stat: path={{output_file}}
|
||||||
|
register: stat_results
|
||||||
|
|
||||||
|
- debug: var=stat_results
|
||||||
|
|
||||||
|
- assert: { that: "stat_results.stat.exists == true" }
|
||||||
|
- assert: { that: "stat_results.stat.isblk == false" }
|
||||||
|
- assert: { that: "stat_results.stat.isfifo == false" }
|
||||||
|
- assert: { that: "stat_results.stat.isreg == true" }
|
||||||
|
- assert: { that: "stat_results.stat.issock == false" }
|
||||||
|
- assert: { that: "stat_results.stat.md5 == 'c47397529fe81ab62ba3f85e9f4c71f2'" }
|
||||||
|
|
||||||
|
- name: overwrite the file via same means
|
||||||
|
copy: src=foo.txt dest={{output_file}}
|
||||||
|
register: copy_result2
|
||||||
|
|
||||||
|
- name: verify the copy was marked unchanged
|
||||||
|
assert: { that: "not copy_result2|changed" }
|
||||||
|
|
||||||
|
- name: overwrite the file using the content system
|
||||||
|
copy: content="modified" dest={{output_file}}
|
||||||
|
register: copy_result3
|
||||||
|
|
||||||
|
- name: verify the copy result was marked changed
|
||||||
|
assert: { that: "copy_result3|changed" }
|
||||||
|
|
||||||
|
- name: overwrite the file again using the content system
|
||||||
|
copy: content="modified" dest={{output_file}}
|
||||||
|
register: copy_result4
|
||||||
|
|
||||||
|
- name: verify the copy result was marked unchanged
|
||||||
|
assert: { that: "not copy_result4|changed" }
|
||||||
|
|
||||||
|
# TODO: test recursive copy
|
||||||
|
# TODO: test copy where destination is a directory like {{output_dir}}/
|
||||||
|
# TODO: test that copy fails if the path does not exist
|
||||||
|
# TODO: ...
|
||||||
|
|
||||||
|
|
1
tests_new/integration/test.sh
Normal file
1
tests_new/integration/test.sh
Normal file
|
@ -0,0 +1 @@
|
||||||
|
ansible-playbook non_destructive.yml -i inventory -e output_dir=~/ansible_testing -v
|
5
tests_new/integration/test_setup.yml
Normal file
5
tests_new/integration/test_setup.yml
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
- hosts: testhost
|
||||||
|
gather_facts: False
|
||||||
|
roles:
|
||||||
|
- test_setup
|
||||||
|
|
5
tests_new/units/README.md
Normal file
5
tests_new/units/README.md
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
Unit tests
|
||||||
|
==========
|
||||||
|
|
||||||
|
Tests at code level. Should be concise and to the point, and organized by subject.
|
||||||
|
|
Loading…
Reference in a new issue