diff options
author | Jay Mundrawala <jdmundrawala@gmail.com> | 2015-04-30 15:00:12 -0700 |
---|---|---|
committer | Jay Mundrawala <jdmundrawala@gmail.com> | 2015-05-15 07:04:16 -0700 |
commit | f2a512109482caeb7a553f2002cb18467da30136 (patch) | |
tree | 29d14f43f2e4ac4be9fcfc57d45cb4a89da150f0 | |
parent | b086721ca70750277c407fd0cc573a08f076649f (diff) | |
download | chef-f2a512109482caeb7a553f2002cb18467da30136.tar.gz |
Modify windows package provider to allow url
-rw-r--r-- | lib/chef/provider/package/windows.rb | 82 | ||||
-rw-r--r-- | lib/chef/resource/windows_package.rb | 20 | ||||
-rw-r--r-- | spec/unit/provider/package/windows_spec.rb | 6 |
3 files changed, 97 insertions, 11 deletions
diff --git a/lib/chef/provider/package/windows.rb b/lib/chef/provider/package/windows.rb index 143d82f111..e944352add 100644 --- a/lib/chef/provider/package/windows.rb +++ b/lib/chef/provider/package/windows.rb @@ -19,6 +19,7 @@ require 'chef/resource/windows_package' require 'chef/provider/package' require 'chef/util/path_helper' +require 'uri' class Chef class Provider @@ -36,19 +37,23 @@ class Chef # load_current_resource is run in Chef::Provider#run_action when not in whyrun_mode? def load_current_resource - @new_resource.source(Chef::Util::PathHelper.validate_path(@new_resource.source)) - @current_resource = Chef::Resource::WindowsPackage.new(@new_resource.name) - @current_resource.version(package_provider.installed_version) - @new_resource.version(package_provider.package_version) - @current_resource + if should_download? + Chef::Log.debug("We do not know the version of #{new_resource.source} because the file is not downloaded") + current_resource.version(:unknown.to_s) + else + current_resource.version(package_provider.installed_version) + new_resource.version(package_provider.package_version) + end + + current_resource end def package_provider @package_provider ||= begin case installer_type when :msi - Chef::Provider::Package::Windows::MSI.new(@new_resource) + Chef::Provider::Package::Windows::MSI.new(resource_for_provider) else raise "Unable to find a Chef::Provider::Package::Windows provider for installer_type '#{installer_type}'" end @@ -71,6 +76,14 @@ class Chef end end + def action_install + if should_download? + download_source_file + load_current_resource + end + super + end + # Chef::Provider::Package action_install + action_remove call install_package + remove_package # Pass those calls to the correct sub-provider def install_package(name, version) @@ -80,6 +93,63 @@ class Chef def remove_package(name, version) package_provider.remove_package(name, version) end + + # @return [Array] new_version(s) as an array + def new_version_array + # Because the one in the parent caches things + [new_resource.version] + end + + private + + def should_download? + is_url?(new_resource.source) && !::File.exists?(source_location) + end + + def resource_for_provider + @resource_for_provider = Chef::Resource::WindowsPackage.new(new_resource.name).tap do |r| + r.source(Chef::Util::PathHelper.validate_path(source_location)) + r.timeout(new_resource.timeout) + r.returns(new_resource.returns) + r.options(new_resource.options) + end + end + + def download_source_file + source_resource.run_action(:create) + Chef::Log.debug("#{@new_resource} fetched source file to #{source_resource.path}") + end + + def source_resource + @remote_file ||= Chef::Resource::RemoteFile.new(source_location, run_context).tap do |r| + r.source(new_resource.source) + r.backup(false) + end + end + + def source_location + @source_location ||= begin + if is_url?(new_resource.source) + 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}") + else + Chef::Util::PathHelper.cleanpath(new_resource.source) + end + end + end + + def is_url?(source) + begin + scheme = URI.split(source).first + return false unless scheme + %w(http https ftp file).include?(scheme.downcase) + rescue URI::InvalidURIError + return false + end + end + end end end diff --git a/lib/chef/resource/windows_package.rb b/lib/chef/resource/windows_package.rb index 16cfcf865e..de4f2573d4 100644 --- a/lib/chef/resource/windows_package.rb +++ b/lib/chef/resource/windows_package.rb @@ -69,10 +69,26 @@ class Chef @source else raise ArgumentError, "Bad type for WindowsPackage resource, use a String" unless arg.is_a?(String) - Chef::Log.debug("#{package_name}: sanitizing source path '#{arg}'") - @source = ::File.absolute_path(arg).gsub(::File::SEPARATOR, ::File::ALT_SEPARATOR) + if is_url?(arg) + @source = arg + else + @source = ::File.absolute_path(arg).gsub(::File::SEPARATOR, ::File::ALT_SEPARATOR) + end end end + + private + + def is_url?(source) + begin + scheme = URI.split(source).first + return false unless scheme + %w(http https ftp file).include?(scheme.downcase) + rescue URI::InvalidURIError + return false + end + end + end end end diff --git a/spec/unit/provider/package/windows_spec.rb b/spec/unit/provider/package/windows_spec.rb index d402113d72..d1a5a98140 100644 --- a/spec/unit/provider/package/windows_spec.rb +++ b/spec/unit/provider/package/windows_spec.rb @@ -47,14 +47,14 @@ describe Chef::Provider::Package::Windows, :windows_only do provider.load_current_resource expect(provider.new_resource.version).to eql("2.0") end + end + describe "package_provider" do it "checks that the source path is valid" do expect(Chef::Util::PathHelper).to receive(:validate_path) - provider.load_current_resource + provider.package_provider end - end - describe "package_provider" do it "sets the package provider to MSI if the the installer type is :msi" do allow(provider).to receive(:installer_type).and_return(:msi) expect(provider.package_provider).to be_a(Chef::Provider::Package::Windows::MSI) |