Class: Chef::Provider::Package::Cab
- Inherits:
-
Chef::Provider::Package
- Object
- Chef::Provider
- Chef::Provider::Package
- Chef::Provider::Package::Cab
- Includes:
- Mixin::Checksum, Mixin::ShellOut, Mixin::Uris
- Defined in:
- lib/chef/provider/package/cab.rb
Instance Attribute Summary
Attributes inherited from Chef::Provider::Package
Attributes inherited from Chef::Provider
#action, #after_resource, #current_resource, #logger, #new_resource, #run_context
Instance Method Summary collapse
- #cab_file_source ⇒ Object
- #cab_identity_from_cab_file ⇒ Object
- #default_download_cache_path ⇒ Object
- #dism_command(command) ⇒ Object
- #download_source_file ⇒ Object
- #install_package(name, version) ⇒ Object
- #installed_packages ⇒ Object
- #installed_version ⇒ Object
- #load_current_resource ⇒ Object
- #new_cab_identity ⇒ Object
- #package_version ⇒ Object
-
#parse_dism_get_package_info(text) ⇒ Object
returns a hash of package information given the output of dism /get-packageinfo.
-
#parse_dism_get_packages(text) ⇒ Object
returns a hash of package state information given the output of dism /get-packages expected keys: package_identity.
- #remove_package(name, version) ⇒ Object
- #source_resource ⇒ Object
- #split_package_identity(identity) ⇒ Object
Methods included from Mixin::Checksum
#checksum, #checksum_match?, #short_cksum
Methods included from Mixin::Uris
Methods inherited from Chef::Provider::Package
#as_array, #check_resource_semantics!, #define_resource_requirements, #expand_options, #have_any_matching_version?, #initialize, #lock_package, #multipackage_api_adapter, #options, #package_locked, #prepare_for_installation, #preseed_package, #purge_package, #reconfig_package, #removing_package?, #target_version_already_installed?, #unlock_package, #upgrade_package, #version_compare, #version_equals?, #version_requirement_satisfied?
Methods included from Mixin::SubclassDirective
Methods inherited from Chef::Provider
action, action_description, action_descriptions, #action_nothing, #check_resource_semantics!, #cleanup_after_converge, #compile_and_converge_action, #converge_by, #converge_if_changed, #cookbook_name, #define_resource_requirements, #description, #events, include_resource_dsl?, include_resource_dsl_module, #initialize, #introduced, #load_after_resource, #node, #process_resource_requirements, provides, provides?, #recipe_name, #requirements, #resource_collection, #resource_updated?, #run_action, #set_updated_status, supports?, use, use_inline_resources, #validate_required_properties!, #whyrun_mode?, #whyrun_supported?
Methods included from Mixin::Provides
#provided_as, #provides, #provides?
Methods included from Mixin::DescendantsTracker
descendants, #descendants, direct_descendants, #direct_descendants, find_descendants_by_name, #find_descendants_by_name, #inherited, store_inherited
Methods included from Mixin::LazyModuleInclude
#descendants, #include, #included
Methods included from Mixin::PowershellOut
#powershell_out, #powershell_out!
Methods included from Mixin::WindowsArchitectureHelper
#assert_valid_windows_architecture!, #disable_wow64_file_redirection, #forced_32bit_override_required?, #is_i386_process_on_x86_64_windows?, #node_supports_windows_architecture?, #node_windows_architecture, #restore_wow64_file_redirection, #valid_windows_architecture?, #with_os_architecture, #wow64_architecture_override_required?, #wow64_directory
Methods included from DSL::Secret
#default_secret_config, #default_secret_service, #secret, #with_secret_config, #with_secret_service
Methods included from DSL::RenderHelpers
#render_json, #render_toml, #render_yaml
Methods included from DSL::ReaderHelpers
#parse_file, #parse_json, #parse_toml, #parse_yaml
Methods included from DSL::Powershell
Methods included from DSL::RegistryHelper
#registry_data_exists?, #registry_get_subkeys, #registry_get_values, #registry_has_subkeys?, #registry_key_exists?, #registry_value_exists?
Methods included from DSL::ChefVault
#chef_vault, #chef_vault_item, #chef_vault_item_for_environment
Methods included from DSL::DataQuery
#data_bag, #data_bag_item, #search, #tagged?
Methods included from EncryptedDataBagItem::CheckEncrypted
Methods included from DSL::PlatformIntrospection
#older_than_win_2012_or_8?, #platform?, #platform_family?, #value_for_platform, #value_for_platform_family
Methods included from DSL::Recipe
#exec, #have_resource_class_for?, #resource_class_for
Methods included from DSL::Definitions
add_definition, #evaluate_resource_definition, #has_resource_definition?
Methods included from DSL::Resources
add_resource_dsl, remove_resource_dsl
Methods included from DSL::Cheffish
Methods included from DSL::RebootPending
Methods included from DSL::IncludeRecipe
Methods included from Mixin::NotifyingBlock
#notifying_block, #subcontext_block
Methods included from DSL::DeclareResource
#build_resource, #declare_resource, #delete_resource, #delete_resource!, #edit_resource, #edit_resource!, #find_resource, #find_resource!, #resources, #with_run_context
Methods included from DSL::Compliance
#include_input, #include_profile, #include_waiver
Constructor Details
This class inherits a constructor from Chef::Provider::Package
Instance Method Details
#cab_file_source ⇒ Object
[View source]
44 45 46 |
# File 'lib/chef/provider/package/cab.rb', line 44 def cab_file_source @cab_file_source ||= uri_scheme?(new_resource.source) ? download_source_file : new_resource.source end |
#cab_identity_from_cab_file ⇒ Object
[View source]
108 109 110 111 112 |
# File 'lib/chef/provider/package/cab.rb', line 108 def cab_identity_from_cab_file stdout = dism_command("/Get-PackageInfo /PackagePath:\"#{cab_file_source}\"").stdout package_info = parse_dism_get_package_info(stdout) split_package_identity(package_info["package_information"]["package_identity"]) end |
#default_download_cache_path ⇒ Object
[View source]
60 61 62 63 64 65 |
# File 'lib/chef/provider/package/cab.rb', line 60 def default_download_cache_path uri = ::URI.parse(new_resource.source) filename = ::File.basename(::CGI.unescape(uri.path)) file_cache_dir = Chef::FileCache.create_cache_path("package/") Chef::Util::PathHelper.cleanpath("#{file_cache_dir}/#{filename}") end |
#dism_command(command) ⇒ Object
[View source]
75 76 77 78 79 80 81 82 83 84 85 |
# File 'lib/chef/provider/package/cab.rb', line 75 def dism_command(command) with_os_architecture(nil) do result = shell_out("dism.exe /Online /English #{command} /NoRestart", timeout: new_resource.timeout) if result.exitstatus == -2146498530 raise Chef::Exceptions::Package, "The specified package is not applicable to this image." if result.stdout.include?("0x800f081e") result.error! end result end end |
#download_source_file ⇒ Object
[View source]
48 49 50 |
# File 'lib/chef/provider/package/cab.rb', line 48 def download_source_file source_resource.path end |
#install_package(name, version) ⇒ Object
[View source]
67 68 69 |
# File 'lib/chef/provider/package/cab.rb', line 67 def install_package(name, version) dism_command("/Add-Package /PackagePath:\"#{cab_file_source}\"") end |
#installed_packages ⇒ Object
[View source]
178 179 180 181 182 183 184 |
# File 'lib/chef/provider/package/cab.rb', line 178 def installed_packages @packages ||= begin output = dism_command("/Get-Packages").stdout packages = parse_dism_get_packages(output) packages end end |
#installed_version ⇒ Object
[View source]
87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 |
# File 'lib/chef/provider/package/cab.rb', line 87 def installed_version # e.g. Package_for_KB2975719~31bf3856ad364e35~amd64~~6.3.1.8 package = new_cab_identity # Search for just the package name to catch a different version being installed logger.trace("#{new_resource} searching for installed package #{package["name"]}") existing_package_identities = installed_packages.map do |p| split_package_identity(p["package_identity"]) end found_packages = existing_package_identities.select do |existing_package_ident| existing_package_ident["version"] == package["version"].chomp && existing_package_ident["name"] == package["name"] end if found_packages.empty? nil elsif found_packages.length == 1 found_packages.first["version"] else # Presuming this won't happen, otherwise we need to handle it raise Chef::Exceptions::Package, "Found multiple packages installed matching name #{package["name"]}, found: #{found_packages.length} matches" end end |
#load_current_resource ⇒ Object
[View source]
36 37 38 39 40 41 42 |
# File 'lib/chef/provider/package/cab.rb', line 36 def load_current_resource @current_resource = Chef::Resource::CabPackage.new(new_resource.name) current_resource.source(cab_file_source) new_resource.version(package_version) current_resource.version(installed_version) current_resource end |
#new_cab_identity ⇒ Object
[View source]
114 115 116 117 |
# File 'lib/chef/provider/package/cab.rb', line 114 def new_cab_identity logger.trace("#{new_resource} getting product version for package at #{cab_file_source}") @new_cab_identity ||= cab_identity_from_cab_file end |
#package_version ⇒ Object
[View source]
119 120 121 |
# File 'lib/chef/provider/package/cab.rb', line 119 def package_version new_cab_identity["version"].chomp end |
#parse_dism_get_package_info(text) ⇒ Object
returns a hash of package information given the output of dism /get-packageinfo
139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 |
# File 'lib/chef/provider/package/cab.rb', line 139 def parse_dism_get_package_info(text) package_data = {} errors = [] in_section = false section_headers = [ "Package information", "Custom Properties", "Features" ] text.each_line do |line| if line =~ /Error: (.*)/ errors << $1.strip elsif section_headers.any? { |header| line =~ /^(#{header})/ } in_section = $1.downcase.tr(" ", "_") elsif line =~ /(.*) ?: (.*)/ v = $2 # has to be first or the gsub below replaces this variable k = $1.downcase.strip.tr(" ", "_") if in_section package_data[in_section] = {} unless package_data[in_section] package_data[in_section][k] = v else package_data[k] = v end end end unless errors.empty? if errors.include?("0x80070003") || errors.include?("0x80070002") raise Chef::Exceptions::Package, "DISM: The system cannot find the path or file specified." elsif errors.include?("740") raise Chef::Exceptions::Package, "DISM: Error 740: Elevated permissions are required to run DISM." else raise Chef::Exceptions::Package, "Unknown errors encountered parsing DISM output: #{errors}" end end package_data end |
#parse_dism_get_packages(text) ⇒ Object
returns a hash of package state information given the output of dism /get-packages expected keys: package_identity
125 126 127 128 129 130 131 132 133 134 135 136 |
# File 'lib/chef/provider/package/cab.rb', line 125 def parse_dism_get_packages(text) packages = [] text.each_line do |line| key, value = line.split(":") if line.start_with?("Package Identity") next if key.nil? || value.nil? package = {} package[key.downcase.strip.tr(" ", "_")] = value.strip.chomp packages << package end packages end |
#remove_package(name, version) ⇒ Object
[View source]
71 72 73 |
# File 'lib/chef/provider/package/cab.rb', line 71 def remove_package(name, version) dism_command("/Remove-Package /PackagePath:\"#{cab_file_source}\"") end |
#source_resource ⇒ Object
[View source]
52 53 54 55 56 57 58 |
# File 'lib/chef/provider/package/cab.rb', line 52 def source_resource declare_resource(:remote_file, new_resource.name) do path default_download_cache_path source new_resource.source backup false end end |
#split_package_identity(identity) ⇒ Object
[View source]
172 173 174 175 176 |
# File 'lib/chef/provider/package/cab.rb', line 172 def split_package_identity(identity) data = {} data["name"], data["publisher"], data["arch"], data["resource_id"], data["version"] = identity.split("~") data end |