Skip to content

Instantly share code, notes, and snippets.

@kreeuwijk
Last active July 17, 2020 13:39
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kreeuwijk/1647a823739257fdcf8a7ff0188f26d7 to your computer and use it in GitHub Desktop.
Save kreeuwijk/1647a823739257fdcf8a7ff0188f26d7 to your computer and use it in GitHub Desktop.
#Provides automated patch management
class profile::patch_mgmt_win (
Array $blacklist = [],
Array $whitelist = [],
Optional[Hash] $patch_window = {
range => '01:00 - 04:00',
weekday => 'Sunday',
repeat => 3
}
) {
include os_patching
class { 'wsus_client':
server_url => 'http://wsus.example.com:8530',
target_group => 'AutoApproval',
enable_status_server => true,
auto_install_minor_updates => false,
auto_update_option => 'NotifyOnly',
detection_frequency_hours => 22
}
if $facts['os_patching'] {
$updatescan = $facts['os_patching']['missing_update_kbs']
}
else {
$updatescan = []
}
if $whitelist.count > 0 {
$updates = $updatescan.filter |$item| { $item in $whitelist }
} elsif $blacklist.count > 0 {
$updates = $updatescan.filter |$item| { !($item in $blacklist) }
} else {
$updates = $updatescan
}
schedule { 'patch_window':
* => $patch_window
}
if $facts['os_patching']['reboots']['reboot_required'] == true {
Windows_updates::Kb {
require => Reboot['patch_window_reboot']
}
notify { 'Reboot pending, rebooting node...':
schedule => 'patch_window',
notify => Reboot['patch_window_reboot']
}
}
reboot { 'patch_window_reboot':
apply => 'finished',
schedule => 'patch_window'
}
$updates.each | $kb | {
windows_updates::kb { $kb:
ensure => 'present',
maintwindow => 'patch_window'
}
}
}
@kreeuwijk
Copy link
Author

kreeuwijk commented Jul 16, 2020

@mike406 can you try the updated 0.2.0 version of the module? This now correctly handles pending reboots, and provides additional capabilities around pre/post patching commands, and pre-reboot commands.

@mike406
Copy link

mike406 commented Jul 16, 2020

This appears to be working!

Edit - a follow up:
I ran the patching process on a couple hundred Windows PC's at our various remote offices and noticed the following behavior for computers that had the "reboot_required = True" fact. Some computers repeatedly reboot - this is because the os_patching scheduled task that runs after reboot is not able to update the fact quick enough before the puppet agent run starts, which also happens at boot.

So these two essentially fight each other for who finishes first. For computers that have slower link speeds or are at remote locations, there is a high chance the os_patching fact for the reboot_required will not update before the puppet agent run starts, causing multiple pending reboots to fire. A classic "stale data" problem...To get around this one could set the puppet service on Windows machines to be Automatic (Delayed) instead of Automatic, but there is still a chance it could still be stale data even then.

https://forge.puppet.com/puppetlabs/reboot#complete-any-pending-reboots-before-installing-a-package
I think using the reboot module's "pending" feature may provide a more accurate way to check for a pending reboot than to check the os_patching fact that may or may not be stale data. For my environment I think I am going to backport some of your new code and combine it with your original example, but utilize the reboot module itself to check for pending reboots.

This is how I have my reboots set up. I'm still new to Puppet so I hope I did it right. My goal is to check for pending reboots with the require, and then notify as well at the end of the patching run to reboot the computer:

        reboot { 'pending_reboot':
                when    => 'pending',
                schedule    => 'patch_window'
        }

        reboot { 'reboot_after_updates':
                apply           => 'finished',
                schedule        => 'patch_window'
        }

        $updates.each | $kb | {
                windows_updates::kb { $kb:
                        ensure          => 'present',
                        maintwindow     => 'patch_window',
                        require         => Reboot['pending_reboot'],
                        notify          => Reboot['reboot_after_updates']
                }
        }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment