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 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'