Skip to content

Commit 2928f02

Browse files
cleanup and comments
1 parent 144f178 commit 2928f02

File tree

8 files changed

+188
-81
lines changed

8 files changed

+188
-81
lines changed

.travis.yml

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,20 @@
11
---
2-
language: python
2+
# Define the language and version used. The CI system will create
3+
# a Python virtualenv for this particular version for the test.
4+
language: "python"
35
python:
46
- "2.7"
57

6-
# Install python packages for ansible and linters.
8+
# Install python packages for ansible and linters first.
79
install:
810
- "pip install -r requirements.txt"
911

10-
# Execute linting and unit tests before running the main playbook.
12+
# Execute linting to catch minor errors before running the main playbook.
13+
# If you have a directory hierarchy, use this style instead:
14+
# "find . -name '*.yml' | xargs yamllint -s"
1115
before_script:
12-
- "find . -name '*.yml' | xargs yamllint -s"
13-
- "export ANSIBLE_HOST_KEY_CHECKING=False"
16+
- "yamllint -s *.yml"
1417

15-
# Perform playbook testing with mock CI inputs.
18+
# Perform playbook testing with on a pre-existing virtual router.
1619
script:
17-
- "ansible-playbook test_playbook.yml -i hosts.yml"
20+
- "ansible-playbook test.yml"

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,5 @@
22
https://travis-ci.org/nickrusso42518/slt-netdevops.svg?branch=master)](
33
https://travis-ci.org/nickrusso42518/slt-netdevops)
44

5-
# Safari Live Training - Foundations of Network DevOps
5+
# Safari Live Training - Network DevOps
66
Actively in development ... check back soon!

ansible.cfg

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# This configuration file identifies general settings
2+
# for the Ansible environment.
3+
[defaults]
4+
5+
# Where to find the list of hosts
6+
inventory = hosts.yml
7+
8+
# Disable general-purpose information collection on control machine
9+
gathering = explicit
10+
11+
# Disable SSH "known_host" key checking; helps with CI
12+
host_key_checking = False
13+
14+
# Use the "network_cli" transport for default; helps for network devices
15+
transport = network_cli

hosts.yml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,23 @@
11
---
2+
# The "all" group is at the top of the hierarchy and encompasses
3+
# all other hosts and subgroups. This particular inventory is
4+
# simplified and contains no subgroups.
25
all:
36
hosts:
7+
# The list of hosts contained in the "all" group. These
8+
# can be real DNS hostnames, local host mappings, or IP
9+
# addresses.
410
csr1.njrusmc.net:
511
# csr2.njrusmc.net:
612
vars:
13+
# These are group-level variables associated with the "all"
14+
# group. Ansible gives many options with respect to variable
15+
# playment, but for a simple example playbook, embedding them in
16+
# the inventory file is acceptable. The "ansible_*" variables
17+
# serve as input for the "network_cli" transport method
18+
# which allow Ansible to connect to our routers. The "ntp_*"
19+
# variables are user-defined and represent that NTP servers we
20+
# are configuring in our main playbook.
721
ansible_network_os: "ios"
822
ansible_user: "ansible"
923
ansible_ssh_pass: "ansible"

ntp_config.yml

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
---
2+
# This is a play, which is an element in the playbook.
3+
# A playbook is a list of plays, and each play runs on
4+
# a subset of hosts in the inventory. This specific play
5+
# runs on all inventory devices. If there was a diverse set
6+
# of hosts, such as routers, firewalls, and wireless LAN
7+
# controllers, each one may have different NTP configuration
8+
# syntax and could use different plays.
9+
- name: "PLAY 1: Manage NTP configuration"
10+
hosts: "all"
11+
tasks:
12+
13+
# This is the first task, and each play generally contains
14+
# a list of tasks. The task is a set of actions to execute
15+
# against each host specified within the play. This task
16+
# checks the data input quality, ensuring that the two
17+
# NTP servers are defined and are valid IPv4 addresses.
18+
# This task uses the "assert" module as a way of integrating
19+
# testing within a playbook.
20+
- name: "TASK 1: Validate NTP server IP addresses"
21+
assert:
22+
that:
23+
- "ntp_server1 is defined"
24+
- "ntp_server2 is defined"
25+
- "ntp_server1 | ipv4 == ntp_server1"
26+
- "ntp_server2 | ipv4 == ntp_server2"
27+
msg: "Malformed input; please check ntp_server values"
28+
29+
# This is the second task. It logs into the Cisco IOS or
30+
# IOS-XE device using the "ios_config" module. The commands
31+
# specified within that module are passed to the router, and
32+
# the NTP server values are substituted using {{ }} syntax.
33+
# The previous task verified that these servers were valid,
34+
# so the router CLI should not report any errors.
35+
# The "register" directive tells Ansible to "save" the
36+
# feedback from the module, which provides us a list of which
37+
# commands needed to be added (between 0 and 4 in this case),
38+
# whether there were any failures, and more.
39+
- name: "TASK 2: Apply NTP updates"
40+
ios_config:
41+
commands:
42+
- "ntp authenticate"
43+
- "ntp logging"
44+
- "ntp server {{ ntp_server1 }}"
45+
- "ntp server {{ ntp_server2 }}"
46+
register: "ntp_updates"
47+
48+
# This is the third task. If any new changes were configured
49+
# on the router (for example, "ntp logging" had been accidentally
50+
# disabled before running the playbook), those delta commands
51+
# are printed to stdout so the user sees them. This only occurs
52+
# if there are changes due to the "when" directive. If the "when"
53+
# evaluates to false, the task is skipped. The task will only
54+
# be false when the registered variable from the previous task
55+
# does not define the "updates" subfield, which indicates no
56+
# changes were needed.
57+
- name: "TASK 3: Print changes if NTP config changed"
58+
debug:
59+
var: "ntp_updates.updates"
60+
when: "ntp_updates.updates is defined"
61+
...

ntp_playbook.yml

Lines changed: 0 additions & 29 deletions
This file was deleted.

test.yml

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
---
2+
# This is the first play, but rather than define a new play
3+
# and corresponding set of tasks, we import the main NTP
4+
# playbook and pass in some custom NTP servers instead. Using
5+
# static inputs is a good way to "stub out" our variables file
6+
# for the purpose of testing the playbook's logic.
7+
- name: "PLAY 1: Import original playbook with mock NTP servers"
8+
import_playbook: "ntp_config.yml"
9+
vars:
10+
ntp_server1: "203.0.113.1"
11+
ntp_server2: "203.0.113.2"
12+
13+
# This is the second play. Its purpose is to ensure the
14+
# first play (playbook import) worked correctly. The general
15+
# flow is to ensure the NTP configuration was correctly applied,
16+
# remove the NTP configuration, then ensure the NTP configuration
17+
# was correctly removed. Removal isn't critical, but without it
18+
- name: "PLAY 2: Log into routers to test playbook"
19+
hosts: "all"
20+
tasks:
21+
22+
# This is the first task. It collects information from the
23+
# router using the "ios_command" module, which is used for
24+
# non-configuration (exec shell) commands. The command issued
25+
# returns a table showing each NTP server configured.
26+
# The output from this command is registered in the
27+
# variable called "ntp_associations".
28+
- name: "TASK 1: Gather mock NTP state data after enabling NTP"
29+
ios_command:
30+
commands: "show ntp associations"
31+
register: "ntp_associations"
32+
33+
# This is the second task. Now that we've registered the router's
34+
# feedback, we can test it using basic string membership/containment
35+
# operations. We must ensure that our two mock NTP servers are
36+
# present in this output. The text output is contained in a subfield
37+
# called "stdout", and the 0 index is used to represent that this is
38+
# the output associated with the first (and only) command issued.
39+
- name: "TASK 2: Check that mock NTP servers are present"
40+
assert:
41+
that:
42+
- "'203.0.113.1' in ntp_associations.stdout[0]"
43+
- "'203.0.113.2' in ntp_associations.stdout[0]"
44+
msg: "Missing some NTP data:\n{{ ntp_associations.stdout[0] }}"
45+
46+
# This is the third task. At this point, we've verified that the
47+
# original NTP playbook works, but we should clean up after ourselves.
48+
# Note that if we wanted to create a more robust and complex CI system,
49+
# these steps would be unnecessary, since the disposal nature of
50+
# virtual routers would indicate that simply deleting the router
51+
# and spinning up a new one for a future CI test would be fine. In our
52+
# case, the virtual router is longer living, and we want to prepare it
53+
# for future tests by removing the mock servers.
54+
- name: "TASK 3: Remove mock NTP servers"
55+
ios_config:
56+
commands:
57+
- "no ntp server 203.0.113.1"
58+
- "no ntp server 203.0.113.2"
59+
60+
# This is the fourth task and inserts a short pause using the
61+
# "pause" module. This allows the router to fully disable its
62+
# NTP logic for the two recently removed servers. Waiting helps
63+
# avoid a false negative in future tasks by ensuring the router
64+
# does not incorrectly report that these NTP servers still exist.
65+
- name: "TASK 4: Wait 1 seconds"
66+
pause:
67+
seconds: 1
68+
69+
# This is the fifth task and is a copy of the second task. We
70+
# need to update our ntp_associations variable and test to
71+
# ensure NTP was removed in a future task.
72+
- name: "TASK 5: Gather mock NTP data after disabling NTP"
73+
ios_command:
74+
commands: "show ntp associations"
75+
register: "ntp_associations"
76+
77+
# This is the sixth task and checks the registered output from the
78+
# previous task to ensure the mock NTP servers were not seen
79+
# in the NTP association state data. If they were, then something
80+
# went wrong with the NTP configuration removal in task 4.
81+
- name: "TASK 6: Check mock NTP data is absent"
82+
assert:
83+
that:
84+
- "'203.0.113.1' not in ntp_associations.stdout[0]"
85+
- "'203.0.113.2' not in ntp_associations.stdout[0]"
86+
msg: "Saw some NTP data:\n{{ ntp_associations.stdout[0] }}"
87+
...

test_playbook.yml

Lines changed: 0 additions & 44 deletions
This file was deleted.

0 commit comments

Comments
 (0)