puppet-resource_api 1.7.0 → 1.8.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c26bda3effbce092aa8b8defb8904fdb41a02231fba2830593bfc85413b66906
4
- data.tar.gz: 89b49840bd21ea57227db05021e0b9ddb7ab7539b9b130a888e3fea99b7da87e
3
+ metadata.gz: '066920a9f1eca6ad946f2c8f39239482a2d00b756a9ac26db2441c4015a6aa37'
4
+ data.tar.gz: b9f87949cc263e98ead6d3fc5dcc480787a8122078e548bb135a2f1c21373f30
5
5
  SHA512:
6
- metadata.gz: 971775219d3ae76f94a18ebef57b0a1be470a0c222b31a4a1cf0d1d4b8f4ecc71516fb6b004674a4878c619d97f4b6f3e644edcc43e3cba419070afd5ad53bd3
7
- data.tar.gz: dfb2823ce573240977587f9a7431b1956a62a0367a740d4e0c9fc412436542d41065be88e7ed8348057fd42b1cf039c4ac69c8e4b7bad7f4771d73c2f6927454
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: true
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
- hipchat:
69
- rooms:
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
 
@@ -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
- @my_provider[Puppet::Util::NetworkDevice.current.class]
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
- else
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
- raise ArgumentError, 'BaseContext requires definition to be a Hash' unless definition.is_a?(Hash)
10
- @typename = definition[:name]
11
- @type = Puppet::ResourceApi::TypeDefinition.new(definition)
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 || @typename}: #{args.last}"
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
- @typename
154
+ @type.name
141
155
  else
142
- "#{@typename}[#{[titles].flatten.compact.join(', ')}]"
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
- def initialize(definition, target = $stderr)
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
- class Puppet::ResourceApi::TypeDefinition
3
- attr_reader :definition
4
-
5
- def initialize(definition)
6
- @data_type_cache = {}
7
- validate_schema(definition)
8
- end
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
- def name
11
- @definition[:name]
12
- end
12
+ def ensurable?
13
+ attributes.key?(:ensure)
14
+ end
13
15
 
14
- def attributes
15
- @definition[:attributes]
16
- end
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
- def ensurable?
19
- @definition[:attributes].key?(:ensure)
20
- end
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
- def namevars
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
- # rubocop complains when this is named has_feature?
29
- def feature?(feature)
30
- supported = (definition[:features] && definition[:features].include?(feature))
31
- if supported
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
- def validate_schema(definition)
40
- raise Puppet::DevError, 'Type definition must be a Hash, not `%{other_type}`' % { other_type: definition.class } unless definition.is_a?(Hash)
41
- raise Puppet::DevError, 'Type definition must have a name' unless definition.key? :name
42
- raise Puppet::DevError, 'Type definition must have `:attributes`' unless definition.key? :attributes
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
- if definition.key?(:title_patterns) && !definition[:title_patterns].is_a?(Array)
52
- raise Puppet::DevError, '`:title_patterns` must be an array, not `%{other_type}`' % { other_type: definition[:title_patterns].class }
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
- Puppet::ResourceApi::DataTypeHandling.validate_ensure(definition)
68
+ # Base RSAPI schema Object
69
+ class BaseTypeDefinition
70
+ attr_reader :definition, :attributes
56
71
 
57
- definition[:features] ||= []
58
- supported_features = %w[supports_noop canonicalize remote_resource simple_get_filter].freeze
59
- unknown_features = definition[:features] - supported_features
60
- Puppet.warning("Unknown feature detected: #{unknown_features.inspect}") unless unknown_features.empty?
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
- definition[:attributes].each do |key, attr|
63
- raise Puppet::DevError, "`#{definition[:name]}.#{key}` must be a Hash, not a #{attr.class}" unless attr.is_a? Hash
64
- raise Puppet::DevError, "`#{definition[:name]}.#{key}` has no type" unless attr.key? :type
65
- Puppet.warning("`#{definition[:name]}.#{key}` has no docs") unless attr.key? :desc
79
+ def name
80
+ definition[:name]
81
+ end
66
82
 
67
- # validate the type by attempting to parse into a puppet type
68
- @data_type_cache[definition[:attributes][key][:type]] ||=
69
- Puppet::ResourceApi::DataTypeHandling.parse_puppet_type(
70
- key,
71
- definition[:attributes][key][:type],
72
- )
83
+ def namevars
84
+ @namevars ||= attributes.select { |_name, options|
85
+ options.key?(:behaviour) && options[:behaviour] == :namevar
86
+ }.keys
87
+ end
73
88
 
74
- # fixup any weird behavior ;-)
75
- next unless attr[:behavior]
76
- if attr[:behaviour]
77
- raise Puppet::DevError, "the '#{key}' attribute has both a `behavior` and a `behaviour`, only use one"
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
- # validates a resource hash against its type schema
87
- def check_schema(resource)
88
- namevars.each do |namevar|
89
- if resource[namevar].nil?
90
- raise Puppet::ResourceError, "`#{name}.get` did not return a value for the `#{namevar}` namevar attribute"
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
- message = "Provider returned data that does not match the Type Schema for `#{name}[#{resource[namevars.first]}]`"
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
- rejected_keys = check_schema_keys(resource) # removes bad keys
97
- bad_values = check_schema_values(resource)
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
- unless rejected_keys.empty?
100
- message += "\n Unknown attribute:\n"
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
- return if rejected_keys.empty? && bad_values.empty?
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
- if Puppet.settings[:strict] == :off
111
- Puppet.debug(message)
112
- elsif Puppet.settings[:strict] == :warning
113
- Puppet::ResourceApi.warning_count += 1
114
- Puppet.warning(message) if Puppet::ResourceApi.warning_count <= 100 # maximum number of schema warnings to display in a run
115
- elsif Puppet.settings[:strict] == :error
116
- raise Puppet::DevError, message
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
- # Returns an array of keys that where not found in the type schema
121
- # Modifies the resource passed in, leaving only valid attributes
122
- def check_schema_keys(resource)
123
- rejected = []
124
- resource.reject! { |key| rejected << key if key != :title && attributes.key?(key) == false }
125
- rejected
126
- end
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
- # Returns a hash of keys and values that are not valid
129
- # does not modify the resource passed in
130
- def check_schema_values(resource)
131
- bad_vals = {}
132
- resource.each do |key, value|
133
- next unless attributes[key]
134
- type = @data_type_cache[attributes[key][:type]]
135
- error_message = Puppet::ResourceApi::DataTypeHandling.try_validate(
136
- type,
137
- value,
138
- '',
139
- )
140
- bad_vals[key] = value unless error_message.nil?
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
@@ -1,5 +1,5 @@
1
1
  module Puppet
2
2
  module ResourceApi
3
- VERSION = '1.7.0'.freeze
3
+ VERSION = '1.8.0'.freeze
4
4
  end
5
5
  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.7.0
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-04-24 00:00:00.000000000 Z
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.2
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'