breeze 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.ruby-version +1 -0
- data/Gemfile +1 -1
- data/README.md +34 -18
- data/features/support/env.rb +1 -0
- data/lib/breeze.rb +1 -1
- data/lib/breeze/fog_wrapper.rb +19 -1
- data/lib/breeze/tasks.rb +2 -0
- data/lib/breeze/tasks/app.rb +142 -44
- data/lib/breeze/tasks/describe.rb +17 -0
- data/lib/breeze/tasks/elasticache.rb +24 -0
- data/lib/breeze/tasks/elb.rb +40 -0
- data/lib/breeze/veur.rb +8 -0
- data/lib/templates/Thorfile +39 -0
- metadata +22 -41
- data/.rbenv-version +0 -1
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 0700bdcae3cd19bf8920aeff10db9d3d4d5eaac6
|
4
|
+
data.tar.gz: 4aea1e6bf9898e114c2ebb87cd74ba3e5e1e5a5f
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: af99135461958862e35d01aa4966fe135ffbcbbc0ea7ff580aedab8016a65d1f3f9e153ca65879ccbac004fca704ca0a168a54440022b0eade90323cc38ef074
|
7
|
+
data.tar.gz: ff9683ce457c7af33c036bbb4d29aadf64bc48ac7a2007dcf89e28369f6112995b2e308a42eadba25601fbc7589836198684af718f4a04539204e784c3867cbe
|
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
2.1.1
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -5,7 +5,8 @@ and deployments. Currently only [Amazon's AWS cloud](http://aws.amazon.com/) is
|
|
5
5
|
[fog](https://github.com/geemus/fog) for the hard work so it should be fairly easy to add support for other cloud computing
|
6
6
|
providers that are supported by fog.
|
7
7
|
|
8
|
-
Breeze implements zero downtime deploys and rollbacks by moving an elastic ip from one server to another
|
8
|
+
Breeze implements zero downtime deploys and rollbacks by moving an elastic ip from one server to another or by replacing
|
9
|
+
server instances behind an [elastic load balancer](http://aws.amazon.com/elasticloadbalancing). Db migrations have to be
|
9
10
|
compatible with the previous version. http://pedro.herokuapp.com/past/2011/7/13/rails_migrations_with_no_downtime/
|
10
11
|
|
11
12
|
## install
|
@@ -50,16 +51,16 @@ These tasks call app tasks with fixed parameters.
|
|
50
51
|
|
51
52
|
app
|
52
53
|
---
|
53
|
-
thor app:deploy PUBLIC_SERVER_NAME
|
54
|
-
thor app:disable PUBLIC_SERVER_NAME
|
55
|
-
thor app:enable PUBLIC_SERVER_NAME
|
56
|
-
thor app:rollback PUBLIC_SERVER_NAME
|
57
|
-
thor app:start PUBLIC_SERVER_NAME
|
58
|
-
thor app:stop PUBLIC_SERVER_NAME
|
54
|
+
thor app:deploy PUBLIC_SERVER_NAME # Deploy a new version by replacing old servers with new ones
|
55
|
+
thor app:disable PUBLIC_SERVER_NAME # Upload system/maintenance.html to web servers
|
56
|
+
thor app:enable PUBLIC_SERVER_NAME # Remove system/maintenance.html from web servers
|
57
|
+
thor app:rollback PUBLIC_SERVER_NAME # Rollback a deploy
|
58
|
+
thor app:start PUBLIC_SERVER_NAME # Start a new app with web server and db
|
59
|
+
thor app:stop PUBLIC_SERVER_NAME # Destroy web server and db
|
59
60
|
|
60
61
|
configuration
|
61
62
|
-------------
|
62
|
-
thor configuration:deploy_to_localhost # Transform and deploy server configuration files to the local file system based
|
63
|
+
thor configuration:deploy_to_localhost [FILE] # Transform and deploy server configuration files to the local file system based on ERB templates in config/server
|
63
64
|
|
64
65
|
db
|
65
66
|
--
|
@@ -67,32 +68,47 @@ These tasks call app tasks with fixed parameters.
|
|
67
68
|
thor db:create SERVER_NAME [DB_NAME] # Create a new database server
|
68
69
|
thor db:destroy NAME # Destroy a database server
|
69
70
|
|
70
|
-
dns
|
71
|
-
---
|
72
|
-
thor dns:record:create ZONE_ID NAME TYPE IP [TTL] # Create a new DNS record
|
73
|
-
thor dns:record:destroy ZONE_ID NAME [TYPE] # Destroy a DNS record
|
74
|
-
thor dns:zone:create DOMAIN # Create a new DNS zone
|
75
|
-
thor dns:zone:destroy ZONE_ID # Destroy a DNS zone
|
76
|
-
thor dns:zone:import ZONE_ID FILE # Creates dns records specified in FILE
|
77
|
-
|
78
71
|
describe
|
79
72
|
--------
|
80
73
|
thor describe:addresses # List allocated ip addresses
|
74
|
+
thor describe:cache_clusters # Describe ElastiCache clusters
|
81
75
|
thor describe:cloud_resources # List all cloud resources that the current account can control with breeze
|
82
76
|
thor describe:db_servers # List database servers
|
83
77
|
thor describe:dns_records ZONE_ID # List all DNS records for the given zone
|
84
78
|
thor describe:dns_zones # Describe DNS zones
|
85
79
|
thor describe:images # Describe machine images owned by Breeze::CONFIGURATION[:image_owner]
|
80
|
+
thor describe:load_balancers # Describe ELB load balancers
|
86
81
|
thor describe:servers # Describe server instances
|
87
82
|
thor describe:volumes # Describe block store volumes (EBS)
|
88
83
|
|
84
|
+
dns
|
85
|
+
---
|
86
|
+
thor dns:record:create ZONE_ID NAME TYPE IP [TTL] # Create a new DNS record
|
87
|
+
thor dns:record:destroy ZONE_ID NAME [TYPE] # Destroy a DNS record
|
88
|
+
thor dns:zone:create DOMAIN # Create a new DNS zone
|
89
|
+
thor dns:zone:destroy ZONE_ID # Destroy a DNS zone
|
90
|
+
thor dns:zone:import ZONE_ID FILE # Creates dns records specified in FILE
|
91
|
+
|
92
|
+
elasticache
|
93
|
+
-----------
|
94
|
+
thor elasticache:create CLUSTER_NAME # Create a new cache cluster
|
95
|
+
thor elasticache:destroy CLUSTER_NAME # Destroy a cache cluster
|
96
|
+
|
97
|
+
elb
|
98
|
+
---
|
99
|
+
thor elb:add_instances LOAD_BALANCER_NAME instance_id [instance_id, ...] # Add server instances to a load balancer
|
100
|
+
thor elb:create LOAD_BALANCER_NAME [CNAME] [DNS_ZONE_ID] # Create a new elastic load balancer
|
101
|
+
thor elb:destroy LOAD_BALANCER_NAME # Destroy an elastic load balancer
|
102
|
+
thor elb:remove_instances LOAD_BALANCER_NAME instance_id [instance_id, ...] # Remove server instances from a load balancer
|
103
|
+
|
89
104
|
server
|
90
105
|
------
|
91
106
|
thor server:address:associate IP NEW_SERVER_ID # Associate an existing IP with a new server
|
92
107
|
thor server:address:create SERVER_ID # Create and associate a new elastic ip
|
93
108
|
thor server:address:release IP # Release the ip address
|
94
109
|
thor server:create # Launch a new server instance
|
95
|
-
thor server:destroy INSTANCE_ID
|
96
|
-
thor server:image:create # Launch a server with the base image, wait for it to boot, invoke
|
110
|
+
thor server:destroy INSTANCE_ID [...] # Terminate a running (or stopped) server instance
|
111
|
+
thor server:image:create # Launch a server with the base image, wait for it to boot, invoke prepare_private_image(ip_address), stop the server, create a new machine image as a snapshot of the root device, and destroy the server.
|
112
|
+
thor server:image:destroy IMAGE_ID [...] # Deregister the image and destroy the related volume snapshot
|
97
113
|
thor server:tag:create SERVER_ID KEY VALUE # Create or update a tag
|
98
114
|
thor server:tag:destroy SERVER_ID KEY # Delete a tag
|
data/features/support/env.rb
CHANGED
data/lib/breeze.rb
CHANGED
data/lib/breeze/fog_wrapper.rb
CHANGED
@@ -7,7 +7,7 @@ module Breeze
|
|
7
7
|
module FogWrapper
|
8
8
|
|
9
9
|
def self.connection(type)
|
10
|
-
{:
|
10
|
+
{compute: Compute, dns: DNS, rds: RDS, elasticache: Elasticache, elb: ELB}[type].get_connection
|
11
11
|
end
|
12
12
|
|
13
13
|
def self.flush_mock_data!
|
@@ -79,5 +79,23 @@ module Breeze
|
|
79
79
|
def mock_class ; Fog::AWS::RDS::Mock ; end
|
80
80
|
end
|
81
81
|
|
82
|
+
class Elasticache < AbstractConnectionWrapper
|
83
|
+
def self.direct_fog_connection
|
84
|
+
Fog::AWS::Elasticache.new(CONFIGURATION[:cloud_service])
|
85
|
+
end
|
86
|
+
private
|
87
|
+
def data_file ; 'fog_elasticache_data.yaml' ; end
|
88
|
+
def mock_class ; Fog::AWS::Elasticache::Mock ; end
|
89
|
+
end
|
90
|
+
|
91
|
+
class ELB < AbstractConnectionWrapper
|
92
|
+
def self.direct_fog_connection
|
93
|
+
Fog::AWS::ELB.new(CONFIGURATION[:cloud_service])
|
94
|
+
end
|
95
|
+
private
|
96
|
+
def data_file ; 'fog_elb_data.yaml' ; end
|
97
|
+
def mock_class ; Fog::AWS::ELB::Mock ; end
|
98
|
+
end
|
99
|
+
|
82
100
|
end
|
83
101
|
end
|
data/lib/breeze/tasks.rb
CHANGED
data/lib/breeze/tasks/app.rb
CHANGED
@@ -4,42 +4,63 @@ module Breeze
|
|
4
4
|
|
5
5
|
class App < Server
|
6
6
|
|
7
|
-
desc 'start PUBLIC_SERVER_NAME
|
8
|
-
method_options :
|
9
|
-
|
7
|
+
desc 'start PUBLIC_SERVER_NAME', 'Start a new app with web server and db'
|
8
|
+
method_options db: true, db_server_name: :string, db_name: :string, db_to_clone: :string,
|
9
|
+
elasticache: true, cache_cluster_name: :string,
|
10
|
+
elastic_ip: true, dns_ttl: 60,
|
11
|
+
elb_name: :string, elb_cname: true,
|
12
|
+
deploy_branch: :string
|
13
|
+
def start(public_server_name)
|
10
14
|
if options[:db]
|
11
|
-
raise '
|
15
|
+
raise '--db-server-name is required unless --no-db is given.' if options[:db_server_name].nil?
|
12
16
|
if options[:db_to_clone]
|
13
|
-
thor("db:clone #{options[:db_to_clone]} #{db_server_name}")
|
17
|
+
thor("db:clone #{options[:db_to_clone]} #{options[:db_server_name]}")
|
14
18
|
else
|
15
|
-
thor("db:create #{db_server_name} #{db_name}")
|
19
|
+
thor("db:create #{options[:db_server_name]} #{options[:db_name]}")
|
16
20
|
end
|
17
21
|
end
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
22
|
+
if options[:elasticache]
|
23
|
+
raise '--cache-cluster-name is required unless --no-elasticache is given.' if options[:cache_cluster_name].nil?
|
24
|
+
thor("elasticache:create #{options[:cache_cluster_name]}")
|
25
|
+
end
|
26
|
+
if options[:elb_name]
|
27
|
+
create_elb_and_app_servers(public_server_name, options)
|
28
|
+
else
|
29
|
+
create_app_server_with_elastic_ip(public_server_name, options)
|
23
30
|
end
|
24
|
-
deploy_command([server], public_server_name, db_server_name, options[:deploy_branch]) if options[:deploy_branch]
|
25
|
-
thor("dns:record:create #{zone_id(public_server_name)} #{public_server_name}. A #{ip(server)} #{options[:dns_ttl]}")
|
26
31
|
end
|
27
32
|
|
28
33
|
desc 'stop PUBLIC_SERVER_NAME', 'Destroy web server and db'
|
29
34
|
method_options :force => false
|
30
35
|
def stop(public_server_name)
|
31
36
|
dbs_to_destroy = []
|
37
|
+
cache_clusters_to_destroy = []
|
38
|
+
elb_to_destroy = nil
|
32
39
|
active_servers(public_server_name).each do |server|
|
33
40
|
server.addresses.each do |address|
|
34
41
|
thor("server:address:release #{address.public_ip}")
|
35
42
|
end
|
36
|
-
thor("dns:record:destroy #{zone_id(public_server_name)} #{public_server_name}. A")
|
37
43
|
dbs_to_destroy << server.breeze_data['db']
|
44
|
+
cache_clusters_to_destroy << server.breeze_data['cache']
|
45
|
+
elb_to_destroy ||= server.breeze_data['elb']
|
38
46
|
thor("server:destroy #{server.id}")
|
39
47
|
end
|
40
48
|
dbs_to_destroy.uniq.compact.each do |db_name|
|
41
49
|
thor("db:destroy #{db_name}")
|
42
50
|
end
|
51
|
+
cache_clusters_to_destroy.uniq.compact.each do |cache_cluster_name|
|
52
|
+
thor("elasticache:destroy #{cache_cluster_name}")
|
53
|
+
end
|
54
|
+
if elb_to_destroy
|
55
|
+
elb_cname_record = find_zone_recursively(public_server_name).records.detect{ |r| r.name == "#{public_server_name}." and r.type == 'CNAME' }
|
56
|
+
if elb_cname_record
|
57
|
+
thor("elb:destroy #{elb_to_destroy} #{public_server_name} #{zone_id(public_server_name)}")
|
58
|
+
else
|
59
|
+
thor("elb:destroy #{elb_to_destroy}")
|
60
|
+
end
|
61
|
+
else
|
62
|
+
thor("dns:record:destroy #{zone_id(public_server_name)} #{public_server_name}. A")
|
63
|
+
end
|
43
64
|
end
|
44
65
|
|
45
66
|
desc 'disable PUBLIC_SERVER_NAME', 'Upload system/maintenance.html to web servers'
|
@@ -52,12 +73,63 @@ module Breeze
|
|
52
73
|
on_each_server(enable_app_command, public_server_name)
|
53
74
|
end
|
54
75
|
|
55
|
-
desc 'deploy PUBLIC_SERVER_NAME
|
56
|
-
|
76
|
+
desc 'deploy PUBLIC_SERVER_NAME', 'Deploy a new version by replacing old servers with new ones'
|
77
|
+
method_options db_server_name: :string, cache_cluster_name: :string, elb_name: :string, deploy_branch: :string
|
78
|
+
def deploy(public_server_name)
|
79
|
+
if options[:elb_name]
|
80
|
+
deploy_with_elb(public_server_name, options)
|
81
|
+
else
|
82
|
+
deploy_with_elastic_ip(public_server_name, options)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
desc 'rollback PUBLIC_SERVER_NAME', 'Rollback a deploy'
|
87
|
+
method_options elb_name: :string
|
88
|
+
def rollback(public_server_name)
|
89
|
+
old_servers = spare_servers(public_server_name)
|
90
|
+
raise "no running spare server found for #{public_server_name}" if old_servers.size == 0
|
91
|
+
old_servers.each do |old_server|
|
92
|
+
unless ip(old_server) # the ip may be temporarily unknown if the old elastic ip has been moved to another instance
|
93
|
+
wait_until { old_server.reload; ip(old_server) }
|
94
|
+
end
|
95
|
+
remote('sudo shutdown -c', :host => ip(old_server))
|
96
|
+
end
|
97
|
+
new_servers = active_servers(public_server_name)
|
98
|
+
new_servers.each do |new_server|
|
99
|
+
remote(disable_app_command, :host => ip(new_server))
|
100
|
+
end
|
101
|
+
if options[:elb_name]
|
102
|
+
thor("elb:add_instances #{options[:elb_name]} #{old_servers.map(&:id).join(' ')}")
|
103
|
+
thor("elb:remove_instances #{options[:elb_name]} #{new_servers.map(&:id).join(' ')}")
|
104
|
+
else
|
105
|
+
move_addresses(new_servers.first, old_servers.first)
|
106
|
+
end
|
107
|
+
old_servers.each { |s| s.breeze_state('reactivated') }
|
108
|
+
new_servers.each { |s| s.breeze_state('abandoned_due_to_rollback') }
|
109
|
+
if accept?("Ready to destroy the abandoned #{new_servers.size} server(s) now?")
|
110
|
+
new_servers.each { |s| s.destroy }
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
private
|
115
|
+
|
116
|
+
def deploy_with_elb(public_server_name, options)
|
117
|
+
old_servers = active_servers(public_server_name)
|
118
|
+
create_app_servers_for_elb(public_server_name, options)
|
119
|
+
if accept?("Continue and remove the old servers from the ELB?")
|
120
|
+
thor("elb:remove_instances #{options[:elb_name]} #{old_servers.map(&:id).join(' ')}")
|
121
|
+
old_servers.each do |old_server|
|
122
|
+
remote("nohup sudo shutdown -h +#{CONFIGURATION[:rollback_window]} > /dev/null 2>&1 &", :host => ip(old_server))
|
123
|
+
old_server.spare_for_rollback!
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
def deploy_with_elastic_ip(public_server_name, options)
|
57
129
|
old_server = active_servers(public_server_name).first
|
58
130
|
new_server = create_server
|
59
|
-
new_server.breeze_data(:
|
60
|
-
deploy_command([new_server], public_server_name,
|
131
|
+
new_server.breeze_data(name: public_server_name, db: options[:db_server_name], cache: options[:cache_cluster_name])
|
132
|
+
deploy_command([new_server], public_server_name, options)
|
61
133
|
puts("The new server should soon be available at: #{ip(new_server)}")
|
62
134
|
if ask("Ready to continue and move the elastic_ip for #{public_server_name} to the new server? [YES/rollback] >") =~ /r|n/i
|
63
135
|
new_server.destroy
|
@@ -72,31 +144,48 @@ module Breeze
|
|
72
144
|
end
|
73
145
|
end
|
74
146
|
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
raise "no running spare server found for #{public_server_name}" unless old_server
|
79
|
-
if ip(old_server)
|
80
|
-
temp_ip = nil
|
147
|
+
def create_elb_and_app_servers(public_server_name, options)
|
148
|
+
if options[:elb_cname]
|
149
|
+
thor("elb:create #{options[:elb_name]} #{public_server_name} #{zone_id(public_server_name)}")
|
81
150
|
else
|
82
|
-
|
83
|
-
thor("server:address:create #{old_server.id}")
|
84
|
-
old_server.reload until old_server.addresses.first
|
85
|
-
temp_ip = ip(old_server)
|
86
|
-
end
|
87
|
-
remote('sudo shutdown -c', :host => ip(old_server))
|
88
|
-
new_server = active_servers(public_server_name).first
|
89
|
-
remote(disable_app_command, :host => ip(new_server))
|
90
|
-
thor("server:address:release #{temp_ip} --force") if temp_ip
|
91
|
-
move_addresses(new_server, old_server)
|
92
|
-
old_server.breeze_state('reactivated')
|
93
|
-
new_server.breeze_state('abandoned_due_to_rollback')
|
94
|
-
if accept?('Ready to destroy the abandoned server now?')
|
95
|
-
new_server.destroy
|
151
|
+
thor("elb:create #{options[:elb_name]}")
|
96
152
|
end
|
153
|
+
create_app_servers_for_elb(public_server_name, options.merge(force: true))
|
97
154
|
end
|
98
155
|
|
99
|
-
|
156
|
+
def create_app_servers_for_elb(public_server_name, options)
|
157
|
+
servers = []
|
158
|
+
CONFIGURATION[:elb][:instances].each do |instance_conf|
|
159
|
+
instance_conf = instance_conf.dup
|
160
|
+
instance_conf.delete(:count).times do
|
161
|
+
servers << create_server(CONFIGURATION[:default_server_options].merge(instance_conf))
|
162
|
+
set_server_tags(servers.last, public_server_name, options)
|
163
|
+
end
|
164
|
+
end
|
165
|
+
deploy_command(servers, public_server_name, options)
|
166
|
+
servers.each do |server|
|
167
|
+
if force_or_accept?("Ready to add #{ip(server)} to ELB #{options[:elb_name]}?")
|
168
|
+
thor("elb:add_instances #{options[:elb_name]} #{server.id}")
|
169
|
+
else
|
170
|
+
server.destroy
|
171
|
+
end
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
def create_app_server_with_elastic_ip(public_server_name, options)
|
176
|
+
server = create_server
|
177
|
+
set_server_tags(server, public_server_name, options)
|
178
|
+
if options[:elastic_ip]
|
179
|
+
thor("server:address:create #{server.id}")
|
180
|
+
server.reload until server.addresses.first
|
181
|
+
end
|
182
|
+
deploy_command([server], public_server_name, options)
|
183
|
+
thor("dns:record:create #{zone_id(public_server_name)} #{public_server_name}. A #{ip(server)} #{options[:dns_ttl]}")
|
184
|
+
end
|
185
|
+
|
186
|
+
def set_server_tags(server, public_server_name, options)
|
187
|
+
server.breeze_data(name: public_server_name, db: options[:db_server_name], cache: options[:cache_cluster_name], elb: options[:elb_name])
|
188
|
+
end
|
100
189
|
|
101
190
|
def move_addresses(from_server, to_server)
|
102
191
|
from_server.addresses.each do |address|
|
@@ -170,11 +259,19 @@ module Breeze
|
|
170
259
|
c.class_eval <<-END_TASKS
|
171
260
|
desc 'deploy', 'Deploy a new version by replacing old servers with new ones'
|
172
261
|
def deploy
|
173
|
-
|
262
|
+
if defined?(ELB_NAME)
|
263
|
+
thor("app:deploy \#{PUBLIC_SERVER_NAME} --db-server-name=\#{DB_SERVER_NAME} --cache-cluster-name=\#{CACHE_CLUSTER_NAME} --elb-name=\#{ELB_NAME} --deploy-branch=\#{BRANCH}")
|
264
|
+
else
|
265
|
+
thor("app:deploy \#{PUBLIC_SERVER_NAME} --db-server-name=\#{DB_SERVER_NAME} --cache-cluster-name=\#{CACHE_CLUSTER_NAME} --deploy-branch=\#{BRANCH}")
|
266
|
+
end
|
174
267
|
end
|
175
268
|
desc 'rollback', 'Rollback the previous deploy'
|
176
269
|
def rollback
|
177
|
-
|
270
|
+
if defined?(ELB_NAME)
|
271
|
+
thor("app:rollback \#{PUBLIC_SERVER_NAME} --elb-name=\#{ELB_NAME}")
|
272
|
+
else
|
273
|
+
thor("app:rollback \#{PUBLIC_SERVER_NAME}")
|
274
|
+
end
|
178
275
|
end
|
179
276
|
desc 'disable', 'Copy maintenance.html to public/system/ on active web servers'
|
180
277
|
def disable
|
@@ -184,9 +281,10 @@ module Breeze
|
|
184
281
|
def enable
|
185
282
|
thor("app:enable \#{PUBLIC_SERVER_NAME}")
|
186
283
|
end
|
187
|
-
desc 'ssh', 'Log in with ssh'
|
188
|
-
def ssh
|
189
|
-
|
284
|
+
desc 'ssh [INSTANCE_ID]', 'Log in with ssh'
|
285
|
+
def ssh(instance_id=nil)
|
286
|
+
server = (instance_id ? fog.servers.get(instance_id) : active_servers(PUBLIC_SERVER_NAME)[0])
|
287
|
+
log_in_to(server.public_ip_address)
|
190
288
|
end
|
191
289
|
END_TASKS
|
192
290
|
end
|
@@ -12,6 +12,8 @@ module Breeze
|
|
12
12
|
volumes
|
13
13
|
db_servers
|
14
14
|
dns_zones
|
15
|
+
cache_clusters
|
16
|
+
load_balancers
|
15
17
|
end
|
16
18
|
|
17
19
|
desc :images, 'Describe machine images owned by Breeze::CONFIGURATION[:image_owner]'
|
@@ -72,5 +74,20 @@ module Breeze
|
|
72
74
|
zone.records.map{ |r| [r.name, r.type, r.ttl, r.ip.join(', ')] }
|
73
75
|
end
|
74
76
|
|
77
|
+
desc :cache_clusters, 'Describe ElastiCache clusters'
|
78
|
+
def cache_clusters
|
79
|
+
report 'CACHE CLUSTERS',
|
80
|
+
['Name', 'Type', 'Engine', 'Nodes', 'Status'],
|
81
|
+
elasticache.clusters.map{ |c| [c.id, c.node_type, c.engine, c.num_nodes, c.status] }
|
82
|
+
# c.nodes[0]['Address']
|
83
|
+
end
|
84
|
+
|
85
|
+
desc :load_balancers, 'Describe ELB load balancers'
|
86
|
+
def load_balancers
|
87
|
+
report 'ELASTIC LOAD BALANCERS',
|
88
|
+
['Name', 'DNS name', 'Availability zones', 'Instances'],
|
89
|
+
elb.load_balancers.map{ |lb| [lb.id, lb.dns_name, lb.availability_zones.join(', '), lb.instances.join(', ')] }
|
90
|
+
end
|
91
|
+
|
75
92
|
end
|
76
93
|
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Breeze
|
2
|
+
|
3
|
+
class Elasticache < Veur
|
4
|
+
|
5
|
+
desc 'create CLUSTER_NAME', 'Create a new cache cluster'
|
6
|
+
method_options CONFIGURATION[:default_elasticache_options]
|
7
|
+
def create(name)
|
8
|
+
options.update(:id => name)
|
9
|
+
# puts "elasticache options: #{options}"
|
10
|
+
elasticache.clusters.create(options)
|
11
|
+
end
|
12
|
+
|
13
|
+
desc 'destroy CLUSTER_NAME', 'Destroy a cache cluster'
|
14
|
+
method_options :force => false
|
15
|
+
def destroy(name)
|
16
|
+
cluster = elasticache.clusters.get(name)
|
17
|
+
if force_or_accept?("Destroy cache cluster #{name}?")
|
18
|
+
cluster.destroy
|
19
|
+
cluster.reload
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module Breeze
|
2
|
+
|
3
|
+
class Elb < Veur
|
4
|
+
|
5
|
+
desc 'create LOAD_BALANCER_NAME [CNAME] [DNS_ZONE_ID]', 'Create a new elastic load balancer'
|
6
|
+
method_options :dns_ttl => 60
|
7
|
+
def create(name, cname=nil, dns_zone_id=nil)
|
8
|
+
conf = CONFIGURATION[:elb]
|
9
|
+
response = elb.create_load_balancer(conf[:instances].map{ |i| i[:availability_zone] }.uniq, name, conf[:listeners])
|
10
|
+
if cname
|
11
|
+
thor("dns:record:create #{dns_zone_id} #{cname}. CNAME #{response.body['CreateLoadBalancerResult']['DNSName']} #{options[:dns_ttl]}")
|
12
|
+
end
|
13
|
+
elb.configure_health_check(name, conf[:health_check])
|
14
|
+
end
|
15
|
+
|
16
|
+
desc 'add_instances LOAD_BALANCER_NAME instance_id [instance_id, ...]', 'Add server instances to a load balancer'
|
17
|
+
def add_instances(name, *instance_ids)
|
18
|
+
elb.register_instances(instance_ids, name)
|
19
|
+
end
|
20
|
+
|
21
|
+
desc 'remove_instances LOAD_BALANCER_NAME instance_id [instance_id, ...]', 'Remove server instances from a load balancer'
|
22
|
+
def remove_instances(name, *instance_ids)
|
23
|
+
elb.deregister_instances(instance_ids, name)
|
24
|
+
end
|
25
|
+
|
26
|
+
desc 'destroy LOAD_BALANCER_NAME', 'Destroy an elastic load balancer'
|
27
|
+
method_options :force => false
|
28
|
+
def destroy(name, cname=nil, dns_zone_id=nil)
|
29
|
+
load_balancer = elb.load_balancers.get(name)
|
30
|
+
if force_or_accept?("Destroy load balancer #{name}?")
|
31
|
+
load_balancer.destroy
|
32
|
+
if cname
|
33
|
+
thor("dns:record:destroy #{dns_zone_id} #{cname}. CNAME --force")
|
34
|
+
end
|
35
|
+
load_balancer.reload
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
end
|
data/lib/breeze/veur.rb
CHANGED
data/lib/templates/Thorfile
CHANGED
@@ -54,6 +54,45 @@ Breeze::CONFIGURATION = {
|
|
54
54
|
:password => 'admin'
|
55
55
|
},
|
56
56
|
|
57
|
+
# elasticache configuration is required in order to use Amazon ElastiCache
|
58
|
+
:default_elasticache_options => {
|
59
|
+
:node_type => 'cache.t1.micro',
|
60
|
+
:security_group_names => '',
|
61
|
+
:num_nodes => 1,
|
62
|
+
:auto_minor_version_upgrade => true,
|
63
|
+
:engine => 'memcached',
|
64
|
+
:engine_version => '',
|
65
|
+
:port => '',
|
66
|
+
:preferred_availablility_zone => ''
|
67
|
+
},
|
68
|
+
|
69
|
+
# ELB configuration is required in order to use Amazon Elastic Load Balancing
|
70
|
+
:elb => {
|
71
|
+
:instances => [
|
72
|
+
{availability_zone: 'us-east-1a', flavor_id: 't1.micro', count: 1},
|
73
|
+
{availability_zone: 'us-east-1d', flavor_id: 't1.micro', count: 1}
|
74
|
+
],
|
75
|
+
:listeners => [{
|
76
|
+
'Protocol' => 'HTTP',
|
77
|
+
'LoadBalancerPort' => 80,
|
78
|
+
'InstancePort' => 80,
|
79
|
+
'InstanceProtocol' => 'HTTP'
|
80
|
+
}, {
|
81
|
+
'Protocol' => 'HTTPS',
|
82
|
+
'LoadBalancerPort' => 443,
|
83
|
+
'InstancePort' => 80,
|
84
|
+
'InstanceProtocol' => 'HTTP',
|
85
|
+
'SSLCertificateId' => 'arn:aws:iam::....'
|
86
|
+
}],
|
87
|
+
:health_check => {
|
88
|
+
'Target' => 'HTTP:80/ping',
|
89
|
+
'Interval' => 20,
|
90
|
+
'Timeout' => 4,
|
91
|
+
'HealthyThreshold' => 3,
|
92
|
+
'UnhealthyThreshold' => 2
|
93
|
+
}
|
94
|
+
},
|
95
|
+
|
57
96
|
# you can add your own keys and access this hash as CONFIGURATION in the erb templates
|
58
97
|
:admin_email => 'YOUR-EMAIL',
|
59
98
|
:app_path => '/srv/YOUR-APP'
|
metadata
CHANGED
@@ -1,89 +1,75 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: breeze
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
5
|
-
prerelease:
|
4
|
+
version: 0.2.0
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- Markus Bengts
|
9
8
|
autorequire:
|
10
9
|
bindir: bin
|
11
10
|
cert_chain: []
|
12
|
-
date:
|
11
|
+
date: 2014-03-22 00:00:00.000000000 Z
|
13
12
|
dependencies:
|
14
13
|
- !ruby/object:Gem::Dependency
|
15
14
|
name: thor
|
16
15
|
requirement: !ruby/object:Gem::Requirement
|
17
|
-
none: false
|
18
16
|
requirements:
|
19
|
-
- -
|
17
|
+
- - ">="
|
20
18
|
- !ruby/object:Gem::Version
|
21
19
|
version: '0'
|
22
20
|
type: :runtime
|
23
21
|
prerelease: false
|
24
22
|
version_requirements: !ruby/object:Gem::Requirement
|
25
|
-
none: false
|
26
23
|
requirements:
|
27
|
-
- -
|
24
|
+
- - ">="
|
28
25
|
- !ruby/object:Gem::Version
|
29
26
|
version: '0'
|
30
27
|
- !ruby/object:Gem::Dependency
|
31
28
|
name: fog
|
32
29
|
requirement: !ruby/object:Gem::Requirement
|
33
|
-
none: false
|
34
30
|
requirements:
|
35
|
-
- -
|
31
|
+
- - ">="
|
36
32
|
- !ruby/object:Gem::Version
|
37
33
|
version: '0'
|
38
34
|
type: :runtime
|
39
35
|
prerelease: false
|
40
36
|
version_requirements: !ruby/object:Gem::Requirement
|
41
|
-
none: false
|
42
37
|
requirements:
|
43
|
-
- -
|
38
|
+
- - ">="
|
44
39
|
- !ruby/object:Gem::Version
|
45
40
|
version: '0'
|
46
41
|
- !ruby/object:Gem::Dependency
|
47
42
|
name: cucumber
|
48
43
|
requirement: !ruby/object:Gem::Requirement
|
49
|
-
none: false
|
50
44
|
requirements:
|
51
|
-
- -
|
45
|
+
- - ">="
|
52
46
|
- !ruby/object:Gem::Version
|
53
47
|
version: '0'
|
54
48
|
type: :development
|
55
49
|
prerelease: false
|
56
50
|
version_requirements: !ruby/object:Gem::Requirement
|
57
|
-
none: false
|
58
51
|
requirements:
|
59
|
-
- -
|
52
|
+
- - ">="
|
60
53
|
- !ruby/object:Gem::Version
|
61
54
|
version: '0'
|
62
55
|
- !ruby/object:Gem::Dependency
|
63
56
|
name: aruba
|
64
57
|
requirement: !ruby/object:Gem::Requirement
|
65
|
-
none: false
|
66
58
|
requirements:
|
67
|
-
- -
|
59
|
+
- - ">="
|
68
60
|
- !ruby/object:Gem::Version
|
69
61
|
version: '0'
|
70
62
|
type: :development
|
71
63
|
prerelease: false
|
72
64
|
version_requirements: !ruby/object:Gem::Requirement
|
73
|
-
none: false
|
74
65
|
requirements:
|
75
|
-
- -
|
66
|
+
- - ">="
|
76
67
|
- !ruby/object:Gem::Version
|
77
68
|
version: '0'
|
78
|
-
description:
|
79
|
-
It provides
|
80
|
-
|
69
|
+
description: |
|
70
|
+
Breeze makes it easy to automate server installation and configuration. It provides
|
81
71
|
example scripts and configuration files that you can modify and keep in your revision
|
82
|
-
|
83
|
-
control system. Thor tasks are provided to create server images, launch server instances
|
84
|
-
etc.
|
85
|
-
|
86
|
-
'
|
72
|
+
control system. Thor tasks are provided to create server images, launch server instances etc.
|
87
73
|
email:
|
88
74
|
- markus.bengts@gmail.com
|
89
75
|
executables:
|
@@ -91,8 +77,8 @@ executables:
|
|
91
77
|
extensions: []
|
92
78
|
extra_rdoc_files: []
|
93
79
|
files:
|
94
|
-
- .gitignore
|
95
|
-
- .
|
80
|
+
- ".gitignore"
|
81
|
+
- ".ruby-version"
|
96
82
|
- Gemfile
|
97
83
|
- LICENSE
|
98
84
|
- README.md
|
@@ -117,6 +103,8 @@ files:
|
|
117
103
|
- lib/breeze/tasks/db.rb
|
118
104
|
- lib/breeze/tasks/describe.rb
|
119
105
|
- lib/breeze/tasks/dns.rb
|
106
|
+
- lib/breeze/tasks/elasticache.rb
|
107
|
+
- lib/breeze/tasks/elb.rb
|
120
108
|
- lib/breeze/tasks/server.rb
|
121
109
|
- lib/breeze/tasks/server/address.rb
|
122
110
|
- lib/breeze/tasks/server/image.rb
|
@@ -141,33 +129,26 @@ files:
|
|
141
129
|
- lib/templates/user_data.sh
|
142
130
|
homepage: https://github.com/markus/breeze
|
143
131
|
licenses: []
|
132
|
+
metadata: {}
|
144
133
|
post_install_message:
|
145
134
|
rdoc_options: []
|
146
135
|
require_paths:
|
147
136
|
- lib
|
148
137
|
required_ruby_version: !ruby/object:Gem::Requirement
|
149
|
-
none: false
|
150
138
|
requirements:
|
151
|
-
- -
|
139
|
+
- - ">="
|
152
140
|
- !ruby/object:Gem::Version
|
153
141
|
version: '0'
|
154
|
-
segments:
|
155
|
-
- 0
|
156
|
-
hash: 4461246332485121240
|
157
142
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
158
|
-
none: false
|
159
143
|
requirements:
|
160
|
-
- -
|
144
|
+
- - ">="
|
161
145
|
- !ruby/object:Gem::Version
|
162
146
|
version: '0'
|
163
|
-
segments:
|
164
|
-
- 0
|
165
|
-
hash: 4461246332485121240
|
166
147
|
requirements: []
|
167
148
|
rubyforge_project: breeze
|
168
|
-
rubygems_version:
|
149
|
+
rubygems_version: 2.2.2
|
169
150
|
signing_key:
|
170
|
-
specification_version:
|
151
|
+
specification_version: 4
|
171
152
|
summary: Thor tasks to manage cloud computing resources and deployments
|
172
153
|
test_files:
|
173
154
|
- features/dns.feature
|
data/.rbenv-version
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
1.9.3-p286
|