Skip to content

(FM-7600) Add Transport.connect method #148

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jan 10, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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