puppet 4.10.1 → 4.10.4

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 (120) hide show
  1. data/ext/project_data.yaml +1 -1
  2. data/lib/puppet.rb +40 -28
  3. data/lib/puppet/application/agent.rb +1 -1
  4. data/lib/puppet/application/apply.rb +1 -1
  5. data/lib/puppet/application/cert.rb +1 -1
  6. data/lib/puppet/application/describe.rb +1 -1
  7. data/lib/puppet/application/device.rb +1 -1
  8. data/lib/puppet/application/doc.rb +3 -3
  9. data/lib/puppet/application/filebucket.rb +1 -1
  10. data/lib/puppet/application/inspect.rb +2 -2
  11. data/lib/puppet/application/lookup.rb +1 -1
  12. data/lib/puppet/application/master.rb +1 -1
  13. data/lib/puppet/application/resource.rb +7 -7
  14. data/lib/puppet/defaults.rb +1 -1
  15. data/lib/puppet/etc.rb +75 -39
  16. data/lib/puppet/face/ca.rb +1 -1
  17. data/lib/puppet/face/catalog.rb +1 -1
  18. data/lib/puppet/face/certificate.rb +1 -1
  19. data/lib/puppet/face/certificate_request.rb +1 -1
  20. data/lib/puppet/face/certificate_revocation_list.rb +1 -1
  21. data/lib/puppet/face/config.rb +1 -1
  22. data/lib/puppet/face/epp.rb +1 -1
  23. data/lib/puppet/face/facts.rb +1 -1
  24. data/lib/puppet/face/file.rb +1 -1
  25. data/lib/puppet/face/help.rb +1 -1
  26. data/lib/puppet/face/key.rb +1 -1
  27. data/lib/puppet/face/man.rb +2 -2
  28. data/lib/puppet/face/module.rb +1 -1
  29. data/lib/puppet/face/node.rb +1 -1
  30. data/lib/puppet/face/parser.rb +1 -1
  31. data/lib/puppet/face/plugin.rb +1 -1
  32. data/lib/puppet/face/report.rb +1 -1
  33. data/lib/puppet/face/resource.rb +1 -1
  34. data/lib/puppet/face/resource_type.rb +1 -1
  35. data/lib/puppet/face/status.rb +1 -1
  36. data/lib/puppet/feature/base.rb +1 -1
  37. data/lib/puppet/functions/eyaml_lookup_key.rb +16 -12
  38. data/lib/puppet/functions/hiera.rb +9 -2
  39. data/lib/puppet/functions/hiera_array.rb +9 -2
  40. data/lib/puppet/functions/hiera_hash.rb +10 -2
  41. data/lib/puppet/functions/hiera_include.rb +17 -3
  42. data/lib/puppet/functions/hocon_data.rb +6 -0
  43. data/lib/puppet/functions/json_data.rb +4 -0
  44. data/lib/puppet/functions/yaml_data.rb +4 -0
  45. data/lib/puppet/generate/models/type/type.rb +6 -5
  46. data/lib/puppet/generate/templates/type/pcore.erb +1 -1
  47. data/lib/puppet/module_tool/skeleton/templates/generator/examples/init.pp.erb +1 -1
  48. data/lib/puppet/parser/functions/create_resources.rb +8 -0
  49. data/lib/puppet/parser/scope.rb +2 -2
  50. data/lib/puppet/pops/adapters.rb +10 -4
  51. data/lib/puppet/pops/evaluator/runtime3_resource_support.rb +0 -2
  52. data/lib/puppet/pops/evaluator/runtime3_support.rb +31 -0
  53. data/lib/puppet/pops/issues.rb +8 -0
  54. data/lib/puppet/pops/loader/loader.rb +4 -0
  55. data/lib/puppet/pops/loader/module_loaders.rb +0 -2
  56. data/lib/puppet/pops/loader/static_loader.rb +1 -1
  57. data/lib/puppet/pops/loader/type_definition_instantiator.rb +1 -1
  58. data/lib/puppet/pops/loader/typed_name.rb +1 -0
  59. data/lib/puppet/pops/loaders.rb +7 -15
  60. data/lib/puppet/pops/lookup/environment_data_provider.rb +1 -1
  61. data/lib/puppet/pops/lookup/hiera_config.rb +3 -1
  62. data/lib/puppet/pops/lookup/interpolation.rb +2 -1
  63. data/lib/puppet/pops/lookup/lookup_key.rb +1 -1
  64. data/lib/puppet/pops/lookup/module_data_provider.rb +10 -2
  65. data/lib/puppet/pops/lookup/sub_lookup.rb +10 -9
  66. data/lib/puppet/pops/parser/lexer2.rb +20 -3
  67. data/lib/puppet/pops/pcore.rb +2 -2
  68. data/lib/puppet/pops/resource/resource_type_impl.rb +2 -2
  69. data/lib/puppet/pops/semantic_error.rb +12 -0
  70. data/lib/puppet/pops/serialization/deserializer.rb +7 -4
  71. data/lib/puppet/pops/types/p_type_set_type.rb +2 -2
  72. data/lib/puppet/pops/types/string_converter.rb +5 -17
  73. data/lib/puppet/pops/types/type_set_reference.rb +1 -1
  74. data/lib/puppet/pops/validation/checker4_0.rb +4 -0
  75. data/lib/puppet/pops/validation/validator_factory_4_0.rb +1 -0
  76. data/lib/puppet/provider/nameservice.rb +12 -4
  77. data/lib/puppet/provider/package/yum.rb +8 -8
  78. data/lib/puppet/provider/user/useradd.rb +1 -1
  79. data/lib/puppet/reference/configuration.rb +1 -1
  80. data/lib/puppet/resource.rb +9 -11
  81. data/lib/puppet/resource/type_collection.rb +1 -0
  82. data/lib/puppet/type/exec.rb +32 -26
  83. data/lib/puppet/type/file/mode.rb +4 -0
  84. data/lib/puppet/util/character_encoding.rb +77 -74
  85. data/lib/puppet/util/monkey_patches.rb +3 -1
  86. data/lib/puppet/util/windows/api_types.rb +3 -0
  87. data/lib/puppet/util/windows/file.rb +1 -1
  88. data/lib/puppet/version.rb +1 -1
  89. data/locales/puppet.pot +31 -7
  90. data/spec/integration/faces/documentation_spec.rb +2 -2
  91. data/spec/integration/parser/pcore_resource_spec.rb +15 -0
  92. data/spec/integration/resource/type_collection_spec.rb +6 -0
  93. data/spec/lib/puppet/face/1.0.0/huzzah.rb +1 -1
  94. data/spec/lib/puppet/face/basetest.rb +1 -1
  95. data/spec/lib/puppet/face/huzzah.rb +1 -1
  96. data/spec/lib/puppet/face/version_matching.rb +1 -1
  97. data/spec/lib/puppet_spec/character_encoding.rb +12 -0
  98. data/spec/lib/puppet_spec/compiler.rb +7 -0
  99. data/spec/shared_examples/rhel_package_provider.rb +10 -11
  100. data/spec/unit/application/resource_spec.rb +22 -1
  101. data/spec/unit/configurer/fact_handler_spec.rb +2 -1
  102. data/spec/unit/etc_spec.rb +361 -153
  103. data/spec/unit/functions/lookup_spec.rb +118 -2
  104. data/spec/unit/parser/functions/create_resources_spec.rb +47 -6
  105. data/spec/unit/parser/scope_spec.rb +8 -0
  106. data/spec/unit/pops/evaluator/evaluating_parser_spec.rb +40 -0
  107. data/spec/unit/pops/loaders/loaders_spec.rb +141 -79
  108. data/spec/unit/pops/lookup/interpolation_spec.rb +49 -9
  109. data/spec/unit/pops/lookup/lookup_spec.rb +32 -0
  110. data/spec/unit/pops/parser/lexer2_spec.rb +28 -0
  111. data/spec/unit/pops/types/p_object_type_spec.rb +1 -1
  112. data/spec/unit/pops/types/p_type_set_type_spec.rb +1 -1
  113. data/spec/unit/pops/types/string_converter_spec.rb +21 -0
  114. data/spec/unit/pops/validator/validator_spec.rb +43 -0
  115. data/spec/unit/provider/nameservice/directoryservice_spec.rb +2 -0
  116. data/spec/unit/provider/nameservice_spec.rb +113 -3
  117. data/spec/unit/provider/user/useradd_spec.rb +13 -0
  118. data/spec/unit/resource/catalog_spec.rb +21 -0
  119. data/spec/unit/util/character_encoding_spec.rb +193 -52
  120. metadata +4 -2
@@ -2080,8 +2080,9 @@ describe "The lookup function" do
2080
2080
  }
2081
2081
  end
2082
2082
 
2083
- it 'raises an error' do
2084
- expect { lookup('mod_a::a') }.to raise_error(Puppet::Error, /hiera.yaml version 3 cannot be used in a module/)
2083
+ it 'raises a warning' do
2084
+ expect(lookup('mod_a::a')).to eql('value mod_a::a (from environment)')
2085
+ expect(warnings).to include(/hiera.yaml version 3 found at module root was ignored/)
2085
2086
  end
2086
2087
  end
2087
2088
 
@@ -2946,6 +2947,121 @@ describe "The lookup function" do
2946
2947
 
2947
2948
  let(:env_data) { data_files }
2948
2949
 
2950
+ context 'and a module using eyaml with different options' do
2951
+
2952
+ let(:private_module_key) do
2953
+ <<-PKCS7.unindent
2954
+ -----BEGIN RSA PRIVATE KEY-----
2955
+ MIIEogIBAAKCAQEAuqVpctipK4OMWM+RwKcd/mR4pg6qE3+ItPVC9TlvBrmDaN/y
2956
+ YZRjQR+XovXSGuy/CneSQ9Qss0Ff3FKAmEeH0qN0V47a81hgLpjhLCX1n+Ov7r1Q
2957
+ DC1ciTpVzHE4krN3rJ/RmDohitIqT1IYYhdcEdaMG9E26HIzn1QIwaDiYU3mfqWM
2958
+ 8CZExa0CeIsEzHRLSxuMi/xX0ENImCRUzY9GH88Cu2gUhpKlbVzJmVqGPgp94pJY
2959
+ YM+SUb0XP1yRySpJMnVg98oCUrQO2OoE/Gax/djAi6hrJUzejPsEKdZ1yxM6OyJW
2960
+ NjWZYs8izAxBqm7pv1hx5+X7AIPqwZTMVrB7TQIDAQABAoIBAHIex13QOYeAlGSM
2961
+ 7bpUtBMiTV6DItxvIyA5wen8ZvU+oqmSHDorp5BfB7E9Cm0qChkVSRot9fLYawtk
2962
+ anoxakuRY4ZRs3AMvipfkXYT854CckTP/cykQ6soPuOU6plQIEEtKtMf3/hoTjRX
2963
+ ps77J3FEtEAh6Kexg/zMPdpeS2xgULhk0P9ZQEg+JhLA5dq0p0nz3SBkuzcxei79
2964
+ +Za/Tg1osD0AINOajdvPnKxvlmWJN0+LpGwVjFNhkoUXPeDyvq0z2V/Uqwz4HP2I
2965
+ UGv4tz3SbzFc3Ie4lzgUZzCQgUK3u60pq1uyA6BRtxwdEmpn5v++jGXBGJZpWwcW
2966
+ UNblESUCgYEA4aTH9+LHsNjLPs2FmSc7hNjwHG1rAHcDXTX2ccySjRcQvH4Z7xBL
2967
+ di+SzZ2Tf8gSLycPRgRVCbrgCODpjoV2D5wWnyUHfWm4+GQxHURYa4UDx69tsSKE
2968
+ OTRASJo7/Mz0M1a6YzgCzVRM/TO676ucmawzKUY5OUm1oehtODAiZOcCgYEA08GM
2969
+ AMBOznys02xREJI5nLR6AveuTbIjF2efEidoxoW+1RrMOkcqaDTrJQ5PLM+oDDwD
2970
+ iPzVjnroSbwJzFB71atIg7b7TwltgkXy7wNTedO2cm5u/I0q8tY2Jaa4Mz8JUnbe
2971
+ yafvtS0/mY6A5k+8/2UIMFin2rqU9NC9EUPIo6sCgYBhOvAwELibq89osIbxB8bN
2972
+ 5+0PUtbYzG/WqnoXb193DIlZr7zdFththPJtR4lXdo7fYqViNluuZahEKyZ5E2lc
2973
+ MJZO3VXs5LGf1wyS3/B55EdMtHs/6O+w9qL8pflTZb2UobqPJoOOltTWBoR24iwI
2974
+ y/r/vhLKbMini9AEdjlb4QKBgGdYsax4Lr4GCQ8ScSnmQ6ngRyAFo5MV2pyEnRTu
2975
+ GOuywKUe9AeJTgAXu5+VMT0Mh9aYv5zu0Ic+IvpBhIKr0RRCCR0Hg/VaA5Et9FeE
2976
+ RwxRMFz+2rn1Z72moDyV9pZEMJeHnknK5WmGEOEvtGczCWmX9Hwr+Jf+sc4dxfiU
2977
+ HWsLAoGAXWSX73p/6R4eRfF5zU2UFJPvDzhmwObAuvU4zKs9x7PMxZfvyt/eBCO1
2978
+ fj2+hIR72RxVuHbLApF1BT6gPVLtNdvaNuCs8YlHcnx/Oi088F0ni7fL/xYBUvaB
2979
+ 7wTf188UJxP1ofVMZW00P4I9mR6BrOulv455gCwsmg2X7WtJU48=
2980
+ -----END RSA PRIVATE KEY-----
2981
+ PKCS7
2982
+ end
2983
+
2984
+ let(:public_module_key) do
2985
+ <<-PKCS7.unindent
2986
+ -----BEGIN CERTIFICATE-----
2987
+ MIIC2TCCAcGgAwIBAgIBATANBgkqhkiG9w0BAQUFADAAMCAXDTE3MDUzMTE2Mjc0
2988
+ M1oYDzIwNjcwNTE5MTYyNzQzWjAAMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
2989
+ CgKCAQEAuqVpctipK4OMWM+RwKcd/mR4pg6qE3+ItPVC9TlvBrmDaN/yYZRjQR+X
2990
+ ovXSGuy/CneSQ9Qss0Ff3FKAmEeH0qN0V47a81hgLpjhLCX1n+Ov7r1QDC1ciTpV
2991
+ zHE4krN3rJ/RmDohitIqT1IYYhdcEdaMG9E26HIzn1QIwaDiYU3mfqWM8CZExa0C
2992
+ eIsEzHRLSxuMi/xX0ENImCRUzY9GH88Cu2gUhpKlbVzJmVqGPgp94pJYYM+SUb0X
2993
+ P1yRySpJMnVg98oCUrQO2OoE/Gax/djAi6hrJUzejPsEKdZ1yxM6OyJWNjWZYs8i
2994
+ zAxBqm7pv1hx5+X7AIPqwZTMVrB7TQIDAQABo1wwWjAPBgNVHRMBAf8EBTADAQH/
2995
+ MB0GA1UdDgQWBBQkhoMgOyPzEe7tOOimNH2//PYF2TAoBgNVHSMEITAfgBQkhoMg
2996
+ OyPzEe7tOOimNH2//PYF2aEEpAIwAIIBATANBgkqhkiG9w0BAQUFAAOCAQEAhRWc
2997
+ Nz3PcUJllao5G/v4AyvjLgwB2JgjJgh6D3ILoOe9TrDSXD7ZV3F30vFae+Eztk86
2998
+ pmM8x57E0HsuuY+Owf6/hvELtwbzf9N/lc9ySZSogGFoQeJ8rnCJAQ0FaPjqb7AN
2999
+ xTaY9HTzr4dZG1f+sw32RUu2fDe7Deqgf85uMSZ1mtRTt9zvo8lMQxVA2nVOfwz2
3000
+ Nxf+qSNYSCtf0/6iwfzHy0qPjaJnywgBCi3Lg2IMSqGUatxzH+9HWrBgD+ZYxmDz
3001
+ 2gW+EIU1Y/We/tbjIWaR1PD+IzeRJi5fHq60RKHPSdp7TGtV48bQRvyZXC7sVCRa
3002
+ yxfX1IGYhCDzbFRQNg==
3003
+ -----END CERTIFICATE-----
3004
+ PKCS7
3005
+ end
3006
+
3007
+ let(:module_keys_dir) do
3008
+ keys = tmpdir('keys')
3009
+ dir_contained_in(keys, {
3010
+ private_key_name => private_module_key,
3011
+ public_key_name => public_module_key
3012
+ })
3013
+ keys
3014
+ end
3015
+
3016
+ let(:private_module_key_path) { File.join(module_keys_dir, private_key_name) }
3017
+ let(:public_module_key_path) { File.join(module_keys_dir, public_key_name) }
3018
+
3019
+ let(:mod_a_files) do
3020
+ {
3021
+ 'mod_a' => {
3022
+ 'hiera.yaml' => <<-YAML.unindent,
3023
+ version: 5
3024
+ hierarchy:
3025
+ - name: EYaml
3026
+ path: common.eyaml
3027
+ lookup_key: eyaml_lookup_key
3028
+ options:
3029
+ pkcs7_private_key: #{private_module_key_path}
3030
+ pkcs7_public_key: #{public_module_key_path}
3031
+ YAML
3032
+ 'data' => {
3033
+ 'common.eyaml' => <<-YAML.unindent
3034
+ ---
3035
+ # "%{lookup('a')} (from module)"
3036
+ mod_a::a: >
3037
+ ENC[PKCS7,MIIBiQYJKoZIhvcNAQcDoIIBejCCAXYCAQAxggEhMIIBHQIBADAFMAACAQEw
3038
+ DQYJKoZIhvcNAQEBBQAEggEAC+lvda8mX6XkgCBstNw4IQUDyFcS6M0mS9gZ
3039
+ ev4VBDeUK4AUNVnzzdbW0Mnj9LbqlpzFx96VGqSxsRBpe7BVD0kVo5jQsEMn
3040
+ nbrWOD1lvXYrXZMXBeD9xJbMbH5EiiFhbaXcEKRAVGaLVQKjXDENDQ/On+it
3041
+ 1+wmmVwJynDJR0lsCz6dcSKvw6wnxBcv32qFyePvJuIf04CHMhaS4ykedYHK
3042
+ vagUn5uVXOv/8G0JPlZnQLyxjE0v0heb0Zj0mvcP2+Y5BSW50AQVrMWJNtdW
3043
+ aFEg6H5hpjduQfQh3iWVuDLnWhbP0sY2Grn5dTOxQP8aTDSsiTUcSeIAmjr/
3044
+ K8YRCjBMBgkqhkiG9w0BBwEwHQYJYIZIAWUDBAEqBBAjL7InlBjRuohLLcBx
3045
+ 686ogCDkhCan8bCE7aX2nr75QtLF3q89pFIR4/NGl5+oGEO+qQ==]
3046
+ YAML
3047
+ }
3048
+ }
3049
+ }
3050
+ end
3051
+
3052
+ let(:populated_env_dir) do
3053
+ dir_contained_in(env_dir, DeepMerge.deep_merge!(environment_files, env_name => { 'modules' => mod_a_files }))
3054
+ env_dir
3055
+ end
3056
+
3057
+ it 'repeatedly finds data in environment and module' do
3058
+ expect(lookup(['array_a', 'mod_a::a', 'hash_a'])).to eql([
3059
+ ['array_a[0]', 'array_a[1]'],
3060
+ "Encrypted value 'a' (from environment) (from module)",
3061
+ {'hash_aa'=>{'aaa'=>'Encrypted value hash_a.hash_aa.aaa (from environment)'}}])
3062
+ end
3063
+ end
3064
+
2949
3065
  it 'finds data in the environment' do
2950
3066
  expect(lookup('a')).to eql("Encrypted value 'a' (from environment)")
2951
3067
  end
@@ -89,6 +89,15 @@ describe 'function for dynamically creating resources' do
89
89
  expect(catalog.resource(:file, "/etc/foo")['ensure']).to eq('present')
90
90
  end
91
91
 
92
+ it 'unrealized exported resources should not be added' do
93
+ # a compiled catalog is normally filtered on virtual resources
94
+ # here the compilation is performed unfiltered to be able to find the exported resource
95
+ # it is then asserted that the exported resource is also virtual (and therefore filtered out by a real compilation).
96
+ catalog = compile_to_catalog_unfiltered("create_resources('@@file', {'/etc/foo'=>{'ensure'=>'present'}})")
97
+ expect(catalog.resource(:file, "/etc/foo").exported).to eq(true)
98
+ expect(catalog.resource(:file, "/etc/foo").virtual).to eq(true)
99
+ end
100
+
92
101
  it 'should be able to add exported resources' do
93
102
  catalog = compile_to_catalog("create_resources('@@file', {'/etc/foo'=>{'ensure'=>'present'}}) realize(File['/etc/foo'])")
94
103
  expect(catalog.resource(:file, "/etc/foo")['ensure']).to eq('present')
@@ -232,6 +241,9 @@ describe 'function for dynamically creating resources' do
232
241
  end
233
242
 
234
243
  describe 'when creating classes' do
244
+ let(:logs) { [] }
245
+ let(:warnings) { logs.select { |log| log.level == :warning }.map { |log| log.message } }
246
+
235
247
  it 'should be able to create classes' do
236
248
  catalog = compile_to_catalog(<<-MANIFEST)
237
249
  class bar($one) {
@@ -245,12 +257,34 @@ describe 'function for dynamically creating resources' do
245
257
  expect(catalog.resource(:class, "bar")).not_to be_nil
246
258
  end
247
259
 
248
- it 'should fail to create non-existing classes' do
249
- expect do
250
- compile_to_catalog(<<-MANIFEST)
251
- create_resources('class', {'blah'=>{'one'=>'two'}})
252
- MANIFEST
253
- end.to raise_error(/Could not find declared class blah at line 1:11 on node test/)
260
+ [:off, :warning].each do | strictness |
261
+ it "should warn if strict = #{strictness} and class is exported" do
262
+ Puppet[:strict] = strictness
263
+ collect_notices('class test{} create_resources("@@class", {test => {}})')
264
+ expect(warnings).to include(/Classes are not virtualizable/)
265
+ end
266
+ end
267
+
268
+ it 'should error if strict = error and class is exported' do
269
+ Puppet[:strict] = :error
270
+ expect{
271
+ compile_to_catalog('class test{} create_resources("@@class", {test => {}})')
272
+ }.to raise_error(/Classes are not virtualizable/)
273
+ end
274
+
275
+ [:off, :warning].each do | strictness |
276
+ it "should warn if strict = #{strictness} and class is virtual" do
277
+ Puppet[:strict] = strictness
278
+ collect_notices('class test{} create_resources("@class", {test => {}})')
279
+ expect(warnings).to include(/Classes are not virtualizable/)
280
+ end
281
+ end
282
+
283
+ it 'should error if strict = error and class is virtual' do
284
+ Puppet[:strict] = :error
285
+ expect{
286
+ compile_to_catalog('class test{} create_resources("@class", {test => {}})')
287
+ }.to raise_error(/Classes are not virtualizable/)
254
288
  end
255
289
 
256
290
  it 'should be able to add edges' do
@@ -291,4 +325,11 @@ describe 'function for dynamically creating resources' do
291
325
  }.to raise_error(Puppet::Error, /Syntax error at.*/)
292
326
  end
293
327
  end
328
+
329
+ def collect_notices(code)
330
+ Puppet::Util::Log.with_destination(Puppet::Test::LogCollector.new(logs)) do
331
+ compile_to_catalog(code)
332
+ end
333
+ end
334
+
294
335
  end
@@ -578,6 +578,14 @@ describe Puppet::Parser::Scope do
578
578
  @scope.unset_ephemeral_var
579
579
  expect(@scope["apple"]).to eq(nil)
580
580
  end
581
+
582
+ it 'should store an undef in local scope and let it override parent scope' do
583
+ @scope['cloaked'] = 'Cloak me please'
584
+ @scope.new_ephemeral(true)
585
+ @scope['cloaked'] = nil
586
+ expect(@scope['cloaked']).to eq(nil)
587
+ end
588
+
581
589
  it "should be created from a hash" do
582
590
  @scope.ephemeral_from({ "apple" => :fruit, "strawberry" => :berry})
583
591
  expect(@scope["apple"]).to eq(:fruit)
@@ -403,6 +403,11 @@ describe 'Puppet::Pops::Evaluator::EvaluatorImpl' do
403
403
  end
404
404
 
405
405
  context "on strings requiring boxing to Numeric" do
406
+ let(:logs) { [] }
407
+ let(:notices) { logs.select { |log| log.level == :notice }.map { |log| log.message } }
408
+ let(:warnings) { logs.select { |log| log.level == :warning }.map { |log| log.message } }
409
+ let(:debugs) { logs.select { |log| log.level == :debug }.map { |log| log.message } }
410
+
406
411
  {
407
412
  "'2' + '2'" => 4,
408
413
  "'-2' + '2'" => 0,
@@ -426,6 +431,35 @@ describe 'Puppet::Pops::Evaluator::EvaluatorImpl' do
426
431
  end
427
432
  end
428
433
 
434
+ {
435
+ "'2' + 2" => 2,
436
+ "'4' - 2" => 4,
437
+ "'2' * 2" => 2,
438
+ "'2' / 1" => 2,
439
+ "'8' >> 1" => 8,
440
+ "'4' << 1" => 4,
441
+ "'10' % 3" => 10,
442
+ }.each do |source, coerced_val|
443
+ it "should warn about numeric coercion in '#{source}' when strict = warning" do
444
+ Puppet[:strict] = :warning
445
+ collect_notices(source)
446
+ expect(warnings).to include(/The string '#{coerced_val}' was automatically coerced to the numerical value #{coerced_val}/)
447
+ end
448
+
449
+ it "should not warn about numeric coercion in '#{source}' if strict = off" do
450
+ Puppet[:strict] = :off
451
+ collect_notices(source)
452
+ expect(warnings).to_not include(/The string '#{coerced_val}' was automatically coerced to the numerical value #{coerced_val}/)
453
+ end
454
+
455
+ it "should error when finding numeric coercion in '#{source}' if strict = error" do
456
+ Puppet[:strict] = :error
457
+ expect { parser.evaluate_string(scope, source, __FILE__) }.to raise_error(
458
+ /The string '#{coerced_val}' was automatically coerced to the numerical value #{coerced_val}/
459
+ )
460
+ end
461
+ end
462
+
429
463
  {
430
464
  "'0888' + '010'" => :error,
431
465
  "'0xWTF' + '010'" => :error,
@@ -1466,4 +1500,10 @@ describe 'Puppet::Pops::Evaluator::EvaluatorImpl' do
1466
1500
  end
1467
1501
  end
1468
1502
 
1503
+ def collect_notices(code)
1504
+ Puppet::Util::Log.with_destination(Puppet::Test::LogCollector.new(logs)) do
1505
+ parser.evaluate_string(scope, code, __FILE__)
1506
+ end
1507
+ end
1508
+
1469
1509
  end
@@ -22,6 +22,16 @@ describe 'loader helper classes' do
22
22
  expect(tn.name).to eq('foo::bar')
23
23
  expect(tn.qualified?).to be_truthy
24
24
  end
25
+
26
+ it 'TypedName converts name to lower case' do
27
+ tn = Puppet::Pops::Loader::TypedName.new(:type, '::Foo::Bar')
28
+ expect(tn.name_parts).to eq(['foo', 'bar'])
29
+ expect(tn.name).to eq('foo::bar')
30
+ end
31
+
32
+ it 'TypedName is case insensitive' do
33
+ expect(Puppet::Pops::Loader::TypedName.new(:type, '::Foo::Bar')).to eq(Puppet::Pops::Loader::TypedName.new(:type, '::foo::bar'))
34
+ end
25
35
  end
26
36
 
27
37
  describe 'loaders' do
@@ -88,7 +98,7 @@ describe 'loaders' do
88
98
  loaders = Puppet::Pops::Loaders.new(empty_test_env)
89
99
 
90
100
  expect(loaders.public_environment_loader()).to be_a(Puppet::Pops::Loader::SimpleEnvironmentLoader)
91
- expect(loaders.public_environment_loader().to_s).to eql("(SimpleEnvironmentLoader 'environment:*test*')")
101
+ expect(loaders.public_environment_loader().to_s).to eql("(SimpleEnvironmentLoader 'environment')")
92
102
  expect(loaders.private_environment_loader()).to be_a(Puppet::Pops::Loader::DependencyLoader)
93
103
  expect(loaders.private_environment_loader().to_s).to eql("(DependencyLoader 'environment private' [])")
94
104
  end
@@ -389,53 +399,13 @@ describe 'loaders' do
389
399
  end
390
400
  end
391
401
 
392
- context 'loading types' do
402
+ context 'loading' do
393
403
  let(:env_name) { 'testenv' }
394
404
  let(:environments_dir) { Puppet[:environmentpath] }
395
405
  let(:env_dir) { File.join(environments_dir, env_name) }
396
406
  let(:env) { Puppet::Node::Environment.create(env_name.to_sym, [File.join(populated_env_dir, 'modules')]) }
397
- let(:metadata_json) {
398
- <<-JSON
399
- {
400
- "name": "example/%1$s",
401
- "version": "0.0.2",
402
- "source": "git@github.com/example/example-%1$s.git",
403
- "dependencies": [],
404
- "author": "Bob the Builder",
405
- "license": "Apache-2.0"%2$s
406
- }
407
- JSON
408
- }
409
-
410
- let(:env_dir_files) do
411
- {
412
- 'modules' => {
413
- 'a' => {
414
- 'manifests' => {
415
- 'init.pp' => 'class a { notice(A::A) }'
416
- },
417
- 'types' => {
418
- 'a.pp' => 'type A::A = Variant[B::B, String]',
419
- 'n.pp' => 'type A::N = C::C'
420
- },
421
- 'metadata.json' => sprintf(metadata_json, 'a', ', "dependencies": [{ "name": "example/b" }]')
422
- },
423
- 'b' => {
424
- 'types' => {
425
- 'b.pp' => 'type B::B = Variant[C::C, Float]',
426
- 'x.pp' => 'type B::X = A::A'
427
- },
428
- 'metadata.json' => sprintf(metadata_json, 'b', ', "dependencies": [{ "name": "example/c" }]')
429
- },
430
- 'c' => {
431
- 'types' => {
432
- 'c.pp' => 'type C::C = Integer'
433
- },
434
- 'metadata.json' => sprintf(metadata_json, 'c', '')
435
- },
436
- }
437
- }
438
- end
407
+ let(:node) { Puppet::Node.new("test", :environment => env) }
408
+ let(:env_dir_files) {}
439
409
 
440
410
  let(:populated_env_dir) do
441
411
  dir_contained_in(environments_dir, env_name => env_dir_files)
@@ -443,46 +413,138 @@ describe 'loaders' do
443
413
  env_dir
444
414
  end
445
415
 
446
- before(:each) do
447
- Puppet.push_context(:loaders => Puppet::Pops::Loaders.new(env))
448
- end
416
+ context 'non autoloaded types and functions' do
417
+ let(:env_dir_files) {
418
+ {
419
+ 'modules' => {
420
+ 'tstf' => {
421
+ 'manifests' => {
422
+ 'init.pp' => <<-PUPPET.unindent
423
+ class tstf {
424
+ notice(testfunc())
425
+ }
426
+ PUPPET
427
+ }
428
+ },
429
+ 'tstt' => {
430
+ 'manifests' => {
431
+ 'init.pp' => <<-PUPPET.unindent
432
+ class tstt {
433
+ notice(assert_type(GlobalType, 23))
434
+ }
435
+ PUPPET
436
+ }
437
+ }
438
+ }
439
+ }
440
+ }
449
441
 
450
- after(:each) do
451
- Puppet.pop_context
452
- end
442
+ it 'finds the function from a module' do
443
+ expect(eval_and_collect_notices(<<-PUPPET.unindent, node)).to eq(['hello from testfunc'])
444
+ function testfunc() {
445
+ 'hello from testfunc'
446
+ }
447
+ include 'tstf'
448
+ PUPPET
449
+ end
453
450
 
454
- it 'resolves types using the loader that loaded the type a -> b -> c' do
455
- type = Puppet::Pops::Types::TypeParser.singleton.parse('A::A', Puppet::Pops::Loaders.find_loader('a'))
456
- expect(type).to be_a(Puppet::Pops::Types::PTypeAliasType)
457
- expect(type.name).to eql('A::A')
458
- type = type.resolved_type
459
- expect(type).to be_a(Puppet::Pops::Types::PVariantType)
460
- type = type.types[0]
461
- expect(type.name).to eql('B::B')
462
- type = type.resolved_type
463
- expect(type).to be_a(Puppet::Pops::Types::PVariantType)
464
- type = type.types[0]
465
- expect(type.name).to eql('C::C')
466
- type = type.resolved_type
467
- expect(type).to be_a(Puppet::Pops::Types::PIntegerType)
451
+ it 'finds the type from a module' do
452
+ expect(eval_and_collect_notices(<<-PUPPET.unindent, node)).to eq(['23'])
453
+ type GlobalType = Integer
454
+ include 'tstt'
455
+ PUPPET
456
+ end
468
457
  end
469
458
 
470
- it 'will not resolve implicit transitive dependencies, a -> c' do
471
- type = Puppet::Pops::Types::TypeParser.singleton.parse('A::N', Puppet::Pops::Loaders.find_loader('a'))
472
- expect(type).to be_a(Puppet::Pops::Types::PTypeAliasType)
473
- expect(type.name).to eql('A::N')
474
- type = type.resolved_type
475
- expect(type).to be_a(Puppet::Pops::Types::PTypeReferenceType)
476
- expect(type.type_string).to eql('C::C')
477
- end
459
+ context 'types' do
460
+ let(:env_name) { 'testenv' }
461
+ let(:environments_dir) { Puppet[:environmentpath] }
462
+ let(:env_dir) { File.join(environments_dir, env_name) }
463
+ let(:env) { Puppet::Node::Environment.create(env_name.to_sym, [File.join(populated_env_dir, 'modules')]) }
464
+ let(:metadata_json) {
465
+ <<-JSON
466
+ {
467
+ "name": "example/%1$s",
468
+ "version": "0.0.2",
469
+ "source": "git@github.com/example/example-%1$s.git",
470
+ "dependencies": [],
471
+ "author": "Bob the Builder",
472
+ "license": "Apache-2.0"%2$s
473
+ }
474
+ JSON
475
+ }
478
476
 
479
- it 'will not resolve reverse dependencies, b -> a' do
480
- type = Puppet::Pops::Types::TypeParser.singleton.parse('B::X', Puppet::Pops::Loaders.find_loader('b'))
481
- expect(type).to be_a(Puppet::Pops::Types::PTypeAliasType)
482
- expect(type.name).to eql('B::X')
483
- type = type.resolved_type
484
- expect(type).to be_a(Puppet::Pops::Types::PTypeReferenceType)
485
- expect(type.type_string).to eql('A::A')
477
+ let(:env_dir_files) do
478
+ {
479
+ 'modules' => {
480
+ 'a' => {
481
+ 'manifests' => {
482
+ 'init.pp' => 'class a { notice(A::A) }'
483
+ },
484
+ 'types' => {
485
+ 'a.pp' => 'type A::A = Variant[B::B, String]',
486
+ 'n.pp' => 'type A::N = C::C'
487
+ },
488
+ 'metadata.json' => sprintf(metadata_json, 'a', ', "dependencies": [{ "name": "example/b" }]')
489
+ },
490
+ 'b' => {
491
+ 'types' => {
492
+ 'b.pp' => 'type B::B = Variant[C::C, Float]',
493
+ 'x.pp' => 'type B::X = A::A'
494
+ },
495
+ 'metadata.json' => sprintf(metadata_json, 'b', ', "dependencies": [{ "name": "example/c" }]')
496
+ },
497
+ 'c' => {
498
+ 'types' => {
499
+ 'c.pp' => 'type C::C = Integer'
500
+ },
501
+ 'metadata.json' => sprintf(metadata_json, 'c', '')
502
+ },
503
+ }
504
+ }
505
+ end
506
+
507
+ before(:each) do
508
+ Puppet.push_context(:loaders => Puppet::Pops::Loaders.new(env))
509
+ end
510
+
511
+ after(:each) do
512
+ Puppet.pop_context
513
+ end
514
+
515
+ it 'resolves types using the loader that loaded the type a -> b -> c' do
516
+ type = Puppet::Pops::Types::TypeParser.singleton.parse('A::A', Puppet::Pops::Loaders.find_loader('a'))
517
+ expect(type).to be_a(Puppet::Pops::Types::PTypeAliasType)
518
+ expect(type.name).to eql('A::A')
519
+ type = type.resolved_type
520
+ expect(type).to be_a(Puppet::Pops::Types::PVariantType)
521
+ type = type.types[0]
522
+ expect(type.name).to eql('B::B')
523
+ type = type.resolved_type
524
+ expect(type).to be_a(Puppet::Pops::Types::PVariantType)
525
+ type = type.types[0]
526
+ expect(type.name).to eql('C::C')
527
+ type = type.resolved_type
528
+ expect(type).to be_a(Puppet::Pops::Types::PIntegerType)
529
+ end
530
+
531
+ it 'will not resolve implicit transitive dependencies, a -> c' do
532
+ type = Puppet::Pops::Types::TypeParser.singleton.parse('A::N', Puppet::Pops::Loaders.find_loader('a'))
533
+ expect(type).to be_a(Puppet::Pops::Types::PTypeAliasType)
534
+ expect(type.name).to eql('A::N')
535
+ type = type.resolved_type
536
+ expect(type).to be_a(Puppet::Pops::Types::PTypeReferenceType)
537
+ expect(type.type_string).to eql('C::C')
538
+ end
539
+
540
+ it 'will not resolve reverse dependencies, b -> a' do
541
+ type = Puppet::Pops::Types::TypeParser.singleton.parse('B::X', Puppet::Pops::Loaders.find_loader('b'))
542
+ expect(type).to be_a(Puppet::Pops::Types::PTypeAliasType)
543
+ expect(type.name).to eql('B::X')
544
+ type = type.resolved_type
545
+ expect(type).to be_a(Puppet::Pops::Types::PTypeReferenceType)
546
+ expect(type.type_string).to eql('A::A')
547
+ end
486
548
  end
487
549
  end
488
550