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
@@ -15,7 +15,7 @@ describe 'the type mismatch describer' do
15
15
  }
16
16
  f({'a' => 'a', 'b' => 23})
17
17
  CODE
18
- expect { eval_and_collect_notices(code) }.to raise_error(Puppet::Error, /expects a Hash\[String, String\] value, got Struct\[\{'a' => String, 'b' => Integer\}\]/)
18
+ expect { eval_and_collect_notices(code) }.to raise_error(Puppet::Error, /'f' parameter 'h' entry 'b' expects a String value, got Integer/)
19
19
  end
20
20
 
21
21
  it 'will report a mismatch between a array and tuple with details' do
@@ -78,7 +78,7 @@ describe 'the type mismatch describer' do
78
78
  check_tree({ 'x' => {'y' => {32 => 'n'}}})
79
79
  CODE
80
80
  expect { eval_and_collect_notices(code) }.to(raise_error(Puppet::Error,
81
- /parameter 'tree' expects a Tree = Hash\[String, Tree\] value, got Struct\[\{'x' => Struct\[\{'y' => Hash\[Integer, String\]\}\]\}\]/))
81
+ /parameter 'tree' entry 'x' entry 'y' expects a Tree = Hash\[String, Tree\] value, got Hash\[Integer\[32, 32\], String\[1, 1\]\]/))
82
82
  end
83
83
 
84
84
  it 'will use type normalization' do
@@ -1,11 +1,13 @@
1
1
  require 'spec_helper'
2
2
  require 'puppet/pops'
3
3
 
4
- describe Puppet::Pops::Types::TypeParser do
4
+ module Puppet::Pops
5
+ module Types
6
+ describe TypeParser do
5
7
  extend RSpec::Matchers::DSL
6
8
 
7
- let(:parser) { Puppet::Pops::Types::TypeParser.new }
8
- let(:types) { Puppet::Pops::Types::TypeFactory }
9
+ let(:parser) { TypeParser.new }
10
+ let(:types) { TypeFactory }
9
11
  it "rejects a puppet expression" do
10
12
  expect { parser.parse("1 + 1") }.to raise_error(Puppet::ParseError, /The expression <1 \+ 1> is not a valid type specification/)
11
13
  end
@@ -60,6 +62,14 @@ describe Puppet::Pops::Types::TypeParser do
60
62
  expect(parser.parse("Hash")).to be_the_type(types.hash_of_data)
61
63
  end
62
64
 
65
+ it "interprets a parameterized Array[0, 0] as an empty hash with no key and value type" do
66
+ expect(parser.parse("Array[0, 0]")).to be_the_type(types.array_of(types.default, types.range(0, 0)))
67
+ end
68
+
69
+ it "interprets a parameterized Hash[0, 0] as an empty hash with no key and value type" do
70
+ expect(parser.parse("Hash[0, 0]")).to be_the_type(types.hash_of(types.default, types.default, types.range(0, 0)))
71
+ end
72
+
63
73
  it "interprets a parameterized Hash[t] as a Hash of Scalar to t" do
64
74
  expect(parser.parse("Hash[Scalar, Integer]")).to be_the_type(types.hash_of(types.integer))
65
75
  end
@@ -123,7 +133,7 @@ describe Puppet::Pops::Types::TypeParser do
123
133
  'Pattern[/x9/, /([a-z]+)([1-9]+)/]' => [:pattern, [/x9/, /([a-z]+)([1-9]+)/]],
124
134
  }.each do |source, type|
125
135
  it "such that the source '#{source}' yields the type #{type.to_s}" do
126
- expect(parser.parse(source)).to be_the_type(Puppet::Pops::Types::TypeFactory.send(type[0], *type[1]))
136
+ expect(parser.parse(source)).to be_the_type(TypeFactory.send(type[0], *type[1]))
127
137
  end
128
138
  end
129
139
  end
@@ -135,50 +145,71 @@ describe Puppet::Pops::Types::TypeParser do
135
145
 
136
146
  context 'with scope context and loader' do
137
147
  let!(:scope) { {} }
148
+ let(:loader) { Object.new }
138
149
 
139
150
  before :each do
140
- loader = mock
141
- loader.stubs(:load).returns nil
142
- Puppet::Pops::Adapters::LoaderAdapter.expects(:loader_for_model_object).with(instance_of(Puppet::Pops::Model::QualifiedReference), scope).at_most_once.returns loader
151
+ Adapters::LoaderAdapter.expects(:loader_for_model_object).with(instance_of(Model::QualifiedReference), scope).at_most_once.returns loader
143
152
  end
144
153
 
145
- it "interprets anything that is not a built in type to be a resource type" do
146
- expect(parser.parse('File', scope)).to be_the_type(types.resource('file'))
154
+ it 'interprets anything that is not found by the loader to be a type reference' do
155
+ loader.expects(:load).with(:type, 'nonesuch').returns nil
156
+ expect(parser.parse('Nonesuch', scope)).to be_the_type(types.type_reference('Nonesuch'))
157
+ end
158
+
159
+ it 'interprets anything that is found by the loader to be what the loader found' do
160
+ loader.expects(:load).with(:type, 'file').returns types.resource('File')
161
+ expect(parser.parse('File', scope)).to be_the_type(types.resource('File'))
147
162
  end
148
163
 
149
164
  it "parses a resource type with title" do
165
+ loader.expects(:load).with(:type, 'file').returns types.resource('File')
150
166
  expect(parser.parse("File['/tmp/foo']", scope)).to be_the_type(types.resource('file', '/tmp/foo'))
151
167
  end
152
168
 
153
169
  it "parses a resource type using 'Resource[type]' form" do
170
+ loader.expects(:load).with(:type, 'file').returns types.resource('File')
154
171
  expect(parser.parse("Resource[File]", scope)).to be_the_type(types.resource('file'))
155
172
  end
156
173
 
157
174
  it "parses a resource type with title using 'Resource[type, title]'" do
175
+ loader.expects(:load).with(:type, 'file').returns nil
158
176
  expect(parser.parse("Resource[File, '/tmp/foo']", scope)).to be_the_type(types.resource('file', '/tmp/foo'))
159
177
  end
178
+
179
+ it "parses a resource type with title using 'Resource[Type[title]]'" do
180
+ loader.expects(:load).with(:type, 'nonesuch').returns nil
181
+ expect(parser.parse("Resource[Nonesuch['fife']]", scope)).to be_the_type(types.resource('nonesuch', 'fife'))
182
+ end
160
183
  end
161
184
 
162
185
  context 'with loader context' do
163
186
  let(:loader) { Puppet::Pops::Loader::BaseLoader.new(nil, "type_parser_unit_test_loader") }
164
187
  before :each do
165
- loader.stubs(:load).returns nil
166
188
  Puppet::Pops::Adapters::LoaderAdapter.expects(:loader_for_model_object).never
167
189
  end
168
190
 
169
- it "interprets anything that is not a built in type to be a resource type" do
191
+ it 'interprets anything that is not found by the loader to be a type reference' do
192
+ loader.expects(:load).with(:type, 'nonesuch').returns nil
193
+ expect(parser.parse('Nonesuch', loader)).to be_the_type(types.type_reference('Nonesuch'))
194
+ end
195
+
196
+ it 'interprets anything that is found by the loader to be what the loader found' do
197
+ loader.expects(:load).with(:type, 'file').returns types.resource('File')
170
198
  expect(parser.parse('File', loader)).to be_the_type(types.resource('file'))
171
199
  end
172
200
 
173
201
  it "parses a resource type with title" do
202
+ loader.expects(:load).with(:type, 'file').returns types.resource('File')
174
203
  expect(parser.parse("File['/tmp/foo']", loader)).to be_the_type(types.resource('file', '/tmp/foo'))
175
204
  end
176
205
 
177
206
  it "parses a resource type using 'Resource[type]' form" do
207
+ loader.expects(:load).with(:type, 'file').returns types.resource('File')
178
208
  expect(parser.parse("Resource[File]", loader)).to be_the_type(types.resource('file'))
179
209
  end
180
210
 
181
211
  it "parses a resource type with title using 'Resource[type, title]'" do
212
+ loader.expects(:load).with(:type, 'file').returns types.resource('File')
182
213
  expect(parser.parse("Resource[File, '/tmp/foo']", loader)).to be_the_type(types.resource('file', '/tmp/foo'))
183
214
  end
184
215
  end
@@ -189,7 +220,7 @@ describe Puppet::Pops::Types::TypeParser do
189
220
  end
190
221
 
191
222
  it "interprets anything that is not a built in type with parameterers to be type reference with parameters" do
192
- expect(parser.parse("File['/tmp/foo']")).to eq(types.type_reference('File', ['/tmp/foo']))
223
+ expect(parser.parse("File['/tmp/foo']")).to eq(types.type_reference("File['/tmp/foo']"))
193
224
  end
194
225
  end
195
226
 
@@ -251,11 +282,17 @@ describe Puppet::Pops::Types::TypeParser do
251
282
  t = parser.parse("Callable[0,1]")
252
283
  expect(t).to be_the_type(types.callable(0,1))
253
284
  # Contains a Unit type to indicate "called with what you accept"
254
- expect(t.param_types.types[0]).to be_the_type(Puppet::Pops::Types::PUnitType.new())
285
+ expect(t.param_types.types[0]).to be_the_type(PUnitType.new())
286
+ end
287
+
288
+ it 'parses all known literals' do
289
+ t = parser.parse('Nonesuch[{a=>undef,b=>true,c=>false,d=>default,e=>"string",f=>0,g=>1.0,h=>[1,2,3]}]')
290
+ expect(t).to be_a(PTypeReferenceType)
291
+ expect(t.type_string).to eql('Nonesuch[{a=>undef,b=>true,c=>false,d=>default,e=>"string",f=>0,g=>1.0,h=>[1,2,3]}]')
255
292
  end
256
293
 
257
294
  matcher :be_the_type do |type|
258
- calc = Puppet::Pops::Types::TypeCalculator.new
295
+ calc = TypeCalculator.new
259
296
 
260
297
  match do |actual|
261
298
  calc.assignable?(actual, type) && calc.assignable?(type, actual)
@@ -283,6 +320,8 @@ describe Puppet::Pops::Types::TypeParser do
283
320
  end
284
321
 
285
322
  def the_type_spec_for(type)
286
- Puppet::Pops::Types::TypeFormatter.string(type)
323
+ TypeFormatter.string(type)
287
324
  end
288
325
  end
326
+ end
327
+ end
@@ -5,6 +5,8 @@ require 'puppet_spec/compiler'
5
5
  module Puppet::Pops
6
6
  module Types
7
7
  describe 'Puppet Type System' do
8
+ include PuppetSpec::Compiler
9
+
8
10
  let(:tf) { TypeFactory }
9
11
  context 'Integer type' do
10
12
  let!(:a) { tf.range(10, 20) }
@@ -152,8 +154,6 @@ describe 'Puppet Type System' do
152
154
  end
153
155
 
154
156
  context 'Iterable type' do
155
- include PuppetSpec::Compiler
156
-
157
157
  it 'can be parameterized with element type' do
158
158
  code = <<-CODE
159
159
  function foo(Iterable[String] $x) {
@@ -168,8 +168,6 @@ describe 'Puppet Type System' do
168
168
  end
169
169
 
170
170
  context 'Iterator type' do
171
- include PuppetSpec::Compiler
172
-
173
171
  let!(:iterint) { tf.iterator(tf.integer) }
174
172
 
175
173
  context 'when testing instance?' do
@@ -216,8 +214,6 @@ describe 'Puppet Type System' do
216
214
  end
217
215
 
218
216
  context 'Collection type' do
219
- include PuppetSpec::Compiler
220
-
221
217
  it 'can be parameterized with a range' do
222
218
  code = <<-CODE
223
219
  notice(Collection[5, default] == Collection[5])
@@ -335,9 +331,22 @@ describe 'Puppet Type System' do
335
331
  end
336
332
  end
337
333
 
338
- context 'Type aliases' do
339
- include PuppetSpec::Compiler
334
+ context 'Runtime type' do
335
+ it 'can be created with a runtime and a runtime type name' do
336
+ expect(tf.runtime('ruby', 'Hash').to_s).to eq("Runtime[ruby, 'Hash']")
337
+ end
340
338
 
339
+ it 'can be created with a runtime and, puppet name pattern, and runtime replacement' do
340
+ expect(tf.runtime('ruby', [/^MyPackage::(.*)$/, 'MyModule::\1']).to_s).to eq("Runtime[ruby, [/^MyPackage::(.*)$/, 'MyModule::\\1']]")
341
+ end
342
+
343
+ it 'will map a Puppet name to a runtime type' do
344
+ t = tf.runtime('ruby', [/^MyPackage::(.*)$/, 'MyModule::\1'])
345
+ expect(t.from_puppet_name('MyPackage::MyType').to_s).to eq("Runtime[ruby, 'MyModule::MyType']")
346
+ end
347
+ end
348
+
349
+ context 'Type aliases' do
341
350
  it 'will resolve nested objects using self recursion' do
342
351
  code = <<-CODE
343
352
  type Tree = Hash[String,Variant[String,Tree]]
@@ -450,7 +459,103 @@ describe 'Puppet Type System' do
450
459
  CODE
451
460
  expect(eval_and_collect_notices(code)).to eq(['true', 'true', 'false'])
452
461
  end
462
+
463
+ it 'will not allow dynamic constructs in type definition' do
464
+ code = <<-CODE
465
+ type Foo = Enum[$facts[os][family]]
466
+ notice(Foo)
467
+ CODE
468
+ expect{ eval_and_collect_notices(code) }.to raise_error(Puppet::Error,
469
+ /The expression <\$facts\[os\]\[family\]> is not a valid type specification/)
470
+ end
453
471
  end
472
+
473
+ context 'Type mappings' do
474
+ it 'can register a singe type mapping' do
475
+ source = <<-CODE
476
+ type MyModule::ImplementationRegistry = Object[{}]
477
+ type Runtime[ruby, 'Puppet::Pops::Types::ImplementationRegistry'] = MyModule::ImplementationRegistry
478
+ notice(true)
479
+ CODE
480
+ collect_notices(source) do |compiler|
481
+ compiler.compile do |catalog|
482
+ type = Loaders.implementation_registry.type_for_module(ImplementationRegistry)
483
+ expect(type).to be_a(PObjectType)
484
+ expect(type.name).to eql('MyModule::ImplementationRegistry')
485
+ catalog
486
+ end
487
+ end
488
+ end
489
+
490
+ it 'can register a regexp based mapping' do
491
+ source = <<-CODE
492
+ type MyModule::TypeMismatchDescriber = Object[{}]
493
+ type Runtime[ruby, [/^Puppet::Pops::Types::(\\w+)$/, 'MyModule::\\1']] = [/^MyModule::(\\w+)$/, 'Puppet::Pops::Types::\\1']
494
+ notice(true)
495
+ CODE
496
+ collect_notices(source) do |compiler|
497
+ compiler.compile do |catalog|
498
+ type = Loaders.implementation_registry.type_for_module(TypeMismatchDescriber)
499
+ expect(type).to be_a(PObjectType)
500
+ expect(type.name).to eql('MyModule::TypeMismatchDescriber')
501
+ catalog
502
+ end
503
+ end
504
+ end
505
+
506
+ it 'a type mapping affects type inference' do
507
+ source = <<-CODE
508
+ type MyModule::ImplementationRegistry = Object[{}]
509
+ type Runtime[ruby, 'Puppet::Pops::Types::ImplementationRegistry'] = MyModule::ImplementationRegistry
510
+ notice(true)
511
+ CODE
512
+ collect_notices(source) do |compiler|
513
+ compiler.compile do |catalog|
514
+ type = TypeCalculator.singleton.infer(Loaders.implementation_registry)
515
+ expect(type).to be_a(PObjectType)
516
+ expect(type.name).to eql('MyModule::ImplementationRegistry')
517
+ catalog
518
+ end
519
+ end
520
+ end
521
+ end
522
+
523
+ context 'When attempting to redefine a built in type' do
524
+ it 'such as Integer, an error is raised' do
525
+ code = <<-CODE
526
+ type Integer = String
527
+ notice 'hello' =~ Integer
528
+ CODE
529
+ expect{ eval_and_collect_notices(code) }.to raise_error(/Attempt to redefine entity 'type\/integer'. Originally set by Puppet-Type-System\/Static-Loader/)
530
+ end
531
+ end
532
+
533
+ context 'instantiation via new_function is supported by' do
534
+ let(:loader) { Loader::BaseLoader.new(nil, "types_unit_test_loader") }
535
+ it 'Integer' do
536
+ func_class = tf.integer.new_function(loader)
537
+ expect(func_class).to be_a(Class)
538
+ expect(func_class.superclass).to be(Puppet::Functions::Function)
539
+ end
540
+
541
+ it 'Optional[Integer]' do
542
+ func_class = tf.optional(tf.integer).new_function(loader)
543
+ expect(func_class).to be_a(Class)
544
+ expect(func_class.superclass).to be(Puppet::Functions::Function)
545
+ end
546
+ end
547
+
548
+ context 'instantiation via new_function is not supported by' do
549
+ let(:loader) { Loader::BaseLoader.new(nil, "types_unit_test_loader") }
550
+
551
+ it 'Any, Scalar, Collection' do
552
+ [tf.any, tf.scalar, tf.collection ].each do |t|
553
+ expect { t.new_function(loader)
554
+ }.to raise_error(ArgumentError, /Creation of new instance of type '#{t.to_s}' is not supported/)
555
+ end
556
+ end
557
+ end
558
+
454
559
  end
455
560
  end
456
561
  end
@@ -2,9 +2,7 @@
2
2
  require 'spec_helper'
3
3
  require 'puppet/pops'
4
4
  require 'puppet_spec/pops'
5
-
6
- # relative to this spec file (./) does not work as this file is loaded by rspec
7
- require File.join(File.dirname(__FILE__), '../parser/parser_rspec_helper')
5
+ require_relative '../parser/parser_rspec_helper'
8
6
 
9
7
  describe "validating 4x" do
10
8
  include ParserRspecHelper
@@ -34,6 +32,45 @@ describe "validating 4x" do
34
32
  expect(validate(fqn('::_aa').var())).to_not have_issue(Puppet::Pops::Issues::ILLEGAL_VAR_NAME)
35
33
  end
36
34
 
35
+ context 'with the default settings for --strict' do
36
+ it 'produces a warning for duplicate keyes in a literal hash' do
37
+ acceptor = validate(parse('{ a => 1, a => 2 }'))
38
+ expect(acceptor.warning_count).to eql(1)
39
+ expect(acceptor.error_count).to eql(0)
40
+ expect(acceptor).to have_issue(Puppet::Pops::Issues::DUPLICATE_KEY)
41
+ end
42
+ end
43
+
44
+ context 'with --strict set to warning' do
45
+ before(:each) { Puppet[:strict] = :warning }
46
+ it 'produces a warning for duplicate keyes in a literal hash' do
47
+ acceptor = validate(parse('{ a => 1, a => 2 }'))
48
+ expect(acceptor.warning_count).to eql(1)
49
+ expect(acceptor.error_count).to eql(0)
50
+ expect(acceptor).to have_issue(Puppet::Pops::Issues::DUPLICATE_KEY)
51
+ end
52
+ end
53
+
54
+ context 'with --strict set to error' do
55
+ before(:each) { Puppet[:strict] = :error }
56
+ it 'produces an error for duplicate keyes in a literal hash' do
57
+ acceptor = validate(parse('{ a => 1, a => 2 }'))
58
+ expect(acceptor.warning_count).to eql(0)
59
+ expect(acceptor.error_count).to eql(1)
60
+ expect(acceptor).to have_issue(Puppet::Pops::Issues::DUPLICATE_KEY)
61
+ end
62
+ end
63
+
64
+ context 'with --strict set to off' do
65
+ before(:each) { Puppet[:strict] = :off }
66
+ it 'does not produce an error or warning for duplicate keyes in a literal hash' do
67
+ acceptor = validate(parse('{ a => 1, a => 2 }'))
68
+ expect(acceptor.warning_count).to eql(0)
69
+ expect(acceptor.error_count).to eql(0)
70
+ expect(acceptor).to_not have_issue(Puppet::Pops::Issues::DUPLICATE_KEY)
71
+ end
72
+ end
73
+
37
74
  context 'for non productive expressions' do
38
75
  [ '1',
39
76
  '3.14',
@@ -385,16 +422,53 @@ describe "validating 4x" do
385
422
  expect(validate(parse(source))).to have_issue(Puppet::Pops::Issues::ILLEGAL_EXPRESSION)
386
423
  end
387
424
  end
388
- end
389
425
 
390
- context "capability annotations" do
391
- before(:each) do
392
- with_app_management(true)
393
- end
426
+ context 'that are type mappings' do
427
+ it 'accepts a valid type mapping expression' do
428
+ source = <<-CODE
429
+ type Runtime[ruby, 'MyModule::MyObject'] = MyPackage::MyObject
430
+ notice(true)
431
+ CODE
432
+ expect(validate(parse(source))).not_to have_any_issues
433
+ end
434
+
435
+ it 'accepts a valid regexp based type mapping expression' do
436
+ source = <<-CODE
437
+ type Runtime[ruby, [/^MyPackage::(\w+)$/, 'MyModule::\1']] = [/^MyModule::(\w+)$/, 'MyPackage::\1']
438
+ notice(true)
439
+ CODE
440
+ expect(validate(parse(source))).not_to have_any_issues
441
+ end
442
+
443
+ it 'raises an error when a regexp based Runtime type is paired with a Puppet Type' do
444
+ source = <<-CODE
445
+ type Runtime[ruby, [/^MyPackage::(\w+)$/, 'MyModule::\1']] = MyPackage::MyObject
446
+ notice(true)
447
+ CODE
448
+ expect(validate(parse(source))).to have_issue(Puppet::Pops::Issues::ILLEGAL_REGEXP_TYPE_MAPPING)
449
+ end
394
450
 
395
- after(:each) do
396
- with_app_management(false)
451
+ it 'raises an error when a singleton Runtime type is paired with replacement pattern' do
452
+ source = <<-CODE
453
+ type Runtime[ruby, 'MyModule::MyObject'] = [/^MyModule::(\w+)$/, 'MyPackage::\1']
454
+ notice(true)
455
+ CODE
456
+ expect(validate(parse(source))).to have_issue(Puppet::Pops::Issues::ILLEGAL_SINGLE_TYPE_MAPPING)
457
+ end
458
+
459
+ it 'raises errors unless LHS is Runtime type' do
460
+ source = <<-CODE
461
+ type Pattern[/^MyPackage::(\w+)$/, 'MyModule::\1'] = [/^MyModule::(\w+)$/, 'MyPackage::\1']
462
+ notice(true)
463
+ CODE
464
+ expect(validate(parse(source))).to have_issue(Puppet::Pops::Issues::UNSUPPORTED_EXPRESSION)
465
+ end
397
466
  end
467
+ end
468
+
469
+ context "capability annotations" do
470
+ before(:each) { Puppet[:app_management] = true }
471
+ after(:each) { Puppet[:app_management] = false }
398
472
 
399
473
  ['produces', 'consumes'].each do |word|
400
474
  it "rejects illegal resource types in #{word} clauses" do