class Chef::Resource::WindowsFeaturePowershell
Public Instance Methods
add the features values to the appropriate array @return [void]
# File lib/chef/resource/windows_feature_powershell.rb, line 239 def add_to_feature_mash(feature_type, feature_details) # add the lowercase feature name to the mash unless we're on < 2012 where they're case sensitive node.override["powershell_features_cache"][feature_type] << (older_than_win_2012_or_8? ? feature_details : feature_details.downcase) end
Fail if any of the packages are in a removed state @return [void]
# File lib/chef/resource/windows_feature_powershell.rb, line 246 def fail_if_removed return if new_resource.source # if someone provides a source then all is well if node["platform_version"].to_f > 6.2 # 2012R2 or later return if registry_key_exists?('HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\Servicing') && registry_value_exists?('HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\Servicing', name: "LocalSourcePath") # if source is defined in the registry, still fine end removed = new_resource.feature_name & node["powershell_features_cache"]["removed"] raise "The Windows feature#{'s' if removed.count > 1} #{removed.join(',')} #{removed.count > 1 ? 'are' : 'is'} removed from the host and cannot be installed." unless removed.empty? end
@return [Array] features the user has requested to delete which need deleting
# File lib/chef/resource/windows_feature_powershell.rb, line 176 def features_to_delete # the intersection of the features to remove & enabled/disabled features are what needs removing @remove ||= begin all_available = node["powershell_features_cache"]["enabled"] + node["powershell_features_cache"]["disabled"] new_resource.feature_name & all_available end end
@return [Array] features the user has requested to install which need installation
# File lib/chef/resource/windows_feature_powershell.rb, line 164 def features_to_install # the intersection of the features to install & disabled features are what needs installing @install ||= new_resource.feature_name & node["powershell_features_cache"]["disabled"] end
@return [Array] features the user has requested to remove which need removing
# File lib/chef/resource/windows_feature_powershell.rb, line 170 def features_to_remove # the intersection of the features to remove & enabled features are what needs removing @remove ||= new_resource.feature_name & node["powershell_features_cache"]["enabled"] end
The appropriate cmdlet to install a windows feature based on windows release @return [String]
# File lib/chef/resource/windows_feature_powershell.rb, line 153 def install_feature_cmdlet older_than_win_2012_or_8? ? "Add-WindowsFeature" : "Install-WindowsFeature" end
fetch the list of available feature names and state in JSON and parse the JSON
# File lib/chef/resource/windows_feature_powershell.rb, line 225 def parsed_feature_list # Grab raw feature information from dism command line # Windows < 2012 doesn't present a state value so we have to check if the feature is installed or not raw_list_of_features = if older_than_win_2012_or_8? # make the older format look like the new format, warts and all powershell_out!('Get-WindowsFeature | Select-Object -Property Name, @{Name="InstallState"; Expression = {If ($_.Installed) { 1 } Else { 0 }}} | ConvertTo-Json -Compress', timeout: new_resource.timeout).stdout else powershell_out!("Get-WindowsFeature | Select-Object -Property Name,InstallState | ConvertTo-Json -Compress", timeout: new_resource.timeout).stdout end Chef::JSONCompat.from_json(raw_list_of_features) end
shellout to determine the actively installed version of powershell we have this same data in ohai, but it doesn't get updated if powershell is installed mid run @return [Integer] the powershell version or 0 for nothing
# File lib/chef/resource/windows_feature_powershell.rb, line 132 def powershell_version cmd = powershell_out("$PSVersionTable.psversion.major") return 1 if cmd.stdout.empty? # PowerShell 1.0 doesn't have a $PSVersionTable Regexp.last_match(1).to_i if cmd.stdout =~ /^(\d+)/ rescue Errno::ENOENT 0 # zero as in nothing is installed end
Fail unless we're on windows 8+ / 2012+ where deleting a feature is supported
# File lib/chef/resource/windows_feature_powershell.rb, line 256 def raise_if_delete_unsupported raise Chef::Exceptions::UnsupportedAction, "#{self} :delete action not supported on Windows releases before Windows 8/2012. Cannot continue!" if older_than_win_2012_or_8? end
raise if we're running powershell less than 3.0 since we need convertto-json check the powershell version via ohai data and if we're < 3.0 also shellout to make sure as a newer version could be installed post ohai run. Yes we're double checking. It's fine. @todo this can go away when we fully remove support for Windows 2008 R2 @raise [RuntimeError] Raise if powershell is < 3.0
# File lib/chef/resource/windows_feature_powershell.rb, line 145 def raise_on_old_powershell # be super defensive about the powershell lang plugin not being there return if node["languages"] && node["languages"]["powershell"] && node["languages"]["powershell"]["version"].to_i >= 3 raise "The windows_feature_powershell resource requires PowerShell 3.0 or later. Please install PowerShell 3.0+ before running this resource." if powershell_version < 3 end
run Get-WindowsFeature to get a list of all available features and their state and save that to the node at node.override level. @return [void]
# File lib/chef/resource/windows_feature_powershell.rb, line 204 def reload_cached_powershell_data Chef::Log.debug("Caching Windows features available via Get-WindowsFeature.") node.override["powershell_features_cache"] = Mash.new node.override["powershell_features_cache"]["enabled"] = [] node.override["powershell_features_cache"]["disabled"] = [] node.override["powershell_features_cache"]["removed"] = [] parsed_feature_list.each do |feature_details_raw| case feature_details_raw["InstallState"] when 5 # matches 'Removed' InstallState add_to_feature_mash("removed", feature_details_raw["Name"]) when 1, 3 # matches 'Installed' or 'InstallPending' states add_to_feature_mash("enabled", feature_details_raw["Name"]) when 0, 2 # matches 'Available' or 'UninstallPending' states add_to_feature_mash("disabled", feature_details_raw["Name"]) end end Chef::Log.debug("The powershell cache contains\n#{node['powershell_features_cache']}") end
The appropriate cmdlet to remove a windows feature based on windows release @return [String]
# File lib/chef/resource/windows_feature_powershell.rb, line 159 def remove_feature_cmdlet older_than_win_2012_or_8? ? "Remove-WindowsFeature" : "Uninstall-WindowsFeature" end
Converts strings of features into an Array. Array objects are lowercased unless we're on < 8/2k12+. @return [Array] array of features
# File lib/chef/resource/windows_feature_powershell.rb, line 55 def to_formatted_array(x) x = x.split(/\s*,\s*/) if x.is_a?(String) # split multiple forms of a comma separated list # feature installs on windows < 8/2012 are case sensitive so only downcase when on 2012+ older_than_win_2012_or_8? ? x : x.map(&:downcase) end