puppet 4.10.8 → 4.10.9

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of puppet might be problematic. Click here for more details.

@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 1c19dcf24ffdd82dc67550cce341c1ab7a7eb101
4
+ data.tar.gz: 7a0d6ea9246d361cbce8c3a317695bbbd3259a11
5
+ SHA512:
6
+ metadata.gz: 2414fbc5362e40b5363ae062036ca6ce77865362e11a85291e8e300f35ce34bbe767a3f170db8cbe93445c3af4d349d0be986eca1232099ba0271df75d9e792b
7
+ data.tar.gz: e269546a3c53346b599e9d98217cb147b856ae57cd11fedde16cbfe71a93e3db243c53cde6b4f6e4a3ad3354eeb3e4f6cc43b234373a2245210871bbc953d68c
@@ -52,7 +52,7 @@ require 'strscan'
52
52
  class ::Nagios::Parser::SyntaxError < RuntimeError; end
53
53
 
54
54
  def parse(src)
55
- if src.respond_to?("force_encoding") then
55
+ if (RUBY_VERSION < '2.1.0') && src.respond_to?("force_encoding") then
56
56
  src.force_encoding("ASCII-8BIT")
57
57
  end
58
58
  @ss = StringScanner.new(src)
@@ -14,7 +14,7 @@ require 'strscan'
14
14
  class ::Nagios::Parser::SyntaxError < RuntimeError; end
15
15
 
16
16
  def parse(src)
17
- if src.respond_to?("force_encoding") then
17
+ if (RUBY_VERSION < '2.1.0') && src.respond_to?("force_encoding") then
18
18
  src.force_encoding("ASCII-8BIT")
19
19
  end
20
20
  @ss = StringScanner.new(src)
@@ -64,7 +64,7 @@ class Puppet::Forge < SemanticPuppet::Dependency::Source
64
64
 
65
65
  if response.code == '200'
66
66
  result = JSON.parse(response.body)
67
- uri = result['pagination']['next']
67
+ uri = decode_uri(result['pagination']['next'])
68
68
  matches.concat result['results']
69
69
  else
70
70
  raise ResponseError.new(:uri => URI.parse(@host).merge(uri), :response => response)
@@ -89,7 +89,7 @@ class Puppet::Forge < SemanticPuppet::Dependency::Source
89
89
  # @see SemanticPuppet::Dependency::Source#fetch
90
90
  def fetch(input)
91
91
  name = input.tr('/', '-')
92
- uri = "/v3/releases?module=#{name}"
92
+ uri = "/v3/releases?module=#{name}&sort_by=version"
93
93
  if Puppet[:module_groups]
94
94
  uri += "&module_groups=#{Puppet[:module_groups].gsub('+', ' ')}"
95
95
  end
@@ -106,7 +106,7 @@ class Puppet::Forge < SemanticPuppet::Dependency::Source
106
106
  end
107
107
 
108
108
  releases.concat(process(response['results']))
109
- uri = response['pagination']['next']
109
+ uri = decode_uri(response['pagination']['next'])
110
110
  end
111
111
 
112
112
  return releases
@@ -225,4 +225,10 @@ class Puppet::Forge < SemanticPuppet::Dependency::Source
225
225
 
226
226
  l.select { |r| r }
227
227
  end
228
+
229
+ def decode_uri(uri)
230
+ return if uri.nil?
231
+
232
+ URI.decode(uri.gsub('+', ' '))
233
+ end
228
234
  end
@@ -44,8 +44,8 @@ class Puppet::Forge
44
44
 
45
45
  # Return a Net::HTTPResponse read for this +path+.
46
46
  def make_http_request(path, io = nil)
47
- Puppet.debug "HTTP GET #{@host}#{path}"
48
47
  request = get_request_object(@uri.path.chomp('/')+path)
48
+ Puppet.debug "HTTP GET #{@host}#{request.path}"
49
49
  return read_response(request, io)
50
50
  end
51
51
 
@@ -244,6 +244,12 @@ class Puppet::Graph::RelationshipGraph < Puppet::Graph::SimpleGraph
244
244
  containers.each { |x|
245
245
  admissible[x] = whit_class.new(:name => "admissible_#{x.ref}", :catalog => catalog)
246
246
  completed[x] = whit_class.new(:name => "completed_#{x.ref}", :catalog => catalog)
247
+
248
+ # This copies the original container's tags over to the two anchor whits.
249
+ # Without this, tags are not propagated to the container's resources.
250
+ admissible[x].set_tags(x)
251
+ completed[x].set_tags(x)
252
+
247
253
  priority = @prioritizer.priority_of(x)
248
254
  add_vertex(admissible[x], priority)
249
255
  add_vertex(completed[x], priority)
@@ -218,7 +218,7 @@ module Puppet::FileBucketFile
218
218
  # and content as that in the bucket_file
219
219
  # @api private
220
220
  def verify_identical_file(contents_file, bucket_file)
221
- (bucket_file.size == Puppet::FileSystem.size(contents_file)) &&
221
+ (bucket_file.to_binary.bytesize == Puppet::FileSystem.size(contents_file)) &&
222
222
  (bucket_file.stream() {|s| Puppet::FileSystem.compare_stream(contents_file, s) })
223
223
  end
224
224
 
@@ -77,7 +77,7 @@ class Puppet::Module
77
77
  Puppet.warning _("GettextSetup initialization for %{module_name} failed with: %{error_message}") % { module_name: name, error_message: e.message }
78
78
  end
79
79
  else
80
- Puppet.warning _("GettextSetup is not available, skipping GettextSetup initialization for %{module_name}.") % { module_name: name }
80
+ Puppet.warn_once("gettext_unavailable", "gettext_unavailable", "GettextSetup is not available, skipping GettextSetup initialization for modules.")
81
81
  end
82
82
  end
83
83
 
@@ -906,6 +906,10 @@ class PNumericType < PAbstractRangeType
906
906
  end
907
907
  end
908
908
 
909
+ def instance?(o, guard = nil)
910
+ (o.is_a?(Float) || o.is_a?(Integer)) && o >= @from && o <= @to
911
+ end
912
+
909
913
  protected
910
914
 
911
915
  # @api_private
@@ -32,15 +32,28 @@ Puppet::Type.type(:service).provide :base, :parent => :service do
32
32
  @resource.fail "Either stop/status commands or a pattern must be specified" unless @resource[:pattern]
33
33
  regex = Regexp.new(@resource[:pattern])
34
34
  ps = getps
35
+
35
36
  self.debug "Executing '#{ps}'"
36
- IO.popen(ps) { |table|
37
- table.each_line { |line|
38
- if regex.match(line)
39
- self.debug "Process matched: #{line}"
40
- ary = line.sub(/^\s+/, '').split(/\s+/)
41
- return ary[1]
42
- end
43
- }
37
+ table = Puppet::Util::Execution.execute(ps)
38
+
39
+ # The output of the PS command can be a mashup of several different
40
+ # encodings depending on which processes are running and what
41
+ # arbitrary data has been used to set their name in the process table.
42
+ #
43
+ # First, try a polite conversion to in order to match the UTF-8 encoding
44
+ # of our regular expression.
45
+ table = Puppet::Util::CharacterEncoding.convert_to_utf_8(table)
46
+ # If that fails, force to UTF-8 and then scrub as most uses are scanning
47
+ # for ACII-compatible program names.
48
+ table.force_encoding(Encoding::UTF_8) unless table.encoding == Encoding::UTF_8
49
+ table = Puppet::Util::CharacterEncoding.scrub(table) unless table.valid_encoding?
50
+
51
+ table.each_line { |line|
52
+ if regex.match(line)
53
+ self.debug "Process matched: #{line}"
54
+ ary = line.sub(/^[[:space:]]+/u, '').split(/[[:space:]]+/u)
55
+ return ary[1]
56
+ end
44
57
  }
45
58
 
46
59
  nil
@@ -15,7 +15,11 @@ Puppet::Type.type(:zfs).provide(:zfs) do
15
15
  Puppet::Type.type(:zfs).validproperties.each do |property|
16
16
  next if property == :ensure
17
17
  if value = @resource[property] and value != ""
18
- properties << "-o" << "#{property}=#{value}"
18
+ if property == :volsize
19
+ properties << "-V" << "#{value}"
20
+ else
21
+ properties << "-o" << "#{property}=#{value}"
22
+ end
19
23
  end
20
24
  end
21
25
  properties
@@ -118,8 +118,7 @@ Puppet::Type.newtype(:scheduled_task) do
118
118
  * `months` --- Which months the task should run, as an array. Defaults to
119
119
  all months. Each month must be an integer between 1 and 12.
120
120
  * `on` **(Required)** --- Which days of the month the task should run,
121
- as an array. Each day must be either an integer between 1 and 31,
122
- or the special value `last,` which is always the last day of the month.
121
+ as an array. Each day must be an integer between 1 and 31.
123
122
  * For `monthly` (by weekday) triggers:
124
123
  * `months` --- Which months the task should run, as an array. Defaults to
125
124
  all months. Each month must be an integer between 1 and 12.
@@ -128,19 +127,19 @@ Puppet::Type.newtype(:scheduled_task) do
128
127
  `tues`, `wed`, `thurs`, `fri`, `sat`, `sun`, or `all`.
129
128
  * `which_occurrence` **(Required)** --- The occurrence of the chosen weekday
130
129
  when the task should run. Must be one of `first`, `second`, `third`,
131
- `fourth`, `fifth`, or `last`.
130
+ `fourth`, or `fifth`.
132
131
 
133
132
 
134
133
  Examples:
135
134
 
136
- # Run at 8am on the 1st, 15th, and last day of the month in January, March,
135
+ # Run at 8am on the 1st and 15th days of the month in January, March,
137
136
  # May, July, September, and November, starting after August 31st, 2011.
138
137
  trigger => {
139
138
  schedule => monthly,
140
139
  start_date => '2011-08-31', # Defaults to current date
141
140
  start_time => '08:00', # Must be specified
142
141
  months => [1,3,5,7,9,11], # Defaults to all
143
- on => [1, 15, last], # Must be specified
142
+ on => [1, 15], # Must be specified
144
143
  }
145
144
 
146
145
  # Run at 8am on the first Monday of the month for January, March, and May,
@@ -179,9 +179,23 @@ module Puppet::Util::Windows::File
179
179
 
180
180
  def self.get_reparse_point_data(handle, &block)
181
181
  # must be multiple of 1024, min 10240
182
- FFI::MemoryPointer.new(REPARSE_DATA_BUFFER.size) do |reparse_data_buffer_ptr|
182
+ FFI::MemoryPointer.new(MAXIMUM_REPARSE_DATA_BUFFER_SIZE) do |reparse_data_buffer_ptr|
183
183
  device_io_control(handle, FSCTL_GET_REPARSE_POINT, nil, reparse_data_buffer_ptr)
184
- yield REPARSE_DATA_BUFFER.new(reparse_data_buffer_ptr)
184
+
185
+ reparse_tag = reparse_data_buffer_ptr.read_win32_ulong
186
+ buffer_type = case reparse_tag
187
+ when 0xA000000C
188
+ SYMLINK_REPARSE_DATA_BUFFER
189
+ when 0xA0000003
190
+ MOUNT_POINT_REPARSE_DATA_BUFFER
191
+ when 0x80000014
192
+ raise Puppet::Util::Windows::Error.new("Retrieving NFS reparse point data is unsupported")
193
+ else
194
+ raise Puppet::Util::Windows::Error.new("DeviceIoControl(#{handle}, " +
195
+ "FSCTL_GET_REPARSE_POINT) returned unknown tag 0x#{reparse_tag.to_s(16).upcase}")
196
+ end
197
+
198
+ yield buffer_type.new(reparse_data_buffer_ptr)
185
199
  end
186
200
 
187
201
  # underlying struct MemoryPointer has been cleaned up by this point, nothing to return
@@ -448,11 +462,11 @@ module Puppet::Util::Windows::File
448
462
 
449
463
  MAXIMUM_REPARSE_DATA_BUFFER_SIZE = 16384
450
464
 
451
- # REPARSE_DATA_BUFFER
465
+ # SYMLINK_REPARSE_DATA_BUFFER
452
466
  # https://msdn.microsoft.com/en-us/library/cc232006.aspx
453
467
  # https://msdn.microsoft.com/en-us/library/windows/hardware/ff552012(v=vs.85).aspx
454
468
  # struct is always MAXIMUM_REPARSE_DATA_BUFFER_SIZE bytes
455
- class REPARSE_DATA_BUFFER < FFI::Struct
469
+ class SYMLINK_REPARSE_DATA_BUFFER < FFI::Struct
456
470
  layout :ReparseTag, :win32_ulong,
457
471
  :ReparseDataLength, :ushort,
458
472
  :Reserved, :ushort,
@@ -466,6 +480,23 @@ module Puppet::Util::Windows::File
466
480
  :PathBuffer, [:byte, MAXIMUM_REPARSE_DATA_BUFFER_SIZE - 20]
467
481
  end
468
482
 
483
+ # MOUNT_POINT_REPARSE_DATA_BUFFER
484
+ # https://msdn.microsoft.com/en-us/library/cc232007.aspx
485
+ # https://msdn.microsoft.com/en-us/library/windows/hardware/ff552012(v=vs.85).aspx
486
+ # struct is always MAXIMUM_REPARSE_DATA_BUFFER_SIZE bytes
487
+ class MOUNT_POINT_REPARSE_DATA_BUFFER < FFI::Struct
488
+ layout :ReparseTag, :win32_ulong,
489
+ :ReparseDataLength, :ushort,
490
+ :Reserved, :ushort,
491
+ :SubstituteNameOffset, :ushort,
492
+ :SubstituteNameLength, :ushort,
493
+ :PrintNameOffset, :ushort,
494
+ :PrintNameLength, :ushort,
495
+ # max less above fields dword / uint 4 bytes, ushort 2 bytes
496
+ # technically a WCHAR buffer, but we care about size in bytes here
497
+ :PathBuffer, [:byte, MAXIMUM_REPARSE_DATA_BUFFER_SIZE - 16]
498
+ end
499
+
469
500
  # https://msdn.microsoft.com/en-us/library/windows/desktop/aa364980(v=vs.85).aspx
470
501
  # DWORD WINAPI GetLongPathName(
471
502
  # _In_ LPCTSTR lpszShortPath,
@@ -6,7 +6,7 @@
6
6
  # Raketasks and such to set the version based on the output of `git describe`
7
7
 
8
8
  module Puppet
9
- PUPPETVERSION = '4.10.8'
9
+ PUPPETVERSION = '4.10.9'
10
10
 
11
11
  ##
12
12
  # version is a public API method intended to always provide a fast and
@@ -6,11 +6,11 @@
6
6
  #, fuzzy
7
7
  msgid ""
8
8
  msgstr ""
9
- "Project-Id-Version: Puppet automation framework 5.0.0-48-gd9d2edc\n"
9
+ "Project-Id-Version: Puppet automation framework 4.10.8-31-gb1fa1dd\n"
10
10
  "\n"
11
11
  "Report-Msgid-Bugs-To: https://tickets.puppetlabs.com\n"
12
- "POT-Creation-Date: 2017-07-14 21:19+0000\n"
13
- "PO-Revision-Date: 2017-07-14 21:19+0000\n"
12
+ "POT-Creation-Date: 2017-10-10 16:45+0000\n"
13
+ "PO-Revision-Date: 2017-10-10 16:45+0000\n"
14
14
  "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
15
15
  "Language-Team: LANGUAGE <LL@li.org>\n"
16
16
  "Language: \n"
@@ -126,10 +126,6 @@ msgstr ""
126
126
  msgid "GettextSetup initialization for %{module_name} failed with: %{error_message}"
127
127
  msgstr ""
128
128
 
129
- #: ../lib/puppet/module.rb:80
130
- msgid "GettextSetup is not available, skipping GettextSetup initialization for %{module_name}."
131
- msgstr ""
132
-
133
129
  #: ../lib/puppet/pops/lookup/environment_data_provider.rb:20
134
130
  msgid "hiera.yaml version 3 found at the environment root was ignored"
135
131
  msgstr ""
@@ -0,0 +1,3 @@
1
+ UID PID PPID C STIME TTY TIME CMD
2
+ root 4113 26549 0 11:07 pts/0 00:00:00 latin-1 args m�ni interesting furry animals
3
+ root 4056 26549 0 11:06 pts/0 00:00:00 utf-8 args including the majestik møøse
@@ -43,12 +43,27 @@ describe Puppet::FileBucket::File do
43
43
  end
44
44
 
45
45
  describe "saving binary files" do
46
- let(:binary) { "\xD1\xF2\r\n\x81NuSc\x00".force_encoding(Encoding::ASCII_8BIT) }
46
+ context "given multiple backups of identical files" do
47
+ it "does not error given content with binary external encoding" do
48
+ binary = "\xD1\xF2\r\n\x81NuSc\x00".force_encoding(Encoding::ASCII_8BIT)
49
+ bucket_file = Puppet::FileBucket::File.new(binary)
50
+ Puppet::FileBucket::File.indirection.save(bucket_file, bucket_file.name)
51
+ Puppet::FileBucket::File.indirection.save(bucket_file, bucket_file.name)
52
+ end
47
53
 
48
- it "does not error when the same contents are saved twice" do
49
- bucket_file = Puppet::FileBucket::File.new(binary)
50
- Puppet::FileBucket::File.indirection.save(bucket_file, bucket_file.name)
51
- Puppet::FileBucket::File.indirection.save(bucket_file, bucket_file.name)
54
+ it "also does not error if the content is reported with UTF-8 external encoding" do
55
+ # PUP-7951 - ensure accurate size comparison across encodings If binary
56
+ # content arrives as a string with UTF-8 default external encoding, its
57
+ # character count might be different than the same bytes with binary
58
+ # external encoding. Ensure our equality comparison does not fail due to this.
59
+ # As would be the case with our friend snowman:
60
+ # Unicode snowman \u2603 - \xE2 \x98 \x83
61
+ # character size 1, if interpreted as UTF-8, 3 "characters" if interpreted as binary
62
+ utf8 = "\u2603".force_encoding(Encoding::UTF_8)
63
+ bucket_file = Puppet::FileBucket::File.new(utf8)
64
+ Puppet::FileBucket::File.indirection.save(bucket_file, bucket_file.name)
65
+ Puppet::FileBucket::File.indirection.save(bucket_file, bucket_file.name)
66
+ end
52
67
  end
53
68
  end
54
69
  end
@@ -1,10 +1,12 @@
1
1
  #! /usr/bin/env ruby
2
2
  require 'spec_helper'
3
+ require 'puppet_spec/compiler'
3
4
 
4
5
  require 'puppet/transaction'
5
6
 
6
7
  describe Puppet::Transaction do
7
8
  include PuppetSpec::Files
9
+ include PuppetSpec::Compiler
8
10
 
9
11
  before do
10
12
  Puppet::Util::Storage.stubs(:store)
@@ -17,11 +19,11 @@ describe Puppet::Transaction do
17
19
  end
18
20
 
19
21
  def touch_path
20
- Puppet.features.microsoft_windows? ? "#{ENV['windir']}/system32" : "/usr/bin:/bin"
22
+ Puppet.features.microsoft_windows? ? "#{ENV['windir']}\\system32" : "/usr/bin:/bin"
21
23
  end
22
24
 
23
25
  def usr_bin_touch(path)
24
- Puppet.features.microsoft_windows? ? "#{ENV['windir']}/system32/cmd.exe /c \"type NUL >> \"#{path}\"\"" : "/usr/bin/touch #{path}"
26
+ Puppet.features.microsoft_windows? ? "#{ENV['windir']}\\system32\\cmd.exe /c \"type NUL >> \"#{path}\"\"" : "/usr/bin/touch #{path}"
25
27
  end
26
28
 
27
29
  def touch(path)
@@ -338,6 +340,37 @@ describe Puppet::Transaction do
338
340
  expect(Puppet::FileSystem.exist?(file2)).to be_truthy
339
341
  end
340
342
  end
343
+
344
+ it "should propagate events correctly from a tagged container when running with tags" do
345
+ file1 = tmpfile("original_tag")
346
+ file2 = tmpfile("tag_propagation")
347
+ command1 = usr_bin_touch(file1)
348
+ command2 = usr_bin_touch(file2)
349
+ manifest = <<-"MANIFEST"
350
+ class foo {
351
+ exec { 'notify test':
352
+ command => '#{command1}',
353
+ refreshonly => true,
354
+ }
355
+ }
356
+
357
+ class test {
358
+ include foo
359
+
360
+ exec { 'test':
361
+ command => '#{command2}',
362
+ notify => Class['foo'],
363
+ }
364
+ }
365
+
366
+ include test
367
+ MANIFEST
368
+
369
+ Puppet[:tags] = 'test'
370
+ apply_compiled_manifest(manifest)
371
+ expect(Puppet::FileSystem.exist?(file1)).to be_truthy
372
+ expect(Puppet::FileSystem.exist?(file2)).to be_truthy
373
+ end
341
374
  end
342
375
 
343
376
  describe "skipping resources" do
@@ -62,7 +62,7 @@ describe Puppet::Forge do
62
62
 
63
63
  # ignores Puppet::Forge::Repository#read_response, provides response to fetch
64
64
  performs_an_http_request(ok_response) do |http|
65
- encoded_uri = "/v3/releases?module=#{module_name}&module_groups=base%20pe"
65
+ encoded_uri = "/v3/releases?module=#{module_name}&sort_by=version&module_groups=base%20pe"
66
66
  http.expects(:request).with(responds_with(:path, encoded_uri))
67
67
  end
68
68
 
@@ -74,7 +74,7 @@ describe Puppet::Forge do
74
74
 
75
75
  # ignores Puppet::Forge::Repository#read_response, provides response to fetch
76
76
  performs_an_http_request(ok_response) do |http|
77
- encoded_uri = "/v3/releases?module=puppetlabs-#{mixed_utf8_query_param_encoded}"
77
+ encoded_uri = "/v3/releases?module=puppetlabs-#{mixed_utf8_query_param_encoded}&sort_by=version"
78
78
  http.expects(:request).with(responds_with(:path, encoded_uri))
79
79
  end
80
80
 
@@ -131,6 +131,111 @@ describe Puppet::Forge do
131
131
  end
132
132
  end
133
133
 
134
+ # See PUP-8008
135
+ context "when multiple module_groups are defined" do
136
+ let(:release_response) do
137
+ releases = JSON.parse(http_response)
138
+ releases['results'] = []
139
+ JSON.dump(releases)
140
+ end
141
+
142
+ context "with space seperator" do
143
+ before :each do
144
+ repository_responds_with(stub(:body => release_response, :code => '200')).with {|uri| uri =~ /module_groups=foo bar/}
145
+ Puppet[:module_groups] = "foo bar"
146
+ end
147
+
148
+ it "passes module_groups with search" do
149
+ forge.search('bacula')
150
+ end
151
+
152
+ it "passes module_groups with fetch" do
153
+ forge.fetch('puppetlabs-bacula')
154
+ end
155
+ end
156
+
157
+ context "with plus seperator" do
158
+ before :each do
159
+ repository_responds_with(stub(:body => release_response, :code => '200')).with {|uri| uri =~ /module_groups=foo bar/}
160
+ Puppet[:module_groups] = "foo+bar"
161
+ end
162
+
163
+ it "passes module_groups with search" do
164
+ forge.search('bacula')
165
+ end
166
+
167
+ it "passes module_groups with fetch" do
168
+ forge.fetch('puppetlabs-bacula')
169
+ end
170
+ end
171
+
172
+ # See PUP-8008
173
+ context "when there are multiple pages of results" do
174
+ before(:each) do
175
+ Puppet::Forge::Repository.any_instance.expects(:make_http_request).with {|uri| uri =~ /module_groups=foo bar/ && uri !=~ /offset/ }.returns(stub(:body => first_page, :code => '200'))
176
+
177
+ # Request for second page should not have module_groups already encoded
178
+ Puppet::Forge::Repository.any_instance.expects(:make_http_request).with {|uri| uri =~ /module_groups=foo bar/ && uri =~ /offset=1/ }.returns(stub(:body => last_page, :code => '200'))
179
+ end
180
+
181
+ context "with space seperator" do
182
+ before(:each) do
183
+ Puppet[:module_groups] = "foo bar"
184
+ end
185
+
186
+ let(:first_page) do
187
+ resp = JSON.parse(http_response)
188
+ resp['results'] = []
189
+ resp['pagination']['next'] = "/v3/modules?limit=1&offset=1&module_groups=foo%20bar"
190
+ JSON.dump(resp)
191
+ end
192
+
193
+ let(:last_page) do
194
+ resp = JSON.parse(http_response)
195
+ resp['results'] = []
196
+ resp['pagination']['current'] = "/v3/modules?limit=1&offset=1&module_groups=foo%20bar"
197
+ JSON.dump(resp)
198
+ end
199
+
200
+ it "traverses pages during search" do
201
+ forge.search('bacula')
202
+ end
203
+
204
+ it "traverses pages during fetch" do
205
+ forge.fetch('puppetlabs-bacula')
206
+ end
207
+ end
208
+
209
+ context "with plus seperator" do
210
+ before(:each) do
211
+ Puppet[:module_groups] = "foo+bar"
212
+ end
213
+
214
+ let(:first_page) do
215
+ resp = JSON.parse(http_response)
216
+ resp['results'] = []
217
+ resp['pagination']['next'] = "/v3/modules?limit=1&offset=1&module_groups=foo+bar"
218
+ JSON.dump(resp)
219
+ end
220
+
221
+ let(:last_page) do
222
+ resp = JSON.parse(http_response)
223
+ resp['results'] = []
224
+ resp['pagination']['current'] = "/v3/modules?limit=1&offset=1&module_groups=foo+bar"
225
+ JSON.dump(resp)
226
+ end
227
+
228
+ it "traverses pages during search" do
229
+ forge.search('bacula')
230
+ end
231
+
232
+ it "traverses pages during fetch" do
233
+ forge.fetch('puppetlabs-bacula')
234
+ end
235
+ end
236
+ end
237
+ end
238
+
134
239
  context "when the connection to the forge fails" do
135
240
  before :each do
136
241
  repository_responds_with(stub(:body => '{}', :code => '404', :message => "not found"))