breeze 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|