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, #current_resource, #logger, #new_resource, #recipe_name, #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
Methods included from Mixin::Uris
Methods included from Mixin::ShellOut
apply_default_env, maybe_add_timeout, #shell_out, #shell_out!
Methods inherited from Chef::Provider::Package
#action_lock, #action_unlock, #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_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, #node, #process_resource_requirements, provides, provides?, #requirements, #resource_collection, #resource_updated?, #run_action, #set_updated_status, supports?, use_inline_resources, #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 Mixin::PowershellExec
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::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 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
Constructor Details
This class inherits a constructor from Chef::Provider::Package
Instance Method Details
#cab_file_source ⇒ Object
43 44 45 |
# File 'lib/chef/provider/package/cab.rb', line 43 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
109 110 111 112 113 |
# File 'lib/chef/provider/package/cab.rb', line 109 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
61 62 63 64 65 66 |
# File 'lib/chef/provider/package/cab.rb', line 61 def default_download_cache_path uri = ::URI.parse(new_resource.source) filename = ::File.basename(::URI.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
76 77 78 79 80 81 82 83 84 85 86 |
# File 'lib/chef/provider/package/cab.rb', line 76 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
47 48 49 50 51 |
# File 'lib/chef/provider/package/cab.rb', line 47 def download_source_file source_resource.run_action(:create) logger.trace("#{new_resource} fetched source file to #{source_resource.path}") source_resource.path end |
#install_package(name, version) ⇒ Object
68 69 70 |
# File 'lib/chef/provider/package/cab.rb', line 68 def install_package(name, version) dism_command("/Add-Package /PackagePath:\"#{cab_file_source}\"") end |
#installed_packages ⇒ Object
179 180 181 182 183 184 185 |
# File 'lib/chef/provider/package/cab.rb', line 179 def installed_packages @packages ||= begin output = dism_command("/Get-Packages").stdout packages = parse_dism_get_packages(output) packages end end |
#installed_version ⇒ Object
88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 |
# File 'lib/chef/provider/package/cab.rb', line 88 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["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
35 36 37 38 39 40 41 |
# File 'lib/chef/provider/package/cab.rb', line 35 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
115 116 117 118 |
# File 'lib/chef/provider/package/cab.rb', line 115 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
120 121 122 |
# File 'lib/chef/provider/package/cab.rb', line 120 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
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 171 |
# File 'lib/chef/provider/package/cab.rb', line 140 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
126 127 128 129 130 131 132 133 134 135 136 137 |
# File 'lib/chef/provider/package/cab.rb', line 126 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
72 73 74 |
# File 'lib/chef/provider/package/cab.rb', line 72 def remove_package(name, version) dism_command("/Remove-Package /PackagePath:\"#{cab_file_source}\"") end |
#source_resource ⇒ Object
53 54 55 56 57 58 59 |
# File 'lib/chef/provider/package/cab.rb', line 53 def source_resource @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
173 174 175 176 177 |
# File 'lib/chef/provider/package/cab.rb', line 173 def split_package_identity(identity) data = {} data["name"], data["publisher"], data["arch"], data["resource_id"], data["version"] = identity.split("~") data end |