diff options
author | NimishaS <nimisha.sharad@msystechnologies.com> | 2016-10-07 09:01:00 +0000 |
---|---|---|
committer | NimishaS <nimisha.sharad@msystechnologies.com> | 2016-11-16 10:04:58 +0000 |
commit | 767b66e13f2989693f7adf1b3cebed2e6da6a12d (patch) | |
tree | 449b11fe6c5f1c41263c9287f744bbdc67cc9e86 /lib/chef | |
parent | bedcbd5f52448d24fdd7ab26ab79185c011beee3 (diff) | |
download | chef-767b66e13f2989693f7adf1b3cebed2e6da6a12d.tar.gz |
msu_package resource for Microsoft Update packages
Signed-off-by: NimishaS <nimisha.sharad@msystechnologies.com>
Signed-off-by: NimishaS <nimisha.sharad@msystechnologies.com>
Diffstat (limited to 'lib/chef')
-rw-r--r-- | lib/chef/provider/package/msu.rb | 163 | ||||
-rw-r--r-- | lib/chef/providers.rb | 1 | ||||
-rw-r--r-- | lib/chef/resource/msu_package.rb | 47 | ||||
-rw-r--r-- | lib/chef/resources.rb | 1 |
4 files changed, 212 insertions, 0 deletions
diff --git a/lib/chef/provider/package/msu.rb b/lib/chef/provider/package/msu.rb new file mode 100644 index 0000000000..e1f0d53a9c --- /dev/null +++ b/lib/chef/provider/package/msu.rb @@ -0,0 +1,163 @@ +# +# Author:: Nimisha Sharad (<nimisha.sharad@msystechnologies.com>) +# Copyright:: Copyright 2015-2016, Chef Software, Inc. +# License:: Apache License, Version 2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +# msu_package leverages cab_package +# The contents of msu file are extracted, which contains one or more cab files. +# The extracted cab files are installed using Chef::Resource::Package::CabPackage +# Reference: https://support.microsoft.com/en-in/kb/934307 +require "chef/provider/package" +require "chef/resource/msu_package" +require "chef/mixin/shell_out" +require "chef/provider/package/cab" +require "chef/util/path_helper" +require "chef/mixin/uris" +require "chef/mixin/checksum" + +class Chef + class Provider + class Package + class Msu < Chef::Provider::Package + use_inline_resources + include Chef::Mixin::ShellOut + include Chef::Mixin::Uris + include Chef::Mixin::Checksum + + provides :msu_package, os: "windows" + + def load_current_resource + @current_resource = Chef::Resource::MsuPackage.new(new_resource.name) + + # download file if source is a url + msu_file = uri_scheme?(new_resource.source) ? download_source_file : @new_resource.source + + # temp directory where the contents of msu file get extracted + @temp_directory = Dir.mktmpdir("chef") + extract_msu_contents(msu_file, @temp_directory) + @cab_files = read_cab_files_from_xml(@temp_directory) + + unless @cab_files.empty? + current_resource.version(get_current_versions) + else + raise Chef::Exceptions::Package, "Corrupt MSU package: MSU package XML does not contain any cab file" + end + current_resource + end + + def get_current_versions + @cab_files.map do |cabfile| + cab_pkg = get_cab_package(cabfile) + cab_pkg.installed_version + end + end + + def get_candidate_versions + @cab_files.map do |cabfile| + cab_pkg = get_cab_package(cabfile) + cab_pkg.package_version + end + end + + def candidate_version + @candidate_version ||= get_candidate_versions + end + + def get_cab_package(cab_file) + cab_resource = @new_resource + cab_resource.source = cab_file + cab_pkg = Chef::Provider::Package::Cab.new(cab_resource, nil) + end + + def download_source_file + source_resource.run_action(:create) + Chef::Log.debug("#{new_resource} fetched source file to #{source_resource.path}") + source_resource.path + end + + def source_resource + @source_resource ||= declare_resource(:remote_file, new_resource.name) do + path default_download_cache_path + source new_resource.source + checksum new_resource.checksum + backup false + end + end + + 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 + + def install_package(name, version) + #use cab_package resource to install the extracted cab packages + @cab_files.each do |cab_file| + declare_resource(:cab_package, @new_resource.name) do + source cab_file + action :install + end + end + end + + def remove_package(name, version) + #use cab_package provider to remove the extracted cab packages + @cab_files.each do |cab_file| + declare_resource(:cab_package, @new_resource.name) do + source cab_file + action :remove + end + end + end + + def extract_msu_contents(msu_file, destination) + shellout = Mixlib::ShellOut.new("expand -f:* #{msu_file} #{destination}", { :timeout => @new_resource.timeout }) + with_os_architecture(nil) do + shellout.run_command + end + end + + # msu package can contain multiple cab files + # Reading cab files from xml to ensure the order of installation in case of multiple cab files + def read_cab_files_from_xml(msu_dir) + # get the file with .xml extension + xml_files = Dir.glob("#{msu_dir}/*.xml") + cab_files = [] + + if xml_files.empty? + raise Chef::Exceptions::Package, "Corrupt MSU package: MSU package doesn't contain any xml file" + else + # msu package contains only single xml file. So using xml_files.first is sufficient + doc = ::File.open("#{xml_files.first}") { |f| REXML::Document.new f } + locations = doc.elements.each("unattend/servicing/package/source") { |element| puts element.attributes["location"] } + locations.each do |loc| + cab_files << msu_dir + "/" + loc.attribute("location").value.split("\\")[1] + end + + cab_files + end + cab_files + end + + def cleanup_after_converge + # delete the temp directory where the contents of msu file are extracted + FileUtils.rm_rf(@temp_directory) if Dir.exists?(@temp_directory) + end + end + end + end +end diff --git a/lib/chef/providers.rb b/lib/chef/providers.rb index 8067643bab..ebb4c45ae8 100644 --- a/lib/chef/providers.rb +++ b/lib/chef/providers.rb @@ -85,6 +85,7 @@ require "chef/provider/package/smartos" require "chef/provider/package/aix" require "chef/provider/package/cab" require "chef/provider/package/powershell" +require "chef/provider/package/msu" require "chef/provider/service/arch" require "chef/provider/service/freebsd" diff --git a/lib/chef/resource/msu_package.rb b/lib/chef/resource/msu_package.rb new file mode 100644 index 0000000000..753992c185 --- /dev/null +++ b/lib/chef/resource/msu_package.rb @@ -0,0 +1,47 @@ +# +# Author:: Nimisha Sharad (<nimisha.sharad@msystechnologies.com>) +# Copyright:: Copyright 2008-2016, Chef Software, Inc. +# License:: Apache License, Version 2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +require "chef/resource/package" +require "chef/mixin/uris" + +class Chef + class Resource + class MsuPackage < Chef::Resource::Package + include Chef::Mixin::Uris + + provides :msu_package, os: "windows" + + allowed_actions :install, :remove + + def initialize(name, run_context = nil) + super + @resource_name = :msu_package + @source = name + @action = :install + end + + property :source, String, + coerce: (proc do |s| + unless s.nil? + uri_scheme?(s) ? s : Chef::Util::PathHelper.canonical_path(s, false) + end + end) + property :checksum, String, desired_state: false + end + end +end diff --git a/lib/chef/resources.rb b/lib/chef/resources.rb index 6634a298d1..de421839e0 100644 --- a/lib/chef/resources.rb +++ b/lib/chef/resources.rb @@ -97,3 +97,4 @@ require "chef/resource/bff_package" require "chef/resource/zypper_package" require "chef/resource/cab_package" require "chef/resource/powershell_package" +require "chef/resource/msu_package" |