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
- #define_resource_requirements ⇒ 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!, #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, #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
53 54 55 |
# File 'lib/chef/provider/package/cab.rb', line 53 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
117 118 119 120 121 |
# File 'lib/chef/provider/package/cab.rb', line 117 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
69 70 71 72 73 74 |
# File 'lib/chef/provider/package/cab.rb', line 69 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 |
#define_resource_requirements ⇒ Object
44 45 46 47 48 49 50 51 |
# File 'lib/chef/provider/package/cab.rb', line 44 def define_resource_requirements super requirements.assert(:all_actions) do |a| a.assertion { !new_resource.environment } a. Chef::Exceptions::Package, "The environment property is not supported for package resources on this platform" end end |
#dism_command(command) ⇒ Object
84 85 86 87 88 89 90 91 92 93 94 |
# File 'lib/chef/provider/package/cab.rb', line 84 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
57 58 59 |
# File 'lib/chef/provider/package/cab.rb', line 57 def download_source_file source_resource.path end |
#install_package(name, version) ⇒ Object
76 77 78 |
# File 'lib/chef/provider/package/cab.rb', line 76 def install_package(name, version) dism_command("/Add-Package /PackagePath:\"#{cab_file_source}\"") end |
#installed_packages ⇒ Object
187 188 189 190 191 192 193 |
# File 'lib/chef/provider/package/cab.rb', line 187 def installed_packages @packages ||= begin output = dism_command("/Get-Packages").stdout packages = parse_dism_get_packages(output) packages end end |
#installed_version ⇒ Object
96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 |
# File 'lib/chef/provider/package/cab.rb', line 96 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
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
123 124 125 126 |
# File 'lib/chef/provider/package/cab.rb', line 123 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
128 129 130 |
# File 'lib/chef/provider/package/cab.rb', line 128 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
148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 |
# File 'lib/chef/provider/package/cab.rb', line 148 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
134 135 136 137 138 139 140 141 142 143 144 145 |
# File 'lib/chef/provider/package/cab.rb', line 134 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
80 81 82 |
# File 'lib/chef/provider/package/cab.rb', line 80 def remove_package(name, version) dism_command("/Remove-Package /PackagePath:\"#{cab_file_source}\"") end |
#source_resource ⇒ Object
61 62 63 64 65 66 67 |
# File 'lib/chef/provider/package/cab.rb', line 61 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
181 182 183 184 185 |
# File 'lib/chef/provider/package/cab.rb', line 181 def split_package_identity(identity) data = {} data["name"], data["publisher"], data["arch"], data["resource_id"], data["version"] = identity.split("~") data end |