Skip to content

Commit

Permalink
Merge pull request #21 from Atalanta/support-selection-of-private-ip
Browse files Browse the repository at this point in the history
Support selection of private ip
  • Loading branch information
fnichol committed Jan 27, 2014
2 parents 8374efe + b63875a commit de67adb
Show file tree
Hide file tree
Showing 8 changed files with 145 additions and 9 deletions.
1 change: 1 addition & 0 deletions .cane
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
--style-measure 100
2 changes: 1 addition & 1 deletion .tailor
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ Tailor.config do |config|
style.indentation_spaces 2, level: :error
style.max_code_lines_in_class 300, level: :error
style.max_code_lines_in_method 30, level: :error
style.max_line_length 80, level: :error
style.max_line_length 100, level: :error
style.spaces_after_comma 1, level: :off
style.spaces_after_lbrace 1, level: :error
style.spaces_after_lbracket 0, level: :error
Expand Down
1 change: 1 addition & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,5 @@ gemspec

group :test do
gem 'rake'
gem 'pry'
end
11 changes: 11 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,17 @@ The SSH port number to be used when communicating with the instance.

The default is `22`.

### < name="interface"></a> interface

The place from which to derive the hostname for communicating with the instance. May be `dns`, `public` or `private`. If this is unset, the driver will derive the hostname by failing back in the following order:

1. DNS Name
2. Public IP Address
3. Private IP Address

The default is unset.


### <a name="config-region"></a> region

**Required** The AWS [region][region_docs] to use.
Expand Down
1 change: 1 addition & 0 deletions kitchen-ec2.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ Gem::Specification.new do |gem|
gem.add_dependency 'test-kitchen', '~> 1.0'
gem.add_dependency 'fog'

gem.add_development_dependency 'rspec'
gem.add_development_dependency 'cane'
gem.add_development_dependency 'tailor'
gem.add_development_dependency 'countloc'
Expand Down
30 changes: 23 additions & 7 deletions lib/kitchen/driver/ec2.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
require 'benchmark'
require 'json'
require 'fog'

require 'kitchen'

module Kitchen
Expand Down Expand Up @@ -59,6 +58,8 @@ class Ec2 < Kitchen::Driver::SSHBase
"https://ec2.#{driver[:region]}.amazonaws.com/"
end

default_config :interface, nil

required_config :aws_access_key_id
required_config :aws_secret_access_key
required_config :aws_ssh_key_id
Expand All @@ -69,11 +70,11 @@ def create(state)
state[:server_id] = server.id

info("EC2 instance <#{state[:server_id]}> created.")
server.wait_for { print "."; ready? }
print "(server ready)"
server.wait_for { print '.'; ready? }
print '(server ready)'
state[:hostname] = hostname(server)
wait_for_sshd(state[:hostname], config[:username])
print "(ssh ready)\n"
print '(ssh ready)\n'
debug("ec2:create '#{state[:hostname]}'")
rescue Fog::Errors::Error, Excon::Errors::Error => ex
raise ActionFailed, ex.message
Expand All @@ -90,12 +91,12 @@ def destroy(state)
end

def default_ami
region = amis["regions"][config[:region]]
region = amis['regions'][config[:region]]
region && region[instance.platform.name]
end

def default_username
amis["usernames"][instance.platform.name] || "root"
amis['usernames'][instance.platform.name] || 'root'
end

private
Expand Down Expand Up @@ -146,8 +147,23 @@ def amis
end
end

def interface_types
{
'dns' => 'dns_name',
'public' => 'public_ip_address',
'private' => 'private_ip_address'
}
end

def hostname(server)
server.dns_name || server.public_ip_address || server.private_ip_address
if config[:interface]
method = interface_types.fetch(config[:interface]) do
raise Kitchen::UserError, 'Invalid interface'
end
server.send(method)
else
server.dns_name || server.public_ip_address || server.private_ip_address
end
end
end
end
Expand Down
2 changes: 1 addition & 1 deletion lib/kitchen/driver/ec2_version.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,6 @@ module Kitchen
module Driver

# Version string for EC2 Test Kitchen driver
EC2_VERSION = "0.7.1.dev"
EC2_VERSION = '0.7.1.dev'
end
end
106 changes: 106 additions & 0 deletions spec/create_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
require 'kitchen/driver/ec2'
require 'kitchen/provisioner/dummy'

describe Kitchen::Driver::Ec2 do

let(:config) do
{}
end

let(:state) do
{}
end

let(:server) do
double(:id => "123",
:wait_for => nil,
:dns_name => "server.example.com",
:private_ip_address => '172.13.16.11',
:public_ip_address => '213.225.123.134')
end

let(:instance) do
Kitchen::Instance.new(:platform => double(:name => "centos-6.4"),
:suite => double(:name => "default"),
:driver => driver,
:provisioner => Kitchen::Provisioner::Dummy.new({}),
:busser => double("busser"),
:state_file => double("state_file"))
end

let(:driver) do
Kitchen::Driver::Ec2.new(config)
end

before do
instance
allow(driver).to receive(:create_server).and_return(server)
allow(driver).to receive(:wait_for_sshd)
end

context 'Interface is set in config' do

it 'derives hostname from DNS when specified in the .kitchen.yml' do
config[:interface] = 'dns'
driver.create(state)
expect(state[:hostname]).to eql('server.example.com')
end

it 'derives hostname from public interface when specified in the .kitchen.yml' do
config[:interface] = 'public'
driver.create(state)
expect(state[:hostname]).to eql('213.225.123.134')
end

it 'derives hostname from private interface when specified in the .kitchen.yml' do
config[:interface] = 'private'
driver.create(state)
expect(state[:hostname]).to eql('172.13.16.11')
end

it 'throws a nice exception if the config is bogus' do
config[:interface] = 'I am an idiot'
expect { driver.create(state) }.to raise_error(Kitchen::UserError, 'Invalid interface')
end

end

context 'Interface is derived automatically' do

let(:server) do
double(:id => "123",
:wait_for => nil,
:dns_name => nil,
:private_ip_address => nil,
:public_ip_address => nil)
end

it 'sets hostname to DNS value if DNS value exists' do
allow(server).to receive(:dns_name).and_return('server.example.com')
driver.create(state)
expect(state[:hostname]).to eql('server.example.com')
end

it 'sets hostname to public value if public value exists' do
allow(server).to receive(:public_ip_address).and_return('213.225.123.134')
driver.create(state)

expect(state[:hostname]).to eql('213.225.123.134')
end

it 'sets hostname to private value if private value exists' do
allow(server).to receive(:private_ip_address).and_return('172.13.16.11')
driver.create(state)
expect(state[:hostname]).to eql('172.13.16.11')
end

it 'sets hostname to DNS if one or more Public/Private values are set' do
allow(server).to receive(:dns_name).and_return('server.example.com')
allow(server).to receive(:public_ip_address).and_return('213.225.123.134')
allow(server).to receive(:private_ip_address).and_return('172.13.16.11')
driver.create(state)
expect(state[:hostname]).to eql('server.example.com')
end

end
end

0 comments on commit de67adb

Please sign in to comment.