Skip to content
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

Add the ability to hint the rolling_deploy with a named ELB #64

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
Open
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
4 changes: 3 additions & 1 deletion capify-ec2.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@ Gem::Specification.new do |s|
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
s.require_paths = ["lib"]
s.add_dependency('fog', '>= 1.23.0')
s.add_dependency('fog', '=1.23.0')
s.add_dependency('aws-sdk', '~> 3')
s.add_dependency('colored', '=1.2')
s.add_dependency('capistrano', '~> 2.14')
s.add_dependency('net-ssh', '=3.0.2')
end
35 changes: 33 additions & 2 deletions lib/capify-ec2.rb
Original file line number Diff line number Diff line change
Expand Up @@ -266,7 +266,6 @@ def get_load_balancer_by_name(load_balancer_name)
lbs[load_balancer.id] = load_balancer
end
lbs[load_balancer_name]

end

def deregister_instance_from_elb(instance_name)
Expand Down Expand Up @@ -306,6 +305,34 @@ def register_instance_in_elb(instance_name, load_balancer_name = '')
end
end

def deregister_instance_from_named_elbs_by_dns(server_dns, load_balancer_names)
instance = get_instance_by_dns(server_dns)

lbs = []
threads = []

for load_balancer_name in load_balancer_names do
threads << Thread.new(load_balancer_name) do |lb|
load_balancer = get_load_balancer_by_name(lb)

if load_balancer
puts "[Capify-EC2] Removing instance from named ELB '#{load_balancer.id}'..."

result = elb.deregister_instances_from_load_balancer(instance.id, load_balancer.id)
raise "Unable to remove instance from ELB '#{load_balancer.id}'..." unless result.status == 200

lbs << load_balancer
end
end
end

for t in threads do
t.join
end

lbs
end

def deregister_instance_from_elb_by_dns(server_dns)
instance = get_instance_by_dns(server_dns)
load_balancer = get_load_balancer_by_instance(instance.id)
Expand All @@ -316,7 +343,11 @@ def deregister_instance_from_elb_by_dns(server_dns)
result = elb.deregister_instances_from_load_balancer(instance.id, load_balancer.id)
raise "Unable to remove instance from ELB '#{load_balancer.id}'..." unless result.status == 200

return load_balancer
#TODO: The ability to remove an instance from multiple ELBs has been added, which returns an [] of elbs.
#I've taken a shortcut here to return an array for this (the single ELB case). However, the correct solution
#would be to extend the above method to remove an instance from multiple ELBs by DNS too.
#This may break things for some users however? Needs to be checked.
return [load_balancer]
end
false
end
Expand Down
42 changes: 30 additions & 12 deletions lib/capify-ec2/capistrano.rb
Original file line number Diff line number Diff line change
Expand Up @@ -121,19 +121,28 @@ def capify_ec2

roles.clear

load_balancer_to_reregister = nil # Set to nil again here, to ensure it always starts off nil for every iteration.
load_balancers_to_reregister = [] # Set to empty again here, to ensure it always starts off empty for every iteration.
is_load_balanced = false
load_balancer_names = false

server_roles.each do |a_role|
role a_role, server_dns, all_options[a_role][server_dns]
is_load_balanced = true if all_options[a_role][server_dns][:load_balanced]

if all_options[a_role][server_dns][:elb_names]
load_balancer_names = all_options[a_role][server_dns][:elb_names]
end
end

puts "[Capify-EC2]"
puts "[Capify-EC2] (#{index+1} of #{all_servers.length}) Beginning deployment to #{instance_dns_with_name_tag(server_dns)} with #{server_roles.count > 1 ? 'roles' : 'role'} '#{server_roles.join(', ')}'...".bold

unless dry_run
load_balancer_to_reregister = capify_ec2.deregister_instance_from_elb_by_dns(server_dns) if is_load_balanced
if is_load_balanced && !dry_run
if load_balancer_names
load_balancers_to_reregister = capify_ec2.deregister_instance_from_named_elbs_by_dns(server_dns, load_balancer_names)
else
load_balancers_to_reregister = capify_ec2.deregister_instance_from_elb_by_dns(server_dns)
end
end

# Call the standard 'cap deploy' task with our redefined role containing a single server.
Expand Down Expand Up @@ -165,19 +174,28 @@ def capify_ec2
end
end
end

end

if load_balancer_to_reregister
reregistered = capify_ec2.reregister_instance_with_elb_by_dns(server_dns, load_balancer_to_reregister, 60)
if reregistered
puts "[Capify-EC2] Instance registration with ELB '#{load_balancer_to_reregister.id}' successful.".green.bold
else
puts "[Capify-EC2] Instance registration with ELB '#{load_balancer_to_reregister.id}' failed!".red.bold
raise CapifyEC2RollingDeployError.new("ELB registration timeout exceeded", server_dns)
threads = []

for load_balancer_to_reregister in load_balancers_to_reregister do
threads << Thread.new(load_balancer_to_reregister) do |lb|
puts "[Capify-EC2] Starting registration of ELB '#{lb.id}'"

reregistered = capify_ec2.reregister_instance_with_elb_by_dns(server_dns, lb, 60)
if reregistered
puts "[Capify-EC2] Instance registration with ELB '#{lb.id}' successful.".green.bold
else
puts "[Capify-EC2] Instance registration with ELB '#{lb.id}' failed!".red.bold
raise CapifyEC2RollingDeployError.new("ELB registration timeout exceeded", server_dns)
end
end
end

for t in threads do
t.join
end

puts "[Capify-EC2] Deployment successful to #{instance_dns_with_name_tag(server_dns)}.".green.bold
successful_deploys << server_dns

Expand Down Expand Up @@ -327,4 +345,4 @@ def pluralise(n, singular, plural=nil)
"#{singular}s"
end
end
end
end
13 changes: 13 additions & 0 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -550,7 +550,20 @@ If an instance has been tagged with multiple roles, this behaviour will apply if

If an instance is not associated with any ELBs, then the behaviour will be skipped silently, even if `:load_balanced` is set to 'true'.

If an instance belongs to multiple ELBs (e.g. a single instance pointed to by separate ELBs), you can force which ELBs are chosen by using the :elb_names parameter like this:

```ruby
ec2_roles :name => "web",
:variables => {
:healthcheck => {
:path => '/status',
:port => 80,
:result => 'OK'
}
:load_balanced => true,
:elb_names => ["the_name_of_your_elb", "the_name_of_another_elb"]
}
```

#### Viewing All Instances

Expand Down