summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.md1
-rw-r--r--lib/chef/knife/bootstrap/templates/chef-full.erb2
-rw-r--r--lib/chef/provider/package/openbsd.rb67
-rw-r--r--spec/unit/provider/package/openbsd_spec.rb122
4 files changed, 156 insertions, 36 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 5760097934..609cf9825f 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7,6 +7,7 @@
fail-fast rather than moving on to the next machine.
* migrate macosx, windows, openbsd, and netbsd resources to dynamic resolution
* migrate cron and mdadm resources to dynamic resolution
+* [Issue 3096](https://github.com/chef/chef/issues/3096) Fix OpenBSD package provider installation issues
## 12.1.2
* [Issue 3022](https://github.com/chef/chef/issues/3022): Homebrew Cask install fails
diff --git a/lib/chef/knife/bootstrap/templates/chef-full.erb b/lib/chef/knife/bootstrap/templates/chef-full.erb
index 17d7a9e3b5..a87ab8e544 100644
--- a/lib/chef/knife/bootstrap/templates/chef-full.erb
+++ b/lib/chef/knife/bootstrap/templates/chef-full.erb
@@ -22,7 +22,7 @@ exists() {
<% if knife_config[:bootstrap_install_command] %>
<%= knife_config[:bootstrap_install_command] %>
<% else %>
- install_sh="<%= knife_config[:bootstrap_url] ? knife_config[:bootstrap_url] : "https://www.chef.io/chef/install.sh" %>"
+ install_sh="<%= knife_config[:bootstrap_url] ? knife_config[:bootstrap_url] : "https://www.opscode.com/chef/install.sh" %>"
if ! exists /usr/bin/chef-client; then
echo "Installing Chef Client..."
if exists wget; then
diff --git a/lib/chef/provider/package/openbsd.rb b/lib/chef/provider/package/openbsd.rb
index f0931d7555..82048c3bd4 100644
--- a/lib/chef/provider/package/openbsd.rb
+++ b/lib/chef/provider/package/openbsd.rb
@@ -24,6 +24,7 @@ require 'chef/resource/package'
require 'chef/provider/package'
require 'chef/mixin/shell_out'
require 'chef/mixin/get_source_from_package'
+require 'chef/exceptions'
class Chef
class Provider
@@ -37,25 +38,42 @@ class Chef
def initialize(*args)
super
- @current_resource = Chef::Resource::Package.new(@new_resource.name)
- @new_resource.source(pkg_path) if !@new_resource.source
+ @current_resource = Chef::Resource::Package.new(new_resource.name)
end
def load_current_resource
- @current_resource.package_name(@new_resource.package_name)
+ @current_resource.package_name(new_resource.package_name)
@current_resource.version(installed_version)
@current_resource
end
+ def define_resource_requirements
+ super
+
+ # Below are incomplete/missing features for this package provider
+ requirements.assert(:all_actions) do |a|
+ a.assertion { !new_resource.source }
+ a.failure_message(Chef::Exceptions::Package, 'The openbsd package provider does not support the source attribute')
+ end
+ requirements.assert(:all_actions) do |a|
+ a.assertion do
+ if new_resource.package_name =~ /^(.+?)--(.+)/
+ !new_resource.version
+ else
+ true
+ end
+ end
+ a.failure_message(Chef::Exceptions::Package, 'The openbsd package provider does not support providing a version and flavor')
+ end
+ end
+
def install_package(name, version)
unless @current_resource.version
- version_string = ''
- version_string += "-#{version}" if version
if parts = name.match(/^(.+?)--(.+)/) # use double-dash for stems with flavors, see man page for pkg_add
name = parts[1]
end
- shell_out!("pkg_add -r #{name}#{version_string}", :env => {"PKG_PATH" => @new_resource.source}).status
- Chef::Log.debug("#{@new_resource} installed from: #{@new_resource.source}")
+ shell_out!("pkg_add -r #{name}#{version_string}", :env => {"PKG_PATH" => pkg_path}).status
+ Chef::Log.debug("#{new_resource.package_name} installed")
end
end
@@ -71,32 +89,45 @@ class Chef
private
def installed_version
- if parts = @new_resource.package_name.match(/^(.+?)--(.+)/)
+ if parts = new_resource.package_name.match(/^(.+?)--(.+)/)
name = parts[1]
else
- name = @new_resource.package_name
+ name = new_resource.package_name
end
pkg_info = shell_out!("pkg_info -e \"#{name}->0\"", :env => nil, :returns => [0,1])
result = pkg_info.stdout[/^inst:#{Regexp.escape(name)}-(.+?)\s/, 1]
- Chef::Log.debug("installed_version of '#{@new_resource.package_name}' is '#{result}'")
+ Chef::Log.debug("installed_version of '#{new_resource.package_name}' is '#{result}'")
result
end
def candidate_version
@candidate_version ||= begin
- version_string = ''
- version_string += "-#{version}" if @new_resource.version
- pkg_info = shell_out!("pkg_info -I \"#{@new_resource.package_name}#{version_string}\"", :env => nil, :returns => [0,1])
- if parts = @new_resource.package_name.match(/^(.+?)--(.+)/)
- result = pkg_info.stdout[/^#{Regexp.escape(parts[1])}-(.+?)\s/, 1]
+ results = []
+ shell_out!("pkg_info -I \"#{new_resource.package_name}#{version_string}\"", :env => nil, :returns => [0,1]).stdout.each_line do |line|
+ if parts = new_resource.package_name.match(/^(.+?)--(.+)/)
+ results << line[/^#{Regexp.escape(parts[1])}-(.+?)\s/, 1]
+ else
+ results << line[/^#{Regexp.escape(new_resource.package_name)}-(.+?)\s/, 1]
+ end
+ end
+ results = results.reject(&:nil?)
+ Chef::Log.debug("candidate versions of '#{new_resource.package_name}' are '#{results}'")
+ case results.length
+ when 0
+ []
+ when 1
+ results[0]
else
- result = pkg_info.stdout[/^#{Regexp.escape(@new_resource.package_name)}-(.+?)\s/, 1]
+ raise Chef::Exceptions::Package, "#{new_resource.name} has multiple matching candidates. Please use a more specific name" if results.length > 1
end
- Chef::Log.debug("candidate_version of '#{@new_resource.package_name}' is '#{result}'")
- result
end
end
+ def version_string
+ ver = ''
+ ver += "-#{new_resource.version}" if new_resource.version
+ end
+
def pkg_path
ENV['PKG_PATH'] || "http://ftp.OpenBSD.org/pub/#{node.kernel.name}/#{node.kernel.release}/packages/#{node.kernel.machine}/"
end
diff --git a/spec/unit/provider/package/openbsd_spec.rb b/spec/unit/provider/package/openbsd_spec.rb
index ee9c9e89fb..b0cdb9969d 100644
--- a/spec/unit/provider/package/openbsd_spec.rb
+++ b/spec/unit/provider/package/openbsd_spec.rb
@@ -21,28 +21,116 @@ require 'ostruct'
describe Chef::Provider::Package::Openbsd do
+ let(:node) do
+ node = Chef::Node.new
+ node.default['kernel'] = {'name' => 'OpenBSD', 'release' => '5.5', 'machine' => 'amd64'}
+ node
+ end
+
+ let (:provider) do
+ events = Chef::EventDispatch::Dispatcher.new
+ run_context = Chef::RunContext.new(node, {}, events)
+ Chef::Provider::Package::Openbsd.new(new_resource, run_context)
+ end
+
+ let(:new_resource) { Chef::Resource::Package.new(name)}
+
before(:each) do
- @node = Chef::Node.new
- @node.default['kernel'] = {'name' => 'OpenBSD', 'release' => '5.5', 'machine' => 'amd64'}
- @events = Chef::EventDispatch::Dispatcher.new
- @run_context = Chef::RunContext.new(@node, {}, @events)
ENV['PKG_PATH'] = nil
end
describe "install a package" do
- before do
- @name = 'ihavetoes'
- @new_resource = Chef::Resource::Package.new(@name)
- @current_resource = Chef::Resource::Package.new(@name)
- @provider = Chef::Provider::Package::Openbsd.new(@new_resource, @run_context)
- @provider.current_resource = @current_resource
- end
- it "should run the installation command" do
- expect(@provider).to receive(:shell_out!).with(
- "pkg_add -r #{@name}",
- {:env => {"PKG_PATH" => "http://ftp.OpenBSD.org/pub/OpenBSD/5.5/packages/amd64/"}}
- ) {OpenStruct.new :status => true}
- @provider.install_package(@name, nil)
+ let(:name) { 'ihavetoes' }
+ let(:version) {'0.0'}
+
+ context 'when not already installed' do
+ before do
+ allow(provider).to receive(:shell_out!).with("pkg_info -e \"#{name}->0\"", anything()).and_return(instance_double('shellout', :stdout => ''))
+ end
+
+ context 'when there is a single candidate' do
+
+ context 'when installing from source' do
+ it 'should run the installation command' do
+ pending('Installing from source is not supported yet')
+ # This is a consequence of load_current_resource being called before define_resource_requirements
+ # It can be deleted once an implementation is provided
+ allow(provider).to receive(:shell_out!).with("pkg_info -I \"#{name}\"", anything()).and_return(
+ instance_double('shellout', :stdout => "#{name}-#{version}\n"))
+ new_resource.source('/some/path/on/disk.tgz')
+ provider.run_action(:install)
+ end
+ end
+
+ context 'when source is not provided' do
+ it 'should run the installation command' do
+ expect(provider).to receive(:shell_out!).with("pkg_info -I \"#{name}\"", anything()).and_return(
+ instance_double('shellout', :stdout => "#{name}-#{version}\n"))
+ expect(provider).to receive(:shell_out!).with(
+ "pkg_add -r #{name}-#{version}",
+ {:env => {"PKG_PATH" => "http://ftp.OpenBSD.org/pub/OpenBSD/5.5/packages/amd64/"}}
+ ) {OpenStruct.new :status => true}
+ provider.run_action(:install)
+ end
+ end
+ end
+
+ context 'when there are multiple candidates' do
+ let(:flavor_a) { 'flavora' }
+ let(:flavor_b) { 'flavorb' }
+
+ context 'if no version is specified' do
+ it 'should raise an exception' do
+ expect(provider).to receive(:shell_out!).with("pkg_info -I \"#{name}\"", anything()).and_return(
+ instance_double('shellout', :stdout => "#{name}-#{version}-#{flavor_a}\n#{name}-#{version}-#{flavor_b}\n"))
+ expect { provider.run_action(:install) }.to raise_error(Chef::Exceptions::Package, /multiple matching candidates/)
+ end
+ end
+
+ context 'if a flavor is specified' do
+
+ let(:flavor) { 'flavora' }
+ let(:package_name) {'ihavetoes' }
+ let(:name) { "#{package_name}--#{flavor}" }
+
+ context 'if no version is specified' do
+ it 'should run the installation command' do
+ expect(provider).to receive(:shell_out!).with("pkg_info -e \"#{package_name}->0\"", anything()).and_return(instance_double('shellout', :stdout => ''))
+ expect(provider).to receive(:shell_out!).with("pkg_info -I \"#{name}\"", anything()).and_return(
+ instance_double('shellout', :stdout => "#{name}-#{version}-#{flavor}\n"))
+ expect(provider).to receive(:shell_out!).with(
+ "pkg_add -r #{name}-#{version}-#{flavor}",
+ {:env => {"PKG_PATH" => "http://ftp.OpenBSD.org/pub/OpenBSD/5.5/packages/amd64/"}}
+ ) {OpenStruct.new :status => true}
+ provider.run_action(:install)
+ end
+ end
+
+ context 'if a version is specified' do
+ it 'runs the installation command' do
+ pending('Specifying both a version and flavor is not supported')
+ new_resource.version(version)
+ allow(provider).to receive(:shell_out!).with(/pkg_info -e/, anything()).and_return(instance_double('shellout', :stdout => ''))
+ allow(provider).to receive(:candidate_version).and_return("#{package_name}-#{version}-#{flavor}")
+ provider.run_action(:install)
+ end
+ end
+ end
+
+ context 'if a version is specified' do
+ it 'should use the flavor from the version' do
+ expect(provider).to receive(:shell_out!).with("pkg_info -I \"#{name}-#{version}-#{flavor_b}\"", anything()).and_return(
+ instance_double('shellout', :stdout => "#{name}-#{version}-#{flavor_a}\n"))
+
+ new_resource.version("#{version}-#{flavor_b}")
+ expect(provider).to receive(:shell_out!).with(
+ "pkg_add -r #{name}-#{version}-#{flavor_b}",
+ {:env => {"PKG_PATH" => "http://ftp.OpenBSD.org/pub/OpenBSD/5.5/packages/amd64/"}}
+ ) {OpenStruct.new :status => true}
+ provider.run_action(:install)
+ end
+ end
+ end
end
end