puppet 4.9.4 → 4.10.0

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.

Files changed (124) hide show
  1. checksums.yaml +7 -0
  2. data/Rakefile +6 -0
  3. data/ext/project_data.yaml +2 -2
  4. data/lib/hiera/puppet_function.rb +1 -1
  5. data/lib/puppet.rb +1 -0
  6. data/lib/puppet/application.rb +14 -0
  7. data/lib/puppet/application/inspect.rb +3 -0
  8. data/lib/puppet/defaults.rb +12 -2
  9. data/lib/puppet/etc.rb +125 -0
  10. data/lib/puppet/face/help.rb +1 -1
  11. data/lib/puppet/functions.rb +49 -4
  12. data/lib/puppet/functions/eyaml_lookup_key.rb +12 -3
  13. data/lib/puppet/functions/hocon_data.rb +9 -0
  14. data/lib/puppet/functions/json_data.rb +9 -0
  15. data/lib/puppet/functions/yaml_data.rb +9 -0
  16. data/lib/puppet/indirector/file_bucket_file/file.rb +69 -22
  17. data/lib/puppet/indirector/key/file.rb +2 -1
  18. data/lib/puppet/indirector/ssl_file.rb +24 -3
  19. data/lib/puppet/module.rb +28 -22
  20. data/lib/puppet/network/http/compression.rb +2 -1
  21. data/lib/puppet/parser/compiler.rb +15 -38
  22. data/lib/puppet/parser/functions/hiera.rb +1 -1
  23. data/lib/puppet/parser/functions/hiera_array.rb +1 -1
  24. data/lib/puppet/parser/functions/hiera_hash.rb +1 -1
  25. data/lib/puppet/parser/functions/hiera_include.rb +1 -1
  26. data/lib/puppet/parser/scope.rb +59 -17
  27. data/lib/puppet/pops/evaluator/callable_signature.rb +7 -0
  28. data/lib/puppet/pops/functions/dispatch.rb +18 -5
  29. data/lib/puppet/pops/functions/dispatcher.rb +7 -13
  30. data/lib/puppet/pops/issue_reporter.rb +1 -1
  31. data/lib/puppet/pops/issues.rb +84 -0
  32. data/lib/puppet/pops/loader/base_loader.rb +13 -5
  33. data/lib/puppet/pops/lookup/configured_data_provider.rb +8 -2
  34. data/lib/puppet/pops/lookup/data_dig_function_provider.rb +109 -19
  35. data/lib/puppet/pops/lookup/data_hash_function_provider.rb +19 -4
  36. data/lib/puppet/pops/lookup/data_provider.rb +43 -29
  37. data/lib/puppet/pops/lookup/environment_data_provider.rb +1 -1
  38. data/lib/puppet/pops/lookup/explainer.rb +1 -0
  39. data/lib/puppet/pops/lookup/function_provider.rb +36 -11
  40. data/lib/puppet/pops/lookup/global_data_provider.rb +18 -5
  41. data/lib/puppet/pops/lookup/hiera_config.rb +203 -84
  42. data/lib/puppet/pops/lookup/interpolation.rb +21 -6
  43. data/lib/puppet/pops/lookup/invocation.rb +14 -9
  44. data/lib/puppet/pops/lookup/location_resolver.rb +27 -0
  45. data/lib/puppet/pops/lookup/lookup_adapter.rb +59 -6
  46. data/lib/puppet/pops/lookup/lookup_key_function_provider.rb +9 -77
  47. data/lib/puppet/pops/lookup/module_data_provider.rb +27 -4
  48. data/lib/puppet/pops/parser/lexer2.rb +1 -1
  49. data/lib/puppet/pops/pcore.rb +3 -3
  50. data/lib/puppet/pops/types/p_object_type.rb +4 -6
  51. data/lib/puppet/pops/types/ruby_generator.rb +2 -2
  52. data/lib/puppet/pops/types/type_asserter.rb +3 -3
  53. data/lib/puppet/pops/types/type_mismatch_describer.rb +25 -7
  54. data/lib/puppet/pops/types/types.rb +20 -29
  55. data/lib/puppet/provider/exec.rb +4 -2
  56. data/lib/puppet/provider/nameservice.rb +8 -8
  57. data/lib/puppet/provider/selmodule/semodule.rb +20 -16
  58. data/lib/puppet/provider/service/src.rb +39 -39
  59. data/lib/puppet/provider/service/systemd.rb +1 -1
  60. data/lib/puppet/provider/user/aix.rb +7 -2
  61. data/lib/puppet/settings.rb +30 -17
  62. data/lib/puppet/ssl/base.rb +14 -1
  63. data/lib/puppet/ssl/certificate_authority.rb +4 -2
  64. data/lib/puppet/ssl/configuration.rb +4 -1
  65. data/lib/puppet/ssl/inventory.rb +10 -3
  66. data/lib/puppet/ssl/key.rb +7 -3
  67. data/lib/puppet/test/test_helper.rb +3 -0
  68. data/lib/puppet/type.rb +13 -1
  69. data/lib/puppet/type/exec.rb +16 -1
  70. data/lib/puppet/type/group.rb +17 -11
  71. data/lib/puppet/type/user.rb +3 -1
  72. data/lib/puppet/util.rb +1 -0
  73. data/lib/puppet/util/character_encoding.rb +95 -0
  74. data/lib/puppet/util/execution.rb +9 -6
  75. data/lib/puppet/util/reference.rb +4 -2
  76. data/lib/puppet/util/windows/file.rb +5 -1
  77. data/lib/puppet/version.rb +6 -2
  78. data/locales/config.yaml +1 -1
  79. data/locales/puppet.pot +18 -4
  80. data/spec/integration/ssl/autosign_spec.rb +18 -3
  81. data/spec/integration/ssl/key_spec.rb +104 -0
  82. data/spec/integration/type/user_spec.rb +13 -6
  83. data/spec/spec_helper.rb +7 -0
  84. data/spec/unit/application/inspect_spec.rb +9 -2
  85. data/spec/unit/data_providers/function_data_provider_spec.rb +2 -2
  86. data/spec/unit/etc_spec.rb +234 -0
  87. data/spec/unit/face/certificate_spec.rb +10 -2
  88. data/spec/unit/functions/dig_spec.rb +1 -1
  89. data/spec/unit/functions/hiera_spec.rb +40 -1
  90. data/spec/unit/functions/lookup_fixture_spec.rb +10 -10
  91. data/spec/unit/functions/lookup_spec.rb +1217 -357
  92. data/spec/unit/functions4_spec.rb +37 -1
  93. data/spec/unit/indirector/file_bucket_file/file_spec.rb +33 -2
  94. data/spec/unit/indirector/key/file_spec.rb +1 -1
  95. data/spec/unit/indirector/ssl_file_spec.rb +3 -3
  96. data/spec/unit/module_spec.rb +52 -59
  97. data/spec/unit/network/http/compression_spec.rb +39 -8
  98. data/spec/unit/parser/compiler_spec.rb +14 -0
  99. data/spec/unit/pops/loaders/loaders_spec.rb +21 -3
  100. data/spec/unit/pops/loaders/module_loaders_spec.rb +61 -0
  101. data/spec/unit/pops/lookup/context_spec.rb +56 -8
  102. data/spec/unit/pops/lookup/lookup_spec.rb +32 -1
  103. data/spec/unit/pops/parser/lexer2_spec.rb +8 -0
  104. data/spec/unit/pops/types/ruby_generator_spec.rb +48 -0
  105. data/spec/unit/pops/types/type_mismatch_describer_spec.rb +12 -3
  106. data/spec/unit/pops/types/types_spec.rb +6 -7
  107. data/spec/unit/provider/nameservice_spec.rb +12 -12
  108. data/spec/unit/provider/package/pkg_spec.rb +2 -0
  109. data/spec/unit/provider/service/src_spec.rb +5 -0
  110. data/spec/unit/ssl/base_spec.rb +9 -0
  111. data/spec/unit/ssl/certificate_authority_spec.rb +2 -2
  112. data/spec/unit/ssl/certificate_request_attributes_spec.rb +6 -0
  113. data/spec/unit/ssl/certificate_request_spec.rb +1 -1
  114. data/spec/unit/ssl/certificate_spec.rb +1 -1
  115. data/spec/unit/ssl/configuration_spec.rb +11 -2
  116. data/spec/unit/ssl/inventory_spec.rb +27 -3
  117. data/spec/unit/ssl/key_spec.rb +7 -7
  118. data/spec/unit/type/exec_spec.rb +41 -4
  119. data/spec/unit/type/file_spec.rb +4 -1
  120. data/spec/unit/util/character_encoding_spec.rb +88 -0
  121. data/spec/unit/util/execution_spec.rb +12 -0
  122. data/spec/unit/version_spec.rb +4 -0
  123. metadata +3803 -3808
  124. data/tasks/i18n.rake +0 -20
@@ -35,6 +35,8 @@ describe 'loaders' do
35
35
  let(:dependent_modules_with_metadata) { config_dir('dependent_modules_with_metadata') }
36
36
  let(:no_modules) { config_dir('no_modules') }
37
37
  let(:user_metadata_path) { File.join(dependent_modules_with_metadata, 'modules/user/metadata.json') }
38
+ let(:usee_metadata_path) { File.join(dependent_modules_with_metadata, 'modules/usee/metadata.json') }
39
+ let(:usee2_metadata_path) { File.join(dependent_modules_with_metadata, 'modules/usee2/metadata.json') }
38
40
 
39
41
  let(:empty_test_env) { environment_for() }
40
42
 
@@ -45,11 +47,11 @@ describe 'loaders' do
45
47
  let(:pp_resources) { config_dir('pp_resources') }
46
48
  let(:environments) { Puppet::Environments::Directories.new(my_fixture_dir, []) }
47
49
  let(:env) { Puppet::Node::Environment.create(:'pp_resources', [File.join(pp_resources, 'modules')]) }
48
- let(:scope) { Puppet::Parser::Compiler.new(Puppet::Node.new("test", :environment => env)).newscope(nil) }
50
+ let(:compiler) { Puppet::Parser::Compiler.new(Puppet::Node.new("test", :environment => env)) }
49
51
  let(:loader) { Puppet::Pops::Loaders.loaders.find_loader(nil) }
50
52
  around(:each) do |example|
51
- Puppet.override(:environments => environments, :current_environment => scope.environment, :global_scope => scope) do
52
- Puppet.override(:loaders => Puppet::Pops::Loaders.new(env)) do
53
+ Puppet.override(:environments => environments) do
54
+ Puppet.override(:loaders => compiler.loaders) do
53
55
  example.run
54
56
  end
55
57
  end
@@ -145,6 +147,8 @@ describe 'loaders' do
145
147
 
146
148
  it 'loader allows loading a function more than once' do
147
149
  File.stubs(:read).with(user_metadata_path, {:encoding => 'utf-8'}).returns ''
150
+ File.stubs(:read).with(usee_metadata_path, {:encoding => 'utf-8'}).raises Errno::ENOENT
151
+ File.stubs(:read).with(usee2_metadata_path, {:encoding => 'utf-8'}).raises Errno::ENOENT
148
152
 
149
153
  env = environment_for(File.join(dependent_modules_with_metadata, 'modules'))
150
154
  loaders = Puppet::Pops::Loaders.new(env)
@@ -204,6 +208,8 @@ describe 'loaders' do
204
208
 
205
209
  it 'all dependent modules are visible' do
206
210
  File.stubs(:read).with(user_metadata_path, {:encoding => 'utf-8'}).returns user_metadata.merge('dependencies' => [ { 'name' => 'test-usee'}, { 'name' => 'test-usee2'} ]).to_pson
211
+ File.stubs(:read).with(usee_metadata_path, {:encoding => 'utf-8'}).raises Errno::ENOENT
212
+ File.stubs(:read).with(usee2_metadata_path, {:encoding => 'utf-8'}).raises Errno::ENOENT
207
213
  loaders = Puppet::Pops::Loaders.new(env)
208
214
 
209
215
  moduleb_loader = loaders.private_loader_for_module('user')
@@ -221,6 +227,8 @@ describe 'loaders' do
221
227
  case_number = from_idx * 3 + called_idx + 1
222
228
  it "can call #{desc[:called]} from #{desc[:from]} when dependency is present in metadata.json" do
223
229
  File.stubs(:read).with(user_metadata_path, {:encoding => 'utf-8'}).returns user_metadata.merge('dependencies' => [ { 'name' => 'test-usee'} ]).to_pson
230
+ File.stubs(:read).with(usee_metadata_path, {:encoding => 'utf-8'}).raises Errno::ENOENT
231
+ File.stubs(:read).with(usee2_metadata_path, {:encoding => 'utf-8'}).raises Errno::ENOENT
224
232
  Puppet[:code] = "$case_number = #{case_number}\ninclude ::user"
225
233
  catalog = compiler.compile
226
234
  resource = catalog.resource('Notify', "case_#{case_number}")
@@ -239,6 +247,8 @@ describe 'loaders' do
239
247
 
240
248
  it "can not call #{desc[:called]} from #{desc[:from]} if dependency is missing in existing metadata.json" do
241
249
  File.stubs(:read).with(user_metadata_path, {:encoding => 'utf-8'}).returns user_metadata.merge('dependencies' => []).to_pson
250
+ File.stubs(:read).with(usee_metadata_path, {:encoding => 'utf-8'}).raises Errno::ENOENT
251
+ File.stubs(:read).with(usee2_metadata_path, {:encoding => 'utf-8'}).raises Errno::ENOENT
242
252
  Puppet[:code] = "$case_number = #{case_number}\ninclude ::user"
243
253
  expect { catalog = compiler.compile }.to raise_error(Puppet::Error, /Unknown function/)
244
254
  end
@@ -247,6 +257,8 @@ describe 'loaders' do
247
257
 
248
258
  it "a type can reference an autoloaded type alias from another module when dependency is present in metadata.json" do
249
259
  File.stubs(:read).with(user_metadata_path, {:encoding => 'utf-8'}).returns user_metadata.merge('dependencies' => [ { 'name' => 'test-usee'} ]).to_pson
260
+ File.stubs(:read).with(usee_metadata_path, {:encoding => 'utf-8'}).raises Errno::ENOENT
261
+ File.stubs(:read).with(usee2_metadata_path, {:encoding => 'utf-8'}).raises Errno::ENOENT
250
262
  expect(eval_and_collect_notices(<<-CODE, node)).to eq(['ok'])
251
263
  assert_type(Usee::Zero, 0)
252
264
  notice(ok)
@@ -263,6 +275,8 @@ describe 'loaders' do
263
275
 
264
276
  it "a type can reference a type alias from another module when other module has it declared in init.pp" do
265
277
  File.stubs(:read).with(user_metadata_path, {:encoding => 'utf-8'}).returns user_metadata.merge('dependencies' => [ { 'name' => 'test-usee'} ]).to_pson
278
+ File.stubs(:read).with(usee_metadata_path, {:encoding => 'utf-8'}).raises Errno::ENOENT
279
+ File.stubs(:read).with(usee2_metadata_path, {:encoding => 'utf-8'}).raises Errno::ENOENT
266
280
  expect(eval_and_collect_notices(<<-CODE, node)).to eq(['ok'])
267
281
  include 'usee'
268
282
  assert_type(Usee::One, 1)
@@ -272,6 +286,8 @@ describe 'loaders' do
272
286
 
273
287
  it "an autoloaded type can reference an autoloaded type alias from another module when dependency is present in metadata.json" do
274
288
  File.stubs(:read).with(user_metadata_path, {:encoding => 'utf-8'}).returns user_metadata.merge('dependencies' => [ { 'name' => 'test-usee'} ]).to_pson
289
+ File.stubs(:read).with(usee_metadata_path, {:encoding => 'utf-8'}).raises Errno::ENOENT
290
+ File.stubs(:read).with(usee2_metadata_path, {:encoding => 'utf-8'}).raises Errno::ENOENT
275
291
  expect(eval_and_collect_notices(<<-CODE, node)).to eq(['ok'])
276
292
  assert_type(User::WithUseeZero, [0])
277
293
  notice(ok)
@@ -280,6 +296,8 @@ describe 'loaders' do
280
296
 
281
297
  it "an autoloaded type can reference an autoloaded type alias from another module when other module has it declared in init.pp" do
282
298
  File.stubs(:read).with(user_metadata_path, {:encoding => 'utf-8'}).returns user_metadata.merge('dependencies' => [ { 'name' => 'test-usee'} ]).to_pson
299
+ File.stubs(:read).with(usee_metadata_path, {:encoding => 'utf-8'}).raises Errno::ENOENT
300
+ File.stubs(:read).with(usee2_metadata_path, {:encoding => 'utf-8'}).raises Errno::ENOENT
283
301
  expect(eval_and_collect_notices(<<-CODE, node)).to eq(['ok'])
284
302
  include 'usee'
285
303
  assert_type(User::WithUseeOne, [1])
@@ -2,6 +2,7 @@ require 'spec_helper'
2
2
  require 'puppet_spec/files'
3
3
  require 'puppet/pops'
4
4
  require 'puppet/loaders'
5
+ require 'puppet_spec/compiler'
5
6
 
6
7
  describe 'FileBased module loader' do
7
8
  include PuppetSpec::Files
@@ -92,4 +93,64 @@ describe 'FileBased module loader' do
92
93
  def typed_name(type, name)
93
94
  Puppet::Pops::Loader::TypedName.new(type, name)
94
95
  end
96
+
97
+ context 'module function and class using a module type alias' do
98
+ include PuppetSpec::Compiler
99
+
100
+ let(:modules) do
101
+ {
102
+ 'mod' => {
103
+ 'functions' => {
104
+ 'afunc.pp' => <<-PUPPET.unindent
105
+ function mod::afunc(Mod::Analias $v) {
106
+ notice($v)
107
+ }
108
+ PUPPET
109
+ },
110
+ 'types' => {
111
+ 'analias.pp' => <<-PUPPET.unindent
112
+ type Mod::Analias = Enum[a,b]
113
+ PUPPET
114
+ },
115
+ 'manifests' => {
116
+ 'init.pp' => <<-PUPPET.unindent
117
+ class mod(Mod::Analias $v) {
118
+ notify { $v: }
119
+ }
120
+ PUPPET
121
+ }
122
+ }
123
+ }
124
+ end
125
+
126
+ let(:testing_env) do
127
+ {
128
+ 'testing' => {
129
+ 'modules' => modules
130
+ }
131
+ }
132
+ end
133
+
134
+ let(:environments_dir) { Puppet[:environmentpath] }
135
+
136
+ let(:testing_env_dir) do
137
+ dir_contained_in(environments_dir, testing_env)
138
+ env_dir = File.join(environments_dir, 'testing')
139
+ PuppetSpec::Files.record_tmp(env_dir)
140
+ env_dir
141
+ end
142
+
143
+ let(:env) { Puppet::Node::Environment.create(:testing, [File.join(testing_env_dir, 'modules')]) }
144
+ let(:node) { Puppet::Node.new('test', :environment => env) }
145
+
146
+ # The call to mod:afunc will load the function, and as a consequence, make an attempt to load
147
+ # the parameter type Mod::Analias. That load in turn, will trigger the Runtime3TypeLoader which
148
+ # will load the manifests in Mod. The init.pp manifest also references the Mod::Analias parameter
149
+ # which results in a recursive call to the same loader. This test asserts that this recursive
150
+ # call is handled OK.
151
+ # See PUP-7391 for more info.
152
+ it 'should handle a recursive load' do
153
+ expect(eval_and_collect_notices("mod::afunc('b')", node)).to eql(['b'])
154
+ end
155
+ end
95
156
  end
@@ -172,10 +172,6 @@ describe 'Puppet::Pops::Lookup::Context' do
172
172
  context 'and multiple compilations' do
173
173
 
174
174
  before(:each) { Puppet.settings[:environment_timeout] = 'unlimited' }
175
- after(:each) do
176
- Puppet.settings[:environment_timeout] = 0
177
- Puppet.lookup(:environments).clear_all
178
- end
179
175
 
180
176
  it 'will reuse cached_file_data and not call block again' do
181
177
 
@@ -206,7 +202,7 @@ describe 'Puppet::Pops::Lookup::Context' do
206
202
  expect(logs.uniq.size).to eql(1)
207
203
  end
208
204
 
209
- it 'will invalidate cache if file changes' do
205
+ it 'will invalidate cache if file changes size' do
210
206
  code = <<-PUPPET.unindent
211
207
  $ctx = Puppet::LookupContext.new(nil)
212
208
  $yaml_data = $ctx.cached_file_data('#{data_path}') |$content| {
@@ -220,12 +216,64 @@ describe 'Puppet::Pops::Lookup::Context' do
220
216
  Puppet[:code] = code
221
217
  Puppet::Parser::Compiler.compile(node)
222
218
 
223
- # Change contents!
224
- File.write(data_path, "b: value b\n")
219
+ # Change content size!
220
+ File.write(data_path, "a: value is now A\n")
221
+ Puppet::Parser::Compiler.compile(node)
222
+ end
223
+ logs = logs.select { |log| log.level == :notice }.map { |log| log.message }
224
+ expect(logs).to eql(["{parsed => a: value a\n}", "{parsed => a: value is now A\n}"])
225
+ end
226
+
227
+ it 'will invalidate cache if file changes mtime' do
228
+ old_mtime = Puppet::FileSystem.stat(data_path).mtime
229
+
230
+ code = <<-PUPPET.unindent
231
+ $ctx = Puppet::LookupContext.new(nil)
232
+ $yaml_data = $ctx.cached_file_data('#{data_path}') |$content| {
233
+ { 'parsed' => $content }
234
+ }
235
+ notice($yaml_data)
236
+ PUPPET
237
+
238
+ logs = []
239
+ Puppet::Util::Log.with_destination(Puppet::Test::LogCollector.new(logs)) do
240
+ Puppet[:code] = code
241
+ Puppet::Parser::Compiler.compile(node)
242
+
243
+ # Write content with the same size
244
+ File.write(data_path, "a: value b\n")
245
+
246
+ # Ensure mtime is at least 1 second ahead
247
+ FileUtils.touch(data_path, :mtime => old_mtime + 1)
248
+
249
+ Puppet::Parser::Compiler.compile(node)
250
+ end
251
+ logs = logs.select { |log| log.level == :notice }.map { |log| log.message }
252
+ expect(logs).to eql(["{parsed => a: value a\n}", "{parsed => a: value b\n}"])
253
+ end
254
+
255
+ it 'will invalidate cache if file changes inode' do
256
+ code = <<-PUPPET.unindent
257
+ $ctx = Puppet::LookupContext.new(nil)
258
+ $yaml_data = $ctx.cached_file_data('#{data_path}') |$content| {
259
+ { 'parsed' => $content }
260
+ }
261
+ notice($yaml_data)
262
+ PUPPET
263
+
264
+ logs = []
265
+ Puppet::Util::Log.with_destination(Puppet::Test::LogCollector.new(logs)) do
266
+ Puppet[:code] = code
267
+ Puppet::Parser::Compiler.compile(node)
268
+
269
+ # Change inode!
270
+ File.delete(data_path);
271
+ # Write content with the same size
272
+ File.write(data_path, "a: value b\n")
225
273
  Puppet::Parser::Compiler.compile(node)
226
274
  end
227
275
  logs = logs.select { |log| log.level == :notice }.map { |log| log.message }
228
- expect(logs).to eql(["{parsed => a: value a\n}", "{parsed => b: value b\n}"])
276
+ expect(logs).to eql(["{parsed => a: value a\n}", "{parsed => a: value b\n}"])
229
277
  end
230
278
  end
231
279
  end
@@ -176,12 +176,30 @@ describe 'The lookup API' do
176
176
  {
177
177
  'hiera.yaml' => <<-YAML.unindent,
178
178
  version: 5
179
+ hierarchy:
180
+ - name: Common
181
+ path: common.yaml
182
+ - name: More
183
+ path: more.yaml
179
184
  YAML
180
185
  'data' => {
181
- 'common.yaml' => <<-YAML.unindent
186
+ 'common.yaml' => <<-YAML.unindent,
182
187
  a: a (from other global)
183
188
  d: d (from other global)
189
+ mixed_adapter_hash:
190
+ a:
191
+ ab: value a.ab (from other common global)
192
+ ad: value a.ad (from other common global)
184
193
  mod::e: mod::e (from other global)
194
+ lookup_options:
195
+ mixed_adapter_hash:
196
+ merge: deep
197
+ YAML
198
+ 'more.yaml' => <<-YAML.unindent
199
+ mixed_adapter_hash:
200
+ a:
201
+ aa: value a.aa (from other more global)
202
+ ac: value a.ac (from other more global)
185
203
  YAML
186
204
  }
187
205
  }
@@ -224,6 +242,19 @@ describe 'The lookup API' do
224
242
  expect(Lookup.lookup('mod::c', nil, 'not found', true, nil, other_invocation)).to eql('not found')
225
243
  expect(Lookup.lookup('mod::c', nil, 'not found', true, nil, invocation)).to eql('mod::c (from module)')
226
244
  end
245
+
246
+ it 'resolves lookup options using the custom adapter' do
247
+ expect(Lookup.lookup('mixed_adapter_hash', nil, 'not found', true, nil, other_invocation)).to eql(
248
+ {
249
+ 'a' => {
250
+ 'aa' => 'value a.aa (from other more global)',
251
+ 'ab' => 'value a.ab (from other common global)',
252
+ 'ac' => 'value a.ac (from other more global)',
253
+ 'ad' => 'value a.ad (from other common global)'
254
+ }
255
+ }
256
+ )
257
+ end
227
258
  end
228
259
  end
229
260
  end
@@ -412,6 +412,14 @@ describe 'Lexer2' do
412
412
  expect(tokens_scanned_from("1 / /./")).to match_tokens2(:NUMBER, :DIV, :REGEX)
413
413
  end
414
414
 
415
+ it "should accept newline in a regular expression" do
416
+ scanned = tokens_scanned_from("/\n.\n/")
417
+ # Note that strange formatting here is important
418
+ expect(scanned[0][1][:value]).to eql(/
419
+ .
420
+ /)
421
+ end
422
+
415
423
  context 'when lexer lexes heredoc' do
416
424
  it 'lexes tag, syntax and escapes, margin and right trim' do
417
425
  code = <<-CODE
@@ -411,6 +411,30 @@ describe 'Puppet Ruby Generator' do
411
411
  expect(inst.age).to eql(30)
412
412
  expect(inst.another).to be_nil
413
413
  end
414
+
415
+ it 'two instances with the same attribute values are equal using #eql?' do
416
+ inst1 = second.create('Bob Builder', '42 Cool Street', '12345', 'bob@example.com', 23)
417
+ inst2 = second.create('Bob Builder', '42 Cool Street', '12345', 'bob@example.com', 23)
418
+ expect(inst1.eql?(inst2)).to be_truthy
419
+ end
420
+
421
+ it 'two instances with the same attribute values are equal using #==' do
422
+ inst1 = second.create('Bob Builder', '42 Cool Street', '12345', 'bob@example.com', 23)
423
+ inst2 = second.create('Bob Builder', '42 Cool Street', '12345', 'bob@example.com', 23)
424
+ expect(inst1 == inst2).to be_truthy
425
+ end
426
+
427
+ it 'two instances with the different attribute in super class values are different' do
428
+ inst1 = second.create('Bob Builder', '42 Cool Street', '12345', 'bob@example.com', 23)
429
+ inst2 = second.create('Bob Engineer', '42 Cool Street', '12345', 'bob@example.com', 23)
430
+ expect(inst1 == inst2).to be_falsey
431
+ end
432
+
433
+ it 'two instances with the different attribute in sub class values are different' do
434
+ inst1 = second.create('Bob Builder', '42 Cool Street', '12345', 'bob@example.com', 23)
435
+ inst2 = second.create('Bob Builder', '42 Cool Street', '12345', 'bob@other.com', 23)
436
+ expect(inst1 == inst2).to be_falsey
437
+ end
414
438
  end
415
439
 
416
440
  context 'the #from_hash class method' do
@@ -541,6 +565,30 @@ describe 'Puppet Ruby Generator' do
541
565
  expect(inst.age).to eql(30)
542
566
  expect(inst.another).to be_nil
543
567
  end
568
+
569
+ it 'two instances with the same attribute values are equal using #eql?' do
570
+ inst1 = PuppetSpec::RubyGenerator::My::SecondGenerated.create('Bob Builder', '42 Cool Street', '12345', 'bob@example.com', 23)
571
+ inst2 = PuppetSpec::RubyGenerator::My::SecondGenerated.create('Bob Builder', '42 Cool Street', '12345', 'bob@example.com', 23)
572
+ expect(inst1.eql?(inst2)).to be_truthy
573
+ end
574
+
575
+ it 'two instances with the same attribute values are equal using #==' do
576
+ inst1 = PuppetSpec::RubyGenerator::My::SecondGenerated.create('Bob Builder', '42 Cool Street', '12345', 'bob@example.com', 23)
577
+ inst2 = PuppetSpec::RubyGenerator::My::SecondGenerated.create('Bob Builder', '42 Cool Street', '12345', 'bob@example.com', 23)
578
+ expect(inst1 == inst2).to be_truthy
579
+ end
580
+
581
+ it 'two instances with the different attribute in super class values are different' do
582
+ inst1 = PuppetSpec::RubyGenerator::My::SecondGenerated.create('Bob Builder', '42 Cool Street', '12345', 'bob@example.com', 23)
583
+ inst2 = PuppetSpec::RubyGenerator::My::SecondGenerated.create('Bob Engineer', '42 Cool Street', '12345', 'bob@example.com', 23)
584
+ expect(inst1 == inst2).to be_falsey
585
+ end
586
+
587
+ it 'two instances with the different attribute in sub class values are different' do
588
+ inst1 = PuppetSpec::RubyGenerator::My::SecondGenerated.create('Bob Builder', '42 Cool Street', '12345', 'bob@example.com', 23)
589
+ inst2 = PuppetSpec::RubyGenerator::My::SecondGenerated.create('Bob Builder', '42 Cool Street', '12345', 'bob@other.com', 23)
590
+ expect(inst1 == inst2).to be_falsey
591
+ end
544
592
  end
545
593
 
546
594
  context 'the #from_hash class method' do
@@ -150,6 +150,15 @@ describe 'the type mismatch describer' do
150
150
  /parameter 'arg' expects a match for Enum\['a', 'b'\], got 'c'/))
151
151
  end
152
152
 
153
+ it "will include Undef when describing a mismatch against a Variant where one of the types is Undef" do
154
+ code = <<-CODE
155
+ define check(Variant[Undef,String,Integer,Hash,Array] $arg) {}
156
+ check{ x: arg => 2.4 }
157
+ CODE
158
+ expect { eval_and_collect_notices(code) }.to(raise_error(Puppet::Error,
159
+ /parameter 'arg' expects a value of type Undef, String, Integer, Hash, or Array/))
160
+ end
161
+
153
162
  it "will not disclose a Sensitive that doesn't match an enum in a define call" do
154
163
  code = <<-CODE
155
164
  define check_enums(Enum[a,b] $arg) {}
@@ -196,21 +205,21 @@ describe 'the type mismatch describer' do
196
205
  it 'reports a missing block as "expects a block"' do
197
206
  callable = parser.parse('Callable[String,String,Callable]')
198
207
  args_tuple = parser.parse('Tuple[String,String]')
199
- dispatch = Functions::Dispatch.new(callable, 'foo', ['a','b'], 'block', nil, nil, false)
208
+ dispatch = Functions::Dispatch.new(callable, 'foo', ['a','b'], false, 'block')
200
209
  expect(subject.describe_signatures('function', [dispatch], args_tuple)).to eq("'function' expects a block")
201
210
  end
202
211
 
203
212
  it 'reports an unexpected block as "does not expect a block"' do
204
213
  callable = parser.parse('Callable[String,String]')
205
214
  args_tuple = parser.parse('Tuple[String,String,Callable]')
206
- dispatch = Functions::Dispatch.new(callable, 'foo', ['a','b'], nil, nil, nil, false)
215
+ dispatch = Functions::Dispatch.new(callable, 'foo', ['a','b'])
207
216
  expect(subject.describe_signatures('function', [dispatch], args_tuple)).to eq("'function' does not expect a block")
208
217
  end
209
218
 
210
219
  it 'reports a block return type mismatch' do
211
220
  callable = parser.parse('Callable[[0,0,Callable[ [0,0],String]],Undef]')
212
221
  args_tuple = parser.parse('Tuple[Callable[[0,0],Integer]]')
213
- dispatch = Functions::Dispatch.new(callable, 'foo', [], 'block', nil, nil, false)
222
+ dispatch = Functions::Dispatch.new(callable, 'foo', [], false, 'block')
214
223
  expect(subject.describe_signatures('function', [dispatch], args_tuple)).to eq("'function' block return expects a String value, got Integer")
215
224
  end
216
225
  end
@@ -330,13 +330,12 @@ describe 'Puppet Type System' do
330
330
  end
331
331
 
332
332
  it 'can be normalized in groups, the result is a Variant containing the resulting normalizations' do
333
- expect(groups.normalize).to eq(tf.variant(
334
- tf.range(8, 28),
335
- tf.float_range(10.0, 28.0),
336
- tf.enum('a', 'b', 'c'),
337
- tf.pattern('a', 'b', 'c'),
338
- tf.optional(tf.range(1,20)))
339
- )
333
+ expect(groups.normalize).to eq(tf.optional(
334
+ tf.variant(
335
+ tf.range(1, 28),
336
+ tf.float_range(10.0, 28.0),
337
+ tf.enum('a', 'b', 'c'),
338
+ tf.pattern('a', 'b', 'c'))))
340
339
  end
341
340
  end
342
341
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  require 'spec_helper'
4
4
  require 'puppet/provider/nameservice'
5
- require 'etc'
5
+ require 'puppet/etc'
6
6
 
7
7
  describe Puppet::Provider::NameService do
8
8
 
@@ -123,26 +123,26 @@ describe Puppet::Provider::NameService do
123
123
  describe "#listbyname" do
124
124
  it "should return a list of users if resource_type is user" do
125
125
  described_class.resource_type = Puppet::Type.type(:user)
126
- Etc.expects(:setpwent)
127
- Etc.stubs(:getpwent).returns *users
128
- Etc.expects(:endpwent)
126
+ Puppet::Etc.expects(:setpwent)
127
+ Puppet::Etc.stubs(:getpwent).returns *users
128
+ Puppet::Etc.expects(:endpwent)
129
129
  expect(described_class.listbyname).to eq(%w{root foo})
130
130
  end
131
131
 
132
132
  it "should return a list of groups if resource_type is group", :unless => Puppet.features.microsoft_windows? do
133
133
  described_class.resource_type = Puppet::Type.type(:group)
134
- Etc.expects(:setgrent)
135
- Etc.stubs(:getgrent).returns *groups
136
- Etc.expects(:endgrent)
134
+ Puppet::Etc.expects(:setgrent)
135
+ Puppet::Etc.stubs(:getgrent).returns *groups
136
+ Puppet::Etc.expects(:endgrent)
137
137
  expect(described_class.listbyname).to eq(%w{root bin})
138
138
  end
139
139
 
140
140
  it "should yield if a block given" do
141
141
  yield_results = []
142
142
  described_class.resource_type = Puppet::Type.type(:user)
143
- Etc.expects(:setpwent)
144
- Etc.stubs(:getpwent).returns *users
145
- Etc.expects(:endpwent)
143
+ Puppet::Etc.expects(:setpwent)
144
+ Puppet::Etc.stubs(:getpwent).returns *users
145
+ Puppet::Etc.expects(:endpwent)
146
146
  described_class.listbyname {|x| yield_results << x }
147
147
  expect(yield_results).to eq(%w{root foo})
148
148
  end
@@ -188,13 +188,13 @@ describe Puppet::Provider::NameService do
188
188
  end
189
189
 
190
190
  it "should return a hash if we can retrieve something" do
191
- Etc.expects(:send).with(:getfoonam, 'bob').returns fakeetcobject
191
+ Puppet::Etc.expects(:send).with(:getfoonam, 'bob').returns fakeetcobject
192
192
  provider.expects(:info2hash).with(fakeetcobject).returns(:foo => 'fooval', :bar => 'barval')
193
193
  expect(provider.getinfo(true)).to eq({:foo => 'fooval', :bar => 'barval'})
194
194
  end
195
195
 
196
196
  it "should return nil if we cannot retrieve anything" do
197
- Etc.expects(:send).with(:getfoonam, 'bob').raises(ArgumentError, "can't find bob")
197
+ Puppet::Etc.expects(:send).with(:getfoonam, 'bob').raises(ArgumentError, "can't find bob")
198
198
  provider.expects(:info2hash).never
199
199
  expect(provider.getinfo(true)).to be_nil
200
200
  end