Skip to content
This repository was archived by the owner on Feb 11, 2022. It is now read-only.

Commit 93f4143

Browse files
committed
Merge pull request #65 from bwhaley/master
Elastic IP for VPC instances per issue 18
2 parents 0678df7 + a9f6342 commit 93f4143

File tree

5 files changed

+74
-3
lines changed

5 files changed

+74
-3
lines changed

lib/vagrant-aws/action/read_ssh_info.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ def read_ssh_info(aws, machine)
3131

3232
# Read the DNS info
3333
return {
34-
:host => server.dns_name || server.private_ip_address,
34+
:host => server.public_ip_address || server.dns_name || server.private_ip_address,
3535
:port => 22
3636
}
3737
end

lib/vagrant-aws/action/run_instance.rb

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
require "log4r"
2+
require 'json'
23

34
require 'vagrant/util/retryable'
45

@@ -35,14 +36,15 @@ def call(env)
3536
tags = region_config.tags
3637
user_data = region_config.user_data
3738
block_device_mapping = region_config.block_device_mapping
39+
elastic_ip = region_config.elastic_ip
3840

3941
# If there is no keypair then warn the user
4042
if !keypair
4143
env[:ui].warn(I18n.t("vagrant_aws.launch_no_keypair"))
4244
end
4345

4446
# If there is a subnet ID then warn the user
45-
if subnet_id
47+
if subnet_id and !elastic_ip
4648
env[:ui].warn(I18n.t("vagrant_aws.launch_vpc_warning"))
4749
end
4850

@@ -55,6 +57,7 @@ def call(env)
5557
env[:ui].info(" -- Keypair: #{keypair}") if keypair
5658
env[:ui].info(" -- Subnet ID: #{subnet_id}") if subnet_id
5759
env[:ui].info(" -- Private IP: #{private_ip_address}") if private_ip_address
60+
env[:ui].info(" -- Elastic IP: #{elastic_ip}") if elastic_ip
5861
env[:ui].info(" -- User Data: yes") if user_data
5962
env[:ui].info(" -- Security Groups: #{security_groups.inspect}") if !security_groups.empty?
6063
env[:ui].info(" -- User Data: #{user_data}") if user_data
@@ -120,6 +123,12 @@ def call(env)
120123

121124
@logger.info("Time to instance ready: #{env[:metrics]["instance_ready_time"]}")
122125

126+
# Allocate and associate an elastic IP if requested
127+
if elastic_ip
128+
domain = subnet_id ? 'vpc' : 'standard'
129+
do_elastic_ip(env, domain, server)
130+
end
131+
123132
if !env[:interrupted]
124133
env[:metrics]["instance_ssh_time"] = Util::Timer.time do
125134
# Wait for SSH to be ready.
@@ -153,6 +162,37 @@ def recover(env)
153162
end
154163
end
155164

165+
def do_elastic_ip(env, domain, server)
166+
allocation = env[:aws_compute].allocate_address(domain)
167+
if allocation.body['publicIp'].nil?
168+
@logger.debug("Could not allocate Elastic IP.")
169+
return nil
170+
end
171+
@logger.debug("Public IP #{allocation.body['publicIp']}")
172+
173+
# Associate the address and save the metadata to a hash
174+
if domain == 'vpc'
175+
# VPC requires an allocation ID to assign an IP
176+
association = env[:aws_compute].associate_address(server.id, nil, nil, allocation.body['allocationId'])
177+
h = { :allocation_id => allocation.body['allocationId'], :association_id => association.body['associationId'], :public_ip => allocation.body['publicIp'] }
178+
else
179+
# Standard EC2 instances only need the allocated IP address
180+
association = env[:aws_compute].associate_address(server.id, allocation.body['publicIp'])
181+
h = { :public_ip => allocation.body['publicIp'] }
182+
end
183+
184+
unless association.body['return']
185+
@logger.debug("Could not associate Elastic IP.")
186+
return nil
187+
end
188+
189+
# Save this IP to the data dir so it can be released when the instance is destroyed
190+
ip_file = env[:machine].data_dir.join('elastic_ip')
191+
ip_file.open('w+') do |f|
192+
f.write(h.to_json)
193+
end
194+
end
195+
156196
def terminate(env)
157197
destroy_env = env.dup
158198
destroy_env.delete(:interrupted)

lib/vagrant-aws/action/terminate_instance.rb

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
require "log4r"
2+
require "json"
23

34
module VagrantPlugins
45
module AWS
@@ -17,9 +18,29 @@ def call(env)
1718
env[:ui].info(I18n.t("vagrant_aws.terminating"))
1819
server.destroy
1920
env[:machine].id = nil
21+
22+
# Release the elastic IP
23+
ip_file = env[:machine].data_dir.join('elastic_ip')
24+
if ip_file.file?
25+
release_address(env,ip_file.read)
26+
ip_file.delete
27+
end
2028

2129
@app.call(env)
2230
end
31+
32+
# Release an elastic IP address
33+
def release_address(env,eip)
34+
h = JSON.parse(eip)
35+
# Use association_id and allocation_id for VPC, use public IP for EC2
36+
if h['association_id']
37+
env[:aws_compute].disassociate_address(nil,h['association_id'])
38+
env[:aws_compute].release_address(h['allocation_id'])
39+
else
40+
env[:aws_compute].disassociate_address(h['public_ip'])
41+
env[:aws_compute].release_address(h['public_ip'])
42+
end
43+
end
2344
end
2445
end
2546
end

lib/vagrant-aws/config.rb

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,11 @@ class Config < Vagrant.plugin("2", :config)
3939
# @return [String]
4040
attr_accessor :private_ip_address
4141

42+
# Acquire and attach an elastic IP address (VPC).
43+
#
44+
# @return [Boolean]
45+
attr_accessor :elastic_ip
46+
4247
# The name of the AWS region in which to create the instance.
4348
#
4449
# @return [String]
@@ -106,6 +111,7 @@ def initialize(region_specific=false)
106111
@user_data = UNSET_VALUE
107112
@use_iam_profile = UNSET_VALUE
108113
@block_device_mapping = {}
114+
@elastic_ip = UNSET_VALUE
109115

110116
# Internal state (prefix with __ so they aren't automatically
111117
# merged)
@@ -196,6 +202,9 @@ def finalize!
196202
# Default the private IP to nil since VPC is not default
197203
@private_ip_address = nil if @private_ip_address == UNSET_VALUE
198204

205+
# Acquire an elastic IP if requested
206+
@elastic_ip = nil if @elastic_ip == UNSET_VALUE
207+
199208
# Default region is us-east-1. This is sensible because AWS
200209
# generally defaults to this as well.
201210
@region = "us-east-1" if @region == UNSET_VALUE

spec/vagrant-aws/config_spec.rb

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
its("user_data") { should be_nil }
3131
its("use_iam_profile") { should be_false }
3232
its("block_device_mapping") {should == {} }
33+
its("elastic_ip") { should be_nil }
3334
end
3435

3536
describe "overriding defaults" do
@@ -40,7 +41,7 @@
4041
[:access_key_id, :ami, :availability_zone, :instance_ready_timeout,
4142
:instance_type, :keypair_name,
4243
:region, :secret_access_key, :security_groups,
43-
:subnet_id, :tags,
44+
:subnet_id, :tags, :elastic_ip,
4445
:use_iam_profile, :user_data, :block_device_mapping].each do |attribute|
4546

4647
it "should not default #{attribute} if overridden" do

0 commit comments

Comments
 (0)