mirror of
https://github.com/saltstack/salt.git
synced 2025-04-17 10:10:20 +00:00
Lint cleanup
This commit is contained in:
parent
56a8fa3f77
commit
215b8f38e2
1 changed files with 317 additions and 54 deletions
|
@ -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():
|
||||
|
|
Loading…
Add table
Reference in a new issue