puppet-resource_api 1.9.0 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +64 -44
- data/lib/puppet/resource_api/base_context.rb +11 -7
- data/lib/puppet/resource_api/data_type_handling.rb +15 -19
- data/lib/puppet/resource_api/glue.rb +4 -7
- data/lib/puppet/resource_api/parameter.rb +2 -2
- data/lib/puppet/resource_api/property.rb +9 -14
- data/lib/puppet/resource_api/provider_get_cache.rb +41 -0
- data/lib/puppet/resource_api/puppet_context.rb +1 -0
- data/lib/puppet/resource_api/simple_provider.rb +19 -19
- data/lib/puppet/resource_api/transport/wrapper.rb +5 -3
- data/lib/puppet/resource_api/transport.rb +24 -31
- data/lib/puppet/resource_api/type_definition.rb +38 -45
- data/lib/puppet/resource_api/value_creator.rb +4 -6
- data/lib/puppet/resource_api/version.rb +1 -1
- data/lib/puppet/resource_api.rb +120 -91
- data/lib/puppet/util/network_device/simple/device.rb +2 -0
- metadata +8 -7
@@ -3,7 +3,7 @@
|
|
3
3
|
require 'puppet/util'
|
4
4
|
require 'puppet/parameter'
|
5
5
|
|
6
|
-
module Puppet; module ResourceApi; end; end # predeclare the main module # rubocop:disable Style/Documentation
|
6
|
+
module Puppet; module ResourceApi; end; end # predeclare the main module # rubocop:disable Style/Documentation
|
7
7
|
|
8
8
|
# Class containing parameter functionality for ResourceApi.
|
9
9
|
class Puppet::ResourceApi::Parameter < Puppet::Parameter
|
@@ -30,7 +30,7 @@ class Puppet::ResourceApi::Parameter < Puppet::Parameter
|
|
30
30
|
@data_type,
|
31
31
|
value,
|
32
32
|
"#{@type_name}.#{@attribute_name}",
|
33
|
-
Puppet::ResourceApi.caller_is_resource_app
|
33
|
+
Puppet::ResourceApi.caller_is_resource_app?
|
34
34
|
)
|
35
35
|
end
|
36
36
|
|
@@ -3,7 +3,7 @@
|
|
3
3
|
require 'puppet/util'
|
4
4
|
require 'puppet/property'
|
5
5
|
|
6
|
-
module Puppet; module ResourceApi; end; end # predeclare the main module # rubocop:disable Style/Documentation
|
6
|
+
module Puppet; module ResourceApi; end; end # predeclare the main module # rubocop:disable Style/Documentation
|
7
7
|
|
8
8
|
# Class containing property functionality for ResourceApi.
|
9
9
|
class Puppet::ResourceApi::Property < Puppet::Property
|
@@ -27,9 +27,7 @@ class Puppet::ResourceApi::Property < Puppet::Property
|
|
27
27
|
# Define class method insync?(is) if the custom_insync feature flag is set
|
28
28
|
if referrable_type&.type_definition&.feature?('custom_insync')
|
29
29
|
def_custom_insync?
|
30
|
-
if @attribute_name == :rsapi_custom_insync_trigger
|
31
|
-
@change_to_s_value = 'Custom insync logic determined that this resource is out of sync'
|
32
|
-
end
|
30
|
+
@change_to_s_value = 'Custom insync logic determined that this resource is out of sync' if @attribute_name == :rsapi_custom_insync_trigger
|
33
31
|
# Define class method insync?(is) if the name is :ensure and custom_insync feature flag is not set
|
34
32
|
elsif @attribute_name == :ensure
|
35
33
|
def_ensure_insync?
|
@@ -62,9 +60,7 @@ class Puppet::ResourceApi::Property < Puppet::Property
|
|
62
60
|
def should=(value)
|
63
61
|
@shouldorig = value
|
64
62
|
|
65
|
-
if @attribute_name == :ensure
|
66
|
-
value = value.to_s
|
67
|
-
end
|
63
|
+
value = value.to_s if @attribute_name == :ensure
|
68
64
|
|
69
65
|
# Puppet requires the @should value to always be stored as an array. We do not use this
|
70
66
|
# for anything else
|
@@ -74,8 +70,8 @@ class Puppet::ResourceApi::Property < Puppet::Property
|
|
74
70
|
@data_type,
|
75
71
|
value,
|
76
72
|
"#{@type_name}.#{@attribute_name}",
|
77
|
-
Puppet::ResourceApi.caller_is_resource_app
|
78
|
-
)
|
73
|
+
Puppet::ResourceApi.caller_is_resource_app?
|
74
|
+
)
|
79
75
|
]
|
80
76
|
end
|
81
77
|
|
@@ -104,21 +100,20 @@ class Puppet::ResourceApi::Property < Puppet::Property
|
|
104
100
|
|
105
101
|
provider_insync_result, change_message = provider.insync?(context, title, @attribute_name, is_hash, should_hash)
|
106
102
|
|
107
|
-
unless provider_insync_result.nil? || change_message.nil? || change_message.empty?
|
108
|
-
@change_to_s_value = change_message
|
109
|
-
end
|
103
|
+
@change_to_s_value = change_message unless provider_insync_result.nil? || change_message.nil? || change_message.empty?
|
110
104
|
|
111
105
|
case provider_insync_result
|
112
106
|
when nil
|
113
107
|
# If validating ensure and no custom insync was used, check if rs_value matches is.
|
114
108
|
return rs_value.to_s == is.to_s if @attribute_name == :ensure
|
109
|
+
|
115
110
|
# Otherwise, super and rely on Puppet::Property.insync?
|
116
111
|
super(is)
|
117
112
|
when TrueClass, FalseClass
|
118
|
-
|
113
|
+
provider_insync_result
|
119
114
|
else
|
120
115
|
# When returning anything else, raise a DevError for a non-idiomatic return
|
121
|
-
raise(Puppet::DevError, "Custom insync for #{@attribute_name} returned a #{provider_insync_result.class} with a value of #{provider_insync_result.inspect} instead of true/false; insync? MUST return nil or the boolean true or false") # rubocop:disable
|
116
|
+
raise(Puppet::DevError, "Custom insync for #{@attribute_name} returned a #{provider_insync_result.class} with a value of #{provider_insync_result.inspect} instead of true/false; insync? MUST return nil or the boolean true or false") # rubocop:disable Layout/LineLength
|
122
117
|
end
|
123
118
|
end
|
124
119
|
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# rubocop:disable Style/Documentation
|
4
|
+
module Puppet; end
|
5
|
+
module Puppet::ResourceApi; end
|
6
|
+
# rubocop:enable Style/Documentation
|
7
|
+
|
8
|
+
# This class provides a simple caching mechanism to support minimizing get()
|
9
|
+
# calls into a provider.
|
10
|
+
class Puppet::ResourceApi::ProviderGetCache
|
11
|
+
def initialize
|
12
|
+
clear
|
13
|
+
end
|
14
|
+
|
15
|
+
def clear
|
16
|
+
@cache = {}
|
17
|
+
@cached_all = false
|
18
|
+
end
|
19
|
+
|
20
|
+
def all
|
21
|
+
raise 'all method called, but cached_all not called' unless @cached_all
|
22
|
+
|
23
|
+
@cache.values
|
24
|
+
end
|
25
|
+
|
26
|
+
def add(key, value)
|
27
|
+
@cache[key] = value
|
28
|
+
end
|
29
|
+
|
30
|
+
def get(key)
|
31
|
+
@cache[key]
|
32
|
+
end
|
33
|
+
|
34
|
+
def cached_all
|
35
|
+
@cached_all = true
|
36
|
+
end
|
37
|
+
|
38
|
+
def cached_all?
|
39
|
+
@cached_all
|
40
|
+
end
|
41
|
+
end
|
@@ -9,6 +9,7 @@ class Puppet::ResourceApi::PuppetContext < Puppet::ResourceApi::BaseContext
|
|
9
9
|
def device
|
10
10
|
# TODO: evaluate facter_url setting for loading config if there is no `current` NetworkDevice
|
11
11
|
raise 'no device configured' unless Puppet::Util::NetworkDevice.current
|
12
|
+
|
12
13
|
Puppet::Util::NetworkDevice.current
|
13
14
|
end
|
14
15
|
|
@@ -6,15 +6,17 @@ module Puppet::ResourceApi
|
|
6
6
|
# This class provides a default implementation for set(), when your resource does not benefit from batching.
|
7
7
|
# Instead of processing changes yourself, the `create`, `update`, and `delete` functions, are called for you,
|
8
8
|
# with proper logging already set up.
|
9
|
-
# Note that your type needs to use `
|
10
|
-
# and absence of resources.
|
9
|
+
# Note that your type needs to use `ensure` in the conventional way with values of `prsesent`
|
10
|
+
# and `absent` to signal presence and absence of resources.
|
11
11
|
class SimpleProvider
|
12
12
|
def set(context, changes)
|
13
|
+
namevars = context.type.namevars
|
14
|
+
|
13
15
|
changes.each do |name, change|
|
14
16
|
is = if context.type.feature?('simple_get_filter')
|
15
|
-
change.key?(:is) ? change[:is] : (get(context, [name]) || []).find { |r| r
|
17
|
+
change.key?(:is) ? change[:is] : (get(context, [name]) || []).find { |r| SimpleProvider.build_name(namevars, r) == name }
|
16
18
|
else
|
17
|
-
change.key?(:is) ? change[:is] : (get(context) || []).find { |r| r
|
19
|
+
change.key?(:is) ? change[:is] : (get(context) || []).find { |r| SimpleProvider.build_name(namevars, r) == name }
|
18
20
|
end
|
19
21
|
context.type.check_schema(is) unless change.key?(:is)
|
20
22
|
|
@@ -22,13 +24,13 @@ module Puppet::ResourceApi
|
|
22
24
|
|
23
25
|
raise 'SimpleProvider cannot be used with a Type that is not ensurable' unless context.type.ensurable?
|
24
26
|
|
25
|
-
|
26
|
-
|
27
|
+
is_ensure = is.nil? ? 'absent' : is[:ensure].to_s
|
28
|
+
should_ensure = should.nil? ? 'absent' : should[:ensure].to_s
|
27
29
|
|
28
|
-
name_hash = if
|
30
|
+
name_hash = if namevars.length > 1
|
29
31
|
# pass a name_hash containing the values of all namevars
|
30
32
|
name_hash = {}
|
31
|
-
|
33
|
+
namevars.each do |namevar|
|
32
34
|
name_hash[namevar] = change[:should][namevar]
|
33
35
|
end
|
34
36
|
name_hash
|
@@ -36,15 +38,15 @@ module Puppet::ResourceApi
|
|
36
38
|
name
|
37
39
|
end
|
38
40
|
|
39
|
-
if
|
41
|
+
if is_ensure == 'absent' && should_ensure == 'present'
|
40
42
|
context.creating(name) do
|
41
43
|
create(context, name_hash, should)
|
42
44
|
end
|
43
|
-
elsif
|
45
|
+
elsif is_ensure == 'present' && should_ensure == 'absent'
|
44
46
|
context.deleting(name) do
|
45
47
|
delete(context, name_hash)
|
46
48
|
end
|
47
|
-
elsif
|
49
|
+
elsif is_ensure == 'present'
|
48
50
|
context.updating(name) do
|
49
51
|
update(context, name_hash, should)
|
50
52
|
end
|
@@ -65,14 +67,12 @@ module Puppet::ResourceApi
|
|
65
67
|
end
|
66
68
|
|
67
69
|
# @api private
|
68
|
-
def self.
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
result[:ensure] = 'absent'
|
75
|
-
result
|
70
|
+
def self.build_name(namevars, resource_hash)
|
71
|
+
if namevars.size > 1
|
72
|
+
Hash[namevars.map { |attr| [attr, resource_hash[attr]] }]
|
73
|
+
else
|
74
|
+
resource_hash[namevars[0]]
|
75
|
+
end
|
76
76
|
end
|
77
77
|
end
|
78
78
|
end
|
@@ -13,6 +13,7 @@ class Puppet::ResourceApi::Transport::Wrapper
|
|
13
13
|
url = URI.parse(url_or_config_or_transport)
|
14
14
|
raise "Unexpected url '#{url_or_config_or_transport}' found. Only file:/// URLs for configuration supported at the moment." unless url.scheme == 'file'
|
15
15
|
raise "Trying to load config from '#{url.path}, but file does not exist." if url && !File.exist?(url.path)
|
16
|
+
|
16
17
|
config = self.class.deep_symbolize(Hocon.load(url.path, syntax: Hocon::ConfigSyntax::HOCON) || {})
|
17
18
|
elsif url_or_config_or_transport.is_a? Hash
|
18
19
|
config = url_or_config_or_transport
|
@@ -25,7 +26,7 @@ class Puppet::ResourceApi::Transport::Wrapper
|
|
25
26
|
end
|
26
27
|
|
27
28
|
def transport_class?(name, transport)
|
28
|
-
class_name = name.split('_').map
|
29
|
+
class_name = name.split('_').map(&:capitalize).join
|
29
30
|
expected = Puppet::Transport.const_get(class_name).to_s
|
30
31
|
expected == transport.class.to_s
|
31
32
|
end
|
@@ -40,9 +41,9 @@ class Puppet::ResourceApi::Transport::Wrapper
|
|
40
41
|
(@transport.respond_to? name) || super
|
41
42
|
end
|
42
43
|
|
43
|
-
def method_missing(method_name,
|
44
|
+
def method_missing(method_name, ...)
|
44
45
|
if @transport.respond_to? method_name
|
45
|
-
@transport.send(method_name,
|
46
|
+
@transport.send(method_name, ...)
|
46
47
|
else
|
47
48
|
super
|
48
49
|
end
|
@@ -52,6 +53,7 @@ class Puppet::ResourceApi::Transport::Wrapper
|
|
52
53
|
def self.deep_symbolize(obj)
|
53
54
|
return obj.each_with_object({}) { |(k, v), memo| memo[k.to_sym] = deep_symbolize(v); } if obj.is_a? Hash
|
54
55
|
return obj.each_with_object([]) { |v, memo| memo << deep_symbolize(v); } if obj.is_a? Array
|
56
|
+
|
55
57
|
obj
|
56
58
|
end
|
57
59
|
end
|
@@ -5,26 +5,26 @@ module Puppet::ResourceApi; end # rubocop:disable Style/Documentation
|
|
5
5
|
# Remote target transport API
|
6
6
|
module Puppet::ResourceApi::Transport
|
7
7
|
def register(schema)
|
8
|
-
raise Puppet::DevError, 'requires a hash as schema, not
|
8
|
+
raise Puppet::DevError, format('requires a hash as schema, not `%<other_type>s`', other_type: schema.class) unless schema.is_a? Hash
|
9
9
|
raise Puppet::DevError, 'requires a `:name`' unless schema.key? :name
|
10
10
|
raise Puppet::DevError, 'requires `:desc`' unless schema.key? :desc
|
11
11
|
raise Puppet::DevError, 'requires `:connection_info`' unless schema.key? :connection_info
|
12
|
-
raise Puppet::DevError, '`:connection_info` must be a hash, not
|
12
|
+
raise Puppet::DevError, format('`:connection_info` must be a hash, not `%<other_type>s`', other_type: schema[:connection_info].class) unless schema[:connection_info].is_a?(Hash)
|
13
|
+
|
13
14
|
if schema[:connection_info_order].nil?
|
14
15
|
schema[:connection_info_order] = schema[:connection_info].keys
|
15
16
|
else
|
16
|
-
|
17
|
+
unless schema[:connection_info_order].is_a?(Array)
|
18
|
+
raise Puppet::DevError,
|
19
|
+
format('`:connection_info_order` must be an array, not `%<other_type>s`', other_type: schema[:connection_info_order].class)
|
20
|
+
end
|
17
21
|
end
|
18
22
|
|
19
|
-
unless transports[schema[:name]].nil?
|
20
|
-
|
21
|
-
name: schema[:name],
|
22
|
-
environment: current_environment_name,
|
23
|
-
}
|
24
|
-
end
|
23
|
+
raise Puppet::DevError, format('Transport `%<name>s` is already registered for `%<environment>s`', name: schema[:name], environment: current_environment_name) unless transports[schema[:name]].nil?
|
24
|
+
|
25
25
|
transports[schema[:name]] = Puppet::ResourceApi::TransportSchemaDef.new(schema)
|
26
26
|
end
|
27
|
-
module_function :register
|
27
|
+
module_function :register
|
28
28
|
|
29
29
|
# retrieve a Hash of transport schemas, keyed by their name.
|
30
30
|
# Only already loaded transports are returned.
|
@@ -33,7 +33,7 @@ module Puppet::ResourceApi::Transport
|
|
33
33
|
def list
|
34
34
|
Marshal.load(Marshal.dump(transports))
|
35
35
|
end
|
36
|
-
module_function :list
|
36
|
+
module_function :list
|
37
37
|
|
38
38
|
# retrieve a Hash of transport schemas, keyed by their name.
|
39
39
|
# This uses the Puppet autoloader, provide an environment name as `force_environment`
|
@@ -46,7 +46,7 @@ module Puppet::ResourceApi::Transport
|
|
46
46
|
Marshal.load(Marshal.dump(transports))
|
47
47
|
end
|
48
48
|
end
|
49
|
-
module_function :list_all_transports
|
49
|
+
module_function :list_all_transports
|
50
50
|
|
51
51
|
# Loads all schemas using the Puppet Autoloader. This method is clearing the cache and forcing `Kernel.load`, so that the cache is up-to-date.
|
52
52
|
def self.load_all_schemas
|
@@ -73,10 +73,10 @@ module Puppet::ResourceApi::Transport
|
|
73
73
|
def connect(name, connection_info)
|
74
74
|
validate(name, connection_info)
|
75
75
|
require "puppet/transport/#{name}"
|
76
|
-
class_name = name.split('_').map
|
76
|
+
class_name = name.split('_').map(&:capitalize).join
|
77
77
|
Puppet::Transport.const_get(class_name).new(get_context(name), wrap_sensitive(name, connection_info))
|
78
78
|
end
|
79
|
-
module_function :connect
|
79
|
+
module_function :connect
|
80
80
|
|
81
81
|
def inject_device(name, transport)
|
82
82
|
transport_wrapper = Puppet::ResourceApi::Transport::Wrapper.new(name, transport)
|
@@ -87,21 +87,14 @@ module Puppet::ResourceApi::Transport
|
|
87
87
|
Puppet::Util::NetworkDevice.instance_variable_set(:@current, transport_wrapper)
|
88
88
|
end
|
89
89
|
end
|
90
|
-
module_function :inject_device
|
90
|
+
module_function :inject_device
|
91
91
|
|
92
92
|
def self.validate(name, connection_info)
|
93
93
|
require "puppet/transport/schema/#{name}" unless transports.key? name
|
94
94
|
transport_schema = transports[name]
|
95
|
-
if transport_schema.nil?
|
96
|
-
raise Puppet::DevError, 'Transport for `%{target}` not registered with `%{environment}`' % {
|
97
|
-
target: name,
|
98
|
-
environment: current_environment_name,
|
99
|
-
}
|
100
|
-
end
|
95
|
+
raise Puppet::DevError, format('Transport for `%<target>s` not registered with `%<environment>s`', target: name, environment: current_environment_name) if transport_schema.nil?
|
101
96
|
|
102
|
-
if connection_info.key?(:
|
103
|
-
clean_bolt_attributes(transport_schema, connection_info)
|
104
|
-
end
|
97
|
+
clean_bolt_attributes(transport_schema, connection_info) if connection_info.key?(:'remote-transport')
|
105
98
|
|
106
99
|
apply_defaults(transport_schema, connection_info)
|
107
100
|
message_prefix = 'The connection info provided does not match the Transport Schema'
|
@@ -133,7 +126,7 @@ module Puppet::ResourceApi::Transport
|
|
133
126
|
context = get_context(transport_schema.name)
|
134
127
|
transport_schema.attributes.each do |attr_name, options|
|
135
128
|
if options.key?(:default) && connection_info.key?(attr_name) == false
|
136
|
-
context.debug('Using default value for attribute:
|
129
|
+
context.debug(format('Using default value for attribute: %<attribute_name>s, value: %<default_value>s', attribute_name: attr_name, default_value: options[:default].inspect))
|
137
130
|
connection_info[attr_name] = options[:default]
|
138
131
|
end
|
139
132
|
end
|
@@ -161,25 +154,25 @@ module Puppet::ResourceApi::Transport
|
|
161
154
|
context = get_context(transport_schema.name)
|
162
155
|
|
163
156
|
# Attributes we expect from bolt, but want to ignore if the transport does not expect them
|
164
|
-
[
|
157
|
+
%i[uri host protocol user port password].each do |attribute_name|
|
165
158
|
if connection_info.key?(attribute_name) && !transport_schema.attributes.key?(attribute_name)
|
166
|
-
context.info('Discarding superfluous bolt attribute:
|
159
|
+
context.info(format('Discarding superfluous bolt attribute: %<attribute_name>s', attribute_name: attribute_name))
|
167
160
|
connection_info.delete(attribute_name)
|
168
161
|
end
|
169
162
|
end
|
170
163
|
|
171
164
|
# Attributes that bolt emits, but we want to ignore if the transport does not expect them
|
172
|
-
([
|
165
|
+
(%i[name path query run-on remote-transport implementations] + connection_info.keys.select { |k| k.to_s.start_with? 'remote-' }).each do |attribute_name|
|
173
166
|
if connection_info.key?(attribute_name) && !transport_schema.attributes.key?(attribute_name)
|
174
|
-
context.debug('Discarding bolt metaparameter:
|
167
|
+
context.debug(format('Discarding bolt metaparameter: %<attribute_name>s', attribute_name: attribute_name))
|
175
168
|
connection_info.delete(attribute_name)
|
176
169
|
end
|
177
170
|
end
|
178
171
|
|
179
172
|
# remove any other attributes the transport is not prepared to handle
|
180
|
-
connection_info.
|
173
|
+
connection_info.each_key do |attribute_name|
|
181
174
|
if connection_info.key?(attribute_name) && !transport_schema.attributes.key?(attribute_name)
|
182
|
-
context.warning('Discarding unknown attribute:
|
175
|
+
context.warning(format('Discarding unknown attribute: %<attribute_name>s', attribute_name: attribute_name))
|
183
176
|
connection_info.delete(attribute_name)
|
184
177
|
end
|
185
178
|
end
|
@@ -25,12 +25,12 @@ module Puppet::ResourceApi
|
|
25
25
|
end
|
26
26
|
|
27
27
|
def validate_schema(definition, attr_key)
|
28
|
-
super
|
29
|
-
[
|
30
|
-
raise Puppet::DevError, 'must not define an attribute called
|
28
|
+
super
|
29
|
+
%i[title provider alias audit before consume export loglevel noop notify require schedule stage subscribe tag].each do |name|
|
30
|
+
raise Puppet::DevError, format('must not define an attribute called `%<name>s`', name: name.inspect) if definition[attr_key].key? name
|
31
31
|
end
|
32
32
|
if definition.key?(:title_patterns) && !definition[:title_patterns].is_a?(Array)
|
33
|
-
raise Puppet::DevError, '`:title_patterns` must be an array, not
|
33
|
+
raise Puppet::DevError, format('`:title_patterns` must be an array, not `%<other_type>s`', other_type: definition[:title_patterns].class)
|
34
34
|
end
|
35
35
|
|
36
36
|
Puppet::ResourceApi::DataTypeHandling.validate_ensure(definition)
|
@@ -54,9 +54,7 @@ module Puppet::ResourceApi
|
|
54
54
|
# options: The hash of attribute options, including type, desc, default, and behaviour
|
55
55
|
def create_attribute_in(type, attribute_name, param_or_property, parent, options)
|
56
56
|
type.send(param_or_property, attribute_name.to_sym, parent: parent) do
|
57
|
-
if options[:desc]
|
58
|
-
desc "#{options[:desc]} (a #{options[:type]})"
|
59
|
-
end
|
57
|
+
desc "#{options[:desc]} (a #{options[:type]})" if options[:desc]
|
60
58
|
|
61
59
|
# The initialize method is called when puppet core starts building up
|
62
60
|
# type objects. The core passes in a hash of shape { resource:
|
@@ -70,9 +68,9 @@ module Puppet::ResourceApi
|
|
70
68
|
|
71
69
|
# get pops data type object for this parameter or property
|
72
70
|
define_singleton_method(:data_type) do
|
73
|
-
@rsapi_data_type ||= Puppet::ResourceApi::DataTypeHandling.parse_puppet_type(
|
71
|
+
@rsapi_data_type ||= Puppet::ResourceApi::DataTypeHandling.parse_puppet_type( # rubocop:disable Naming/MemoizedInstanceVariableName
|
74
72
|
attribute_name,
|
75
|
-
options[:type]
|
73
|
+
options[:type]
|
76
74
|
)
|
77
75
|
end
|
78
76
|
|
@@ -82,7 +80,7 @@ module Puppet::ResourceApi
|
|
82
80
|
self,
|
83
81
|
data_type,
|
84
82
|
param_or_property,
|
85
|
-
options
|
83
|
+
options
|
86
84
|
)
|
87
85
|
end
|
88
86
|
end
|
@@ -101,12 +99,10 @@ module Puppet::ResourceApi
|
|
101
99
|
attributes.each do |name, _options|
|
102
100
|
type = @data_type_cache[attributes[name][:type]]
|
103
101
|
|
104
|
-
if resource[name].nil? && !(type.instance_of? Puppet::Pops::Types::POptionalType)
|
105
|
-
missing_attrs << name
|
106
|
-
end
|
102
|
+
missing_attrs << name if resource[name].nil? && !(type.instance_of? Puppet::Pops::Types::POptionalType)
|
107
103
|
end
|
108
104
|
|
109
|
-
error_msg = "The following mandatory attributes were not provided:\n *
|
105
|
+
error_msg = "The following mandatory attributes were not provided:\n * #{missing_attrs.join(", \n * ")}"
|
110
106
|
raise Puppet::ResourceError, error_msg if missing_attrs.any?
|
111
107
|
end
|
112
108
|
|
@@ -131,57 +127,54 @@ module Puppet::ResourceApi
|
|
131
127
|
end
|
132
128
|
|
133
129
|
def namevars
|
134
|
-
@namevars ||= attributes.select
|
130
|
+
@namevars ||= attributes.select do |_name, options|
|
135
131
|
options.key?(:behaviour) && options[:behaviour] == :namevar
|
136
|
-
|
132
|
+
end.keys
|
137
133
|
end
|
138
134
|
|
139
135
|
def insyncable_attributes
|
140
|
-
@insyncable_attributes ||= attributes.reject
|
136
|
+
@insyncable_attributes ||= attributes.reject do |_name, options|
|
141
137
|
# Only attributes without any behavior are normal Puppet Properties and get insynced
|
142
138
|
options.key?(:behaviour)
|
143
|
-
|
139
|
+
end.keys
|
144
140
|
end
|
145
141
|
|
146
142
|
def validate_schema(definition, attr_key)
|
147
|
-
raise Puppet::DevError, '
|
143
|
+
raise Puppet::DevError, format('%<type_class>s must be a Hash, not `%<other_type>s`', type_class: self.class.name, other_type: definition.class) unless definition.is_a?(Hash)
|
144
|
+
|
148
145
|
@attributes = definition[attr_key]
|
149
|
-
raise Puppet::DevError, '
|
150
|
-
raise Puppet::DevError, '
|
151
|
-
|
152
|
-
|
153
|
-
name: definition[:name], attrs: attr_key, other_type: attributes.class
|
154
|
-
}
|
155
|
-
end
|
146
|
+
raise Puppet::DevError, format('%<type_class>s must have a name', type_class: self.class.name) unless definition.key? :name
|
147
|
+
raise Puppet::DevError, format('%<type_class>s must have `%<attr_key>s`', type_class: self.class.name, attrs: attr_key) unless definition.key? attr_key
|
148
|
+
|
149
|
+
raise Puppet::DevError, format('`%<name>s.%<attrs>s` must be a hash, not `%<other_type>s`', name: definition[:name], attrs: attr_key, other_type: attributes.class) unless attributes.is_a?(Hash)
|
156
150
|
|
157
151
|
# fixup desc/docs backwards compatibility
|
158
152
|
if definition.key? :docs
|
159
|
-
if definition[:desc]
|
160
|
-
|
161
|
-
end
|
153
|
+
raise Puppet::DevError, format('`%<name>s` has both `desc` and `docs`, prefer using `desc`', name: definition[:name]) if definition[:desc]
|
154
|
+
|
162
155
|
definition[:desc] = definition[:docs]
|
163
156
|
definition.delete(:docs)
|
164
157
|
end
|
165
|
-
Puppet.warning('
|
158
|
+
Puppet.warning(format('`%<name>s` has no documentation, add it using a `desc` key', name: definition[:name])) unless definition.key? :desc
|
166
159
|
|
167
160
|
attributes.each do |key, attr|
|
168
|
-
raise Puppet::DevError, '`rsapi_custom_insync_trigger` cannot be specified as an attribute; it is reserved for propertyless types with the custom_insync feature' if key == :rsapi_custom_insync_trigger # rubocop:disable
|
161
|
+
raise Puppet::DevError, '`rsapi_custom_insync_trigger` cannot be specified as an attribute; it is reserved for propertyless types with the custom_insync feature' if key == :rsapi_custom_insync_trigger # rubocop:disable Layout/LineLength
|
169
162
|
raise Puppet::DevError, "`#{definition[:name]}.#{key}` must be a Hash, not a #{attr.class}" unless attr.is_a? Hash
|
170
163
|
raise Puppet::DevError, "`#{definition[:name]}.#{key}` has no type" unless attr.key? :type
|
171
|
-
|
164
|
+
|
165
|
+
Puppet.warning(format('`%<name>s.%<key>s` has no documentation, add it using a `desc` key', name: definition[:name], key: key)) unless attr.key? :desc
|
172
166
|
|
173
167
|
# validate the type by attempting to parse into a puppet type
|
174
168
|
@data_type_cache[attributes[key][:type]] ||=
|
175
169
|
Puppet::ResourceApi::DataTypeHandling.parse_puppet_type(
|
176
170
|
key,
|
177
|
-
attributes[key][:type]
|
171
|
+
attributes[key][:type]
|
178
172
|
)
|
179
173
|
|
180
174
|
# fixup any weird behavior ;-)
|
181
175
|
next unless attr[:behavior]
|
182
|
-
if attr[:behaviour]
|
183
|
-
|
184
|
-
end
|
176
|
+
raise Puppet::DevError, "the '#{key}' attribute has both a `behavior` and a `behaviour`, only use one" if attr[:behaviour]
|
177
|
+
|
185
178
|
attr[:behaviour] = attr[:behavior]
|
186
179
|
attr.delete(:behavior)
|
187
180
|
end
|
@@ -190,9 +183,7 @@ module Puppet::ResourceApi
|
|
190
183
|
# validates a resource hash against its type schema
|
191
184
|
def check_schema(resource, message_prefix = nil)
|
192
185
|
namevars.each do |namevar|
|
193
|
-
if resource[namevar].nil?
|
194
|
-
raise Puppet::ResourceError, "`#{name}.get` did not return a value for the `#{namevar}` namevar attribute"
|
195
|
-
end
|
186
|
+
raise Puppet::ResourceError, "`#{name}.get` did not return a value for the `#{namevar}` namevar attribute" if resource[namevar].nil?
|
196
187
|
end
|
197
188
|
|
198
189
|
message_prefix = 'Provider returned data that does not match the Type Schema' if message_prefix.nil?
|
@@ -216,12 +207,13 @@ module Puppet::ResourceApi
|
|
216
207
|
end
|
217
208
|
|
218
209
|
def notify_schema_errors(message)
|
219
|
-
|
210
|
+
case Puppet.settings[:strict]
|
211
|
+
when :off
|
220
212
|
Puppet.debug(message)
|
221
|
-
|
213
|
+
when :warning
|
222
214
|
Puppet::ResourceApi.warning_count += 1
|
223
215
|
Puppet.warning(message) if Puppet::ResourceApi.warning_count <= 100 # maximum number of schema warnings to display in a run
|
224
|
-
|
216
|
+
when :error
|
225
217
|
raise Puppet::DevError, message
|
226
218
|
end
|
227
219
|
end
|
@@ -240,15 +232,16 @@ module Puppet::ResourceApi
|
|
240
232
|
bad_vals = {}
|
241
233
|
resource.each do |key, value|
|
242
234
|
next unless attributes[key]
|
235
|
+
|
243
236
|
type = @data_type_cache[attributes[key][:type]]
|
244
|
-
is_sensitive =
|
237
|
+
is_sensitive = attributes[key].key?(:sensitive) && (attributes[key][:sensitive] == true)
|
245
238
|
error_message = Puppet::ResourceApi::DataTypeHandling.try_validate(
|
246
239
|
type,
|
247
240
|
value,
|
248
|
-
''
|
241
|
+
''
|
249
242
|
)
|
250
243
|
if is_sensitive
|
251
|
-
bad_vals[key] =
|
244
|
+
bad_vals[key] = "<< redacted value >> #{error_message}" unless error_message.nil?
|
252
245
|
else
|
253
246
|
bad_vals[key] = "#{value} (#{error_message})" unless error_message.nil?
|
254
247
|
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
module Puppet; module ResourceApi; end; end # predeclare the main module # rubocop:disable Style/Documentation
|
3
|
+
module Puppet; module ResourceApi; end; end # predeclare the main module # rubocop:disable Style/Documentation
|
4
4
|
|
5
5
|
# This module is responsible for setting default and alias values for the
|
6
6
|
# resource class.
|
@@ -36,14 +36,12 @@ module Puppet::ResourceApi::ValueCreator
|
|
36
36
|
end
|
37
37
|
|
38
38
|
# provide hints to `puppet type generate` for better parsing
|
39
|
-
if data_type.instance_of? Puppet::Pops::Types::POptionalType
|
40
|
-
data_type = data_type.type
|
41
|
-
end
|
39
|
+
data_type = data_type.type if data_type.instance_of? Puppet::Pops::Types::POptionalType
|
42
40
|
|
43
41
|
case data_type
|
44
42
|
when Puppet::Pops::Types::PStringType
|
45
43
|
# require any string value
|
46
|
-
def_newvalues(attribute_class, param_or_property,
|
44
|
+
def_newvalues(attribute_class, param_or_property, //)
|
47
45
|
when Puppet::Pops::Types::PBooleanType
|
48
46
|
def_newvalues(attribute_class, param_or_property, 'true', 'false')
|
49
47
|
attribute_class.aliasvalue true, 'true'
|
@@ -51,7 +49,7 @@ module Puppet::ResourceApi::ValueCreator
|
|
51
49
|
attribute_class.aliasvalue :true, 'true' # rubocop:disable Lint/BooleanSymbol
|
52
50
|
attribute_class.aliasvalue :false, 'false' # rubocop:disable Lint/BooleanSymbol
|
53
51
|
when Puppet::Pops::Types::PIntegerType
|
54
|
-
def_newvalues(attribute_class, param_or_property,
|
52
|
+
def_newvalues(attribute_class, param_or_property, /^-?\d+$/)
|
55
53
|
when Puppet::Pops::Types::PFloatType, Puppet::Pops::Types::PNumericType
|
56
54
|
def_newvalues(attribute_class, param_or_property, Puppet::Pops::Patterns::NUMERIC)
|
57
55
|
end
|