Skip to content

Add feature to disable fact generation shell script #235

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 1 commit into
base: development
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions data/common.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
---
os_patching::fact_cron: true
os_patching::fact_upload: true
os_patching::use_shell_script: true
os_patching::pre_patching_command: NULL
os_patching::block_patching_on_warnings: false
os_patching::reboot_override: 'default'
Expand Down
214 changes: 139 additions & 75 deletions lib/facter/os_patching.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
end
else
Facter.add('os_patching', :type => :aggregate) do

confine { ['FreeBSD', 'Linux', 'windows'].include?(Facter.value(:kernel)) }
require 'time'
now = Time.now.iso8601
Expand All @@ -19,10 +20,21 @@
case Facter.value(:kernel)
when 'FreeBSD', 'Linux'
os_patching_dir = '/var/cache/os_patching'
os_patching_shell_script = '/usr/local/bin/os_patching_fact_generation.sh'
when 'windows'
os_patching_dir = 'C:\ProgramData\os_patching'
end

use_shell_script = File.file?(os_patching_shell_script)
unless use_shell_script
pkgs = `yum -q check-update 2>/dev/null | egrep -v "^[Ss]ecurity:" | grep -oP '^.*?(?= )' | sed 's/Obsoleting.*//'`.split("\n")
sec_pkgs = `yum -q --security check-update 2>/dev/null | egrep -v "^Security:" | grep -oP '^.*?(?= )' | sed 's/Obsoleting.*//'`.split("\n")
held_pkgs = `[ -r /etc/yum/pluginconf.d/versionlock.list ] && awk -F':' '/:/ {print $2}' /etc/yum/pluginconf.d/versionlock.list | sed 's/-[0-9].*//'`.split("\n")

vardir = `puppet config print vardir`.strip
catalog = vardir + "/client_data/catalog/" + `puppet config print certname --section agent`.strip + ".json"
end

chunk(:agent_type) do
data = {}
if Facter.value(:aio_agent_build) =~ /[0-9]/
Expand All @@ -35,26 +47,32 @@

chunk(:updates) do
data = {}
updatelist = []
updatefile = os_patching_dir + '/package_updates'
if File.file?(updatefile)
if (Time.now - File.mtime(updatefile)) / (24 * 3600) > 10
warnings['update_file_time'] = 'Update file has not been updated in 10 days'
end
if use_shell_script
updatelist = []
updatefile = os_patching_dir + '/package_updates'
if File.file?(updatefile)
if (Time.now - File.mtime(updatefile)) / (24 * 3600) > 10
warnings['update_file_time'] = 'Update file has not been updated in 10 days'
end

updates = File.open(updatefile, 'r').read
updates.each_line do |line|
next unless line =~ /[A-Za-z0-9]+/
next if line =~ /^#|^$/
line.sub! 'Title : ', ''
updatelist.push line.chomp
updates = File.open(updatefile, 'r').read
updates.each_line do |line|
next unless line =~ /[A-Za-z0-9]+/
next if line =~ /^#|^$/
line.sub! 'Title : ', ''
updatelist.push line.chomp
end
else
warnings['update_file'] = 'Update file not found, update information invalid'
end
data['package_updates'] = updatelist
data['package_update_count'] = updatelist.count
data
else
warnings['update_file'] = 'Update file not found, update information invalid'
data['package_updates'] = pkgs
data['package_update_count'] = pkgs.count
data
end
data['package_updates'] = updatelist
data['package_update_count'] = updatelist.count
data
end

chunk(:kb_updates) do
Expand All @@ -73,24 +91,30 @@

chunk(:secupdates) do
data = {}
secupdatelist = []
secupdatefile = os_patching_dir + '/security_package_updates'
if File.file?(secupdatefile)
if (Time.now - File.mtime(secupdatefile)) / (24 * 3600) > 10
warnings['sec_update_file_time'] = 'Security update file has not been updated in 10 days'
end
secupdates = File.open(secupdatefile, 'r').read
secupdates.each_line do |line|
next if line.empty?
next if line =~ /^#|^$/
secupdatelist.push line.chomp
if use_shell_script
secupdatelist = []
secupdatefile = os_patching_dir + '/security_package_updates'
if File.file?(secupdatefile)
if (Time.now - File.mtime(secupdatefile)) / (24 * 3600) > 10
warnings['sec_update_file_time'] = 'Security update file has not been updated in 10 days'
end
secupdates = File.open(secupdatefile, 'r').read
secupdates.each_line do |line|
next if line.empty?
next if line =~ /^#|^$/
secupdatelist.push line.chomp
end
else
warnings['security_update_file'] = 'Security update file not found, update information invalid'
end
data['security_package_updates'] = secupdatelist
data['security_package_update_count'] = secupdatelist.count
data
else
warnings['security_update_file'] = 'Security update file not found, update information invalid'
data['security_package_updates'] = sec_pkgs
data['security_package_update_count'] = sec_pkgs.count
data
end
data['security_package_updates'] = secupdatelist
data['security_package_update_count'] = secupdatelist.count
data
end

chunk(:blackouts) do
Expand Down Expand Up @@ -132,24 +156,44 @@
# Are there any pinned/version locked packages?
chunk(:pinned) do
data = {}
pinnedpkgs = []
mismatchpinnedpackagefile = os_patching_dir + '/mismatched_version_locked_packages'
pinnedpackagefile = os_patching_dir + '/os_version_locked_packages'
if File.file?(pinnedpackagefile)
pinnedfile = File.open(pinnedpackagefile, 'r').read.chomp
pinnedfile.each_line do |line|
pinnedpkgs.push line.chomp
if use_shell_script
pinnedpkgs = []
mismatchpinnedpackagefile = os_patching_dir + '/mismatched_version_locked_packages'
pinnedpackagefile = os_patching_dir + '/os_version_locked_packages'
if File.file?(pinnedpackagefile)
pinnedfile = File.open(pinnedpackagefile, 'r').read.chomp
pinnedfile.each_line do |line|
pinnedpkgs.push line.chomp
end
end
end
if File.file?(mismatchpinnedpackagefile) && !File.zero?(mismatchpinnedpackagefile)
warnings['version_specified_but_not_locked_packages'] = []
mismatchfile = File.open(mismatchpinnedpackagefile, 'r').read
mismatchfile.each_line do |line|
warnings['version_specified_but_not_locked_packages'].push line.chomp
if File.file?(mismatchpinnedpackagefile) && !File.zero?(mismatchpinnedpackagefile)
warnings['version_specified_but_not_locked_packages'] = []
mismatchfile = File.open(mismatchpinnedpackagefile, 'r').read
mismatchfile.each_line do |line|
warnings['version_specified_but_not_locked_packages'].push line.chomp
end
end
data['pinned_packages'] = pinnedpkgs
data
else
require 'json'
pinned_list = []

File.open(catalog, 'r') do |file|
json_hash = JSON.load file
json_hash['resources'].select { |r| r['type'] == 'Package' and r['parameters'] and r['parameters']['ensure'] and r['parameters']['ensure'].match /\d.+/ }.each do | m |
pinned_list.push(m['title'])
end
end
data['pinned_packages'] = pinned_list

pinned_list.each do | pkg |
if held_pkgs.include?(pkg)
warnings['version_specified_but_not_locked_packages'].push pkg
end
end
data
end
data['pinned_packages'] = pinnedpkgs
data
end

# History info
Expand Down Expand Up @@ -222,39 +266,59 @@
chunk(:reboot_required) do
data = {}
data['reboots'] = {}
reboot_required_file = os_patching_dir + '/reboot_required'
if File.file?(reboot_required_file)
if (Time.now - File.mtime(reboot_required_file)) / (24 * 3600) > 10
warnings['reboot_required_file_time'] = 'Reboot required file has not been updated in 10 days'

if use_shell_script
reboot_required_file = os_patching_dir + '/reboot_required'
if File.file?(reboot_required_file)
if (Time.now - File.mtime(reboot_required_file)) / (24 * 3600) > 10
warnings['reboot_required_file_time'] = 'Reboot required file has not been updated in 10 days'
end
reboot_required_fh = File.open(reboot_required_file, 'r').to_a
data['reboots']['reboot_required'] = case reboot_required_fh.last
when /^[Tt]rue$/
true
when /^[Ff]alse$/
false
else
''
end
else
data['reboots']['reboot_required'] = 'unknown'
end
app_restart_file = os_patching_dir + '/apps_to_restart'
if File.file?(app_restart_file)
app_restart_fh = File.open(app_restart_file, 'r').to_a
data['reboots']['apps_needing_restart'] = {}
app_restart_fh.each do |line|
line.chomp!
key_value = line.split(' : ')
data['reboots']['apps_needing_restart'][key_value[0]] = key_value[1]
end
data['reboots']['app_restart_required'] = if data['reboots']['apps_needing_restart'].empty?
false
else
true
end
end
reboot_required_fh = File.open(reboot_required_file, 'r').to_a
data['reboots']['reboot_required'] = case reboot_required_fh.last
when /^[Tt]rue$/
true
when /^[Ff]alse$/
false
else
''
end
data
else
data['reboots']['reboot_required'] = 'unknown'
end
app_restart_file = os_patching_dir + '/apps_to_restart'
if File.file?(app_restart_file)
app_restart_fh = File.open(app_restart_file, 'r').to_a
data['reboots']['apps_needing_restart'] = {}
app_restart_fh.each do |line|
line.chomp!
key_value = line.split(' : ')
data['reboots']['apps_needing_restart'][key_value[0]] = key_value[1]
reboot = `/usr/bin/needs-restarting -r 2>/dev/null 1>/dev/null`.split("\n")
unless reboot.empty?
data['reboots']['reboot_required'] = true
else
data['reboots']['reboot_required'] = false
end
data['reboots']['app_restart_required'] = if data['reboots']['apps_needing_restart'].empty?
false
else
true
end

apps_restart = `/usr/bin/needs-restarting 2>/dev/null | grep -v 'Updating Subscription Management repositories' | sed 's/[[:space:]]*$//'`.split("\n")
data['reboots']['apps_needing_restart'] = apps_restart

unless data['reboots']['apps_needing_restart'].empty?
data['reboots']['app_restart_required'] = true
else
data['reboots']['app_restart_required'] = false
end
data
end
data
end

# Should we patch if there are warnings?
Expand Down
63 changes: 41 additions & 22 deletions manifests/init.pp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,15 @@
# @param fact_upload [Boolean]
# Should `puppet fact upload` be run after any changes to the fact cache files?
#
# @param fact_cron [Boolean]
# Feature flag to toggle cron jobs to refresh facts
#
# @param enable_facts_script [Boolean]
# Determines whether a shell script will be used to generate facts for Facter to read from
# This primarily affects facts generated with package management tools
# If `true` a shell script will be used to generate facts
# If `false` facts will be generated on the fly within Facter
#
# @param apt_autoremove [Boolean]
# Should `apt-get autoremove` be run during reboot?
#
Expand Down Expand Up @@ -149,6 +158,8 @@
Boolean $manage_delta_rpm,
Boolean $manage_yum_plugin_security,
Boolean $fact_upload,
Boolean $fact_cron,
Boolean $enable_facts_script,
Boolean $block_patching_on_warnings,
Boolean $apt_autoremove,
Integer[0,23] $windows_update_hour,
Expand Down Expand Up @@ -197,8 +208,8 @@
default => undef
}

$ensure_file = $ensure ? {
'present' => 'file',
$ensure_file = ($ensure == 'present' and $enable_facts_script ) ? {
true => 'file',
default => 'absent',
}

Expand All @@ -220,7 +231,10 @@
ensure => $ensure_file,
mode => $fact_mode,
source => "puppet:///modules/${module_name}/${fact_file}",
notify => Exec[$fact_exec],
}

if $enable_facts_script {
File[$fact_cmd]->Exec[$fact_exec]
}

$autoremove_ensure = $apt_autoremove ? {
Expand Down Expand Up @@ -255,7 +269,10 @@

file { "${cache_dir}/block_patching_on_warnings":
ensure => $block_patching_ensure,
notify => Exec[$fact_exec],
}

if $enable_facts_script {
File["${cache_dir}/block_patching_on_warnings"]->Exec[$fact_exec]
}

$reboot_override_ensure = ($ensure == 'present' and $reboot_override) ? {
Expand Down Expand Up @@ -353,7 +370,7 @@
}
}

if $fact_exec {
if $fact_exec and $enable_facts_script {
exec { $fact_exec:
command => $fact_cmd,
user => $patch_data_owner,
Expand All @@ -366,24 +383,26 @@
}
}

cron { 'Cache patching data':
ensure => $ensure,
command => $fact_cmd,
user => $patch_cron_user,
hour => $patch_cron_hour,
minute => $patch_cron_min,
month => $patch_cron_month,
monthday => $patch_cron_monthday,
weekday => $patch_cron_weekday,
require => File[$fact_cmd],
}
if $fact_cron {
cron { 'Cache patching data':
ensure => $ensure,
command => $fact_cmd,
user => $patch_cron_user,
hour => $patch_cron_hour,
minute => $patch_cron_min,
month => $patch_cron_month,
monthday => $patch_cron_monthday,
weekday => $patch_cron_weekday,
require => File[$fact_cmd],
}

cron { 'Cache patching data at reboot':
ensure => $ensure,
command => $fact_cmd,
user => $patch_cron_user,
special => 'reboot',
require => File[$fact_cmd],
cron { 'Cache patching data at reboot':
ensure => $ensure,
command => $fact_cmd,
user => $patch_cron_user,
special => 'reboot',
require => File[$fact_cmd],
}
}

if $facts['os']['family'] == 'Debian' {
Expand Down
Loading