Skip to content

Commit

Permalink
Merge pull request #148 from da-ar/transport_connect
Browse files Browse the repository at this point in the history
(FM-7600) RSAPI Transport connect method
  • Loading branch information
da-ar authored Jan 10, 2019
2 parents ad91a0f + 80faf28 commit 385447e
Show file tree
Hide file tree
Showing 4 changed files with 124 additions and 1 deletion.
21 changes: 21 additions & 0 deletions lib/puppet/resource_api/transport.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,25 @@ def register(schema)
@transports[schema[:name]] = Puppet::ResourceApi::TransportSchemaDef.new(schema)
end
module_function :register # rubocop:disable Style/AccessModifierDeclarations

def connect(name, connection_info)
validate(name, connection_info)
begin
require "puppet/transport/#{name}"
class_name = name.split('_').map { |e| e.capitalize }.join
Puppet::Transport.const_get(class_name).new(connection_info)
rescue LoadError, NameError => detail
raise Puppet::DevError, 'Cannot load transport for `%{target}`: %{detail}' % { target: name, detail: detail }
end
end
module_function :connect # rubocop:disable Style/AccessModifierDeclarations

def self.validate(name, connection_info)
@transports ||= {}
transport_schema = @transports[name]
raise Puppet::DevError, 'Transport for `%{target}` not registered' % { target: name } if transport_schema.nil?

transport_schema.check_schema(connection_info)
transport_schema.validate(connection_info)
end
end
16 changes: 16 additions & 0 deletions lib/puppet/resource_api/type_definition.rb
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,22 @@ class TransportSchemaDef < BaseTypeDefinition
def initialize(definition)
super(definition, :connection_info)
end

def validate(resource)
# enforce mandatory attributes
missing_attrs = []

attributes.each do |name, _options|
type = @data_type_cache[attributes[name][:type]]

if resource[name].nil? && !(type.instance_of? Puppet::Pops::Types::POptionalType)
missing_attrs << name
end
end

error_msg = "The following mandatory attributes were not provided:\n * " + missing_attrs.join(", \n * ")
raise Puppet::ResourceError, error_msg if missing_attrs.any?
end
end

# Base RSAPI schema Object
Expand Down
17 changes: 17 additions & 0 deletions spec/puppet/resource_api/transport_schema_def_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,21 @@
it { expect(type.attributes).to be_key(:user) }
end
end

describe '#validate' do
context 'when resource is missing attributes' do
let(:resource) { {} }

it 'raises an error listing the missing attributes' do
expect { type.validate(resource) }.to raise_error Puppet::ResourceError, %r{host}
expect { type.validate(resource) }.to raise_error Puppet::ResourceError, %r{user}
end
end

context 'when resource has all its attributes' do
let(:resource) { { host: '1234', user: '4321' } }

it { expect { type.validate(resource) }.not_to raise_error }
end
end
end
71 changes: 70 additions & 1 deletion spec/puppet/resource_api/transport_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,8 @@
desc: 'the user to connect as',
},
password: {
type: 'Sensitive[String]',
type: 'String',
sensitive: true,
desc: 'the password to make the connection',
},
},
Expand Down Expand Up @@ -76,4 +77,72 @@
)
}
end

context 'when connecting to a transport' do
let(:name) { 'test_target' }
let(:connection_info) do
{
name: 'test_target',
desc: 'a basic transport',
connection_info: {
host: {
type: 'String',
desc: 'the host ip address or hostname',
},
},
}
end

context 'when the transport file does not exist' do
it 'throws a DevError' do
expect(described_class).to receive(:validate).with(name, connection_info)
expect { described_class.connect(name, connection_info) }.to raise_error Puppet::DevError,
%r{Cannot load transport for `test_target`}
end
end

context 'when the transport file does exist' do
context 'with and incorrectly defined transport' do
it 'throws a DevError' do
expect(described_class).to receive(:validate).with(name, connection_info)
expect(described_class).to receive(:require).with('puppet/transport/test_target')
expect { described_class.connect(name, connection_info) }.to raise_error Puppet::DevError,
%r{uninitialized constant Puppet::Transport}
end
end

context 'with a correctly defined transport' do
let(:test_target) { double('Puppet::Transport::TestTarget') } # rubocop:disable RSpec/VerifiedDoubles

it 'loads initiates the class successfully' do
expect(described_class).to receive(:require).with('puppet/transport/test_target')
expect(described_class).to receive(:validate).with(name, connection_info)

stub_const('Puppet::Transport::TestTarget', test_target)
expect(test_target).to receive(:new).with(connection_info)

described_class.connect(name, connection_info)
end
end
end
end

describe '#self.validate' do
context 'when the transport being validated has not be registered' do
it { expect { described_class.validate('wibble', {}) }.to raise_error Puppet::DevError, %r{Transport for `wibble` not registered} }
end

context 'when the transport being validated has been registered' do
let(:schema) { { name: 'validate', desc: 'a minimal connection', connection_info: {} } }

it 'continues to validate the connection_info' do
# rubocop:disable RSpec/AnyInstance
expect_any_instance_of(Puppet::ResourceApi::TransportSchemaDef).to receive(:check_schema).with({})
expect_any_instance_of(Puppet::ResourceApi::TransportSchemaDef).to receive(:validate).with({})
# rubocop:enable RSpec/AnyInstance
described_class.register(schema)
described_class.validate('validate', {})
end
end
end
end

0 comments on commit 385447e

Please sign in to comment.