Navigation Menu

Skip to content

Commit

Permalink
initial version
Browse files Browse the repository at this point in the history
  • Loading branch information
jnewland committed May 19, 2011
1 parent 7492546 commit 6503338
Show file tree
Hide file tree
Showing 6 changed files with 243 additions and 0 deletions.
31 changes: 31 additions & 0 deletions libraries/elb.rb
@@ -0,0 +1,31 @@
module WebsterClay
module Aws
module Elb
def elb
@@elb ||= Fog::AWS::ELB.new(
:aws_access_key_id => new_resource.aws_access_key,
:aws_secret_access_key => new_resource.aws_secret_access_key,
:region => new_resource.region
)
end

def ec2
@@ec2 ||= Fog::Compute.new(:provider => 'AWS',
:aws_access_key_id => new_resource.aws_access_key,
:aws_secret_access_key => new_resource.aws_secret_access_key,
:region => new_resource.region
)
end

def load_balancer_by_name(name)
elb.describe_load_balancers.body["DescribeLoadBalancersResult"]["LoadBalancerDescriptions"].detect { |lb| lb["LoadBalancerName"] == new_resource.lb_name }
end

def availability_zone_for_instances(instances)
ec2.describe_instances('instance-id' => [*instances]).body['reservationSet'].map { |r| r['instancesSet'] }.flatten.map { |i| i['placement']['availabilityZone'] }
end

end
end
end

29 changes: 29 additions & 0 deletions metadata.json
@@ -0,0 +1,29 @@
{
"dependencies": {
},
"name": "elb",
"maintainer_email": "jesse@websterclay.com",
"attributes": {
},
"license": "Apache 2.0",
"suggestions": {
},
"platforms": {
},
"maintainer": "Jesse Newland",
"long_description": "= DESCRIPTION:\n\n= REQUIREMENTS:\n\n= ATTRIBUTES: \n\n= USAGE:\n\n",
"version": "0.1.0",
"recommendations": {
},
"recipes": {
},
"groupings": {
},
"conflicting": {
},
"replacing": {
},
"description": "Configure Elastic Load Balancers at AWS",
"providing": {
}
}
6 changes: 6 additions & 0 deletions metadata.rb
@@ -0,0 +1,6 @@
maintainer "Jesse Newland"
maintainer_email "jesse@websterclay.com"
license "Apache 2.0"
description "Configure Elastic Load Balancers at AWS"
long_description IO.read(File.join(File.dirname(__FILE__), 'README.rdoc'))
version "0.1"
138 changes: 138 additions & 0 deletions providers/load_balancer.rb
@@ -0,0 +1,138 @@
include WebsterClay::Aws::Elb

# TODO: error handling
# TODO: count instances in each zone and warn if not equal
# TODO: warn if only one availability zone

def load_current_resource

@current_lb = load_balancer_by_name(new_resource.lb_name)

@current_resource = Chef::Resource::ElbLoadBalancer.new(new_resource.lb_name)
@current_resource.lb_name(new_resource.lb_name)
@current_resource.aws_access_key(new_resource.aws_access_key)
@current_resource.aws_secret_access_key(new_resource.aws_secret_access_key)
@current_resource.region(new_resource.region)
@current_resource.listeners(new_resource.listeners)
@current_resource.timeout(new_resource.timeout)

if @current_lb
@current_resource.availability_zones(@current_lb['AvailabilityZones'])
@current_resource.instances(@current_lb['Instances'])
end
@current_resource.availability_zones || @current_resource.availability_zones([])
@current_resource.instances || @current_resource.instances([])

if new_resource.instances.nil? && new_resource.search_query
new_resource.instances(search(:node, new_resource.search_query).map { |n| n['ec2']['instance_id']})
end

all_zones = availability_zone_for_instances(new_resource.instances)
unique_zones = all_zones.compact.uniq

if new_resource.availability_zones.nil?
new_resource.availability_zones(unique_zones)
end
end

action :create do
ruby_block "Create ELB #{new_resource.lb_name}" do
block do
elb.create_load_balancer(new_resource.availability_zones, new_resource.lb_name, new_resource.listeners)
data = nil
begin
Timeout::timeout(new_resource.timeout) do
while true
data = load_balancer_by_name(new_resource.lb_name)
break if data
sleep 3
end
end
rescue Timeout::Error
raise "Timed out waiting for ELB data after #{new_resource.timeout} seconds"
end
node.set[:elb][new_resource.lb_name] = data
node.save if !Chef::Config.solo
end
action :create
not_if do
if data = load_balancer_by_name(new_resource.lb_name)
node.set[:elb][new_resource.lb_name] = data
node.save if !Chef::Config.solo
true
else
false
end
end
end
new_resource.updated_by_last_action(true)

instances_to_add = new_resource.instances - current_resource.instances
instances_to_delete = current_resource.instances - new_resource.instances

instances_to_add.each do |instance_to_add|
ruby_block "Register instance #{instance_to_add} with ELB #{new_resource.lb_name}" do
block do
elb.register_instances_with_load_balancer([instance_to_add], new_resource.lb_name)
node.set[:elb][new_resource.lb_name] = load_balancer_by_name(new_resource.lb_name)
node.save if !Chef::Config.solo
end
action :create
end
new_resource.updated_by_last_action(true)
end

instances_to_delete.each do |instance_to_delete|
ruby_block "Deregister instance #{instance_to_delete} from ELB #{new_resource.lb_name}" do
block do
elb.deregister_instances_from_load_balancer([instance_to_delete], new_resource.lb_name)
node.set[:elb][new_resource.lb_name] = load_balancer_by_name(new_resource.lb_name)
node.save if !Chef::Config.solo
end
action :create
end
new_resource.updated_by_last_action(true)
end

zones_to_add = new_resource.availability_zones - current_resource.availability_zones
zones_to_delete = current_resource.availability_zones - new_resource.availability_zones

zones_to_add.each do |zone_to_add|
ruby_block "Enabling Availability Zone #{zone_to_add} for ELB #{new_resource.lb_name}" do
block do
elb.enable_availability_zones_for_load_balancer([zone_to_add], new_resource.lb_name)
node.set[:elb][new_resource.lb_name] = load_balancer_by_name(new_resource.lb_name)
node.save if !Chef::Config.solo
end
action :create
end
new_resource.updated_by_last_action(true)
end

zones_to_delete.each do |zone_to_delete|
ruby_block "Disable Availability Zone #{zone_to_delete} for ELB #{new_resource.lb_name}" do
block do
elb.disable_availability_zones_for_load_balancer([zone_to_delete], new_resource.lb_name)
node.set[:elb][new_resource.lb_name] = load_balancer_by_name(new_resource.lb_name)
node.save if !Chef::Config.solo
end
action :create
end
new_resource.updated_by_last_action(true)
end

end

action :delete do
ruby_block "Delete ELB #{new_resource.lb_name}" do
block do
elb.delete_load_balancer(new_resource.lb_name)
node.set[:elb][new_resource.lb_name] = nil
node.save if !Chef::Config.solo
end
action :create
not_if do
!!!load_balancer_by_name(new_resource.lb_name)
end
end
end
28 changes: 28 additions & 0 deletions recipes/default.rb
@@ -0,0 +1,28 @@
#
# Cookbook Name:: elb
# Recipe:: default
#
# Copyright 2011, Webster Clay, LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

r = gem_package "fog" do
action :nothing
end

r.run_action(:install)

require 'rubygems'
Gem.clear_paths
require 'fog'
11 changes: 11 additions & 0 deletions resources/load_balancer.rb
@@ -0,0 +1,11 @@
actions :create, :delete

attribute :lb_name, :kind_of => String, :name_attribute => true
attribute :aws_access_key, :kind_of => String
attribute :aws_secret_access_key, :kind_of => String
attribute :region, :kind_of => String, :default => 'us-east-1'
attribute :availability_zones, :kind_of => Array
attribute :listeners, :kind_of => Array, :default => [{"InstancePort" => 80, "Protocol" => "HTTP", "LoadBalancerPort" => 80}]
attribute :instances, :kind_of => Array
attribute :search_query, :kind_of => String
attribute :timeout, :default => 60

0 comments on commit 6503338

Please sign in to comment.