Skip to content

Commit 415932f

Browse files
committed
Inventory: Start setting up integration tests (netbox-community#56)
1 parent 10daa7f commit 415932f

9 files changed

+1258
-17
lines changed

.travis.yml

Lines changed: 50 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -27,15 +27,16 @@ jobs:
2727
- docker-compose pull
2828
- docker-compose up -d
2929
- cd ..
30-
- pip install -U pip
30+
# setuptools <46.1.3 has issues with ansible-test executables https://github.com/ansible/ansible/issues/68963
31+
- pip install -U pip "setuptools>=46.1.3"
3132
# coverage 5.0 is not compatible with ansible-test https://github.com/ansible/ansible/issues/65907
3233
- pip install pytest==4.6.5 pytest-mock pytest-xdist jinja2 PyYAML black==19.10b0 "coverage<5"
33-
- pip install pynetbox cryptography codecov jmespath ansible
34+
- pip install pynetbox cryptography codecov jmespath jsondiff pycodestyle ansible
3435

35-
# Latest release of Netbox and Ansible
3636
- name: "Python 3.6 - Netbox 2.7 - Latest PyPi Ansible"
3737
python: 3.6
38-
env: PYTHON_VER=3.6 VERSION=v2.7
38+
env:
39+
- PYTHON_VER=3.6 VERSION=v2.7
3940
install:
4041
- cd ..
4142
# Setup netbox container for integration testing
@@ -44,16 +45,32 @@ jobs:
4445
- docker-compose pull
4546
- docker-compose up -d
4647
- cd ..
47-
- pip install -U pip
48+
- pip install -U pip "setuptools>=46.1.3"
4849
- pip install pytest==4.6.5 pytest-mock pytest-xdist jinja2 PyYAML black==19.10b0 "coverage<5"
49-
- pip install pynetbox cryptography codecov jmespath ansible
50+
- pip install pynetbox cryptography codecov jmespath jsondiff pycodestyle ansible
51+
52+
- name: "Python 3.8 - Netbox 2.8 - Latest PyPi Ansible"
53+
python: 3.8
54+
env:
55+
- PYTHON_VER=3.8 VERSION=v2.8
56+
install:
57+
- cd ..
58+
# Setup netbox container for integration testing
59+
- git clone https://github.com/netbox-community/netbox-docker.git
60+
- cd netbox-docker
61+
- docker-compose pull
62+
- docker-compose up -d
63+
- cd ..
64+
- pip install -U pip "setuptools>=46.1.3"
65+
- pip install pytest==4.6.5 pytest-mock pytest-xdist jinja2 PyYAML black==19.10b0 "coverage<5"
66+
- pip install pynetbox cryptography codecov jmespath jsondiff pycodestyle ansible
5067

5168
# Latest development versions of Netbox and Ansible, newest Python
5269
# This may be broken sometimes by changes in the netbox & ansible projects
5370
# Failures will be allowed in this build
54-
- name: "Python 3.8 - Netbox develop-2.8 - Ansible Devel"
71+
- name: "Python 3.8 - Netbox develop branch (snapshot) - Ansible Devel"
5572
python: 3.8
56-
env: PYTHON_VER=3.8 VERSION=develop-2.8
73+
env: PYTHON_VER=3.8 VERSION=snapshot
5774
install:
5875
- cd ..
5976
# Setup netbox container for integration testing
@@ -62,16 +79,16 @@ jobs:
6279
- docker-compose pull
6380
- docker-compose up -d
6481
- cd ..
65-
- pip install -U pip
82+
- pip install -U pip "setuptools>=46.1.3"
6683
- pip install pytest==4.6.5 pytest-mock pytest-xdist jinja2 PyYAML black==19.10b0 "coverage<5"
67-
- pip install pynetbox cryptography jmespath
84+
- pip install pynetbox cryptography jmespath jsondiff pycodestyle
6885
- git clone https://github.com/ansible/ansible.git
6986
- cd ansible
7087
- source hacking/env-setup
7188
- cd ..
7289
allow_failures:
7390
# When testing against dev netbox and dev ansible, allow failures
74-
- env: PYTHON_VER=3.8 VERSION=develop-2.8
91+
- env: PYTHON_VER=3.8 VERSION=snapshot
7592

7693
before_script:
7794
- mkdir -p ~/ansible_collections/$COLLECTION_NAMESPACE
@@ -80,28 +97,44 @@ before_script:
8097
- ansible-galaxy collection build .
8198
- ansible-galaxy collection install $COLLECTION_NAMESPACE-$COLLECTION_NAME-$COLLECTION_VERSION.tar.gz -p /home/travis/.ansible/collections
8299

100+
# Run all further tests from within the installed directory
101+
# Required to resolve imports of other collections
102+
- cd /home/travis/.ansible/collections/ansible_collections/$COLLECTION_NAMESPACE/$COLLECTION_NAME
103+
104+
# Set runme.sh execute permissions stripped by ansible-galaxy. Should be fixed in Ansible 2.10
105+
# https://github.com/ansible/ansible/issues/68415
106+
- chmod +x tests/integration/targets/inventory/runme.sh
107+
- chmod +x tests/integration/targets/inventory/compare_inventory_json.py
108+
83109
script:
84-
# Perform unit tests on collection from within the installed directory, not the source directory
85-
# Required for imports of other collections (ie. ansible.netcommon) to work correctly
86-
- (cd /home/travis/.ansible/collections/ansible_collections/$COLLECTION_NAMESPACE/$COLLECTION_NAME && ansible-test units --coverage --python $PYTHON_VER -v)
87110

88111
# Check python syntax
89112
- black . --check --diff
90113

114+
# Sanity tests
115+
- ansible-test sanity -v --python $PYTHON_VER
116+
117+
# Unit tests, with code coverage
118+
- ansible-test units -vvvv --coverage --python $PYTHON_VER
119+
91120
# Wait for Netbox containers to be running
92121
- timeout 300 bash -c 'while [[ "$(curl -s -o /dev/null -w ''%{http_code}'' localhost:32768)" != "200" ]]; do echo "waiting for Netbox"; sleep 5; done' || false
93122

94123
# Prepare data in Netbox
95124
- python tests/integration/netbox-deploy.py
96125

97126
# Run regression and integration tests
127+
128+
# Run the inventory test first, in case any of the other tests modify the data.
129+
# -vvvv is too much for integration tests
130+
# Only run on Netbox > 2.6 - test data is different with API 2.6, haven't yet worked out a difference
131+
- if [ "$VERSION" != "v2.6" ] ; then ansible-test integration -vv --coverage --python $PYTHON_VER inventory; fi
132+
98133
- ansible-playbook tests/integration/regression-tests.yml -vvvv
99134
- ansible-playbook tests/integration/$VERSION/main.yml -vvvv
100-
- ansible-inventory -vvvv -i tests/integration/test-inventory.yml --list
101-
- ansible-inventory -vvvv -i tests/integration/test-inventory-plurals.yml --list
102135

103136
# Report code coverage
104-
- (cd /home/travis/.ansible/collections/ansible_collections/$COLLECTION_NAMESPACE/$COLLECTION_NAME && ansible-test coverage report)
137+
- ansible-test coverage report
105138

106139
deploy:
107140
provider: script

tests/integration/integration.cfg

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
[defaults]
2+
force_valid_group_names = always
3+
4+
[inventory]
5+
enable_plugins = netbox.netbox.nb_inventory, auto, host_list, yaml, ini, toml, script
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
# https://docs.ansible.com/ansible/devel/dev_guide/testing/sanity/integration-aliases.html
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
#!/usr/bin/env python
2+
3+
# Inspired by community.aws collection script_inventory_ec2 test
4+
# https://github.com/ansible-collections/community.aws/blob/master/tests/integration/targets/script_inventory_ec2/inventory_diff.py
5+
6+
import sys
7+
import json
8+
from jsondiff import diff
9+
from typing import Iterable
10+
11+
# Netbox includes created and last_updated times on objects.
12+
# These end up in the interfaces objects that are included verbatim from the Netbox API.
13+
# Ignore these when performing diffs as they will be different for each test run
14+
ignored_keys = set(["created", "last_updated"])
15+
16+
17+
# Assume the object will not be recursive, as it originally came from JSON
18+
def remove_ignored_keys(obj):
19+
20+
if isinstance(obj, dict):
21+
keys_to_remove = ignored_keys.intersection(obj.keys())
22+
for key in keys_to_remove:
23+
del obj[key]
24+
25+
for (key, value) in obj.items():
26+
remove_ignored_keys(value)
27+
28+
elif isinstance(obj, list):
29+
for item in obj:
30+
remove_ignored_keys(item)
31+
32+
33+
def main():
34+
if len(sys.argv) != 3:
35+
print(
36+
"Error: Must have exactly 2 file to compare passed as arguments. Received %i."
37+
% (len(sys.argv) - 1),
38+
file=sys.stderr,
39+
)
40+
sys.exit(2)
41+
42+
a = sys.argv[1]
43+
b = sys.argv[2]
44+
45+
with open(a, "r") as f:
46+
adata = json.loads(f.read())
47+
with open(b, "r") as f:
48+
bdata = json.loads(f.read())
49+
50+
# Remove keys that we don't want to diff
51+
# ie. times that will change on each run of tests
52+
remove_ignored_keys(adata)
53+
remove_ignored_keys(bdata)
54+
55+
# Perform the diff
56+
# syntax='symmetric' will produce output that prints both the before and after as "$insert" and "$delete"
57+
# marshal=True removes any special types, allowing to be dumped as json
58+
result = diff(adata, bdata, marshal=True, syntax="symmetric")
59+
60+
if result:
61+
# Dictionary is not empty - print differences
62+
print(json.dumps(result, sort_keys=True, indent=4))
63+
sys.exit(1)
64+
else:
65+
# Success, no differences
66+
sys.exit(0)
67+
68+
69+
if __name__ == "__main__":
70+
main()

0 commit comments

Comments
 (0)