From e8ebb05d2d332f70766f0c59e7be1c0aa6350f24 Mon Sep 17 00:00:00 2001 From: Sebastian Reitenbach Date: Wed, 20 Mar 2024 22:59:13 +0100 Subject: [PATCH 01/15] bring OpenBSD package handling up to date to what is in the ports tree and gets packaged. --- lib/puppet/provider/package/openbsd.rb | 150 ++++++++++--------------- 1 file changed, 61 insertions(+), 89 deletions(-) diff --git a/lib/puppet/provider/package/openbsd.rb b/lib/puppet/provider/package/openbsd.rb index c230fe41099..46aaa19aa2c 100644 --- a/lib/puppet/provider/package/openbsd.rb +++ b/lib/puppet/provider/package/openbsd.rb @@ -24,6 +24,8 @@ has_feature :upgradeable has_feature :supports_flavors + mk_resource_methods + def self.instances packages = [] @@ -46,12 +48,6 @@ def self.instances packages << new(hash) hash = {} - else - unless line =~ /Updating the pkgdb/ - # Print a warning on lines we can't match, but move - # on, since it should be non-fatal - warning(_("Failed to match line %{line}") % { line: line }) - end end } end @@ -67,26 +63,17 @@ def self.listcmd end def latest - parse_pkgconf - - if @resource[:source][-1, 1] == ::File::SEPARATOR - e_vars = { 'PKG_PATH' => @resource[:source] } - else - e_vars = {} - end - if @resource[:flavor] query = "#{@resource[:name]}--#{@resource[:flavor]}" else - query = @resource[:name] + query = @resource[:name] + "--" end - output = Puppet::Util.withenv(e_vars) { pkginfo "-Q", query } - version = properties[:ensure] + output = Puppet::Util.withenv({}) {pkginfo "-Q", query} if output.nil? or output.size == 0 or output =~ /Error from / debug "Failed to query for #{resource[:name]}" - return version + return properties[:ensure] else # Remove all fuzzy matches first. output = output.split.select { |p| p =~ /^#{resource[:name]}-(\d[^-]*)-?(\w*)/ }.join @@ -95,21 +82,21 @@ def latest if output =~ /^#{resource[:name]}-(\d[^-]*)-?(\w*) \(installed\)$/ debug "Package is already the latest available" - version + return properties[:ensure] else match = /^(.*)-(\d[^-]*)-?(\w*)$/.match(output) debug "Latest available for #{resource[:name]}: #{match[2]}" - if version.to_sym == :absent || version.to_sym == :purged + if properties[:ensure].to_sym == :absent return match[2] end - vcmp = version.split('.').map(&:to_i) <=> match[2].split('.').map(&:to_i) + vcmp = properties[:ensure].split('.').map{|s|s.to_i} <=> match[2].split('.').map{|s|s.to_i} if vcmp > 0 # The locally installed package may actually be newer than what a mirror # has. Log it at debug, but ignore it otherwise. - debug "Package #{resource[:name]} #{version} newer then available #{match[2]}" - version + debug "Package #{resource[:name]} #{properties[:ensure]} newer then available #{match[2]}" + return properties[:ensure] else match[2] end @@ -120,57 +107,25 @@ def update install(true) end - def parse_pkgconf - unless @resource[:source] - if Puppet::FileSystem.exist?("/etc/pkg.conf") - File.open("/etc/pkg.conf", "rb").readlines.each do |line| - matchdata = line.match(/^installpath\s*=\s*(.+)\s*$/i) - if matchdata - @resource[:source] = matchdata[1] - else - matchdata = line.match(/^installpath\s*\+=\s*(.+)\s*$/i) - if matchdata - if @resource[:source].nil? - @resource[:source] = matchdata[1] - else - @resource[:source] += ":" + matchdata[1] - end - end - end - end - - unless @resource[:source] - raise Puppet::Error, - _("No valid installpath found in /etc/pkg.conf and no source was set") - end - else - raise Puppet::Error, - _("You must specify a package source or configure an installpath in /etc/pkg.conf") - end - end - end - def install(latest = false) cmd = [] - parse_pkgconf - - if @resource[:source][-1, 1] == ::File::SEPARATOR - e_vars = { 'PKG_PATH' => @resource[:source] } - full_name = get_full_name(latest) - else - e_vars = {} - full_name = @resource[:source] - end - + cmd << '-r' cmd << install_options - cmd << full_name + cmd << get_full_name(latest) if latest - cmd.unshift('-rz') + cmd.unshift('-z') end - Puppet::Util.withenv(e_vars) { pkgadd cmd.flatten.compact } + # pkg_add(1) doesn't set the return value upon failure so we have to peek + # at it's output to see if something went wrong. + output = Puppet::Util.withenv({}) { pkgadd cmd.flatten.compact } + require 'pp' + pp output + if output =~ /Can't find / + self.fail "pkg_add returned: #{output.chomp}" + end end def get_full_name(latest = false) @@ -179,11 +134,20 @@ def get_full_name(latest = false) # installing with 'latest', we do need to handle the flavors. This is # done so we can feed pkg_add(8) the full package name to install to # prevent ambiguity. - if latest && resource[:flavor] - "#{resource[:name]}--#{resource[:flavor]}" - elsif latest - # Don't depend on get_version for updates. - @resource[:name] + if resource[:flavor] + # If :ensure contains a version, use that instead of looking it up. + # This allows for installing packages with the same stem, but multiple + # version such as postfix-VERSION-flavor. + if @resource[:ensure].to_s =~ /(\d[^-]*)$/ + use_version = @resource[:ensure] + else + use_version = '' + end + "#{resource[:name]}-#{use_version}-#{resource[:flavor]}" + elsif resource[:name].to_s.match(/[a-z0-9]%[0-9a-z]/i) + "#{resource[:name]}" + elsif not latest + "#{resource[:name]}--" else # If :ensure contains a version, use that instead of looking it up. # This allows for installing packages with the same stem, but multiple @@ -194,33 +158,41 @@ def get_full_name(latest = false) use_version = get_version end - [@resource[:name], use_version, @resource[:flavor]].join('-').gsub(/-+$/, '') + if resource[:flavor] + [ @resource[:name], use_version, @resource[:flavor]].join('-').gsub(/-+$/, '') + else + [ @resource[:name], use_version ] + end end end def get_version - execpipe([command(:pkginfo), "-I", @resource[:name]]) do |process| - # our regex for matching pkg_info output - regex = /^(.*)-(\d[^-]*)-?(\w*)(.*)$/ - master_version = 0 - version = -1 - - process.each_line do |line| - match = regex.match(line.split[0]) - next unless match - + pkg_search_name = @resource[:name] + unless pkg_search_name.match(/[a-z0-9]%[0-9a-z]/i) and not @resource[:flavor] + # we are only called when no flavor is specified + # so append '--' to the :name to avoid patch versions on flavors + pkg_search_name << "--" + end + # our regex for matching pkg_info output + regex = /^(.*)-(\d[^-]*)[-]?(\w*)(.*)$/ + master_version = 0 + version = -1 + + # pkg_info -I might return multiple lines, i.e. flavors + matching_pkgs = pkginfo("-I", "pkg_search_name") + matching_pkgs.each_line do |line| + if match = regex.match(line.split[0]) # now we return the first version, unless ensure is latest version = match.captures[1] return version unless @resource[:ensure] == "latest" - master_version = version unless master_version > version end - - return master_version unless master_version == 0 - return '' if version == -1 - - raise Puppet::Error, _("%{version} is not available for this package") % { version: version } end + + return master_version unless master_version == 0 + return '' if version == -1 + raise Puppet::Error, _("%{version} is not available for this package") % { version: version } + rescue Puppet::ExecutionFailure nil end @@ -239,7 +211,7 @@ def install_options end def uninstall_options - join_options(resource[:uninstall_options]) + [join_options(resource[:uninstall_options])] end def uninstall From a43d2e03d8bf2deb487e761d907e3c67dc95edb2 Mon Sep 17 00:00:00 2001 From: Sebastian Reitenbach Date: Wed, 20 Mar 2024 23:09:14 +0100 Subject: [PATCH 02/15] make rubocop a bit happier --- lib/puppet/provider/package/openbsd.rb | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/puppet/provider/package/openbsd.rb b/lib/puppet/provider/package/openbsd.rb index 46aaa19aa2c..702c93f2165 100644 --- a/lib/puppet/provider/package/openbsd.rb +++ b/lib/puppet/provider/package/openbsd.rb @@ -69,7 +69,7 @@ def latest query = @resource[:name] + "--" end - output = Puppet::Util.withenv({}) {pkginfo "-Q", query} + output = Puppet::Util.withenv({}) { pkginfo "-Q", query } if output.nil? or output.size == 0 or output =~ /Error from / debug "Failed to query for #{resource[:name]}" @@ -91,12 +91,12 @@ def latest return match[2] end - vcmp = properties[:ensure].split('.').map{|s|s.to_i} <=> match[2].split('.').map{|s|s.to_i} + vcmp = properties[:ensure].split('.').map { |s|s.to_i } <=> match[2].split('.').map { |s|s.to_i } if vcmp > 0 # The locally installed package may actually be newer than what a mirror # has. Log it at debug, but ignore it otherwise. debug "Package #{resource[:name]} #{properties[:ensure]} newer then available #{match[2]}" - return properties[:ensure] + properties[:ensure] else match[2] end @@ -142,11 +142,11 @@ def get_full_name(latest = false) use_version = @resource[:ensure] else use_version = '' - end + end "#{resource[:name]}-#{use_version}-#{resource[:flavor]}" elsif resource[:name].to_s.match(/[a-z0-9]%[0-9a-z]/i) "#{resource[:name]}" - elsif not latest + elsif ! latest "#{resource[:name]}--" else # If :ensure contains a version, use that instead of looking it up. @@ -168,7 +168,7 @@ def get_full_name(latest = false) def get_version pkg_search_name = @resource[:name] - unless pkg_search_name.match(/[a-z0-9]%[0-9a-z]/i) and not @resource[:flavor] + unless pkg_search_name.match(/[a-z0-9]%[0-9a-z]/i) and ! @resource[:flavor] # we are only called when no flavor is specified # so append '--' to the :name to avoid patch versions on flavors pkg_search_name << "--" From b9bed77285bbb45b921f626ec1cbae674aff8c9b Mon Sep 17 00:00:00 2001 From: Sebastian Reitenbach Date: Thu, 21 Mar 2024 08:03:05 +0100 Subject: [PATCH 03/15] more rubocop --- lib/puppet/provider/package/openbsd.rb | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/lib/puppet/provider/package/openbsd.rb b/lib/puppet/provider/package/openbsd.rb index 702c93f2165..e83e0c0ae05 100644 --- a/lib/puppet/provider/package/openbsd.rb +++ b/lib/puppet/provider/package/openbsd.rb @@ -82,7 +82,7 @@ def latest if output =~ /^#{resource[:name]}-(\d[^-]*)-?(\w*) \(installed\)$/ debug "Package is already the latest available" - return properties[:ensure] + properties[:ensure] else match = /^(.*)-(\d[^-]*)-?(\w*)$/.match(output) debug "Latest available for #{resource[:name]}: #{match[2]}" @@ -91,7 +91,7 @@ def latest return match[2] end - vcmp = properties[:ensure].split('.').map { |s|s.to_i } <=> match[2].split('.').map { |s|s.to_i } + vcmp = properties[:ensure].split('.').map { &:to_i } <=> match[2].split('.').map { &:to_i } if vcmp > 0 # The locally installed package may actually be newer than what a mirror # has. Log it at debug, but ignore it otherwise. @@ -121,7 +121,6 @@ def install(latest = false) # pkg_add(1) doesn't set the return value upon failure so we have to peek # at it's output to see if something went wrong. output = Puppet::Util.withenv({}) { pkgadd cmd.flatten.compact } - require 'pp' pp output if output =~ /Can't find / self.fail "pkg_add returned: #{output.chomp}" @@ -145,8 +144,8 @@ def get_full_name(latest = false) end "#{resource[:name]}-#{use_version}-#{resource[:flavor]}" elsif resource[:name].to_s.match(/[a-z0-9]%[0-9a-z]/i) - "#{resource[:name]}" - elsif ! latest + "#{resource[:name]}" + elsif !latest "#{resource[:name]}--" else # If :ensure contains a version, use that instead of looking it up. @@ -168,7 +167,7 @@ def get_full_name(latest = false) def get_version pkg_search_name = @resource[:name] - unless pkg_search_name.match(/[a-z0-9]%[0-9a-z]/i) and ! @resource[:flavor] + unless pkg_search_name.match(/[a-z0-9]%[0-9a-z]/i) and !@resource[:flavor] # we are only called when no flavor is specified # so append '--' to the :name to avoid patch versions on flavors pkg_search_name << "--" From 839a1c0267055e146f69d50ab2dc05110a4829bc Mon Sep 17 00:00:00 2001 From: Sebastian Reitenbach Date: Thu, 21 Mar 2024 08:07:48 +0100 Subject: [PATCH 04/15] get rid of warning --- lib/puppet/provider/package/openbsd.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/puppet/provider/package/openbsd.rb b/lib/puppet/provider/package/openbsd.rb index e83e0c0ae05..54d261bc146 100644 --- a/lib/puppet/provider/package/openbsd.rb +++ b/lib/puppet/provider/package/openbsd.rb @@ -91,7 +91,7 @@ def latest return match[2] end - vcmp = properties[:ensure].split('.').map { &:to_i } <=> match[2].split('.').map { &:to_i } + vcmp = properties[:ensure].split('.').map { |s|s.to_i } <=> match[2].split('.').map { |s|s.to_i } if vcmp > 0 # The locally installed package may actually be newer than what a mirror # has. Log it at debug, but ignore it otherwise. From 3af3f180f1dab24f93f5d8287d12d428986ae756 Mon Sep 17 00:00:00 2001 From: Sebastian Reitenbach Date: Thu, 21 Mar 2024 08:17:54 +0100 Subject: [PATCH 05/15] more --- lib/puppet/provider/package/openbsd.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/puppet/provider/package/openbsd.rb b/lib/puppet/provider/package/openbsd.rb index 54d261bc146..c5bcfe8199c 100644 --- a/lib/puppet/provider/package/openbsd.rb +++ b/lib/puppet/provider/package/openbsd.rb @@ -91,7 +91,7 @@ def latest return match[2] end - vcmp = properties[:ensure].split('.').map { |s|s.to_i } <=> match[2].split('.').map { |s|s.to_i } + vcmp = properties[:ensure].split('.').map { |s| s.to_i } <=> match[2].split('.').map { |s| s.to_i } if vcmp > 0 # The locally installed package may actually be newer than what a mirror # has. Log it at debug, but ignore it otherwise. @@ -184,11 +184,13 @@ def get_version # now we return the first version, unless ensure is latest version = match.captures[1] return version unless @resource[:ensure] == "latest" + master_version = version unless master_version > version end end return master_version unless master_version == 0 + return '' if version == -1 raise Puppet::Error, _("%{version} is not available for this package") % { version: version } From bfd78a1b752888131ee84aed0793c01f16ee4f94 Mon Sep 17 00:00:00 2001 From: Sebastian Reitenbach Date: Thu, 21 Mar 2024 08:25:59 +0100 Subject: [PATCH 06/15] more --- lib/puppet/provider/package/openbsd.rb | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/lib/puppet/provider/package/openbsd.rb b/lib/puppet/provider/package/openbsd.rb index c5bcfe8199c..fc52e1b3831 100644 --- a/lib/puppet/provider/package/openbsd.rb +++ b/lib/puppet/provider/package/openbsd.rb @@ -39,7 +39,7 @@ def self.instances # now turn each returned line into a package object process.each_line { |line| match = regex.match(line.split[0]) - if match + next unless match fields.zip(match.captures) { |field, value| hash[field] = value } @@ -144,7 +144,7 @@ def get_full_name(latest = false) end "#{resource[:name]}-#{use_version}-#{resource[:flavor]}" elsif resource[:name].to_s.match(/[a-z0-9]%[0-9a-z]/i) - "#{resource[:name]}" + resource[:name].to_s elsif !latest "#{resource[:name]}--" else @@ -158,9 +158,9 @@ def get_full_name(latest = false) end if resource[:flavor] - [ @resource[:name], use_version, @resource[:flavor]].join('-').gsub(/-+$/, '') + [@resource[:name], use_version, @resource[:flavor]].join('-').gsub(/-+$/, '') else - [ @resource[:name], use_version ] + [@resource[:name], use_version] end end end @@ -180,7 +180,7 @@ def get_version # pkg_info -I might return multiple lines, i.e. flavors matching_pkgs = pkginfo("-I", "pkg_search_name") matching_pkgs.each_line do |line| - if match = regex.match(line.split[0]) + next unless (match = regex.match(line.split[0])) # now we return the first version, unless ensure is latest version = match.captures[1] return version unless @resource[:ensure] == "latest" @@ -192,8 +192,9 @@ def get_version return master_version unless master_version == 0 return '' if version == -1 + raise Puppet::Error, _("%{version} is not available for this package") % { version: version } - + rescue Puppet::ExecutionFailure nil end From 38d6f10bb7303dcb009e6fbeb92824112735a1ec Mon Sep 17 00:00:00 2001 From: Sebastian Reitenbach Date: Thu, 21 Mar 2024 08:33:22 +0100 Subject: [PATCH 07/15] fix --- lib/puppet/provider/package/openbsd.rb | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/lib/puppet/provider/package/openbsd.rb b/lib/puppet/provider/package/openbsd.rb index fc52e1b3831..14ed1fdb500 100644 --- a/lib/puppet/provider/package/openbsd.rb +++ b/lib/puppet/provider/package/openbsd.rb @@ -40,15 +40,14 @@ def self.instances process.each_line { |line| match = regex.match(line.split[0]) next unless match - fields.zip(match.captures) { |field, value| - hash[field] = value - } + fields.zip(match.captures) { |field, value| + hash[field] = value + } - hash[:provider] = name + hash[:provider] = name - packages << new(hash) - hash = {} - end + packages << new(hash) + hash = {} } end @@ -181,12 +180,11 @@ def get_version matching_pkgs = pkginfo("-I", "pkg_search_name") matching_pkgs.each_line do |line| next unless (match = regex.match(line.split[0])) - # now we return the first version, unless ensure is latest - version = match.captures[1] - return version unless @resource[:ensure] == "latest" + # now we return the first version, unless ensure is latest + version = match.captures[1] + return version unless @resource[:ensure] == "latest" - master_version = version unless master_version > version - end + master_version = version unless master_version > version end return master_version unless master_version == 0 From a10eac2b0cccf0c930cf8e5bc36edbb5c380414a Mon Sep 17 00:00:00 2001 From: Sebastian Reitenbach Date: Thu, 21 Mar 2024 08:38:15 +0100 Subject: [PATCH 08/15] mostly done --- lib/puppet/provider/package/openbsd.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/puppet/provider/package/openbsd.rb b/lib/puppet/provider/package/openbsd.rb index 14ed1fdb500..a9f08973e5f 100644 --- a/lib/puppet/provider/package/openbsd.rb +++ b/lib/puppet/provider/package/openbsd.rb @@ -40,6 +40,7 @@ def self.instances process.each_line { |line| match = regex.match(line.split[0]) next unless match + fields.zip(match.captures) { |field, value| hash[field] = value } @@ -180,6 +181,7 @@ def get_version matching_pkgs = pkginfo("-I", "pkg_search_name") matching_pkgs.each_line do |line| next unless (match = regex.match(line.split[0])) + # now we return the first version, unless ensure is latest version = match.captures[1] return version unless @resource[:ensure] == "latest" @@ -192,7 +194,6 @@ def get_version return '' if version == -1 raise Puppet::Error, _("%{version} is not available for this package") % { version: version } - rescue Puppet::ExecutionFailure nil end From f2db2c6e51c8028c352e6f5f9530038df122b477 Mon Sep 17 00:00:00 2001 From: Sebastian Reitenbach Date: Thu, 21 Mar 2024 16:20:19 +0100 Subject: [PATCH 09/15] get rid of old pkg.conf related spec tests --- spec/unit/provider/package/openbsd_spec.rb | 150 --------------------- 1 file changed, 150 deletions(-) diff --git a/spec/unit/provider/package/openbsd_spec.rb b/spec/unit/provider/package/openbsd_spec.rb index 8717da3c36b..3d74bf139ce 100644 --- a/spec/unit/provider/package/openbsd_spec.rb +++ b/spec/unit/provider/package/openbsd_spec.rb @@ -81,156 +81,6 @@ def expect_pkgadd_with_env_and_name(source, &block) end context "#install" do - it "should fail if the resource doesn't have a source" do - expect(Puppet::FileSystem).to receive(:exist?).with('/etc/pkg.conf').and_return(false) - - expect { - provider.install - }.to raise_error(Puppet::Error, /must specify a package source/) - end - - it "should fail if /etc/pkg.conf exists, but is not readable" do - expect(Puppet::FileSystem).to receive(:exist?).with('/etc/pkg.conf').and_return(true) - expect(File).to receive(:open).with('/etc/pkg.conf', 'rb').and_raise(Errno::EACCES) - - expect { - provider.install - }.to raise_error(Errno::EACCES, /Permission denied/) - end - - it "should fail if /etc/pkg.conf exists, but there is no installpath" do - expect_read_from_pkgconf([]) - expect { - provider.install - }.to raise_error(Puppet::Error, /No valid installpath found in \/etc\/pkg\.conf and no source was set/) - end - - it "should install correctly when given a directory-unlike source" do - source = '/whatever.tgz' - provider.resource[:source] = source - expect_pkgadd_with_source(source) - - provider.install - end - - it "should install correctly when given a directory-like source" do - source = '/whatever/' - provider.resource[:source] = source - expect_pkgadd_with_env_and_name(source) do - provider.install - end - end - - it "should install correctly when given a CDROM installpath" do - dir = '/mnt/cdrom/5.2/packages/amd64/' - expect_read_from_pkgconf(["installpath = #{dir}"]) - expect_pkgadd_with_env_and_name(dir) do - provider.install - end - end - - it "should install correctly when given a ftp mirror" do - url = 'ftp://your.ftp.mirror/pub/OpenBSD/5.2/packages/amd64/' - expect_read_from_pkgconf(["installpath = #{url}"]) - expect_pkgadd_with_env_and_name(url) do - provider.install - end - end - - it "should set the resource's source parameter" do - url = 'ftp://your.ftp.mirror/pub/OpenBSD/5.2/packages/amd64/' - expect_read_from_pkgconf(["installpath = #{url}"]) - expect_pkgadd_with_env_and_name(url) do - provider.install - end - - expect(provider.resource[:source]).to eq(url) - end - - it "should strip leading whitespace in installpath" do - dir = '/one/' - lines = ["# Notice the extra spaces after the ='s\n", - "installpath = #{dir}\n", - "# And notice how each line ends with a newline\n"] - - expect_read_from_pkgconf(lines) - expect_pkgadd_with_env_and_name(dir) do - provider.install - end - end - - it "should not require spaces around the equals" do - dir = '/one/' - lines = ["installpath=#{dir}"] - - expect_read_from_pkgconf(lines) - expect_pkgadd_with_env_and_name(dir) do - provider.install - end - end - - it "should be case-insensitive" do - dir = '/one/' - lines = ["INSTALLPATH = #{dir}"] - - expect_read_from_pkgconf(lines) - expect_pkgadd_with_env_and_name(dir) do - provider.install - end - end - - it "should ignore unknown keywords" do - dir = '/one/' - lines = ["foo = bar\n", - "installpath = #{dir}\n"] - - expect_read_from_pkgconf(lines) - expect_pkgadd_with_env_and_name(dir) do - provider.install - end - end - - it "should preserve trailing spaces" do - dir = '/one/ ' - lines = ["installpath = #{dir}"] - - expect_read_from_pkgconf(lines) - expect_pkgadd_with_source(dir) - - provider.install - end - - it "should append installpath" do - urls = ["ftp://your.ftp.mirror/pub/OpenBSD/5.2/packages/amd64/", - "http://another.ftp.mirror/pub/OpenBSD/5.2/packages/amd64/"] - lines = ["installpath = #{urls[0]}\n", - "installpath += #{urls[1]}\n"] - - expect_read_from_pkgconf(lines) - expect_pkgadd_with_env_and_name(urls.join(":")) do - provider.install - end - end - - it "should handle append on first installpath" do - url = "ftp://your.ftp.mirror/pub/OpenBSD/5.2/packages/amd64/" - lines = ["installpath += #{url}\n"] - - expect_read_from_pkgconf(lines) - expect_pkgadd_with_env_and_name(url) do - provider.install - end - end - - %w{ installpath installpath= installpath+=}.each do |line| - it "should reject '#{line}'" do - expect_read_from_pkgconf([line]) - expect { - provider.install - }.to raise_error(Puppet::Error, /No valid installpath found in \/etc\/pkg\.conf and no source was set/) - end - end - it 'should use install_options as Array' do provider.resource[:source] = '/tma1/' provider.resource[:install_options] = ['-r', '-z'] From cd350d91eba84e42c8f75abcdf7b8027138b89e4 Mon Sep 17 00:00:00 2001 From: Sebastian Reitenbach Date: Thu, 21 Mar 2024 16:29:48 +0100 Subject: [PATCH 10/15] fix more specs --- spec/unit/provider/package/openbsd_spec.rb | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/spec/unit/provider/package/openbsd_spec.rb b/spec/unit/provider/package/openbsd_spec.rb index 3d74bf139ce..92f603802ad 100644 --- a/spec/unit/provider/package/openbsd_spec.rb +++ b/spec/unit/provider/package/openbsd_spec.rb @@ -82,9 +82,8 @@ def expect_pkgadd_with_env_and_name(source, &block) context "#install" do it 'should use install_options as Array' do - provider.resource[:source] = '/tma1/' - provider.resource[:install_options] = ['-r', '-z'] - expect(provider).to receive(:pkgadd).with(['-r', '-z', 'bash']) + provider.resource[:install_options] = ['-z'] + expect(provider).to receive(:pkgadd).with(['-r', '-z', 'bash--']) provider.install end end @@ -93,12 +92,12 @@ def expect_pkgadd_with_env_and_name(source, &block) before do provider.resource[:source] = '/tmp/tcsh.tgz' provider.resource[:name] = 'tcsh' - allow(provider).to receive(:pkginfo).with('tcsh') + allow(provider).to receive(:pkginfo).with('tcsh--') end it "should return the ensure value if the package is already installed" do allow(provider).to receive(:properties).and_return({:ensure => '4.2.45'}) - allow(provider).to receive(:pkginfo).with('-Q', 'tcsh') + allow(provider).to receive(:pkginfo).with('-Q', 'tcsh--') expect(provider.latest).to eq('4.2.45') end From d416f373e902ca4166c198a53129937547ab17fb Mon Sep 17 00:00:00 2001 From: Sebastian Reitenbach Date: Thu, 21 Mar 2024 16:35:52 +0100 Subject: [PATCH 11/15] more --- spec/unit/provider/package/openbsd_spec.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/spec/unit/provider/package/openbsd_spec.rb b/spec/unit/provider/package/openbsd_spec.rb index 92f603802ad..367577f0033 100644 --- a/spec/unit/provider/package/openbsd_spec.rb +++ b/spec/unit/provider/package/openbsd_spec.rb @@ -103,20 +103,20 @@ def expect_pkgadd_with_env_and_name(source, &block) it "should recognize a new version" do pkginfo_query = 'tcsh-6.18.01p1' - allow(provider).to receive(:pkginfo).with('-Q', 'tcsh').and_return(pkginfo_query) + allow(provider).to receive(:pkginfo).with('-Q', 'tcsh--').and_return(pkginfo_query) expect(provider.latest).to eq('6.18.01p1') end it "should recognize a newer version" do allow(provider).to receive(:properties).and_return({:ensure => '1.6.8'}) pkginfo_query = 'tcsh-1.6.10' - allow(provider).to receive(:pkginfo).with('-Q', 'tcsh').and_return(pkginfo_query) + allow(provider).to receive(:pkginfo).with('-Q', 'tcsh--').and_return(pkginfo_query) expect(provider.latest).to eq('1.6.10') end it "should recognize a package that is already the newest" do pkginfo_query = 'tcsh-6.18.01p0 (installed)' - allow(provider).to receive(:pkginfo).with('-Q', 'tcsh').and_return(pkginfo_query) + allow(provider).to receive(:pkginfo).with('-Q', 'tcsh--').and_return(pkginfo_query) expect(provider.latest).to eq('6.18.01p0') end end From eaccd7555ca313f29329d0157f956826d67c1a9a Mon Sep 17 00:00:00 2001 From: Sebastian Reitenbach Date: Thu, 21 Mar 2024 16:47:36 +0100 Subject: [PATCH 12/15] yuck, more speck --- spec/unit/provider/package/openbsd_spec.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/spec/unit/provider/package/openbsd_spec.rb b/spec/unit/provider/package/openbsd_spec.rb index 367577f0033..ce8799aac08 100644 --- a/spec/unit/provider/package/openbsd_spec.rb +++ b/spec/unit/provider/package/openbsd_spec.rb @@ -110,13 +110,13 @@ def expect_pkgadd_with_env_and_name(source, &block) it "should recognize a newer version" do allow(provider).to receive(:properties).and_return({:ensure => '1.6.8'}) pkginfo_query = 'tcsh-1.6.10' - allow(provider).to receive(:pkginfo).with('-Q', 'tcsh--').and_return(pkginfo_query) + allow(provider).to receive(:pkginfo).with('tcsh').and_return(pkginfo_query) expect(provider.latest).to eq('1.6.10') end it "should recognize a package that is already the newest" do pkginfo_query = 'tcsh-6.18.01p0 (installed)' - allow(provider).to receive(:pkginfo).with('-Q', 'tcsh--').and_return(pkginfo_query) + allow(provider).to receive(:pkginfo).with('tcsh').and_return(pkginfo_query) expect(provider.latest).to eq('6.18.01p0') end end @@ -131,7 +131,7 @@ def expect_pkgadd_with_env_and_name(source, &block) it "should return the full unversioned package name when updating without a flavor" do provider.resource[:name] = 'puppet' provider.resource[:ensure] = 'latest' - expect(provider.get_full_name).to eq('puppet') + expect(provider.get_full_name).to eq('puppet--') end it "should use the ensure parameter if it is numeric" do From cb3b5c12624b1b415df09b502b3209f424271220 Mon Sep 17 00:00:00 2001 From: Sebastian Reitenbach Date: Thu, 21 Mar 2024 16:59:08 +0100 Subject: [PATCH 13/15] blubb --- spec/unit/provider/package/openbsd_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/unit/provider/package/openbsd_spec.rb b/spec/unit/provider/package/openbsd_spec.rb index ce8799aac08..5e4a6b7ce01 100644 --- a/spec/unit/provider/package/openbsd_spec.rb +++ b/spec/unit/provider/package/openbsd_spec.rb @@ -103,7 +103,7 @@ def expect_pkgadd_with_env_and_name(source, &block) it "should recognize a new version" do pkginfo_query = 'tcsh-6.18.01p1' - allow(provider).to receive(:pkginfo).with('-Q', 'tcsh--').and_return(pkginfo_query) + allow(provider).to receive(:pkginfo).with('tcsh').and_return(pkginfo_query) expect(provider.latest).to eq('6.18.01p1') end From 26046da3a8763e07a49a65a7ea27e05573990dd2 Mon Sep 17 00:00:00 2001 From: Sebastian Reitenbach Date: Thu, 21 Mar 2024 17:07:08 +0100 Subject: [PATCH 14/15] fix --- spec/unit/provider/package/openbsd_spec.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/spec/unit/provider/package/openbsd_spec.rb b/spec/unit/provider/package/openbsd_spec.rb index 5e4a6b7ce01..9d8ec479a3f 100644 --- a/spec/unit/provider/package/openbsd_spec.rb +++ b/spec/unit/provider/package/openbsd_spec.rb @@ -103,20 +103,20 @@ def expect_pkgadd_with_env_and_name(source, &block) it "should recognize a new version" do pkginfo_query = 'tcsh-6.18.01p1' - allow(provider).to receive(:pkginfo).with('tcsh').and_return(pkginfo_query) + allow(provider).to receive(:pkginfo).with('-Q', 'tcsh--').and_return(pkginfo_query) expect(provider.latest).to eq('6.18.01p1') end it "should recognize a newer version" do allow(provider).to receive(:properties).and_return({:ensure => '1.6.8'}) pkginfo_query = 'tcsh-1.6.10' - allow(provider).to receive(:pkginfo).with('tcsh').and_return(pkginfo_query) + allow(provider).to receive(:pkginfo).with('-Q', 'tcsh--').and_return(pkginfo_query) expect(provider.latest).to eq('1.6.10') end it "should recognize a package that is already the newest" do pkginfo_query = 'tcsh-6.18.01p0 (installed)' - allow(provider).to receive(:pkginfo).with('tcsh').and_return(pkginfo_query) + allow(provider).to receive(:pkginfo).with('-Q', 'tcsh--').and_return(pkginfo_query) expect(provider.latest).to eq('6.18.01p0') end end From ee87505ee788447bcdbcfd6c943b390821b09263 Mon Sep 17 00:00:00 2001 From: Sebastian Reitenbach Date: Thu, 11 Apr 2024 21:24:29 +0200 Subject: [PATCH 15/15] Revamp OpenBSD package handling * pkg.conf file is long gone * drop versionable * drop upgradeable * add support for package branches --- lib/puppet/provider/package/openbsd.rb | 191 +++++------------- .../provider/package/openbsd/pkginfo.detail | 19 -- .../provider/package/openbsd/pkginfo.list | 16 +- .../provider/package/openbsd/pkginfo.query | 1 - .../package/openbsd/pkginfo_flavors.list | 2 - spec/unit/provider/package/openbsd_spec.rb | 164 ++++----------- 6 files changed, 98 insertions(+), 295 deletions(-) delete mode 100644 spec/fixtures/unit/provider/package/openbsd/pkginfo.detail delete mode 100644 spec/fixtures/unit/provider/package/openbsd/pkginfo.query delete mode 100644 spec/fixtures/unit/provider/package/openbsd/pkginfo_flavors.list diff --git a/lib/puppet/provider/package/openbsd.rb b/lib/puppet/provider/package/openbsd.rb index a9f08973e5f..5cadfc4daa5 100644 --- a/lib/puppet/provider/package/openbsd.rb +++ b/lib/puppet/provider/package/openbsd.rb @@ -6,49 +6,56 @@ Puppet::Type.type(:package).provide :openbsd, :parent => Puppet::Provider::Package do desc "OpenBSD's form of `pkg_add` support. + OpenBSD has the concept of package branches, providing multiple versions of the + same package, i.e. `stable` vs. `snapshot`. To select a specific branch, + suffix the package name with % sign follwed by the branch name, i.e. `gimp%stable`. + This provider supports the `install_options` and `uninstall_options` attributes, which allow command-line flags to be passed to pkg_add and pkg_delete. These options should be specified as an array where each element is either a string or a hash." - commands :pkginfo => "pkg_info", - :pkgadd => "pkg_add", + commands :pkgadd => "pkg_add", + :pkginfo => "pkg_info", :pkgdelete => "pkg_delete" defaultfor 'os.name' => :openbsd confine 'os.name' => :openbsd - has_feature :versionable has_feature :install_options has_feature :uninstall_options - has_feature :upgradeable has_feature :supports_flavors - mk_resource_methods - def self.instances packages = [] begin execpipe(listcmd) do |process| # our regex for matching pkg_info output - regex = /^(.*)-(\d[^-]*)-?([\w-]*)(.*)$/ - fields = [:name, :ensure, :flavor] + regex = /^(.*)--([\w-]+)?(%[^w]+)?$/ + fields = [:name, :flavor, :branch] hash = {} # now turn each returned line into a package object process.each_line { |line| - match = regex.match(line.split[0]) - next unless match - - fields.zip(match.captures) { |field, value| - hash[field] = value - } - - hash[:provider] = name - - packages << new(hash) - hash = {} + match = regex.match(line.split("\n")[0]) + if match + fields.zip(match.captures) { |field, value| + hash[field] = value + } + + hash[:name] = "#{hash[:name]}#{hash[:branch]}" if hash[:branch] + + hash[:provider] = name + packages << new(hash) + hash = {} + else + unless line =~ /Updating the pkgdb/ + # Print a warning on lines we can't match, but move + # on, since it should be non-fatal + warning(_("Failed to match line %{line}") % { line: line }) + end + end } end @@ -59,152 +66,55 @@ def self.instances end def self.listcmd - [command(:pkginfo), "-a"] - end - - def latest - if @resource[:flavor] - query = "#{@resource[:name]}--#{@resource[:flavor]}" - else - query = @resource[:name] + "--" - end - - output = Puppet::Util.withenv({}) { pkginfo "-Q", query } - - if output.nil? or output.size == 0 or output =~ /Error from / - debug "Failed to query for #{resource[:name]}" - return properties[:ensure] - else - # Remove all fuzzy matches first. - output = output.split.select { |p| p =~ /^#{resource[:name]}-(\d[^-]*)-?(\w*)/ }.join - debug "pkg_info -Q for #{resource[:name]}: #{output}" - end - - if output =~ /^#{resource[:name]}-(\d[^-]*)-?(\w*) \(installed\)$/ - debug "Package is already the latest available" - properties[:ensure] - else - match = /^(.*)-(\d[^-]*)-?(\w*)$/.match(output) - debug "Latest available for #{resource[:name]}: #{match[2]}" - - if properties[:ensure].to_sym == :absent - return match[2] - end - - vcmp = properties[:ensure].split('.').map { |s| s.to_i } <=> match[2].split('.').map { |s| s.to_i } - if vcmp > 0 - # The locally installed package may actually be newer than what a mirror - # has. Log it at debug, but ignore it otherwise. - debug "Package #{resource[:name]} #{properties[:ensure]} newer then available #{match[2]}" - properties[:ensure] - else - match[2] - end - end + [command(:pkginfo), "-a", "-z"] end - def update - install(true) - end - - def install(latest = false) + def install cmd = [] + full_name = get_full_name + cmd << '-r' cmd << install_options - cmd << get_full_name(latest) - - if latest - cmd.unshift('-z') - end + cmd << full_name # pkg_add(1) doesn't set the return value upon failure so we have to peek # at it's output to see if something went wrong. output = Puppet::Util.withenv({}) { pkgadd cmd.flatten.compact } - pp output if output =~ /Can't find / self.fail "pkg_add returned: #{output.chomp}" end end - def get_full_name(latest = false) + def get_full_name # In case of a real update (i.e., the package already exists) then # pkg_add(8) can handle the flavors. However, if we're actually # installing with 'latest', we do need to handle the flavors. This is # done so we can feed pkg_add(8) the full package name to install to # prevent ambiguity. - if resource[:flavor] - # If :ensure contains a version, use that instead of looking it up. - # This allows for installing packages with the same stem, but multiple - # version such as postfix-VERSION-flavor. - if @resource[:ensure].to_s =~ /(\d[^-]*)$/ - use_version = @resource[:ensure] - else - use_version = '' - end - "#{resource[:name]}-#{use_version}-#{resource[:flavor]}" - elsif resource[:name].to_s.match(/[a-z0-9]%[0-9a-z]/i) - resource[:name].to_s - elsif !latest - "#{resource[:name]}--" - else - # If :ensure contains a version, use that instead of looking it up. - # This allows for installing packages with the same stem, but multiple - # version such as openldap-server. - if @resource[:ensure].to_s =~ /(\d[^-]*)$/ - use_version = @resource[:ensure] - else - use_version = get_version - end - - if resource[:flavor] - [@resource[:name], use_version, @resource[:flavor]].join('-').gsub(/-+$/, '') - else - [@resource[:name], use_version] - end - end - end - def get_version - pkg_search_name = @resource[:name] - unless pkg_search_name.match(/[a-z0-9]%[0-9a-z]/i) and !@resource[:flavor] - # we are only called when no flavor is specified - # so append '--' to the :name to avoid patch versions on flavors - pkg_search_name << "--" + name_branch_regex = /^(\S*)(%\w*)$/ + match = name_branch_regex.match(@resource[:name]) + if match + use_name = match.captures[0] + use_branch = match.captures[1] + else + use_name = @resource[:name] + use_branch = '' end - # our regex for matching pkg_info output - regex = /^(.*)-(\d[^-]*)[-]?(\w*)(.*)$/ - master_version = 0 - version = -1 - - # pkg_info -I might return multiple lines, i.e. flavors - matching_pkgs = pkginfo("-I", "pkg_search_name") - matching_pkgs.each_line do |line| - next unless (match = regex.match(line.split[0])) - - # now we return the first version, unless ensure is latest - version = match.captures[1] - return version unless @resource[:ensure] == "latest" - master_version = version unless master_version > version + if @resource[:flavor] + "#{use_name}--#{@resource[:flavor]}#{use_branch}" + else + "#{use_name}--#{use_branch}" end - - return master_version unless master_version == 0 - - return '' if version == -1 - - raise Puppet::Error, _("%{version} is not available for this package") % { version: version } - rescue Puppet::ExecutionFailure - nil end def query - # Search for the version info - if pkginfo(@resource[:name]) =~ /Information for (inst:)?#{@resource[:name]}-(\S+)/ - { :ensure => Regexp.last_match(2) } - else - nil + pkg = self.class.instances.find do |package| + @resource[:name] == package.name end + pkg ? pkg.properties : nil end def install_options @@ -212,15 +122,15 @@ def install_options end def uninstall_options - [join_options(resource[:uninstall_options])] + join_options(resource[:uninstall_options]) || [] end def uninstall - pkgdelete uninstall_options.flatten.compact, @resource[:name] + pkgdelete uninstall_options.flatten.compact, get_full_name end def purge - pkgdelete "-c", "-q", @resource[:name] + pkgdelete "-c", "-qq", uninstall_options.flatten.compact, get_full_name end def flavor @@ -229,7 +139,6 @@ def flavor def flavor=(value) if flavor != @resource.should(:flavor) - uninstall install end end diff --git a/spec/fixtures/unit/provider/package/openbsd/pkginfo.detail b/spec/fixtures/unit/provider/package/openbsd/pkginfo.detail deleted file mode 100644 index 5879a2abe61..00000000000 --- a/spec/fixtures/unit/provider/package/openbsd/pkginfo.detail +++ /dev/null @@ -1,19 +0,0 @@ -Information for bash-3.1.17 - -Comment: -GNU Bourne Again Shell - -Description: -Bash is the GNU Project's Bourne Again SHell, an sh-compatible -command language interpreter that executes commands read from the -standard input or from a file. Bash also incorporates useful -features from the Korn and C shells (ksh and csh). - -Bash is intended to be a conformant implementation of the IEEE POSIX -Shell and Tools specification (IEEE Working Group 1003.2). - -Maintainer: Christian Weisgerber - -WWW: http://cnswww.cns.cwru.edu/~chet/bash/bashtop.html - - diff --git a/spec/fixtures/unit/provider/package/openbsd/pkginfo.list b/spec/fixtures/unit/provider/package/openbsd/pkginfo.list index 5f4866aa133..936cffc38e2 100644 --- a/spec/fixtures/unit/provider/package/openbsd/pkginfo.list +++ b/spec/fixtures/unit/provider/package/openbsd/pkginfo.list @@ -1,10 +1,6 @@ -bash-3.1.17 GNU Bourne Again Shell -bzip2-1.0.3 block-sorting file compressor, unencumbered -expat-2.0.0 XML 1.0 parser written in C -gettext-0.14.5p1 GNU gettext -libiconv-1.9.2p3 character set conversion library -lzo-1.08p1 portable speedy lossless data compression library -openvpn-2.0.6 easy-to-use, robust, and highly configurable VPN -python-2.4.3p0 interpreted object-oriented programming language -vim-7.0.42-no_x11 vi clone, many additional features -wget-1.10.2p0 retrieve files from the web via HTTP, HTTPS and FTP +autoconf--%2.13 +autoconf--%2.56 +bash-- +postfix--ldap%stable +puppet--%8 +zstd-- diff --git a/spec/fixtures/unit/provider/package/openbsd/pkginfo.query b/spec/fixtures/unit/provider/package/openbsd/pkginfo.query deleted file mode 100644 index d79aecfa309..00000000000 --- a/spec/fixtures/unit/provider/package/openbsd/pkginfo.query +++ /dev/null @@ -1 +0,0 @@ -bash-3.1.17 GNU Bourne Again Shell diff --git a/spec/fixtures/unit/provider/package/openbsd/pkginfo_flavors.list b/spec/fixtures/unit/provider/package/openbsd/pkginfo_flavors.list deleted file mode 100644 index 1ed49a5ebed..00000000000 --- a/spec/fixtures/unit/provider/package/openbsd/pkginfo_flavors.list +++ /dev/null @@ -1,2 +0,0 @@ -bash-3.1.17-static GNU Bourne Again Shell -vim-7.0.42-no_x11 vi clone, many additional features diff --git a/spec/unit/provider/package/openbsd_spec.rb b/spec/unit/provider/package/openbsd_spec.rb index 9d8ec479a3f..3248c1683f0 100644 --- a/spec/unit/provider/package/openbsd_spec.rb +++ b/spec/unit/provider/package/openbsd_spec.rb @@ -2,42 +2,16 @@ require 'stringio' describe Puppet::Type.type(:package).provider(:openbsd) do + include PuppetSpec::Fixtures + let(:package) { Puppet::Type.type(:package).new(:name => 'bash', :provider => 'openbsd') } let(:provider) { described_class.new(package) } - def expect_read_from_pkgconf(lines) - pkgconf = double(:readlines => lines) - expect(Puppet::FileSystem).to receive(:exist?).with('/etc/pkg.conf').and_return(true) - expect(File).to receive(:open).with('/etc/pkg.conf', 'rb').and_return(pkgconf) - end - - def expect_pkgadd_with_source(source) - expect(provider).to receive(:pkgadd).with([source]) do - expect(ENV).not_to have_key('PKG_PATH') - end - end - - def expect_pkgadd_with_env_and_name(source, &block) - expect(ENV).not_to have_key('PKG_PATH') - - expect(provider).to receive(:pkgadd).with([provider.resource[:name]]) do - expect(ENV).to have_key('PKG_PATH') - expect(ENV['PKG_PATH']).to eq(source) - end - expect(provider).to receive(:execpipe).with(['/bin/pkg_info', '-I', provider.resource[:name]]).and_yield('') - - yield - - expect(ENV).not_to be_key('PKG_PATH') - end - context 'provider features' do it { is_expected.to be_installable } it { is_expected.to be_install_options } it { is_expected.to be_uninstallable } it { is_expected.to be_uninstall_options } - it { is_expected.to be_upgradeable } - it { is_expected.to be_versionable } end before :each do @@ -46,37 +20,40 @@ def expect_pkgadd_with_env_and_name(source, &block) allow(described_class).to receive(:command).with(:pkginfo).and_return('/bin/pkg_info') allow(described_class).to receive(:command).with(:pkgadd).and_return('/bin/pkg_add') allow(described_class).to receive(:command).with(:pkgdelete).and_return('/bin/pkg_delete') - - allow(Puppet::FileSystem).to receive(:exist?) end context "#instances" do it "should return nil if execution failed" do - expect(described_class).to receive(:execpipe).and_raise(Puppet::ExecutionFailure, 'wawawa') + #expect(provider).to receive(:pkginfo).and_raise(Puppet::ExecutionFailure, 'wawawa') + #expect(provider).to receive(:pkginfo).with(['-a', '-z']) expect(described_class.instances).to be_nil end it "should return the empty set if no packages are listed" do - expect(described_class).to receive(:execpipe).with(%w{/bin/pkg_info -a}).and_yield(StringIO.new('')) + expect(described_class).to receive(:execpipe).with(%w{/bin/pkg_info -a -z}).and_yield(StringIO.new('')) expect(described_class.instances).to be_empty end it "should return all packages when invoked" do fixture = File.read(my_fixture('pkginfo.list')) - expect(described_class).to receive(:execpipe).with(%w{/bin/pkg_info -a}).and_yield(fixture) + expect(described_class).to receive(:execpipe).with(%w{/bin/pkg_info -a -z}).and_yield(fixture) expect(described_class.instances.map(&:name).sort).to eq( - %w{bash bzip2 expat gettext libiconv lzo openvpn python vim wget}.sort + %w{autoconf%2.13 autoconf%2.56 bash postfix%stable puppet%8 zstd}.sort ) end it "should return all flavors if set" do - fixture = File.read(my_fixture('pkginfo_flavors.list')) - expect(described_class).to receive(:execpipe).with(%w{/bin/pkg_info -a}).and_yield(fixture) + fixture = File.read(my_fixture('pkginfo.list')) + expect(described_class).to receive(:execpipe).with(%w{/bin/pkg_info -a -z}).and_yield(fixture) instances = described_class.instances.map {|p| {:name => p.get(:name), - :ensure => p.get(:ensure), :flavor => p.get(:flavor)}} - expect(instances.size).to eq(2) - expect(instances[0]).to eq({:name => 'bash', :ensure => '3.1.17', :flavor => 'static'}) - expect(instances[1]).to eq({:name => 'vim', :ensure => '7.0.42', :flavor => 'no_x11'}) + :flavor => p.get(:flavor), :branch => p.get(:branch)}} + expect(instances.size).to eq(6) + expect(instances[0]).to eq({:name => 'autoconf%2.13', :flavor => :absent, :branch => '%2.13'}) + expect(instances[1]).to eq({:name => 'autoconf%2.56', :flavor => :absent, :branch => '%2.56'}) + expect(instances[2]).to eq({:name => 'bash', :flavor => :absent, :branch => :absent}) + expect(instances[3]).to eq({:name => 'postfix%stable', :flavor => 'ldap', :branch => '%stable'}) + expect(instances[4]).to eq({:name => 'puppet%8', :flavor => :absent, :branch => '%8'}) + expect(instances[5]).to eq({:name => 'zstd', :flavor => :absent, :branch => :absent}) end end @@ -88,102 +65,46 @@ def expect_pkgadd_with_env_and_name(source, &block) end end - context "#latest" do - before do - provider.resource[:source] = '/tmp/tcsh.tgz' - provider.resource[:name] = 'tcsh' - allow(provider).to receive(:pkginfo).with('tcsh--') - end - - it "should return the ensure value if the package is already installed" do - allow(provider).to receive(:properties).and_return({:ensure => '4.2.45'}) - allow(provider).to receive(:pkginfo).with('-Q', 'tcsh--') - expect(provider.latest).to eq('4.2.45') - end - - it "should recognize a new version" do - pkginfo_query = 'tcsh-6.18.01p1' - allow(provider).to receive(:pkginfo).with('-Q', 'tcsh--').and_return(pkginfo_query) - expect(provider.latest).to eq('6.18.01p1') - end - - it "should recognize a newer version" do - allow(provider).to receive(:properties).and_return({:ensure => '1.6.8'}) - pkginfo_query = 'tcsh-1.6.10' - allow(provider).to receive(:pkginfo).with('-Q', 'tcsh--').and_return(pkginfo_query) - expect(provider.latest).to eq('1.6.10') - end - - it "should recognize a package that is already the newest" do - pkginfo_query = 'tcsh-6.18.01p0 (installed)' - allow(provider).to receive(:pkginfo).with('-Q', 'tcsh--').and_return(pkginfo_query) - expect(provider.latest).to eq('6.18.01p0') - end - end - context "#get_full_name" do - it "should return the full unversioned package name when updating with a flavor" do - provider.resource[:ensure] = 'latest' + it "should return the full unversioned package name when installing with a flavor" do + provider.resource[:ensure] = 'present' provider.resource[:flavor] = 'static' expect(provider.get_full_name).to eq('bash--static') end - it "should return the full unversioned package name when updating without a flavor" do - provider.resource[:name] = 'puppet' - provider.resource[:ensure] = 'latest' - expect(provider.get_full_name).to eq('puppet--') + it "should return the full unversioned package name when installing with a branch" do + provider.resource[:name] = 'bash%stable' + expect(provider.get_full_name).to eq('bash--%stable') end - it "should use the ensure parameter if it is numeric" do - provider.resource[:name] = 'zsh' - provider.resource[:ensure] = '1.0' - expect(provider.get_full_name).to eq('zsh-1.0') - end - - it "should lookup the correct version" do - output = 'bash-3.1.17 GNU Bourne Again Shell' - expect(provider).to receive(:execpipe).with(%w{/bin/pkg_info -I bash}).and_yield(output) - expect(provider.get_full_name).to eq('bash-3.1.17') - end - - it "should lookup the correction version with flavors" do - provider.resource[:name] = 'fossil' - provider.resource[:flavor] = 'static' - output = 'fossil-1.29v0-static simple distributed software configuration management' - expect(provider).to receive(:execpipe).with(%w{/bin/pkg_info -I fossil}).and_yield(output) - expect(provider.get_full_name).to eq('fossil-1.29v0-static') + it "should return the full unversioned package name when installing without a flavor" do + provider.resource[:name] = 'puppet' + expect(provider.get_full_name).to eq('puppet--') end - end - context "#get_version" do - it "should return nil if execution fails" do - expect(provider).to receive(:execpipe).and_raise(Puppet::ExecutionFailure, 'wawawa') - expect(provider.get_version).to be_nil + it "should return unversioned package name when installing without flavor or branch" do + expect(provider.get_full_name).to eq('bash--') end - it "should return the package version if in the output" do - output = 'bash-3.1.17 GNU Bourne Again Shell' - expect(provider).to receive(:execpipe).with(%w{/bin/pkg_info -I bash}).and_yield(output) - expect(provider.get_version).to eq('3.1.17') + it "should return the full unversioned package name when installing with branch and flavor" do + provider.resource[:name] = 'postfix%stable' + provider.resource[:flavor] = 'ldap-mysql' + expect(provider.get_full_name).to eq('postfix--ldap-mysql%stable') end - it "should return the empty string if the package is not present" do - provider.resource[:name] = 'zsh' - expect(provider).to receive(:execpipe).with(%w{/bin/pkg_info -I zsh}).and_yield(StringIO.new('')) - expect(provider.get_version).to eq('') - end end context "#query" do - it "should return the installed version if present" do - fixture = File.read(my_fixture('pkginfo.detail')) - expect(provider).to receive(:pkginfo).with('bash').and_return(fixture) - expect(provider.query).to eq({ :ensure => '3.1.17' }) + it "should return package info if present" do + fixture = File.read(my_fixture('pkginfo.list')) + expect(described_class).to receive(:execpipe).with(%w{/bin/pkg_info -a -z}).and_yield(fixture) + expect(provider.query).to eq({:branch=>nil, :flavor=>nil, :name=>"bash", :provider=>:openbsd}) end it "should return nothing if not present" do + fixture = File.read(my_fixture('pkginfo.list')) provider.resource[:name] = 'zsh' - expect(provider).to receive(:pkginfo).with('zsh').and_return('') + expect(described_class).to receive(:execpipe).with(%w{/bin/pkg_info -a -z}).and_yield(fixture) expect(provider.query).to be_nil end end @@ -210,8 +131,8 @@ def expect_pkgadd_with_env_and_name(source, &block) end context "#uninstall_options" do - it "should return nill by default" do - expect(provider.uninstall_options).to be_nil + it "should return empty array by default" do + expect(provider.uninstall_options).to eq([]) end it "should return uninstall_options when set" do @@ -233,7 +154,7 @@ def expect_pkgadd_with_env_and_name(source, &block) context "#uninstall" do describe 'when uninstalling' do it 'should use erase to purge' do - expect(provider).to receive(:pkgdelete).with('-c', '-q', 'bash') + expect(provider).to receive(:pkgdelete).with('-c', '-qq', [], 'bash--') provider.purge end end @@ -241,7 +162,7 @@ def expect_pkgadd_with_env_and_name(source, &block) describe 'with uninstall_options' do it 'should use uninstall_options as Array' do provider.resource[:uninstall_options] = ['-q', '-c'] - expect(provider).to receive(:pkgdelete).with(['-q', '-c'], 'bash') + expect(provider).to receive(:pkgdelete).with(['-q', '-c'], 'bash--') provider.uninstall end end @@ -256,9 +177,8 @@ def expect_pkgadd_with_env_and_name(source, &block) expect(provider.flavor).to eq('no_x11-python') end - it 'should remove and install the new flavor if different' do + it 'should reinstall the new flavor if different' do provider.resource[:flavor] = 'no_x11-ruby' - expect(provider).to receive(:uninstall).ordered expect(provider).to receive(:install).ordered provider.flavor = provider.resource[:flavor] end