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
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
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
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
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
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
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
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
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
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
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
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
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
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
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 |