From 2a39ff13577aabb4359f6d78f7b0bab4e78cfee4 Mon Sep 17 00:00:00 2001 From: cmcmarrow Date: Wed, 15 May 2019 10:57:21 -0700 Subject: [PATCH] Add win_task state and tests. --- salt/states/win_task.py | 41 +++++++++++++++++------------- tests/unit/states/test_win_task.py | 40 ++++++++++++++++------------- 2 files changed, 46 insertions(+), 35 deletions(-) diff --git a/salt/states/win_task.py b/salt/states/win_task.py index a28ed942ad0..d27293f028f 100644 --- a/salt/states/win_task.py +++ b/salt/states/win_task.py @@ -2,10 +2,10 @@ # https://msdn.microsoft.com/en-us/library/windows/desktop/aa383608(v=vs.85).aspx from __future__ import absolute_import, print_function, unicode_literals -''' -State Module for managing task scheduler on Windows. -You can add or remove tasks. -''' + +# State Module for managing task scheduler on Windows. +# You can add or remove tasks. + # Import Python libs import copy import logging @@ -17,10 +17,14 @@ import salt.utils.platform import salt.utils.dateutils # Import 3rd-party libs -import pywintypes +try: + import pywintypes +except ImportError: + pass + ACTION_PARTS = {'Execute': ['cmd'], - 'Email': ['from', 'to', 'cc', 'server'], + 'Email': ['from', 'to', 'cc', 'server'], 'Message': ['title', 'message']} OPTIONAL_ACTION_PARTS = {'start_in': '', @@ -78,7 +82,8 @@ def __virtual__(): ''' Load only on minions running on Windows and with task Module loaded. ''' - if not salt.utils.platform.is_windows() or 'task.list_tasks' not in __salt__: + if not salt.utils.platform.is_windows() or 'task.list_tasks' not in __salt__ or\ + 'pywintypes' not in globals(): return False, 'State win_task: state only works on Window systems with task loaded' return __virtualname__ @@ -129,13 +134,13 @@ def _get_task_state_data(name, task_state = {'location_valid': False, 'task_found': False, 'task_info': {}} - + # if valid location then try to get more info on task if _valid_location(location): task_state['location_valid'] = True task_state['task_found'] = name in __salt__['task.list_tasks'](location) # if task was found then get actions and triggers info - if task_state['task_found']: + if task_state['task_found']: task_info = __salt__['task.info'](name, location) task_state['task_info'] = {key: task_info[key] for key in TASK_PARTS} @@ -143,9 +148,9 @@ def _get_task_state_data(name, def _get_arguments(arguments_given, - key_arguments, - arguments_need_it, - optional_arguments): + key_arguments, + arguments_need_it, + optional_arguments): block = {} # check if key arguments are present for key in key_arguments: @@ -330,10 +335,10 @@ def present(name, salt 'minion-id' state.apply ''' - + ret = _get_state_data(name) before = _get_task_state_data(name, location) - + # if location not valid the task present will fail if not before['location_valid']: ret['result'] = False @@ -353,7 +358,7 @@ def present(name, # if win os is higher than 7 then Email and Message action_type is not supported try: if int(__grains__['osversion'].split('.')[0]) >= 8 and new_task['action']['action_type'] in ['Email', 'Message']: - log.warning('This OS %s does not support Email or Message action_type.' % __grains__['osversion']) + log.warning('This OS %s does not support Email or Message action_type.' % __grains__['osversion']) except ValueError: pass @@ -363,7 +368,7 @@ def present(name, ret['comment'] = '%s: %s' % (key, new_task[key]) ret['result'] = False return ret - + if __opts__['test']: # if force is False and task is found then no changes will take place if not force and before['task_found']: @@ -463,7 +468,7 @@ def absent(name, 'task_found': False, 'task_info': {}}) return ret - + # if task was found then delete it if before['task_found']: # try to delete task @@ -473,6 +478,6 @@ def absent(name, # if 'task.delete_task' returns a str then task was not deleted if isinstance(ret['result'], str): ret['result'] = False - + ret['changes'] = salt.utils.data.compare_dicts(before, _get_task_state_data(name, location)) return ret diff --git a/tests/unit/states/test_win_task.py b/tests/unit/states/test_win_task.py index 1941b4cadb5..a00418b929d 100644 --- a/tests/unit/states/test_win_task.py +++ b/tests/unit/states/test_win_task.py @@ -2,21 +2,21 @@ # https://msdn.microsoft.com/en-us/library/windows/desktop/aa383608(v=vs.85).aspx from __future__ import absolute_import, print_function, unicode_literals -# Import Python Libs -import copy - # Import Salt Libs import salt.modules.win_task import salt.states.win_task as win_task # Import Salt Testing Libs +import salt.utils.platform from tests.support.mixins import LoaderModuleMockMixin -from tests.support.mock import MagicMock, patch -from tests.support.unit import TestCase +from tests.support.mock import NO_MOCK, NO_MOCK_REASON, MagicMock, patch +from tests.support.unit import skipIf, TestCase from tests.support.helpers import destructiveTest @destructiveTest +@skipIf(NO_MOCK, NO_MOCK_REASON) +@skipIf(not salt.utils.platform.is_windows(), "Windows is required") class WinTaskCase(TestCase, LoaderModuleMockMixin): ''' Test cases for salt.states.win_task @@ -84,6 +84,8 @@ class WinTaskCase(TestCase, LoaderModuleMockMixin): self.assertEqual(ret['result'], True) +@skipIf(NO_MOCK, NO_MOCK_REASON) +@skipIf(not salt.utils.platform.is_windows(), "Windows is required") class WinTaskPrivateCase(TestCase, LoaderModuleMockMixin): def setup_loader_modules(self): return {win_task: {}} @@ -162,11 +164,14 @@ class WinTaskPrivateCase(TestCase, LoaderModuleMockMixin): prediction = win_task._get_task_state_prediction(state, task_info) self.assertEqual(state, prediction) + +@skipIf(NO_MOCK, NO_MOCK_REASON) +@skipIf(not salt.utils.platform.is_windows(), "Windows is required") class WinTaskTriggersCase(TestCase, LoaderModuleMockMixin): ''' - The test below just checks if the state perdition is correct. - A lot of test might look the same but under hud a lot of checks are happening. - Triggers Test does not test Once or Event + The test below just checks if the state perdition is correct. + A lot of test might look the same but under hud a lot of checks are happening. + Triggers Test does not test Once or Event ''' def setup_loader_modules(self): return {win_task: {}} @@ -175,7 +180,7 @@ class WinTaskTriggersCase(TestCase, LoaderModuleMockMixin): kwargs = {'action_type': 'Execute', 'cmd': 'del /Q /S C:\\\\Temp', 'trigger_type': 'Daily', - 'start_data': '2019-05-14', + 'start_date': '2019-05-14', 'start_time': '01:00 pm', 'days_interval': 101} @@ -211,7 +216,7 @@ class WinTaskTriggersCase(TestCase, LoaderModuleMockMixin): kwargs = {'action_type': 'Execute', 'cmd': 'del /Q /S C:\\\\Temp', 'trigger_type': 'Weekly', - 'start_data': '2019-05-14', + 'start_date': '2019-05-14', 'start_time': '01:00 pm', 'days_of_week': ['Monday', 'Wednesday', 'Friday'], 'weeks_interval': 1} @@ -248,7 +253,7 @@ class WinTaskTriggersCase(TestCase, LoaderModuleMockMixin): kwargs = {'action_type': 'Execute', 'cmd': 'del /Q /S C:\\\\Temp', 'trigger_type': 'Monthly', - 'start_data': '2019-05-14', + 'start_date': '2019-05-14', 'start_time': '01:00 pm', 'months_of_year': ['January', 'July'], 'days_of_month': [6, 16, 26], @@ -285,7 +290,7 @@ class WinTaskTriggersCase(TestCase, LoaderModuleMockMixin): kwargs = {'action_type': 'Execute', 'cmd': 'del /Q /S C:\\\\Temp', 'trigger_type': 'MonthlyDay', - 'start_data': '2019-05-14', + 'start_date': '2019-05-14', 'start_time': '01:00 pm', 'months_of_year': ['January', 'July'], 'weeks_of_month': ['First', 'Third'], @@ -324,7 +329,7 @@ class WinTaskTriggersCase(TestCase, LoaderModuleMockMixin): kwargs = {'action_type': 'Execute', 'cmd': 'del /Q /S C:\\\\Temp', 'trigger_type': 'OnIdle', - 'start_data': '2019-05-14', + 'start_date': '2019-05-14', 'start_time': '01:00 pm'} info = {'triggers': [{'start_date': '2019-05-14', @@ -359,7 +364,7 @@ class WinTaskTriggersCase(TestCase, LoaderModuleMockMixin): kwargs = {'action_type': 'Execute', 'cmd': 'del /Q /S C:\\\\Temp', 'trigger_type': 'OnTaskCreation', - 'start_data': '2019-05-14', + 'start_date': '2019-05-14', 'start_time': '01:00 pm'} info = {'triggers': [{'start_date': '2019-05-14', @@ -395,7 +400,7 @@ class WinTaskTriggersCase(TestCase, LoaderModuleMockMixin): kwargs = {'action_type': 'Execute', 'cmd': 'del /Q /S C:\\\\Temp', 'trigger_type': 'OnBoot', - 'start_data': '2019-05-14', + 'start_date': '2019-05-14', 'start_time': '01:00 pm'} info = {'triggers': [{'start_date': '2019-05-14', @@ -432,7 +437,7 @@ class WinTaskTriggersCase(TestCase, LoaderModuleMockMixin): kwargs = {'action_type': 'Execute', 'cmd': 'del /Q /S C:\\\\Temp', 'trigger_type': 'OnLogon', - 'start_data': '2019-05-14', + 'start_date': '2019-05-14', 'start_time': '01:00 pm'} info = {'triggers': [{'start_date': '2019-05-14', @@ -468,7 +473,7 @@ class WinTaskTriggersCase(TestCase, LoaderModuleMockMixin): kwargs = {'action_type': 'Execute', 'cmd': 'del /Q /S C:\\\\Temp', 'trigger_type': 'OnSessionChange', - 'start_data': '2019-05-14', + 'start_date': '2019-05-14', 'start_time': '01:00 pm', 'state_change': 'SessionUnlock'} @@ -498,4 +503,5 @@ class WinTaskTriggersCase(TestCase, LoaderModuleMockMixin): patch.dict(win_task.__opts__, {"test": True}), \ patch.dict(win_task.__grains__, {'osversion': '7.1'}): ret = win_task.present(name='salt', location='', force=True, **kwargs) + self.assertEqual(ret['result'], True)