bolt 0.7.0 → 0.8.0

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

Potentially problematic release.


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

Files changed (76) hide show
  1. checksums.yaml +4 -4
  2. data/lib/bolt/cli.rb +65 -28
  3. data/lib/bolt/config.rb +18 -8
  4. data/lib/bolt/executor.rb +21 -6
  5. data/lib/bolt/node.rb +3 -0
  6. data/lib/bolt/node/result.rb +5 -0
  7. data/lib/bolt/node/ssh.rb +81 -25
  8. data/lib/bolt/node/winrm.rb +70 -31
  9. data/lib/bolt/notifier.rb +20 -0
  10. data/lib/bolt/outputter.rb +21 -0
  11. data/lib/bolt/outputter/human.rb +30 -0
  12. data/lib/bolt/outputter/json.rb +51 -0
  13. data/lib/bolt/result.rb +32 -5
  14. data/lib/bolt/version.rb +1 -1
  15. data/vendored/puppet/lib/puppet.rb +4 -5
  16. data/vendored/puppet/lib/puppet/agent.rb +22 -2
  17. data/vendored/puppet/lib/puppet/application/agent.rb +1 -1
  18. data/vendored/puppet/lib/puppet/application/apply.rb +1 -1
  19. data/vendored/puppet/lib/puppet/configurer/downloader_factory.rb +10 -0
  20. data/vendored/puppet/lib/puppet/configurer/plugin_handler.rb +4 -4
  21. data/vendored/puppet/lib/puppet/defaults.rb +21 -2
  22. data/vendored/puppet/lib/puppet/external/nagios/parser.rb +1 -1
  23. data/vendored/puppet/lib/puppet/file_serving/configuration.rb +3 -0
  24. data/vendored/puppet/lib/puppet/file_serving/configuration/parser.rb +2 -0
  25. data/vendored/puppet/lib/puppet/file_serving/mount/locales.rb +35 -0
  26. data/vendored/puppet/lib/puppet/forge.rb +9 -3
  27. data/vendored/puppet/lib/puppet/forge/repository.rb +1 -1
  28. data/vendored/puppet/lib/puppet/functions/file_upload.rb +20 -15
  29. data/vendored/puppet/lib/puppet/functions/new.rb +1 -4
  30. data/vendored/puppet/lib/puppet/functions/run_command.rb +15 -13
  31. data/vendored/puppet/lib/puppet/functions/run_script.rb +27 -14
  32. data/vendored/puppet/lib/puppet/functions/run_task.rb +21 -19
  33. data/vendored/puppet/lib/puppet/gettext/config.rb +86 -28
  34. data/vendored/puppet/lib/puppet/indirector/catalog/compiler.rb +25 -5
  35. data/vendored/puppet/lib/puppet/indirector/file_bucket_file/file.rb +1 -1
  36. data/vendored/puppet/lib/puppet/module.rb +13 -17
  37. data/vendored/puppet/lib/puppet/pops/evaluator/access_operator.rb +20 -21
  38. data/vendored/puppet/lib/puppet/pops/evaluator/compare_operator.rb +3 -3
  39. data/vendored/puppet/lib/puppet/pops/evaluator/evaluator_impl.rb +9 -0
  40. data/vendored/puppet/lib/puppet/pops/loader/static_loader.rb +20 -1
  41. data/vendored/puppet/lib/puppet/pops/loader/task_instantiator.rb +2 -1
  42. data/vendored/puppet/lib/puppet/pops/loaders.rb +6 -41
  43. data/vendored/puppet/lib/puppet/pops/pcore.rb +9 -0
  44. data/vendored/puppet/lib/puppet/pops/serialization/from_data_converter.rb +64 -10
  45. data/vendored/puppet/lib/puppet/pops/serialization/json_path.rb +2 -1
  46. data/vendored/puppet/lib/puppet/pops/types/execution_result.rb +7 -4
  47. data/vendored/puppet/lib/puppet/pops/types/p_binary_type.rb +9 -2
  48. data/vendored/puppet/lib/puppet/pops/types/p_init_type.rb +1 -1
  49. data/vendored/puppet/lib/puppet/pops/types/p_meta_type.rb +4 -0
  50. data/vendored/puppet/lib/puppet/pops/types/p_object_type.rb +81 -4
  51. data/vendored/puppet/lib/puppet/pops/types/p_object_type_extension.rb +213 -0
  52. data/vendored/puppet/lib/puppet/pops/types/p_sem_ver_type.rb +10 -2
  53. data/vendored/puppet/lib/puppet/pops/types/puppet_object.rb +11 -1
  54. data/vendored/puppet/lib/puppet/pops/types/type_calculator.rb +2 -2
  55. data/vendored/puppet/lib/puppet/pops/types/type_factory.rb +16 -6
  56. data/vendored/puppet/lib/puppet/pops/types/type_formatter.rb +22 -14
  57. data/vendored/puppet/lib/puppet/pops/types/type_parser.rb +17 -15
  58. data/vendored/puppet/lib/puppet/pops/types/types.rb +181 -72
  59. data/vendored/puppet/lib/puppet/provider.rb +18 -8
  60. data/vendored/puppet/lib/puppet/provider/package/yum.rb +22 -7
  61. data/vendored/puppet/lib/puppet/provider/service/base.rb +21 -8
  62. data/vendored/puppet/lib/puppet/provider/service/launchd.rb +2 -3
  63. data/vendored/puppet/lib/puppet/provider/user/aix.rb +1 -0
  64. data/vendored/puppet/lib/puppet/provider/user/user_role_add.rb +7 -1
  65. data/vendored/puppet/lib/puppet/provider/user/useradd.rb +3 -2
  66. data/vendored/puppet/lib/puppet/provider/zfs/zfs.rb +5 -1
  67. data/vendored/puppet/lib/puppet/type/exec.rb +5 -4
  68. data/vendored/puppet/lib/puppet/type/macauthorization.rb +1 -1
  69. data/vendored/puppet/lib/puppet/type/user.rb +19 -0
  70. data/vendored/puppet/lib/puppet/util/log/destinations.rb +10 -0
  71. data/vendored/puppet/lib/puppet/util/windows/file.rb +35 -4
  72. data/vendored/puppet/lib/puppet/vendor/semantic_puppet/lib/semantic_puppet.rb +1 -1
  73. data/vendored/puppet/lib/puppet/version.rb +1 -1
  74. data/vendored/puppet/lib/puppet_pal.rb +15 -5
  75. metadata +8 -3
  76. data/vendored/puppet/lib/puppet/pops/types/p_error_type.rb +0 -158
@@ -60,14 +60,14 @@ class PSemVerType < PScalarType
60
60
  local_types do
61
61
  type 'PositiveInteger = Integer[0,default]'
62
62
  type 'SemVerQualifier = Pattern[/\A(?<part>[0-9A-Za-z-]+)(?:\.\g<part>)*\Z/]'
63
- type 'SemVerString = String[1]'
63
+ type "SemVerPattern = Pattern[/\\A#{SemanticPuppet::Version::REGEX_FULL}\\Z/]"
64
64
  type 'SemVerHash = Struct[{major=>PositiveInteger,minor=>PositiveInteger,patch=>PositiveInteger,Optional[prerelease]=>SemVerQualifier,Optional[build]=>SemVerQualifier}]'
65
65
  end
66
66
 
67
67
  # Creates a SemVer from a string as specified by http://semver.org/
68
68
  #
69
69
  dispatch :from_string do
70
- param 'SemVerString', :str
70
+ param 'SemVerPattern', :str
71
71
  end
72
72
 
73
73
  # Creates a SemVer from integers, prerelease, and build arguments
@@ -86,6 +86,10 @@ class PSemVerType < PScalarType
86
86
  param 'SemVerHash', :hash_args
87
87
  end
88
88
 
89
+ argument_mismatch :on_error do
90
+ param 'String', :str
91
+ end
92
+
89
93
  def from_string(str)
90
94
  SemanticPuppet::Version.parse(str)
91
95
  end
@@ -97,6 +101,10 @@ class PSemVerType < PScalarType
97
101
  def from_hash(hash)
98
102
  SemanticPuppet::Version.new(hash['major'], hash['minor'], hash['patch'], hash['prerelease'], hash['build'])
99
103
  end
104
+
105
+ def on_error(str)
106
+ _("The string '%{str}' cannot be converted to a SemVer") % { str: str }
107
+ end
100
108
  end
101
109
  end
102
110
 
@@ -9,7 +9,17 @@ module PuppetObject
9
9
  #
10
10
  # @return [PObjectType] the type
11
11
  def _pcore_type
12
- self.class._pcore_type
12
+ t = self.class._pcore_type
13
+ if t.parameterized?
14
+ unless instance_variable_defined?(:@_cached_ptype)
15
+ # Create a parameterized type based on the values of this instance that
16
+ # contains a parameter value for each type parameter that matches an
17
+ # attribute by name and type of value
18
+ @_cached_ptype = PObjectTypeExtension.create(t, self)
19
+ end
20
+ t = @_cached_ptype
21
+ end
22
+ t
13
23
  end
14
24
 
15
25
  def _pcore_all_contents(path, &block)
@@ -614,12 +614,12 @@ class TypeCalculator
614
614
 
615
615
  # @api private
616
616
  def infer_TrueClass(o)
617
- PBooleanType::DEFAULT
617
+ PBooleanType::TRUE
618
618
  end
619
619
 
620
620
  # @api private
621
621
  def infer_FalseClass(o)
622
- PBooleanType::DEFAULT
622
+ PBooleanType::FALSE
623
623
  end
624
624
 
625
625
  # @api private
@@ -127,7 +127,13 @@ module TypeFactory
127
127
  # @api public
128
128
  #
129
129
  def self.enum(*values)
130
- PEnumType.new(values)
130
+ last = values.last
131
+ case_insensitive = false
132
+ if last == true || last == false
133
+ case_insensitive = last
134
+ values = values[0...-1]
135
+ end
136
+ PEnumType.new(values, case_insensitive)
131
137
  end
132
138
 
133
139
  # Produces the Variant type, optionally with the "one of" types
@@ -227,8 +233,8 @@ module TypeFactory
227
233
  # Produces the Boolean type
228
234
  # @api public
229
235
  #
230
- def self.boolean
231
- PBooleanType::DEFAULT
236
+ def self.boolean(value = nil)
237
+ value.nil? ? PBooleanType::DEFAULT : (value ? PBooleanType::TRUE : PBooleanType::FALSE)
232
238
  end
233
239
 
234
240
  # Produces the Any type
@@ -511,11 +517,15 @@ module TypeFactory
511
517
  inst_type.nil? ? PTypeType::DEFAULT : PTypeType.new(inst_type)
512
518
  end
513
519
 
514
- # Produces a type for Error[K, I]
520
+ # Produces a type for Error
515
521
  # @api public
516
522
  #
517
- def self.error(kind = nil, issue_code = nil)
518
- kind.nil? && issue_code.nil? ? PErrorType::DEFAULT : PErrorType.new(kind, issue_code)
523
+ def self.error
524
+ @error_t ||= TypeParser.singleton.parse('Error', Loaders.static_loader)
525
+ end
526
+
527
+ def self.target
528
+ @target_t ||= TypeParser.singleton.parse('Target')
519
529
  end
520
530
 
521
531
  # Produce a type corresponding to the class of given unless given is a
@@ -149,7 +149,9 @@ class TypeFormatter
149
149
  def string_PDefaultType(_) ; @bld << 'Default' ; end
150
150
 
151
151
  # @api private
152
- def string_PBooleanType(_) ; @bld << 'Boolean' ; end
152
+ def string_PBooleanType(t)
153
+ append_array('Boolean', t.value.nil?) { append_string(t.value) }
154
+ end
153
155
 
154
156
  # @api private
155
157
  def string_PScalarType(_) ; @bld << 'Scalar' ; end
@@ -213,7 +215,13 @@ class TypeFormatter
213
215
 
214
216
  # @api private
215
217
  def string_PEnumType(t)
216
- append_array('Enum', t.values.empty?) { append_strings(t.values) }
218
+ append_array('Enum', t.values.empty?) do
219
+ append_strings(t.values)
220
+ if t.case_insensitive?
221
+ @bld << COMMA_SEP
222
+ append_string(true)
223
+ end
224
+ end
217
225
  end
218
226
 
219
227
  # @api private
@@ -322,17 +330,6 @@ class TypeFormatter
322
330
  append_array('Pattern', t.patterns.empty?) { append_strings(t.patterns.map(&:regexp)) }
323
331
  end
324
332
 
325
- # @api private
326
- def string_PErrorType(t)
327
- append_array('Error', t.kind.nil? && t.issue_code.nil?) do
328
- t.kind.nil? ? append_default : append_error_param(t.kind)
329
- unless t.issue_code.nil?
330
- @bld << COMMA_SEP
331
- append_error_param(t.issue_code)
332
- end
333
- end
334
- end
335
-
336
333
  def append_error_param(ep)
337
334
  case ep
338
335
  when PStringType
@@ -490,6 +487,17 @@ class TypeFormatter
490
487
  end
491
488
  end
492
489
 
490
+ def string_PObjectTypeExtension(t)
491
+ append_array(@type_set ? @type_set.name_for(t, t.name) : t.name, false) do
492
+ ips = t.init_parameters
493
+ if ips.is_a?(Array)
494
+ append_strings(ips)
495
+ else
496
+ append_string(ips)
497
+ end
498
+ end
499
+ end
500
+
493
501
  # @api private
494
502
  def string_PSensitiveType(t)
495
503
  append_array('Sensitive', PAnyType::DEFAULT == t.type) { append_string(t.type) }
@@ -569,7 +577,7 @@ class TypeFormatter
569
577
  end
570
578
 
571
579
  # @api private
572
- def string_NilClass(t) ; @bld << (@ruby ? 'nil' : '?') ; end
580
+ def string_NilClass(t) ; @bld << (@ruby ? 'nil' : 'undef') ; end
573
581
 
574
582
  # @api private
575
583
  def string_Numeric(t) ; @bld << t.to_s ; end
@@ -201,7 +201,6 @@ class TypeParser
201
201
  'semverrange' => TypeFactory.sem_ver_range,
202
202
  'timestamp' => TypeFactory.timestamp,
203
203
  'timespan' => TypeFactory.timespan,
204
- 'error' => TypeFactory.error
205
204
  }.freeze
206
205
  end
207
206
 
@@ -341,27 +340,22 @@ class TypeParser
341
340
  TypeFactory.regexp(parameters[0])
342
341
 
343
342
  when 'enum'
344
- # 1..m parameters being strings
343
+ # 1..m parameters being string
344
+ last = parameters.last
345
+ case_insensitive = false
346
+ if last == true || last == false
347
+ parameters = parameters[0...-1]
348
+ case_insensitive = last
349
+ end
345
350
  raise_invalid_parameters_error('Enum', '1 or more', parameters.size) unless parameters.size >= 1
346
351
  parameters.each { |p| raise Puppet::ParseError, 'Enum parameters must be identifiers or strings' unless p.is_a?(String) }
347
- TypeFactory.enum(*parameters)
352
+ PEnumType.new(parameters, case_insensitive)
348
353
 
349
354
  when 'pattern'
350
355
  # 1..m parameters being strings or regular expressions
351
356
  raise_invalid_parameters_error('Pattern', '1 or more', parameters.size) unless parameters.size >= 1
352
357
  TypeFactory.pattern(*parameters)
353
358
 
354
- when 'error'
355
- # 1 - 2 parameters where both are string, regexp, or type
356
- case parameters.size
357
- when 1, 2
358
- pt = PErrorType::TYPE_ERROR_PARAM
359
- parameters.each { |p| raise Puppet::ParseError, "Error parameters must be ${pt}" unless pt.instance?(p) }
360
- TypeFactory.error(*parameters)
361
- else
362
- raise_invalid_parameters_error('Error', '1 - 2', parameters.size)
363
- end
364
-
365
359
  when 'variant'
366
360
  # 1..m parameters being strings or regular expressions
367
361
  raise_invalid_parameters_error('Variant', '1 or more', parameters.size) unless parameters.size >= 1
@@ -405,6 +399,12 @@ class TypeParser
405
399
  raise_invalid_type_specification_error(ast) unless h.is_a?(Hash)
406
400
  TypeFactory.struct(h)
407
401
 
402
+ when 'boolean'
403
+ raise_invalid_parameters_error('Boolean', '1', parameters.size) unless parameters.size == 1
404
+ p = parameters[0]
405
+ raise Puppet::ParseError, 'Boolean parameter must be true or false' unless p == true || p == false
406
+ TypeFactory.boolean(p)
407
+
408
408
  when 'integer'
409
409
  if parameters.size == 1
410
410
  case parameters[0]
@@ -497,7 +497,7 @@ class TypeParser
497
497
  assert_type(ast, param) unless param.is_a?(String)
498
498
  TypeFactory.optional(param)
499
499
 
500
- when 'any', 'data', 'catalogentry', 'boolean', 'scalar', 'undef', 'numeric', 'default', 'semverrange'
500
+ when 'any', 'data', 'catalogentry', 'scalar', 'undef', 'numeric', 'default', 'semverrange'
501
501
  raise_unparameterized_type_error(qref)
502
502
 
503
503
  when 'notundef'
@@ -548,6 +548,8 @@ class TypeParser
548
548
  elsif type.is_a?(PResourceType)
549
549
  raise_invalid_parameters_error(qref.cased_value, 1, parameters.size) unless parameters.size == 1
550
550
  TypeFactory.resource(type.type_name, parameters[0])
551
+ elsif type.is_a?(PObjectType)
552
+ PObjectTypeExtension.create(type, parameters)
551
553
  else
552
554
  # Must be a type alias. They can't use parameters (yet)
553
555
  raise_unparameterized_type_error(qref)
@@ -482,7 +482,7 @@ class PTypeType < PTypeWithContainedType
482
482
  def self.new_function(type)
483
483
  @new_function ||= Puppet::Functions.create_loaded_function(:new_type, type.loader) do
484
484
  dispatch :from_string do
485
- param 'String', :type_string
485
+ param 'String[1]', :type_string
486
486
  end
487
487
 
488
488
  def from_string(type_string)
@@ -756,13 +756,20 @@ end
756
756
  #
757
757
  class PEnumType < PScalarDataType
758
758
  def self.register_ptype(loader, ir)
759
- create_ptype(loader, ir, 'ScalarDataType', 'values' => PArrayType.new(PStringType::NON_EMPTY))
759
+ create_ptype(loader, ir, 'ScalarDataType',
760
+ 'values' => PArrayType.new(PStringType::NON_EMPTY),
761
+ 'case_insensitive' => { 'type' => PBooleanType::DEFAULT, 'value' => false })
760
762
  end
761
763
 
762
- attr_reader :values
764
+ attr_reader :values, :case_insensitive
763
765
 
764
- def initialize(values)
766
+ def initialize(values, case_insensitive = false)
765
767
  @values = values.uniq.sort.freeze
768
+ @case_insensitive = case_insensitive
769
+ end
770
+
771
+ def case_insensitive?
772
+ @case_insensitive
766
773
  end
767
774
 
768
775
  # Returns Enumerator if no block is given, otherwise, calls the given
@@ -792,15 +799,19 @@ class PEnumType < PScalarDataType
792
799
  end
793
800
 
794
801
  def hash
795
- @values.hash
802
+ @values.hash ^ @case_insensitive.hash
796
803
  end
797
804
 
798
805
  def eql?(o)
799
- self.class == o.class && @values == o.values
806
+ self.class == o.class && @values == o.values && @case_insensitive == o.case_insensitive?
800
807
  end
801
808
 
802
809
  def instance?(o, guard = nil)
803
- o.is_a?(String) && @values.any? { |p| p == o }
810
+ if o.is_a?(String)
811
+ @case_insensitive ? @values.any? { |p| p.casecmp(o) == 0 } : @values.any? { |p| p == o }
812
+ else
813
+ false
814
+ end
804
815
  end
805
816
 
806
817
  DEFAULT = PEnumType.new(EMPTY_ARRAY)
@@ -819,13 +830,26 @@ class PEnumType < PScalarDataType
819
830
  # if the contained string is found in the set of enums
820
831
  instance?(o.value, guard)
821
832
  when PEnumType
822
- !o.values.empty? && o.values.all? { |s| instance?(s, guard) }
833
+ !o.values.empty? && (case_insensitive? || !o.case_insensitive?) && o.values.all? { |s| instance?(s, guard) }
823
834
  else
824
835
  false
825
836
  end
826
837
  end
827
838
  end
828
839
 
840
+ INTEGER_HEX = '(?:0[xX][0-9A-Fa-f]+)'
841
+ INTEGER_OCT = '(?:0[0-7]+)'
842
+ INTEGER_BIN = '(?:0[bB][01]+)'
843
+ INTEGER_DEC = '(?:0|[1-9]\d*)'
844
+ SIGN_PREFIX = '[+-]?\s*'
845
+
846
+ OPTIONAL_FRACTION = '(?:\.\d+)?'
847
+ OPTIONAL_EXPONENT = '(?:[eE]-?\d+)?'
848
+ FLOAT_DEC = '(?:' + INTEGER_DEC + OPTIONAL_FRACTION + OPTIONAL_EXPONENT + ')'
849
+
850
+ INTEGER_PATTERN = '\A' + SIGN_PREFIX + '(?:' + INTEGER_DEC + '|' + INTEGER_HEX + '|' + INTEGER_OCT + '|' + INTEGER_BIN + ')\z'
851
+ FLOAT_PATTERN = '\A' + SIGN_PREFIX + '(?:' + FLOAT_DEC + '|' + INTEGER_HEX + '|' + INTEGER_OCT + '|' + INTEGER_BIN + ')\z'
852
+
829
853
  # @api public
830
854
  #
831
855
  class PNumericType < PScalarDataType
@@ -839,7 +863,7 @@ class PNumericType < PScalarDataType
839
863
  def self.new_function(type)
840
864
  @new_function ||= Puppet::Functions.create_loaded_function(:new_numeric, type.loader) do
841
865
  local_types do
842
- type 'Convertible = Variant[Undef, Integer, Float, Boolean, String, Timespan, Timestamp]'
866
+ type "Convertible = Variant[Integer, Float, Boolean, Pattern[/#{FLOAT_PATTERN}/], Timespan, Timestamp]"
843
867
  type 'NamedArgs = Struct[{from => Convertible, Optional[abs] => Boolean}]'
844
868
  end
845
869
 
@@ -852,6 +876,11 @@ class PNumericType < PScalarDataType
852
876
  param 'NamedArgs', :hash_args
853
877
  end
854
878
 
879
+ argument_mismatch :on_error do
880
+ param 'Any', :from
881
+ optional_param 'Boolean', :abs
882
+ end
883
+
855
884
  def from_args(from, abs = false)
856
885
  result = from_convertible(from)
857
886
  abs ? result.abs : result
@@ -863,8 +892,6 @@ class PNumericType < PScalarDataType
863
892
 
864
893
  def from_convertible(from)
865
894
  case from
866
- when NilClass
867
- throw :undefined_value
868
895
  when Float
869
896
  from
870
897
  when Integer
@@ -875,7 +902,7 @@ class PNumericType < PScalarDataType
875
902
  1
876
903
  when FalseClass
877
904
  0
878
- when String
905
+ else
879
906
  begin
880
907
  if from[0] == '0' && (from[1].downcase == 'b' || from[1].downcase == 'x')
881
908
  Integer(from)
@@ -887,9 +914,15 @@ class PNumericType < PScalarDataType
887
914
  rescue ArgumentError => e
888
915
  raise TypeConversionError.new(e.message)
889
916
  end
917
+ end
918
+ end
919
+
920
+ def on_error(from, abs = false)
921
+ if from.is_a?(String)
922
+ _("The string '%{str}' cannot be converted to Numeric") % { str: from }
890
923
  else
891
- t = Puppet::Pops::Types::TypeCalculator.singleton.infer(from).generalize
892
- raise TypeConversionError.new("Value of type '#{t}' cannot be converted to Numeric")
924
+ t = TypeCalculator.singleton.infer(from).generalize
925
+ _("Value of type %{type} cannot be converted to Numeric") % { type: t }
893
926
  end
894
927
  end
895
928
  end
@@ -945,7 +978,7 @@ class PNumericType < PScalarDataType
945
978
  end
946
979
 
947
980
  def instance?(o, guard = nil)
948
- o.is_a?(Numeric) && o >= @from && o <= @to
981
+ (o.is_a?(Float) || o.is_a?(Integer)) && o >= @from && o <= @to
949
982
  end
950
983
 
951
984
  def unbounded?
@@ -1050,7 +1083,7 @@ class PIntegerType < PNumericType
1050
1083
  @@new_function ||= Puppet::Functions.create_loaded_function(:new, loader) do
1051
1084
  local_types do
1052
1085
  type 'Radix = Variant[Default, Integer[2,2], Integer[8,8], Integer[10,10], Integer[16,16]]'
1053
- type 'Convertible = Variant[Undef, Numeric, Boolean, String, Timespan, Timestamp]'
1086
+ type "Convertible = Variant[Numeric, Boolean, Pattern[/#{INTEGER_PATTERN}/], Timespan, Timestamp]"
1054
1087
  type 'NamedArgs = Struct[{from => Convertible, Optional[radix] => Radix, Optional[abs] => Boolean}]'
1055
1088
  end
1056
1089
 
@@ -1064,6 +1097,16 @@ class PIntegerType < PNumericType
1064
1097
  param 'NamedArgs', :hash_args
1065
1098
  end
1066
1099
 
1100
+ argument_mismatch :on_error_hash do
1101
+ param 'Hash', :hash_args
1102
+ end
1103
+
1104
+ argument_mismatch :on_error do
1105
+ param 'Any', :from
1106
+ optional_param 'Integer', :radix
1107
+ optional_param 'Boolean', :abs
1108
+ end
1109
+
1067
1110
  def from_args(from, radix = :default, abs = false)
1068
1111
  result = from_convertible(from, radix)
1069
1112
  abs ? result.abs : result
@@ -1075,8 +1118,6 @@ class PIntegerType < PNumericType
1075
1118
 
1076
1119
  def from_convertible(from, radix)
1077
1120
  case from
1078
- when NilClass
1079
- throw :undefined_value
1080
1121
  when Float, Time::TimeData
1081
1122
  from.to_i
1082
1123
  when Integer
@@ -1085,9 +1126,9 @@ class PIntegerType < PNumericType
1085
1126
  1
1086
1127
  when FalseClass
1087
1128
  0
1088
- when String
1129
+ else
1089
1130
  begin
1090
- radix == :default ? Integer(from) : Integer(from, assert_radix(radix))
1131
+ radix == :default ? Integer(from) : Integer(from, radix)
1091
1132
  rescue TypeError => e
1092
1133
  raise TypeConversionError.new(e.message)
1093
1134
  rescue ArgumentError => e
@@ -1103,17 +1144,34 @@ class PIntegerType < PNumericType
1103
1144
  end
1104
1145
  raise TypeConversionError.new(e.message)
1105
1146
  end
1147
+ end
1148
+ end
1149
+
1150
+ def on_error_hash(args_hash)
1151
+ if args_hash.include?('from')
1152
+ from = args_hash['from']
1153
+ return on_error(from) unless loader.load(:type, 'convertible').instance?(from)
1154
+ end
1155
+ radix = args_hash['radix']
1156
+ assert_radix(radix) unless radix.nil? || radix == :default
1157
+ TypeAsserter.assert_instance_of('Integer.new', loader.load(:type, 'namedargs'), args_hash)
1158
+ end
1159
+
1160
+ def on_error(from, radix = :default, abs = nil)
1161
+ assert_radix(radix) unless radix == :default
1162
+ if from.is_a?(String)
1163
+ _("The string '%{str}' cannot be converted to Integer") % { str: from }
1106
1164
  else
1107
- t = Puppet::Pops::Types::TypeCalculator.singleton.infer(from).generalize
1108
- raise TypeConversionError.new("Value of type '#{t}' cannot be converted to an Integer")
1165
+ t = TypeCalculator.singleton.infer(from).generalize
1166
+ _("Value of type %{type} cannot be converted to Integer") % { type: t }
1109
1167
  end
1110
1168
  end
1111
1169
 
1112
1170
  def assert_radix(radix)
1113
1171
  case radix
1114
- when 2, 8, 10, 16, :default
1172
+ when 2, 8, 10, 16
1115
1173
  else
1116
- raise ArgumentError.new("Illegal radix: '#{radix}', expected 2, 8, 10, 16, or default")
1174
+ raise ArgumentError.new(_("Illegal radix: %{radix}, expected 2, 8, 10, 16, or default") % { radix: radix })
1117
1175
  end
1118
1176
  radix
1119
1177
  end
@@ -1160,7 +1218,7 @@ class PFloatType < PNumericType
1160
1218
  def self.new_function(type)
1161
1219
  @new_function ||= Puppet::Functions.create_loaded_function(:new_float, type.loader) do
1162
1220
  local_types do
1163
- type 'Convertible = Variant[Undef, Numeric, Boolean, String, Timespan, Timestamp]'
1221
+ type "Convertible = Variant[Numeric, Boolean, Pattern[/#{FLOAT_PATTERN}/], Timespan, Timestamp]"
1164
1222
  type 'NamedArgs = Struct[{from => Convertible, Optional[abs] => Boolean}]'
1165
1223
  end
1166
1224
 
@@ -1173,6 +1231,11 @@ class PFloatType < PNumericType
1173
1231
  param 'NamedArgs', :hash_args
1174
1232
  end
1175
1233
 
1234
+ argument_mismatch :on_error do
1235
+ param 'Any', :from
1236
+ optional_param 'Boolean', :abs
1237
+ end
1238
+
1176
1239
  def from_args(from, abs = false)
1177
1240
  result = from_convertible(from)
1178
1241
  abs ? result.abs : result
@@ -1184,8 +1247,6 @@ class PFloatType < PNumericType
1184
1247
 
1185
1248
  def from_convertible(from)
1186
1249
  case from
1187
- when NilClass
1188
- throw :undefined_value
1189
1250
  when Float
1190
1251
  from
1191
1252
  when Integer
@@ -1196,7 +1257,7 @@ class PFloatType < PNumericType
1196
1257
  1.0
1197
1258
  when FalseClass
1198
1259
  0.0
1199
- when String
1260
+ else
1200
1261
  begin
1201
1262
  # support a binary as float
1202
1263
  if from[0] == '0' && from[1].downcase == 'b'
@@ -1218,9 +1279,15 @@ class PFloatType < PNumericType
1218
1279
  end
1219
1280
  raise TypeConversionError.new(e.message)
1220
1281
  end
1282
+ end
1283
+ end
1284
+
1285
+ def on_error(from, _ = false)
1286
+ if from.is_a?(String)
1287
+ _("The string '%{str}' cannot be converted to Float") % { str: from }
1221
1288
  else
1222
- t = Puppet::Pops::Types::TypeCalculator.singleton.infer(from).generalize
1223
- raise TypeConversionError.new("Value of type '#{t}' cannot be converted to Float")
1289
+ t = TypeCalculator.singleton.infer(from).generalize
1290
+ _("Value of type %{type} cannot be converted to Float") % { type: t }
1224
1291
  end
1225
1292
  end
1226
1293
  end
@@ -1577,7 +1644,7 @@ class PStringType < PScalarDataType
1577
1644
  # Must match exactly when value is a string
1578
1645
  @size_type_or_value.nil? || @size_type_or_value == o.size_type_or_value
1579
1646
  when PEnumType
1580
- @size_type_or_value.nil? ? true : o.values.size == 1 && @size_type_or_value == o.values[0]
1647
+ @size_type_or_value.nil? ? true : o.values.size == 1 && !o.case_insensitive? && o.values[0]
1581
1648
  when PPatternType
1582
1649
  @size_type_or_value.nil?
1583
1650
  else
@@ -1786,46 +1853,73 @@ class PBooleanType < PScalarDataType
1786
1853
  create_ptype(loader, ir, 'ScalarDataType')
1787
1854
  end
1788
1855
 
1856
+ attr_reader :value
1857
+
1858
+ def initialize(value = nil)
1859
+ @value = value
1860
+ end
1861
+
1862
+ def eql?(o)
1863
+ o.is_a?(PBooleanType) && @value == o.value
1864
+ end
1865
+
1866
+ def generalize
1867
+ PBooleanType::DEFAULT
1868
+ end
1869
+
1870
+ def hash
1871
+ 31 ^ @value.hash
1872
+ end
1873
+
1789
1874
  def instance?(o, guard = nil)
1790
- o == true || o == false
1875
+ (o == true || o == false) && (@value.nil? || value == o)
1791
1876
  end
1792
1877
 
1793
1878
  def self.new_function(type)
1794
1879
  @new_function ||= Puppet::Functions.create_loaded_function(:new_boolean, type.loader) do
1795
1880
  dispatch :from_args do
1796
- param 'Variant[Undef, Integer, Float, Boolean, String]', :from
1881
+ param "Variant[Integer, Float, Boolean, Enum['false','true','yes','no','y','n',true]]", :from
1882
+ end
1883
+
1884
+ argument_mismatch :on_error do
1885
+ param 'Any', :from
1797
1886
  end
1798
1887
 
1799
1888
  def from_args(from)
1800
1889
  from = from.downcase if from.is_a?(String)
1801
1890
  case from
1802
- when NilClass
1803
- throw :undefined_value
1804
1891
  when Float
1805
1892
  from != 0.0
1806
1893
  when Integer
1807
1894
  from != 0
1808
- when true, false
1809
- from
1810
- when 'false', 'no', 'n'
1895
+ when false, 'false', 'no', 'n'
1811
1896
  false
1812
- when 'true', 'yes', 'y'
1897
+ else
1813
1898
  true
1899
+ end
1900
+ end
1901
+
1902
+ def on_error(from)
1903
+ if from.is_a?(String)
1904
+ _("The string '%{str}' cannot be converted to Boolean") % { str: from }
1814
1905
  else
1815
- raise TypeConversionError.new("Value '#{from}' of type '#{from.class}' cannot be converted to Boolean")
1906
+ t = TypeCalculator.singleton.infer(from).generalize
1907
+ _("Value of type %{type} cannot be converted to Boolean") % { type: t }
1816
1908
  end
1817
1909
  end
1818
1910
  end
1819
1911
  end
1820
1912
 
1821
1913
  DEFAULT = PBooleanType.new
1914
+ TRUE = PBooleanType.new(true)
1915
+ FALSE = PBooleanType.new(false)
1822
1916
 
1823
1917
  protected
1824
1918
 
1825
1919
  # @api private
1826
1920
  #
1827
1921
  def _assignable?(o, guard)
1828
- o.is_a?(PBooleanType)
1922
+ o.is_a?(PBooleanType) && (@value.nil? || @value == o.value)
1829
1923
  end
1830
1924
  end
1831
1925
 
@@ -2504,41 +2598,43 @@ class PArrayType < PCollectionType
2504
2598
  def self.new_function(type)
2505
2599
  @new_function ||= Puppet::Functions.create_loaded_function(:new_array, type.loader) do
2506
2600
 
2507
- dispatch :from_args do
2508
- param 'Any', :from
2509
- optional_param 'Boolean', :wrap
2601
+ dispatch :to_array do
2602
+ param 'Variant[Array,Hash,Binary,Iterable]', :from
2603
+ optional_param 'Boolean[false]', :wrap
2604
+ end
2605
+
2606
+ dispatch :wrapped do
2607
+ param 'Any', :from
2608
+ param 'Boolean[true]', :wrap
2609
+ end
2610
+
2611
+ argument_mismatch :on_error do
2612
+ param 'Any', :from
2613
+ optional_param 'Boolean', :wrap
2510
2614
  end
2511
2615
 
2512
- def from_args(from, wrap = false)
2616
+ def wrapped(from, _)
2617
+ from.is_a?(Array) ? from : [from]
2618
+ end
2619
+
2620
+ def to_array(from, _ = false)
2513
2621
  case from
2514
- when NilClass
2515
- if wrap
2516
- [nil]
2517
- else
2518
- throw :undefined_value
2519
- end
2520
2622
  when Array
2521
2623
  from
2522
2624
  when Hash
2523
- wrap ? [from] : from.to_a
2524
-
2625
+ from.to_a
2525
2626
  when PBinaryType::Binary
2526
2627
  # For older rubies, the #bytes method returns an Enumerator that must be rolled out
2527
- wrap ? [from] : from.binary_buffer.bytes.to_a
2528
-
2628
+ from.binary_buffer.bytes.to_a
2529
2629
  else
2530
- if wrap
2531
- [from]
2532
- else
2533
- if PIterableType::DEFAULT.instance?(from)
2534
- Iterable.on(from).to_a
2535
- else
2536
- t = Puppet::Pops::Types::TypeCalculator.singleton.infer(from).generalize
2537
- raise TypeConversionError.new("Value of type '#{t}' cannot be converted to Array")
2538
- end
2539
- end
2630
+ Iterable.on(from).to_a
2540
2631
  end
2541
2632
  end
2633
+
2634
+ def on_error(from, _ = false)
2635
+ t = TypeCalculator.singleton.infer(from).generalize
2636
+ _("Value of type %{type} cannot be converted to Array") % { type: t }
2637
+ end
2542
2638
  end
2543
2639
  end
2544
2640
 
@@ -2738,14 +2834,12 @@ class PHashType < PCollectionType
2738
2834
 
2739
2835
  def from_array(from)
2740
2836
  case from
2741
- when NilClass
2742
- throw :undefined_value
2743
2837
  when Array
2744
2838
  if from.size == 0
2745
2839
  {}
2746
2840
  else
2747
2841
  unless from.size % 2 == 0
2748
- raise TypeConversionError.new("odd number of arguments for Hash")
2842
+ raise TypeConversionError.new(_('odd number of arguments for Hash'))
2749
2843
  end
2750
2844
  Hash[*from]
2751
2845
  end
@@ -2755,8 +2849,8 @@ class PHashType < PCollectionType
2755
2849
  if PIterableType::DEFAULT.instance?(from)
2756
2850
  Hash[*Iterable.on(from).to_a]
2757
2851
  else
2758
- t = Puppet::Pops::Types::TypeCalculator.singleton.infer(from).generalize
2759
- raise TypeConversionError.new("Value of type '#{t}' cannot be converted to Hash")
2852
+ t = TypeCalculator.singleton.infer(from).generalize
2853
+ raise TypeConversionError.new(_("Value of type %{type} cannot be converted to Hash") % { type: t })
2760
2854
  end
2761
2855
  end
2762
2856
  end
@@ -2948,8 +3042,9 @@ class PVariantType < PAnyType
2948
3042
 
2949
3043
  # @api private
2950
3044
  def merge_enums(array)
3045
+ # Merge case sensitive enums and strings
2951
3046
  if array.size > 1
2952
- parts = array.partition {|t| t.is_a?(PEnumType) && !t.values.empty? || t.is_a?(PStringType) && !t.value.nil? }
3047
+ parts = array.partition {|t| t.is_a?(PEnumType) && !t.values.empty? && !t.case_insensitive? || t.is_a?(PStringType) && !t.value.nil? }
2953
3048
  enums = parts[0]
2954
3049
  if enums.size > 1
2955
3050
  others = parts[1]
@@ -2957,6 +3052,20 @@ class PVariantType < PAnyType
2957
3052
  array = others
2958
3053
  end
2959
3054
  end
3055
+
3056
+ # Merge case insensitive enums
3057
+ if array.size > 1
3058
+ parts = array.partition {|t| t.is_a?(PEnumType) && !t.values.empty? && t.case_insensitive? }
3059
+ enums = parts[0]
3060
+ if enums.size > 1
3061
+ others = parts[1]
3062
+ values = []
3063
+ enums.each { |enum| enum.values.each { |value| values << value.downcase }}
3064
+ values.uniq!
3065
+ others << PEnumType.new(values, true)
3066
+ array = others
3067
+ end
3068
+ end
2960
3069
  array
2961
3070
  end
2962
3071
 
@@ -3513,7 +3622,7 @@ require_relative 'p_timespan_type'
3513
3622
  require_relative 'p_timestamp_type'
3514
3623
  require_relative 'p_binary_type'
3515
3624
  require_relative 'p_init_type'
3516
- require_relative 'p_error_type'
3625
+ require_relative 'p_object_type_extension'
3517
3626
  require_relative 'type_set_reference'
3518
3627
  require_relative 'implementation_registry'
3519
3628
  require_relative 'tree_iterators'