summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Manyanza <rm@dsc.co.tz>2014-03-06 09:23:13 +0300
committerRichard Manyanza <rm@dsc.co.tz>2014-03-11 18:14:00 +0300
commitd575316610937859250fb31070884c42a294ab96 (patch)
treea8e9c30e1604bc58ca1d4a1238eca74ff8c31c70
parentddc3d9afe6a608af0b14bad38b891c6d8a504cae (diff)
downloadchef-d575316610937859250fb31070884c42a294ab96.tar.gz
Refactor FreeBSD package providers
-rw-r--r--lib/chef.rb1
-rw-r--r--lib/chef/platform/provider_mapping.rb14
-rw-r--r--lib/chef/provider/package/freebsd.rb149
-rw-r--r--lib/chef/provider/package/freebsd/base.rb92
-rw-r--r--lib/chef/provider/package/freebsd/pkg.rb113
-rw-r--r--lib/chef/provider/package/freebsd/pkgng.rb80
-rw-r--r--lib/chef/provider/package/freebsd/port.rb70
-rw-r--r--lib/chef/provider/package/freebsd_next_gen.rb131
-rw-r--r--lib/chef/provider_resolver.rb37
-rw-r--r--lib/chef/provider_resolver/package/freebsd.rb59
-rw-r--r--lib/chef/provider_resolvers.rb20
-rw-r--r--lib/chef/providers.rb5
-rw-r--r--lib/chef/resource/freebsd_package.rb4
-rw-r--r--spec/unit/provider/package/freebsd/pkg_spec.rb (renamed from spec/unit/provider/package/freebsd_spec.rb)51
-rw-r--r--spec/unit/provider/package/freebsd/pkgng_spec.rb155
-rw-r--r--spec/unit/provider/package/freebsd/port_spec.rb160
-rw-r--r--spec/unit/provider/package/freebsd_next_gen_spec.rb204
-rw-r--r--spec/unit/provider_resolver/package/freebsd_spec.rb65
-rw-r--r--spec/unit/resource/freebsd_package_spec.rb5
19 files changed, 888 insertions, 527 deletions
diff --git a/lib/chef.rb b/lib/chef.rb
index 0d5fb3de2c..89e3ff375d 100644
--- a/lib/chef.rb
+++ b/lib/chef.rb
@@ -23,6 +23,7 @@ require 'chef/exceptions'
require 'chef/log'
require 'chef/config'
require 'chef/providers'
+require 'chef/provider_resolvers'
require 'chef/resources'
require 'chef/shell_out'
diff --git a/lib/chef/platform/provider_mapping.rb b/lib/chef/platform/provider_mapping.rb
index 3fe3f97dbb..ce2f34347d 100644
--- a/lib/chef/platform/provider_mapping.rb
+++ b/lib/chef/platform/provider_mapping.rb
@@ -31,6 +31,7 @@ require 'chef/provider/mount'
require 'chef/provider/service'
require 'chef/provider/package'
require 'chef/provider/ifconfig'
+require 'chef/provider_resolver'
class Chef
@@ -60,13 +61,10 @@ class Chef
:freebsd => {
:default => {
:group => Chef::Provider::Group::Pw,
- :package => Chef::Provider::Package::Freebsd,
+ :package => Chef::ProviderResolver::Package::Freebsd,
:service => Chef::Provider::Service::Freebsd,
:user => Chef::Provider::User::Pw,
:cron => Chef::Provider::Cron
- },
- ">= 10.0" => {
- :package => Chef::Provider::Package::FreebsdNextGen
}
},
:ubuntu => {
@@ -453,7 +451,13 @@ class Chef
def find_provider_for_node(node, resource_type)
platform, version = find_platform_and_version(node)
- find_provider(platform, version, resource_type)
+ provider = find_provider(platform, version, resource_type)
+
+ if provider.is_a?(Class) && provider.ancestors.include?(Chef::ProviderResolver)
+ provider.new(node, resource_type).resolve
+ else
+ provider
+ end
end
def set(args)
diff --git a/lib/chef/provider/package/freebsd.rb b/lib/chef/provider/package/freebsd.rb
deleted file mode 100644
index f9cb5eb422..0000000000
--- a/lib/chef/provider/package/freebsd.rb
+++ /dev/null
@@ -1,149 +0,0 @@
-#
-# Authors:: Bryan McLellan (btm@loftninjas.org)
-# Matthew Landauer (matthew@openaustralia.org)
-# Copyright:: Copyright (c) 2009 Bryan McLellan, Matthew Landauer
-# 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'
-require 'chef/mixin/shell_out'
-require 'chef/resource/package'
-require 'chef/mixin/get_source_from_package'
-
-class Chef
- class Provider
- class Package
- class Freebsd < Chef::Provider::Package
- include Chef::Mixin::ShellOut
-
- include Chef::Mixin::GetSourceFromPackage
-
- def initialize(*args)
- super
- @current_resource = Chef::Resource::Package.new(@new_resource.name)
- end
-
- def current_installed_version
- pkg_info = shell_out!("pkg_info -E \"#{package_name}*\"", :env => nil, :returns => [0,1])
- pkg_info.stdout[/^#{Regexp.escape(package_name)}-(.+)/, 1]
- end
-
- def port_path
- case @new_resource.package_name
- # When the package name starts with a '/' treat it as the full path to the ports directory
- when /^\//
- @new_resource.package_name
- # Otherwise if the package name contains a '/' not at the start (like 'www/wordpress') treat as a relative
- # path from /usr/ports
- when /\//
- "/usr/ports/#{@new_resource.package_name}"
- # Otherwise look up the path to the ports directory using 'whereis'
- else
- whereis = shell_out!("whereis -s #{@new_resource.package_name}", :env => nil)
- unless path = whereis.stdout[/^#{Regexp.escape(@new_resource.package_name)}:\s+(.+)$/, 1]
- raise Chef::Exceptions::Package, "Could not find port with the name #{@new_resource.package_name}"
- end
- path
- end
- end
-
- def ports_makefile_variable_value(variable)
- make_v = shell_out!("make -V #{variable}", :cwd => port_path, :env => nil, :returns => [0,1])
- make_v.stdout.strip.split($\).first # $\ is the line separator, i.e., newline
- end
-
- def ports_candidate_version
- ports_makefile_variable_value("PORTVERSION")
- end
-
- def file_candidate_version_path
- Dir["#{@new_resource.source}/#{@current_resource.package_name}*"][-1].to_s
- end
-
- def file_candidate_version
- file_candidate_version_path.split(/-/).last.split(/.tbz/).first
- end
-
- def load_current_resource
- @current_resource.package_name(@new_resource.package_name)
-
- @current_resource.version(current_installed_version)
- Chef::Log.debug("#{@new_resource} current version is #{@current_resource.version}") if @current_resource.version
-
- case @new_resource.source
- when /^http/, /^ftp/
- @candidate_version = "0.0.0"
- when /^\//
- @candidate_version = file_candidate_version
- else
- @candidate_version = ports_candidate_version
- end
-
- Chef::Log.debug("#{@new_resource} ports candidate version is #{@candidate_version}") if @candidate_version
-
- @current_resource
- end
-
- def latest_link_name
- ports_makefile_variable_value("LATEST_LINK")
- end
-
- # The name of the package (without the version number) as understood by pkg_add and pkg_info
- def package_name
- if ::File.exist?("/usr/ports/Makefile")
- if ports_makefile_variable_value("PKGNAME") =~ /^(.+)-[^-]+$/
- $1
- else
- raise Chef::Exceptions::Package, "Unexpected form for PKGNAME variable in #{port_path}/Makefile"
- end
- else
- @new_resource.package_name
- end
- end
-
- def install_package(name, version)
- unless @current_resource.version
- case @new_resource.source
- when /^ports$/
- shell_out!("make -DBATCH install", :timeout => 1200, :env => nil, :cwd => port_path).status
- when /^http/, /^ftp/
- if @new_resource.source =~ /\/$/
- shell_out!("pkg_add -r #{package_name}", :env => { "PACKAGESITE" => @new_resource.source, 'LC_ALL' => nil }).status
- else
- shell_out!("pkg_add -r #{package_name}", :env => { "PACKAGEROOT" => @new_resource.source, 'LC_ALL' => nil }).status
- end
- Chef::Log.debug("#{@new_resource} installed from: #{@new_resource.source}")
- when /^\//
- shell_out!("pkg_add #{file_candidate_version_path}", :env => { "PKG_PATH" => @new_resource.source , 'LC_ALL'=>nil}).status
- Chef::Log.debug("#{@new_resource} installed from: #{@new_resource.source}")
- else
- shell_out!("pkg_add -r #{latest_link_name}", :env => nil).status
- end
- end
- end
-
- def remove_package(name, version)
- # a version is mandatory
- if version
- shell_out!("pkg_delete #{package_name}-#{version}", :env => nil).status
- else
- shell_out!("pkg_delete #{package_name}-#{@current_resource.version}", :env => nil).status
- end
- end
-
- end
- end
- end
-end
diff --git a/lib/chef/provider/package/freebsd/base.rb b/lib/chef/provider/package/freebsd/base.rb
new file mode 100644
index 0000000000..24f79484f0
--- /dev/null
+++ b/lib/chef/provider/package/freebsd/base.rb
@@ -0,0 +1,92 @@
+#
+# Authors:: Bryan McLellan (btm@loftninjas.org)
+# Matthew Landauer (matthew@openaustralia.org)
+# Richard Manyanza (liseki@nyikacraftsmen.com)
+# Copyright:: Copyright (c) 2009 Bryan McLellan, Matthew Landauer
+# Copyright:: Copyright (c) 2014 Richard Manyanza
+# 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/provider/package'
+require 'chef/mixin/shell_out'
+require 'chef/mixin/get_source_from_package'
+
+class Chef
+ class Provider
+ class Package
+ module Freebsd
+
+ module PortsHelper
+ def supports_ports?
+ ::File.exist?("/usr/ports/Makefile")
+ end
+
+ def port_dir(port)
+ case port
+
+ # When the package name starts with a '/' treat it as the full path to the ports directory.
+ when /^\//
+ port
+
+ # Otherwise if the package name contains a '/' not at the start (like 'www/wordpress') treat
+ # as a relative path from /usr/ports.
+ when /\//
+ "/usr/ports/#{port}"
+
+ # Otherwise look up the path to the ports directory using 'whereis'
+ else
+ whereis = shell_out!("whereis -s #{port}", :env => nil)
+ unless _path = whereis.stdout[/^#{Regexp.escape(port)}:\s+(.+)$/, 1]
+ raise Chef::Exceptions::Package, "Could not find port with the name #{port}"
+ end
+ _path
+ end
+ end
+
+ def makefile_variable_value(variable, dir = nil)
+ options = dir ? { :cwd => dir } : {}
+ make_v = shell_out!("make -V #{variable}", options.merge!(:env => nil, :returns => [0,1]))
+ make_v.exitstatus.zero? ? make_v.stdout.strip.split($\).first : nil # $\ is the line separator, i.e. newline.
+ end
+ end
+
+
+ class Base < Chef::Provider::Package
+ include Chef::Mixin::ShellOut
+ include Chef::Mixin::GetSourceFromPackage
+
+ def initialize(*args)
+ super
+ @current_resource = Chef::Resource::Package.new(@new_resource.name)
+ end
+
+ def load_current_resource
+ @current_resource.package_name(@new_resource.package_name)
+
+ @current_resource.version(current_installed_version)
+ Chef::Log.debug("#{@new_resource} current version is #{@current_resource.version}") if @current_resource.version
+
+ @candidate_version = candidate_version
+ Chef::Log.debug("#{@new_resource} candidate version is #{@candidate_version}") if @candidate_version
+
+ @current_resource
+ end
+ end
+
+ end
+ end
+ end
+end
diff --git a/lib/chef/provider/package/freebsd/pkg.rb b/lib/chef/provider/package/freebsd/pkg.rb
new file mode 100644
index 0000000000..c757d26fe5
--- /dev/null
+++ b/lib/chef/provider/package/freebsd/pkg.rb
@@ -0,0 +1,113 @@
+#
+# Authors:: Bryan McLellan (btm@loftninjas.org)
+# Matthew Landauer (matthew@openaustralia.org)
+# Richard Manyanza (liseki@nyikacraftsmen.com)
+# Copyright:: Copyright (c) 2009 Bryan McLellan, Matthew Landauer
+# Copyright:: Copyright (c) 2014 Richard Manyanza
+# 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/freebsd/base'
+
+class Chef
+ class Provider
+ class Package
+ module Freebsd
+ class Pkg < Base
+ include PortsHelper
+
+ def install_package(name, version)
+ unless @current_resource.version
+ case @new_resource.source
+ when /^http/, /^ftp/
+ if @new_resource.source =~ /\/$/
+ shell_out!("pkg_add -r #{package_name}", :env => { "PACKAGESITE" => @new_resource.source, 'LC_ALL' => nil }).status
+ else
+ shell_out!("pkg_add -r #{package_name}", :env => { "PACKAGEROOT" => @new_resource.source, 'LC_ALL' => nil }).status
+ end
+ Chef::Log.debug("#{@new_resource} installed from: #{@new_resource.source}")
+
+ when /^\//
+ shell_out!("pkg_add #{file_candidate_version_path}", :env => { "PKG_PATH" => @new_resource.source , 'LC_ALL'=>nil}).status
+ Chef::Log.debug("#{@new_resource} installed from: #{@new_resource.source}")
+
+ else
+ shell_out!("pkg_add -r #{latest_link_name}", :env => nil).status
+ end
+ end
+ end
+
+ def remove_package(name, version)
+ shell_out!("pkg_delete #{package_name}-#{version || @current_resource.version}", :env => nil).status
+ end
+
+ # The name of the package (without the version number) as understood by pkg_add and pkg_info.
+ def package_name
+ if supports_ports?
+ if makefile_variable_value("PKGNAME", port_path) =~ /^(.+)-[^-]+$/
+ $1
+ else
+ raise Chef::Exceptions::Package, "Unexpected form for PKGNAME variable in #{port_path}/Makefile"
+ end
+ else
+ @new_resource.package_name
+ end
+ end
+
+ def latest_link_name
+ makefile_variable_value("LATEST_LINK", port_path)
+ end
+
+ def current_installed_version
+ pkg_info = shell_out!("pkg_info -E \"#{package_name}*\"", :env => nil, :returns => [0,1])
+ pkg_info.stdout[/^#{Regexp.escape(package_name)}-(.+)/, 1]
+ end
+
+ def candidate_version
+ case @new_resource.source
+ when /^http/, /^ftp/
+ repo_candidate_version
+ when /^\//
+ file_candidate_version
+ else
+ ports_candidate_version
+ end
+ end
+
+ def file_candidate_version_path
+ Dir["#{@new_resource.source}/#{@current_resource.package_name}*"][-1].to_s
+ end
+
+ def file_candidate_version
+ file_candidate_version_path.split(/-/).last.split(/.tbz/).first
+ end
+
+ def repo_candidate_version
+ "0.0.0"
+ end
+
+ def ports_candidate_version
+ makefile_variable_value("PORTVERSION", port_path)
+ end
+
+ def port_path
+ port_dir @new_resource.package_name
+ end
+
+ end
+ end
+ end
+ end
+end
diff --git a/lib/chef/provider/package/freebsd/pkgng.rb b/lib/chef/provider/package/freebsd/pkgng.rb
new file mode 100644
index 0000000000..da531facc1
--- /dev/null
+++ b/lib/chef/provider/package/freebsd/pkgng.rb
@@ -0,0 +1,80 @@
+#
+# Authors:: Richard Manyanza (liseki@nyikacraftsmen.com)
+# Copyright:: Copyright (c) 2014 Richard Manyanza
+# 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/freebsd/base'
+
+class Chef
+ class Provider
+ class Package
+ module Freebsd
+ class Pkgng < Base
+
+ def install_package(name, version)
+ unless @current_resource.version
+ case @new_resource.source
+ when /^(http|ftp|\/)/
+ shell_out!("pkg add#{expand_options(@new_resource.options)} #{@new_resource.source}", :env => { 'LC_ALL' => nil }).status
+ Chef::Log.debug("#{@new_resource} installed from: #{@new_resource.source}")
+
+ else
+ shell_out!("pkg install -y#{expand_options(@new_resource.options)} #{name}", :env => { 'LC_ALL' => nil }).status
+ end
+ end
+ end
+
+ def remove_package(name, version)
+ options = @new_resource.options && @new_resource.options.sub(repo_regex, '')
+ options && !options.empty? || options = nil
+ shell_out!("pkg delete -y#{expand_options(options)} #{name}#{version ? '-' + version : ''}", :env => nil).status
+ end
+
+ def current_installed_version
+ pkg_info = shell_out!("pkg info \"#{@new_resource.package_name}\"", :env => nil, :returns => [0,70])
+ pkg_info.stdout[/^#{Regexp.escape(@new_resource.package_name)}-(.+)/, 1]
+ end
+
+ def candidate_version
+ @new_resource.source ? file_candidate_version : repo_candidate_version
+ end
+
+
+
+ private
+
+ def file_candidate_version
+ @new_resource.source[/#{Regexp.escape(@new_resource.package_name)}-(.+)\.txz/, 1]
+ end
+
+ def repo_candidate_version
+ if @new_resource.options && @new_resource.options.match(repo_regex)
+ options = $1
+ end
+
+ pkg_query = shell_out!("pkg rquery#{expand_options(options)} '%v' #{@new_resource.package_name}", :env => nil)
+ pkg_query.exitstatus.zero? ? pkg_query.stdout.strip.split(/\n/).last : nil
+ end
+
+ def repo_regex
+ /(-r\s?\S+)\b/
+ end
+
+ end
+ end
+ end
+ end
+end
diff --git a/lib/chef/provider/package/freebsd/port.rb b/lib/chef/provider/package/freebsd/port.rb
new file mode 100644
index 0000000000..6f4471a6f7
--- /dev/null
+++ b/lib/chef/provider/package/freebsd/port.rb
@@ -0,0 +1,70 @@
+#
+# Authors:: Richard Manyanza (liseki@nyikacraftsmen.com)
+# Copyright:: Copyright (c) 2014 Richard Manyanza
+# 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/freebsd/base'
+
+class Chef
+ class Provider
+ class Package
+ module Freebsd
+ class Port < Base
+ include PortsHelper
+
+ def install_package(name, version)
+ shell_out!("make -DBATCH install clean", :timeout => 1800, :env => nil, :cwd => port_dir).status
+ end
+
+ def remove_package(name, version)
+ shell_out!("make deinstall", :timeout => 300, :env => nil, :cwd => port_dir).status
+ end
+
+ def current_installed_version
+ pkg_info = if supports_pkgng?
+ shell_out!("pkg info \"#{@new_resource.package_name}\"", :env => nil, :returns => [0,70])
+ else
+ shell_out!("pkg_info -E \"#{@new_resource.package_name}*\"", :env => nil, :returns => [0,1])
+ end
+ pkg_info.stdout[/^#{Regexp.escape(@new_resource.package_name)}-(.+)/, 1]
+ end
+
+ def candidate_version
+ if supports_ports?
+ makefile_variable_value("PORTVERSION", port_dir)
+ else
+ raise Chef::Exceptions::Package, "Ports collection could not be found"
+ end
+ end
+
+ def port_dir
+ super(@new_resource.package_name)
+ end
+
+
+
+ private
+
+ def supports_pkgng?
+ with_pkgng = makefile_variable_value('WITH_PKGNG')
+ with_pkgng && with_pkgng =~ /yes/i
+ end
+
+ end
+ end
+ end
+ end
+end
diff --git a/lib/chef/provider/package/freebsd_next_gen.rb b/lib/chef/provider/package/freebsd_next_gen.rb
deleted file mode 100644
index d7dcd757bc..0000000000
--- a/lib/chef/provider/package/freebsd_next_gen.rb
+++ /dev/null
@@ -1,131 +0,0 @@
-#
-# Authors:: Richard Manyanza (liseki@nyikacraftsmen.com)
-# Copyright:: Copyright (c) 2013 Richard Manyanza
-# 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'
-require 'chef/mixin/shell_out'
-require 'chef/resource/package'
-require 'chef/mixin/get_source_from_package'
-
-class Chef
- class Provider
- class Package
- class FreebsdNextGen < Chef::Provider::Package
- include Chef::Mixin::ShellOut
-
- include Chef::Mixin::GetSourceFromPackage
-
- def initialize(*args)
- super
- @current_resource = Chef::Resource::Package.new(@new_resource.name)
- end
-
- def load_current_resource
- @current_resource.package_name(@new_resource.package_name)
-
- @current_resource.version(current_installed_version)
- Chef::Log.debug("#{@new_resource} current version is #{@current_resource.version}") if @current_resource.version
-
- @candidate_version = case @new_resource.source
- when /^ports$/i
- ports_candidate_version
- else
- package_candidate_version
- end
-
- Chef::Log.debug("#{@new_resource} ports candidate version is #{@candidate_version}") if @candidate_version
-
- @current_resource
- end
-
- def install_package(name, version)
- unless @current_resource.version
- case @new_resource.source
- when /^ports$/i
- shell_out!("make -DBATCH install", :timeout => 1800, :env => nil, :cwd => port_path).status
- when /^(http|ftp|\/)/
- shell_out!("pkg add#{expand_options(@new_resource.options)} #{@new_resource.source}", :env => { 'LC_ALL' => nil }).status
- Chef::Log.debug("#{@new_resource} installed from: #{@new_resource.source}")
- else
- shell_out!("pkg install#{expand_options(@new_resource.options || '-y')} #{name}", :env => { 'LC_ALL' => nil }).status
- end
- end
- end
-
- def remove_package(name, version)
- shell_out!("pkg delete#{expand_options(@new_resource.options || '-y')} #{name}#{version ? '-' + version : ''}", :env => nil).status
- end
-
-
-
-
- private
-
- def current_installed_version
- pkg_info = shell_out!("pkg info \"#{@new_resource.package_name}\"", :env => nil, :returns => [0,70])
- pkg_info.stdout[/^#{Regexp.escape(@new_resource.package_name)}-(.+)/, 1]
- end
-
- def package_candidate_version
- if @new_resource.source
- @new_resource.source[/#{Regexp.escape(@new_resource.package_name)}-(.+)\.[[:alpha:]]{3}/, 1]
- else
- repo_candidate_version
- end
- end
-
- def repo_candidate_version
- if @new_resource.options && @new_resource.options.match(/(r .+)\b/)
- options = "-#{$1}"
- end
-
- pkg_query = shell_out!("pkg rquery#{expand_options(options)} '%v' #{@new_resource.package_name}", :env => nil, :returns => [0,69])
- pkg_query.stdout.strip.split(/\n/).first
- end
-
- def ports_candidate_version
- ports_makefile_variable_value("PORTVERSION")
- end
-
- def port_path
- case @new_resource.package_name
- # When the package name starts with a '/' treat it as the full path to the ports directory
- when /^\//
- @new_resource.package_name
- # Otherwise if the package name contains a '/' not at the start (like 'www/wordpress') treat as a relative
- # path from /usr/ports
- when /\//
- "/usr/ports/#{@new_resource.package_name}"
- # Otherwise look up the path to the ports directory using 'whereis'
- else
- whereis = shell_out!("whereis -s #{@new_resource.package_name}", :env => nil)
- unless path = whereis.stdout[/^#{Regexp.escape(@new_resource.package_name)}:\s+(.+)$/, 1]
- raise Chef::Exceptions::Package, "Could not find port with the name #{@new_resource.package_name}"
- end
- path
- end
- end
-
- def ports_makefile_variable_value(variable)
- make_v = shell_out!("make -V #{variable}", :cwd => port_path, :env => nil, :returns => [0,1])
- make_v.stdout.strip.split(/\n/).first
- end
-
- end
- end
- end
-end
diff --git a/lib/chef/provider_resolver.rb b/lib/chef/provider_resolver.rb
new file mode 100644
index 0000000000..6864036cfb
--- /dev/null
+++ b/lib/chef/provider_resolver.rb
@@ -0,0 +1,37 @@
+#
+# Authors:: Richard Manyanza (liseki@nyikacraftsmen.com)
+# Copyright:: Copyright (c) 2014 Richard Manyanza
+# 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/exceptions'
+
+class Chef
+ class ProviderResolver
+ attr_reader :node, :resource
+
+ def initialize(node, resource)
+ @node = node
+ @resource = resource
+ end
+
+ def resolve
+ raise Chef::Exceptions::NotImplementedError, "Implement a resolve method"
+ end
+ end
+end
+
+
+
diff --git a/lib/chef/provider_resolver/package/freebsd.rb b/lib/chef/provider_resolver/package/freebsd.rb
new file mode 100644
index 0000000000..c7f07cafc6
--- /dev/null
+++ b/lib/chef/provider_resolver/package/freebsd.rb
@@ -0,0 +1,59 @@
+#
+# Authors:: Richard Manyanza (liseki@nyikacraftsmen.com)
+# Copyright:: Copyright (c) 2014 Richard Manyanza
+# 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_resolver'
+require 'chef/provider/package/freebsd/port'
+require 'chef/provider/package/freebsd/pkg'
+require 'chef/provider/package/freebsd/pkgng'
+require 'chef/mixin/shell_out'
+
+class Chef
+ class ProviderResolver
+ module Package
+ class Freebsd < Chef::ProviderResolver
+ include Chef::Mixin::ShellOut
+
+ def resolve
+ if resource.source.to_s =~ /^ports$/i
+ Chef::Provider::Package::Freebsd::Port
+ elsif ships_with_pkgng? || supports_pkgng?
+ Chef::Provider::Package::Freebsd::Pkgng
+ else
+ Chef::Provider::Package::Freebsd::Pkg
+ end
+ end
+
+
+
+ private
+
+ def ships_with_pkgng?
+ # It was not until __FreeBSD_version 1000017 that pkgng became
+ # the default binary package manager. See '/usr/ports/Mk/bsd.port.mk'.
+ node[:os_version].to_i >= 1000017
+ end
+
+ def supports_pkgng?
+ !!shell_out!("make -V WITH_PKGNG", :env => nil).stdout.match(/yes/i)
+ end
+ end
+ end
+ end
+end
+
+
diff --git a/lib/chef/provider_resolvers.rb b/lib/chef/provider_resolvers.rb
new file mode 100644
index 0000000000..df82201d03
--- /dev/null
+++ b/lib/chef/provider_resolvers.rb
@@ -0,0 +1,20 @@
+#
+# Authors:: Richard Manyanza (liseki@nyikacraftsmen.com)
+# Copyright:: Copyright (c) 2014 Richard Manyanza
+# 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_resolver/package/freebsd'
+
diff --git a/lib/chef/providers.rb b/lib/chef/providers.rb
index e5843596b0..d6e70c1d4e 100644
--- a/lib/chef/providers.rb
+++ b/lib/chef/providers.rb
@@ -55,8 +55,9 @@ require 'chef/provider/env/windows'
require 'chef/provider/package/apt'
require 'chef/provider/package/dpkg'
require 'chef/provider/package/easy_install'
-require 'chef/provider/package/freebsd'
-require 'chef/provider/package/freebsd_next_gen'
+require 'chef/provider/package/freebsd/port'
+require 'chef/provider/package/freebsd/pkg'
+require 'chef/provider/package/freebsd/pkgng'
require 'chef/provider/package/ips'
require 'chef/provider/package/macports'
require 'chef/provider/package/pacman'
diff --git a/lib/chef/resource/freebsd_package.rb b/lib/chef/resource/freebsd_package.rb
index 94286eae18..934e42e816 100644
--- a/lib/chef/resource/freebsd_package.rb
+++ b/lib/chef/resource/freebsd_package.rb
@@ -17,7 +17,6 @@
#
require 'chef/resource/package'
-require 'chef/provider/package/freebsd'
class Chef
class Resource
@@ -26,7 +25,8 @@ class Chef
def initialize(name, run_context=nil)
super
@resource_name = :freebsd_package
- @provider = Chef::Provider::Package::Freebsd
+
+ # The provider is resolved by Chef::ProviderResolver::Package::Freebsd.
end
end
diff --git a/spec/unit/provider/package/freebsd_spec.rb b/spec/unit/provider/package/freebsd/pkg_spec.rb
index 962f9c23d1..9b2493a4c5 100644
--- a/spec/unit/provider/package/freebsd_spec.rb
+++ b/spec/unit/provider/package/freebsd/pkg_spec.rb
@@ -20,7 +20,7 @@
require 'spec_helper'
require 'ostruct'
-describe Chef::Provider::Package::Freebsd, "load_current_resource" do
+describe Chef::Provider::Package::Freebsd::Pkg, "load_current_resource" do
before(:each) do
@node = Chef::Node.new
@events = Chef::EventDispatch::Dispatcher.new
@@ -28,7 +28,7 @@ describe Chef::Provider::Package::Freebsd, "load_current_resource" do
@new_resource = Chef::Resource::Package.new("zsh")
@current_resource = Chef::Resource::Package.new("zsh")
- @provider = Chef::Provider::Package::Freebsd.new(@new_resource, @run_context)
+ @provider = Chef::Provider::Package::Freebsd::Pkg.new(@new_resource, @run_context)
@provider.current_resource = @current_resource
::File.stub(:exist?).with('/usr/ports/Makefile').and_return(false)
end
@@ -39,7 +39,7 @@ describe Chef::Provider::Package::Freebsd, "load_current_resource" do
end
it "should create a current resource with the name of the new_resource" do
- current_resource = Chef::Provider::Package::Freebsd.new(@new_resource, @run_context).current_resource
+ current_resource = Chef::Provider::Package::Freebsd::Pkg.new(@new_resource, @run_context).current_resource
current_resource.name.should == "zsh"
end
@@ -66,7 +66,7 @@ describe Chef::Provider::Package::Freebsd, "load_current_resource" do
before do
#@new_resource = Chef::Resource::Package.new("zsh")
- #@provider = Chef::Provider::Package::Freebsd.new(@node, @new_resource)
+ #@provider = Chef::Provider::Package::Freebsd::Pkg.new(@node, @new_resource)
#@status = double("Status", :exitstatus => 0)
#@stdin = double("STDIN", :null_object => true)
@@ -101,7 +101,7 @@ describe Chef::Provider::Package::Freebsd, "load_current_resource" do
# Not happy with the form of these tests as they are far too closely tied to the implementation and so very fragile.
it "should return the ports candidate version when given a valid port path" do
@provider.stub(:port_path).and_return("/usr/ports/shells/zsh")
- make_v = OpenStruct.new(:stdout => "4.3.6\n")
+ make_v = OpenStruct.new(:stdout => "4.3.6\n", :exitstatus => 0)
@provider.should_receive(:shell_out!).with("make -V PORTVERSION", {:cwd=>"/usr/ports/shells/zsh", :returns=>[0, 1], :env=>nil}).and_return(make_v)
@provider.ports_candidate_version.should == "4.3.6"
end
@@ -109,14 +109,14 @@ describe Chef::Provider::Package::Freebsd, "load_current_resource" do
it "should figure out the package name when we have ports" do
::File.stub(:exist?).with('/usr/ports/Makefile').and_return(true)
@provider.stub(:port_path).and_return("/usr/ports/shells/zsh")
- make_v = OpenStruct.new(:stdout => "zsh-4.3.6_7\n")
+ make_v = OpenStruct.new(:stdout => "zsh-4.3.6_7\n", :exitstatus => 0)
@provider.should_receive(:shell_out!).with("make -V PKGNAME", {:cwd=>"/usr/ports/shells/zsh", :env=>nil, :returns=>[0, 1]}).and_return(make_v)
#@provider.should_receive(:ports_makefile_variable_value).with("PKGNAME").and_return("zsh-4.3.6_7")
@provider.package_name.should == "zsh"
end
end
- describe Chef::Provider::Package::Freebsd, "install_package" do
+ describe Chef::Provider::Package::Freebsd::Pkg, "install_package" do
before(:each) do
@cmd_result = OpenStruct.new(:status => true)
@@ -130,21 +130,14 @@ describe Chef::Provider::Package::Freebsd, "load_current_resource" do
@provider.should_receive(:shell_out!).with("pkg_add -r zsh", :env => nil).and_return(@cmd_result)
@provider.install_package("zsh", "4.3.6_7")
end
-
- it "should run make install when installing from ports" do
- @new_resource.stub(:source).and_return("ports")
- @provider.should_not_receive(:shell_out!).with("make -DBATCH -f /usr/ports/shells/zsh/Makefile install", :timeout => 1200, :env=>nil)
- @provider.should_receive(:shell_out!).with("make -DBATCH install", :timeout => 1200, :env=>nil, :cwd => @provider.port_path).and_return(@cmd_result)
- @provider.install_package("zsh", "4.3.6_7")
- end
end
- describe Chef::Provider::Package::Freebsd, "port path" do
+ describe Chef::Provider::Package::Freebsd::Pkg, "port path" do
before do
#@node = Chef::Node.new
@new_resource = Chef::Resource::Package.new("zsh")
@new_resource.cookbook_name = "adventureclub"
- @provider = Chef::Provider::Package::Freebsd.new(@new_resource, @run_context)
+ @provider = Chef::Provider::Package::Freebsd::Pkg.new(@new_resource, @run_context)
end
it "should figure out the port path from the package_name using whereis" do
@@ -155,7 +148,7 @@ describe Chef::Provider::Package::Freebsd, "load_current_resource" do
it "should use the package_name as the port path when it starts with /" do
new_resource = Chef::Resource::Package.new("/usr/ports/www/wordpress")
- provider = Chef::Provider::Package::Freebsd.new(new_resource, @run_context)
+ provider = Chef::Provider::Package::Freebsd::Pkg.new(new_resource, @run_context)
provider.should_not_receive(:popen4)
provider.port_path.should == "/usr/ports/www/wordpress"
end
@@ -165,17 +158,17 @@ describe Chef::Provider::Package::Freebsd, "load_current_resource" do
# :package_name => "www/wordpress",
# :cookbook_name => "xenoparadox")
new_resource = Chef::Resource::Package.new("www/wordpress")
- provider = Chef::Provider::Package::Freebsd.new(new_resource, @run_context)
+ provider = Chef::Provider::Package::Freebsd::Pkg.new(new_resource, @run_context)
provider.should_not_receive(:popen4)
provider.port_path.should == "/usr/ports/www/wordpress"
end
end
- describe Chef::Provider::Package::Freebsd, "ruby-iconv (package with a dash in the name)" do
+ describe Chef::Provider::Package::Freebsd::Pkg, "ruby-iconv (package with a dash in the name)" do
before(:each) do
@new_resource = Chef::Resource::Package.new("ruby-iconv")
@current_resource = Chef::Resource::Package.new("ruby-iconv")
- @provider = Chef::Provider::Package::Freebsd.new(@new_resource, @run_context)
+ @provider = Chef::Provider::Package::Freebsd::Pkg.new(@new_resource, @run_context)
@provider.current_resource = @current_resource
@provider.stub(:port_path).and_return("/usr/ports/converters/ruby-iconv")
@provider.stub(:package_name).and_return("ruby18-iconv")
@@ -188,15 +181,9 @@ describe Chef::Provider::Package::Freebsd, "load_current_resource" do
@provider.should_receive(:shell_out!).with("pkg_add -r ruby18-iconv", :env => nil).and_return(@install_result)
@provider.install_package("ruby-iconv", "1.0")
end
-
- it "should run make install when installing from ports" do
- @new_resource.stub(:source).and_return("ports")
- @provider.should_receive(:shell_out!).with("make -DBATCH install", :timeout => 1200, :env=>nil, :cwd => @provider.port_path).and_return(@install_result)
- @provider.install_package("ruby-iconv", "1.0")
- end
end
- describe Chef::Provider::Package::Freebsd, "remove_package" do
+ describe Chef::Provider::Package::Freebsd::Pkg, "remove_package" do
before(:each) do
@pkg_delete = OpenStruct.new(:status => true)
@new_resource.version "4.3.6_7"
@@ -216,11 +203,11 @@ describe Chef::Provider::Package::Freebsd, "load_current_resource" do
# version of a package is currently installed and to get the port_path.
# Example package name: bonnie++
- describe Chef::Provider::Package::Freebsd, "bonnie++ (package with a plus in the name :: CHEF-4371)" do
+ describe Chef::Provider::Package::Freebsd::Pkg, "bonnie++ (package with a plus in the name :: CHEF-4371)" do
before(:each) do
@new_resource = Chef::Resource::Package.new("bonnie++")
@current_resource = Chef::Resource::Package.new("bonnie++")
- @provider = Chef::Provider::Package::Freebsd.new(@new_resource, @run_context)
+ @provider = Chef::Provider::Package::Freebsd::Pkg.new(@new_resource, @run_context)
@provider.current_resource = @current_resource
end
@@ -256,11 +243,11 @@ describe Chef::Provider::Package::Freebsd, "load_current_resource" do
# The variable LATEST_LINK is named that way because the directory that "pkg_add -r" downloads from is called "Latest" and
# contains the "latest" versions of package as symbolic links to the files in the "All" directory.
- describe Chef::Provider::Package::Freebsd, "install_package latest link fixes" do
+ describe Chef::Provider::Package::Freebsd::Pkg, "install_package latest link fixes" do
it "should install the perl binary package with the correct name" do
@new_resource = Chef::Resource::Package.new("perl5.8")
@current_resource = Chef::Resource::Package.new("perl5.8")
- @provider = Chef::Provider::Package::Freebsd.new(@new_resource, @run_context)
+ @provider = Chef::Provider::Package::Freebsd::Pkg.new(@new_resource, @run_context)
@provider.current_resource = @current_resource
@provider.stub(:package_name).and_return("perl")
@provider.stub(:latest_link_name).and_return("perl")
@@ -274,7 +261,7 @@ describe Chef::Provider::Package::Freebsd, "load_current_resource" do
@new_resource = Chef::Resource::Package.new("mysql50-server")
@current_resource = Chef::Resource::Package.new("mysql50-server")
- @provider = Chef::Provider::Package::Freebsd.new(@new_resource, @run_context)
+ @provider = Chef::Provider::Package::Freebsd::Pkg.new(@new_resource, @run_context)
@provider.current_resource = @current_resource
@provider.stub(:package_name).and_return("mysql-server")
@provider.stub(:latest_link_name).and_return("mysql50-server")
diff --git a/spec/unit/provider/package/freebsd/pkgng_spec.rb b/spec/unit/provider/package/freebsd/pkgng_spec.rb
new file mode 100644
index 0000000000..001c9e23ba
--- /dev/null
+++ b/spec/unit/provider/package/freebsd/pkgng_spec.rb
@@ -0,0 +1,155 @@
+#
+# Authors:: Richard Manyanza (liseki@nyikacraftsmen.com)
+# Copyright:: Copyright (c) 2014 Richard Manyanza
+# 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'
+require 'ostruct'
+
+describe Chef::Provider::Package::Freebsd::Port do
+ before(:each) do
+ @node = Chef::Node.new
+ @events = Chef::EventDispatch::Dispatcher.new
+ @run_context = Chef::RunContext.new(@node, {}, @events)
+
+ @new_resource = Chef::Resource::Package.new("zsh")
+ @provider = Chef::Provider::Package::Freebsd::Pkgng.new(@new_resource, @run_context)
+ end
+
+
+ describe "initialization" do
+ it "should create a current resource with the name of the new resource" do
+ @provider.current_resource.is_a?(Chef::Resource::Package).should be_true
+ @provider.current_resource.name.should == 'zsh'
+ end
+ end
+
+
+ describe "loading current resource" do
+ before(:each) do
+ @provider.stub(:current_installed_version)
+ @provider.stub(:candidate_version)
+ end
+
+ it "should set the package name" do
+ @provider.load_current_resource
+ @provider.current_resource.package_name.should == "zsh"
+ end
+
+ it "should set the current version" do
+ @provider.should_receive(:current_installed_version).and_return("5.0.2")
+ @provider.load_current_resource
+ @provider.current_resource.version.should == "5.0.2"
+ end
+
+ it "should set the candidate version" do
+ @provider.should_receive(:candidate_version).and_return("5.0.5")
+ @provider.load_current_resource
+ @provider.instance_variable_get(:"@candidate_version").should == "5.0.5"
+ end
+ end
+
+
+ describe "determining current installed version" do
+ before(:each) do
+ @provider.stub(:supports_pkgng?)
+ @pkg_info = OpenStruct.new(:stdout => "zsh-3.1.7\n")
+ end
+
+ it "should query pkg database" do
+ @provider.should_receive(:shell_out!).with('pkg info "zsh"', :env => nil, :returns => [0,70]).and_return(@pkg_info)
+ @provider.current_installed_version.should == "3.1.7"
+ end
+ end
+
+
+ describe "determining candidate version" do
+ it "should query repository" do
+ pkg_query = OpenStruct.new(:stdout => "5.0.5\n", :exitstatus => 0)
+ @provider.should_receive(:shell_out!).with("pkg rquery '%v' zsh", :env => nil).and_return(pkg_query)
+ @provider.candidate_version.should == "5.0.5"
+ end
+
+ it "should query specified repository when given option" do
+ @provider.new_resource.options('-r LocalMirror') # This requires LocalMirror repo configuration.
+ pkg_query = OpenStruct.new(:stdout => "5.0.3\n", :exitstatus => 0)
+ @provider.should_receive(:shell_out!).with("pkg rquery -r LocalMirror '%v' zsh", :env => nil).and_return(pkg_query)
+ @provider.candidate_version.should == "5.0.3"
+ end
+
+ it "should return candidate version from file when given a file" do
+ @provider.new_resource.source("/nas/pkg/repo/zsh-5.0.1.txz")
+ @provider.candidate_version.should == "5.0.1"
+ end
+ end
+
+
+ describe "installing a binary package" do
+ before(:each) do
+ @install_result = OpenStruct.new(:status => true)
+ end
+
+ it "should handle package source from file" do
+ @provider.new_resource.source("/nas/pkg/repo/zsh-5.0.1.txz")
+ @provider.should_receive(:shell_out!).
+ with("pkg add /nas/pkg/repo/zsh-5.0.1.txz", :env => { 'LC_ALL' => nil }).
+ and_return(@install_result)
+ @provider.install_package("zsh", "5.0.1")
+ end
+
+ it "should handle package source over ftp or http" do
+ @provider.new_resource.source("http://repo.example.com/zsh-5.0.1.txz")
+ @provider.should_receive(:shell_out!).
+ with("pkg add http://repo.example.com/zsh-5.0.1.txz", :env => { 'LC_ALL' => nil }).
+ and_return(@install_result)
+ @provider.install_package("zsh", "5.0.1")
+ end
+
+ it "should handle a package name" do
+ @provider.should_receive(:shell_out!).
+ with("pkg install -y zsh", :env => { 'LC_ALL' => nil }).and_return(@install_result)
+ @provider.install_package("zsh", "5.0.1")
+ end
+
+ it "should handle a package name with a specified repo" do
+ @provider.new_resource.options('-r LocalMirror') # This requires LocalMirror repo configuration.
+ @provider.should_receive(:shell_out!).
+ with("pkg install -y -r LocalMirror zsh", :env => { 'LC_ALL' => nil }).and_return(@install_result)
+ @provider.install_package("zsh", "5.0.1")
+ end
+ end
+
+
+ describe "removing a binary package" do
+ before(:each) do
+ @install_result = OpenStruct.new(:status => true)
+ end
+
+ it "should call pkg delete" do
+ @provider.should_receive(:shell_out!).
+ with("pkg delete -y zsh-5.0.1", :env => nil).and_return(@install_result)
+ @provider.remove_package("zsh", "5.0.1")
+ end
+
+ it "should not include repo option in pkg delete" do
+ @provider.new_resource.options('-r LocalMirror') # This requires LocalMirror repo configuration.
+ @provider.should_receive(:shell_out!).
+ with("pkg delete -y zsh-5.0.1", :env => nil).and_return(@install_result)
+ @provider.remove_package("zsh", "5.0.1")
+ end
+ end
+end
diff --git a/spec/unit/provider/package/freebsd/port_spec.rb b/spec/unit/provider/package/freebsd/port_spec.rb
new file mode 100644
index 0000000000..e946719451
--- /dev/null
+++ b/spec/unit/provider/package/freebsd/port_spec.rb
@@ -0,0 +1,160 @@
+#
+# Authors:: Richard Manyanza (liseki@nyikacraftsmen.com)
+# Copyright:: Copyright (c) 2014 Richard Manyanza
+# 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'
+require 'ostruct'
+
+describe Chef::Provider::Package::Freebsd::Port do
+ before(:each) do
+ @node = Chef::Node.new
+ @events = Chef::EventDispatch::Dispatcher.new
+ @run_context = Chef::RunContext.new(@node, {}, @events)
+
+ @new_resource = Chef::Resource::Package.new("zsh")
+ @provider = Chef::Provider::Package::Freebsd::Port.new(@new_resource, @run_context)
+ end
+
+
+ describe "initialization" do
+ it "should create a current resource with the name of the new resource" do
+ @provider.current_resource.is_a?(Chef::Resource::Package).should be_true
+ @provider.current_resource.name.should == 'zsh'
+ end
+ end
+
+
+ describe "loading current resource" do
+ before(:each) do
+ @provider.stub(:current_installed_version)
+ @provider.stub(:candidate_version)
+ end
+
+ it "should set the package name" do
+ @provider.load_current_resource
+ @provider.current_resource.package_name.should == "zsh"
+ end
+
+ it "should set the current version" do
+ @provider.should_receive(:current_installed_version).and_return("5.0.2")
+ @provider.load_current_resource
+ @provider.current_resource.version.should == "5.0.2"
+ end
+
+ it "should set the candidate version" do
+ @provider.should_receive(:candidate_version).and_return("5.0.5")
+ @provider.load_current_resource
+ @provider.instance_variable_get(:"@candidate_version").should == "5.0.5"
+ end
+ end
+
+
+ describe "determining current installed version" do
+ before(:each) do
+ @provider.stub(:supports_pkgng?)
+ @pkg_info = OpenStruct.new(:stdout => "zsh-3.1.7\n")
+ end
+
+ it "should check 'pkg_info' if system uses pkg_* tools" do
+ @provider.should_receive(:supports_pkgng?).and_return(false)
+ @provider.should_receive(:shell_out!).with('pkg_info -E "zsh*"', :env => nil, :returns => [0,1]).and_return(@pkg_info)
+ @provider.current_installed_version.should == "3.1.7"
+ end
+
+ it "should check 'pkg info' if system uses pkgng" do
+ @provider.should_receive(:supports_pkgng?).and_return(true)
+ @provider.should_receive(:shell_out!).with('pkg info "zsh"', :env => nil, :returns => [0,70]).and_return(@pkg_info)
+ @provider.current_installed_version.should == "3.1.7"
+ end
+ end
+
+
+ describe "determining candidate version" do
+ before(:each) do
+ @port_version = OpenStruct.new(:stdout => "5.0.5\n", :exitstatus => 0)
+ end
+
+ it "should return candidate version if port exists" do
+ ::File.stub(:exist?).with('/usr/ports/Makefile').and_return(true)
+ @provider.stub(:port_dir).and_return('/usr/ports/shells/zsh')
+ @provider.should_receive(:shell_out!).with("make -V PORTVERSION", :cwd => "/usr/ports/shells/zsh", :env => nil, :returns => [0,1]).
+ and_return(@port_version)
+ @provider.candidate_version.should == "5.0.5"
+ end
+
+ it "should raise exception if ports tree not found" do
+ ::File.stub(:exist?).with('/usr/ports/Makefile').and_return(false)
+ expect { @provider.candidate_version }.to raise_error(Chef::Exceptions::Package, "Ports collection could not be found")
+ end
+ end
+
+
+ describe "determining port directory" do
+ it "should return name if package name is absolute path" do
+ @provider.new_resource.stub(:package_name).and_return("/var/ports/shells/zsh")
+ @provider.port_dir.should == "/var/ports/shells/zsh"
+ end
+
+ it "should return full ports path given package name and category" do
+ @provider.new_resource.stub(:package_name).and_return("shells/zsh")
+ @provider.port_dir.should == "/usr/ports/shells/zsh"
+ end
+
+ it "should query system for path given just a name" do
+ whereis = OpenStruct.new(:stdout => "zsh: /usr/ports/shells/zsh\n")
+ @provider.should_receive(:shell_out!).with("whereis -s zsh", :env => nil).and_return(whereis)
+ @provider.port_dir.should == "/usr/ports/shells/zsh"
+ end
+
+ it "should raise exception if not found" do
+ whereis = OpenStruct.new(:stdout => "zsh:\n")
+ @provider.should_receive(:shell_out!).with("whereis -s zsh", :env => nil).and_return(whereis)
+ expect { @provider.port_dir }.to raise_error(Chef::Exceptions::Package, "Could not find port with the name zsh")
+ end
+ end
+
+
+ describe "building a binary package" do
+ before(:each) do
+ @install_result = OpenStruct.new(:status => true)
+ end
+
+ it "should run make install in port directory" do
+ @provider.stub(:port_dir).and_return("/usr/ports/shells/zsh")
+ @provider.should_receive(:shell_out!).
+ with("make -DBATCH install clean", :timeout => 1800, :cwd => "/usr/ports/shells/zsh", :env => nil).
+ and_return(@install_result)
+ @provider.install_package("zsh", "5.0.5")
+ end
+ end
+
+
+ describe "removing a binary package" do
+ before(:each) do
+ @install_result = OpenStruct.new(:status => true)
+ end
+
+ it "should run make deinstall in port directory" do
+ @provider.stub(:port_dir).and_return("/usr/ports/shells/zsh")
+ @provider.should_receive(:shell_out!).
+ with("make deinstall", :timeout => 300, :cwd => "/usr/ports/shells/zsh", :env => nil).
+ and_return(@install_result)
+ @provider.remove_package("zsh", "5.0.5")
+ end
+ end
+end
diff --git a/spec/unit/provider/package/freebsd_next_gen_spec.rb b/spec/unit/provider/package/freebsd_next_gen_spec.rb
deleted file mode 100644
index 6eb5faa55f..0000000000
--- a/spec/unit/provider/package/freebsd_next_gen_spec.rb
+++ /dev/null
@@ -1,204 +0,0 @@
-#
-# Authors:: Richard Manyanza (liseki@nyikacraftsmen.com)
-# Copyright:: Copyright (c) 2013 Richard Manyanza
-# 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'
-require 'ostruct'
-
-
-describe Chef::Provider::Package::FreebsdNextGen do
- before(:each) do
- @node = Chef::Node.new
- @events = Chef::EventDispatch::Dispatcher.new
- @run_context = Chef::RunContext.new(@node, {}, @events)
- @new_resource = Chef::Resource::Package.new("zsh")
- @provider = Chef::Provider::Package::FreebsdNextGen.new(@new_resource, @run_context)
- end
-
-
- describe "initialization" do
- it "should create a current resource with the name of the new resource" do
- @provider.current_resource.is_a?(Chef::Resource::Package).should be_true
- @provider.current_resource.name.should == 'zsh'
- end
- end
-
-
- describe "loading current resource" do
- before(:each) do
- @provider.stub!(:current_installed_version).and_return(nil)
- @provider.stub!(:ports_candidate_version).and_return("5.0.2_1")
- @provider.stub!(:repo_candidate_version).and_return("5.0.2_5")
- end
-
- it "should set current version if the package is installed" do
- @provider.should_receive(:current_installed_version).and_return("5.0.2")
- @provider.load_current_resource
- @provider.current_resource.version.should == "5.0.2"
- end
-
- it "should not set current version if the package is not installed" do
- @provider.load_current_resource
- @provider.current_resource.version.should be_nil
- end
-
- it "should set candidate version from port if building port" do
- @new_resource.source('ports')
- @provider.load_current_resource
- @provider.candidate_version.should == "5.0.2_1"
- end
-
- it "should set candidate version from file if adding local or remote package" do
- @new_resource.source('/root/packages/zsh-5.0.2_3.txz')
- @provider.load_current_resource
- @provider.candidate_version.should == "5.0.2_3"
- end
- end
-
-
- describe "querying repository for package version" do
- before(:each) do
- @provider.stub!(:current_installed_version).and_return(nil)
- @pkg_query = OpenStruct.new(:stdout => "5.0.2_1")
- end
-
- it "should make call to repository" do
- @provider.should_receive(:shell_out!).with("pkg rquery '%v' zsh", :env => nil, :returns => [0,69]).and_return(@pkg_query)
- @provider.load_current_resource
- @provider.candidate_version.should == "5.0.2_1"
- end
-
- it "should be able to use custom repository option" do
- @provider.should_receive(:shell_out!).with("pkg rquery -r http://pkgrepo.example.com '%v' zsh", :env => nil, :returns => [0,69]).and_return(@pkg_query)
- @new_resource.options('-r http://pkgrepo.example.com')
- @provider.load_current_resource
- end
- end
-
-
- describe "querying package state" do
- it "should return version number if package is installed" do
- pkg_info = OpenStruct.new(:stdout => "zsh-4.3.6_7")
- @provider.should_receive(:shell_out!).with('pkg info "zsh"', :env => nil, :returns => [0,70]).and_return(pkg_info)
- @provider.send(:current_installed_version).should == "4.3.6_7"
- end
-
- it "should not return a version number if package is not installed" do
- pkg_info = OpenStruct.new(:stdout => "pkg: No package(s) matching zsh")
- @provider.should_receive(:shell_out!).with('pkg info "zsh"', :env => nil, :returns => [0,70]).and_return(pkg_info)
- @provider.send(:current_installed_version).should be_nil
- end
-
- it "should return the port path for a valid port name" do
- whereis = OpenStruct.new(:stdout => "zsh: /usr/ports/shells/zsh")
- @provider.should_receive(:shell_out!).with("whereis -s zsh", :env => nil).and_return(whereis)
- @provider.send(:port_path).should == '/usr/ports/shells/zsh'
- end
-
- it "should return the ports candidate version when given a valid port path" do
- @provider.stub!(:port_path).and_return("/usr/ports/shells/zsh")
- make_v = OpenStruct.new(:stdout => "4.3.6\n")
- @provider.should_receive(:shell_out!).with("make -V PORTVERSION", {:cwd=>"/usr/ports/shells/zsh", :returns=>[0, 1], :env=>nil}).and_return(make_v)
- @provider.send(:ports_candidate_version).should == "4.3.6"
- end
- end
-
-
- describe "installing a binary package" do
- before do
- @provider.stub!(:current_installed_version).and_return(nil)
- @status = OpenStruct.new(:status => true)
- end
-
- it "should be able to install from a package repository" do
- @provider.should_receive(:shell_out!).with("pkg install -y zsh", :env => { 'LC_ALL' => nil }).and_return(@status)
- @new_resource.source.should be_nil
- @provider.install_package('zsh', nil)
- end
-
- it "should be able to install from a custom repository" do
- @provider.should_receive(:shell_out!).with("pkg install -r http://pkgrepo.example.com zsh", :env => { 'LC_ALL' => nil }).and_return(@status)
- @new_resource.source.should be_nil
- @new_resource.options('-r http://pkgrepo.example.com')
- @provider.install_package('zsh', nil)
- end
-
- it "should be able to install a local package" do
- @provider.should_receive(:shell_out!).with("pkg add /root/packages/zsh-5.0.2.txz", :env => { 'LC_ALL' => nil }).and_return(@status)
- @new_resource.source('/root/packages/zsh-5.0.2.txz')
- @provider.install_package('zsh', '5.0.2')
- end
-
- it "should be able to install a remote package" do
- @provider.should_receive(:shell_out!).with("pkg add http://pkgrepo.eg.com/All/zsh-5.0.2.txz", :env => { 'LC_ALL' => nil }).and_return(@status)
- @new_resource.source('http://pkgrepo.eg.com/All/zsh-5.0.2.txz')
- @provider.install_package('zsh', '5.0.2')
- end
- end
-
-
- describe "building a binary package" do
- before do
- @provider.stub!(:current_installed_version).and_return(nil)
- @status = OpenStruct.new(:status => true)
- end
-
- it "should handle a regular port name" do
- @provider.should_receive(:shell_out!).with('whereis -s zsh', :env => nil).and_return(OpenStruct.new(:stdout => 'zsh: /usr/ports/shells/zsh'))
- @provider.should_receive(:shell_out!).with('make -DBATCH install', :timeout => 1800, :env => nil, :cwd => '/usr/ports/shells/zsh').and_return(@status)
- @new_resource.source('ports')
- @provider.install_package('zsh', '5.0.2')
- end
-
- it "should handle a port name including section" do
- @provider.should_receive(:shell_out!).with('make -DBATCH install', :timeout => 1800, :env => nil, :cwd => '/usr/ports/shells/zsh').and_return(@status)
- @new_resource.package_name('shells/zsh')
- @new_resource.source('ports')
- @provider.install_package('zsh', '5.0.2')
- end
-
- it "should handle a custom port location" do
- @provider.should_receive(:shell_out!).with('make -DBATCH install', :timeout => 1800, :env => nil, :cwd => '/master/ports/shells/zsh').and_return(@status)
- @new_resource.package_name('/master/ports/shells/zsh')
- @new_resource.source('ports')
- @provider.install_package('zsh', '5.0.2')
- end
- end
-
-
- describe "removing a binary package" do
- before do
- @status = OpenStruct.new(:status => true)
- end
-
- it "should be able to remove package with version number" do
- @provider.should_receive(:shell_out!).with("pkg delete -y zsh-5.0.2_1", :env => nil).and_return(@status)
- @provider.remove_package("zsh", "5.0.2_1")
- end
-
- it "should be able to remove package without version number" do
- @provider.should_receive(:shell_out!).with("pkg delete -y zsh", :env => nil).and_return(@status)
- @provider.remove_package("zsh", nil)
- end
-
- it "should be able to pass custom options" do
- @provider.should_receive(:shell_out!).with("pkg delete -Df zsh-5.0.2_1", :env => nil).and_return(@status)
- @new_resource.options('-Df')
- @provider.remove_package("zsh", "5.0.2_1")
- end
- end
-end
diff --git a/spec/unit/provider_resolver/package/freebsd_spec.rb b/spec/unit/provider_resolver/package/freebsd_spec.rb
new file mode 100644
index 0000000000..ea82dad09c
--- /dev/null
+++ b/spec/unit/provider_resolver/package/freebsd_spec.rb
@@ -0,0 +1,65 @@
+#
+# Authors:: Richard Manyanza (liseki@nyikacraftsmen.com)
+# Copyright:: Copyright (c) 2014 Richard Manyanza
+# 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'
+require 'ostruct'
+
+describe Chef::ProviderResolver::Package::Freebsd do
+ before(:each) do
+ @node = {}
+ @resource = Chef::Resource::Package.new("zsh")
+ @resolver = Chef::ProviderResolver::Package::Freebsd.new(@node, @resource)
+ end
+
+ describe "if ports specified as source" do
+ it "should resolve to Freebsd::Port" do
+ @resource.source('ports')
+ @resolver.resolve.should == Chef::Provider::Package::Freebsd::Port
+ end
+ end
+
+ describe "if __Freebsd_version greater than or equal to 1000017" do
+ it "should resolve to Freebsd::Pkgng" do
+ [1000017, 1000018, 1000500, 1001001, 1100000].each do |__freebsd_version|
+ @node[:os_version] = __freebsd_version
+ @resolver.resolve.should == Chef::Provider::Package::Freebsd::Pkgng
+ end
+ end
+ end
+
+ describe "if pkgng enabled" do
+ it "should resolve to Freebsd::Pkgng" do
+ pkg_enabled = OpenStruct.new(:stdout => "yes\n")
+ @resolver.should_receive(:shell_out!).with("make -V WITH_PKGNG", :env => nil).and_return(pkg_enabled)
+ @resolver.resolve.should == Chef::Provider::Package::Freebsd::Pkgng
+ end
+ end
+
+ describe "if __Freebsd_version less than 1000017 and pkgng not enabled" do
+ it "should resolve to Freebsd::Pkg" do
+ pkg_enabled = OpenStruct.new(:stdout => "\n")
+ @resolver.stub(:shell_out!).with("make -V WITH_PKGNG", :env => nil).and_return(pkg_enabled)
+
+ [1000016, 1000000, 901503, 902506, 802511].each do |__freebsd_version|
+ @node[:os_version] == __freebsd_version
+ @resolver.resolve.should == Chef::Provider::Package::Freebsd::Pkg
+ end
+ end
+ end
+end
diff --git a/spec/unit/resource/freebsd_package_spec.rb b/spec/unit/resource/freebsd_package_spec.rb
index b80a94f98d..9f5572af66 100644
--- a/spec/unit/resource/freebsd_package_spec.rb
+++ b/spec/unit/resource/freebsd_package_spec.rb
@@ -32,8 +32,9 @@ describe Chef::Resource::FreebsdPackage, "initialize" do
@resource.resource_name.should eql(:freebsd_package)
end
- it "should set the provider to Chef::Provider::Package::freebsd" do
- @resource.provider.should eql(Chef::Provider::Package::Freebsd)
+ it "should not set the provider" do
+ # This will be handlded by Chef::ProviderResolver::Package::Freebsd
+ @resource.provider.should be_nil
end
end