mirror of
https://github.com/saltstack/salt.git
synced 2025-04-17 10:10:20 +00:00
Merge pull request #51277 from garethgreenaway/merge-2019.2
[2019.2] Merge forward from 2018.3 to 2019.2
This commit is contained in:
commit
8596ee45a0
10 changed files with 113 additions and 19 deletions
|
@ -87,6 +87,13 @@ the context into the included file is required:
|
|||
.. code-block:: jinja
|
||||
|
||||
{% from 'lib.sls' import test with context %}
|
||||
|
||||
Includes must use full paths, like so:
|
||||
|
||||
.. code-block:: jinja
|
||||
:caption: spam/eggs.jinja
|
||||
|
||||
{% include 'spam/foobar.jinja' %}
|
||||
|
||||
Including Context During Include/Import
|
||||
---------------------------------------
|
||||
|
|
|
@ -19,8 +19,7 @@ The firewall configuration is generated by Capirca_.
|
|||
|
||||
.. _Capirca: https://github.com/google/capirca
|
||||
|
||||
Capirca is not yet available on PyPI threrefore it has to be installed
|
||||
directly form Git: ``pip install -e git+git@github.com:google/capirca.git#egg=aclgen``.
|
||||
To install Capirca, execute: ``pip install capirca``.
|
||||
'''
|
||||
from __future__ import absolute_import, print_function, unicode_literals
|
||||
|
||||
|
@ -34,7 +33,10 @@ log = logging.getLogger(__file__)
|
|||
# Import third party libs
|
||||
from salt.ext import six
|
||||
try:
|
||||
import aclgen
|
||||
import capirca
|
||||
import capirca.aclgen
|
||||
import capirca.lib.policy
|
||||
import capirca.lib.aclgenerator
|
||||
HAS_CAPIRCA = True
|
||||
except ImportError:
|
||||
HAS_CAPIRCA = False
|
||||
|
@ -69,10 +71,12 @@ def __virtual__():
|
|||
# module globals
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
|
||||
# define the default values for all possible term fields
|
||||
# we could also extract them from the `policy` module, inspecting the `Policy`
|
||||
# class, but that might be overkill & it would make the code less obvious.
|
||||
# we can revisit this later if necessary.
|
||||
|
||||
_TERM_FIELDS = {
|
||||
'action': [],
|
||||
'address': [],
|
||||
|
@ -161,7 +165,19 @@ _SERVICES = {}
|
|||
|
||||
|
||||
if HAS_CAPIRCA:
|
||||
class _Policy(aclgen.policy.Policy):
|
||||
_TempTerm = capirca.lib.policy.Term
|
||||
|
||||
def _add_object(self, obj):
|
||||
return
|
||||
|
||||
setattr(_TempTerm, 'AddObject', _add_object)
|
||||
dumy_term = _TempTerm(None)
|
||||
for item in dir(dumy_term):
|
||||
if hasattr(item, '__func__') or item.startswith('_') or item != item.lower():
|
||||
continue
|
||||
_TERM_FIELDS[item] = getattr(dumy_term, item)
|
||||
|
||||
class _Policy(capirca.lib.policy.Policy):
|
||||
'''
|
||||
Extending the Capirca Policy class to allow inserting custom filters.
|
||||
'''
|
||||
|
@ -169,7 +185,7 @@ if HAS_CAPIRCA:
|
|||
self.filters = []
|
||||
self.filename = ''
|
||||
|
||||
class _Term(aclgen.policy.Term):
|
||||
class _Term(capirca.lib.policy.Term):
|
||||
'''
|
||||
Extending the Capirca Term class to allow setting field valued on the fly.
|
||||
'''
|
||||
|
@ -186,10 +202,10 @@ def _import_platform_generator(platform):
|
|||
for a class inheriting the `ACLGenerator` class.
|
||||
'''
|
||||
log.debug('Using platform: {plat}'.format(plat=platform))
|
||||
for mod_name, mod_obj in inspect.getmembers(aclgen):
|
||||
for mod_name, mod_obj in inspect.getmembers(capirca.aclgen):
|
||||
if mod_name == platform and inspect.ismodule(mod_obj):
|
||||
for plat_obj_name, plat_obj in inspect.getmembers(mod_obj): # pylint: disable=unused-variable
|
||||
if inspect.isclass(plat_obj) and issubclass(plat_obj, aclgen.aclgenerator.ACLGenerator):
|
||||
if inspect.isclass(plat_obj) and issubclass(plat_obj, capirca.lib.aclgenerator.ACLGenerator):
|
||||
log.debug('Identified Capirca class {cls} for {plat}'.format(
|
||||
cls=plat_obj,
|
||||
plat=platform))
|
||||
|
@ -366,7 +382,11 @@ def _clean_term_opts(term_opts):
|
|||
# IP-type fields need to be transformed
|
||||
ip_values = []
|
||||
for addr in value:
|
||||
ip_values.append(aclgen.policy.nacaddr.IP(addr))
|
||||
if six.PY2:
|
||||
addr = six.text_type(addr)
|
||||
# Adding this, as ipaddress would complain about valid
|
||||
# addresses not being valid. #pythonIsFun
|
||||
ip_values.append(capirca.lib.policy.nacaddr.IP(addr))
|
||||
value = ip_values[:]
|
||||
clean_opts[field] = value
|
||||
return clean_opts
|
||||
|
@ -427,7 +447,7 @@ def _merge_list_of_dict(first, second, prepend=True):
|
|||
if first and not second:
|
||||
return first
|
||||
# Determine overlaps
|
||||
# So we don't change the position of the existing terms/filters
|
||||
# So we dont change the position of the existing terms/filters
|
||||
overlaps = []
|
||||
merged = []
|
||||
appended = []
|
||||
|
@ -514,7 +534,7 @@ def _get_policy_object(platform,
|
|||
continue # go to the next filter
|
||||
filter_name = filter_.keys()[0]
|
||||
filter_config = filter_.values()[0]
|
||||
header = aclgen.policy.Header() # same header everywhere
|
||||
header = capirca.lib.policy.Header() # same header everywhere
|
||||
target_opts = [
|
||||
platform,
|
||||
filter_name
|
||||
|
@ -524,7 +544,7 @@ def _get_policy_object(platform,
|
|||
filter_options = _make_it_list({}, filter_name, filter_options)
|
||||
# make sure the filter options are sent as list
|
||||
target_opts.extend(filter_options)
|
||||
target = aclgen.policy.Target(target_opts)
|
||||
target = capirca.lib.policy.Target(target_opts)
|
||||
header.AddObject(target)
|
||||
filter_terms = []
|
||||
for term_ in filter_config.get('terms', []):
|
||||
|
|
|
@ -226,6 +226,7 @@ def _resolve_user_group_names(opts):
|
|||
if _info and _param in _info:
|
||||
_id = _info[_param]
|
||||
opts[ind] = _param + '=' + six.text_type(_id)
|
||||
opts[ind] = opts[ind].replace('\\040', '\\ ')
|
||||
return opts
|
||||
|
||||
|
||||
|
@ -729,7 +730,7 @@ def set_fstab(
|
|||
'name': name,
|
||||
'device': device.replace('\\ ', '\\040'),
|
||||
'fstype': fstype,
|
||||
'opts': opts,
|
||||
'opts': opts.replace('\\ ', '\\040'),
|
||||
'dump': dump,
|
||||
'pass_num': pass_num,
|
||||
}
|
||||
|
|
|
@ -19,6 +19,8 @@ The firewall configuration is generated by Capirca_.
|
|||
|
||||
.. _Capirca: https://github.com/google/capirca
|
||||
|
||||
To install Capirca, execute: ``pip install capirca``.
|
||||
|
||||
To be able to load configuration on network devices,
|
||||
it requires NAPALM_ library to be installed: ``pip install napalm``.
|
||||
Please check Installation_ for complete details.
|
||||
|
@ -34,7 +36,10 @@ log = logging.getLogger(__file__)
|
|||
# Import third party libs
|
||||
try:
|
||||
# pylint: disable=W0611
|
||||
import aclgen
|
||||
import capirca
|
||||
import capirca.aclgen
|
||||
import capirca.lib.policy
|
||||
import capirca.lib.aclgenerator
|
||||
HAS_CAPIRCA = True
|
||||
# pylint: enable=W0611
|
||||
except ImportError:
|
||||
|
|
|
@ -2675,6 +2675,7 @@ def managed(name,
|
|||
ret, 'Defaults must be formed as a dict')
|
||||
|
||||
if not replace and os.path.exists(name):
|
||||
ret_perms = {}
|
||||
# Check and set the permissions if necessary
|
||||
if salt.utils.platform.is_windows():
|
||||
ret = __salt__['file.check_perms'](
|
||||
|
@ -2686,10 +2687,19 @@ def managed(name,
|
|||
inheritance=win_inheritance,
|
||||
reset=win_perms_reset)
|
||||
else:
|
||||
ret, _ = __salt__['file.check_perms'](
|
||||
ret, ret_perms = __salt__['file.check_perms'](
|
||||
name, ret, user, group, mode, attrs, follow_symlinks)
|
||||
if __opts__['test']:
|
||||
ret['comment'] = 'File {0} not updated'.format(name)
|
||||
if isinstance(ret_perms, dict) and \
|
||||
'lmode' in ret_perms and \
|
||||
mode != ret_perms['lmode']:
|
||||
ret['comment'] = ('File {0} will be updated with permissions '
|
||||
'{1} from its current '
|
||||
'state of {2}'.format(name,
|
||||
mode,
|
||||
ret_perms['lmode']))
|
||||
else:
|
||||
ret['comment'] = 'File {0} not updated'.format(name)
|
||||
elif not ret['changes'] and ret['result']:
|
||||
ret['comment'] = ('File {0} exists with proper permissions. '
|
||||
'No changes made.'.format(name))
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
Network ACL
|
||||
===========
|
||||
|
||||
Manage the firewall configuration on the network device namaged through NAPALM.
|
||||
Manage the firewall configuration on the network device managed through NAPALM.
|
||||
The firewall configuration is generated by Capirca_.
|
||||
|
||||
.. _Capirca: https://github.com/google/capirca
|
||||
|
@ -18,7 +18,13 @@ The firewall configuration is generated by Capirca_.
|
|||
Dependencies
|
||||
------------
|
||||
|
||||
Capirca: ``pip install -e git+git@github.com:google/capirca.git#egg=aclgen``
|
||||
Capirca
|
||||
~~~~~~~
|
||||
|
||||
To install Capirca, execute: ``pip install capirca``.
|
||||
|
||||
NAPALM
|
||||
~~~~~~
|
||||
|
||||
To be able to load configuration on network devices,
|
||||
it requires NAPALM_ library to be installed: ``pip install napalm``.
|
||||
|
@ -35,7 +41,10 @@ log = logging.getLogger(__file__)
|
|||
# Import third party libs
|
||||
try:
|
||||
# pylint: disable=W0611
|
||||
import aclgen
|
||||
import capirca
|
||||
import capirca.aclgen
|
||||
import capirca.lib.policy
|
||||
import capirca.lib.aclgenerator
|
||||
HAS_CAPIRCA = True
|
||||
# pylint: enable=W0611
|
||||
except ImportError:
|
||||
|
|
|
@ -270,6 +270,8 @@ def state(name,
|
|||
|
||||
cmd_kw['tgt_type'] = tgt_type
|
||||
cmd_kw['ssh'] = ssh
|
||||
if 'roster' in kwargs:
|
||||
cmd_kw['roster'] = kwargs['roster']
|
||||
cmd_kw['expect_minions'] = expect_minions
|
||||
if highstate:
|
||||
fun = 'state.highstate'
|
||||
|
|
|
@ -149,7 +149,7 @@ def nodegroup_comp(nodegroup, nodegroups, skip=None, first_call=True):
|
|||
# No compound operators found in nodegroup definition. Check for
|
||||
# group type specifiers
|
||||
group_type_re = re.compile('^[A-Z]@')
|
||||
regex_chars = ['(', '[', '{', '\\', '?''}])']
|
||||
regex_chars = ['(', '[', '{', '\\', '?', '}', ']', ')']
|
||||
if not [x for x in ret if '*' in x or group_type_re.match(x)]:
|
||||
# No group type specifiers and no wildcards.
|
||||
# Treat this as an expression.
|
||||
|
|
|
@ -786,6 +786,28 @@ class TestFileState(TestCase, LoaderModuleMockMixin):
|
|||
(name, user=user, group=group),
|
||||
ret)
|
||||
|
||||
if salt.utils.platform.is_windows():
|
||||
mock_ret = MagicMock(return_value=ret)
|
||||
comt = ('File {0} not updated'.format(name))
|
||||
else:
|
||||
perms = {'luser': user,
|
||||
'lmode': '0644',
|
||||
'lgroup': group}
|
||||
mock_ret = MagicMock(return_value=(ret, perms))
|
||||
comt = ('File {0} will be updated with '
|
||||
'permissions 0400 from its current '
|
||||
'state of 0644'.format(name))
|
||||
|
||||
with patch.dict(filestate.__salt__,
|
||||
{'file.check_perms': mock_ret}):
|
||||
with patch.object(os.path, 'exists', mock_t):
|
||||
with patch.dict(filestate.__opts__, {'test': True}):
|
||||
ret.update({'comment': comt})
|
||||
self.assertDictEqual(filestate.managed
|
||||
(name, user=user,
|
||||
group=group,
|
||||
mode=400), ret)
|
||||
|
||||
# 'directory' function tests: 1
|
||||
|
||||
def test_directory(self):
|
||||
|
|
|
@ -282,6 +282,24 @@ class SaltmodTestCase(TestCase, LoaderModuleMockMixin):
|
|||
with patch.dict(saltmod.__salt__, {'saltutil.wheel': wheel_mock}):
|
||||
self.assertDictEqual(saltmod.wheel(name), ret)
|
||||
|
||||
def test_state_ssh(self):
|
||||
'''
|
||||
Test saltmod passes roster to saltutil.cmd
|
||||
'''
|
||||
origcmd = saltmod.__salt__['saltutil.cmd']
|
||||
cmd_kwargs = {}
|
||||
cmd_args = []
|
||||
|
||||
def cmd_mock(*args, **kwargs):
|
||||
cmd_args.extend(args)
|
||||
cmd_kwargs.update(kwargs)
|
||||
return origcmd(*args, **kwargs)
|
||||
|
||||
with patch.dict(saltmod.__salt__, {'saltutil.cmd': cmd_mock}):
|
||||
ret = saltmod.state('state.sls', tgt='*', ssh=True, highstate=True, roster='my_roster')
|
||||
assert 'roster' in cmd_kwargs
|
||||
assert cmd_kwargs['roster'] == 'my_roster'
|
||||
|
||||
|
||||
@skipIf(NO_MOCK, NO_MOCK_REASON)
|
||||
class StatemodTests(TestCase, LoaderModuleMockMixin):
|
||||
|
|
Loading…
Add table
Reference in a new issue