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.
- checksums.yaml +4 -4
- data/lib/bolt/cli.rb +65 -28
- data/lib/bolt/config.rb +18 -8
- data/lib/bolt/executor.rb +21 -6
- data/lib/bolt/node.rb +3 -0
- data/lib/bolt/node/result.rb +5 -0
- data/lib/bolt/node/ssh.rb +81 -25
- data/lib/bolt/node/winrm.rb +70 -31
- data/lib/bolt/notifier.rb +20 -0
- data/lib/bolt/outputter.rb +21 -0
- data/lib/bolt/outputter/human.rb +30 -0
- data/lib/bolt/outputter/json.rb +51 -0
- data/lib/bolt/result.rb +32 -5
- data/lib/bolt/version.rb +1 -1
- data/vendored/puppet/lib/puppet.rb +4 -5
- data/vendored/puppet/lib/puppet/agent.rb +22 -2
- data/vendored/puppet/lib/puppet/application/agent.rb +1 -1
- data/vendored/puppet/lib/puppet/application/apply.rb +1 -1
- data/vendored/puppet/lib/puppet/configurer/downloader_factory.rb +10 -0
- data/vendored/puppet/lib/puppet/configurer/plugin_handler.rb +4 -4
- data/vendored/puppet/lib/puppet/defaults.rb +21 -2
- data/vendored/puppet/lib/puppet/external/nagios/parser.rb +1 -1
- data/vendored/puppet/lib/puppet/file_serving/configuration.rb +3 -0
- data/vendored/puppet/lib/puppet/file_serving/configuration/parser.rb +2 -0
- data/vendored/puppet/lib/puppet/file_serving/mount/locales.rb +35 -0
- data/vendored/puppet/lib/puppet/forge.rb +9 -3
- data/vendored/puppet/lib/puppet/forge/repository.rb +1 -1
- data/vendored/puppet/lib/puppet/functions/file_upload.rb +20 -15
- data/vendored/puppet/lib/puppet/functions/new.rb +1 -4
- data/vendored/puppet/lib/puppet/functions/run_command.rb +15 -13
- data/vendored/puppet/lib/puppet/functions/run_script.rb +27 -14
- data/vendored/puppet/lib/puppet/functions/run_task.rb +21 -19
- data/vendored/puppet/lib/puppet/gettext/config.rb +86 -28
- data/vendored/puppet/lib/puppet/indirector/catalog/compiler.rb +25 -5
- data/vendored/puppet/lib/puppet/indirector/file_bucket_file/file.rb +1 -1
- data/vendored/puppet/lib/puppet/module.rb +13 -17
- data/vendored/puppet/lib/puppet/pops/evaluator/access_operator.rb +20 -21
- data/vendored/puppet/lib/puppet/pops/evaluator/compare_operator.rb +3 -3
- data/vendored/puppet/lib/puppet/pops/evaluator/evaluator_impl.rb +9 -0
- data/vendored/puppet/lib/puppet/pops/loader/static_loader.rb +20 -1
- data/vendored/puppet/lib/puppet/pops/loader/task_instantiator.rb +2 -1
- data/vendored/puppet/lib/puppet/pops/loaders.rb +6 -41
- data/vendored/puppet/lib/puppet/pops/pcore.rb +9 -0
- data/vendored/puppet/lib/puppet/pops/serialization/from_data_converter.rb +64 -10
- data/vendored/puppet/lib/puppet/pops/serialization/json_path.rb +2 -1
- data/vendored/puppet/lib/puppet/pops/types/execution_result.rb +7 -4
- data/vendored/puppet/lib/puppet/pops/types/p_binary_type.rb +9 -2
- data/vendored/puppet/lib/puppet/pops/types/p_init_type.rb +1 -1
- data/vendored/puppet/lib/puppet/pops/types/p_meta_type.rb +4 -0
- data/vendored/puppet/lib/puppet/pops/types/p_object_type.rb +81 -4
- data/vendored/puppet/lib/puppet/pops/types/p_object_type_extension.rb +213 -0
- data/vendored/puppet/lib/puppet/pops/types/p_sem_ver_type.rb +10 -2
- data/vendored/puppet/lib/puppet/pops/types/puppet_object.rb +11 -1
- data/vendored/puppet/lib/puppet/pops/types/type_calculator.rb +2 -2
- data/vendored/puppet/lib/puppet/pops/types/type_factory.rb +16 -6
- data/vendored/puppet/lib/puppet/pops/types/type_formatter.rb +22 -14
- data/vendored/puppet/lib/puppet/pops/types/type_parser.rb +17 -15
- data/vendored/puppet/lib/puppet/pops/types/types.rb +181 -72
- data/vendored/puppet/lib/puppet/provider.rb +18 -8
- data/vendored/puppet/lib/puppet/provider/package/yum.rb +22 -7
- data/vendored/puppet/lib/puppet/provider/service/base.rb +21 -8
- data/vendored/puppet/lib/puppet/provider/service/launchd.rb +2 -3
- data/vendored/puppet/lib/puppet/provider/user/aix.rb +1 -0
- data/vendored/puppet/lib/puppet/provider/user/user_role_add.rb +7 -1
- data/vendored/puppet/lib/puppet/provider/user/useradd.rb +3 -2
- data/vendored/puppet/lib/puppet/provider/zfs/zfs.rb +5 -1
- data/vendored/puppet/lib/puppet/type/exec.rb +5 -4
- data/vendored/puppet/lib/puppet/type/macauthorization.rb +1 -1
- data/vendored/puppet/lib/puppet/type/user.rb +19 -0
- data/vendored/puppet/lib/puppet/util/log/destinations.rb +10 -0
- data/vendored/puppet/lib/puppet/util/windows/file.rb +35 -4
- data/vendored/puppet/lib/puppet/vendor/semantic_puppet/lib/semantic_puppet.rb +1 -1
- data/vendored/puppet/lib/puppet/version.rb +1 -1
- data/vendored/puppet/lib/puppet_pal.rb +15 -5
- metadata +8 -3
- data/vendored/puppet/lib/puppet/pops/types/p_error_type.rb +0 -158
@@ -42,6 +42,15 @@ module Pcore
|
|
42
42
|
if Puppet[:tasks]
|
43
43
|
require_relative 'types/task'
|
44
44
|
require_relative 'types/execution_result'
|
45
|
+
|
46
|
+
add_object_type('Target', <<-PUPPET, loader)
|
47
|
+
{
|
48
|
+
attributes => {
|
49
|
+
host => String[1],
|
50
|
+
options => { type => Hash[String[1], Data], value => {} }
|
51
|
+
}
|
52
|
+
}
|
53
|
+
PUPPET
|
45
54
|
end
|
46
55
|
Types::TypedModelObject.register_ptypes(loader, ir)
|
47
56
|
|
@@ -1,5 +1,57 @@
|
|
1
1
|
module Puppet::Pops
|
2
2
|
module Serialization
|
3
|
+
class Builder
|
4
|
+
def initialize(values)
|
5
|
+
@values = values
|
6
|
+
@resolved = true
|
7
|
+
end
|
8
|
+
|
9
|
+
def [](key)
|
10
|
+
@values[key]
|
11
|
+
end
|
12
|
+
|
13
|
+
def []=(key, value)
|
14
|
+
@values[key] = value
|
15
|
+
@resolved = false if value.is_a?(Builder)
|
16
|
+
end
|
17
|
+
|
18
|
+
def resolve
|
19
|
+
unless @resolved
|
20
|
+
@resolved = true
|
21
|
+
if @values.is_a?(Array)
|
22
|
+
@values.each_with_index { |v, idx| @values[idx] = v.resolve if v.is_a?(Builder) }
|
23
|
+
elsif @values.is_a?(Hash)
|
24
|
+
@values.each_pair { |k, v| @values[k] = v.resolve if v.is_a?(Builder) }
|
25
|
+
end
|
26
|
+
end
|
27
|
+
@values
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
class ObjectHashBuilder < Builder
|
32
|
+
def initialize(instance)
|
33
|
+
super({})
|
34
|
+
@instance = instance
|
35
|
+
end
|
36
|
+
|
37
|
+
def resolve
|
38
|
+
@instance._pcore_init_from_hash(super)
|
39
|
+
@instance
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
class ObjectArrayBuilder < Builder
|
44
|
+
def initialize(instance)
|
45
|
+
super({})
|
46
|
+
@instance = instance
|
47
|
+
end
|
48
|
+
|
49
|
+
def resolve
|
50
|
+
@instance.send(:initialize, *super.values)
|
51
|
+
@instance
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
3
55
|
# Class that can process the `Data` produced by the {ToDataConverter} class and reassemble
|
4
56
|
# the objects that were converted.
|
5
57
|
#
|
@@ -137,9 +189,16 @@ module Serialization
|
|
137
189
|
end
|
138
190
|
|
139
191
|
def build(value, &block)
|
140
|
-
|
141
|
-
|
142
|
-
|
192
|
+
vx = Builder.new(value)
|
193
|
+
@current[@key] = vx unless @current.nil?
|
194
|
+
with_value(vx, &block) if block_given?
|
195
|
+
vx.resolve
|
196
|
+
end
|
197
|
+
|
198
|
+
def build_object(builder, &block)
|
199
|
+
@current[@key] = builder unless @current.nil?
|
200
|
+
with_value(builder, &block) if block_given?
|
201
|
+
builder.resolve
|
143
202
|
end
|
144
203
|
|
145
204
|
def pcore_type_hash_to_value(pcore_type, value)
|
@@ -148,14 +207,9 @@ module Serialization
|
|
148
207
|
if value.empty?
|
149
208
|
build(pcore_type.create)
|
150
209
|
elsif pcore_type.implementation_class.respond_to?(:_pcore_init_from_hash)
|
151
|
-
|
152
|
-
@current._pcore_init_from_hash(with_value({}) { value.each_pair { |key, elem| with(key) { convert(elem) } } })
|
153
|
-
end
|
210
|
+
build_object(ObjectHashBuilder.new(pcore_type.allocate)) { value.each_pair { |key, elem| with(key) { convert(elem) } } }
|
154
211
|
else
|
155
|
-
|
156
|
-
args = with_value([]) { value.values.each_with_index { |elem, idx| with(idx) { convert(elem) }}}
|
157
|
-
@current.send(:initialize, *args)
|
158
|
-
end
|
212
|
+
build_object(ObjectArrayBuilder.new(pcore_type.allocate)) { value.each_pair { |key, elem| with(key) { convert(elem) } } }
|
159
213
|
end
|
160
214
|
elsif value.is_a?(String)
|
161
215
|
build(pcore_type.create(value))
|
@@ -47,7 +47,8 @@ module JsonPath
|
|
47
47
|
#
|
48
48
|
def resolve(context, path)
|
49
49
|
factory = @parser.parse_string(path)
|
50
|
-
resolve_any(factory.model.body, context, path)
|
50
|
+
v = resolve_any(factory.model.body, context, path)
|
51
|
+
v.is_a?(Builder) ? v.resolve : v
|
51
52
|
end
|
52
53
|
|
53
54
|
def resolve_any(ast, context, path)
|
@@ -62,7 +62,8 @@ module Types
|
|
62
62
|
|
63
63
|
def error_nodes
|
64
64
|
result = {}
|
65
|
-
|
65
|
+
t = TypeFactory.error
|
66
|
+
@result_hash.each_pair { |k, v| result[k] = v if t.instance?(v) }
|
66
67
|
self.class.new(result)
|
67
68
|
end
|
68
69
|
|
@@ -75,13 +76,15 @@ module Types
|
|
75
76
|
end
|
76
77
|
|
77
78
|
def ok
|
78
|
-
|
79
|
+
t = TypeFactory.error
|
80
|
+
!@result_hash.values.any? { |v| t.instance?(v) }
|
79
81
|
end
|
80
82
|
alias_method :ok?, :ok
|
81
83
|
|
82
84
|
def ok_nodes
|
83
85
|
result = {}
|
84
|
-
|
86
|
+
t = TypeFactory.error
|
87
|
+
@result_hash.each_pair { |k, v| result[k] = v unless t.instance?(v) }
|
85
88
|
self.class.new(result)
|
86
89
|
end
|
87
90
|
|
@@ -116,7 +119,7 @@ module Types
|
|
116
119
|
if error.nil?
|
117
120
|
value
|
118
121
|
else
|
119
|
-
|
122
|
+
TypeFactory.error.create(error['msg'], error['kind'], error['issue_code'], value, error['details'])
|
120
123
|
end
|
121
124
|
end
|
122
125
|
|
@@ -2,8 +2,15 @@ require 'base64'
|
|
2
2
|
module Puppet::Pops
|
3
3
|
module Types
|
4
4
|
|
5
|
-
# A Puppet Language Type that
|
6
|
-
#
|
5
|
+
# A Puppet Language Type that represents binary data content (a sequence of 8-bit bytes).
|
6
|
+
# Instances of this data type can be created from `String` and `Array[Integer[0,255]]`
|
7
|
+
# values. Also see the `binary_file` function for reading binary content from a file.
|
8
|
+
#
|
9
|
+
# A `Binary` can be converted to `String` and `Array` form - see function `new` for
|
10
|
+
# the respective target data type for more information.
|
11
|
+
#
|
12
|
+
# Instances of this data type serialize as base 64 encoded strings when the serialization
|
13
|
+
# format is textual, and as binary content when a serialization format supports this.
|
7
14
|
#
|
8
15
|
# @api public
|
9
16
|
class PBinaryType < PAnyType
|
@@ -156,7 +156,7 @@ class PInitType < PTypeWithContainedType
|
|
156
156
|
rescue ArgumentError
|
157
157
|
raise ArgumentError, _("Creation of new instance of type '%{type_name}' is not supported") % { type_name: @type.to_s }
|
158
158
|
end
|
159
|
-
param_tuples = new_func.dispatcher.
|
159
|
+
param_tuples = new_func.dispatcher.signatures.map { |closure| closure.type.param_types }
|
160
160
|
|
161
161
|
# An instance of the contained type is always a match to this type.
|
162
162
|
single_types = [@type]
|
@@ -13,6 +13,7 @@ KEY_FUNCTIONS = 'functions'.freeze
|
|
13
13
|
KEY_KIND = 'kind'.freeze
|
14
14
|
KEY_OVERRIDE = 'override'.freeze
|
15
15
|
KEY_PARENT = 'parent'.freeze
|
16
|
+
KEY_TYPE_PARAMETERS = 'type_parameters'.freeze
|
16
17
|
|
17
18
|
# @api public
|
18
19
|
class PObjectType < PMetaType
|
@@ -34,8 +35,14 @@ class PObjectType < PMetaType
|
|
34
35
|
TypeFactory.optional(KEY_ANNOTATIONS) => TYPE_ANNOTATIONS
|
35
36
|
})
|
36
37
|
|
38
|
+
TYPE_PARAMETER = TypeFactory.struct({
|
39
|
+
KEY_TYPE => PTypeType::DEFAULT,
|
40
|
+
TypeFactory.optional(KEY_ANNOTATIONS) => TYPE_ANNOTATIONS
|
41
|
+
})
|
42
|
+
|
37
43
|
TYPE_CONSTANTS = TypeFactory.hash_kv(Pcore::TYPE_MEMBER_NAME, PAnyType::DEFAULT)
|
38
44
|
TYPE_ATTRIBUTES = TypeFactory.hash_kv(Pcore::TYPE_MEMBER_NAME, TypeFactory.not_undef)
|
45
|
+
TYPE_PARAMETERS = TypeFactory.hash_kv(Pcore::TYPE_MEMBER_NAME, TypeFactory.not_undef)
|
39
46
|
TYPE_ATTRIBUTE_CALLABLE = TypeFactory.callable(0,0)
|
40
47
|
|
41
48
|
TYPE_FUNCTION_TYPE = PTypeType.new(PCallableType::DEFAULT)
|
@@ -55,6 +62,7 @@ class PObjectType < PMetaType
|
|
55
62
|
TYPE_OBJECT_I12N = TypeFactory.struct({
|
56
63
|
TypeFactory.optional(KEY_NAME) => TYPE_OBJECT_NAME,
|
57
64
|
TypeFactory.optional(KEY_PARENT) => PTypeType::DEFAULT,
|
65
|
+
TypeFactory.optional(KEY_TYPE_PARAMETERS) => TYPE_PARAMETERS,
|
58
66
|
TypeFactory.optional(KEY_ATTRIBUTES) => TYPE_ATTRIBUTES,
|
59
67
|
TypeFactory.optional(KEY_CONSTANTS) => TYPE_CONSTANTS,
|
60
68
|
TypeFactory.optional(KEY_FUNCTIONS) => TYPE_FUNCTIONS,
|
@@ -335,6 +343,22 @@ class PObjectType < PMetaType
|
|
335
343
|
end
|
336
344
|
end
|
337
345
|
|
346
|
+
class PTypeParameter < PAttribute
|
347
|
+
# @return [Hash{String=>Object}] the hash
|
348
|
+
# @api private
|
349
|
+
def _pcore_init_hash
|
350
|
+
hash = super
|
351
|
+
hash[KEY_TYPE] = hash[KEY_TYPE].type
|
352
|
+
hash.delete(KEY_VALUE) if hash.include?(KEY_VALUE) && hash[KEY_VALUE].nil?
|
353
|
+
hash
|
354
|
+
end
|
355
|
+
|
356
|
+
# @api private
|
357
|
+
def self.feature_type
|
358
|
+
'type_parameter'
|
359
|
+
end
|
360
|
+
end
|
361
|
+
|
338
362
|
# Describes a named Function in an Object type
|
339
363
|
# @api public
|
340
364
|
class PFunction < PAnnotatedMember
|
@@ -359,8 +383,6 @@ class PObjectType < PMetaType
|
|
359
383
|
|
360
384
|
attr_reader :name
|
361
385
|
attr_reader :parent
|
362
|
-
attr_reader :attributes
|
363
|
-
attr_reader :functions
|
364
386
|
attr_reader :equality
|
365
387
|
attr_reader :checks
|
366
388
|
attr_reader :annotations
|
@@ -387,6 +409,7 @@ class PObjectType < PMetaType
|
|
387
409
|
_pcore_init_from_hash(_pcore_init_hash)
|
388
410
|
@loader = init_hash_expression unless init_hash_expression.nil?
|
389
411
|
else
|
412
|
+
@type_parameters = EMPTY_HASH
|
390
413
|
@attributes = EMPTY_HASH
|
391
414
|
@functions = EMPTY_HASH
|
392
415
|
@name = TypeAsserter.assert_instance_of('object name', TYPE_OBJECT_NAME, _pcore_init_hash)
|
@@ -595,6 +618,7 @@ class PObjectType < PMetaType
|
|
595
618
|
# @api private
|
596
619
|
def _pcore_init_from_hash(init_hash)
|
597
620
|
TypeAsserter.assert_instance_of('object initializer', TYPE_OBJECT_I12N, init_hash)
|
621
|
+
@type_parameters = EMPTY_HASH
|
598
622
|
@attributes = EMPTY_HASH
|
599
623
|
@functions = EMPTY_HASH
|
600
624
|
|
@@ -605,6 +629,7 @@ class PObjectType < PMetaType
|
|
605
629
|
@parent = init_hash[KEY_PARENT]
|
606
630
|
|
607
631
|
parent_members = EMPTY_HASH
|
632
|
+
parent_type_params = EMPTY_HASH
|
608
633
|
parent_object_type = nil
|
609
634
|
unless @parent.nil?
|
610
635
|
check_self_recursion(self)
|
@@ -613,6 +638,24 @@ class PObjectType < PMetaType
|
|
613
638
|
if rp.is_a?(PObjectType)
|
614
639
|
parent_object_type = rp
|
615
640
|
parent_members = rp.members(true)
|
641
|
+
parent_type_params = rp.type_parameters(true)
|
642
|
+
end
|
643
|
+
end
|
644
|
+
|
645
|
+
type_parameters = init_hash[KEY_TYPE_PARAMETERS]
|
646
|
+
unless type_parameters.nil? || type_parameters.empty?
|
647
|
+
@type_parameters = {}
|
648
|
+
type_parameters.each do |key, param_spec|
|
649
|
+
param_value = :undef
|
650
|
+
if param_spec.is_a?(Hash)
|
651
|
+
param_type = param_spec[KEY_TYPE]
|
652
|
+
param_value = param_spec[KEY_VALUE] if param_spec.include?(KEY_VALUE)
|
653
|
+
else
|
654
|
+
param_type = TypeAsserter.assert_instance_of(nil, PTypeType::DEFAULT, param_spec) { "type_parameter #{label}[#{key}]" }
|
655
|
+
end
|
656
|
+
param_type = POptionalType.new(param_type) unless param_type.is_a?(POptionalType)
|
657
|
+
type_param = PTypeParameter.new(key, self, KEY_TYPE => param_type, KEY_VALUE => param_value).assert_override(parent_type_params)
|
658
|
+
@type_parameters[key] = type_param
|
616
659
|
end
|
617
660
|
end
|
618
661
|
|
@@ -634,7 +677,7 @@ class PObjectType < PMetaType
|
|
634
677
|
KEY_KIND => ATTRIBUTE_KIND_CONSTANT
|
635
678
|
}
|
636
679
|
# Indicate override if parent member exists. Type check etc. will take place later on.
|
637
|
-
attr_spec[KEY_OVERRIDE] =
|
680
|
+
attr_spec[KEY_OVERRIDE] = parent_members.include?(key)
|
638
681
|
attr_specs[key] = attr_spec
|
639
682
|
end
|
640
683
|
end
|
@@ -715,6 +758,7 @@ class PObjectType < PMetaType
|
|
715
758
|
guarded_recursion(guard, nil) do |g|
|
716
759
|
super(visitor, g)
|
717
760
|
@parent.accept(visitor, g) unless parent.nil?
|
761
|
+
@type_parameters.values.each { |p| p.accept(visitor, g) }
|
718
762
|
@attributes.values.each { |a| a.accept(visitor, g) }
|
719
763
|
@functions.values.each { |f| f.accept(visitor, g) }
|
720
764
|
end
|
@@ -771,6 +815,7 @@ class PObjectType < PMetaType
|
|
771
815
|
result = super()
|
772
816
|
result[KEY_NAME] = @name if include_name && !@name.nil?
|
773
817
|
result[KEY_PARENT] = @parent unless @parent.nil?
|
818
|
+
result[KEY_TYPE_PARAMETERS] = compressed_members_hash(@type_parameters) unless @type_parameters.empty?
|
774
819
|
unless @attributes.empty?
|
775
820
|
# Divide attributes into constants and others
|
776
821
|
tc = TypeCalculator.singleton
|
@@ -795,6 +840,7 @@ class PObjectType < PMetaType
|
|
795
840
|
self.class == o.class &&
|
796
841
|
@name == o.name &&
|
797
842
|
@parent == o.parent &&
|
843
|
+
@type_parameters == o.type_parameters &&
|
798
844
|
@attributes == o.attributes &&
|
799
845
|
@functions == o.functions &&
|
800
846
|
@equality == o.equality &&
|
@@ -802,7 +848,7 @@ class PObjectType < PMetaType
|
|
802
848
|
end
|
803
849
|
|
804
850
|
def hash
|
805
|
-
@name.nil? ? [@parent, @attributes, @functions].hash : @name.hash
|
851
|
+
@name.nil? ? [@parent, @type_parameters, @attributes, @functions].hash : @name.hash
|
806
852
|
end
|
807
853
|
|
808
854
|
def kind_of_callable?(optional=true, guard = nil)
|
@@ -817,6 +863,14 @@ class PObjectType < PMetaType
|
|
817
863
|
@parent.nil? ? false : @parent.iterable_type(guard)
|
818
864
|
end
|
819
865
|
|
866
|
+
def parameterized?
|
867
|
+
if @type_parameters.empty?
|
868
|
+
@parent.is_a?(PObjectType) ? @parent.parameterized? : false
|
869
|
+
else
|
870
|
+
true
|
871
|
+
end
|
872
|
+
end
|
873
|
+
|
820
874
|
# Returns the members (attributes and functions) of this `Object` type. If _include_parent_ is `true`, then all
|
821
875
|
# inherited members will be included in the returned `Hash`.
|
822
876
|
#
|
@@ -891,6 +945,18 @@ class PObjectType < PMetaType
|
|
891
945
|
label.split(DOUBLE_COLON).last
|
892
946
|
end
|
893
947
|
|
948
|
+
# Returns the type_parameters of this `Object` type. If _include_parent_ is `true`, then all
|
949
|
+
# inherited type_parameters will be included in the returned `Hash`.
|
950
|
+
#
|
951
|
+
# @param include_parent [Boolean] `true` if inherited type_parameters should be included
|
952
|
+
# @return [Hash{String=>PTypeParameter}] a hash with the type_parameters
|
953
|
+
# @api public
|
954
|
+
def type_parameters(include_parent = false)
|
955
|
+
all = {}
|
956
|
+
collect_type_parameters(all, include_parent)
|
957
|
+
all
|
958
|
+
end
|
959
|
+
|
894
960
|
protected
|
895
961
|
|
896
962
|
# An Object type is only assignable from another Object type. The other type
|
@@ -903,6 +969,8 @@ class PObjectType < PMetaType
|
|
903
969
|
op = o.parent
|
904
970
|
op.nil? ? false : assignable?(op, guard)
|
905
971
|
end
|
972
|
+
elsif o.is_a?(PObjectTypeExtension)
|
973
|
+
assignable?(o.base_type, guard)
|
906
974
|
else
|
907
975
|
false
|
908
976
|
end
|
@@ -936,6 +1004,15 @@ class PObjectType < PMetaType
|
|
936
1004
|
nil
|
937
1005
|
end
|
938
1006
|
|
1007
|
+
def collect_type_parameters(collector, include_parent)
|
1008
|
+
if include_parent
|
1009
|
+
parent = resolved_parent
|
1010
|
+
parent.collect_type_parameters(collector, include_parent) if parent.is_a?(PObjectType)
|
1011
|
+
end
|
1012
|
+
collector.merge!(@type_parameters)
|
1013
|
+
nil
|
1014
|
+
end
|
1015
|
+
|
939
1016
|
private
|
940
1017
|
|
941
1018
|
def compressed_members_hash(features)
|
@@ -0,0 +1,213 @@
|
|
1
|
+
module Puppet::Pops
|
2
|
+
module Types
|
3
|
+
|
4
|
+
# Base class for Parameterized Object implementations. The wrapper impersonates the base
|
5
|
+
# object and extends it with methods to filter assignable types and instances based on parameter
|
6
|
+
# values.
|
7
|
+
#
|
8
|
+
# @api public
|
9
|
+
class PObjectTypeExtension < PAnyType
|
10
|
+
def self.register_ptype(loader, ir)
|
11
|
+
create_ptype(loader, ir, 'AnyType',
|
12
|
+
'base_type' => {
|
13
|
+
KEY_TYPE => PTypeType::DEFAULT
|
14
|
+
},
|
15
|
+
'init_parameters' => {
|
16
|
+
KEY_TYPE => PArrayType::DEFAULT
|
17
|
+
}
|
18
|
+
)
|
19
|
+
end
|
20
|
+
|
21
|
+
attr_reader :base_type, :parameters
|
22
|
+
|
23
|
+
# @api private
|
24
|
+
def self.create(base_type, init_parameters)
|
25
|
+
impl_class = Loaders.implementation_registry.module_for_type("#{base_type.name}TypeExtension") || self
|
26
|
+
impl_class.new(base_type, init_parameters)
|
27
|
+
end
|
28
|
+
|
29
|
+
# @api private
|
30
|
+
def initialize(base_type, init_parameters)
|
31
|
+
pts = base_type.type_parameters(true)
|
32
|
+
raise Puppet::ParseError, _('The %{label}-Type cannot be parameterized using []') % { label: base_type.label } if pts.empty?
|
33
|
+
@base_type = base_type
|
34
|
+
|
35
|
+
named_args = false
|
36
|
+
if init_parameters.is_a?(PuppetObject)
|
37
|
+
init_parameters = parameters_from_instance(init_parameters, pts)
|
38
|
+
else
|
39
|
+
named_args = init_parameters.size == 1 && init_parameters[0].is_a?(Hash)
|
40
|
+
if named_args
|
41
|
+
# Catch case when first parameter is an assignable Hash
|
42
|
+
named_args = pts.size >= 1 && !pts.values[0].type.instance?(init_parameters[0])
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
by_name = {}
|
47
|
+
if named_args
|
48
|
+
hash = init_parameters[0]
|
49
|
+
hash.each_pair do |pn, pv|
|
50
|
+
tp = pts[pn]
|
51
|
+
if tp.nil?
|
52
|
+
raise Puppet::ParseError, _("'%{pn}' is not a known type parameter for %{label}-Type") % { pn: pn, label: base_type.label }
|
53
|
+
end
|
54
|
+
by_name[pn] = check_param(tp, pv) unless pv == :default
|
55
|
+
end
|
56
|
+
else
|
57
|
+
pts.values.each_with_index do |tp, idx|
|
58
|
+
if idx < init_parameters.size
|
59
|
+
pv = init_parameters[idx]
|
60
|
+
by_name[tp.name] = check_param(tp, pv) unless pv == :default
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
if by_name.empty?
|
65
|
+
raise Puppet::ParseError, _('The %{label}-Type cannot be parameterized using an empty parameter list') % { label: base_type.label }
|
66
|
+
end
|
67
|
+
@parameters = by_name
|
68
|
+
end
|
69
|
+
|
70
|
+
def check_param(type_param, v)
|
71
|
+
TypeAsserter.assert_instance_of(nil, type_param.type, v) { type_param.label }
|
72
|
+
end
|
73
|
+
|
74
|
+
# Return the parameter values as positional arguments with unset values as :default. The
|
75
|
+
# array is stripped from trailing :default values
|
76
|
+
# @return [Array] the parameter values
|
77
|
+
# @api private
|
78
|
+
def init_parameters
|
79
|
+
pts = @base_type.type_parameters(true)
|
80
|
+
if pts.size > 2
|
81
|
+
@parameters
|
82
|
+
else
|
83
|
+
result = pts.values.map do |tp|
|
84
|
+
pn = tp.name
|
85
|
+
@parameters.include?(pn) ? @parameters[pn] : :default
|
86
|
+
end
|
87
|
+
# Remove trailing defaults
|
88
|
+
result.pop while result.last == :default
|
89
|
+
result
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
# @api private
|
94
|
+
def eql?(o)
|
95
|
+
super(o) && @base_type.eql?(o.base_type) && @parameters.eql?(o.parameters)
|
96
|
+
end
|
97
|
+
|
98
|
+
# @api private
|
99
|
+
def generalize
|
100
|
+
@base_type
|
101
|
+
end
|
102
|
+
|
103
|
+
# @api private
|
104
|
+
def hash
|
105
|
+
@base_type.hash ^ @parameters.hash
|
106
|
+
end
|
107
|
+
|
108
|
+
# @api private
|
109
|
+
def loader
|
110
|
+
@base_type.loader
|
111
|
+
end
|
112
|
+
|
113
|
+
# @api private
|
114
|
+
def check_self_recursion(originator)
|
115
|
+
@base_type.check_self_recursion(originator)
|
116
|
+
end
|
117
|
+
|
118
|
+
# @api private
|
119
|
+
def create(*args)
|
120
|
+
@base_type.create(*args)
|
121
|
+
end
|
122
|
+
|
123
|
+
# @api private
|
124
|
+
def instance?(o, guard = nil)
|
125
|
+
@base_type.instance?(o, guard) && test_instance?(o, guard)
|
126
|
+
end
|
127
|
+
|
128
|
+
# @api private
|
129
|
+
def new_function
|
130
|
+
@base_type.new_function
|
131
|
+
end
|
132
|
+
|
133
|
+
# @api private
|
134
|
+
def simple_name
|
135
|
+
@base_type.simple_name
|
136
|
+
end
|
137
|
+
|
138
|
+
protected
|
139
|
+
|
140
|
+
# Creates an array of type parameters from the attributes that matches the
|
141
|
+
# type parameters by name. Type parameters for which there is no matching attribute
|
142
|
+
# will have `nil` in their corresponding position on the array.
|
143
|
+
#
|
144
|
+
# @return [Array] array of values from instance that maps to type parameters
|
145
|
+
def parameters_from_instance(instance, type_parameters)
|
146
|
+
attrs = @base_type.attributes(true)
|
147
|
+
type_parameters.keys.map do |pn|
|
148
|
+
attr = attrs[pn]
|
149
|
+
attr.nil? ? nil : instance.send(pn)
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
# Checks that the given `param_values` hash contains all keys present in the `parameters` of
|
154
|
+
# this instance and that each keyed value is a match for the given parameter. The match is done
|
155
|
+
# using case expression semantics.
|
156
|
+
#
|
157
|
+
# This method is only called when a given type is found to be assignable to the base type of
|
158
|
+
# this extension.
|
159
|
+
#
|
160
|
+
# @param param_values[Hash] the parameter values of the assignable type
|
161
|
+
# @param guard[RecursionGuard] guard against endless recursion
|
162
|
+
# @return [Boolean] true or false to indicate assignability
|
163
|
+
# @api public
|
164
|
+
def test_assignable?(param_values, guard)
|
165
|
+
# Default implementation performs case expression style matching of all parameter values
|
166
|
+
# provided that the value exist (this should always be the case, since all defaults have
|
167
|
+
# been assigned at this point)
|
168
|
+
eval = Parser::EvaluatingParser.singleton.evaluator
|
169
|
+
@parameters.keys.all? do |pn|
|
170
|
+
if param_values.include?(pn)
|
171
|
+
a = param_values[pn]
|
172
|
+
b = @parameters[pn]
|
173
|
+
eval.match?(a, b) || a.is_a?(PAnyType) && b.is_a?(PAnyType) && b.assignable?(a)
|
174
|
+
else
|
175
|
+
false
|
176
|
+
end
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
# Checks that the given instance `o` has one attribute for each key present in the `parameters` of
|
181
|
+
# this instance and that each attribute value is a match for the given parameter. The match is done
|
182
|
+
# using case expression semantics.
|
183
|
+
#
|
184
|
+
# This method is only called when the given value is found to be an instance of the base type of
|
185
|
+
# this extension.
|
186
|
+
#
|
187
|
+
# @param o [Object] the instance to test
|
188
|
+
# @param guard[RecursionGuard] guard against endless recursion
|
189
|
+
# @return [Boolean] true or false to indicate if the value is an instance or not
|
190
|
+
# @api public
|
191
|
+
def test_instance?(o, guard)
|
192
|
+
eval = Parser::EvaluatingParser.singleton.evaluator
|
193
|
+
@parameters.keys.all? do |pn|
|
194
|
+
begin
|
195
|
+
m = o.public_method(pn)
|
196
|
+
m.arity == 0 ? eval.match?(m.call, @parameters[pn]) : false
|
197
|
+
rescue NameError
|
198
|
+
false
|
199
|
+
end
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
# @api private
|
204
|
+
def _assignable?(o, guard = nil)
|
205
|
+
if o.is_a?(PObjectTypeExtension)
|
206
|
+
@base_type.assignable?(o.base_type, guard) && test_assignable?(o.parameters, guard)
|
207
|
+
else
|
208
|
+
@base_type.assignable?(o, guard) && test_assignable?(EMPTY_HASH, guard)
|
209
|
+
end
|
210
|
+
end
|
211
|
+
end
|
212
|
+
end
|
213
|
+
end
|