-
Notifications
You must be signed in to change notification settings - Fork 53
/
Copy pathnetcfg_diff.py
119 lines (99 loc) · 4.23 KB
/
netcfg_diff.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
# (c) 2018 Red Hat, Inc.
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
#
# You should have received a copy of the GNU General Public License
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
DOCUMENTATION = """
lookup: netcfg_diff
author: Ansible Network
version_added: "2.5"
short_description: Generates a text configuration difference between two configuration
mainly used with network devices.
description:
- This plugin lookups will generate a difference between two text configuration that
is supported by Network OS. This difference can be used to identify the
exact change that is required to be pushed to remote host.
options:
_terms:
description:
- Specifies the wanted text configuration. Theis is usually
the text configuration that is expected to be present on remote host.
required: True
have:
description:
- Specifies the text configuration. The C(have) is usually
the text configuration that is active on remote host.
required: True
match:
description:
- Instructs the module on the way to perform the matching of
the set of text commands between C(want) and C(have).
If match is set to I(line), commands are matched line by line. If
match is set to I(strict), command lines are matched with respect
to position. If match is set to I(exact), command lines
must be an equal match.
default: line
choices: ['line', 'strict', 'exact']
replace:
description:
- Instructs the module on the way to perform the configuration
diff. If the replace argument is set to I(line) then
the modified lines are pushed in the generated diff. If the replace argument
is set to I(block) then the entire command block is pushed in the generated
diff if any line is not correct.
default: line
choices: ['line', 'block']
indent:
description:
- Specifies the indentation used for the block in text configuration. The value of C(indent)
is specific on network platform to which the text configuration in C(want) and C(have)
conforms to.
default: 1
type: int
ignore_lines:
description:
- This specifies the lines to be ignored while generating diff. The value of C(ignore_lines) can
also be a python regex.
"""
EXAMPLES = """
- name: generate diff between two text configuration
debug: msg="{{ lookup('netcfg_diff', want, have=have) }}
"""
RETURN = """
_raw:
description: The text difference between values of want and have with want as base reference
"""
from ansible.plugins.lookup import LookupBase
from ansible.module_utils.network.common.config import NetworkConfig, dumps
from ansible.errors import AnsibleError
MATCH_CHOICES = ('line', 'strict', 'exact')
REPLACE_CHOICES = ('line', 'block')
class LookupModule(LookupBase):
def run(self, terms, variables, **kwargs):
ret = []
try:
want = terms[0]
except IndexError:
raise AnsibleError("value of 'want' must be specified")
try:
have = kwargs['have']
except KeyError:
raise AnsibleError("value of 'have' must be specified")
match = kwargs.get('match', 'line')
if match not in MATCH_CHOICES:
choices_str = ", ".join(MATCH_CHOICES)
raise AnsibleError("value of match must be one of: %s, got: %s" % (choices_str, match))
replace = kwargs.get('replace', 'line')
if replace not in REPLACE_CHOICES:
choices_str = ", ".join(REPLACE_CHOICES)
raise AnsibleError("value of replace must be one of: %s, got: %s" % (choices_str, replace))
indent = int(kwargs.get('indent', 1))
ignore_lines = kwargs.get('ignore_lines')
running_obj = NetworkConfig(indent=indent, contents=have, ignore_lines=ignore_lines)
candidate_obj = NetworkConfig(indent=indent, contents=want, ignore_lines=ignore_lines)
configobjs = candidate_obj.difference(running_obj, match=match, replace=replace)
diff = dumps(configobjs, output='commands')
ret.append(diff)
return ret