puppet 4.4.2 → 4.5.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 (218) hide show
  1. data/CONTRIBUTING.md +5 -5
  2. data/Gemfile +2 -2
  3. data/LICENSE +2 -2
  4. data/README.md +5 -0
  5. data/ext/project_data.yaml +2 -0
  6. data/lib/hiera_puppet.rb +6 -14
  7. data/lib/puppet/application/agent.rb +2 -3
  8. data/lib/puppet/data_providers/hiera_config.rb +2 -4
  9. data/lib/puppet/data_providers/hiera_interpolate.rb +12 -154
  10. data/lib/puppet/data_providers/json_data_provider_factory.rb +0 -7
  11. data/lib/puppet/data_providers/yaml_data_provider_factory.rb +2 -8
  12. data/lib/puppet/defaults.rb +70 -7
  13. data/lib/puppet/functions.rb +69 -0
  14. data/lib/puppet/functions/dig.rb +39 -0
  15. data/lib/puppet/functions/lest.rb +53 -0
  16. data/lib/puppet/functions/lookup.rb +40 -27
  17. data/lib/puppet/functions/new.rb +502 -0
  18. data/lib/puppet/functions/regsubst.rb +11 -10
  19. data/lib/puppet/functions/then.rb +74 -0
  20. data/lib/puppet/functions/type.rb +4 -4
  21. data/lib/puppet/functions/with.rb +1 -1
  22. data/lib/puppet/indirector/catalog/compiler.rb +2 -0
  23. data/lib/puppet/indirector/resource_type/parser.rb +5 -0
  24. data/lib/puppet/indirector/rest.rb +5 -1
  25. data/lib/puppet/loaders.rb +2 -0
  26. data/lib/puppet/metatype/manager.rb +19 -2
  27. data/lib/puppet/module_tool/applications/application.rb +1 -1
  28. data/lib/puppet/module_tool/skeleton/templates/generator/Gemfile +6 -2
  29. data/lib/puppet/module_tool/skeleton/templates/generator/Rakefile +19 -4
  30. data/lib/puppet/module_tool/skeleton/templates/generator/{tests → examples}/init.pp.erb +1 -1
  31. data/lib/puppet/module_tool/skeleton/templates/generator/spec/classes/init_spec.rb.erb +0 -1
  32. data/lib/puppet/network/http/api/master/v3/environment.rb +6 -2
  33. data/lib/puppet/parser/ast/pops_bridge.rb +20 -3
  34. data/lib/puppet/parser/compiler/catalog_validator/relationship_validator.rb +24 -2
  35. data/lib/puppet/parser/e4_parser_adapter.rb +13 -12
  36. data/lib/puppet/parser/environment_compiler.rb +2 -2
  37. data/lib/puppet/parser/resource.rb +14 -5
  38. data/lib/puppet/parser/scope.rb +18 -15
  39. data/lib/puppet/plugins/data_providers/data_provider.rb +19 -8
  40. data/lib/puppet/pops.rb +6 -0
  41. data/lib/puppet/pops/adapters.rb +5 -1
  42. data/lib/puppet/pops/evaluator/access_operator.rb +52 -14
  43. data/lib/puppet/pops/evaluator/compare_operator.rb +34 -4
  44. data/lib/puppet/pops/evaluator/evaluator_impl.rb +75 -22
  45. data/lib/puppet/pops/evaluator/literal_evaluator.rb +7 -6
  46. data/lib/puppet/pops/evaluator/runtime3_converter.rb +13 -1
  47. data/lib/puppet/pops/evaluator/runtime3_support.rb +14 -4
  48. data/lib/puppet/pops/functions/dispatcher.rb +1 -1
  49. data/lib/puppet/pops/issues.rb +18 -2
  50. data/lib/puppet/pops/loader/base_loader.rb +48 -7
  51. data/lib/puppet/pops/loader/dependency_loader.rb +27 -2
  52. data/lib/puppet/pops/loader/loader.rb +12 -0
  53. data/lib/puppet/pops/loader/predefined_loader.rb +29 -0
  54. data/lib/puppet/pops/loader/runtime3_type_loader.rb +57 -0
  55. data/lib/puppet/pops/loader/static_loader.rb +92 -5
  56. data/lib/puppet/pops/loader/type_definition_instantiator.rb +25 -3
  57. data/lib/puppet/pops/loaders.rb +84 -14
  58. data/lib/puppet/pops/lookup/explainer.rb +38 -1
  59. data/lib/puppet/pops/lookup/interpolation.rb +115 -0
  60. data/lib/puppet/pops/lookup/sub_lookup.rb +86 -0
  61. data/lib/puppet/pops/model/ast_transformer.rb +8 -1
  62. data/lib/puppet/pops/model/factory.rb +31 -8
  63. data/lib/puppet/pops/model/model.rb +8 -0
  64. data/lib/puppet/pops/model/model_label_provider.rb +1 -0
  65. data/lib/puppet/pops/model/model_meta.rb +7 -1
  66. data/lib/puppet/pops/model/model_tree_dumper.rb +4 -0
  67. data/lib/puppet/pops/parser/egrammar.ra +24 -7
  68. data/lib/puppet/pops/parser/eparser.rb +863 -798
  69. data/lib/puppet/pops/parser/evaluating_parser.rb +4 -0
  70. data/lib/puppet/pops/parser/locator.rb +8 -4
  71. data/lib/puppet/pops/pcore.rb +30 -0
  72. data/lib/puppet/pops/types/class_loader.rb +2 -4
  73. data/lib/puppet/pops/types/implementation_registry.rb +146 -0
  74. data/lib/puppet/pops/types/iterable.rb +4 -4
  75. data/lib/puppet/pops/types/p_object_type.rb +846 -0
  76. data/lib/puppet/pops/types/p_runtime_type.rb +102 -0
  77. data/lib/puppet/pops/types/p_sem_ver_range_type.rb +164 -0
  78. data/lib/puppet/pops/types/p_sem_ver_type.rb +113 -0
  79. data/lib/puppet/pops/types/puppet_object.rb +21 -0
  80. data/lib/puppet/pops/types/ruby_generator.rb +258 -0
  81. data/lib/puppet/pops/types/string_converter.rb +922 -0
  82. data/lib/puppet/pops/types/type_calculator.rb +29 -5
  83. data/lib/puppet/pops/types/type_conversion_error.rb +15 -0
  84. data/lib/puppet/pops/types/type_factory.rb +49 -16
  85. data/lib/puppet/pops/types/type_formatter.rb +335 -112
  86. data/lib/puppet/pops/types/type_mismatch_describer.rb +110 -29
  87. data/lib/puppet/pops/types/type_parser.rb +205 -197
  88. data/lib/puppet/pops/types/types.rb +481 -103
  89. data/lib/puppet/pops/validation.rb +1 -1
  90. data/lib/puppet/pops/validation/checker4_0.rb +66 -4
  91. data/lib/puppet/pops/validation/validator_factory_4_0.rb +1 -0
  92. data/lib/puppet/pops/visitor.rb +3 -1
  93. data/lib/puppet/property.rb +1 -1
  94. data/lib/puppet/provider/augeas/augeas.rb +1 -1
  95. data/lib/puppet/provider/package/pip.rb +64 -20
  96. data/lib/puppet/provider/package/rpm.rb +112 -0
  97. data/lib/puppet/provider/package/yum.rb +7 -68
  98. data/lib/puppet/provider/service/daemontools.rb +3 -3
  99. data/lib/puppet/provider/service/init.rb +4 -2
  100. data/lib/puppet/provider/service/runit.rb +3 -3
  101. data/lib/puppet/provider/service/smf.rb +6 -3
  102. data/lib/puppet/provider/service/systemd.rb +59 -73
  103. data/lib/puppet/reference/providers.rb +1 -2
  104. data/lib/puppet/resource.rb +54 -37
  105. data/lib/puppet/resource/catalog.rb +31 -29
  106. data/lib/puppet/resource/type_collection.rb +23 -8
  107. data/lib/puppet/settings.rb +4 -2
  108. data/lib/puppet/settings/base_setting.rb +9 -3
  109. data/lib/puppet/settings/symbolic_enum_setting.rb +17 -0
  110. data/lib/puppet/test/test_helper.rb +0 -1
  111. data/lib/puppet/type.rb +9 -3
  112. data/lib/puppet/type/exec.rb +17 -17
  113. data/lib/puppet/type/file.rb +12 -0
  114. data/lib/puppet/type/file/content.rb +6 -6
  115. data/lib/puppet/type/file/ensure.rb +4 -4
  116. data/lib/puppet/type/file/source.rb +4 -4
  117. data/lib/puppet/type/file/target.rb +2 -2
  118. data/lib/puppet/type/mount.rb +18 -1
  119. data/lib/puppet/type/package.rb +3 -3
  120. data/lib/puppet/type/schedule.rb +4 -4
  121. data/lib/puppet/type/service.rb +15 -0
  122. data/lib/puppet/type/sshkey.rb +5 -3
  123. data/lib/puppet/type/tidy.rb +3 -3
  124. data/lib/puppet/type/zone.rb +5 -5
  125. data/lib/puppet/util/feature.rb +1 -1
  126. data/lib/puppet/util/monkey_patches.rb +8 -0
  127. data/lib/puppet/util/network_device/cisco/device.rb +16 -6
  128. data/lib/puppet/util/network_device/cisco/interface.rb +5 -6
  129. data/lib/puppet/util/plist.rb +3 -3
  130. data/lib/puppet/version.rb +1 -1
  131. data/spec/fixtures/unit/application/environments/production/data/common.yaml +13 -0
  132. data/spec/fixtures/unit/data_providers/environments/production/modules/abc/lib/puppet/functions/abc/data.rb +2 -1
  133. data/spec/fixtures/unit/data_providers/environments/production/modules/abc/manifests/init.pp +2 -1
  134. data/spec/fixtures/unit/functions/lookup/environments/production/modules/empty_key_json/data/empty_key.json +1 -0
  135. data/spec/fixtures/unit/functions/lookup/environments/production/modules/empty_key_json/hiera.yaml +5 -0
  136. data/spec/fixtures/unit/functions/lookup/environments/production/modules/empty_key_json/manifests/init.pp +2 -0
  137. data/spec/fixtures/unit/functions/lookup/environments/production/modules/empty_key_json/metadata.json +9 -0
  138. data/spec/fixtures/unit/functions/lookup/environments/production/modules/empty_key_yaml/data/empty_key.yaml +1 -0
  139. data/spec/fixtures/unit/functions/lookup/environments/production/modules/empty_key_yaml/hiera.yaml +5 -0
  140. data/spec/fixtures/unit/functions/lookup/environments/production/modules/empty_key_yaml/manifests/init.pp +2 -0
  141. data/spec/fixtures/unit/functions/lookup/environments/production/modules/empty_key_yaml/metadata.json +9 -0
  142. data/spec/fixtures/unit/functions/lookup/environments/production/modules/empty_yaml/data/empty.yaml +1 -0
  143. data/spec/fixtures/unit/pops/loaders/loaders/dependent_modules_with_metadata/modules/usee/lib/puppet/type/usee_type.rb +5 -0
  144. data/spec/fixtures/unit/pops/loaders/loaders/dependent_modules_with_metadata/modules/user/manifests/init.pp +6 -0
  145. data/spec/fixtures/unit/provider/service/smf/svcs.out +4 -3
  146. data/spec/integration/module_tool/tar/mini_spec.rb +27 -27
  147. data/spec/integration/parser/catalog_spec.rb +14 -2
  148. data/spec/integration/parser/compiler_spec.rb +94 -3
  149. data/spec/integration/parser/resource_expressions_spec.rb +1 -1
  150. data/spec/integration/resource/type_collection_spec.rb +8 -0
  151. data/spec/lib/puppet_spec/compiler.rb +11 -4
  152. data/spec/shared_contexts/types_setup.rb +4 -0
  153. data/spec/unit/application/lookup_spec.rb +91 -9
  154. data/spec/unit/appmgmt_spec.rb +44 -35
  155. data/spec/unit/capability_spec.rb +33 -53
  156. data/spec/unit/data_providers/function_data_provider_spec.rb +19 -1
  157. data/spec/unit/data_providers/hiera_data_provider_spec.rb +1 -1
  158. data/spec/unit/defaults_spec.rb +18 -0
  159. data/spec/unit/functions/assert_type_spec.rb +1 -1
  160. data/spec/unit/functions/dig_spec.rb +58 -0
  161. data/spec/unit/functions/lest_spec.rb +34 -0
  162. data/spec/unit/functions/lookup_spec.rb +108 -2
  163. data/spec/unit/functions/new_spec.rb +543 -0
  164. data/spec/unit/functions/regsubst_spec.rb +8 -0
  165. data/spec/unit/functions/then_spec.rb +40 -0
  166. data/spec/unit/functions4_spec.rb +78 -10
  167. data/spec/unit/hiera_puppet_spec.rb +49 -8
  168. data/spec/unit/indirector/resource_type/parser_spec.rb +5 -0
  169. data/spec/unit/indirector/rest_spec.rb +12 -0
  170. data/spec/unit/network/http/api/master/v3/environment_spec.rb +60 -0
  171. data/spec/unit/node/environment_spec.rb +10 -0
  172. data/spec/unit/parser/compiler_spec.rb +20 -1
  173. data/spec/unit/parser/functions/create_resources_spec.rb +2 -2
  174. data/spec/unit/parser/functions/shared.rb +1 -1
  175. data/spec/unit/parser/resource_spec.rb +8 -1
  176. data/spec/unit/parser/scope_spec.rb +45 -0
  177. data/spec/unit/pops/evaluator/access_ops_spec.rb +14 -0
  178. data/spec/unit/pops/evaluator/evaluating_parser_spec.rb +13 -5
  179. data/spec/unit/pops/loaders/static_loader_spec.rb +92 -1
  180. data/spec/unit/{data_providers/hiera_interpolation_spec.rb → pops/lookup/interpolation_spec.rb} +7 -5
  181. data/spec/unit/pops/parser/lexer2_spec.rb +2 -9
  182. data/spec/unit/pops/parser/parse_application_spec.rb +3 -8
  183. data/spec/unit/pops/parser/parse_basic_expressions_spec.rb +19 -0
  184. data/spec/unit/pops/parser/parse_capabilities_spec.rb +3 -10
  185. data/spec/unit/pops/parser/parse_site_spec.rb +19 -10
  186. data/spec/unit/pops/parser/parser_rspec_helper.rb +0 -4
  187. data/spec/unit/pops/types/enumeration_spec.rb +13 -12
  188. data/spec/unit/pops/types/iterable_spec.rb +2 -2
  189. data/spec/unit/pops/types/p_object_type_spec.rb +1060 -0
  190. data/spec/unit/pops/types/p_sem_ver_type_spec.rb +285 -0
  191. data/spec/unit/pops/types/recursion_guard_spec.rb +19 -17
  192. data/spec/unit/pops/types/ruby_generator_spec.rb +261 -0
  193. data/spec/unit/pops/types/string_converter_spec.rb +904 -0
  194. data/spec/unit/pops/types/type_calculator_spec.rb +430 -406
  195. data/spec/unit/pops/types/type_factory_spec.rb +119 -104
  196. data/spec/unit/pops/types/type_formatter_spec.rb +73 -6
  197. data/spec/unit/pops/types/type_mismatch_describer_spec.rb +2 -2
  198. data/spec/unit/pops/types/type_parser_spec.rb +54 -15
  199. data/spec/unit/pops/types/types_spec.rb +113 -8
  200. data/spec/unit/pops/validator/validator_spec.rb +84 -10
  201. data/spec/unit/provider/package/pip3_spec.rb +9 -270
  202. data/spec/unit/provider/package/pip_spec.rb +85 -30
  203. data/spec/unit/provider/package/rpm_spec.rb +160 -3
  204. data/spec/unit/provider/package/yum_spec.rb +23 -134
  205. data/spec/unit/provider/service/smf_spec.rb +14 -2
  206. data/spec/unit/provider/service/systemd_spec.rb +33 -41
  207. data/spec/unit/resource/capability_finder_spec.rb +10 -2
  208. data/spec/unit/settings/file_setting_spec.rb +6 -0
  209. data/spec/unit/transaction/additional_resource_generator_spec.rb +80 -65
  210. data/spec/unit/type/mount_spec.rb +51 -10
  211. data/spec/unit/type/service_spec.rb +16 -0
  212. data/spec/unit/type_spec.rb +14 -0
  213. data/spec/unit/util/feature_spec.rb +1 -1
  214. data/spec/unit/util/monkey_patches_spec.rb +60 -0
  215. data/spec/unit/util/network_device/cisco/device_spec.rb +1 -1
  216. metadata +63 -11
  217. data/lib/puppet/pops/types/types_meta.rb +0 -0
  218. data/spec/integration/provider/package_spec.rb +0 -35
@@ -43,7 +43,7 @@ describe "when using function data provider" do
43
43
  node = Puppet::Node.new("testnode", :facts => Puppet::Node::Facts.new("facts", {}), :environment => 'production')
44
44
  compiler = Puppet::Parser::Compiler.new(node)
45
45
  catalog = compiler.compile()
46
- resources_created_in_fixture = ["Notify[env_test1]", "Notify[env_test2]", "Notify[module_test3]"]
46
+ resources_created_in_fixture = ["Notify[env_test1]", "Notify[env_test2]", "Notify[module_test3]", "Notify[env_test2-ipl]"]
47
47
  expect(resources_in(catalog)).to include(*resources_created_in_fixture)
48
48
  end
49
49
 
@@ -56,6 +56,24 @@ describe "when using function data provider" do
56
56
  expect(resources_in(catalog)).to include(*resources_created_in_fixture)
57
57
  end
58
58
 
59
+ it 'gets data from puppet function delivering environment data' do
60
+ Puppet[:code] = <<-CODE
61
+ function environment::data() {
62
+ { 'cls::test1' => 'env_puppet1',
63
+ 'cls::test2' => 'env_puppet2'
64
+ }
65
+ }
66
+ class cls ($test1, $test2) {
67
+ notify { $test1: }
68
+ notify { $test2: }
69
+ }
70
+ include cls
71
+ CODE
72
+ node = Puppet::Node.new('testnode', :facts => Puppet::Node::Facts.new('facts', {}), :environment => 'production')
73
+ catalog = Puppet::Parser::Compiler.new(node).compile
74
+ expect(resources_in(catalog)).to include('Notify[env_puppet1]', 'Notify[env_puppet2]')
75
+ end
76
+
59
77
  it 'raises an error if the environment data function does not return a hash' do
60
78
  Puppet[:code] = 'include abc'
61
79
  # find the loaders to patch with faulty function
@@ -186,7 +186,7 @@ Merge strategy first
186
186
  Path "#{environmentpath}/hiera_misc/data/common.yaml"
187
187
  Original path: "common"
188
188
  Interpolation on "Value from interpolation %{scope("target_scope")}"
189
- Global Scope"
189
+ Global Scope
190
190
  Found key: "target_scope" value: "with scope"
191
191
  Found key: "km_scope" value: "Value from interpolation with scope"
192
192
  Merged result: "Value from interpolation with scope"
@@ -72,6 +72,24 @@ describe "Defaults" do
72
72
 
73
73
  end
74
74
 
75
+ describe 'strict' do
76
+ it 'should accept the valid value :off' do
77
+ expect {Puppet.settings[:strict] = 'off'}.to_not raise_exception
78
+ end
79
+
80
+ it 'should accept the valid value :warning' do
81
+ expect {Puppet.settings[:strict] = 'warning'}.to_not raise_exception
82
+ end
83
+
84
+ it 'should accept the valid value :error' do
85
+ expect {Puppet.settings[:strict] = 'error'}.to_not raise_exception
86
+ end
87
+
88
+ it 'should fail if given an invalid value' do
89
+ expect {Puppet.settings[:strict] = 'ignore'}.to raise_exception(/Invalid value 'ignore' for parameter strict\./)
90
+ end
91
+ end
92
+
75
93
  describe 'supported_checksum_types' do
76
94
  it 'should default to md5,sha256' do
77
95
  expect(Puppet.settings[:supported_checksum_types]).to eq(['md5', 'sha256'])
@@ -92,6 +92,6 @@ describe 'the assert_type function' do
92
92
  assert_type(Struct[{a=>Integer,b=>Boolean}], {a=>hej,x=>s})
93
93
  CODE
94
94
  expect { eval_and_collect_notices(code) }.to raise_error(Puppet::Error,
95
- /struct member 'a' expected an Integer value, got String.*expected a value for key 'b'.*did not have a 'x' key/m)
95
+ /entry 'a' expected an Integer value, got String.*expected a value for key 'b'.*unrecognized key 'x'/m)
96
96
  end
97
97
  end
@@ -0,0 +1,58 @@
1
+ require 'spec_helper'
2
+
3
+ require 'puppet_spec/compiler'
4
+ require 'matchers/resource'
5
+
6
+ describe 'the dig function' do
7
+ include PuppetSpec::Compiler
8
+ include Matchers::Resource
9
+
10
+ it 'returns a value from an array index via integer index' do
11
+ expect(compile_to_catalog("notify { [testing].dig(0): }")).to have_resource('Notify[testing]')
12
+ end
13
+
14
+ it 'returns undef if given an undef key' do
15
+ expect(compile_to_catalog(<<-SOURCE)).to have_resource('Notify[test-Undef-ing]')
16
+ notify { "test-${type([testing].dig(undef))}-ing": }
17
+ SOURCE
18
+ end
19
+
20
+ it 'returns undef if starting with undef' do
21
+ expect(compile_to_catalog(<<-SOURCE)).to have_resource('Notify[test-Undef-ing]')
22
+ notify { "test-${type(undef.dig(undef))}-ing": }
23
+ SOURCE
24
+ end
25
+
26
+ it 'returns a value from an hash key via given key' do
27
+ expect(compile_to_catalog("notify { {key => testing}.dig(key): }")).to have_resource('Notify[testing]')
28
+ end
29
+
30
+ it 'continues digging if result is an array' do
31
+ expect(compile_to_catalog("notify { [nope, [testing]].dig(1, 0): }")).to have_resource('Notify[testing]')
32
+ end
33
+
34
+ it 'continues digging if result is a hash' do
35
+ expect(compile_to_catalog("notify { [nope, {yes => testing}].dig(1, yes): }")).to have_resource('Notify[testing]')
36
+ end
37
+
38
+ it 'stops digging when step is undef' do
39
+ expect(compile_to_catalog(<<-SOURCE)).to have_resource('Notify[testing]')
40
+ $result = [nope, {yes => testing}].dig(1, no, 2)
41
+ notify { "test${result}ing": }
42
+ SOURCE
43
+ end
44
+
45
+ it 'errors if step is neither Array nor Hash' do
46
+ expect { compile_to_catalog(<<-SOURCE)}.to raise_error(/The given data does not contain a Collection at \[1, "yes"\], got 'String'/)
47
+ $result = [nope, {yes => testing}].dig(1, yes, 2)
48
+ notify { "test${result}ing": }
49
+ SOURCE
50
+ end
51
+
52
+ it 'errors if not given a non Collection as the starting point' do
53
+ expect { compile_to_catalog(<<-SOURCE)}.to raise_error(/'dig' parameter 'data' expects a Collection value, got String/)
54
+ "hello".dig(1, yes, 2)
55
+ SOURCE
56
+ end
57
+
58
+ end
@@ -0,0 +1,34 @@
1
+ require 'spec_helper'
2
+
3
+ require 'puppet_spec/compiler'
4
+ require 'matchers/resource'
5
+
6
+ describe 'the lest function' do
7
+ include PuppetSpec::Compiler
8
+ include Matchers::Resource
9
+
10
+ it 'calls a lambda passing no argument' do
11
+ expect(compile_to_catalog("lest(undef) || { notify { testing: } }")).to have_resource('Notify[testing]')
12
+ end
13
+
14
+ it 'produces what lambda returns if value is undef' do
15
+ expect(compile_to_catalog("notify{ lest(undef) || { testing }: }")).to have_resource('Notify[testing]')
16
+ end
17
+
18
+ it 'does not call lambda if argument is not undef' do
19
+ expect(compile_to_catalog('lest(1) || { notify { "failed": } }')).to_not have_resource('Notify[failed]')
20
+ end
21
+
22
+ it 'produces given argument if given not undef' do
23
+ expect(compile_to_catalog(<<-SOURCE)).to have_resource('Notify[test_yay_ing]')
24
+ notify{ "test${lest('_yay_') || { '_oh_no_' }}ing": }
25
+ SOURCE
26
+ end
27
+
28
+ it 'errors when lambda wants too many args' do
29
+ expect do
30
+ compile_to_catalog('lest(1) |$x| { }')
31
+ end.to raise_error(/'lest' block expects no arguments, got 1/m)
32
+ end
33
+
34
+ end
@@ -249,7 +249,7 @@ describe "when performing lookup" do
249
249
  expect do
250
250
  assemble_and_compile('${r[a]}_${r[b]}', "'abc::x'", 'Hash[String,String]', 'undef', "{'a' => 'dflt_x', 'b' => 32}")
251
251
  end.to raise_error(Puppet::ParseError,
252
- /Default value had wrong type, expected a Hash\[String, String\] value, got Struct\[\{'a' => String, 'b' => Integer\}\]/)
252
+ /Default value had wrong type, entry 'b' expected a String value, got Integer/)
253
253
  end
254
254
  end
255
255
 
@@ -283,7 +283,7 @@ describe "when performing lookup" do
283
283
  expect do
284
284
  assemble_and_compile_with_block('${r[a]}_${r[b]}', "{'a' => 'dflt_x', 'b' => 32}", "'abc::x'", 'Hash[String,String]')
285
285
  end.to raise_error(Puppet::ParseError,
286
- /Value returned from default block had wrong type, expected a Hash\[String, String\] value, got Struct\[\{'a' => String, 'b' => Integer\}\]/)
286
+ /Value returned from default block had wrong type, entry 'b' expected a String value, got Integer/)
287
287
  end
288
288
 
289
289
  it 'receives a single name parameter' do
@@ -298,6 +298,38 @@ describe "when performing lookup" do
298
298
  end
299
299
  end
300
300
 
301
+ context 'when using dotted keys' do
302
+ it 'can access values in data using dot notation' do
303
+ source = <<-CODE
304
+ function environment::data() {
305
+ { a => { b => { c => 'the data' }}}
306
+ }
307
+ notice(lookup('a.b.c'))
308
+ CODE
309
+ expect(eval_and_collect_notices(source)).to include('the data')
310
+ end
311
+
312
+ it 'can find data using quoted dot notation' do
313
+ source = <<-CODE
314
+ function environment::data() {
315
+ { 'a.b.c' => 'the data' }
316
+ }
317
+ notice(lookup('"a.b.c"'))
318
+ CODE
319
+ expect(eval_and_collect_notices(source)).to include('the data')
320
+ end
321
+
322
+ it 'can access values in data using a mix of dot notation and quoted dot notation' do
323
+ source = <<-CODE
324
+ function environment::data() {
325
+ { 'a' => { 'b.c' => 'the data' }}
326
+ }
327
+ notice(lookup('a."b.c"'))
328
+ CODE
329
+ expect(eval_and_collect_notices(source)).to include('the data')
330
+ end
331
+ end
332
+
301
333
  context 'when passing a hash as the only parameter' do
302
334
  it 'can pass a single name correctly' do
303
335
  resources = assemble_and_compile('${r}', "{name => 'abc::a'}")
@@ -432,6 +464,58 @@ describe "when performing lookup" do
432
464
  end
433
465
  end
434
466
 
467
+ context 'when accessing nil values' do
468
+ it 'will find a key with undef value in a yaml file' do
469
+ Puppet[:code] = 'include empty_key_yaml'
470
+ compiler.compile do |catalog|
471
+ lookup_invocation = Puppet::Pops::Lookup::Invocation.new(compiler.topscope, {}, {}, true)
472
+ begin
473
+ Puppet::Pops::Lookup.lookup('empty_key_yaml::has_undef_value',nil, nil, false, nil, lookup_invocation)
474
+ rescue Puppet::Error
475
+ end
476
+ expect(lookup_invocation.explainer.to_s).to eq(<<EOS)
477
+ Merge strategy first
478
+ Data Binding "hiera"
479
+ No such key: "empty_key_yaml::has_undef_value"
480
+ Data Provider "FunctionEnvDataProvider"
481
+ No such key: "empty_key_yaml::has_undef_value"
482
+ Module "empty_key_yaml" using Data Provider "Hiera Data Provider, version 4"
483
+ ConfigurationPath "#{environmentpath}/production/modules/empty_key_yaml/hiera.yaml"
484
+ Data Provider "empty_key"
485
+ Path "#{environmentpath}/production/modules/empty_key_yaml/data/empty_key.yaml"
486
+ Original path: "empty_key"
487
+ Found key: "empty_key_yaml::has_undef_value" value: nil
488
+ Merged result: nil
489
+ EOS
490
+ end
491
+ end
492
+
493
+ it 'will find a key with undef value in a json file' do
494
+ Puppet[:code] = 'include empty_key_json'
495
+ compiler.compile do |catalog|
496
+ lookup_invocation = Puppet::Pops::Lookup::Invocation.new(compiler.topscope, {}, {}, true)
497
+ begin
498
+ Puppet::Pops::Lookup.lookup('empty_key_json::has_undef_value',nil, nil, false, nil, lookup_invocation)
499
+ rescue Puppet::Error
500
+ end
501
+ expect(lookup_invocation.explainer.to_s).to eq(<<EOS)
502
+ Merge strategy first
503
+ Data Binding "hiera"
504
+ No such key: "empty_key_json::has_undef_value"
505
+ Data Provider "FunctionEnvDataProvider"
506
+ No such key: "empty_key_json::has_undef_value"
507
+ Module "empty_key_json" using Data Provider "Hiera Data Provider, version 4"
508
+ ConfigurationPath "#{environmentpath}/production/modules/empty_key_json/hiera.yaml"
509
+ Data Provider "empty_key"
510
+ Path "#{environmentpath}/production/modules/empty_key_json/data/empty_key.json"
511
+ Original path: "empty_key"
512
+ Found key: "empty_key_json::has_undef_value" value: nil
513
+ Merged result: nil
514
+ EOS
515
+ end
516
+ end
517
+ end
518
+
435
519
  context 'when using explain' do
436
520
  it 'will explain that module is not found' do
437
521
  assemble_and_compile('${r}', "'abc::a'") do |scope|
@@ -558,6 +642,28 @@ EOS
558
642
  end
559
643
  end
560
644
 
645
+ it 'will explain value access caused by dot notation in key' do
646
+ assemble_and_compile('${r}', "'abc::a'") do |scope|
647
+ lookup_invocation = Puppet::Pops::Lookup::Invocation.new(scope, {}, {}, true)
648
+ Puppet::Pops::Lookup.lookup('abc::f.k1.s1', Puppet::Pops::Types::TypeParser.new.parse('String'), nil, false, nil, lookup_invocation)
649
+ expect(lookup_invocation.explainer.to_s).to eq(<<EOS)
650
+ Merge strategy first
651
+ Data Binding "hiera"
652
+ No such key: "abc::f.k1.s1"
653
+ Data Provider "FunctionEnvDataProvider"
654
+ Sub key: "k1.s1"
655
+ Found key: "k1" value: {
656
+ "s1" => "env_f11",
657
+ "s2" => "env_f12"
658
+ }
659
+ Found key: "s1" value: "env_f11"
660
+ Found key: "abc::f.k1.s1" value: "env_f11"
661
+ Merged result: "env_f11"
662
+ EOS
663
+ end
664
+ end
665
+
666
+
561
667
  it 'will provide a hash containing all explanation elements' do
562
668
  assemble_and_compile('${r}', "'abc::a'") do |scope|
563
669
  lookup_invocation = Puppet::Pops::Lookup::Invocation.new(scope, {}, {}, true)
@@ -0,0 +1,543 @@
1
+ require 'spec_helper'
2
+
3
+ require 'puppet_spec/compiler'
4
+ require 'matchers/resource'
5
+
6
+ describe 'the new function' do
7
+ include PuppetSpec::Compiler
8
+ include Matchers::Resource
9
+
10
+ it 'yields converted value if given a block' do
11
+ expect(compile_to_catalog(<<-MANIFEST
12
+ $x = Integer.new('42') |$x| { $x+2 }
13
+ notify { "${type($x, generalized)}, $x": }
14
+ MANIFEST
15
+ )).to have_resource('Notify[Integer, 44]')
16
+ end
17
+
18
+ it 'produces undef if given an undef value and type accepts it' do
19
+ expect(compile_to_catalog(<<-MANIFEST
20
+ $x = Optional[Integer].new(undef)
21
+ notify { "one${x}word": }
22
+ MANIFEST
23
+ )).to have_resource('Notify[oneword]')
24
+ end
25
+
26
+ it 'errors if given undef and type does not accept the value' do
27
+ expect{compile_to_catalog(<<-MANIFEST
28
+ $x = Integer.new(undef)
29
+ notify { "one${x}word": }
30
+ MANIFEST
31
+ )}.to raise_error(Puppet::Error, /expected an Integer value, got Undef/)
32
+ end
33
+
34
+ it 'errors if converted value is not assignable to the type' do
35
+ expect{compile_to_catalog(<<-MANIFEST
36
+ $x = Integer[1,5].new('42')
37
+ notify { "one${x}word": }
38
+ MANIFEST
39
+ )}.to raise_error(Puppet::Error, /expected an Integer\[1, 5\] value, got Integer\[42, 42\]/)
40
+ end
41
+
42
+ context 'when invoked on NotUndef' do
43
+ it 'produces an instance of the NotUndef nested type' do
44
+ expect(compile_to_catalog(<<-MANIFEST
45
+ $x = NotUndef[Integer].new(42)
46
+ notify { "${type($x, generalized)}, $x": }
47
+ MANIFEST
48
+ )).to have_resource('Notify[Integer, 42]')
49
+ end
50
+
51
+ it 'produces the given value when there is no type specified' do
52
+ expect(compile_to_catalog(<<-MANIFEST
53
+ $x = NotUndef.new(42)
54
+ notify { "${type($x, generalized)}, $x": }
55
+ MANIFEST
56
+ )).to have_resource('Notify[Integer, 42]')
57
+ end
58
+ end
59
+
60
+ context 'when invoked on an Integer' do
61
+ it 'produces 42 when given the integer 42' do
62
+ expect(compile_to_catalog(<<-MANIFEST
63
+ $x = Integer.new(42)
64
+ notify { "${type($x, generalized)}, $x": }
65
+ MANIFEST
66
+ )).to have_resource('Notify[Integer, 42]')
67
+ end
68
+
69
+ it 'produces 3 when given the float 3.1415' do
70
+ expect(compile_to_catalog(<<-MANIFEST
71
+ $x = Integer.new(3.1415)
72
+ notify { "${type($x, generalized)}, $x": }
73
+ MANIFEST
74
+ )).to have_resource('Notify[Integer, 3]')
75
+ end
76
+
77
+ it 'produces 0 from false' do
78
+ expect(compile_to_catalog(<<-MANIFEST
79
+ $x = Integer.new(false)
80
+ notify { "${type($x, generalized)}, $x": }
81
+ MANIFEST
82
+ )).to have_resource('Notify[Integer, 0]')
83
+ end
84
+
85
+ it 'produces 1 from true' do
86
+ expect(compile_to_catalog(<<-MANIFEST
87
+ $x = Integer.new(true)
88
+ notify { "${type($x, generalized)}, $x": }
89
+ MANIFEST
90
+ )).to have_resource('Notify[Integer, 1]')
91
+ end
92
+
93
+ context "when radix is not set it uses default and" do
94
+ { "10" => 10,
95
+ "010" => 8,
96
+ "0x10" => 16,
97
+ "0X10" => 16,
98
+ '0B111' => 7,
99
+ '0b111' => 7
100
+ }.each do |str, result|
101
+ it "produces #{result} from the string '#{str}'" do
102
+ expect(compile_to_catalog(<<-"MANIFEST"
103
+ $x = Integer.new("#{str}")
104
+ notify { "${type($x, generalized)}, $x": }
105
+ MANIFEST
106
+ )).to have_resource("Notify[Integer, #{result}]")
107
+ end
108
+ end
109
+ end
110
+
111
+ context "when radix is explicitly set to 'default' it" do
112
+ { "10" => 10,
113
+ "010" => 8,
114
+ "0x10" => 16,
115
+ "0X10" => 16,
116
+ '0B111' => 7,
117
+ '0b111' => 7
118
+ }.each do |str, result|
119
+ it "produces #{result} from the string '#{str}'" do
120
+ expect(compile_to_catalog(<<-"MANIFEST"
121
+ $x = Integer.new("#{str}", default)
122
+ notify { "${type($x, generalized)}, $x": }
123
+ MANIFEST
124
+ )).to have_resource("Notify[Integer, #{result}]")
125
+ end
126
+ end
127
+ end
128
+
129
+ context "when radix is explicitly set to '2' it" do
130
+ { "10" => 2,
131
+ "010" => 2,
132
+ "00010" => 2,
133
+ '0B111' => 7,
134
+ '0b111' => 7
135
+ }.each do |str, result|
136
+ it "produces #{result} from the string '#{str}'" do
137
+ expect(compile_to_catalog(<<-"MANIFEST"
138
+ $x = Integer.new("#{str}", 2)
139
+ notify { "${type($x, generalized)}, $x": }
140
+ MANIFEST
141
+ )).to have_resource("Notify[Integer, #{result}]")
142
+ end
143
+ end
144
+
145
+ { "0x10" => :error,
146
+ '0X10' => :error
147
+ }.each do |str, result|
148
+ it "errors when given the non binary value compliant string '#{str}'" do
149
+ expect{compile_to_catalog(<<-"MANIFEST"
150
+ $x = Integer.new("#{str}", 2)
151
+ MANIFEST
152
+ )}.to raise_error(Puppet::Error, /invalid value/)
153
+ end
154
+ end
155
+ end
156
+
157
+ context "when radix is explicitly set to '8' it" do
158
+ { "10" => 8,
159
+ "010" => 8,
160
+ "00010" => 8,
161
+ }.each do |str, result|
162
+ it "produces #{result} from the string '#{str}'" do
163
+ expect(compile_to_catalog(<<-"MANIFEST"
164
+ $x = Integer.new("#{str}", 8)
165
+ notify { "${type($x, generalized)}, $x": }
166
+ MANIFEST
167
+ )).to have_resource("Notify[Integer, #{result}]")
168
+ end
169
+ end
170
+
171
+ { "0x10" => :error,
172
+ '0X10' => :error,
173
+ '0B10' => :error,
174
+ '0b10' => :error,
175
+ }.each do |str, result|
176
+ it "errors when given the non octal value compliant string '#{str}'" do
177
+ expect{compile_to_catalog(<<-"MANIFEST"
178
+ $x = Integer.new("#{str}", 8)
179
+ MANIFEST
180
+ )}.to raise_error(Puppet::Error, /invalid value/)
181
+ end
182
+ end
183
+ end
184
+
185
+ context "when radix is explicitly set to '16' it" do
186
+ { "10" => 16,
187
+ "010" => 16,
188
+ "00010" => 16,
189
+ "0x10" => 16,
190
+ "0X10" => 16,
191
+ "0b1" => 16*11+1,
192
+ "0B1" => 16*11+1,
193
+ }.each do |str, result|
194
+ it "produces #{result} from the string '#{str}'" do
195
+ expect(compile_to_catalog(<<-"MANIFEST"
196
+ $x = Integer.new("#{str}", 16)
197
+ notify { "${type($x, generalized)}, $x": }
198
+ MANIFEST
199
+ )).to have_resource("Notify[Integer, #{result}]")
200
+ end
201
+ end
202
+
203
+ { '0XGG' => :error,
204
+ }.each do |str, result|
205
+ it "errors when given the non octal value compliant string '#{str}'" do
206
+ expect{compile_to_catalog(<<-"MANIFEST"
207
+ $x = Integer.new("#{str}", 8)
208
+ MANIFEST
209
+ )}.to raise_error(Puppet::Error, /invalid value/)
210
+ end
211
+ end
212
+ end
213
+
214
+ context "when radix is explicitly set to '10' it" do
215
+ { "10" => 10,
216
+ "010" => 10,
217
+ "00010" => 10,
218
+ }.each do |str, result|
219
+ it "produces #{result} from the string '#{str}'" do
220
+ expect(compile_to_catalog(<<-"MANIFEST"
221
+ $x = Integer.new("#{str}", 10)
222
+ notify { "${type($x, generalized)}, $x": }
223
+ MANIFEST
224
+ )).to have_resource("Notify[Integer, #{result}]")
225
+ end
226
+ end
227
+
228
+ { '0X10' => :error,
229
+ '0X10' => :error,
230
+ '0b10' => :error,
231
+ '0B10' => :error,
232
+ }.each do |str, result|
233
+ it "errors when given the non octal value compliant string '#{str}'" do
234
+ expect{compile_to_catalog(<<-"MANIFEST"
235
+ $x = Integer.new("#{str}", 10)
236
+ MANIFEST
237
+ )}.to raise_error(Puppet::Error, /invalid value/)
238
+ end
239
+ end
240
+ end
241
+
242
+ context "input can be given in long form " do
243
+ { {'from' => "10", 'radix' => 2} => 2,
244
+ {'from' => "10", 'radix' => 8} => 8,
245
+ {'from' => "10", 'radix' => 10} => 10,
246
+ {'from' => "10", 'radix' => 16} => 16,
247
+ {'from' => "10", 'radix' => :default} => 10,
248
+ }.each do |options, result|
249
+ it "produces #{result} from the long form '#{options}'" do
250
+ src = <<-"MANIFEST"
251
+ $x = Integer.new(#{options.to_s.gsub(/:/, '')})
252
+ notify { "${type($x, generalized)}, $x": }
253
+ MANIFEST
254
+ expect(compile_to_catalog(src)).to have_resource("Notify[Integer, #{result}]")
255
+ end
256
+ end
257
+ end
258
+
259
+ context 'errors when' do
260
+ it 'radix is wrong and when given directly' do
261
+ expect{compile_to_catalog(<<-"MANIFEST"
262
+ $x = Integer.new('10', 3)
263
+ MANIFEST
264
+ )}.to raise_error(Puppet::Error, /rejected: parameter 'radix'/m)
265
+ end
266
+
267
+ it 'radix is wrong and when given in long form' do
268
+ expect{compile_to_catalog(<<-"MANIFEST"
269
+ $x = Integer.new({from =>'10', radix=>3})
270
+ MANIFEST
271
+ )}.to raise_error(Puppet::Error, /rejected: parameter 'hash_args' entry 'radix'/m)
272
+ end
273
+
274
+ it 'value is not numeric and given directly' do
275
+ expect{compile_to_catalog(<<-"MANIFEST"
276
+ $x = Integer.new('eleven', 10)
277
+ MANIFEST
278
+ )}.to raise_error(Puppet::Error, /invalid value/)
279
+ end
280
+
281
+ it 'value is not numeric and given in long form' do
282
+ expect{compile_to_catalog(<<-"MANIFEST"
283
+ $x = Integer.new({from => 'eleven', radix => 10})
284
+ MANIFEST
285
+ )}.to raise_error(Puppet::Error, /invalid value/)
286
+ end
287
+ end
288
+ end
289
+
290
+ context 'when invoked on Numeric' do
291
+ { 42 => "Notify[Integer, 42]",
292
+ 42.3 => "Notify[Float, 42.3]",
293
+ "42.0" => "Notify[Float, 42.0]",
294
+ "42.3" => "Notify[Float, 42.3]",
295
+ "0x10" => "Notify[Integer, 16]",
296
+ "010" => "Notify[Integer, 8]",
297
+ "0.10" => "Notify[Float, 0.1]",
298
+ "0b10" => "Notify[Integer, 2]",
299
+ false => "Notify[Integer, 0]",
300
+ true => "Notify[Integer, 1]",
301
+ }.each do |input, result|
302
+ it "produces #{result} when given the value #{input.inspect}" do
303
+ expect(compile_to_catalog(<<-MANIFEST
304
+ $x = Numeric.new(#{input.inspect})
305
+ notify { "${type($x, generalized)}, $x": }
306
+ MANIFEST
307
+ )).to have_resource(result)
308
+ end
309
+ end
310
+
311
+ it "produces a result when long from hash {from => val} is used" do
312
+ expect(compile_to_catalog(<<-MANIFEST
313
+ $x = Numeric.new({from=>'42'})
314
+ notify { "${type($x, generalized)}, $x": }
315
+ MANIFEST
316
+ )).to have_resource('Notify[Integer, 42]')
317
+ end
318
+ end
319
+
320
+ context 'when invoked on Float' do
321
+ { 42 => "Notify[Float, 42.0]",
322
+ 42.3 => "Notify[Float, 42.3]",
323
+ "42.0" => "Notify[Float, 42.0]",
324
+ "42.3" => "Notify[Float, 42.3]",
325
+ "0x10" => "Notify[Float, 16.0]",
326
+ "010" => "Notify[Float, 10.0]",
327
+ "0.10" => "Notify[Float, 0.1]",
328
+ false => "Notify[Float, 0.0]",
329
+ true => "Notify[Float, 1.0]",
330
+ '0b10' => "Notify[Float, 2.0]",
331
+ '0B10' => "Notify[Float, 2.0]",
332
+ }.each do |input, result|
333
+ it "produces #{result} when given the value #{input.inspect}" do
334
+ expect(compile_to_catalog(<<-MANIFEST
335
+ $x = Float.new(#{input.inspect})
336
+ notify { "${type($x, generalized)}, $x": }
337
+ MANIFEST
338
+ )).to have_resource(result)
339
+ end
340
+ end
341
+
342
+ it "produces a result when long from hash {from => val} is used" do
343
+ expect(compile_to_catalog(<<-MANIFEST
344
+ $x = Float.new({from=>42})
345
+ notify { "${type($x, generalized)}, $x": }
346
+ MANIFEST
347
+ )).to have_resource('Notify[Float, 42.0]')
348
+ end
349
+ end
350
+
351
+ context 'when invoked on Boolean' do
352
+ { true => 'Notify[Boolean, true]',
353
+ false => 'Notify[Boolean, false]',
354
+ 0 => 'Notify[Boolean, false]',
355
+ 1 => 'Notify[Boolean, true]',
356
+ 0.0 => 'Notify[Boolean, false]',
357
+ 1.0 => 'Notify[Boolean, true]',
358
+
359
+ 'true' => 'Notify[Boolean, true]',
360
+ 'TrUe' => 'Notify[Boolean, true]',
361
+ 'yes' => 'Notify[Boolean, true]',
362
+ 'YeS' => 'Notify[Boolean, true]',
363
+ 'y' => 'Notify[Boolean, true]',
364
+ 'Y' => 'Notify[Boolean, true]',
365
+
366
+ 'false' => 'Notify[Boolean, false]',
367
+ 'no' => 'Notify[Boolean, false]',
368
+ 'n' => 'Notify[Boolean, false]',
369
+ 'FalSE' => 'Notify[Boolean, false]',
370
+ 'nO' => 'Notify[Boolean, false]',
371
+ 'N' => 'Notify[Boolean, false]',
372
+ }.each do |input, result|
373
+ it "produces #{result} when given the value #{input.inspect}" do
374
+ expect(compile_to_catalog(<<-MANIFEST
375
+ $x = Boolean.new(#{input.inspect})
376
+ notify { "${type($x, generalized)}, $x": }
377
+ MANIFEST
378
+ )).to have_resource(result)
379
+ end
380
+ end
381
+
382
+ it "errors when given an non boolean representation like the string 'hello'" do
383
+ expect{compile_to_catalog(<<-"MANIFEST"
384
+ $x = Boolean.new('hello')
385
+ MANIFEST
386
+ )}.to raise_error(Puppet::Error, /cannot be converted to Boolean/)
387
+ end
388
+
389
+ it "does not convert an undef (as may be expected, but is handled as every other undef)" do
390
+ expect{compile_to_catalog(<<-"MANIFEST"
391
+ $x = Boolean.new(undef)
392
+ MANIFEST
393
+ )}.to raise_error(Puppet::Error, /expected a Boolean value, got Undef/)
394
+ end
395
+ end
396
+
397
+ context 'when invoked on Array' do
398
+ { [] => 'Notify[Array[Unit], []]',
399
+ [true] => 'Notify[Array[Boolean], [true]]',
400
+ {'a'=>true, 'b' => false} => 'Notify[Array[Array[Scalar]], [[a, true], [b, false]]]',
401
+ 'abc' => 'Notify[Array[String], [a, b, c]]',
402
+ 3 => 'Notify[Array[Integer], [0, 1, 2]]',
403
+ }.each do |input, result|
404
+ it "produces #{result} when given the value #{input.inspect} and wrap is not given" do
405
+ expect(compile_to_catalog(<<-MANIFEST
406
+ $x = Array.new(#{input.inspect})
407
+ notify { "${type($x, generalized)}, $x": }
408
+ MANIFEST
409
+ )).to have_resource(result)
410
+ end
411
+ end
412
+
413
+ {
414
+ true => /cannot be converted to Array/,
415
+ 42.3 => /cannot be converted to Array/,
416
+ }.each do |input, error_match|
417
+ it "errors when given an non convertible #{input.inspect} when wrap is not given" do
418
+ expect{compile_to_catalog(<<-"MANIFEST"
419
+ $x = Array.new(#{input.inspect})
420
+ MANIFEST
421
+ )}.to raise_error(Puppet::Error, error_match)
422
+ end
423
+ end
424
+
425
+ { [] => 'Notify[Array[Unit], []]',
426
+ [true] => 'Notify[Array[Boolean], [true]]',
427
+ {'a'=>true} => 'Notify[Array[Hash[String, Boolean]], [{a => true}]]',
428
+ 'hello' => 'Notify[Array[String], [hello]]',
429
+ true => 'Notify[Array[Boolean], [true]]',
430
+ 42 => 'Notify[Array[Integer], [42]]',
431
+ }.each do |input, result|
432
+ it "produces #{result} when given the value #{input.inspect} and wrap is given" do
433
+ expect(compile_to_catalog(<<-MANIFEST
434
+ $x = Array.new(#{input.inspect}, true)
435
+ notify { "${type($x, generalized)}, $x": }
436
+ MANIFEST
437
+ )).to have_resource(result)
438
+ end
439
+ end
440
+ end
441
+
442
+ context 'when invoked on Tuple' do
443
+ { 'abc' => 'Notify[Array[String], [a, b, c]]',
444
+ 3 => 'Notify[Array[Integer], [0, 1, 2]]',
445
+ }.each do |input, result|
446
+ it "produces #{result} when given the value #{input.inspect} and wrap is not given" do
447
+ expect(compile_to_catalog(<<-MANIFEST
448
+ $x = Tuple[Any,3].new(#{input.inspect})
449
+ notify { "${type($x, generalized)}, $x": }
450
+ MANIFEST
451
+ )).to have_resource(result)
452
+ end
453
+ end
454
+
455
+ it "errors when tuple requirements are not met" do
456
+ expect{compile_to_catalog(<<-"MANIFEST"
457
+ $x = Tuple[Integer,6].new(3)
458
+ MANIFEST
459
+ )}.to raise_error(Puppet::Error, /expected size to be at least 6, got 3/)
460
+ end
461
+ end
462
+
463
+ context 'when invoked on Hash' do
464
+ { {} => 'Notify[Hash[0, 0], {}]',
465
+ [] => 'Notify[Hash[0, 0], {}]',
466
+ {'a'=>true} => 'Notify[Hash[String, Boolean], {a => true}]',
467
+ [1,2,3,4] => 'Notify[Hash[Integer, Integer], {1 => 2, 3 => 4}]',
468
+ [[1,2],[3,4]] => 'Notify[Hash[Integer, Integer], {1 => 2, 3 => 4}]',
469
+ 'abcd' => 'Notify[Hash[String, String], {a => b, c => d}]',
470
+ 4 => 'Notify[Hash[Integer, Integer], {0 => 1, 2 => 3}]',
471
+
472
+ }.each do |input, result|
473
+ it "produces #{result} when given the value #{input.inspect}" do
474
+ expect(compile_to_catalog(<<-MANIFEST
475
+ $x = Hash.new(#{input.inspect})
476
+ notify { "${type($x, generalized)}, $x": }
477
+ MANIFEST
478
+ )).to have_resource(result)
479
+ end
480
+ end
481
+
482
+ { true => /cannot be converted to Hash/,
483
+ [1,2,3] => /odd number of arguments for Hash/,
484
+ }.each do |input, error_match|
485
+ it "errors when given an non convertible #{input.inspect}" do
486
+ expect{compile_to_catalog(<<-"MANIFEST"
487
+ $x = Hash.new(#{input.inspect})
488
+ MANIFEST
489
+ )}.to raise_error(Puppet::Error, error_match)
490
+ end
491
+ end
492
+ end
493
+
494
+ context 'when invoked on Struct' do
495
+ { {'a' => 2} => 'Notify[Struct[{\'a\' => Integer[2, 2]}], {a => 2}]',
496
+ }.each do |input, result|
497
+ it "produces #{result} when given the value #{input.inspect}" do
498
+ expect(compile_to_catalog(<<-MANIFEST
499
+ $x = Struct[{a => Integer[2]}].new(#{input.inspect})
500
+ notify { "${type($x)}, $x": }
501
+ MANIFEST
502
+ )).to have_resource(result)
503
+ end
504
+ end
505
+
506
+ it "errors when tuple requirements are not met" do
507
+ expect{compile_to_catalog(<<-"MANIFEST"
508
+ $x = Struct[{a => Integer[2]}].new({a => 0})
509
+ MANIFEST
510
+ )}.to raise_error(Puppet::Error, /entry 'a' expected an Integer\[2, default\]/)
511
+ end
512
+ end
513
+
514
+ context 'when invoked on String' do
515
+ { {} => 'Notify[String, {}]',
516
+ [] => 'Notify[String, []]',
517
+ {'a'=>true} => 'Notify[String, {"a" => true}]',
518
+ [1,2,3,4] => 'Notify[String, [1, 2, 3, 4]]',
519
+ [[1,2],[3,4]] => 'Notify[String, [[1, 2], [3, 4]]]',
520
+ 'abcd' => 'Notify[String, abcd]',
521
+ 4 => 'Notify[String, 4]',
522
+ }.each do |input, result|
523
+ it "produces #{result} when given the value #{input.inspect}" do
524
+ expect(compile_to_catalog(<<-MANIFEST
525
+ $x = String.new(#{input.inspect})
526
+ notify { "${type($x, generalized)}, $x": }
527
+ MANIFEST
528
+ )).to have_resource(result)
529
+ end
530
+ end
531
+ end
532
+
533
+ context 'when invoked on a type alias' do
534
+ it 'delegates the new to the aliased type' do
535
+ expect(compile_to_catalog(<<-MANIFEST
536
+ type X = Boolean
537
+ $x = X.new('yes')
538
+ notify { "${type($x, generalized)}, $x": }
539
+ MANIFEST
540
+ )).to have_resource('Notify[Boolean, true]')
541
+ end
542
+ end
543
+ end