Add wua.removed state function

This commit is contained in:
twangboy 2016-10-25 14:52:18 -06:00
parent ddcc53bc30
commit e4964e5eaa
2 changed files with 158 additions and 24 deletions

View File

@ -5,6 +5,7 @@ from __future__ import absolute_import
import logging
# Import salt libs
from salt.ext import six
import salt.utils
import salt.utils.win_update
from salt.exceptions import CommandExecutionError
@ -27,18 +28,24 @@ def __virtual__():
return __virtualname__
def installed(name):
def installed(name, updates=None):
'''
Ensure Microsoft Updates are installed.
Ensure Microsoft Updates are installed. Updates will be downloaded if
needed.
Args:
name (str): Can be the GUID, the KB number, or any part of the
Title of Microsoft update. GUID is the preferred method to ensure you're
installing the correct update. Can also be a list of identifiers.
name (str): The identifier of a single update to install.
.. warning:: Using a partial KB number or a partial Title could result
in more than one update being applied.
updates (list): A list of identifiers for updates to be installed.
Overrides ``name``. Default is None.
.. note:: Identifiers can be the GUID, the KB number, or any part of the
Title of the Microsoft update. GUID's and KB's are the preferred method
to ensure you're installing the correct update.
.. warning:: Using a partial KB number or a partial Title could result in
more than one update being installed.
Returns:
dict: A dictionary containing the results of the update
@ -69,11 +76,11 @@ def installed(name):
- KB3194343
- 28cf1b09-2b1a-458c-9bd1-971d1b26b211
'''
if isinstance(name, list) and len(name) == 0:
return {'name': name,
'changes': {},
'result': True,
'comment': 'No updates provided'}
if isinstance(updates, six.string_types):
updates = [updates]
if not updates:
updates = name
ret = {'name': name,
'changes': {},
@ -83,7 +90,7 @@ def installed(name):
wua = salt.utils.win_update.WindowsUpdateAgent()
# Search for updates
install_list = wua.search(name)
install_list = wua.search(updates)
# No updates found
if install_list.count() == 0:
@ -98,12 +105,16 @@ def installed(name):
# List of updates to install
install = salt.utils.win_update.Updates()
installed_updates = []
for item in install_list.updates:
if not salt.utils.is_true(item.IsInstalled):
install.updates.Add(item)
else:
installed_updates.extend('KB' + kb for kb in item.KBArticleIDs)
if install.count() == 0:
ret['comment'] = 'Updates already installed'
ret['comment'] = 'Updates already installed: '
ret['comment'] += '\n - '.join(installed_updates)
return ret
# Return comment of changes if test.
@ -117,10 +128,10 @@ def installed(name):
return ret
# Download updates
wua.download(download.updates)
wua.download(download)
# Install updates
wua.install(install.updates)
wua.install(install)
# Refresh windows update info
wua.refresh()
@ -130,20 +141,142 @@ def installed(name):
for item in install.list():
if not salt.utils.is_true(post_info[item]['Installed']):
ret['changes']['failed'] = {
item: {'Title': post_info[item]['Title']}
item: {'Title': post_info[item]['Title'][:40] + '...',
'KBs': post_info[item]['KBs']}
}
ret['result'] = False
failed.append(item)
else:
ret['changes']['installed'] = {
item: {'Title': post_info[item]['Title'],
'NeedsReboot': post_info[item]['NeedsReboot']}
item: {'Title': post_info[item]['Title'][:40] + '...',
'NeedsReboot': post_info[item]['NeedsReboot'],
'KBs': post_info[item]['KBs']}
}
succeeded.append(item)
if ret['changes'].get('failed', False):
ret['comment'] = 'Some updates failed'
ret['comment'] = 'Updates failed'
else:
ret['comment'] = 'Updates completed successfully'
ret['comment'] = 'Updates installed successfully'
return ret
def removed(name, updates=None):
'''
Ensure Microsoft Updates are uninstalled.
Args:
name (str): The identifier of a single update to uninstall.
updates (list): A list of identifiers for updates to be removed.
Overrides ``name``. Default is None.
.. note:: Identifiers can be the GUID, the KB number, or any part of the
Title of the Microsoft update. GUID's and KB's are the preferred method
to ensure you're uninstalling the correct update.
.. warning:: Using a partial KB number or a partial Title could result in
more than one update being removed.
Returns:
dict: A dictionary containing the results of the removal
CLI Example:
.. code-block:: yaml
# using a GUID
uninstall_update:
wua.removed:
- name: 28cf1b09-2b1a-458c-9bd1-971d1b26b211
# using a KB
uninstall_update:
wua.removed:
- name: KB3194343
# using the full Title
uninstall_update:
wua.removed:
- name: Security Update for Adobe Flash Player for Windows 10 Version 1607 (for x64-based Systems) (KB3194343)
# Install multiple updates
uninstall_updates:
wua.removed:
- updates:
- KB3194343
- 28cf1b09-2b1a-458c-9bd1-971d1b26b211
'''
if isinstance(updates, six.string_types):
updates = [updates]
if not updates:
updates = name
ret = {'name': name,
'changes': {},
'result': True,
'comment': ''}
wua = salt.utils.win_update.WindowsUpdateAgent()
# Search for updates
updates = wua.search(updates)
# No updates found
if updates.count() == 0:
ret['comment'] = 'No updates found'
return ret
# List of updates to uninstall
uninstall = salt.utils.win_update.Updates()
removed_updates = []
for item in updates.updates:
if salt.utils.is_true(item.IsInstalled):
uninstall.updates.Add(item)
else:
removed_updates.extend('KB' + kb for kb in item.KBArticleIDs)
if uninstall.count() == 0:
ret['comment'] = 'Updates already removed: '
ret['comment'] += '\n - '.join(removed_updates)
return ret
# Return comment of changes if test.
if __opts__['test']:
ret['result'] = None
ret['comment'] = 'Updates will be removed:'
for update in uninstall.updates:
ret['comment'] += '\n'
ret['comment'] += ': '.join(
[update.Identity.UpdateID, update.Title])
return ret
# Install updates
wua.uninstall(uninstall)
# Refresh windows update info
wua.refresh()
post_info = wua.updates().list()
# Verify the installation
for item in uninstall.list():
if salt.utils.is_true(post_info[item]['Installed']):
ret['changes']['failed'] = {
item: {'Title': post_info[item]['Title'][:40] + '...',
'KBs': post_info[item]['KBs']}
}
ret['result'] = False
else:
ret['changes']['removed'] = {
item: {'Title': post_info[item]['Title'][:40] + '...',
'NeedsReboot': post_info[item]['NeedsReboot'],
'KBs': post_info[item]['KBs']}
}
if ret['changes'].get('failed', False):
ret['comment'] = 'Updates failed'
else:
ret['comment'] = 'Updates removed successfully'
return ret

View File

@ -759,7 +759,8 @@ class WindowsUpdateAgent(object):
.. note:: Starting with Windows 10 the Windows Update Agent is unable to
uninstall updates. An ``Uninstall Not Allowed`` error is returned. If
this error is encountered this function will instead attempt to use
``dism.exe`` to perform the uninstallation.
``dism.exe`` to perform the uninstallation. ``dism.exe`` may fail to
to find the KB number for the package. In that case, removal will fail.
Args: