class Chef::Resource::WindowsFeatureDism
Public Instance Methods
parse the feature string and add the values to the appropriate array in the strips trailing whitespace characters then split on n number of spaces + | + n number of spaces @return [void]
# File lib/chef/resource/windows_feature_dism.rb, line 197 def add_to_feature_mash(feature_type, feature_string) feature_details = feature_string.strip.split(/\s+[|]\s+/).first # dism on windows 2012+ isn't case sensitive so it's best to compare # lowercase lists so the user input doesn't need to be case sensitive # @todo when we're ready to remove windows 2008R2 the gating here can go away feature_details.downcase! unless node["platform_version"].to_f < 6.2 node.override["dism_features_cache"][feature_type] << feature_details end
Fail if any of the packages are in a removed state @return [void]
# File lib/chef/resource/windows_feature_dism.rb, line 209 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 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["dism_features_cache"]["removed"] raise "The Windows feature#{'s' if removed.count > 1} #{removed.join(',')} #{removed.count > 1 ? 'are' : 'is'} have been 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_dism.rb, line 136 def features_to_delete # the intersection of the features to remove & enabled/disabled features are what needs removing @remove ||= begin all_available = node["dism_features_cache"]["enabled"] + node["dism_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_dism.rb, line 116 def features_to_install @install ||= begin # disabled features are always available to install available_for_install = node["dism_features_cache"]["disabled"] # if the user passes a source then removed features are also available for installation available_for_install.concat(node["dism_features_cache"]["removed"]) if new_resource.source # the intersection of the features to install & disabled/removed(if passing source) features are what needs installing new_resource.feature_name & available_for_install end end
@return [Array] features the user has requested to remove which need removing
# File lib/chef/resource/windows_feature_dism.rb, line 130 def features_to_remove # the intersection of the features to remove & enabled features are what needs removing @remove ||= new_resource.feature_name & node["dism_features_cache"]["enabled"] end
Fail unless we're on windows 8+ / 2012+ where deleting a feature is supported @return [void]
# File lib/chef/resource/windows_feature_dism.rb, line 220 def raise_if_delete_unsupported raise Chef::Exceptions::UnsupportedAction, "#{self} :delete action not support on Windows releases before Windows 8/2012. Cannot continue!" unless node["platform_version"].to_f >= 6.2 end
run dism.exe to get a list of all available features and their state and save that to the node at node.override level. We do this because getting a list of features in dism takes at least a second and this data will be persisted across multiple resource runs which gives us a much faster run when no features actually need to be installed / removed. @return [void]
# File lib/chef/resource/windows_feature_dism.rb, line 167 def reload_cached_dism_data logger.trace("Caching Windows features available via dism.exe.") node.override["dism_features_cache"] = Mash.new node.override["dism_features_cache"]["enabled"] = [] node.override["dism_features_cache"]["disabled"] = [] node.override["dism_features_cache"]["removed"] = [] # Grab raw feature information from dism command line raw_list_of_features = shell_out("dism.exe /Get-Features /Online /Format:Table /English").stdout # Split stdout into an array by windows line ending features_list = raw_list_of_features.split("\r\n") features_list.each do |feature_details_raw| case feature_details_raw when /Payload Removed/ # matches 'Disabled with Payload Removed' add_to_feature_mash("removed", feature_details_raw) when /Enable/ # matches 'Enabled' and 'Enable Pending' aka after reboot add_to_feature_mash("enabled", feature_details_raw) when /Disable/ # matches 'Disabled' and 'Disable Pending' aka after reboot add_to_feature_mash("disabled", feature_details_raw) end end logger.trace("The cache contains\n#{node['dism_features_cache']}") end
# File lib/chef/resource/windows_feature_dism.rb, line 47 def to_lowercase_array(x) x = x.split(/\s*,\s*/) if x.is_a?(String) # split multiple forms of a comma separated list # dism on windows < 2012 is case sensitive so only downcase when on 2012+ # @todo when we're really ready to remove support for Windows 2008 R2 this check can go away node["platform_version"].to_f < 6.2 ? x : x.map(&:downcase) end