Merge branch '2016.3' into 'develop'

Conflicts:
  - salt/grains/core.py
  - tests/unit/grains/core_test.py
This commit is contained in:
rallytime 2016-06-23 17:13:20 -06:00
commit ea048fd9b6
5 changed files with 289 additions and 28 deletions

View File

@ -1291,6 +1291,11 @@ def os_data():
if 'CPE_NAME' in os_release:
if ":suse:" in os_release['CPE_NAME'] or ":opensuse:" in os_release['CPE_NAME']:
grains['os'] = "SUSE"
# openSUSE `osfullname` grain normalization
if os_release.get("NAME") == "openSUSE Leap":
grains['osfullname'] = "Leap"
elif os_release.get("VERSION") == "Tumbleweed":
grains['osfullname'] = os_release["VERSION"]
elif os.path.isfile('/etc/SuSE-release'):
grains['lsb_distrib_id'] = 'SUSE'
version = ''

View File

@ -106,8 +106,8 @@ duration = {'Immediately': 'PT0M',
'4 hours': 'PT4H',
'8 hours': 'PT8H',
'12 hours': 'PT12H',
'1 day': 'P1D',
'3 days': 'P3D',
'1 day': ['P1D', 'PT24H'],
'3 days': ['P3D', 'PT72H'],
'30 days': 'P30D',
'90 days': 'P90D',
'180 days': 'P180D',
@ -117,6 +117,18 @@ action_types = {'Execute': TASK_ACTION_EXEC,
'Email': TASK_ACTION_SEND_EMAIL,
'Message': TASK_ACTION_SHOW_MESSAGE}
trigger_types = {'Event': TASK_TRIGGER_EVENT,
'Once': TASK_TRIGGER_TIME,
'Daily': TASK_TRIGGER_DAILY,
'Weekly': TASK_TRIGGER_WEEKLY,
'Monthly': TASK_TRIGGER_MONTHLY,
'MonthlyDay': TASK_TRIGGER_MONTHLYDOW,
'OnIdle': TASK_TRIGGER_IDLE,
'OnTaskCreation': TASK_TRIGGER_REGISTRATION,
'OnBoot': TASK_TRIGGER_BOOT,
'OnLogon': TASK_TRIGGER_LOGON,
'OnSessionChange': TASK_TRIGGER_SESSION_STATE_CHANGE}
states = {TASK_STATE_UNKNOWN: 'Unknown',
TASK_STATE_DISABLED: 'Disabled',
TASK_STATE_QUEUED: 'Queued',
@ -217,7 +229,36 @@ def _reverse_lookup(dictionary, value):
:return: Returns the first key to match the value
:rtype: str
'''
return dictionary.keys()[dictionary.values().index(value)]
value_index = -1
for idx, dict_value in enumerate(dictionary.values()):
if type(dict_value) == list:
if value in dict_value:
value_index = idx
break
elif value == dict_value:
value_index = idx
break
return dictionary.keys()[value_index]
def _lookup_first(dictionary, key):
'''
Lookup the first value given a key. Returns the first value if the key
refers to a list or the value itself.
:param dict dictionary: The dictionary to search
:param str key: The key to get
:return: Returns the first value available for the key
:rtype: str
'''
value = dictionary[key]
if type(value) == list:
return value[0]
else:
return value
def _save_task_definition(name,
@ -435,7 +476,8 @@ def create_task(name,
# Modify task settings
edit_task(task_definition=task_definition,
user_name=user_name,
password=password)
password=password,
**kwargs)
# Add Action
add_action(task_definition=task_definition, **kwargs)
@ -842,12 +884,12 @@ def edit_task(name=None,
task_definition.Settings.IdleSettings.RestartOnIdle = idle_restart
if idle_duration is not None:
if idle_duration in duration:
task_definition.Settings.IdleSettings.IdleDuration = duration[idle_duration]
task_definition.Settings.IdleSettings.IdleDuration = _lookup_first(duration, idle_duration)
else:
return 'Invalid value for "idle_duration"'
if idle_wait_timeout is not None:
if idle_wait_timeout in duration:
task_definition.Settings.IdleSettings.WaitTimeout = duration[idle_wait_timeout]
task_definition.Settings.IdleSettings.WaitTimeout = _lookup_first(duration, idle_wait_timeout)
else:
return 'Invalid value for "idle_wait_timeout"'
@ -879,7 +921,7 @@ def edit_task(name=None,
task_definition.Settings.RestartInterval = ''
else:
if restart_every in duration:
task_definition.Settings.RestartInterval = duration[restart_every]
task_definition.Settings.RestartInterval = _lookup_first(duration, restart_every)
else:
return 'Invalid value for "restart_every"'
if task_definition.Settings.RestartInterval:
@ -893,7 +935,7 @@ def edit_task(name=None,
task_definition.Settings.ExecutionTimeLimit = 'PT0S'
else:
if execution_time_limit in duration:
task_definition.Settings.ExecutionTimeLimit = duration[execution_time_limit]
task_definition.Settings.ExecutionTimeLimit = _lookup_first(duration, execution_time_limit)
else:
return 'Invalid value for "execution_time_limit"'
if force_stop is not None:
@ -903,7 +945,7 @@ def edit_task(name=None,
if delete_after is False:
task_definition.Settings.DeleteExpiredTaskAfter = ''
if delete_after in duration:
task_definition.Settings.DeleteExpiredTaskAfter = duration[delete_after]
task_definition.Settings.DeleteExpiredTaskAfter = _lookup_first(duration, delete_after)
else:
return 'Invalid value for "delete_after"'
if multiple_instances is not None:
@ -1221,8 +1263,43 @@ def info(name, location='\\'):
conditions['network_id'] = net_set.Id
conditions['network_name'] = net_set.Name
actions = []
for actionObj in task.Definition.Actions:
action = {}
action['action_type'] = _reverse_lookup(action_types, actionObj.Type)
if actionObj.Path:
action['cmd'] = actionObj.Path
if actionObj.Arguments:
action['arguments'] = actionObj.Arguments
if actionObj.WorkingDirectory:
action['working_dir'] = actionObj.WorkingDirectory
actions.append(action)
triggers = []
for triggerObj in task.Definition.Triggers:
trigger = {}
trigger['trigger_type'] = _reverse_lookup(trigger_types, triggerObj.Type)
if triggerObj.ExecutionTimeLimit:
trigger['execution_time_limit'] = _reverse_lookup(duration, triggerObj.ExecutionTimeLimit)
if triggerObj.StartBoundary:
start_date, start_time = triggerObj.StartBoundary.split('T', 1)
trigger['start_date'] = start_date
trigger['start_time'] = start_time
if triggerObj.EndBoundary:
end_date, end_time = triggerObj.EndBoundary.split('T', 1)
trigger['end_date'] = end_date
trigger['end_time'] = end_time
trigger['enabled'] = triggerObj.Enabled
if triggerObj.RandomDelay == '':
trigger['random_delay'] = False
else:
trigger['random_delay'] = _reverse_lookup(duration, triggerObj.RandomDelay)
triggers.append(trigger)
properties['settings'] = settings
properties['conditions'] = conditions
properties['actions'] = actions
properties['triggers'] = triggers
ret = properties
return ret
@ -1651,18 +1728,6 @@ def add_trigger(name=None,
return 'Required parameter "trigger_type" not specified'
# Define lookup dictionaries
trigger_types = {'Event': TASK_TRIGGER_EVENT,
'Once': TASK_TRIGGER_TIME,
'Daily': TASK_TRIGGER_DAILY,
'Weekly': TASK_TRIGGER_WEEKLY,
'Monthly': TASK_TRIGGER_MONTHLY,
'MonthlyDay': TASK_TRIGGER_MONTHLYDOW,
'OnIdle': TASK_TRIGGER_IDLE,
'OnTaskCreation': TASK_TRIGGER_REGISTRATION,
'OnBoot': TASK_TRIGGER_BOOT,
'OnLogon': TASK_TRIGGER_LOGON,
'OnSessionChange': TASK_TRIGGER_SESSION_STATE_CHANGE}
state_changes = {'ConsoleConnect': 1,
'ConsoleDisconnect': 2,
'RemoteConnect': 3,
@ -1809,14 +1874,14 @@ def add_trigger(name=None,
trigger.StartBoundary = start_boundary
# Advanced Settings
if random_delay:
trigger.RandomDelay = duration[random_delay]
trigger.RandomDelay = _lookup_first(duration, random_delay)
if repeat_interval:
trigger.Repetition.Interval = duration[repeat_interval]
trigger.Repetition.Interval = _lookup_first(duration, repeat_interval)
if repeat_duration:
trigger.Repetition.Duration = duration[repeat_duration]
trigger.Repetition.Duration = _lookup_first(duration, repeat_duration)
trigger.Repetition.StopAtDurationEnd = repeat_stop_at_duration_end
if execution_time_limit:
trigger.ExecutionTimeLimit = duration[execution_time_limit]
trigger.ExecutionTimeLimit = _lookup_first(duration, execution_time_limit)
if end_boundary:
trigger.EndBoundary = end_boundary
trigger.Enabled = trigger_enabled

View File

@ -640,17 +640,24 @@ class Finder(object):
for criterion in self.criteria:
if fstat is None and criterion.requires() & _REQUIRES_STAT:
fullpath = os.path.join(dirpath, name)
fstat = os.stat(fullpath)
try:
fstat = os.stat(fullpath)
except OSError:
fstat = os.lstat(fullpath)
if not criterion.match(dirpath, name, fstat):
matches = False
break
if matches:
if fullpath is None:
fullpath = os.path.join(dirpath, name)
for action in self.actions:
if (fstat is None and
action.requires() & _REQUIRES_STAT):
fstat = os.stat(fullpath)
try:
fstat = os.stat(fullpath)
except OSError:
fstat = os.lstat(fullpath)
result = action.execute(fullpath, fstat, test=self.test)
if result is not None:
yield result

View File

@ -963,7 +963,7 @@ class CkMinions(object):
for item in auth_list:
if isinstance(item, six.string_types):
continue
ou_names.append([potential_ou for potential_ou in item.keys() if potential_ou.startswith('ldap(')])
ou_names.extend([potential_ou for potential_ou in item.keys() if potential_ou.startswith('ldap(')])
if ou_names:
auth_list = salt.auth.ldap.expand_ldap_entries(auth_list, opts)
return auth_list

View File

@ -14,6 +14,7 @@ from salttesting.helpers import ensure_in_syspath
from salttesting.mock import (
MagicMock,
patch,
mock_open,
NO_MOCK,
NO_MOCK_REASON
)
@ -185,7 +186,190 @@ class CoreGrainsTestCase(TestCase):
self.assertEqual(os_grains.get('os_family'), 'SUSE')
self.assertEqual(os_grains.get('os'), 'SUSE')
def _run_suse_os_grains_tests(self, os_release_map):
path_isfile_mock = MagicMock(side_effect=lambda x: x in os_release_map['files'])
empty_mock = MagicMock(return_value={})
osarch_mock = MagicMock(return_value="amd64")
os_release_mock = MagicMock(return_value=os_release_map.get('os_release_file'))
orig_import = __import__
def _import_mock(name, *args):
if name == 'lsb_release':
raise ImportError('No module named lsb_release')
return orig_import(name, *args)
# Skip the first if statement
with patch.object(salt.utils, 'is_proxy',
MagicMock(return_value=False)):
# Skip the selinux/systemd stuff (not pertinent)
with patch.object(core, '_linux_bin_exists',
MagicMock(return_value=False)):
# Skip the init grain compilation (not pertinent)
with patch.object(os.path, 'exists', path_isfile_mock):
# Ensure that lsb_release fails to import
with patch('__builtin__.__import__',
side_effect=_import_mock):
# Skip all the /etc/*-release stuff (not pertinent)
with patch.object(os.path, 'isfile', path_isfile_mock):
with patch.object(core, '_parse_os_release', os_release_mock):
# Mock platform.linux_distribution to give us the
# OS name that we want.
distro_mock = MagicMock(
return_value=('SUSE test', 'version', 'arch')
)
with patch("salt.utils.fopen", mock_open()) as suse_release_file:
suse_release_file.return_value.__iter__.return_value = os_release_map.get('suse_release_file', '').splitlines()
with patch.object(platform, 'linux_distribution', distro_mock):
with patch.object(core, '_linux_gpu_data', empty_mock):
with patch.object(core, '_linux_cpudata', empty_mock):
with patch.object(core, '_virtual', empty_mock):
# Mock the osarch
with patch.dict(core.__salt__, {'cmd.run': osarch_mock}):
os_grains = core.os_data()
self.assertEqual(os_grains.get('os'), 'SUSE')
self.assertEqual(os_grains.get('os_family'), 'SUSE')
self.assertEqual(os_grains.get('osfullname'), os_release_map['osfullname'])
self.assertEqual(os_grains.get('oscodename'), os_release_map['oscodename'])
self.assertEqual(os_grains.get('osrelease'), os_release_map['osrelease'])
self.assertListEqual(list(os_grains.get('osrelease_info')), os_release_map['osrelease_info'])
@skipIf(not salt.utils.is_linux(), 'System is not Linux')
def test_suse_os_grains_sles11sp3(self):
'''
Test if OS grains are parsed correctly in SLES 11 SP3
'''
_os_release_map = {
'suse_release_file': '''SUSE Linux Enterprise Server 11 (x86_64)
VERSION = 11
PATCHLEVEL = 3
''',
'oscodename': 'SUSE Linux Enterprise Server 11 SP3',
'osfullname': "SLES",
'osrelease': '11.3',
'osrelease_info': [11, 3],
'files': ["/etc/SuSE-release"],
}
self._run_suse_os_grains_tests(_os_release_map)
@skipIf(not salt.utils.is_linux(), 'System is not Linux')
def test_suse_os_grains_sles11sp4(self):
'''
Test if OS grains are parsed correctly in SLES 11 SP4
'''
_os_release_map = {
'os_release_file': {
'NAME': 'SLES',
'VERSION': '11.4',
'VERSION_ID': '11.4',
'PRETTY_NAME': 'SUSE Linux Enterprise Server 11 SP4',
'ID': 'sles',
'ANSI_COLOR': '0;32',
'CPE_NAME': 'cpe:/o:suse:sles:11:4'
},
'oscodename': 'SUSE Linux Enterprise Server 11 SP4',
'osfullname': "SLES",
'osrelease': '11.4',
'osrelease_info': [11, 4],
'files': ["/etc/os-release"],
}
self._run_suse_os_grains_tests(_os_release_map)
@skipIf(not salt.utils.is_linux(), 'System is not Linux')
def test_suse_os_grains_sles12(self):
'''
Test if OS grains are parsed correctly in SLES 12
'''
_os_release_map = {
'os_release_file': {
'NAME': 'SLES',
'VERSION': '12',
'VERSION_ID': '12',
'PRETTY_NAME': 'SUSE Linux Enterprise Server 12',
'ID': 'sles',
'ANSI_COLOR': '0;32',
'CPE_NAME': 'cpe:/o:suse:sles:12'
},
'oscodename': 'SUSE Linux Enterprise Server 12',
'osfullname': "SLES",
'osrelease': '12',
'osrelease_info': [12],
'files': ["/etc/os-release"],
}
self._run_suse_os_grains_tests(_os_release_map)
@skipIf(not salt.utils.is_linux(), 'System is not Linux')
def test_suse_os_grains_sles12sp1(self):
'''
Test if OS grains are parsed correctly in SLES 12 SP1
'''
_os_release_map = {
'os_release_file': {
'NAME': 'SLES',
'VERSION': '12-SP1',
'VERSION_ID': '12.1',
'PRETTY_NAME': 'SUSE Linux Enterprise Server 12 SP1',
'ID': 'sles',
'ANSI_COLOR': '0;32',
'CPE_NAME': 'cpe:/o:suse:sles:12:sp1'
},
'oscodename': 'SUSE Linux Enterprise Server 12 SP1',
'osfullname': "SLES",
'osrelease': '12.1',
'osrelease_info': [12, 1],
'files': ["/etc/os-release"],
}
self._run_suse_os_grains_tests(_os_release_map)
@skipIf(not salt.utils.is_linux(), 'System is not Linux')
def test_suse_os_grains_opensuse_leap_42_1(self):
'''
Test if OS grains are parsed correctly in openSUSE Leap 42.1
'''
_os_release_map = {
'os_release_file': {
'NAME': 'openSUSE Leap',
'VERSION': '42.1',
'VERSION_ID': '42.1',
'PRETTY_NAME': 'openSUSE Leap 42.1 (x86_64)',
'ID': 'opensuse',
'ANSI_COLOR': '0;32',
'CPE_NAME': 'cpe:/o:opensuse:opensuse:42.1'
},
'oscodename': 'openSUSE Leap 42.1 (x86_64)',
'osfullname': "Leap",
'osrelease': '42.1',
'osrelease_info': [42, 1],
'files': ["/etc/os-release"],
}
self._run_suse_os_grains_tests(_os_release_map)
@skipIf(not salt.utils.is_linux(), 'System is not Linux')
def test_suse_os_grains_tumbleweed(self):
'''
Test if OS grains are parsed correctly in openSUSE Tumbleweed
'''
_os_release_map = {
'os_release_file': {
'NAME': 'openSUSE',
'VERSION': 'Tumbleweed',
'VERSION_ID': '20160504',
'PRETTY_NAME': 'openSUSE Tumbleweed (20160504) (x86_64)',
'ID': 'opensuse',
'ANSI_COLOR': '0;32',
'CPE_NAME': 'cpe:/o:opensuse:opensuse:20160504'
},
'oscodename': 'openSUSE Tumbleweed (20160504) (x86_64)',
'osfullname': "Tumbleweed",
'osrelease': '20160504',
'osrelease_info': [20160504],
'files': ["/etc/os-release"],
}
self._run_suse_os_grains_tests(_os_release_map)
if __name__ == '__main__':
from integration import run_tests
run_tests(CoreGrainsTestCase, needs_daemon=False)