puppet 4.7.1 → 4.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 puppet might be problematic. Click here for more details.

Files changed (276) hide show
  1. data/Gemfile +0 -3
  2. data/MAINTAINERS +76 -0
  3. data/README.md +0 -6
  4. data/Rakefile +2 -2
  5. data/lib/puppet/agent.rb +3 -3
  6. data/lib/puppet/application/apply.rb +1 -1
  7. data/lib/puppet/configurer.rb +2 -2
  8. data/lib/puppet/data_providers.rb +1 -0
  9. data/lib/puppet/data_providers/data_adapter.rb +1 -0
  10. data/lib/puppet/data_providers/data_function_support.rb +1 -0
  11. data/lib/puppet/data_providers/function_env_data_provider.rb +1 -0
  12. data/lib/puppet/data_providers/function_module_data_provider.rb +1 -0
  13. data/lib/puppet/data_providers/hiera_config.rb +1 -0
  14. data/lib/puppet/data_providers/hiera_env_data_provider.rb +1 -0
  15. data/lib/puppet/data_providers/hiera_interpolate.rb +1 -0
  16. data/lib/puppet/data_providers/hiera_module_data_provider.rb +1 -0
  17. data/lib/puppet/data_providers/hiera_support.rb +1 -2
  18. data/lib/puppet/data_providers/json_data_provider_factory.rb +2 -0
  19. data/lib/puppet/data_providers/yaml_data_provider_factory.rb +2 -0
  20. data/lib/puppet/defaults.rb +20 -1
  21. data/lib/puppet/environments.rb +5 -2
  22. data/lib/puppet/face/catalog.rb +1 -1
  23. data/lib/puppet/face/epp.rb +57 -11
  24. data/lib/puppet/face/module/install.rb +6 -6
  25. data/lib/puppet/functions.rb +23 -24
  26. data/lib/puppet/functions/alert.rb +14 -0
  27. data/lib/puppet/functions/binary_file.rb +25 -0
  28. data/lib/puppet/functions/break.rb +22 -0
  29. data/lib/puppet/functions/contain.rb +33 -0
  30. data/lib/puppet/functions/crit.rb +14 -0
  31. data/lib/puppet/functions/debug.rb +14 -0
  32. data/lib/puppet/functions/emerg.rb +14 -0
  33. data/lib/puppet/functions/epp.rb +1 -1
  34. data/lib/puppet/functions/err.rb +14 -0
  35. data/lib/puppet/functions/find_file.rb +31 -0
  36. data/lib/puppet/functions/include.rb +21 -0
  37. data/lib/puppet/functions/info.rb +14 -0
  38. data/lib/puppet/functions/new.rb +1 -1
  39. data/lib/puppet/functions/next.rb +23 -0
  40. data/lib/puppet/functions/notice.rb +14 -0
  41. data/lib/puppet/functions/regsubst.rb +12 -16
  42. data/lib/puppet/functions/require.rb +37 -0
  43. data/lib/puppet/functions/return.rb +22 -0
  44. data/lib/puppet/functions/strftime.rb +35 -0
  45. data/lib/puppet/functions/warning.rb +14 -0
  46. data/lib/puppet/generate/models/type/type.rb +4 -0
  47. data/lib/puppet/generate/templates/type/pcore.erb +2 -1
  48. data/lib/puppet/indirector/face.rb +6 -1
  49. data/lib/puppet/network/http/error.rb +2 -2
  50. data/lib/puppet/network/http/handler.rb +2 -2
  51. data/lib/puppet/node/environment.rb +11 -0
  52. data/lib/puppet/parser/ast.rb +5 -0
  53. data/lib/puppet/parser/ast/pops_bridge.rb +17 -4
  54. data/lib/puppet/parser/compiler.rb +29 -1
  55. data/lib/puppet/parser/functions.rb +6 -0
  56. data/lib/puppet/parser/functions/assert_type.rb +1 -1
  57. data/lib/puppet/parser/functions/binary_file.rb +24 -0
  58. data/lib/puppet/parser/functions/break.rb +39 -0
  59. data/lib/puppet/parser/functions/contain.rb +7 -15
  60. data/lib/puppet/parser/functions/defined.rb +2 -2
  61. data/lib/puppet/parser/functions/dig.rb +1 -1
  62. data/lib/puppet/parser/functions/each.rb +1 -1
  63. data/lib/puppet/parser/functions/epp.rb +2 -2
  64. data/lib/puppet/parser/functions/filter.rb +1 -1
  65. data/lib/puppet/parser/functions/find_file.rb +28 -0
  66. data/lib/puppet/parser/functions/hiera.rb +4 -4
  67. data/lib/puppet/parser/functions/hiera_array.rb +1 -1
  68. data/lib/puppet/parser/functions/hiera_hash.rb +1 -1
  69. data/lib/puppet/parser/functions/hiera_include.rb +1 -1
  70. data/lib/puppet/parser/functions/include.rb +4 -8
  71. data/lib/puppet/parser/functions/inline_epp.rb +1 -1
  72. data/lib/puppet/parser/functions/lest.rb +1 -1
  73. data/lib/puppet/parser/functions/lookup.rb +4 -2
  74. data/lib/puppet/parser/functions/map.rb +1 -1
  75. data/lib/puppet/parser/functions/match.rb +1 -1
  76. data/lib/puppet/parser/functions/new.rb +414 -18
  77. data/lib/puppet/parser/functions/next.rb +38 -0
  78. data/lib/puppet/parser/functions/reduce.rb +1 -1
  79. data/lib/puppet/parser/functions/regsubst.rb +4 -2
  80. data/lib/puppet/parser/functions/require.rb +4 -27
  81. data/lib/puppet/parser/functions/return.rb +71 -0
  82. data/lib/puppet/parser/functions/reverse_each.rb +1 -1
  83. data/lib/puppet/parser/functions/scanf.rb +13 -8
  84. data/lib/puppet/parser/functions/slice.rb +1 -1
  85. data/lib/puppet/parser/functions/split.rb +1 -1
  86. data/lib/puppet/parser/functions/step.rb +1 -1
  87. data/lib/puppet/parser/functions/strftime.rb +185 -0
  88. data/lib/puppet/parser/functions/then.rb +1 -1
  89. data/lib/puppet/parser/functions/type.rb +1 -1
  90. data/lib/puppet/parser/functions/with.rb +3 -3
  91. data/lib/puppet/parser/resource.rb +8 -5
  92. data/lib/puppet/parser/scope.rb +1 -1
  93. data/lib/puppet/plugins/configuration.rb +8 -0
  94. data/lib/puppet/plugins/data_providers.rb +1 -0
  95. data/lib/puppet/plugins/data_providers/data_provider.rb +7 -28
  96. data/lib/puppet/plugins/data_providers/registry.rb +1 -0
  97. data/lib/puppet/pops.rb +4 -0
  98. data/lib/puppet/pops/evaluator/access_operator.rb +36 -5
  99. data/lib/puppet/pops/evaluator/closure.rb +81 -12
  100. data/lib/puppet/pops/evaluator/compare_operator.rb +24 -1
  101. data/lib/puppet/pops/evaluator/evaluator_impl.rb +29 -5
  102. data/lib/puppet/pops/evaluator/json_strict_literal_evaluator.rb +1 -1
  103. data/lib/puppet/pops/evaluator/runtime3_converter.rb +53 -62
  104. data/lib/puppet/pops/evaluator/runtime3_support.rb +15 -6
  105. data/lib/puppet/pops/functions/dispatch.rb +9 -2
  106. data/lib/puppet/pops/functions/dispatcher.rb +3 -1
  107. data/lib/puppet/pops/functions/function.rb +19 -2
  108. data/lib/puppet/pops/issues.rb +9 -0
  109. data/lib/puppet/pops/label_provider.rb +2 -2
  110. data/lib/puppet/pops/loader/loader.rb +17 -0
  111. data/lib/puppet/pops/loader/static_loader.rb +0 -41
  112. data/lib/puppet/pops/lookup.rb +12 -0
  113. data/lib/puppet/pops/lookup/context.rb +86 -0
  114. data/lib/puppet/pops/lookup/explainer.rb +46 -6
  115. data/lib/puppet/pops/lookup/invocation.rb +19 -0
  116. data/lib/puppet/pops/lookup/sub_lookup.rb +1 -1
  117. data/lib/puppet/pops/model/factory.rb +20 -8
  118. data/lib/puppet/pops/model/model_label_provider.rb +3 -0
  119. data/lib/puppet/pops/model/model_meta.rb +2 -0
  120. data/lib/puppet/pops/model/model_tree_dumper.rb +14 -0
  121. data/lib/puppet/pops/parser/egrammar.ra +11 -6
  122. data/lib/puppet/pops/parser/eparser.rb +1112 -1086
  123. data/lib/puppet/pops/parser/heredoc_support.rb +1 -2
  124. data/lib/puppet/pops/pcore.rb +1 -0
  125. data/lib/puppet/pops/puppet_stack.rb +3 -3
  126. data/lib/puppet/pops/resource/param.rb +5 -1
  127. data/lib/puppet/pops/resource/resource_type_impl.rb +8 -4
  128. data/lib/puppet/pops/resource/resource_type_set.pcore +1 -0
  129. data/lib/puppet/pops/serialization/abstract_reader.rb +19 -2
  130. data/lib/puppet/pops/serialization/abstract_writer.rb +16 -3
  131. data/lib/puppet/pops/serialization/deserializer.rb +5 -1
  132. data/lib/puppet/pops/serialization/extension.rb +2 -0
  133. data/lib/puppet/pops/serialization/json.rb +76 -26
  134. data/lib/puppet/pops/serialization/serializer.rb +5 -1
  135. data/lib/puppet/pops/serialization/time_factory.rb +2 -1
  136. data/lib/puppet/pops/time/timespan.rb +718 -0
  137. data/lib/puppet/pops/time/timestamp.rb +148 -0
  138. data/lib/puppet/pops/types/p_binary_type.rb +220 -0
  139. data/lib/puppet/pops/types/p_object_type.rb +12 -6
  140. data/lib/puppet/pops/types/p_sensitive_type.rb +5 -1
  141. data/lib/puppet/pops/types/p_timespan_type.rb +141 -0
  142. data/lib/puppet/pops/types/p_timestamp_type.rb +69 -0
  143. data/lib/puppet/pops/types/string_converter.rb +62 -0
  144. data/lib/puppet/pops/types/type_asserter.rb +1 -1
  145. data/lib/puppet/pops/types/type_calculator.rb +17 -3
  146. data/lib/puppet/pops/types/type_factory.rb +35 -1
  147. data/lib/puppet/pops/types/type_formatter.rb +64 -11
  148. data/lib/puppet/pops/types/type_mismatch_describer.rb +110 -61
  149. data/lib/puppet/pops/types/type_parser.rb +18 -4
  150. data/lib/puppet/pops/types/types.rb +98 -63
  151. data/lib/puppet/pops/validation.rb +9 -1
  152. data/lib/puppet/pops/validation/checker4_0.rb +7 -0
  153. data/lib/puppet/property.rb +1 -1
  154. data/lib/puppet/provider.rb +3 -6
  155. data/lib/puppet/provider/mcx/mcxcontent.rb +1 -1
  156. data/lib/puppet/provider/mount/parsed.rb +18 -4
  157. data/lib/puppet/provider/nameservice/directoryservice.rb +15 -7
  158. data/lib/puppet/provider/package/gem.rb +6 -1
  159. data/lib/puppet/provider/package/pip.rb +0 -1
  160. data/lib/puppet/provider/package/pkg.rb +5 -1
  161. data/lib/puppet/provider/package/pkgng.rb +1 -1
  162. data/lib/puppet/provider/package/yum.rb +10 -0
  163. data/lib/puppet/provider/service/launchd.rb +1 -0
  164. data/lib/puppet/provider/user/directoryservice.rb +6 -6
  165. data/lib/puppet/provider/yumrepo/inifile.rb +1 -1
  166. data/lib/puppet/provider/zpool/zpool.rb +1 -1
  167. data/lib/puppet/resource.rb +54 -12
  168. data/lib/puppet/resource/capability_finder.rb +15 -9
  169. data/lib/puppet/resource/catalog.rb +25 -6
  170. data/lib/puppet/resource/type.rb +3 -1
  171. data/lib/puppet/settings.rb +1 -1
  172. data/lib/puppet/settings/environment_conf.rb +12 -4
  173. data/lib/puppet/syntax_checkers/base64.rb +41 -0
  174. data/lib/puppet/syntax_checkers/json.rb +0 -2
  175. data/lib/puppet/transaction.rb +6 -0
  176. data/lib/puppet/transaction/additional_resource_generator.rb +5 -0
  177. data/lib/puppet/transaction/report.rb +7 -2
  178. data/lib/puppet/type.rb +2 -1
  179. data/lib/puppet/type/file/checksum.rb +1 -0
  180. data/lib/puppet/type/file/content.rb +4 -4
  181. data/lib/puppet/type/mount.rb +44 -0
  182. data/lib/puppet/type/ssh_authorized_key.rb +1 -1
  183. data/lib/puppet/type/tidy.rb +3 -0
  184. data/lib/puppet/type/user.rb +12 -6
  185. data/lib/puppet/util/log.rb +25 -0
  186. data/lib/puppet/util/plist.rb +8 -3
  187. data/lib/puppet/version.rb +1 -1
  188. data/lib/puppet_x.rb +7 -1
  189. data/spec/integration/application/apply_spec.rb +118 -0
  190. data/spec/integration/parser/compiler_spec.rb +28 -0
  191. data/spec/integration/parser/pcore_resource_spec.rb +40 -3
  192. data/spec/integration/provider/mount_spec.rb +2 -1
  193. data/spec/integration/util/windows/principal_spec.rb +2 -2
  194. data/spec/integration/util/windows/registry_spec.rb +4 -4
  195. data/spec/lib/puppet_spec/compiler.rb +5 -1
  196. data/spec/lib/puppet_spec/unindent.rb +5 -0
  197. data/spec/shared_contexts/types_setup.rb +6 -0
  198. data/spec/shared_examples/rhel_package_provider.rb +16 -0
  199. data/spec/spec_helper.rb +1 -0
  200. data/spec/unit/agent_spec.rb +11 -0
  201. data/spec/unit/application/lookup_spec.rb +94 -3
  202. data/spec/unit/capability_spec.rb +22 -0
  203. data/spec/unit/configurer_spec.rb +8 -0
  204. data/spec/unit/face/epp_face_spec.rb +22 -3
  205. data/spec/unit/functions/assert_type_spec.rb +3 -3
  206. data/spec/unit/functions/binary_file_spec.rb +46 -0
  207. data/spec/unit/functions/break_spec.rb +89 -0
  208. data/spec/unit/{parser/functions → functions}/contain_spec.rb +68 -3
  209. data/spec/unit/functions/find_file_spec.rb +69 -0
  210. data/spec/unit/functions/include_spec.rb +175 -0
  211. data/spec/unit/functions/logging_spec.rb +54 -0
  212. data/spec/unit/functions/lookup_spec.rb +3 -3
  213. data/spec/unit/functions/new_spec.rb +105 -5
  214. data/spec/unit/functions/next_spec.rb +93 -0
  215. data/spec/unit/functions/require_spec.rb +83 -0
  216. data/spec/unit/functions/return_spec.rb +105 -0
  217. data/spec/unit/{parser/functions → functions}/shared.rb +14 -11
  218. data/spec/unit/functions/strftime_spec.rb +152 -0
  219. data/spec/unit/functions4_spec.rb +22 -0
  220. data/spec/unit/indirector/face_spec.rb +10 -2
  221. data/spec/unit/network/http/error_spec.rb +1 -2
  222. data/spec/unit/network/http/handler_spec.rb +6 -5
  223. data/spec/unit/parser/functions/hiera_array_spec.rb +1 -1
  224. data/spec/unit/parser/functions/hiera_hash_spec.rb +1 -1
  225. data/spec/unit/parser/functions/hiera_include_spec.rb +1 -1
  226. data/spec/unit/parser/functions/hiera_spec.rb +1 -1
  227. data/spec/unit/parser/functions/lookup_spec.rb +1 -1
  228. data/spec/unit/parser/functions/regsubst_spec.rb +1 -1
  229. data/spec/unit/parser/functions/split_spec.rb +1 -1
  230. data/spec/unit/pops/evaluator/access_ops_spec.rb +81 -1
  231. data/spec/unit/pops/evaluator/arithmetic_ops_spec.rb +170 -0
  232. data/spec/unit/pops/evaluator/evaluating_parser_spec.rb +29 -4
  233. data/spec/unit/pops/evaluator/runtime3_converter_spec.rb +112 -4
  234. data/spec/unit/pops/loaders/dependency_loader_spec.rb +12 -0
  235. data/spec/unit/pops/loaders/static_loader_spec.rb +0 -26
  236. data/spec/unit/pops/lookup/context_spec.rb +149 -0
  237. data/spec/unit/pops/parser/parse_functions_spec.rb +19 -0
  238. data/spec/unit/pops/parser/parse_lambda_spec.rb +19 -0
  239. data/spec/unit/pops/puppet_stack_spec.rb +1 -1
  240. data/spec/unit/pops/resource/resource_type_impl_spec.rb +74 -0
  241. data/spec/unit/pops/serialization/packer_spec.rb +34 -14
  242. data/spec/unit/pops/serialization/serialization_spec.rb +67 -5
  243. data/spec/unit/pops/time/timespan_spec.rb +121 -0
  244. data/spec/unit/pops/types/p_binary_type_spec.rb +243 -0
  245. data/spec/unit/pops/types/p_object_type_spec.rb +7 -7
  246. data/spec/unit/pops/types/p_sensitive_type_spec.rb +1 -1
  247. data/spec/unit/pops/types/p_timespan_type_spec.rb +273 -0
  248. data/spec/unit/pops/types/p_timestamp_type_spec.rb +311 -0
  249. data/spec/unit/pops/types/p_type_set_type_spec.rb +13 -13
  250. data/spec/unit/pops/types/ruby_generator_spec.rb +12 -12
  251. data/spec/unit/pops/types/string_converter_spec.rb +89 -0
  252. data/spec/unit/pops/types/type_asserter_spec.rb +3 -3
  253. data/spec/unit/pops/types/type_calculator_spec.rb +113 -5
  254. data/spec/unit/pops/types/type_formatter_spec.rb +40 -0
  255. data/spec/unit/pops/types/type_mismatch_describer_spec.rb +49 -38
  256. data/spec/unit/pops/types/type_parser_spec.rb +87 -4
  257. data/spec/unit/pops/types/types_spec.rb +1 -1
  258. data/spec/unit/pops/validator/validator_spec.rb +23 -0
  259. data/spec/unit/provider/mount/parsed_spec.rb +47 -29
  260. data/spec/unit/provider/package/pkg_spec.rb +109 -99
  261. data/spec/unit/provider/ssh_authorized_key/parsed_spec.rb +1 -0
  262. data/spec/unit/provider/user/aix_spec.rb +1 -1
  263. data/spec/unit/provider/user/directoryservice_spec.rb +101 -30
  264. data/spec/unit/resource/capability_finder_spec.rb +29 -7
  265. data/spec/unit/resource/catalog_spec.rb +127 -0
  266. data/spec/unit/ssl/certificate_request_spec.rb +1 -1
  267. data/spec/unit/transaction/additional_resource_generator_spec.rb +30 -0
  268. data/spec/unit/transaction/persistence_spec.rb +1 -6
  269. data/spec/unit/transaction/report_spec.rb +23 -0
  270. data/spec/unit/transaction_spec.rb +38 -0
  271. data/spec/unit/type/mount_spec.rb +5 -0
  272. data/spec/unit/util/plist_spec.rb +14 -2
  273. metadata +71 -12
  274. data/spec/integration/parser/functions/require_spec.rb +0 -43
  275. data/spec/unit/parser/functions/include_spec.rb +0 -55
  276. data/spec/unit/parser/functions/require_spec.rb +0 -68
@@ -0,0 +1,148 @@
1
+ module Puppet::Pops
2
+ module Time
3
+ class Timestamp < TimeData
4
+ DEFAULT_FORMATS_WO_TZ = ['%FT%T.L', '%FT%T', '%F']
5
+ DEFAULT_FORMATS = ['%FT%T.%L %Z', '%FT%T %Z', '%F %Z'] + DEFAULT_FORMATS_WO_TZ
6
+
7
+ CURRENT_TIMEZONE = 'current'.freeze
8
+ KEY_TIMEZONE = 'timezone'.freeze
9
+
10
+ # Converts a timezone that strptime can parse using '%z' into '-HH:MM' or '+HH:MM'
11
+ # @param [String] tz the timezone to convert
12
+ # @return [String] the converted timezone
13
+ #
14
+ # @api private
15
+ def self.convert_timezone(tz)
16
+ if tz =~ /\A[+-]\d\d:\d\d\z/
17
+ tz
18
+ else
19
+ offset = utc_offset(tz) / 60
20
+ if offset < 0
21
+ offset = offset.abs
22
+ sprintf('-%2.2d:%2.2d', offset / 60, offset % 60)
23
+ else
24
+ sprintf('+%2.2d:%2.2d', offset / 60, offset % 60)
25
+ end
26
+ end
27
+ end
28
+
29
+ # Returns the zone offset from utc for the given `timezone`
30
+ # @param [String] timezone the timezone to get the offset for
31
+ # @return [Integer] the timezone offset, in seconds
32
+ #
33
+ # @api private
34
+ def self.utc_offset(timezone)
35
+ if CURRENT_TIMEZONE.casecmp(timezone) == 0
36
+ ::Time.now.utc_offset
37
+ else
38
+ hash = DateTime._strptime(timezone, '%z')
39
+ offset = hash.nil? ? nil : hash[:offset]
40
+ raise ArgumentError, "Illegal timezone '#{timezone}'" if offset.nil?
41
+ offset
42
+ end
43
+ end
44
+
45
+ # Formats a ruby Time object using the given timezone
46
+ def self.format_time(format, time, timezone)
47
+ unless timezone.nil? || timezone.empty?
48
+ time = time.localtime(convert_timezone(timezone))
49
+ end
50
+ time.strftime(format)
51
+ end
52
+
53
+ def self.now
54
+ from_time(::Time.now)
55
+ end
56
+
57
+ def self.from_time(t)
58
+ new(t.tv_sec * NSECS_PER_SEC + t.tv_nsec)
59
+ end
60
+
61
+ def self.from_hash(args_hash)
62
+ parse(args_hash[KEY_STRING], args_hash[KEY_FORMAT], args_hash[KEY_TIMEZONE])
63
+ end
64
+
65
+ def self.parse(str, format = :default, timezone = nil)
66
+ has_timezone = !(timezone.nil? || timezone.empty? || timezone == :default)
67
+ if format.nil? || format == :default
68
+ format = has_timezone ? DEFAULT_FORMATS_WO_TZ : DEFAULT_FORMATS
69
+ end
70
+
71
+ parsed = nil
72
+ if format.is_a?(Array)
73
+ format.each do |fmt|
74
+ assert_no_tz_extractor(fmt) if has_timezone
75
+ begin
76
+ parsed = DateTime.strptime(str, fmt)
77
+ break
78
+ rescue ArgumentError
79
+ end
80
+ end
81
+ raise ArgumentError, "Unable to parse '#{str}' using any of the formats #{format.join(', ')}" if parsed.nil?
82
+ else
83
+ assert_no_tz_extractor(format) if has_timezone
84
+ begin
85
+ parsed = DateTime.strptime(str, format)
86
+ rescue ArgumentError
87
+ raise ArgumentError, "Unable to parse '#{str}' using format '#{format}'"
88
+ end
89
+ end
90
+ parsed_time = parsed.to_time
91
+ parsed_time -= utc_offset(timezone) if has_timezone
92
+ from_time(parsed_time)
93
+ end
94
+
95
+ def self.assert_no_tz_extractor(format)
96
+ if format =~ /[^%]%[zZ]/
97
+ raise ArgumentError, 'Using a Timezone designator in format specification is mutually exclusive to providing an explicit timezone argument'
98
+ end
99
+ end
100
+
101
+ undef_method :-@, :+@, :div, :fdiv, :abs, :abs2, :magnitude # does not make sense on a Timestamp
102
+ if method_defined?(:negative?)
103
+ undef_method :negative?, :positive?
104
+ end
105
+ if method_defined?(:%)
106
+ undef_method :%, :modulo, :divmod
107
+ end
108
+
109
+ def +(o)
110
+ case o
111
+ when Timespan
112
+ Timestamp.new(@nsecs + o.nsecs)
113
+ when Integer, Float
114
+ Timestamp.new(@nsecs + (o * NSECS_PER_SEC).to_i)
115
+ else
116
+ raise ArgumentError, "#{a_an_uc(o)} cannot be added to a Timestamp"
117
+ end
118
+ end
119
+
120
+ def -(o)
121
+ case o
122
+ when Timestamp
123
+ # Diff between two timestamps is a timespan
124
+ Timespan.new(@nsecs - o.nsecs)
125
+ when Timespan
126
+ Timestamp.new(@nsecs - o.nsecs)
127
+ when Integer, Float
128
+ # Subtract seconds
129
+ Timestamp.new(@nsecs - (o * NSECS_PER_SEC).to_i)
130
+ else
131
+ raise ArgumentError, "#{a_an_uc(o)} cannot be subtracted from a Timestamp"
132
+ end
133
+ end
134
+
135
+ def format(format, timezone = nil)
136
+ self.class.format_time(format, to_time, timezone)
137
+ end
138
+
139
+ def to_s
140
+ format(DEFAULT_FORMATS[0])
141
+ end
142
+
143
+ def to_time
144
+ ::Time.at(to_r).utc
145
+ end
146
+ end
147
+ end
148
+ end
@@ -0,0 +1,220 @@
1
+ require 'base64'
2
+ module Puppet::Pops
3
+ module Types
4
+
5
+ # A Puppet Language Type that exposes the {{SemanticPuppet::Version}} and {{SemanticPuppet::VersionRange}}.
6
+ # The version type is parameterized with version ranges.
7
+ #
8
+ # @api public
9
+ class PBinaryType < PAnyType
10
+
11
+ # Represents a binary buffer
12
+ # @api public
13
+ class Binary
14
+ attr_reader :binary_buffer
15
+
16
+ # Constructs an instance of Binary from a base64 urlsafe encoded string (RFC 2045).
17
+ # @param [String] A string with RFC 2045 compliant encoded binary
18
+ #
19
+ def self.from_base64(str)
20
+ new(Base64.decode64(str))
21
+ end
22
+
23
+ # Constructs an instance of Binary from a base64 encoded string (RFC4648 with "URL and Filename
24
+ # Safe Alphabet" (That is with '-' instead of '+', and '_' instead of '/').
25
+ #
26
+ def self.from_base64_urlsafe(str)
27
+ new(Base64.urlsafe_decode64(str))
28
+ end
29
+
30
+ # Constructs an instance of Binary from a base64 strict encoded string (RFC 4648)
31
+ # Where correct padding must be used and line breaks causes an error to be raised.
32
+ #
33
+ # @param [String] A string with RFC 4648 compliant encoded binary
34
+ #
35
+ def self.from_base64_strict(str)
36
+ new(Base64.strict_decode64(str))
37
+ end
38
+
39
+ # Creates a new Binary from a String containing binary data. If the string's encoding
40
+ # is not already ASCII-8BIT, a copy of the string is force encoded as ASCII-8BIT (that is Ruby's "binary" format).
41
+ # This means that this binary will have the exact same content, but the string will considered
42
+ # to hold a sequence of bytes in the range 0 to 255.
43
+ #
44
+ # The given string will be frozen as a side effect if it is in ASCII-8BIT encoding. If this is not
45
+ # wanted, a copy should be given to this method.
46
+ #
47
+ # @param [String] A string with binary data
48
+ # @api public
49
+ #
50
+ def self.from_binary_string(bin)
51
+ new(bin)
52
+ end
53
+
54
+ # Creates a new Binary from a String containing text/binary in its given encoding. If the string's encoding
55
+ # is not already UTF-8, the string is first transcoded to UTF-8.
56
+ # This means that this binary will have the UTF-8 byte representation of the original string.
57
+ # For this to be valid, the encoding used in the given string must be valid.
58
+ # The validity of the given string is therefore asserted.
59
+ #
60
+ # The given string will be frozen as a side effect if it is in ASCII-8BIT encoding. If this is not
61
+ # wanted, a copy should be given to this method.
62
+ #
63
+ # @param [String] A string with valid content in its given encoding
64
+ # @return [Puppet::Pops::Types::PBinaryType::Binary] with the UTF-8 representation of the UTF-8 transcoded string
65
+ # @api public
66
+ #
67
+ def self.from_string(encoded_string)
68
+ enc = encoded_string.encoding.name
69
+ unless encoded_string.valid_encoding?
70
+ raise ArgumentError, "The given string in encoding '#{enc}' is invalid. Cannot create a Binary UTF-8 representation"
71
+ end
72
+ # Convert to UTF-8 (if not already UTF-8), and then to binary
73
+ encoded_string = (enc == "UTF-8") ? encoded_string.dup : encoded_string.encode('UTF-8')
74
+ encoded_string.force_encoding("ASCII-8BIT")
75
+ new(encoded_string)
76
+ end
77
+
78
+ # Creates a new Binary from a String containing raw binary data of unknown encoding. If the string's encoding
79
+ # is not already ASCII-8BIT, a copy of the string is forced to ASCII-8BIT (that is Ruby's "binary" format).
80
+ # This means that this binary will have the exact same content, but the string will considered
81
+ # to hold a sequence of bytes in the range 0 to 255.
82
+ #
83
+ # @param [String] A string with binary data
84
+ # @api private
85
+ #
86
+ def initialize(bin)
87
+ # TODO: When Ruby 1.9.3 support is dropped change this to `bin.b` for binary encoding instead of force_encoding
88
+ @binary_buffer = (bin.encoding.name == "ASCII-8BIT" ? bin : bin.dup.force_encoding("ASCII-8BIT")).freeze
89
+ end
90
+
91
+ # Presents the binary content as a string base64 encoded string (without line breaks).
92
+ #
93
+ def to_s
94
+ Base64.strict_encode64(@binary_buffer)
95
+ end
96
+
97
+ # Returns the binary content as a "relaxed" base64 (standard) encoding where
98
+ # the string is broken up with new lines.
99
+ def relaxed_to_s
100
+ Base64.encode64(@binary_buffer)
101
+ end
102
+
103
+ # Returns the binary content as a url safe base64 string (where + and / are replaced by - and _)
104
+ #
105
+ def urlsafe_to_s
106
+ Base64.urlsafe_encode64(@binary_buffer)
107
+ end
108
+
109
+ def hash
110
+ @binary_buffer.hash
111
+ end
112
+
113
+ def eql?(o)
114
+ self.class == o.class && @binary_buffer == o.binary_buffer
115
+ end
116
+
117
+ def ==(o)
118
+ self.eql?(o)
119
+ end
120
+
121
+ def length()
122
+ @binary_buffer.length
123
+ end
124
+ end
125
+
126
+ def self.register_ptype(loader, ir)
127
+ create_ptype(loader, ir, 'AnyType')
128
+ end
129
+
130
+ # Only instances of Binary are instances of the PBinaryType
131
+ #
132
+ def instance?(o, guard = nil)
133
+ o.is_a?(Binary)
134
+ end
135
+
136
+ def eql?(o)
137
+ self.class == o.class
138
+ end
139
+
140
+ # @api private
141
+ def self.new_function(_, loader)
142
+ @new_function ||= Puppet::Functions.create_loaded_function(:new_Binary, loader) do
143
+ local_types do
144
+ type 'ByteInteger = Integer[0,255]'
145
+ type 'Base64Format = Enum["%b", "%u", "%B", "%s", "%r"]'
146
+ type 'StringHash = Struct[{value => String, "format" => Optional[Base64Format]}]'
147
+ type 'ArrayHash = Struct[{value => Array[ByteInteger]}]'
148
+ type 'BinaryArgsHash = Variant[StringHash, ArrayHash]'
149
+ end
150
+
151
+ # Creates a binary from a base64 encoded string in one of the formats %b, %u, %B, %s, or %r
152
+ dispatch :from_string do
153
+ param 'String', :str
154
+ optional_param 'Base64Format', :format
155
+ end
156
+
157
+ dispatch :from_array do
158
+ param 'Array[ByteInteger]', :byte_array
159
+ end
160
+
161
+ # Same as from_string, or from_array, but value and (for string) optional format are given in the form
162
+ # of a hash.
163
+ #
164
+ dispatch :from_hash do
165
+ param 'BinaryArgsHash', :hash_args
166
+ end
167
+
168
+ def from_string(str, format = nil)
169
+ format ||= '%B'
170
+ case format
171
+ when "%b"
172
+ # padding must be added for older rubies to avoid truncation
173
+ padding = '=' * (str.length % 3)
174
+ Binary.new(Base64.decode64(str + padding))
175
+
176
+ when "%u"
177
+ Binary.new(Base64.urlsafe_decode64(str))
178
+
179
+ when "%B"
180
+ Binary.new(Base64.strict_decode64(str))
181
+
182
+ when "%s"
183
+ Binary.from_string(str)
184
+
185
+ when "%r"
186
+ Binary.from_binary_string(str)
187
+
188
+ else
189
+ raise ArgumentError, "Unsupported Base64 format '#{format}'"
190
+ end
191
+ end
192
+
193
+ def from_array(array)
194
+ # The array is already known to have bytes in the range 0-255, or it is in error
195
+ # Without this pack C would produce weird results
196
+ Binary.from_binary_string(array.pack("C*"))
197
+ end
198
+
199
+ def from_hash(hash)
200
+ case hash['value']
201
+ when Array
202
+ from_array(hash['value'])
203
+ when String
204
+ from_string(hash['value'], hash['format'])
205
+ end
206
+ end
207
+ end
208
+ end
209
+
210
+ DEFAULT = PBinaryType.new
211
+
212
+ protected
213
+
214
+ def _assignable?(o, guard)
215
+ o.class == self.class
216
+ end
217
+
218
+ end
219
+ end
220
+ end
@@ -201,17 +201,23 @@ class PObjectType < PMetaType
201
201
  @dispatch ||= create_dispatch(receiver)
202
202
 
203
203
  args_type = TypeCalculator.infer_set(block_given? ? args + [block] : args)
204
- unless @dispatch.type.callable?(args_type)
205
- raise ArgumentError, TypeMismatchDescriber.describe_signatures(label, [@dispatch], args_type)
206
- end
207
- @dispatch.invoke(receiver, scope, args, &block)
204
+ found = @dispatch.find { |d| d.type.callable?(args_type) }
205
+ raise ArgumentError, TypeMismatchDescriber.describe_signatures(label, @dispatch, args_type) if found.nil?
206
+ found.invoke(receiver, scope, args, &block)
208
207
  end
209
208
 
210
209
  # @api private
211
210
  def create_dispatch(instance)
212
211
  # TODO: Assumes Ruby implementation for now
213
- Functions::Dispatch.new(callable_type, name, [],
214
- callable_type.block_type.nil? ? nil : 'block', nil, nil, false)
212
+ if(callable_type.is_a?(PVariantType))
213
+ callable_type.types.map do |ct|
214
+ Functions::Dispatch.new(ct, name, [],
215
+ ct.block_type.nil? ? nil : 'block', nil, nil, false)
216
+ end
217
+ else
218
+ [Functions::Dispatch.new(callable_type, name, [],
219
+ callable_type.block_type.nil? ? nil : 'block', nil, nil, false)]
220
+ end
215
221
  end
216
222
 
217
223
  # @api private
@@ -6,7 +6,7 @@ module Types
6
6
  #
7
7
  #
8
8
  # @api public
9
- class PSensitiveType < Puppet::Pops::Types::PTypeWithContainedType
9
+ class PSensitiveType < PTypeWithContainedType
10
10
 
11
11
  class Sensitive
12
12
  def initialize(value)
@@ -26,6 +26,10 @@ class PSensitiveType < Puppet::Pops::Types::PTypeWithContainedType
26
26
  end
27
27
  end
28
28
 
29
+ def self.register_ptype(loader, ir)
30
+ create_ptype(loader, ir, 'AnyType')
31
+ end
32
+
29
33
  def initialize(type = nil)
30
34
  @type = type.nil? ? PAnyType.new : type.generalize
31
35
  end
@@ -0,0 +1,141 @@
1
+ module Puppet::Pops
2
+ module Types
3
+ class PAbstractTimeDataType < PAbstractRangeType
4
+ # @param [AbstractTime] min lower bound for this type. Nil or :default means unbounded
5
+ # @param [AbstractTime] max upper bound for this type. Nil or :default means unbounded
6
+ def initialize(min = nil, max = nil)
7
+ super(convert_arg(min, true), convert_arg(max, false))
8
+ end
9
+
10
+ def convert_arg(arg, min)
11
+ case arg
12
+ when impl_class
13
+ arg
14
+ when Hash
15
+ impl_class.from_hash(arg)
16
+ when nil, :default
17
+ nil
18
+ when String
19
+ impl_class.parse(arg)
20
+ when Integer
21
+ arg == impl_class.new(arg * Time::NSECS_PER_SEC)
22
+ when Float
23
+ arg == (min ? -Float::INFINITY : Float::INFINITY) ? arg : impl_class.new(arg * Time::NSECS_PER_SEC)
24
+ else
25
+ raise ArgumentError, "Unable to create a #{impl_class.name} from a #{arg.class.name}" unless arg.nil? || arg == :default
26
+ nil
27
+ end
28
+ end
29
+
30
+ # Concatenates this range with another range provided that the ranges intersect or
31
+ # are adjacent. When that's not the case, this method will return `nil`
32
+ #
33
+ # @param o [PAbstractTimeDataType] the range to concatenate with this range
34
+ # @return [PAbstractTimeDataType,nil] the concatenated range or `nil` when the ranges were apart
35
+ # @api public
36
+ def merge(o)
37
+ if intersect?(o) || adjacent?(o)
38
+ new_min = numeric_from <= o.numeric_from ? numeric_from : o.numeric_from
39
+ new_max = numeric_to >= o.numeric_to ? numeric_to : o.numeric_to
40
+ self.class.new(new_min, new_max)
41
+ else
42
+ nil
43
+ end
44
+ end
45
+
46
+ def _assignable?(o, guard)
47
+ self.class == o.class && numeric_from <= o.numeric_from && numeric_to >= o.numeric_to
48
+ end
49
+ end
50
+
51
+ class PTimespanType < PAbstractTimeDataType
52
+ def self.register_ptype(loader, ir)
53
+ create_ptype(loader, ir, 'ScalarType',
54
+ 'from' => { KEY_TYPE => PTimespanType::DEFAULT, KEY_VALUE => :default },
55
+ 'to' => { KEY_TYPE => PTimespanType::DEFAULT, KEY_VALUE => :default }
56
+ )
57
+ end
58
+
59
+ def self.new_function(_, loader)
60
+ @new_function ||= Puppet::Functions.create_loaded_function(:new_timespan, loader) do
61
+ local_types do
62
+ type 'Formats = Variant[String[2],Array[String[2]], 1]'
63
+ end
64
+
65
+ dispatch :from_seconds do
66
+ param 'Variant[Integer,Float]', :seconds
67
+ end
68
+
69
+ dispatch :from_string do
70
+ param 'String[1]', :string
71
+ optional_param 'Formats', :format
72
+ end
73
+
74
+ dispatch :from_fields do
75
+ param 'Integer', :days
76
+ param 'Integer', :hours
77
+ param 'Integer', :minutes
78
+ param 'Integer', :seconds
79
+ optional_param 'Integer', :milliseconds
80
+ optional_param 'Integer', :microseconds
81
+ optional_param 'Integer', :nanoseconds
82
+ end
83
+
84
+ dispatch :from_string_hash do
85
+ param <<-TYPE, :hash_arg
86
+ Struct[{
87
+ string => String[1],
88
+ Optional[format] => Formats
89
+ }]
90
+ TYPE
91
+ end
92
+
93
+ dispatch :from_fields_hash do
94
+ param <<-TYPE, :hash_arg
95
+ Struct[{
96
+ Optional[negative] => Boolean,
97
+ Optional[days] => Integer,
98
+ Optional[hours] => Integer,
99
+ Optional[minutes] => Integer,
100
+ Optional[seconds] => Integer,
101
+ Optional[milliseconds] => Integer,
102
+ Optional[microseconds] => Integer,
103
+ Optional[nanoseconds] => Integer
104
+ }]
105
+ TYPE
106
+ end
107
+
108
+ def from_seconds(seconds)
109
+ Time::Timespan.new((seconds * Time::NSECS_PER_SEC).to_i)
110
+ end
111
+
112
+ def from_string(string, format = Time::Timespan::Format::DEFAULTS)
113
+ Time::Timespan.parse(string, format)
114
+ end
115
+
116
+ def from_fields(days, hours, minutes, seconds, milliseconds = 0, microseconds = 0, nanoseconds = 0)
117
+ Time::Timespan.from_fields(days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds)
118
+ end
119
+
120
+ def from_string_hash(args_hash)
121
+ Time::Timespan.from_string_hash(args_hash)
122
+ end
123
+
124
+ def from_fields_hash(args_hash)
125
+ Time::Timespan.from_fields_hash(args_hash)
126
+ end
127
+ end
128
+ end
129
+
130
+ def generalize
131
+ DEFAULT
132
+ end
133
+
134
+ def impl_class
135
+ Time::Timespan
136
+ end
137
+
138
+ DEFAULT = PTimespanType.new(nil, nil)
139
+ end
140
+ end
141
+ end