summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTim Smith <tsmith@chef.io>2019-05-07 10:41:08 -0700
committerGitHub <noreply@github.com>2019-05-07 10:41:08 -0700
commitb2c16e5438b43f0154d0cd61cea3cc6ff00433b9 (patch)
tree84e7fa1a53126927330e71c6865b7b2e2a60817d
parent3f39c7eb9a5f0eadf768cc92630744f66242dfa3 (diff)
parent38c62c0c14794045154d886ffaf6f27778e659dd (diff)
downloadchef-b2c16e5438b43f0154d0cd61cea3cc6ff00433b9.tar.gz
Merge pull request #8307 from MsysTechnologiesllc/Kapil/MSYS-986_Move_response_file_and_response_file_variables_out_of_base_package_resource
package: move response_file and response_file_variables out of base package resource
-rw-r--r--lib/chef/provider/package.rb91
-rw-r--r--lib/chef/provider/package/apt.rb19
-rw-r--r--lib/chef/provider/package/deb.rb131
-rw-r--r--lib/chef/provider/package/dpkg.rb18
-rw-r--r--lib/chef/resource/apt_package.rb8
-rw-r--r--lib/chef/resource/dpkg_package.rb8
-rw-r--r--lib/chef/resource/package.rb8
-rw-r--r--spec/data/cookbooks/irssi/files/default/irssi.response2
-rw-r--r--spec/data/cookbooks/wget/files/default/wget.response2
-rw-r--r--spec/support/shared/unit/provider/package/package_shared.rb95
-rw-r--r--spec/unit/cookbook_loader_spec.rb2
-rw-r--r--spec/unit/provider/package/apt_spec.rb30
-rw-r--r--spec/unit/provider/package/deb_spec.rb135
-rw-r--r--spec/unit/provider/package/dpkg_spec.rb29
-rw-r--r--spec/unit/provider/package_spec.rb168
-rw-r--r--spec/unit/resource/apt_package_spec.rb10
-rw-r--r--spec/unit/resource/dpkg_package_spec.rb10
-rw-r--r--spec/unit/resource/package_spec.rb10
18 files changed, 467 insertions, 309 deletions
diff --git a/lib/chef/provider/package.rb b/lib/chef/provider/package.rb
index 44d7fed6f4..d0fb216604 100644
--- a/lib/chef/provider/package.rb
+++ b/lib/chef/provider/package.rb
@@ -88,14 +88,7 @@ class Chef
return
end
- # @todo: move the preseed code out of the base class (and complete the fix for Array of preseeds? ugh...)
- if new_resource.response_file
- if preseed_file = get_preseed_file(package_names_for_targets, versions_for_targets)
- converge_by("preseed package #{package_names_for_targets}") do
- preseed_package(preseed_file)
- end
- end
- end
+ prepare_for_installation
converge_by(install_description) do
multipackage_api_adapter(package_names_for_targets, versions_for_targets) do |name, version|
@@ -194,31 +187,6 @@ class Chef
end
end
- action :reconfig do
- if current_resource.version.nil?
- logger.trace("#{new_resource} is NOT installed - nothing to do")
- return
- end
-
- unless new_resource.response_file
- logger.trace("#{new_resource} no response_file provided - nothing to do")
- return
- end
-
- if preseed_file = get_preseed_file(new_resource.package_name, current_resource.version)
- converge_by("reconfigure package #{new_resource.package_name}") do
- preseed_package(preseed_file)
- multipackage_api_adapter(new_resource.package_name, current_resource.version) do |name, version|
- reconfig_package(name, version)
-
- end
- logger.info("#{new_resource} reconfigured")
- end
- else
- logger.trace("#{new_resource} preseeding has not changed - nothing to do")
- end
- end
-
def action_lock
packages_locked = if respond_to?(:packages_all_locked?, true)
packages_all_locked?(Array(new_resource.package_name), Array(new_resource.version))
@@ -262,6 +230,10 @@ class Chef
raise Chef::Exceptions::UnsupportedAction, "#{self} has no way to detect if package is locked"
end
+ # Subclasses will override this to a method and provide a preseed file path
+ def prepare_for_installation
+ end
+
# @todo use composition rather than inheritance
def multipackage_api_adapter(name, version)
@@ -292,7 +264,7 @@ class Chef
raise Chef::Exceptions::UnsupportedAction, "#{self} does not support pre-seeding package install/upgrade instructions"
end
- def reconfig_package(name, version)
+ def reconfig_package(name)
raise( Chef::Exceptions::UnsupportedAction, "#{self} does not support :reconfig" )
end
@@ -384,46 +356,6 @@ class Chef
target_version_already_installed?(current_version, new_version)
end
- # @todo: extract apt/dpkg specific preseeding to a helper class
- def get_preseed_file(name, version)
- resource = preseed_resource(name, version)
- resource.run_action(:create)
- logger.trace("#{new_resource} fetched preseed file to #{resource.path}")
-
- if resource.updated_by_last_action?
- resource.path
- else
- false
- end
- end
-
- # @todo: extract apt/dpkg specific preseeding to a helper class
- def preseed_resource(name, version)
- # A directory in our cache to store this cookbook's preseed files in
- file_cache_dir = Chef::FileCache.create_cache_path("preseed/#{new_resource.cookbook_name}")
- # The full path where the preseed file will be stored
- cache_seed_to = "#{file_cache_dir}/#{name}-#{version}.seed"
-
- logger.trace("#{new_resource} fetching preseed file to #{cache_seed_to}")
-
- if template_available?(new_resource.response_file)
- logger.trace("#{new_resource} fetching preseed file via Template")
- remote_file = Chef::Resource::Template.new(cache_seed_to, run_context)
- remote_file.variables(new_resource.response_file_variables)
- elsif cookbook_file_available?(new_resource.response_file)
- logger.trace("#{new_resource} fetching preseed file via cookbook_file")
- remote_file = Chef::Resource::CookbookFile.new(cache_seed_to, run_context)
- else
- message = "No template or cookbook file found for response file #{new_resource.response_file}"
- raise Chef::Exceptions::FileNotFound, message
- end
-
- remote_file.cookbook_name = new_resource.cookbook_name
- remote_file.source(new_resource.response_file)
- remote_file.backup(false)
- remote_file
- end
-
# helper method used by subclasses
#
def as_array(thing)
@@ -479,7 +411,6 @@ class Chef
@target_version_array ||=
begin
target_version_array = []
-
each_package do |package_name, new_version, current_version, candidate_version|
case action
when :upgrade
@@ -657,16 +588,6 @@ class Chef
end
end
- # @todo: extract apt/dpkg specific preseeding to a helper class
- def template_available?(path)
- run_context.has_template_in_cookbook?(new_resource.cookbook_name, path)
- end
-
- # @todo: extract apt/dpkg specific preseeding to a helper class
- def cookbook_file_available?(path)
- run_context.has_cookbook_file_in_cookbook?(new_resource.cookbook_name, path)
- end
-
def allow_downgrade
if new_resource.respond_to?("allow_downgrade")
new_resource.allow_downgrade
diff --git a/lib/chef/provider/package/apt.rb b/lib/chef/provider/package/apt.rb
index dfc7e602dd..75c7935805 100644
--- a/lib/chef/provider/package/apt.rb
+++ b/lib/chef/provider/package/apt.rb
@@ -17,12 +17,14 @@
#
require "chef/provider/package"
+require "chef/provider/package/deb"
require "chef/resource/apt_package"
class Chef
class Provider
class Package
class Apt < Chef::Provider::Package
+ include Chef::Provider::Package::Deb
use_multipackage_api
provides :package, platform_family: "debian"
@@ -114,16 +116,6 @@ class Chef
run_noninteractive("apt-get", "-q", "-y", options, "purge", package_name)
end
- def preseed_package(preseed_file)
- logger.info("#{new_resource} pre-seeding package installation instructions")
- run_noninteractive("debconf-set-selections", preseed_file)
- end
-
- def reconfig_package(name, version)
- logger.info("#{new_resource} reconfiguring")
- run_noninteractive("dpkg-reconfigure", name)
- end
-
def lock_package(name, version)
run_noninteractive("apt-mark", options, "hold", name)
end
@@ -161,13 +153,6 @@ class Chef
end
end
- # Runs command via shell_out with magic environment to disable
- # interactive prompts. Command is run with default localization rather
- # than forcing locale to "C", so command output may not be stable.
- def run_noninteractive(*args)
- shell_out!(*args, env: { "DEBIAN_FRONTEND" => "noninteractive" })
- end
-
def default_release_options
# Use apt::Default-Release option only if provider supports it
if new_resource.respond_to?(:default_release) && new_resource.default_release
diff --git a/lib/chef/provider/package/deb.rb b/lib/chef/provider/package/deb.rb
new file mode 100644
index 0000000000..439127e18a
--- /dev/null
+++ b/lib/chef/provider/package/deb.rb
@@ -0,0 +1,131 @@
+#
+# Author:: Kapil Chouhan (<kapil.chouhan@msystechnologies.com>)
+# Copyright:: Copyright 2010-2019, 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/provider/package"
+
+class Chef
+ class Provider
+ class Package
+ module Deb
+ def self.included(base)
+ base.class_eval do
+ use_multipackage_api
+
+ action :reconfig do
+ if current_resource.version.nil?
+ logger.trace("#{new_resource} is NOT installed - nothing to do")
+ return
+ end
+
+ unless new_resource.response_file
+ logger.trace("#{new_resource} no response_file provided - nothing to do")
+ return
+ end
+
+ if preseed_file = get_preseed_file(new_resource.package_name, current_resource.version)
+ converge_by("reconfigure package #{new_resource.package_name}") do
+ preseed_package(preseed_file)
+ multipackage_api_adapter(new_resource.package_name, current_resource.version) do |name, _version|
+ reconfig_package(name)
+ end
+ logger.info("#{new_resource} reconfigured")
+ end
+ else
+ logger.trace("#{new_resource} preseeding has not changed - nothing to do")
+ end
+ end
+
+ # This method is used for getting preseed file
+ # it will return preseed file path or false if response_file is present
+ def prepare_for_installation
+ if new_resource.response_file && preseed_file = get_preseed_file(package_names_for_targets, versions_for_targets)
+ converge_by("preseed package #{package_names_for_targets}") do
+ preseed_package(preseed_file)
+ end
+ end
+ end
+
+ def get_preseed_file(name, version)
+ resource = preseed_resource(name, version)
+ resource.run_action(:create)
+ logger.trace("#{new_resource} fetched preseed file to #{resource.path}")
+
+ if resource.updated_by_last_action?
+ resource.path
+ else
+ false
+ end
+ end
+
+ def preseed_resource(name, version)
+ # A directory in our cache to store this cookbook's preseed files in
+ file_cache_dir = Chef::FileCache.create_cache_path("preseed/#{new_resource.cookbook_name}")
+ # The full path where the preseed file will be stored
+ cache_seed_to = "#{file_cache_dir}/#{name}-#{version}.seed"
+
+ logger.trace("#{new_resource} fetching preseed file to #{cache_seed_to}")
+
+ if template_available?(new_resource.response_file)
+ logger.trace("#{new_resource} fetching preseed file via Template")
+ remote_file = Chef::Resource::Template.new(cache_seed_to, run_context)
+ remote_file.variables(new_resource.response_file_variables)
+ elsif cookbook_file_available?(new_resource.response_file)
+ logger.trace("#{new_resource} fetching preseed file via cookbook_file")
+ remote_file = Chef::Resource::CookbookFile.new(cache_seed_to, run_context)
+ else
+ message = "No template or cookbook file found for response file #{new_resource.response_file}"
+ raise Chef::Exceptions::FileNotFound, message
+ end
+
+ remote_file.cookbook_name = new_resource.cookbook_name
+ remote_file.source(new_resource.response_file)
+ remote_file.backup(false)
+ remote_file
+ end
+
+ def preseed_package(preseed_file)
+ logger.info("#{new_resource} pre-seeding package installation instructions")
+ run_noninteractive("debconf-set-selections", preseed_file)
+ end
+
+ def reconfig_package(name)
+ logger.info("#{new_resource} reconfiguring")
+ run_noninteractive("dpkg-reconfigure", *name)
+ end
+
+ # Runs command via shell_out with magic environment to disable
+ # interactive prompts.
+ def run_noninteractive(*command)
+ shell_out!(*command, env: { "DEBIAN_FRONTEND" => "noninteractive" })
+ end
+
+ private
+
+ def template_available?(path)
+ run_context.has_template_in_cookbook?(new_resource.cookbook_name, path)
+ end
+
+ def cookbook_file_available?(path)
+ run_context.has_cookbook_file_in_cookbook?(new_resource.cookbook_name, path)
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/chef/provider/package/dpkg.rb b/lib/chef/provider/package/dpkg.rb
index 38129c8931..25878797c1 100644
--- a/lib/chef/provider/package/dpkg.rb
+++ b/lib/chef/provider/package/dpkg.rb
@@ -17,12 +17,14 @@
#
require "chef/provider/package"
+require "chef/provider/package/deb"
require "chef/resource/package"
class Chef
class Provider
class Package
class Dpkg < Chef::Provider::Package
+ include Chef::Provider::Package::Deb
DPKG_REMOVED = /^Status: deinstall ok config-files/.freeze
DPKG_INSTALLED = /^Status: install ok installed/.freeze
DPKG_VERSION = /^Version: (.+)$/.freeze
@@ -91,16 +93,6 @@ class Chef
install_package(name, version)
end
- def preseed_package(preseed_file)
- logger.info("#{new_resource} pre-seeding package installation instructions")
- run_noninteractive("debconf-set-selections", *preseed_file)
- end
-
- def reconfig_package(name, version)
- logger.info("#{new_resource} reconfiguring")
- run_noninteractive("dpkg-reconfigure", *name)
- end
-
# Override the superclass check. Multiple sources are required here.
def check_resource_semantics!; end
@@ -149,12 +141,6 @@ class Chef
end
end
- # Runs command via shell_out with magic environment to disable
- # interactive prompts.
- def run_noninteractive(*command)
- shell_out!(*command, env: { "DEBIAN_FRONTEND" => "noninteractive" })
- end
-
# Returns true if all sources exist. Returns false if any do not, or if no
# sources were specified.
#
diff --git a/lib/chef/resource/apt_package.rb b/lib/chef/resource/apt_package.rb
index e55d37fcc8..4ee636062d 100644
--- a/lib/chef/resource/apt_package.rb
+++ b/lib/chef/resource/apt_package.rb
@@ -35,6 +35,14 @@ class Chef
description: "Overwrite existing configuration files with those supplied by the package, if prompted by APT.",
default: false
+ property :response_file, String,
+ description: "The direct path to the file used to pre-seed a package.",
+ desired_state: false
+
+ property :response_file_variables, Hash,
+ description: "A Hash of response file variables in the form of {'VARIABLE' => 'VALUE'}.",
+ default: lazy { Hash.new }, desired_state: false
+
end
end
end
diff --git a/lib/chef/resource/dpkg_package.rb b/lib/chef/resource/dpkg_package.rb
index 742b291508..f5b9e5f14a 100644
--- a/lib/chef/resource/dpkg_package.rb
+++ b/lib/chef/resource/dpkg_package.rb
@@ -28,6 +28,14 @@ class Chef
property :source, [ String, Array, nil ],
description: "The path to a package in the local file system."
+
+ property :response_file, String,
+ description: "The direct path to the file used to pre-seed a package.",
+ desired_state: false
+
+ property :response_file_variables, Hash,
+ description: "A Hash of response file variables in the form of {'VARIABLE' => 'VALUE'}.",
+ default: lazy { Hash.new }, desired_state: false
end
end
end
diff --git a/lib/chef/resource/package.rb b/lib/chef/resource/package.rb
index 71f030244b..67b01402a7 100644
--- a/lib/chef/resource/package.rb
+++ b/lib/chef/resource/package.rb
@@ -52,14 +52,6 @@ class Chef
description: "One (or more) additional command options that are passed to the command.",
coerce: proc { |x| x.is_a?(String) ? x.shellsplit : x }
- property :response_file, String,
- description: "The direct path to the file used to pre-seed a package.",
- desired_state: false
-
- property :response_file_variables, Hash,
- description: "A Hash of response file variables in the form of {'VARIABLE' => 'VALUE'}.",
- default: lazy { Hash.new }, desired_state: false
-
property :source, String,
description: "The optional path to a package on the local file system.",
desired_state: false
diff --git a/spec/data/cookbooks/irssi/files/default/irssi.response b/spec/data/cookbooks/irssi/files/default/irssi.response
new file mode 100644
index 0000000000..6b67a12758
--- /dev/null
+++ b/spec/data/cookbooks/irssi/files/default/irssi.response
@@ -0,0 +1,2 @@
+# Hi, I'm pretending to be the preseed file for installing the irssi on debian
+# or Ubuntu
diff --git a/spec/data/cookbooks/wget/files/default/wget.response b/spec/data/cookbooks/wget/files/default/wget.response
new file mode 100644
index 0000000000..b5f22f4d10
--- /dev/null
+++ b/spec/data/cookbooks/wget/files/default/wget.response
@@ -0,0 +1,2 @@
+# Hi, I'm pretending to be the preseed file for installing the wget on debian
+# or Ubuntu
diff --git a/spec/support/shared/unit/provider/package/package_shared.rb b/spec/support/shared/unit/provider/package/package_shared.rb
new file mode 100644
index 0000000000..7cd97f5e0c
--- /dev/null
+++ b/spec/support/shared/unit/provider/package/package_shared.rb
@@ -0,0 +1,95 @@
+#
+# Author:: Kapil Chouhan (<kapil.chouhan@msystechnologies.com>)
+# Copyright:: Copyright 2010-2019, 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.
+#
+
+shared_examples_for "given a response file" do
+ let(:cookbook_repo) { File.expand_path(File.join(CHEF_SPEC_DATA, "cookbooks")) }
+ let(:cookbook_loader) do
+ Chef::Cookbook::FileVendor.fetch_from_disk(cookbook_repo)
+ Chef::CookbookLoader.new(cookbook_repo)
+ end
+ let(:cookbook_collection) do
+ cookbook_loader.load_cookbooks
+ Chef::CookbookCollection.new(cookbook_loader)
+ end
+ let(:run_context) { Chef::RunContext.new(node, cookbook_collection, events) }
+
+ describe "creating the cookbook file resource to fetch the response file" do
+ before do
+ expect(Chef::FileCache).to receive(:create_cache_path).with(path).and_return(tmp_path)
+ end
+
+ it "sets the preseed resource's runcontext to its own run context" do
+ cookbook_collection
+ allow(Chef::FileCache).to receive(:create_cache_path).and_return(tmp_path)
+ expect(@provider.preseed_resource(package_name, package_version).run_context).not_to be_nil
+ expect(@provider.preseed_resource(package_name, package_version).run_context).to equal(@provider.run_context)
+ end
+
+ it "should set the cookbook name of the remote file to the new resources cookbook name" do
+ expect(@provider.preseed_resource(package_name, package_version).cookbook_name).to eq(package_name)
+ end
+
+ it "should set remote files source to the new resources response file" do
+ expect(@provider.preseed_resource(package_name, package_version).source).to eq(response)
+ end
+
+ it "should never back up the cached response file" do
+ expect(@provider.preseed_resource(package_name, package_version).backup).to be_falsey
+ end
+
+ it "sets the install path of the resource to $file_cache/$cookbook/$pkg_name-$pkg_version.seed" do
+ expect(@provider.preseed_resource(package_name, package_version).path).to eq(tmp_preseed_path)
+ end
+ end
+
+ describe "when installing the preseed file to the cache location" do
+ let(:response_file_destination) { Dir.tmpdir + preseed_path }
+ let(:response_file_resource) do
+ response_file_resource = Chef::Resource::CookbookFile.new(response_file_destination, run_context)
+ response_file_resource.cookbook_name = package_name
+ response_file_resource.backup(false)
+ response_file_resource.source(response)
+ response_file_resource
+ end
+
+ before do
+ expect(@provider).to receive(:preseed_resource).with(package_name, package_version).and_return(response_file_resource)
+ end
+
+ after do
+ FileUtils.rm(response_file_destination) if ::File.exist?(response_file_destination)
+ end
+
+ it "creates the preseed file in the cache" do
+ expect(response_file_resource).to receive(:run_action).with(:create)
+ @provider.get_preseed_file(package_name, package_version)
+ end
+
+ it "returns the path to the response file if the response file was updated" do
+ expect(@provider.get_preseed_file(package_name, package_version)).to eq(response_file_destination)
+ end
+
+ it "should return false if the response file has not been updated" do
+ response_file_resource.updated_by_last_action(false)
+ expect(response_file_resource).not_to be_updated_by_last_action
+ # don't let the response_file_resource set updated to true
+ expect(response_file_resource).to receive(:run_action).with(:create)
+ expect(@provider.get_preseed_file(package_name, package_version)).to be(false)
+ end
+ end
+end
diff --git a/spec/unit/cookbook_loader_spec.rb b/spec/unit/cookbook_loader_spec.rb
index ddb4f00f35..9180f13f33 100644
--- a/spec/unit/cookbook_loader_spec.rb
+++ b/spec/unit/cookbook_loader_spec.rb
@@ -101,7 +101,7 @@ describe Chef::CookbookLoader do
cookbook_loader.each_key do |cookbook_name|
seen << cookbook_name
end
- expect(seen).to eq %w{angrybash apache2 borken ignorken java name-mismatch openldap preseed supports-platform-constraints}
+ expect(seen).to eq %w{angrybash apache2 borken ignorken irssi java name-mismatch openldap preseed supports-platform-constraints wget}
end
end
diff --git a/spec/unit/provider/package/apt_spec.rb b/spec/unit/provider/package/apt_spec.rb
index 24bd642317..31b37f5094 100644
--- a/spec/unit/provider/package/apt_spec.rb
+++ b/spec/unit/provider/package/apt_spec.rb
@@ -24,10 +24,11 @@ describe Chef::Provider::Package::Apt do
# XXX: sorry this is ugly and was done quickly to get 12.0.2 out, this file needs a rewrite to use
# let blocks and shared examples
+ let(:node) { Chef::Node.new }
+ let(:events) { Chef::EventDispatch::Dispatcher.new }
+
before(:each) do
- @node = Chef::Node.new
- @events = Chef::EventDispatch::Dispatcher.new
- @run_context = Chef::RunContext.new(@node, {}, @events)
+ @run_context = Chef::RunContext.new(node, {}, events)
allow(@run_context).to receive(:logger).and_return(logger)
@new_resource = Chef::Resource::AptPackage.new("irssi", @run_context)
@@ -428,6 +429,27 @@ describe Chef::Provider::Package::Apt do
end
end
+ describe "when given a response file" do
+ it_behaves_like "given a response file" do
+ before do
+ @provider = Chef::Provider::Package::Apt.new(new_resource, run_context)
+ end
+ let(:new_resource) do
+ new_resource = Chef::Resource::AptPackage.new("irssi", run_context)
+ new_resource.response_file("irssi.response")
+ new_resource.cookbook_name = "irssi"
+ new_resource
+ end
+ let(:path) { "preseed/irssi" }
+ let(:tmp_path) { "/tmp/preseed/irssi" }
+ let(:package_name) { "irssi" }
+ let(:package_version) { "1.0.5-1" }
+ let(:response) { "irssi.response" }
+ let(:tmp_preseed_path) { "/tmp/preseed/irssi/irssi-1.0.5-1.seed" }
+ let(:preseed_path) { "/preseed--irssi--irssi-1.0.5-1.seed" }
+ end
+ end
+
describe "when preseeding a package" do
before(:each) do
allow(@provider).to receive(:get_preseed_file).and_return("/tmp/irssi-0.8.12-7.seed")
@@ -472,7 +494,7 @@ describe Chef::Provider::Package::Apt do
env: { "DEBIAN_FRONTEND" => "noninteractive" },
timeout: @timeout
)
- @provider.reconfig_package("irssi", "0.8.12-7")
+ @provider.reconfig_package("irssi")
end
end
diff --git a/spec/unit/provider/package/deb_spec.rb b/spec/unit/provider/package/deb_spec.rb
new file mode 100644
index 0000000000..d67a79586f
--- /dev/null
+++ b/spec/unit/provider/package/deb_spec.rb
@@ -0,0 +1,135 @@
+#
+# Author:: Kapil Chouhan (<kapil.chouhan@msystechnologies.com>)
+# Copyright:: Copyright 2010-2019, 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 "spec_helper"
+
+describe Chef::Provider::Package::Deb do
+ let(:node) do
+ node = Chef::Node.new
+ node.automatic_attrs[:platform] = :just_testing
+ node.automatic_attrs[:platform_version] = :just_testing
+ node
+ end
+ let(:events) { Chef::EventDispatch::Dispatcher.new }
+ let(:logger) { double("Mixlib::Log::Child").as_null_object }
+ let(:run_context) { Chef::RunContext.new(node, {}, events) }
+ let(:new_resource) { Chef::Resource::AptPackage.new("emacs", run_context) }
+ let(:current_resource) { Chef::Resource::AptPackage.new("emacs", run_context) }
+ let(:candidate_version) { "1.0" }
+ let(:provider) do
+ provider = Chef::Provider::Package::Apt.new(new_resource, run_context) { include Chef::Provider::Package::Deb }
+ provider.current_resource = current_resource
+ provider.candidate_version = candidate_version
+ provider
+ end
+
+ before do
+ allow(run_context).to receive(:logger).and_return(logger)
+ end
+
+ describe "when reconfiguring the package" do
+ before(:each) do
+ allow(provider).to receive(:reconfig_package).and_return(true)
+ end
+
+ context "when reconfigure the package" do
+ it "reconfigure the package and update the resource" do
+ allow(provider).to receive(:get_current_versions).and_return("1.0")
+ allow(new_resource).to receive(:response_file).and_return(true)
+ expect(provider).to receive(:get_preseed_file).and_return("/var/cache/preseed-test")
+ allow(provider).to receive(:preseed_package).and_return(true)
+ allow(provider).to receive(:reconfig_package).and_return(true)
+ expect(logger).to receive(:info).with("apt_package[emacs] reconfigured")
+ expect(provider).to receive(:reconfig_package)
+ provider.run_action(:reconfig)
+ expect(new_resource).to be_updated
+ expect(new_resource).to be_updated_by_last_action
+ end
+ end
+
+ context "when not reconfigure the package" do
+ it "does not reconfigure the package if the package is not installed" do
+ allow(provider).to receive(:get_current_versions).and_return(nil)
+ allow(provider.load_current_resource).to receive(:version).and_return(nil)
+ expect(logger).to receive(:trace).with("apt_package[emacs] is NOT installed - nothing to do")
+ expect(provider).not_to receive(:reconfig_package)
+ provider.run_action(:reconfig)
+ expect(new_resource).not_to be_updated_by_last_action
+ end
+
+ it "does not reconfigure the package if no response_file is given" do
+ allow(provider).to receive(:get_current_versions).and_return("1.0")
+ allow(new_resource).to receive(:response_file).and_return(nil)
+ expect(logger).to receive(:trace).with("apt_package[emacs] no response_file provided - nothing to do")
+ expect(provider).not_to receive(:reconfig_package)
+ provider.run_action(:reconfig)
+ expect(new_resource).not_to be_updated_by_last_action
+ end
+
+ it "does not reconfigure the package if the response_file has not changed" do
+ allow(provider).to receive(:get_current_versions).and_return("1.0")
+ allow(new_resource).to receive(:response_file).and_return(true)
+ expect(provider).to receive(:get_preseed_file).and_return(false)
+ allow(provider).to receive(:preseed_package).and_return(false)
+ expect(logger).to receive(:trace).with("apt_package[emacs] preseeding has not changed - nothing to do")
+ expect(provider).not_to receive(:reconfig_package)
+ provider.run_action(:reconfig)
+ expect(new_resource).not_to be_updated_by_last_action
+ end
+ end
+ end
+
+ describe "Subclass with use_multipackage_api" do
+ class MyDebianPackageResource < Chef::Resource::Package
+ end
+
+ class MyDebianPackageProvider < Chef::Provider::Package
+ include Chef::Provider::Package::Deb
+ use_multipackage_api
+ end
+ let(:node) { Chef::Node.new }
+ let(:events) { Chef::EventDispatch::Dispatcher.new }
+ let(:run_context) { Chef::RunContext.new(node, {}, events) }
+ let(:new_resource) { MyDebianPackageResource.new("installs the packages") }
+ let(:current_resource) { MyDebianPackageResource.new("installs the packages") }
+ let(:provider) do
+ provider = MyDebianPackageProvider.new(new_resource, run_context)
+ provider.current_resource = current_resource
+ provider
+ end
+
+ it "has use_multipackage_api? methods on the class and instance" do
+ expect(MyDebianPackageProvider.use_multipackage_api?).to be true
+ expect(provider.use_multipackage_api?).to be true
+ end
+
+ it "when user passes string to package_name, passes arrays to reconfig_package" do
+ new_resource.package_name "vim"
+ current_resource.package_name "vim"
+ current_resource.version [ "1.0" ]
+ allow(new_resource).to receive(:response_file).and_return(true)
+ allow(new_resource).to receive(:resource_name).and_return(:apt_package)
+ expect(provider).to receive(:get_preseed_file).and_return("/var/cache/preseed-test")
+ allow(provider).to receive(:preseed_package).and_return(true)
+ allow(provider).to receive(:reconfig_package).and_return(true)
+ expect(provider).to receive(:reconfig_package).with([ "vim" ]).and_return(true)
+ provider.run_action(:reconfig)
+ expect(new_resource).to be_updated_by_last_action
+ end
+ end
+end
diff --git a/spec/unit/provider/package/dpkg_spec.rb b/spec/unit/provider/package/dpkg_spec.rb
index 9df19f0f1b..318b91c77e 100644
--- a/spec/unit/provider/package/dpkg_spec.rb
+++ b/spec/unit/provider/package/dpkg_spec.rb
@@ -53,7 +53,6 @@ describe Chef::Provider::Package::Dpkg do
before(:each) do
allow(provider).to receive(:shell_out_compacted!).with("dpkg-deb", "-W", source, timeout: 900).and_return(dpkg_deb_status)
allow(provider).to receive(:shell_out_compacted!).with("dpkg", "-s", package, timeout: 900, returns: [0, 1]).and_return(double(stdout: "", exitstatus: 1))
- allow(::File).to receive(:exist?).with(source).and_return(true)
end
describe "#define_resource_requirements" do
@@ -104,6 +103,9 @@ describe Chef::Provider::Package::Dpkg do
end
describe "when loading the current resource state" do
+ before(:each) do
+ allow(::File).to receive(:exist?).with(source).and_return(true)
+ end
it "should create a current resource with the name of the new_resource" do
provider.load_current_resource
@@ -213,6 +215,10 @@ describe Chef::Provider::Package::Dpkg do
end
describe Chef::Provider::Package::Dpkg, "install and upgrade" do
+ before(:each) do
+ allow(::File).to receive(:exist?).with(source).and_return(true)
+ end
+
it "should run dpkg -i with the package source" do
expect(provider).to receive(:run_noninteractive).with(
"dpkg", "-i", "/tmp/wget_1.11.4-1ubuntu1_amd64.deb"
@@ -284,4 +290,25 @@ describe Chef::Provider::Package::Dpkg do
provider.purge_package(["wget"], ["1.11.4-1ubuntu1"])
end
end
+
+ describe "when given a response file" do
+ it_behaves_like "given a response file" do
+ before do
+ @provider = Chef::Provider::Package::Dpkg.new(new_resource, run_context)
+ end
+ let(:new_resource) do
+ new_resource = Chef::Resource::DpkgPackage.new("wget", run_context)
+ new_resource.response_file("wget.response")
+ new_resource.cookbook_name = "wget"
+ new_resource
+ end
+ let(:path) { "preseed/wget" }
+ let(:tmp_path) { "/tmp/preseed/wget" }
+ let(:package_name) { "wget" }
+ let(:package_version) { "1.11.4" }
+ let(:response) { "wget.response" }
+ let(:tmp_preseed_path) { "/tmp/preseed/wget/wget-1.11.4.seed" }
+ let(:preseed_path) { "/preseed--wget--wget-1.11.4.seed" }
+ end
+ end
end
diff --git a/spec/unit/provider/package_spec.rb b/spec/unit/provider/package_spec.rb
index f085e09ce4..accd913ebe 100644
--- a/spec/unit/provider/package_spec.rb
+++ b/spec/unit/provider/package_spec.rb
@@ -61,24 +61,6 @@ describe Chef::Provider::Package do
expect { provider.run_action(:install) }.to raise_error(Chef::Exceptions::Package)
end
- it "should call preseed_package if a response_file is given" do
- new_resource.response_file("foo")
- expect(provider).to receive(:get_preseed_file).with(
- new_resource.package_name,
- provider.candidate_version
- ).and_return("/var/cache/preseed-test")
-
- expect(provider).to receive(:preseed_package).with(
- "/var/cache/preseed-test"
- ).and_return(true)
- provider.run_action(:install)
- end
-
- it "should not call preseed_package if a response_file is not given" do
- expect(provider).not_to receive(:preseed_package)
- provider.run_action(:install)
- end
-
it "should install the package at the candidate_version if it is not already installed" do
expect(provider).to receive(:install_package).with(
new_resource.package_name,
@@ -281,53 +263,6 @@ describe Chef::Provider::Package do
end
- describe "when reconfiguring the package" do
- before(:each) do
- allow(provider).to receive(:reconfig_package).and_return(true)
- end
-
- it "should info log, reconfigure the package and update the resource" do
- allow(current_resource).to receive(:version).and_return("1.0")
- allow(new_resource).to receive(:response_file).and_return(true)
- expect(provider).to receive(:get_preseed_file).and_return("/var/cache/preseed-test")
- allow(provider).to receive(:preseed_package).and_return(true)
- allow(provider).to receive(:reconfig_package).and_return(true)
- expect(logger).to receive(:info).with("package[install emacs] reconfigured")
- expect(provider).to receive(:reconfig_package)
- provider.run_action(:reconfig)
- expect(new_resource).to be_updated
- expect(new_resource).to be_updated_by_last_action
- end
-
- it "should debug log and not reconfigure the package if the package is not installed" do
- allow(current_resource).to receive(:version).and_return(nil)
- expect(logger).to receive(:trace).with("package[install emacs] is NOT installed - nothing to do")
- expect(provider).not_to receive(:reconfig_package)
- provider.run_action(:reconfig)
- expect(new_resource).not_to be_updated_by_last_action
- end
-
- it "should debug log and not reconfigure the package if no response_file is given" do
- allow(current_resource).to receive(:version).and_return("1.0")
- allow(new_resource).to receive(:response_file).and_return(nil)
- expect(logger).to receive(:trace).with("package[install emacs] no response_file provided - nothing to do")
- expect(provider).not_to receive(:reconfig_package)
- provider.run_action(:reconfig)
- expect(new_resource).not_to be_updated_by_last_action
- end
-
- it "should debug log and not reconfigure the package if the response_file has not changed" do
- allow(current_resource).to receive(:version).and_return("1.0")
- allow(new_resource).to receive(:response_file).and_return(true)
- expect(provider).to receive(:get_preseed_file).and_return(false)
- allow(provider).to receive(:preseed_package).and_return(false)
- expect(logger).to receive(:trace).with("package[install emacs] preseeding has not changed - nothing to do")
- expect(provider).not_to receive(:reconfig_package)
- provider.run_action(:reconfig)
- expect(new_resource).not_to be_updated_by_last_action
- end
- end
-
describe "When locking the package" do
before(:each) do
allow(provider).to receive(:lock_package).with(
@@ -421,7 +356,7 @@ describe Chef::Provider::Package do
end
it "should raise UnsupportedAction for reconfig" do
- expect { provider.reconfig_package("emacs", "1.4.2") }.to raise_error(Chef::Exceptions::UnsupportedAction)
+ expect { provider.reconfig_package("emacs") }.to raise_error(Chef::Exceptions::UnsupportedAction)
end
it "should raise UnsupportedAction for lock" do
@@ -432,91 +367,6 @@ describe Chef::Provider::Package do
expect { provider.unlock_package("emacs", nil) }.to raise_error(Chef::Exceptions::UnsupportedAction)
end
end
-
- describe "when given a response file" do
- let(:cookbook_repo) { File.expand_path(File.join(CHEF_SPEC_DATA, "cookbooks")) }
- let(:cookbook_loader) do
- Chef::Cookbook::FileVendor.fetch_from_disk(cookbook_repo)
- Chef::CookbookLoader.new(cookbook_repo)
- end
- let(:cookbook_collection) do
- cookbook_loader.load_cookbooks
- Chef::CookbookCollection.new(cookbook_loader)
- end
- let(:run_context) { Chef::RunContext.new(node, cookbook_collection, events) }
- let(:new_resource) do
- new_resource = Chef::Resource::Package.new("emacs")
- new_resource.response_file("java.response")
- new_resource.cookbook_name = "java"
- new_resource
- end
-
- describe "creating the cookbook file resource to fetch the response file" do
- before do
- expect(Chef::FileCache).to receive(:create_cache_path).with("preseed/java").and_return("/tmp/preseed/java")
- end
-
- it "sets the preseed resource's runcontext to its own run context" do
- allow(Chef::FileCache).to receive(:create_cache_path).and_return("/tmp/preseed/java")
- expect(provider.preseed_resource("java", "6").run_context).not_to be_nil
- expect(provider.preseed_resource("java", "6").run_context).to equal(provider.run_context)
- end
-
- it "should set the cookbook name of the remote file to the new resources cookbook name" do
- expect(provider.preseed_resource("java", "6").cookbook_name).to eq("java")
- end
-
- it "should set remote files source to the new resources response file" do
- expect(provider.preseed_resource("java", "6").source).to eq("java.response")
- end
-
- it "should never back up the cached response file" do
- expect(provider.preseed_resource("java", "6").backup).to be_falsey
- end
-
- it "sets the install path of the resource to $file_cache/$cookbook/$pkg_name-$pkg_version.seed" do
- expect(provider.preseed_resource("java", "6").path).to eq("/tmp/preseed/java/java-6.seed")
- end
- end
-
- describe "when installing the preseed file to the cache location" do
- let(:response_file_destination) { Dir.tmpdir + "/preseed--java--java-6.seed" }
- let(:response_file_resource) do
- response_file_resource = Chef::Resource::CookbookFile.new(response_file_destination, run_context)
- response_file_resource.cookbook_name = "java"
- response_file_resource.backup(false)
- response_file_resource.source("java.response")
- response_file_resource
- end
-
- before do
- expect(provider).to receive(:preseed_resource).with("java", "6").and_return(response_file_resource)
- end
-
- after do
- FileUtils.rm(response_file_destination) if ::File.exist?(response_file_destination)
- end
-
- it "creates the preseed file in the cache" do
- expect(response_file_resource).to receive(:run_action).with(:create)
- provider.get_preseed_file("java", "6")
- end
-
- it "returns the path to the response file if the response file was updated" do
- expect(provider.get_preseed_file("java", "6")).to eq(response_file_destination)
- end
-
- it "should return false if the response file has not been updated" do
- response_file_resource.updated_by_last_action(false)
- expect(response_file_resource).not_to be_updated_by_last_action
- # don't let the response_file_resource set updated to true
- expect(response_file_resource).to receive(:run_action).with(:create)
- expect(provider.get_preseed_file("java", "6")).to be(false)
- end
-
- end
-
- end
end
describe "Subclass with use_multipackage_api" do
@@ -622,22 +472,6 @@ describe "Subclass with use_multipackage_api" do
expect(new_resource).to be_updated_by_last_action
expect(new_resource.version).to eql(nil)
end
-
- it "when user passes string to package_name, passes arrays to reconfig_package" do
- new_resource.package_name "vim"
- current_resource.package_name "vim"
- current_resource.version [ "1.0" ]
- allow(new_resource).to receive(:response_file).and_return(true)
- expect(provider).to receive(:get_preseed_file).and_return("/var/cache/preseed-test")
- allow(provider).to receive(:preseed_package).and_return(true)
- allow(provider).to receive(:reconfig_package).and_return(true)
- expect(provider).to receive(:reconfig_package).with(
- [ "vim" ],
- [ "1.0" ]
- ).and_return(true)
- provider.run_action(:reconfig)
- expect(new_resource).to be_updated_by_last_action
- end
end
describe "Chef::Provider::Package - Multi" do
diff --git a/spec/unit/resource/apt_package_spec.rb b/spec/unit/resource/apt_package_spec.rb
index 66fe05ef33..c39c768ae2 100644
--- a/spec/unit/resource/apt_package_spec.rb
+++ b/spec/unit/resource/apt_package_spec.rb
@@ -53,4 +53,14 @@ describe Chef::Resource::AptPackage, "initialize" do
it "should preserve configuration files by default" do
expect(resource.overwrite_config_files).to eql(false)
end
+
+ it "accepts a string for the response file" do
+ resource.response_file "something"
+ expect(resource.response_file).to eql("something")
+ end
+
+ it "accepts a hash for response file template variables" do
+ resource.response_file_variables({ variables: true })
+ expect(resource.response_file_variables).to eql({ variables: true })
+ end
end
diff --git a/spec/unit/resource/dpkg_package_spec.rb b/spec/unit/resource/dpkg_package_spec.rb
index ff32d7e413..562dbeef76 100644
--- a/spec/unit/resource/dpkg_package_spec.rb
+++ b/spec/unit/resource/dpkg_package_spec.rb
@@ -36,6 +36,16 @@ describe Chef::Resource::DpkgPackage, "initialize" do
expect(resource.action).to eql([:install])
end
+ it "accepts a string for the response file" do
+ resource.response_file "something"
+ expect(resource.response_file).to eql("something")
+ end
+
+ it "accepts a hash for response file template variables" do
+ resource.response_file_variables({ variables: true })
+ expect(resource.response_file_variables).to eql({ variables: true })
+ end
+
it "supports :install, :lock, :purge, :reconfig, :remove, :unlock, :upgrade actions" do
expect { resource.action :install }.not_to raise_error
expect { resource.action :lock }.not_to raise_error
diff --git a/spec/unit/resource/package_spec.rb b/spec/unit/resource/package_spec.rb
index b0e1304775..6e3d609e4b 100644
--- a/spec/unit/resource/package_spec.rb
+++ b/spec/unit/resource/package_spec.rb
@@ -50,16 +50,6 @@ describe Chef::Resource::Package do
expect(resource.version).to eql("something")
end
- it "accepts a string for the response file" do
- resource.response_file "something"
- expect(resource.response_file).to eql("something")
- end
-
- it "accepts a hash for response file template variables" do
- resource.response_file_variables({ variables: true })
- expect(resource.response_file_variables).to eql({ variables: true })
- end
-
it "accepts a string for the source" do
resource.source "something"
expect(resource.source).to eql("something")