Lint cleanup

This commit is contained in:
Mircea Ulinic 2016-11-23 15:20:32 +00:00
parent 56a8fa3f77
commit 215b8f38e2
No known key found for this signature in database
GPG key ID: D8D1A1F6129DCBF4

View file

@ -109,7 +109,7 @@ def _filter_dict(input_dict, search_key, search_value):
return output_dict
def _config_logic(loaded_result, test=False, commit_config=True):
def _config_logic(loaded_result, test=False, commit_config=True, loaded_config=None):
'''
Builds the config logic for `load_config` and `load_template` functions.
@ -117,6 +117,10 @@ def _config_logic(loaded_result, test=False, commit_config=True):
loaded_result['already_configured'] = False
loaded_result['loaded_config'] = ''
if loaded_config:
loaded_result['loaded_config'] = loaded_config
_compare = compare_config()
if _compare.get('result', False):
loaded_result['diff'] = _compare.get('out')
@ -732,8 +736,12 @@ def mac(address='', interface='', vlan=0):
# ----- Configuration specific functions ------------------------------------------------------------------------------>
def load_config(filename=None, text=None, test=False, commit=True, replace=False):
def load_config(filename=None,
text=None,
test=False,
commit=True,
debug=False,
replace=False):
'''
Populates the candidate configuration. It can be loaded from a file or from a string. If you send both a
filename and a string containing the configuration, the file takes precedence.
@ -744,23 +752,43 @@ def load_config(filename=None, text=None, test=False, commit=True, replace=False
Be aware that by default this method will commit the configuration. If there are no changes, it does not commit and
the flag ``already_configured`` will be set as ``True`` to point this out.
:param filename: Path to the file containing the desired configuration. By default is None.
:param text: String containing the desired configuration.
:param test: Dry run? If set as ``True``, will apply the config, discard and return the changes. Default: ``False``\
and will commit the changes on the device.
:param commit: Commit? (default: ``True``) Sometimes it is not needed to commit the config immediately \
after loading the changes. E.g.: a state loads a couple of parts (add / remove / update) \
and would not be optimal to commit after each operation. \
Also, from the CLI when the user needs to apply the similar changes before committing, \
can specify ``commit=False`` and will not discard the config.
:param replace: Load and replace the configuration. Default: ``False``.
filename
Path to the file containing the desired configuration. By default is None.
text
String containing the desired configuration.
test: False
Dry run? If set as ``True``, will apply the config, discard and return the changes. Default: ``False``
and will commit the changes on the device.
commit: True
Commit? (default: ``True``) Sometimes it is not needed to commit the config immediately
after loading the changes. E.g.: a state loads a couple of parts (add / remove / update)
and would not be optimal to commit after each operation.
Also, from the CLI when the user needs to apply the similar changes before committing,
can specify ``commit=False`` and will not discard the config.
debug: False
Debug mode. Will insert a new key under the output dictionary, as ``loaded_config`` contaning the raw
configuration loaded on the device.
.. versionadded:: 2016.11.1
replace: False
Load and replace the configuration. Default: ``False``.
.. versionadded:: 2016.11.1
:return: a dictionary having the following keys:
* result (bool): if the config was applied successfully. It is ``False`` only in case of failure. In case
there are no changes to be applied and successfully performs all operations it is still ``True`` and so will be
* result (bool): if the config was applied successfully. It is ``False`` only in case of failure. In case \
there are no changes to be applied and successfully performs all operations it is still `True` and so will be \
the ``already_configured`` flag (example below)
* comment (str): a message for the user
* already_configured (bool): flag to check if there were no changes applied
* loaded_config (str): the configuration loaded on the device, after rendering the template. Requires ``debug`` \
to be set as ``True``
* diff (str): returns the config changes applied
CLI Example:
@ -775,7 +803,6 @@ def load_config(filename=None, text=None, test=False, commit=True, replace=False
Example output:
.. code-block:: python
{
'comment': 'Configuration discarded.',
'already_configured': False,
@ -787,7 +814,6 @@ def load_config(filename=None, text=None, test=False, commit=True, replace=False
fun = 'load_merge_candidate'
if replace:
fun = 'load_replace_candidate'
_loaded = __proxy__['napalm.call'](
fun,
**{
@ -795,36 +821,125 @@ def load_config(filename=None, text=None, test=False, commit=True, replace=False
'config': text
}
)
return _config_logic(_loaded, test=test, commit_config=commit)
loaded_config = None
if debug:
if filename:
loaded_config = open(filename).read()
else:
loaded_config = text
return _config_logic(_loaded,
test=test,
commit_config=commit,
loaded_config=loaded_config)
def load_template(template_name,
template_source=None,
template_path=None,
template_hash=None,
template_hash_name=None,
template_user='root',
template_group='root',
template_mode='755',
saltenv=None,
template_engine='jinja',
skip_verify=True,
defaults=None,
test=False,
commit=True,
debug=False,
replace=False,
**template_vars):
'''
Renders a configuration template (Jinja) and loads the result on the device.
By default will commit the changes. To force a dry run, set ``test=True``.
:param template_name: Identifies the template name.
:param template_source (optional): Inline config template to be rendered and loaded on the device.
:param template_path (optional): Specifies the absolute path to a different directory for the configuration \
templates. If not specified, by default will use the default templates defined in NAPALM.
:param test: Dry run? If set to ``True``, will apply the config, discard and return the changes. Default: ``False``\
and will commit the changes on the device.
:param commit: Commit? (default: ``True``) Sometimes it is not needed to commit the config immediately \
after loading the changes. E.g.: a state loads a couple of parts (add / remove / update) \
and would not be optimal to commit after each operation. \
Also, from the CLI when the user needs to apply the similar changes before committing, \
can specify ``commit=False`` and will not discard the config.
:param replace: Load and replace the configuration.
:param template_vars: Dictionary with the arguments to be used when the template is rendered.
template_name
Identifies the template name. If specifies the complete path, will render the template via
template_source: None
Inline config template to be rendered and loaded on the device.
template_path: None
Specifies the absolute path to a the template directory.
template_hash: None
Hash of the template file. Format: ``{hash_type: 'md5', 'hsum': <md5sum>}``
.. versionadded:: 2016.11.1
template_hash_name: None
When ``template_hash`` refers to a remote file, this specifies the filename to look for in that file.
.. versionadded:: 2016.11.1
template_group: root
Owner of file.
.. versionadded:: 2016.11.1
template_user: root
Group owner of file.
.. versionadded:: 2016.11.1
template_user: 755
Permissions of file
.. versionadded:: 2016.11.1
saltenv: base
Specifies the template environment. This will influence the relative imports inside the templates.
.. versionadded:: 2016.11.1
template_engine: jinja
The following templates engines are supported:
- :mod:`cheetah<salt.renderers.cheetah>`
- :mod:`genshi<salt.renderers.genshi>`
- :mod:`jinja<salt.renderers.jinja>`
- :mod:`mako<salt.renderers.mako>`
- :mod:`py<salt.renderers.py>`
- :mod:`wempy<salt.renderers.wempy>`
.. versionadded:: 2016.11.1
skip_verify: True
If ``True``, hash verification of remote file sources (``http://``, ``https://``, ``ftp://``) will be skipped,
and the ``source_hash`` argument will be ignored.
.. versionadded:: 2016.11.1
test: False
Dry run? If set to ``True``, will apply the config, discard and return the changes. Default: ``False``
and will commit the changes on the device.
commit: True
Commit? (default: ``True``) Sometimes it is not needed to commit the config immediately
after loading the changes. E.g.: a state loads a couple of parts (add / remove / update)
and would not be optimal to commit after each operation.
Also, from the CLI when the user needs to apply the similar changes before committing,
can specify ``commit=False`` and will not discard the config.
debug: False
Debug mode. Will insert a new key under the output dictionary, as ``loaded_config`` contaning the raw
result after the template was rendered.
replace: False
Load and replace the configuration.
.. versionadded:: 2016.11.1
defaults: None
Default variables/context passed to the template.
.. versionadded:: 2016.11.1
template_vars
Dictionary with the arguments/context to be used when the template is rendered.
:return: a dictionary having the following keys:
* result (bool): if the config was applied successfully. It is ``False`` only in case of failure. In case \
@ -832,6 +947,8 @@ def load_template(template_name,
the ``already_configured`` flag (example below)
* comment (str): a message for the user
* already_configured (bool): flag to check if there were no changes applied
* loaded_config (str): the configuration loaded on the device, after rendering the template. Requires ``debug`` \
to be set as ``True``
* diff (str): returns the config changes applied
The template can use variables from the ``grains``, ``pillar`` or ``opts``, for example:
@ -845,18 +962,45 @@ def load_template(template_name,
system {
host-name {{hostname}};
}
{% elif router_vendor|lower == 'cisco' %}
hostname {{hostname}}
{% endif %}
CLI Example:
CLI Examples:
.. code-block:: bash
salt '*' net.load_template ntp_peers peers=[192.168.0.1] # uses NAPALM default templates
salt '*' net.load_template set_hostname template_source='system { domain-name {{domain_name}}; }'
domain_name='test.com'
salt '*' net.load_template set_ntp_peers peers=[192.168.0.1] # uses NAPALM default templates
# inline template:
salt -G 'os:junos' net.load_template set_hostname template_source='system { host-name {{host_name}}; }' \
host_name='MX480.lab'
# inline template using grains info:
salt -G 'os:junos' net.load_template set_hostname \
template_source='system { host-name {{grains.model}}.lab; }'
# if the device is a MX480, the command above will set the hostname as: MX480.lab
# inline template using pillar data:
salt -G 'os:junos' net.load_template set_hostname template_source='system { host-name {{pillar.proxy.host}}; }'
salt '*' net.load_template my_template template_path='/tmp/tpl/' my_param='aaa' # will commit
salt '*' net.load_template my_template template_path='/tmp/tpl/' my_param='aaa' test=True # dry run
salt '*' net.load_template salt://templates/my_stuff.jinja debug=True # equivalent of the next command
salt '*' net.load_template my_stuff.jinja template_path=salt://templates/ debug=True
# in case the template needs to include files that are not under the same path (e.g. http://),
# to help the templating engine find it, you will need to specify the `saltenv` argument:
salt '*' net.load_template my_stuff.jinja template_path=salt://templates saltenv=/path/to/includes debug=True
# render a mako template:
salt '*' net.load_template salt://templates/my_stuff.mako template_engine=mako debug=True
# render remote template
salt -G 'os:junos' net.load_template http://bit.ly/2fReJg7 test=True debug=True peers=['192.168.0.1']
salt -G 'os:ios' net.load_template http://bit.ly/2gKOj20 test=True debug=True peers=['192.168.0.1']
Example output:
.. code-block:: python
@ -865,30 +1009,149 @@ def load_template(template_name,
'comment': '',
'already_configured': False,
'result': True,
'diff': '[edit system]+ host-name edge01.bjm01'
'diff': '[edit system]+ host-name edge01.bjm01',
'loaded_config': 'system { host-name edge01.bjm01; }''
}
'''
_rendered = ''
_loaded = {
'result': True,
'comment': '',
'out': None
}
loaded_config = None
load_templates_params = template_vars.copy() # to leave the template_vars unchanged
load_templates_params.update(
{
'template_name': template_name,
'template_source': template_source, # inline template
'template_path': template_path,
'replace': replace, # to load_replace_candidate after the template is rendered
'pillar': __pillar__, # inject pillar content, accessible as `pillar`
'grains': __grains__, # inject grains, accessible as `grains`
'opts': __opts__ # inject opts, accessible as `opts`
}
)
# prechecks
if template_engine not in salt.utils.templates.TEMPLATE_REGISTRY:
_loaded.update({
'result': False,
'comment': 'Invalid templating engine! Choose between: {tpl_eng_opts}'.format(
tpl_eng_opts=', '.join(list(salt.utils.templates.TEMPLATE_REGISTRY.keys()))
)
})
return _loaded # exit
_loaded = __proxy__['napalm.call']('load_template',
**load_templates_params
)
# to check if will be rendered by salt or NAPALM
salt_render_prefixes = ('salt://', 'http://', 'https://', 'ftp://')
salt_render = False
for salt_render_prefix in salt_render_prefixes:
if not salt_render:
salt_render = salt_render or template_name.startswith(salt_render_prefix) or \
(template_path and template_path.startswith(salt_render_prefix))
file_exists = __salt__['file.file_exists'](template_name)
if template_source or template_path or file_exists or salt_render:
# either inline template
# either template in a custom path
# either abs path send
# either starts with salt:// and
# then use Salt render system
# if needed to render the template send as inline arg
if template_source:
# render the content
if not saltenv:
saltenv = template_path if template_path else 'base' # either use the env from the path, either base
_rendered = __salt__['file.apply_template_on_contents'](
contents=template_source,
template=template_engine,
context=template_vars,
defaults=defaults,
saltenv=saltenv
)
if not isinstance(_rendered, six.string_types):
if 'result' in _rendered:
_loaded['result'] = _rendered['result']
else:
_loaded['result'] = False
if 'comment' in _rendered:
_loaded['comment'] = _rendered['comment']
else:
_loaded['comment'] = 'Error while rendering the template.'
return _loaded
else:
if template_path and not file_exists:
template_name = __salt__['file.join'](template_path, template_name)
if not saltenv:
# no saltenv overriden
# use the custom template path
saltenv = template_path if not salt_render else 'base'
elif salt_render and not saltenv:
# if saltenv not overrided and path specified as salt:// or http:// etc.
# will use the default environment, from the base
saltenv = template_path if template_path else 'base'
if not saltenv:
# still not specified, default to `base`
saltenv = 'base'
# render the file - either local, either remote
_rand_filename = __salt__['random.hash'](template_name, 'md5')
_temp_file = __salt__['file.join']('/tmp', _rand_filename)
_managed = __salt__['file.get_managed'](name=_temp_file,
source=template_name, # abs path
source_hash=template_hash,
source_hash_name=template_hash_name,
user=template_user,
group=template_group,
mode=template_mode,
template=template_engine,
context=template_vars,
defaults=defaults,
saltenv=saltenv,
skip_verify=skip_verify)
if not isinstance(_managed, (list, tuple)) and isinstance(_managed, six.string_types):
_loaded['comment'] = _managed
_loaded['result'] = False
elif isinstance(_managed, (list, tuple)) and not len(_managed) > 0:
_loaded['result'] = False
_loaded['comment'] = 'Error while rendering the template.'
elif isinstance(_managed, (list, tuple)) and not len(_managed[0]) > 0:
_loaded['result'] = False
_loaded['comment'] = _managed[-1] # contains the error message
if _loaded['result']: # all good
_temp_tpl_file = _managed[0]
_temp_tpl_file_exists = __salt__['file.file_exists'](_temp_tpl_file)
if not _temp_tpl_file_exists:
_loaded['result'] = False
_loaded['comment'] = 'Error while rendering the template.'
return _loaded
_rendered = open(_temp_tpl_file).read()
else:
return _loaded # exit
if debug: # all good, but debug mode required
# valid output and debug mode
loaded_config = _rendered
if _loaded['result']: # all good
fun = 'load_merge_candidate'
if replace: # replace requested
fun = 'load_replace_candidate'
_loaded = __proxy__['napalm.call'](
fun,
**{
'config': _rendered
}
)
else:
# otherwise, use NAPALM render system, injecting pillar/grains/opts vars
load_templates_params = defaults if defaults else {}
load_templates_params.update(template_vars)
load_templates_params.update(
{
'template_name': template_name,
'template_source': template_source, # inline template
'template_path': template_path,
'pillar': __pillar__, # inject pillar content
'grains': __grains__, # inject grains content
'opts': __opts__ # inject opts content
}
)
_loaded = __proxy__['napalm.call']('load_template',
**load_templates_params)
return _config_logic(_loaded,
test=test,
commit_config=commit)
commit_config=commit,
loaded_config=loaded_config)
def commit():