cap-elb 0.0.3 → 0.0.4
Sign up to get free protection for your applications and to get access to all the features.
- data/MIT-LICENSE +20 -0
- data/README.markdown +104 -2
- data/Rakefile +6 -0
- data/cap-elb.gemspec +2 -2
- data/lib/cap-elb/version.rb +1 -1
- data/lib/cap-elb.rb +53 -20
- data/test/elb_test.rb +15 -0
- data/test/health/test_elb.rb +15 -0
- metadata +18 -14
- data/spec/elb_test.rb +0 -0
- /data/{spec → test}/.gemtest +0 -0
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2011 Dan MIley
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.markdown
CHANGED
@@ -3,12 +3,114 @@ cap-elb
|
|
3
3
|
|
4
4
|
Capistrano plugin or deploying to Amazon EC2 instances behind ELBs
|
5
5
|
|
6
|
-
|
7
6
|
Introduction
|
8
7
|
============
|
9
8
|
|
10
|
-
This capistrano plugin
|
9
|
+
This capistrano plugin lets you perform capistrano deployment tasks on either complete or highly segmented AWS instance sets within an AWS load balancer under your control.
|
11
10
|
|
12
11
|
Installation
|
13
12
|
============
|
14
13
|
|
14
|
+
`cap-elb` is a Capistrano plug-in configured as Ruby gem. You can install from rubygems.com or build from source via GitHub fork or downlaod.
|
15
|
+
|
16
|
+
RubyGems install:
|
17
|
+
---------
|
18
|
+
$ gem install cap-elb
|
19
|
+
|
20
|
+
How to Use
|
21
|
+
=====
|
22
|
+
|
23
|
+
In order to use the `cap-elb` plugin, you must require it in your `deploy.rb`:
|
24
|
+
|
25
|
+
require 'cap-elb'
|
26
|
+
|
27
|
+
If you have already been doing capistrano deploys to your AWS instances, you probably already have your
|
28
|
+
AWD credentials configured. Either add your credentials to your ~/.caprc :
|
29
|
+
|
30
|
+
set :aws_access_key_id, 'YOUR_AWS_ACCESS_KEY_ID'
|
31
|
+
set :aws_secret_access_key, 'YOUR_AWS_SECRET_ACCESS_KEY'
|
32
|
+
|
33
|
+
or, directly in your deploy file:
|
34
|
+
|
35
|
+
set :aws_access_key_id, 'YOUR_AWS_ACCESS_KEY_ID'
|
36
|
+
set :aws_secret_access_key, 'YOUR_AWS_SECRET_ACCESS_KEY'
|
37
|
+
|
38
|
+
If you wish, you can also set other AWS specfic parameters:
|
39
|
+
|
40
|
+
set :aws_params, :region => 'us-east-1'
|
41
|
+
|
42
|
+
In order to define your instance groups, you must specify the security group name, the roles and params:
|
43
|
+
Next you will set up your instance sets associated with a named load balancer instance in your AWS account.
|
44
|
+
You will call out the load balancer name (e.g. 'lb_webserver'), the capistrano role associated with that load balancer (.e.g. 'web'),
|
45
|
+
and any optional params.
|
46
|
+
|
47
|
+
loadbalancer :lb_webserver, :web
|
48
|
+
loadbalancer :lb_appserver, :app
|
49
|
+
loadbalancer :lb_dbserver, :db, :port => 22000
|
50
|
+
|
51
|
+
There are two special parameters you can add, :require and :exclude.
|
52
|
+
|
53
|
+
AWS instances have top level metadata and user defined tag data, and this data can be used by your loadbalancer rule
|
54
|
+
to include or exclude certain instances from the instance set.
|
55
|
+
|
56
|
+
Take the :require keyword; Lets say we only want to deploy to AWS instances which are in the 'running' state. To do that:
|
57
|
+
|
58
|
+
loadbalancer :lb_appserver, :app, :require => { :aws_state => "running" }
|
59
|
+
|
60
|
+
The server set defined here for role :app are all instances in the loadbalancer 'lb_appserver' with aws_state set to 'running'.
|
61
|
+
|
62
|
+
Perhaps you have added tags to your instances, if so, you might want to deploy to only the instances meeting a specific tag value:
|
63
|
+
|
64
|
+
loadbalancer :lb_appserver, :app, :require => { :aws_state => "running", :tags => {'fleet_color' => "green", 'tier' => 'free'} }
|
65
|
+
|
66
|
+
The server set defined here for role :app are all instances in the loadbalancer 'lb_appserver' with aws_state set to 'running',
|
67
|
+
and that have the named 2 tags set, with exactly those values for each. There can be other tags in the instance, but the named tags in the rule must be present
|
68
|
+
for the given instance to make it into the server set.
|
69
|
+
|
70
|
+
Now consider the :exclude keyword; Lets say we do not want to deploy to AWS instances which are 'micro' sized. To do that:
|
71
|
+
|
72
|
+
loadbalancer :lb_appserver, :app, :exclude => { :aws_instance_type => "t1.micro" }
|
73
|
+
|
74
|
+
You can exclude instances that have certain tags:
|
75
|
+
|
76
|
+
loadbalancer :lb_appserver, :app, :exclude => { :aws_instance_type => "t1.micro", :tags => {'state' => 'dontdeploy' } }
|
77
|
+
|
78
|
+
When your capistrono script is complete, you can deploy to all instances within the ELB that meet your criteria with:
|
79
|
+
|
80
|
+
% cap deploy
|
81
|
+
|
82
|
+
Here's an example of a task that does a quick list of the instance ids (if any) within the load balancer associated with the 'app' role
|
83
|
+
that meets the criteria you laid out in the loadbalancer definition line,
|
84
|
+
add this to your cap deploy file:
|
85
|
+
|
86
|
+
# run with cap ec2:list
|
87
|
+
namespace :ec2 do
|
88
|
+
desc "list instances"
|
89
|
+
task :list, :roles => :app do
|
90
|
+
run "hostname"
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
This will give you the list of hosts behind the load balancer that meet the criteria.
|
95
|
+
% cap ec2:list
|
96
|
+
|
97
|
+
Documentation
|
98
|
+
=============
|
99
|
+
Additional Ruby class/method documentation is available at: [http://rubydoc.info/gems/cap-elb/frames] (http://rubydoc.info/gems/cap-elb/frames)
|
100
|
+
|
101
|
+
* capistrano: [http://capify.org](http://capify.org)
|
102
|
+
* Amazon AWS: [http://aws.amazon.com](http://aws.amazon.com)
|
103
|
+
* Amazon AMI instance metadata: [http://docs.amazonwebservices.com/AWSEC2/latest/UserGuide/index.html?AESDG-chapter-instancedata.html](http://docs.amazonwebservices.com/AWSEC2/latest/UserGuide/index.html?AESDG-chapter-instancedata.html)
|
104
|
+
* Amazon AMI Tags: [http://docs.amazonwebservices.com/AWSEC2/latest/UserGuide/Using_Tags.html[(http://docs.amazonwebservices.com/AWSEC2/latest/UserGuide/Using_Tags.html)
|
105
|
+
|
106
|
+
Credits
|
107
|
+
=======
|
108
|
+
* capistrano-ec2group: [Logan Raarup](http://github.com/logandk)
|
109
|
+
* capistrano: [Jamis Buck](http://github.com/jamis/capistrano)
|
110
|
+
|
111
|
+
|
112
|
+
###Thanks to###
|
113
|
+
* [Logan Raarup](http://github.com/logandk - Logan's work with cap deploy using security group abstraction got me going on how to do an AWS oriented cap plug-in, thank you!
|
114
|
+
|
115
|
+
|
116
|
+
Copyright (c) 2011 Dan Miley, released under the MIT license
|
data/Rakefile
CHANGED
data/cap-elb.gemspec
CHANGED
@@ -8,8 +8,8 @@ Gem::Specification.new do |s|
|
|
8
8
|
s.authors = ["Dan Miley"]
|
9
9
|
s.email = ["dan.miley@gmail.com"]
|
10
10
|
s.homepage = "http://github.com/danmiley/cap-elb"
|
11
|
-
s.summary = %q{
|
12
|
-
s.description = %q{Capistrano can perform tasks on Amazon ELB instances; various arguments to allow instance tags to determine whether task should be applied on the given tag}
|
11
|
+
s.summary = %q{UNDEREAVY DEVELOPMENT AT THIS TIME: Capistrano can perform tasks on Amazon ELB instances.}
|
12
|
+
s.description = %q{(UNDER HEAVY ITERATIVE DEVELOPMENT AT THIS TIME, recommend wait for a 0.x release for usage.) Capistrano can perform tasks on Amazon ELB instances; various arguments to allow instance tags to determine whether task should be applied on the given tag}
|
13
13
|
|
14
14
|
s.rubyforge_project = "cap-elb"
|
15
15
|
|
data/lib/cap-elb/version.rb
CHANGED
data/lib/cap-elb.rb
CHANGED
@@ -1,8 +1,8 @@
|
|
1
|
-
require "cap-elb/version"
|
2
1
|
require 'right_aws'
|
2
|
+
require "cap-elb/version"
|
3
3
|
|
4
4
|
unless Capistrano::Configuration.respond_to?(:instance)
|
5
|
-
abort "
|
5
|
+
abort "cap-elb requires Capistrano 2"
|
6
6
|
end
|
7
7
|
|
8
8
|
module Capistrano
|
@@ -17,42 +17,75 @@ module Capistrano
|
|
17
17
|
# group :webserver, :web
|
18
18
|
# group :app_myappname, :app
|
19
19
|
# group "MySQL Servers", :db, :port => 22000
|
20
|
-
def loadbalancer (
|
20
|
+
def loadbalancer (named_load_balancer, *args)
|
21
|
+
require_arglist = args[1][:require] rescue {}
|
22
|
+
exclude_arglist = args[1][:exclude] rescue {}
|
21
23
|
|
22
24
|
# list of all the instances assoc'ed with this account
|
23
25
|
@ec2_api ||= RightAws::Ec2.new(fetch(:aws_access_key_id), fetch(:aws_secret_access_key), fetch(:aws_params, {}))
|
24
26
|
|
25
27
|
# fetch a raw list all the load balancers
|
26
28
|
@elb_api ||= RightAws::ElbInterface.new(fetch(:aws_access_key_id), fetch(:aws_secret_access_key))
|
29
|
+
|
27
30
|
# only get the named load balancer
|
28
|
-
named_elb_instance = @elb_api.describe_load_balancers.delete_if{ |
|
31
|
+
named_elb_instance = @elb_api.describe_load_balancers.delete_if{ |instance| instance[:load_balancer_name] != named_load_balancer.to_s }
|
29
32
|
|
30
|
-
|
33
|
+
# must exit if no load balancer on record for this account by given name in cap config file
|
34
|
+
raise Exception, "No load balancer named: #{named_load_balancer.to_s} for aws account with this access key: #{:aws_access_key_id}" if named_elb_instance.empty?
|
31
35
|
|
32
36
|
elb_ec2_instances = named_elb_instance[0][:instances] rescue {}
|
33
37
|
|
34
|
-
#
|
35
|
-
|
38
|
+
# get the full instance list for account, this is necessary to subsquently fish out the :dns_name for the instances that survive our reduction steps
|
39
|
+
account_instance_list = @ec2_api.describe_instances
|
40
|
+
|
41
|
+
# reduce to only the instances in the named ELB
|
42
|
+
account_instance_list.delete_if { |i| ! elb_ec2_instances.include?(i[:aws_instance_id]) }
|
36
43
|
|
37
|
-
#
|
38
|
-
|
44
|
+
# reduce against 'require' args, if an instance doesnt have the args in require_arglist, remove
|
45
|
+
account_instance_list.delete_if { |i| ! all_args_within_instance(i, require_arglist) } unless require_arglist.nil? or require_arglist.empty?
|
39
46
|
|
40
|
-
#
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
47
|
+
# reduce against 'exclude_arglist', if an instance has any of the args in exclude_arglist, remove
|
48
|
+
account_instance_list.delete_if { |i| any_args_within_instance(i, exclude_arglist) } unless exclude_arglist.nil? or exclude_arglist.empty?
|
49
|
+
|
50
|
+
# finally load the derived instances into the serverlist used by capistrano tasks
|
51
|
+
account_instance_list.each do |instance|
|
52
|
+
server(instance[:dns_name], *args)
|
46
53
|
end
|
47
54
|
end
|
55
|
+
|
56
|
+
private
|
57
|
+
|
58
|
+
def any_args_within_instance(instance, exclude_arglist)
|
59
|
+
exargs = exclude_arglist.clone # must copy since delete transcends scope; if we don't copy, subsequent 'map'ped enum arglists would be side-effected
|
60
|
+
tag_exclude_state = nil # default assumption
|
61
|
+
# pop off a :tags arg to treat separately, its a separate namespace
|
62
|
+
tag_exclude_arglist = exargs.delete(:tags)
|
63
|
+
|
64
|
+
tag_exclude_state = tag_exclude_arglist.map { |k, v| (instance[:tags][k] == v rescue nil) }.inject(nil) { |inj, el| el || inj } if !tag_exclude_arglist.nil?
|
65
|
+
# we want all nils for the result here, so we logical-or the result map, and invert it
|
66
|
+
tag_exclude_state || exargs.map { |k, v| instance[k] == v }.inject(nil) { |inj, el| inj || el }
|
67
|
+
end
|
68
|
+
|
69
|
+
# the instance has attributes
|
70
|
+
def all_args_within_instance(instance, require_arglist)
|
71
|
+
reqargs = require_arglist.clone # must copy since delete transcends scope; if we don't copy, subsequent 'map'ped enum arglists would be side-effected
|
72
|
+
tag_require_state = true # default assumption
|
73
|
+
# pop off a :tags arg to treat separately, effectively a separate namespace to be checked agains
|
74
|
+
tag_require_arglist = reqargs.delete(:tags)
|
75
|
+
tag_require_state = tag_require_arglist.map { |k, v| (instance[:tags][k] == v rescue nil) }.inject(nil) { |inj, el| el || inj } if !tag_require_arglist.nil?
|
76
|
+
|
77
|
+
# require arglist is a hash with k/v's, each of those need to be in the instance
|
78
|
+
tag_require_state && reqargs.map { |k, v| instance[k] == v }.inject(true) { |inj, el| inj && el }
|
79
|
+
end
|
80
|
+
|
48
81
|
end
|
49
82
|
|
50
83
|
include LoadBalancers
|
51
84
|
end
|
52
85
|
end
|
53
86
|
|
54
|
-
#
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
87
|
+
# stub for future extensions
|
88
|
+
module Cap
|
89
|
+
module Elb
|
90
|
+
end
|
91
|
+
end
|
data/test/elb_test.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'rspec'
|
2
|
+
require 'capistrano'
|
3
|
+
require 'cap-elb'
|
4
|
+
|
5
|
+
describe Cap, "baseline" do
|
6
|
+
it "returns a good error if no load balancer found" do
|
7
|
+
true.should == true
|
8
|
+
end
|
9
|
+
it "returns a good error if no load balancer found" do
|
10
|
+
true.should == true
|
11
|
+
end
|
12
|
+
it "returns a good error if no load balancer found" do
|
13
|
+
true.should == true
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'rspec'
|
2
|
+
require 'capistrano'
|
3
|
+
require 'cap-elb'
|
4
|
+
|
5
|
+
describe Cap, "baseline" do
|
6
|
+
it "returns a good error if no load balancer found" do
|
7
|
+
true.should == true
|
8
|
+
end
|
9
|
+
it "returns a good error if no load balancer found" do
|
10
|
+
true.should == true
|
11
|
+
end
|
12
|
+
it "returns a good error if no load balancer found" do
|
13
|
+
true.should == true
|
14
|
+
end
|
15
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cap-elb
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.4
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2011-10-
|
12
|
+
date: 2011-10-27 00:00:00.000000000Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: right_aws
|
16
|
-
requirement: &
|
16
|
+
requirement: &2156460540 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - =
|
@@ -21,10 +21,10 @@ dependencies:
|
|
21
21
|
version: 2.1.0
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *2156460540
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: rspec
|
27
|
-
requirement: &
|
27
|
+
requirement: &2156459320 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ~>
|
@@ -32,10 +32,11 @@ dependencies:
|
|
32
32
|
version: '2.6'
|
33
33
|
type: :development
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
36
|
-
description:
|
37
|
-
|
38
|
-
|
35
|
+
version_requirements: *2156459320
|
36
|
+
description: (UNDER HEAVY ITERATIVE DEVELOPMENT AT THIS TIME, recommend wait for a
|
37
|
+
0.x release for usage.) Capistrano can perform tasks on Amazon ELB instances; various
|
38
|
+
arguments to allow instance tags to determine whether task should be applied on
|
39
|
+
the given tag
|
39
40
|
email:
|
40
41
|
- dan.miley@gmail.com
|
41
42
|
executables: []
|
@@ -44,13 +45,15 @@ extra_rdoc_files: []
|
|
44
45
|
files:
|
45
46
|
- .gitignore
|
46
47
|
- Gemfile
|
48
|
+
- MIT-LICENSE
|
47
49
|
- README.markdown
|
48
50
|
- Rakefile
|
49
51
|
- cap-elb.gemspec
|
50
52
|
- lib/cap-elb.rb
|
51
53
|
- lib/cap-elb/version.rb
|
52
|
-
-
|
53
|
-
-
|
54
|
+
- test/.gemtest
|
55
|
+
- test/elb_test.rb
|
56
|
+
- test/health/test_elb.rb
|
54
57
|
homepage: http://github.com/danmiley/cap-elb
|
55
58
|
licenses: []
|
56
59
|
post_install_message:
|
@@ -71,10 +74,11 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
71
74
|
version: '0'
|
72
75
|
requirements: []
|
73
76
|
rubyforge_project: cap-elb
|
74
|
-
rubygems_version: 1.8.
|
77
|
+
rubygems_version: 1.8.11
|
75
78
|
signing_key:
|
76
79
|
specification_version: 3
|
77
|
-
summary: ! '
|
80
|
+
summary: ! 'UNDEREAVY DEVELOPMENT AT THIS TIME: Capistrano can perform tasks on Amazon
|
78
81
|
ELB instances.'
|
79
82
|
test_files:
|
80
|
-
-
|
83
|
+
- test/elb_test.rb
|
84
|
+
- test/health/test_elb.rb
|
data/spec/elb_test.rb
DELETED
File without changes
|
/data/{spec → test}/.gemtest
RENAMED
File without changes
|