puppet-resource_api 1.7.0 → 1.8.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +1 -2
- data/.travis.yml +3 -8
- data/CHANGELOG.md +51 -0
- data/lib/puppet/resource_api.rb +19 -3
- data/lib/puppet/resource_api/base_context.rb +20 -6
- data/lib/puppet/resource_api/io_context.rb +6 -1
- data/lib/puppet/resource_api/puppet_context.rb +6 -0
- data/lib/puppet/resource_api/transport.rb +95 -0
- data/lib/puppet/resource_api/transport/wrapper.rb +55 -0
- data/lib/puppet/resource_api/type_definition.rb +156 -113
- data/lib/puppet/resource_api/version.rb +1 -1
- metadata +5 -4
- data/.rubocop_todo.yml +0 -17
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: '066920a9f1eca6ad946f2c8f39239482a2d00b756a9ac26db2441c4015a6aa37'
|
4
|
+
data.tar.gz: b9f87949cc263e98ead6d3fc5dcc480787a8122078e548bb135a2f1c21373f30
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c61a6bc59301a6214c53470b213d59493a31056f20b02ab6f6688ee9809f3f0a05494b66e8c2c0daa28fb222af85f132867a4b1164121ac1aa4f184d60a2acda
|
7
|
+
data.tar.gz: 393f017b70985894eb1f5abe4ecd0ec41d6640bd5d57fa288fb2a66acfc202dcb42b1c11fda89ec1e4c694a688442555015465a8e4ffd6354150da59f245faae
|
data/.rubocop.yml
CHANGED
@@ -1,6 +1,5 @@
|
|
1
1
|
---
|
2
2
|
require: rubocop-rspec
|
3
|
-
inherit_from: .rubocop_todo.yml
|
4
3
|
AllCops:
|
5
4
|
TargetRubyVersion: '2.1'
|
6
5
|
Include:
|
@@ -157,4 +156,4 @@ Naming/UncommunicativeMethodParamName:
|
|
157
156
|
|
158
157
|
# This cop breaks syntax highlighting in VSCode
|
159
158
|
Layout/ClosingHeredocIndentation:
|
160
|
-
Enabled: false
|
159
|
+
Enabled: false
|
data/.travis.yml
CHANGED
@@ -25,7 +25,7 @@ matrix:
|
|
25
25
|
- env: RVM="jruby-9.1.9.0" PUPPET_GEM_VERSION='~> 5' JRUBY_OPTS="--debug"
|
26
26
|
before_cache: pushd ~/.rvm && rm -rf archives rubies/ruby-2.2.7 rubies/ruby-2.3.4 && popd
|
27
27
|
cache:
|
28
|
-
bundler:
|
28
|
+
bundler: false
|
29
29
|
directories: ~/.rvm
|
30
30
|
before_install: rvm use jruby-9.1.9.0 --install --binary --fuzzy
|
31
31
|
- rvm: 2.4.3
|
@@ -65,10 +65,5 @@ matrix:
|
|
65
65
|
- rvm: 2.5.1
|
66
66
|
env: PUPPET_GEM_VERSION='https://github.com/puppetlabs/puppet.git#6.0.x'
|
67
67
|
notifications:
|
68
|
-
|
69
|
-
|
70
|
-
secure: 10a49kkZcghKHNnef8x7eBG+KjScL3i1VpygFg6DPAOK2YNbEoyEx1Kv9KLC7GSRYov/SQZOsZrvHZtDhEtFSKhhiAjOwxl1jV1t6aAMGMnN1IoZBOvdAJKrZsm54/bBeYp+je2wqnnoFNtLVFSoOX0LkFaDEWT+zGZ5xKJIH25GpeQEZf1eDxs/d8YX/m+RwbGXHVA//hOpvZo0ntvznh2EbW5OPODKSeUXbWZ+W4ndODTsKWFc/WLMSSgFDzW/Y2/9V40D4IC8lvSx6eKFryMfAQy6pO/d1aTB468awzyVcdYAMMCOITm7hlKGRKxNgq6NkOsXs5KLg6ifpn+a/Rhapbz6Qxbpjjho/7Wxngl4B3T+i35ap/mFrS/fOfKCq3gEQlYn29its9bEFArNGbr+/sXKABb+sRpgW4RTPWYDHJyHJendbevd5tZ+fd0JUBOi0Cb4PcXxQxM8IQrbuu2zso0K5MV05kL0S1DE/VsuUrPaK0RsF+b1+i6NfvtN8kgbYs1eiVku+guIG2ec3xIefQ1hsEOFPFNqSDfHp7nANnRVIbBCt8qw8DhmNEczsfN5Dp21euJUsO9qpau++NzD3jRhkE5Zki5cwsakU7hIQzw82BIb0eSQJCHygieExeEboWRqtDgy/IKIWPgIvEuU68ppR2bl2reKCHLCnWc=
|
71
|
-
template:
|
72
|
-
- '%{repository}#%{build_number} (%{branch} - %{commit} : %{author}): %{message}
|
73
|
-
(<a href="%{build_url}">Details</a> | <a href="%{compare_url}">PR/Diff</a>)'
|
74
|
-
format: html
|
68
|
+
slack:
|
69
|
+
secure: aPXZYNow8LsmmlS8PQU3FjL0bc7FqUUA95d++wZfIu7YAjGboIUiekxYouQ0XnY+Aig8InvbTOIgBHgGNheyr/YFbFS90/jtulbF8oW7BitW+imgjeAHDCwlQZTCc4FFYde/2pI7QTT8H5NpLR9mKxlTU77Sqr8gFAIybuPdHcKMYQZdEZS07ma2pUp7+GyKS6PDQpzW2+mDCz/wfi3/JdsUvc0mclCZ8vxySc66j5P1E6nFDMzuakBOjwJHpgeDpreapbmSUQLAX0a3ZsFP+N+SNduLotlV2BWnJK2gcO6rGFP4Fz1D0bGXuBnYYdIiB+9OgI3wtXg9y1SifNHUG3IrOBAA8CGNyrebTGKtH0TS2O+HZLbaNX2g6udD5e3156vys9wScmJuQ/rSkVtQfXf1qUm5eijvlXI+DIbssbZHqm6QQGyM4p3NoULmNmF1C85bQoZ4GF7b1P/8mstsVE/HUfnzRPNbwD0r6j1aE/ck3PKMi7ZAhIi0Ja9RnAgP3wi0t62uERYcJGGYEycWohMWnrf2w6GFwGeuoiwAkASdHOLX0/AOMPc4mBOjlc621o8uYMrrZqfF5CrOAvJ151USSsWn2AhXaibIvnHo6X91paNvvNpU/GYu3CUAl6q8OhYovvjtRVPVnhs2DrpgoRB+6NWHnzjRG/wr6Z9U+vA=
|
data/CHANGELOG.md
CHANGED
@@ -3,6 +3,57 @@
|
|
3
3
|
All significant changes to this repo will be summarized in this file.
|
4
4
|
|
5
5
|
|
6
|
+
## [v1.8.0](https://github.com/puppetlabs/puppet-resource_api/tree/v1.8.0) (2019-02-26)
|
7
|
+
[Full Changelog](https://github.com/puppetlabs/puppet-resource_api/compare/v1.7.0...v1.8.0)
|
8
|
+
|
9
|
+
**Implemented enhancements:**
|
10
|
+
|
11
|
+
- \(FM-7695\) Transports - the remote content framework [\#157](https://github.com/puppetlabs/puppet-resource_api/pull/157) ([DavidS](https://github.com/DavidS))
|
12
|
+
- \(FM-7698\) implement `sensitive:true` handling [\#156](https://github.com/puppetlabs/puppet-resource_api/pull/156) ([da-ar](https://github.com/da-ar))
|
13
|
+
- \(PDK-1271\) Allow a transport to be wrapped and used like a device [\#155](https://github.com/puppetlabs/puppet-resource_api/pull/155) ([da-ar](https://github.com/da-ar))
|
14
|
+
- \(FM-7701\) Support device providers when using Transport Wrapper [\#154](https://github.com/puppetlabs/puppet-resource_api/pull/154) ([da-ar](https://github.com/da-ar))
|
15
|
+
- \(FM-7726\) implement `context.transport` to provide access [\#152](https://github.com/puppetlabs/puppet-resource_api/pull/152) ([DavidS](https://github.com/DavidS))
|
16
|
+
- \(FM-7674\) Allow wrapping a Transport in a legacy Device [\#149](https://github.com/puppetlabs/puppet-resource_api/pull/149) ([da-ar](https://github.com/da-ar))
|
17
|
+
- \(FM-7600\) Add Transport.connect method [\#148](https://github.com/puppetlabs/puppet-resource_api/pull/148) ([da-ar](https://github.com/da-ar))
|
18
|
+
|
19
|
+
**Fixed bugs:**
|
20
|
+
|
21
|
+
- \(FM-7690\) Fix transports cache to be environment aware [\#151](https://github.com/puppetlabs/puppet-resource_api/pull/151) ([da-ar](https://github.com/da-ar))
|
22
|
+
|
23
|
+
**Merged pull requests:**
|
24
|
+
|
25
|
+
- \(FM-7726\) cleanups for the transport [\#153](https://github.com/puppetlabs/puppet-resource_api/pull/153) ([DavidS](https://github.com/DavidS))
|
26
|
+
- \(FM-7691,FM-7696\) refactoring definition handling in contexts [\#150](https://github.com/puppetlabs/puppet-resource_api/pull/150) ([DavidS](https://github.com/DavidS))
|
27
|
+
|
28
|
+
## [v1.7.0](https://github.com/puppetlabs/puppet-resource_api/tree/v1.7.0) (2019-01-07)
|
29
|
+
[Full Changelog](https://github.com/puppetlabs/puppet-resource_api/compare/v1.6.3...v1.7.0)
|
30
|
+
|
31
|
+
**Implemented enhancements:**
|
32
|
+
|
33
|
+
- \(maint\) Validate Type Schema [\#142](https://github.com/puppetlabs/puppet-resource_api/pull/142) ([da-ar](https://github.com/da-ar))
|
34
|
+
|
35
|
+
**Merged pull requests:**
|
36
|
+
|
37
|
+
- \(maint\) Bundler 2.0 dropped support for Ruby versions \< 2.2 [\#147](https://github.com/puppetlabs/puppet-resource_api/pull/147) ([da-ar](https://github.com/da-ar))
|
38
|
+
- \(FM-7597\) RSAPI Transport register function [\#146](https://github.com/puppetlabs/puppet-resource_api/pull/146) ([da-ar](https://github.com/da-ar))
|
39
|
+
- \(packaging\) Update version to 1.7.0 [\#144](https://github.com/puppetlabs/puppet-resource_api/pull/144) ([branan](https://github.com/branan))
|
40
|
+
|
41
|
+
## [v1.6.3](https://github.com/puppetlabs/puppet-resource_api/tree/v1.6.3) (2018-12-11)
|
42
|
+
[Full Changelog](https://github.com/puppetlabs/puppet-resource_api/compare/v1.6.2...v1.6.3)
|
43
|
+
|
44
|
+
**Closed issues:**
|
45
|
+
|
46
|
+
- Trying to understand stubbing in the examples [\#136](https://github.com/puppetlabs/puppet-resource_api/issues/136)
|
47
|
+
|
48
|
+
**Merged pull requests:**
|
49
|
+
|
50
|
+
- \(packaging\) Update version to 1.6.3 [\#143](https://github.com/puppetlabs/puppet-resource_api/pull/143) ([branan](https://github.com/branan))
|
51
|
+
- Move parameter and property logic to separate classes [\#140](https://github.com/puppetlabs/puppet-resource_api/pull/140) ([bpietraga](https://github.com/bpietraga))
|
52
|
+
- \(maint\) Predeclare Puppet module before ResourceApi [\#139](https://github.com/puppetlabs/puppet-resource_api/pull/139) ([caseywilliams](https://github.com/caseywilliams))
|
53
|
+
- \(maint\) minor fix to make data\_type\_handling change work [\#138](https://github.com/puppetlabs/puppet-resource_api/pull/138) ([DavidS](https://github.com/DavidS))
|
54
|
+
- \(maint\) extract data type handling code [\#137](https://github.com/puppetlabs/puppet-resource_api/pull/137) ([bpietraga](https://github.com/bpietraga))
|
55
|
+
- Release prep for v1.6.2 [\#135](https://github.com/puppetlabs/puppet-resource_api/pull/135) ([DavidS](https://github.com/DavidS))
|
56
|
+
|
6
57
|
## [v1.6.2](https://github.com/puppetlabs/puppet-resource_api/tree/v1.6.2) (2018-10-25)
|
7
58
|
[Full Changelog](https://github.com/puppetlabs/puppet-resource_api/compare/v1.6.1...v1.6.2)
|
8
59
|
|
data/lib/puppet/resource_api.rb
CHANGED
@@ -5,12 +5,15 @@ require 'puppet/resource_api/parameter'
|
|
5
5
|
require 'puppet/resource_api/property'
|
6
6
|
require 'puppet/resource_api/puppet_context' unless RUBY_PLATFORM == 'java'
|
7
7
|
require 'puppet/resource_api/read_only_parameter'
|
8
|
+
require 'puppet/resource_api/transport'
|
9
|
+
require 'puppet/resource_api/transport/wrapper'
|
8
10
|
require 'puppet/resource_api/type_definition'
|
9
11
|
require 'puppet/resource_api/value_creator'
|
10
12
|
require 'puppet/resource_api/version'
|
11
13
|
require 'puppet/type'
|
12
14
|
require 'puppet/util/network_device'
|
13
15
|
|
16
|
+
# This module contains the main API to register and access types, providers and transports.
|
14
17
|
module Puppet::ResourceApi
|
15
18
|
@warning_count = 0
|
16
19
|
|
@@ -38,7 +41,12 @@ module Puppet::ResourceApi
|
|
38
41
|
# Keeps a copy of the provider around. Weird naming to avoid clashes with puppet's own `provider` member
|
39
42
|
define_singleton_method(:my_provider) do
|
40
43
|
@my_provider ||= Hash.new { |hash, key| hash[key] = Puppet::ResourceApi.load_provider(definition[:name]).new }
|
41
|
-
|
44
|
+
|
45
|
+
if Puppet::Util::NetworkDevice.current.is_a? Puppet::ResourceApi::Transport::Wrapper
|
46
|
+
@my_provider[Puppet::Util::NetworkDevice.current.transport.class]
|
47
|
+
else
|
48
|
+
@my_provider[Puppet::Util::NetworkDevice.current.class]
|
49
|
+
end
|
42
50
|
end
|
43
51
|
|
44
52
|
# make the provider available in the instance's namespace
|
@@ -352,7 +360,7 @@ MESSAGE
|
|
352
360
|
end
|
353
361
|
|
354
362
|
define_singleton_method(:context) do
|
355
|
-
@context ||= PuppetContext.new(definition)
|
363
|
+
@context ||= PuppetContext.new(TypeDefinition.new(definition))
|
356
364
|
end
|
357
365
|
|
358
366
|
def context
|
@@ -410,8 +418,10 @@ MESSAGE
|
|
410
418
|
type_name_sym = type_name.to_sym
|
411
419
|
device_name = if Puppet::Util::NetworkDevice.current.nil?
|
412
420
|
nil
|
413
|
-
|
421
|
+
elsif Puppet::Util::NetworkDevice.current.is_a? Puppet::ResourceApi::Transport::Wrapper
|
414
422
|
# extract the device type from the currently loaded device's class
|
423
|
+
Puppet::Util::NetworkDevice.current.schema.name
|
424
|
+
else
|
415
425
|
Puppet::Util::NetworkDevice.current.class.name.split('::')[-2].downcase
|
416
426
|
end
|
417
427
|
device_class_name = class_name_from_type_name(device_name)
|
@@ -451,6 +461,12 @@ MESSAGE
|
|
451
461
|
end
|
452
462
|
module_function :load_device_provider # rubocop:disable Style/AccessModifierDeclarations
|
453
463
|
|
464
|
+
# keeps the existing register API format. e.g. Puppet::ResourceApi.register_type
|
465
|
+
def register_transport(schema)
|
466
|
+
Puppet::ResourceApi::Transport.register(schema)
|
467
|
+
end
|
468
|
+
module_function :register_transport # rubocop:disable Style/AccessModifierDeclarations
|
469
|
+
|
454
470
|
def self.class_name_from_type_name(type_name)
|
455
471
|
type_name.to_s.split('_').map(&:capitalize).join
|
456
472
|
end
|
@@ -1,20 +1,34 @@
|
|
1
1
|
require 'puppet/resource_api/type_definition'
|
2
2
|
|
3
|
+
# rubocop:disable Style/Documentation
|
3
4
|
module Puppet; end
|
4
5
|
module Puppet::ResourceApi; end
|
6
|
+
# rubocop:enable Style/Documentation
|
7
|
+
|
8
|
+
# This class provides access to all common external dependencies of providers and transports.
|
9
|
+
# The runtime environment will inject an appropriate implementation.
|
5
10
|
class Puppet::ResourceApi::BaseContext
|
6
11
|
attr_reader :type
|
7
12
|
|
8
13
|
def initialize(definition)
|
9
|
-
|
10
|
-
|
11
|
-
|
14
|
+
if definition.is_a?(Hash)
|
15
|
+
# this is only for backwards compatibility
|
16
|
+
@type = Puppet::ResourceApi::TypeDefinition.new(definition)
|
17
|
+
elsif definition.is_a? Puppet::ResourceApi::BaseTypeDefinition
|
18
|
+
@type = definition
|
19
|
+
else
|
20
|
+
raise ArgumentError, 'BaseContext requires definition to be a child of Puppet::ResourceApi::BaseTypeDefinition, not <%{actual_type}>' % { actual_type: definition.class }
|
21
|
+
end
|
12
22
|
end
|
13
23
|
|
14
24
|
def device
|
15
25
|
raise 'Received device() on an unprepared BaseContext. Use a PuppetContext instead.'
|
16
26
|
end
|
17
27
|
|
28
|
+
def transport
|
29
|
+
raise 'No transport available.'
|
30
|
+
end
|
31
|
+
|
18
32
|
def failed?
|
19
33
|
@failed
|
20
34
|
end
|
@@ -27,7 +41,7 @@ class Puppet::ResourceApi::BaseContext
|
|
27
41
|
[:debug, :info, :notice, :warning, :err].each do |level|
|
28
42
|
define_method(level) do |*args|
|
29
43
|
if args.length == 1
|
30
|
-
message = "#{@context || @
|
44
|
+
message = "#{@context || @type.name}: #{args.last}"
|
31
45
|
elsif args.length == 2
|
32
46
|
resources = format_titles(args.first)
|
33
47
|
message = "#{resources}: #{args.last}"
|
@@ -137,9 +151,9 @@ class Puppet::ResourceApi::BaseContext
|
|
137
151
|
|
138
152
|
def format_titles(titles)
|
139
153
|
if titles.length.zero? && !titles.is_a?(String)
|
140
|
-
@
|
154
|
+
@type.name
|
141
155
|
else
|
142
|
-
"#{@
|
156
|
+
"#{@type.name}[#{[titles].flatten.compact.join(', ')}]"
|
143
157
|
end
|
144
158
|
end
|
145
159
|
|
@@ -1,9 +1,14 @@
|
|
1
1
|
require 'puppet/resource_api/base_context'
|
2
2
|
|
3
|
+
# Implement Resource API Conext to log through an IO object, defaulting to `$stderr`.
|
4
|
+
# There is no access to a device here. You can supply a transport if necessary.
|
3
5
|
class Puppet::ResourceApi::IOContext < Puppet::ResourceApi::BaseContext
|
4
|
-
|
6
|
+
attr_reader :transport
|
7
|
+
|
8
|
+
def initialize(definition, target = $stderr, transport = nil)
|
5
9
|
super(definition)
|
6
10
|
@target = target
|
11
|
+
@transport = transport
|
7
12
|
end
|
8
13
|
|
9
14
|
protected
|
@@ -1,6 +1,8 @@
|
|
1
1
|
require 'puppet/resource_api/base_context'
|
2
2
|
require 'puppet/util/logging'
|
3
3
|
|
4
|
+
# Implement Resource API Context to log through Puppet facilities
|
5
|
+
# and access/expose the puppet process' current device/transport
|
4
6
|
class Puppet::ResourceApi::PuppetContext < Puppet::ResourceApi::BaseContext
|
5
7
|
def device
|
6
8
|
# TODO: evaluate facter_url setting for loading config if there is no `current` NetworkDevice
|
@@ -8,6 +10,10 @@ class Puppet::ResourceApi::PuppetContext < Puppet::ResourceApi::BaseContext
|
|
8
10
|
Puppet::Util::NetworkDevice.current
|
9
11
|
end
|
10
12
|
|
13
|
+
def transport
|
14
|
+
device.transport
|
15
|
+
end
|
16
|
+
|
11
17
|
def log_exception(exception, message: 'Error encountered', trace: false)
|
12
18
|
super(exception, message: message, trace: trace || Puppet[:trace])
|
13
19
|
end
|
@@ -0,0 +1,95 @@
|
|
1
|
+
module Puppet::ResourceApi; end # rubocop:disable Style/Documentation
|
2
|
+
|
3
|
+
# Remote target transport API
|
4
|
+
module Puppet::ResourceApi::Transport
|
5
|
+
def register(schema)
|
6
|
+
raise Puppet::DevError, 'requires a hash as schema, not `%{other_type}`' % { other_type: schema.class } unless schema.is_a? Hash
|
7
|
+
raise Puppet::DevError, 'requires a `:name`' unless schema.key? :name
|
8
|
+
raise Puppet::DevError, 'requires `:desc`' unless schema.key? :desc
|
9
|
+
raise Puppet::DevError, 'requires `:connection_info`' unless schema.key? :connection_info
|
10
|
+
raise Puppet::DevError, '`:connection_info` must be a hash, not `%{other_type}`' % { other_type: schema[:connection_info].class } unless schema[:connection_info].is_a?(Hash)
|
11
|
+
|
12
|
+
init_transports
|
13
|
+
unless @transports[@environment][schema[:name]].nil?
|
14
|
+
raise Puppet::DevError, 'Transport `%{name}` is already registered for `%{environment}`' % {
|
15
|
+
name: schema[:name],
|
16
|
+
environment: @environment,
|
17
|
+
}
|
18
|
+
end
|
19
|
+
@transports[@environment][schema[:name]] = Puppet::ResourceApi::TransportSchemaDef.new(schema)
|
20
|
+
end
|
21
|
+
module_function :register # rubocop:disable Style/AccessModifierDeclarations
|
22
|
+
|
23
|
+
# retrieve a Hash of transport schemas, keyed by their name.
|
24
|
+
def list
|
25
|
+
init_transports
|
26
|
+
Marshal.load(Marshal.dump(@transports[@environment]))
|
27
|
+
end
|
28
|
+
module_function :list # rubocop:disable Style/AccessModifierDeclarations
|
29
|
+
|
30
|
+
def connect(name, connection_info)
|
31
|
+
validate(name, connection_info)
|
32
|
+
require "puppet/transport/#{name}"
|
33
|
+
class_name = name.split('_').map { |e| e.capitalize }.join
|
34
|
+
Puppet::Transport.const_get(class_name).new(get_context(name), wrap_sensitive(name, connection_info))
|
35
|
+
end
|
36
|
+
module_function :connect # rubocop:disable Style/AccessModifierDeclarations
|
37
|
+
|
38
|
+
def inject_device(name, transport)
|
39
|
+
transport_wrapper = Puppet::ResourceApi::Transport::Wrapper.new(name, transport)
|
40
|
+
|
41
|
+
if Puppet::Util::NetworkDevice.respond_to?(:set_device)
|
42
|
+
Puppet::Util::NetworkDevice.set_device(name, transport_wrapper)
|
43
|
+
else
|
44
|
+
Puppet::Util::NetworkDevice.instance_variable_set(:@current, transport_wrapper)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
module_function :inject_device # rubocop:disable Style/AccessModifierDeclarations
|
48
|
+
|
49
|
+
def self.validate(name, connection_info)
|
50
|
+
init_transports
|
51
|
+
require "puppet/transport/schema/#{name}" unless @transports[@environment].key? name
|
52
|
+
transport_schema = @transports[@environment][name]
|
53
|
+
if transport_schema.nil?
|
54
|
+
raise Puppet::DevError, 'Transport for `%{target}` not registered with `%{environment}`' % {
|
55
|
+
target: name,
|
56
|
+
environment: @environment,
|
57
|
+
}
|
58
|
+
end
|
59
|
+
message_prefix = 'The connection info provided does not match the Transport Schema'
|
60
|
+
transport_schema.check_schema(connection_info, message_prefix)
|
61
|
+
transport_schema.validate(connection_info)
|
62
|
+
end
|
63
|
+
private_class_method :validate
|
64
|
+
|
65
|
+
def self.get_context(name)
|
66
|
+
require 'puppet/resource_api/puppet_context'
|
67
|
+
Puppet::ResourceApi::PuppetContext.new(@transports[@environment][name])
|
68
|
+
end
|
69
|
+
private_class_method :get_context
|
70
|
+
|
71
|
+
def self.init_transports
|
72
|
+
lookup = Puppet.lookup(:current_environment) if Puppet.respond_to? :lookup
|
73
|
+
@environment = if lookup.nil?
|
74
|
+
:transports_default
|
75
|
+
else
|
76
|
+
lookup.name
|
77
|
+
end
|
78
|
+
@transports ||= {}
|
79
|
+
@transports[@environment] ||= {}
|
80
|
+
end
|
81
|
+
private_class_method :init_transports
|
82
|
+
|
83
|
+
def self.wrap_sensitive(name, connection_info)
|
84
|
+
transport_schema = @transports[@environment][name]
|
85
|
+
if transport_schema
|
86
|
+
transport_schema.definition[:connection_info].each do |attr_name, options|
|
87
|
+
if options.key?(:sensitive) && (options[:sensitive] == true)
|
88
|
+
connection_info[attr_name] = Puppet::Pops::Types::PSensitiveType::Sensitive.new(connection_info[attr_name])
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
connection_info
|
93
|
+
end
|
94
|
+
private_class_method :wrap_sensitive
|
95
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
require 'puppet/resource_api/transport'
|
2
|
+
require 'hocon'
|
3
|
+
require 'hocon/config_syntax'
|
4
|
+
|
5
|
+
# Puppet::ResourceApi::Transport::Wrapper` to interface between the Util::NetworkDevice
|
6
|
+
class Puppet::ResourceApi::Transport::Wrapper
|
7
|
+
attr_reader :transport, :schema
|
8
|
+
|
9
|
+
def initialize(name, url_or_config_or_transport)
|
10
|
+
if url_or_config_or_transport.is_a? String
|
11
|
+
url = URI.parse(url_or_config_or_transport)
|
12
|
+
raise "Unexpected url '#{url_or_config_or_transport}' found. Only file:/// URLs for configuration supported at the moment." unless url.scheme == 'file'
|
13
|
+
raise "Trying to load config from '#{url.path}, but file does not exist." if url && !File.exist?(url.path)
|
14
|
+
config = self.class.deep_symbolize(Hocon.load(url.path, syntax: Hocon::ConfigSyntax::HOCON) || {})
|
15
|
+
elsif url_or_config_or_transport.is_a? Hash
|
16
|
+
config = url_or_config_or_transport
|
17
|
+
elsif transport_class?(name, url_or_config_or_transport)
|
18
|
+
@transport = url_or_config_or_transport
|
19
|
+
end
|
20
|
+
|
21
|
+
@transport ||= Puppet::ResourceApi::Transport.connect(name, config)
|
22
|
+
@schema = Puppet::ResourceApi::Transport.list[name]
|
23
|
+
end
|
24
|
+
|
25
|
+
def transport_class?(name, transport)
|
26
|
+
class_name = name.split('_').map { |e| e.capitalize }.join
|
27
|
+
expected = Puppet::Transport.const_get(class_name).to_s
|
28
|
+
expected == transport.class.to_s
|
29
|
+
end
|
30
|
+
|
31
|
+
def facts
|
32
|
+
context = Puppet::ResourceApi::PuppetContext.new(@schema)
|
33
|
+
# @transport.facts + custom_facts # look into custom facts work by TP
|
34
|
+
@transport.facts(context)
|
35
|
+
end
|
36
|
+
|
37
|
+
def respond_to_missing?(name, _include_private)
|
38
|
+
(@transport.respond_to? name) || super
|
39
|
+
end
|
40
|
+
|
41
|
+
def method_missing(method_name, *args, &block)
|
42
|
+
if @transport.respond_to? method_name
|
43
|
+
@transport.send(method_name, *args, &block)
|
44
|
+
else
|
45
|
+
super
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
# From https://stackoverflow.com/a/11788082/4918
|
50
|
+
def self.deep_symbolize(obj)
|
51
|
+
return obj.each_with_object({}) { |(k, v), memo| memo[k.to_sym] = deep_symbolize(v); } if obj.is_a? Hash
|
52
|
+
return obj.each_with_object([]) { |v, memo| memo << deep_symbolize(v); } if obj.is_a? Array
|
53
|
+
obj
|
54
|
+
end
|
55
|
+
end
|
@@ -1,144 +1,187 @@
|
|
1
1
|
# Provides accessor methods for the type being provided
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
2
|
+
module Puppet::ResourceApi
|
3
|
+
# pre-declare class
|
4
|
+
class BaseTypeDefinition; end
|
5
|
+
|
6
|
+
# RSAPI Resource Type
|
7
|
+
class TypeDefinition < BaseTypeDefinition
|
8
|
+
def initialize(definition)
|
9
|
+
super(definition, :attributes)
|
10
|
+
end
|
9
11
|
|
10
|
-
|
11
|
-
|
12
|
-
|
12
|
+
def ensurable?
|
13
|
+
attributes.key?(:ensure)
|
14
|
+
end
|
13
15
|
|
14
|
-
|
15
|
-
|
16
|
-
|
16
|
+
# rubocop complains when this is named has_feature?
|
17
|
+
def feature?(feature)
|
18
|
+
supported = (definition[:features] && definition[:features].include?(feature))
|
19
|
+
if supported
|
20
|
+
Puppet.debug("#{definition[:name]} supports `#{feature}`")
|
21
|
+
else
|
22
|
+
Puppet.debug("#{definition[:name]} does not support `#{feature}`")
|
23
|
+
end
|
24
|
+
supported
|
25
|
+
end
|
17
26
|
|
18
|
-
|
19
|
-
|
20
|
-
|
27
|
+
def validate_schema(definition, attr_key)
|
28
|
+
super(definition, attr_key)
|
29
|
+
[:title, :provider, :alias, :audit, :before, :consume, :export, :loglevel, :noop, :notify, :require, :schedule, :stage, :subscribe, :tag].each do |name|
|
30
|
+
raise Puppet::DevError, 'must not define an attribute called `%{name}`' % { name: name.inspect } if definition[attr_key].key? name
|
31
|
+
end
|
32
|
+
if definition.key?(:title_patterns) && !definition[:title_patterns].is_a?(Array)
|
33
|
+
raise Puppet::DevError, '`:title_patterns` must be an array, not `%{other_type}`' % { other_type: definition[:title_patterns].class }
|
34
|
+
end
|
21
35
|
|
22
|
-
|
23
|
-
@namevars ||= @definition[:attributes].select { |_name, options|
|
24
|
-
options.key?(:behaviour) && options[:behaviour] == :namevar
|
25
|
-
}.keys
|
26
|
-
end
|
36
|
+
Puppet::ResourceApi::DataTypeHandling.validate_ensure(definition)
|
27
37
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
Puppet.debug("#{definition[:name]} supports `#{feature}`")
|
33
|
-
else
|
34
|
-
Puppet.debug("#{definition[:name]} does not support `#{feature}`")
|
38
|
+
definition[:features] ||= []
|
39
|
+
supported_features = %w[supports_noop canonicalize remote_resource simple_get_filter].freeze
|
40
|
+
unknown_features = definition[:features] - supported_features
|
41
|
+
Puppet.warning("Unknown feature detected: #{unknown_features.inspect}") unless unknown_features.empty?
|
35
42
|
end
|
36
|
-
supported
|
37
43
|
end
|
38
44
|
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
unless definition[:attributes].is_a?(Hash)
|
44
|
-
raise Puppet::DevError, '`%{name}.attributes` must be a hash, not `%{other_type}`' % {
|
45
|
-
name: definition[:name], other_type: definition[:attributes].class
|
46
|
-
}
|
47
|
-
end
|
48
|
-
[:title, :provider, :alias, :audit, :before, :consume, :export, :loglevel, :noop, :notify, :require, :schedule, :stage, :subscribe, :tag].each do |name|
|
49
|
-
raise Puppet::DevError, 'must not define an attribute called `%{name}`' % { name: name.inspect } if definition[:attributes].key? name
|
45
|
+
# RSAPI Transport schema
|
46
|
+
class TransportSchemaDef < BaseTypeDefinition
|
47
|
+
def initialize(definition)
|
48
|
+
super(definition, :connection_info)
|
50
49
|
end
|
51
|
-
|
52
|
-
|
50
|
+
|
51
|
+
def validate(resource)
|
52
|
+
# enforce mandatory attributes
|
53
|
+
missing_attrs = []
|
54
|
+
|
55
|
+
attributes.each do |name, _options|
|
56
|
+
type = @data_type_cache[attributes[name][:type]]
|
57
|
+
|
58
|
+
if resource[name].nil? && !(type.instance_of? Puppet::Pops::Types::POptionalType)
|
59
|
+
missing_attrs << name
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
error_msg = "The following mandatory attributes were not provided:\n * " + missing_attrs.join(", \n * ")
|
64
|
+
raise Puppet::ResourceError, error_msg if missing_attrs.any?
|
53
65
|
end
|
66
|
+
end
|
54
67
|
|
55
|
-
|
68
|
+
# Base RSAPI schema Object
|
69
|
+
class BaseTypeDefinition
|
70
|
+
attr_reader :definition, :attributes
|
56
71
|
|
57
|
-
definition
|
58
|
-
|
59
|
-
|
60
|
-
|
72
|
+
def initialize(definition, attr_key)
|
73
|
+
@data_type_cache = {}
|
74
|
+
validate_schema(definition, attr_key)
|
75
|
+
# store the validated definition
|
76
|
+
@definition = definition
|
77
|
+
end
|
61
78
|
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
Puppet.warning("`#{definition[:name]}.#{key}` has no docs") unless attr.key? :desc
|
79
|
+
def name
|
80
|
+
definition[:name]
|
81
|
+
end
|
66
82
|
|
67
|
-
|
68
|
-
@
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
)
|
83
|
+
def namevars
|
84
|
+
@namevars ||= attributes.select { |_name, options|
|
85
|
+
options.key?(:behaviour) && options[:behaviour] == :namevar
|
86
|
+
}.keys
|
87
|
+
end
|
73
88
|
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
89
|
+
def validate_schema(definition, attr_key)
|
90
|
+
raise Puppet::DevError, '%{type_class} must be a Hash, not `%{other_type}`' % { type_class: self.class.name, other_type: definition.class } unless definition.is_a?(Hash)
|
91
|
+
@attributes = definition[attr_key]
|
92
|
+
raise Puppet::DevError, '%{type_class} must have a name' % { type_class: self.class.name } unless definition.key? :name
|
93
|
+
raise Puppet::DevError, '%{type_class} must have `%{attr_key}`' % { type_class: self.class.name, attrs: attr_key } unless definition.key? attr_key
|
94
|
+
unless attributes.is_a?(Hash)
|
95
|
+
raise Puppet::DevError, '`%{name}.%{attrs}` must be a hash, not `%{other_type}`' % {
|
96
|
+
name: definition[:name], attrs: attr_key, other_type: attributes.class
|
97
|
+
}
|
78
98
|
end
|
79
|
-
attr[:behaviour] = attr[:behavior]
|
80
|
-
attr.delete(:behavior)
|
81
|
-
end
|
82
|
-
# store the validated definition
|
83
|
-
@definition = definition
|
84
|
-
end
|
85
99
|
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
100
|
+
attributes.each do |key, attr|
|
101
|
+
raise Puppet::DevError, "`#{definition[:name]}.#{key}` must be a Hash, not a #{attr.class}" unless attr.is_a? Hash
|
102
|
+
raise Puppet::DevError, "`#{definition[:name]}.#{key}` has no type" unless attr.key? :type
|
103
|
+
Puppet.warning("`#{definition[:name]}.#{key}` has no docs") unless attr.key? :desc
|
104
|
+
|
105
|
+
# validate the type by attempting to parse into a puppet type
|
106
|
+
@data_type_cache[attributes[key][:type]] ||=
|
107
|
+
Puppet::ResourceApi::DataTypeHandling.parse_puppet_type(
|
108
|
+
key,
|
109
|
+
attributes[key][:type],
|
110
|
+
)
|
111
|
+
|
112
|
+
# fixup any weird behavior ;-)
|
113
|
+
next unless attr[:behavior]
|
114
|
+
if attr[:behaviour]
|
115
|
+
raise Puppet::DevError, "the '#{key}' attribute has both a `behavior` and a `behaviour`, only use one"
|
116
|
+
end
|
117
|
+
attr[:behaviour] = attr[:behavior]
|
118
|
+
attr.delete(:behavior)
|
91
119
|
end
|
92
120
|
end
|
93
121
|
|
94
|
-
|
122
|
+
# validates a resource hash against its type schema
|
123
|
+
def check_schema(resource, message_prefix = nil)
|
124
|
+
namevars.each do |namevar|
|
125
|
+
if resource[namevar].nil?
|
126
|
+
raise Puppet::ResourceError, "`#{name}.get` did not return a value for the `#{namevar}` namevar attribute"
|
127
|
+
end
|
128
|
+
end
|
95
129
|
|
96
|
-
|
97
|
-
|
130
|
+
message_prefix = 'Provider returned data that does not match the Type Schema' if message_prefix.nil?
|
131
|
+
message = "#{message_prefix} for `#{name}[#{resource[namevars.first]}]`"
|
98
132
|
|
99
|
-
|
100
|
-
|
101
|
-
rejected_keys.each { |key, _value| message += " * #{key}\n" }
|
102
|
-
end
|
103
|
-
unless bad_values.empty?
|
104
|
-
message += "\n Value type mismatch:\n"
|
105
|
-
bad_values.each { |key, value| message += " * #{key}: #{value}\n" }
|
106
|
-
end
|
133
|
+
rejected_keys = check_schema_keys(resource)
|
134
|
+
bad_values = check_schema_values(resource)
|
107
135
|
|
108
|
-
|
136
|
+
unless rejected_keys.empty?
|
137
|
+
message += "\n Unknown attribute:\n"
|
138
|
+
rejected_keys.each { |key, _value| message += " * #{key}\n" }
|
139
|
+
end
|
140
|
+
unless bad_values.empty?
|
141
|
+
message += "\n Value type mismatch:\n"
|
142
|
+
bad_values.each { |key, value| message += " * #{key}: #{value}\n" }
|
143
|
+
end
|
144
|
+
|
145
|
+
return if rejected_keys.empty? && bad_values.empty?
|
109
146
|
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
147
|
+
if Puppet.settings[:strict] == :off
|
148
|
+
Puppet.debug(message)
|
149
|
+
elsif Puppet.settings[:strict] == :warning
|
150
|
+
Puppet::ResourceApi.warning_count += 1
|
151
|
+
Puppet.warning(message) if Puppet::ResourceApi.warning_count <= 100 # maximum number of schema warnings to display in a run
|
152
|
+
elsif Puppet.settings[:strict] == :error
|
153
|
+
raise Puppet::DevError, message
|
154
|
+
end
|
117
155
|
end
|
118
|
-
end
|
119
156
|
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
157
|
+
# Returns an array of keys that where not found in the type schema
|
158
|
+
# No longer modifies the resource passed in
|
159
|
+
def check_schema_keys(resource)
|
160
|
+
rejected = []
|
161
|
+
resource.reject { |key| rejected << key if key != :title && attributes.key?(key) == false }
|
162
|
+
rejected
|
163
|
+
end
|
127
164
|
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
165
|
+
# Returns a hash of keys and values that are not valid
|
166
|
+
# does not modify the resource passed in
|
167
|
+
def check_schema_values(resource)
|
168
|
+
bad_vals = {}
|
169
|
+
resource.each do |key, value|
|
170
|
+
next unless attributes[key]
|
171
|
+
type = @data_type_cache[attributes[key][:type]]
|
172
|
+
is_sensitive = (attributes[key].key?(:sensitive) && (attributes[key][:sensitive] == true))
|
173
|
+
error_message = Puppet::ResourceApi::DataTypeHandling.try_validate(
|
174
|
+
type,
|
175
|
+
value,
|
176
|
+
'',
|
177
|
+
)
|
178
|
+
if is_sensitive
|
179
|
+
bad_vals[key] = '<< redacted value >> ' + error_message unless error_message.nil?
|
180
|
+
else
|
181
|
+
bad_vals[key] = value unless error_message.nil?
|
182
|
+
end
|
183
|
+
end
|
184
|
+
bad_vals
|
141
185
|
end
|
142
|
-
bad_vals
|
143
186
|
end
|
144
187
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: puppet-resource_api
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.8.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- David Schmitt
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-
|
11
|
+
date: 2019-02-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: hocon
|
@@ -36,7 +36,6 @@ files:
|
|
36
36
|
- ".gitignore"
|
37
37
|
- ".rspec"
|
38
38
|
- ".rubocop.yml"
|
39
|
-
- ".rubocop_todo.yml"
|
40
39
|
- ".travis.yml"
|
41
40
|
- CHANGELOG.md
|
42
41
|
- CONTRIBUTING.md
|
@@ -61,6 +60,8 @@ files:
|
|
61
60
|
- lib/puppet/resource_api/puppet_context.rb
|
62
61
|
- lib/puppet/resource_api/read_only_parameter.rb
|
63
62
|
- lib/puppet/resource_api/simple_provider.rb
|
63
|
+
- lib/puppet/resource_api/transport.rb
|
64
|
+
- lib/puppet/resource_api/transport/wrapper.rb
|
64
65
|
- lib/puppet/resource_api/type_definition.rb
|
65
66
|
- lib/puppet/resource_api/value_creator.rb
|
66
67
|
- lib/puppet/resource_api/version.rb
|
@@ -87,7 +88,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
87
88
|
version: '0'
|
88
89
|
requirements: []
|
89
90
|
rubyforge_project:
|
90
|
-
rubygems_version: 2.7.6
|
91
|
+
rubygems_version: 2.7.6
|
91
92
|
signing_key:
|
92
93
|
specification_version: 4
|
93
94
|
summary: This library provides a simple way to write new native resources for puppet.
|
data/.rubocop_todo.yml
DELETED
@@ -1,17 +0,0 @@
|
|
1
|
-
# This configuration was generated by
|
2
|
-
# `rubocop --auto-gen-config`
|
3
|
-
# on 2017-09-05 11:31:11 +0100 using RuboCop version 0.49.1.
|
4
|
-
# The point is for the user to remove these configuration records
|
5
|
-
# one by one as the offenses are removed from the code base.
|
6
|
-
# Note that changes in the inspected code, or installation of new
|
7
|
-
# versions of RuboCop, may require this file to be generated again.
|
8
|
-
|
9
|
-
# Offense count: 6
|
10
|
-
Style/Documentation:
|
11
|
-
Exclude:
|
12
|
-
- 'spec/**/*'
|
13
|
-
- 'test/**/*'
|
14
|
-
- 'lib/puppet/resource_api.rb'
|
15
|
-
- 'lib/puppet/resource_api/base_context.rb'
|
16
|
-
- 'lib/puppet/resource_api/io_context.rb'
|
17
|
-
- 'lib/puppet/resource_api/puppet_context.rb'
|