diff options
-rw-r--r-- | lib/chef/provider/package/openbsd.rb | 173 | ||||
-rw-r--r-- | spec/unit/provider/package/openbsd_spec.rb | 299 |
2 files changed, 23 insertions, 449 deletions
diff --git a/lib/chef/provider/package/openbsd.rb b/lib/chef/provider/package/openbsd.rb index 83c0683d66..da711b364f 100644 --- a/lib/chef/provider/package/openbsd.rb +++ b/lib/chef/provider/package/openbsd.rb @@ -41,185 +41,50 @@ class Chef @new_resource.source("#{mirror}/pub/#{node.kernel.name}/#{node.kernel.release}/packages/#{node.kernel.machine}/") if !@new_resource.source end + def load_current_resource + @current_resource.package_name(@new_resource.package_name) + @current_resource.version(installed_version) + @candidate_version = candidate_version + @current_resource + end + def install_package(name, version) unless @current_resource.version version_string = '' version_string += "-#{version}" if version && version != '0.0.0' - case @new_resource.source - when /^http/, /^ftp/ - if @new_resource.source =~ /\/$/ - shell_out!("pkg_add -r #{short_package_name}#{version_string}", :env => { "PACKAGESITE" => @new_resource.source, 'LC_ALL' => nil }).status - else - shell_out!("pkg_add -r #{short_package_name}#{version_string}", :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}") - + if @new_resource.source =~ /\/$/ + shell_out!("pkg_add -r #{name}#{version_string}", :env => { "PACKAGESITE" => @new_resource.source, 'LC_ALL' => nil }).status else - shell_out!("pkg_add -r #{latest_link_name}", :env => nil).status + shell_out!("pkg_add -r #{name}#{version_string}", :env => { "PACKAGEROOT" => @new_resource.source, 'LC_ALL' => nil }).status end + Chef::Log.debug("#{@new_resource} installed from: #{@new_resource.source}") end end def remove_package(name, version) version_string = '' version_string += "-#{version}" if version && version != '0.0.0' - shell_out!("pkg_delete #{short_package_name}#{version_string}", :env => nil).status + shell_out!("pkg_delete #{name}#{version_string}", :env => nil).status end - # The name of the package (without the version number) as understood - # by pkg_add and pkg_info. - def short_package_name - result = '' - info = find_package(@new_resource.package_name) - result += info[:short_name] - if info[:version] - subpackage = info[:version].match /(.*)-\d.*/ - result += '-' + subpackage[1] if subpackage - end + private - result - end - - def current_installed_version - pkg_info = shell_out!("pkg_info -e \"#{short_package_name}->0\"", :env => nil, :returns => [0,1]) - result = pkg_info.stdout[/^inst:#{Regexp.escape(short_package_name)}-(.+)/, 1] - Chef::Log.debug("current_installed_version of '#{short_package_name}' is '#{result}'") + def installed_version + pkg_info = shell_out!("pkg_info -e \"#{@new_resource.package_name}->0\"", :env => nil, :returns => [0,1]) + result = pkg_info.stdout[/^inst:#{Regexp.escape(@new_resource.package_name)}-(.+)/, 1] result end def candidate_version - case @new_resource.source - when /^http/, /^ftp/ - repo_candidate_version - when /^\// - file_candidate_version - else - port_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(options={}) - return '0.0.0' if @new_resource.package_name == 'sqlports' - info = find_package(@new_resource.package_name) - info[:fullpkgname].sub(/^#{info[:short_name]}-/,'') - end - - def port_candidate_version - name = makefile_variable_value("DISTNAME", port_path) || - makefile_variable_value("PKGNAME", port_path) - name.match(/.*?-(\d.*)/)[1] - end - - # does NOT include port options, i.e. flavors and subpackages - # i.e. /usr/ports/meta/gnome,-extra ... does NOT include the ',-extra' - def port_path - '/usr/ports/' + find_package(@new_resource.package_name)[:fullpkgpath].split(',').first - end - - def find_package(name) - return {short_name: 'sqlports'} if name == 'sqlports' - - result = nil - - query = "SELECT fullpkgname, fullpkgpath, pkgspec, pkgname FROM ports WHERE" - if name.include? '/' - rows = sqlports.execute "#{query} fullpkgpath = '#{name}'" - rows = sqlports.execute "#{query} fullpkgpath = '#{name},-main'" if rows.empty? - else - rows = sqlports.execute "#{query} fullpkgname = '#{name}'" - rows = sqlports.execute "#{query} pkgname = '#{name}'" if rows.empty? - rows = sqlports.execute "#{query} pkgspec = '#{name}-*'" if rows.empty? - end - if rows.size > 0 - row = rows.first - result = { - short_name: row[2].sub(/-[\*><=].*/,''), - short_version: row[3].sub(row[2].sub(/[\*><=].*/,''), ''), - pkgspec: row[2], - fullpkgname: row[0], - fullpkgpath: row[1], - } - else - raise Chef::Exceptions::Package, "Could not find a package that matches: #{name}" - end - - result + pkg_info = shell_out!("pkg_info -I \"#{@new_resource.package_name}\"", :env => nil, :returns => [0,1]) + result = pkg_info.stdout[/^#{Regexp.escape(@new_resource.package_name)}-(.+)/, 1] + Chef::Log.debug("candidate_version of '#{@new_resource.package_name}' is '#{result}'") end def mirror 'http://ftp.eu.openbsd.org' end - def sqlports(options={}) - # install the DB that maps ports paths to package names, assume it - # will stay installed during this chef run, we won't bother to check - # it on every call to this method - if !@@sqlports - Chef::Log.debug("Initializing sqlports") - shell_out!("pkg_add sqlports") unless ::File.exists?('/usr/local/share/sqlports') - shell_out!("gem install sqlite3", :returns => [0,1]) unless shell_out!("gem list | grep sqlite3").stdout.include?('sqlite3') - require 'sqlite3' - @@sqlports = SQLite3::Database.new '/usr/local/share/sqlports' - end - - @@sqlports - 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}" - - else - rows = sqlports.execute "SELECT fullpkgpath FROM ports WHERE pkgspec = '#{port}-*';" - if rows.size > 0 - "/usr/ports/#{rows.first.first.split(',').first}" - else - raise Chef::Exceptions::Package, "Could not find port: #{port}" - end - 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])) - - # $\ is the line separator, i.e. newline. - result = make_v.exitstatus.zero? ? make_v.stdout.strip.split($\).first : nil - - # some make variables reference other variables, recurse to resolve - result = result.gsub(/\${?[A-Z0-9_]*}?/) {|match| makefile_variable_value(match[1..-1].gsub(/[\{\}]/,''), dir)} if result - result - 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 diff --git a/spec/unit/provider/package/openbsd_spec.rb b/spec/unit/provider/package/openbsd_spec.rb index ecf8402727..37d0d844a9 100644 --- a/spec/unit/provider/package/openbsd_spec.rb +++ b/spec/unit/provider/package/openbsd_spec.rb @@ -19,14 +19,7 @@ require 'spec_helper' require 'ostruct' -def running_compatible_os - @os ||= `uname`.downcase.strip - @os_version ||= `uname -r`.strip - @os_architecture ||= `uname -m`.downcase.strip - @os == 'openbsd' && @os_version == '5.5' && @os_architecture == 'amd64' -end - -describe Chef::Provider::Package::Openbsd, 'find_package', :if => running_compatible_os do +describe Chef::Provider::Package::Openbsd do before(:each) do @node = Chef::Node.new @@ -35,295 +28,13 @@ describe Chef::Provider::Package::Openbsd, 'find_package', :if => running_compat @run_context = Chef::RunContext.new(@node, {}, @events) end - describe "plain package name (zsh)" do - before do - @name = 'zsh' - @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 - @provider.sqlports(:skip_installation => true) - @info = @provider.find_package(@name) - end - - it "should parse as a plain package with no version" do - @info[:short_name].should == 'zsh' - @info[:short_version].should == '5.0.2' - @info[:pkgspec].should == 'zsh-*' - @info[:fullpkgname].should == 'zsh-5.0.2' - @info[:fullpkgpath].should == 'shells/zsh' - end - - it "should translate to a port path" do - @provider.port_path.should == '/usr/ports/shells/zsh' - end - - it "should have a valid repo candidate version" do - @provider.repo_candidate_version.should == '5.0.2' - end - - it "should have a valid port candidate version" do - @provider.port_candidate_version.should == '5.0.2' - end - - end - - describe "package name with unavailable version (zsh-5.0.10)" do - before do - @name = 'zsh-5.0.10' - @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 - @provider.sqlports(:skip_installation => true) - end - - it "should raise an exception when the requested version does not match whats available in the repo" do - expect {@provider.find_package(@name)}.to raise_error Chef::Exceptions::Package - end - -end - - describe "package name with available version (zsh-5.0.2)" do - before do - @name = 'zsh-5.0.2' - @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 - @provider.sqlports(:skip_installation => true) - @info = @provider.find_package(@name) - end - - it "should parse as a plain package with no version" do - @info[:short_name].should == 'zsh' - @info[:short_version].should == '5.0.2' - @info[:pkgspec].should == 'zsh-*' - @info[:fullpkgname].should == 'zsh-5.0.2' - @info[:fullpkgpath].should == 'shells/zsh' - end - - it "should translate to a port path" do - @provider.port_path.should == '/usr/ports/shells/zsh' - end - - it "should have a valid repo candidate version" do - @provider.repo_candidate_version.should == '5.0.2' - end - - it "should have a valid port candidate version" do - @provider.port_candidate_version.should == '5.0.2' - end - - end - - describe "package with version and flavor (mutt-1.5.22p0v0-sasl)" do - before do - @name = 'mutt-1.5.22p0v0-sasl' - @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 - @provider.sqlports(:skip_installation => true) - @info = @provider.find_package(@name) - end - - it "should parse as a plain package with no version" do - @info[:short_name].should == 'mutt' - @info[:short_version].should == '1.5.22' - @info[:pkgspec].should == 'mutt-*' - @info[:fullpkgname].should == 'mutt-1.5.22p0v0-sasl' - @info[:fullpkgpath].should == 'mail/mutt/snapshot,sasl' - end - - it "should translate to a port path" do - @provider.port_path.should == '/usr/ports/mail/mutt/snapshot' - end - - it "should have a valid repo candidate version" do - @provider.repo_candidate_version.should == '1.5.22p0v0-sasl' - end - - it "should have a valid port candidate version" do - @provider.port_candidate_version.should == '1.5.22' - end - - end - - describe "package with subpackage (gnome-extra)" do - before do - @name = 'gnome-extra' - @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 - @provider.sqlports(:skip_installation => true) - @info = @provider.find_package(@name) - end - - it "should parse as a plain package with no version" do - @info[:short_name].should == 'gnome-extra' - @info[:short_version].should == '3.10.2' - @info[:pkgspec].should == 'gnome-extra-*' - @info[:fullpkgname].should == 'gnome-extra-3.10.2' - @info[:fullpkgpath].should == 'meta/gnome,-extra' - end - - it "should translate to a port path" do - @provider.port_path.should == '/usr/ports/meta/gnome' - end - - it "should have a valid repo candidate version" do - @provider.repo_candidate_version.should == '3.10.2' - end - - it "should have a valid port candidate version" do - @provider.port_candidate_version.should == '3.10.2' - end - - end - - describe "port path with 'main' subpackage (mail/gmime,-main)" do - before do - @name = 'mail/gmime,-main' - @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 - @provider.sqlports(:skip_installation => true) - @info = @provider.find_package(@name) - end - - it "should parse as a plain package with no version" do - @info[:short_name].should == 'gmime' - @info[:short_version].should == '2.6.19' - @info[:pkgspec].should == 'gmime-*' - @info[:fullpkgname].should == 'gmime-2.6.19' - @info[:fullpkgpath].should == 'mail/gmime,-main' - end - - it "should translate to a port path" do - @provider.port_path.should == '/usr/ports/mail/gmime' - end - - it "should have a valid repo candidate version" do - @provider.repo_candidate_version.should == '2.6.19' - end - - it "should have a valid port candidate version" do - @provider.port_candidate_version.should == '2.6.19' - end - - end - - describe "port path with non-'main' subpackage (mail/gmime,-mono)" do - before do - @name = 'mail/gmime,-mono' - @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 - @provider.sqlports(:skip_installation => true) - @info = @provider.find_package(@name) - end - - it "should parse as a plain package with no version" do - @info[:short_name].should == 'gmime-sharp' - @info[:short_version].should == '2.6.19' - @info[:pkgspec].should == 'gmime-sharp-*' - @info[:fullpkgname].should == 'gmime-sharp-2.6.19' - @info[:fullpkgpath].should == @name - end - - it "should translate to a port path" do - @provider.port_path.should == '/usr/ports/mail/gmime' - end - - it "should have a valid repo candidate version" do - @provider.repo_candidate_version.should == '2.6.19' - end - - it "should have a valid port candidate version" do - @provider.port_candidate_version.should == '2.6.19' - end - - end - - describe "package with a dash in the name, multiple major versions, and different package and port versions (php-zip-5.4.24)" do - before do - @name = 'php-zip-5.4.24' - @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 - @provider.sqlports(:skip_installation => true) - @info = @provider.find_package(@name) - end - - it "should parse as a plain package with no version" do - @info[:short_name].should == 'php-zip' - @info[:short_version].should == '5.4.24' - @info[:pkgspec].should == 'php-zip->=5.4,<5.5' - @info[:fullpkgname].should == 'php-zip-5.4.24' - @info[:fullpkgpath].should == 'lang/php/5.4,-zip' - end - - it "should translate to a port path" do - @provider.port_path.should == '/usr/ports/lang/php/5.4' - end - - it "should have a valid repo candidate version" do - @provider.repo_candidate_version.should == '5.4.24' - end - - it "should have a valid port candidate version" do - @provider.port_candidate_version.should =~ /5\.4\.\d*/ - end - - end - - describe "another package name to parse, for good measure (clamav)" do - before do - @name = 'clamav' - @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 - @provider.sqlports(:skip_installation => true) - @info = @provider.find_package(@name) - end - - it "should parse as a plain package with no version" do - @info[:short_name].should == 'clamav' - @info[:short_version].should == '0.98.1' - @info[:pkgspec].should == 'clamav-*' - @info[:fullpkgname].should == 'clamav-0.98.1' - @info[:fullpkgpath].should == 'security/clamav' - end - - it "should translate to a port path" do - @provider.port_path.should == '/usr/ports/security/clamav' - end - - it "should have a valid repo candidate version" do - @provider.repo_candidate_version.should == '0.98.1' - end - - it "should have a valid port candidate version" do - @provider.port_candidate_version.should == '0.98.4' - end - - end - describe "install a package" do before do - @name = 'zzuf' + @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 - @provider.sqlports(:skip_installation => true) - @info = @provider.find_package(@name) end it "should run the installation command" do expect(@provider).to receive(:shell_out!).with( @@ -339,17 +50,15 @@ end describe "delete a package" do before do - @name = 'sqlports' + @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 - @provider.sqlports(:skip_installation => true) - @info = @provider.find_package(@name) end it "should run the command to delete the installed package" do expect(@provider).to receive(:shell_out!).with( - "pkg_delete sqlports", :env=>nil + "pkg_delete #{@name}", :env=>nil ) {OpenStruct.new :status => true} @provider.remove_package(@name, nil) end |