Adding Netbox

This commit is contained in:
Patrick Toal
2019-05-06 00:34:45 -04:00
parent 832502de34
commit 6e2205a046
278 changed files with 12767 additions and 0 deletions

View File

@@ -0,0 +1,48 @@
# (c) 2012, Michael DeHaan <michael.dehaan@gmail.com>
# (c) 2012-17 Ansible Project
# 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: config_template
author: Peter Sprygada (privateip)
version_added: "2.7"
short_description: retrieve contents of file after templating with Jinja2
description:
- This lookup plugin implements the standard template plugin with a slight
twist in that it supports using default(omit) to remove an entire line
options:
_terms:
description: list of files to template
"""
EXAMPLES = """
- name: show templating results
debug: msg="{{ lookup('config_template', './some_template.j2') }}
"""
RETURN = """
_raw:
description: file(s) content after templating
"""
from ansible.plugins.lookup.template import LookupModule as LookupBase
class LookupModule(LookupBase):
def run(self, terms, variables, **kwargs):
ret = super(LookupModule, self).run(terms, variables, **kwargs)
omit = variables['omit']
filtered = list()
for line in ret[0].split('\n'):
if all((line, omit not in line, not line.startswith('!'))):
filtered.append(line)
return [filtered]

View File

@@ -0,0 +1,68 @@
# (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: json_template
author: Ansible Network
version_added: "2.5"
short_description: retrieve and template device configuration
description:
- This plugin lookups the content(key-value pair) of a JSON file
and returns network configuration in JSON format.
options:
_terms:
description: File for lookup
"""
EXAMPLES = """
- name: show interface lookup result
debug: msg="{{ lookup('json_template', './show_interface.json') }}
"""
RETURN = """
_raw:
description: JSON file content
"""
import json
import os
import sys
from ansible.errors import AnsibleError, AnsibleParserError
from ansible.plugins.lookup import LookupBase, display
from ansible.module_utils._text import to_bytes
sys.path.insert(0, os.path.join(os.path.dirname(__file__), os.path.pardir, 'lib'))
from network_engine.plugins import template_loader
class LookupModule(LookupBase):
def run(self, terms, variables, **kwargs):
ret = list()
self.ds = variables.copy()
self.template = template_loader.get('json_template', self._templar)
display.debug("File lookup term: %s" % terms[0])
lookupfile = self.find_file_in_search_path(variables, 'files', terms[0])
display.vvvv("File lookup using %s as file" % lookupfile)
try:
if lookupfile:
with open(to_bytes(lookupfile, errors='surrogate_or_strict'), 'rb') as f:
json_data = list()
json_data.append(json.load(f))
ret.append(self.template.run(json_data, self.ds))
else:
raise AnsibleParserError()
except AnsibleParserError:
raise AnsibleError("could not locate file in lookup: %s" % terms[0])
return ret

View File

@@ -0,0 +1,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

View File

@@ -0,0 +1,257 @@
# -*- coding: utf-8 -*-
# (c) 2018, Ansible by 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
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
#
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
DOCUMENTATION = """
lookup: network_template
author: Ansible Network
version_added: "2.5"
short_description: template device configuration
description:
- This plugin will lookup the file and template it into a network
configuration.
deprecated:
removed_in: "2.7.7"
options:
_terms:
description: list of files to template
"""
EXAMPLES = """
- name: show config template results
debug: msg="{{ lookup('network_template', './config_template.j2') }}
"""
RETURN = """
_raw:
description: file(s) content after templating
"""
import collections
from ansible.plugins.lookup import LookupBase, display
from ansible.module_utils.common._collections_compat import Mapping
from ansible.module_utils.network.common.utils import to_list
from ansible.module_utils.six import iteritems, string_types
from ansible.module_utils._text import to_text, to_bytes
from ansible.errors import AnsibleError, AnsibleUndefinedVariable
class LookupModule(LookupBase):
def run(self, terms, variables, **kwargs):
self.ds = variables.copy()
config_lines = list()
for term in to_list(terms[0]):
display.debug("File lookup term: %s" % term)
lookupfile = self.find_file_in_search_path(variables, 'templates', term)
display.vvvv("File lookup using %s as file" % lookupfile)
if lookupfile:
with open(to_bytes(lookupfile, errors='surrogate_or_strict'), 'rb'):
tasks = self._loader.load_from_file(lookupfile)
for task in tasks:
task.pop('name', None)
register = task.pop('register', None)
when = task.pop('when', None)
if when is not None:
if not self._check_conditional(when, self.ds):
display.vvv('skipping task due to conditional check failure')
continue
loop = task.pop('loop', None)
if loop:
loop = self.template(loop, self.ds)
loop_result = list()
if isinstance(loop, Mapping):
for loop_key, loop_value in iteritems(loop):
self.ds['item'] = {'key': loop_key, 'value': loop_value}
res = self._process_directive(task)
if res:
loop_result.extend(to_list(res))
elif isinstance(loop, collections.Iterable) and not isinstance(loop, string_types):
for loop_item in loop:
self.ds['item'] = loop_item
res = self._process_directive(task)
if res:
loop_result.extend(to_list(res))
config_lines.extend(loop_result)
if register:
self.ds[register] = loop_result
else:
res = self._process_directive(task)
if res:
config_lines.extend(to_list(res))
if register:
self.ds[register] = res
else:
raise AnsibleError("the template file %s could not be found for the lookup" % term)
return [to_text('\n'.join(config_lines)).strip()]
def do_context(self, block):
results = list()
for entry in block:
task = entry.copy()
task.pop('name', None)
task.pop('register', None)
when = task.pop('when', None)
if when is not None:
if not self._check_conditional(when, self.ds):
display.vvv('skipping context due to conditional check failure')
continue
loop = task.pop('loop', None)
if loop:
loop = self.template(loop, self.ds)
if 'context' in task:
res = self.do_context(task['context'])
if res:
results.extend(res)
elif isinstance(loop, Mapping):
loop_result = list()
for loop_key, loop_value in iteritems(loop):
self.ds['item'] = {'key': loop_key, 'value': loop_value}
loop_result.extend(to_list(self._process_directive(task)))
results.extend(loop_result)
elif isinstance(loop, collections.Iterable) and not isinstance(loop, string_types):
loop_result = list()
for loop_item in loop:
self.ds['item'] = loop_item
loop_result.extend(to_list(self._process_directive(task)))
results.extend(loop_result)
else:
res = self._process_directive(task)
if res:
results.extend(to_list(res))
return results
def _process_directive(self, task):
for directive, args in iteritems(task):
if directive == 'context':
meth = getattr(self, 'do_%s' % directive)
if meth:
return meth(args)
else:
meth = getattr(self, 'do_%s' % directive)
if meth:
return meth(**args)
def do_lines_template(self, template, join=False, when=None, required=False):
templated_lines = list()
_processed = list()
if when is not None:
if not self._check_conditional(when, self.ds):
display.vvv("skipping due to conditional failure")
return templated_lines
for line in to_list(template):
res = self.template(line, self.ds)
if res:
_processed.append(res)
elif not res and join:
break
if required and not _processed:
raise AnsibleError('unabled to templated required line')
elif _processed and join:
templated_lines.append(' '.join(_processed))
elif _processed:
templated_lines.extend(_processed)
return templated_lines
def _process_include(self, item, variables):
name = item.get('name')
include = item['include']
src = self.template(include, variables)
source = self._find_needle('templates', src)
when = item.get('when')
if when:
conditional = "{%% if %s %%}True{%% else %%}False{%% endif %%}"
if not self.template(conditional % when, variables, fail_on_undefined=False):
display.vvvvv("include '%s' skipped due to conditional check failure" % name)
return []
display.display('including file %s' % source)
include_data = self._loader.load_from_file(source)
template_data = item.copy()
# replace include directive with block directive and contents of
# included file. this will preserve other values such as loop,
# loop_control, etc
template_data.pop('include')
template_data['block'] = include_data
return self.build([template_data], variables)
def template(self, data, variables, convert_bare=False):
if isinstance(data, Mapping):
templated_data = {}
for key, value in iteritems(data):
templated_key = self.template(key, variables, convert_bare=convert_bare)
templated_data[templated_key] = self.template(value, variables, convert_bare=convert_bare)
return templated_data
elif isinstance(data, collections.Iterable) and not isinstance(data, string_types):
return [self.template(i, variables, convert_bare=convert_bare) for i in data]
else:
data = data or {}
tmp_avail_vars = self._templar._available_variables
self._templar.set_available_variables(variables)
try:
resp = self._templar.template(data, convert_bare=convert_bare)
resp = self._coerce_to_native(resp)
except AnsibleUndefinedVariable:
resp = None
finally:
self._templar.set_available_variables(tmp_avail_vars)
return resp
def _coerce_to_native(self, value):
if not isinstance(value, bool):
try:
value = int(value)
except Exception:
if value is None or len(value) == 0:
return None
return value
def _check_conditional(self, when, variables):
conditional = "{%% if %s %%}True{%% else %%}False{%% endif %%}"
return self.template(conditional % when, variables)