breeze 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
@@ -0,0 +1 @@
1
+ 2.1.1
data/Gemfile CHANGED
@@ -1,4 +1,4 @@
1
- source "http://rubygems.org"
1
+ source "https://rubygems.org"
2
2
 
3
3
  # Specify your gem's dependencies in breeze.gemspec
4
4
  gemspec
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. Db migrations have to be
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 DB_SERVER_NAME BRANCH # Deploy a new version by replacing old servers with new ones
54
- thor app:disable PUBLIC_SERVER_NAME # Upload system/maintenance.html to web servers
55
- thor app:enable PUBLIC_SERVER_NAME # Remove system/maintenance.html from web servers
56
- thor app:rollback PUBLIC_SERVER_NAME # Rollback a deploy
57
- thor app:start PUBLIC_SERVER_NAME [DB_SERVER_NAME] [DB_NAME] # Start a new app with web server and db
58
- thor app:stop PUBLIC_SERVER_NAME # Destroy web server and db
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 # Terminate a running (or stopped) server instance
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
@@ -35,4 +35,5 @@ system("echo 'Fog.mock!' >> #{thorfile_path}")
35
35
  Before do
36
36
  system("cp -r #{template_dir} tmp/aruba")
37
37
  @aruba_timeout_seconds = 5
38
+ @dirs = ['tmp/aruba/test_app_template']
38
39
  end
@@ -1,6 +1,6 @@
1
1
  module Breeze
2
2
 
3
- VERSION = "0.1.0"
3
+ VERSION = "0.2.0"
4
4
  autoload :Veur, 'breeze/veur'
5
5
 
6
6
  end
@@ -7,7 +7,7 @@ module Breeze
7
7
  module FogWrapper
8
8
 
9
9
  def self.connection(type)
10
- {:compute => Compute, :dns => DNS, :rds => RDS}[type].get_connection
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
@@ -7,4 +7,6 @@ require 'breeze/tasks/server/image'
7
7
  require 'breeze/tasks/server/tag'
8
8
  require 'breeze/tasks/dns'
9
9
  require 'breeze/tasks/db'
10
+ require 'breeze/tasks/elasticache'
11
+ require 'breeze/tasks/elb'
10
12
  require 'breeze/tasks/app'
@@ -4,42 +4,63 @@ module Breeze
4
4
 
5
5
  class App < Server
6
6
 
7
- desc 'start PUBLIC_SERVER_NAME [DB_SERVER_NAME] [DB_NAME]', 'Start a new app with web server and db'
8
- method_options :db => true, :db_to_clone => :string, :elastic_ip => true, :dns_ttl => 60, :deploy_branch => :string
9
- def start(public_server_name, db_server_name=nil, db_name=nil)
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 'DB_SERVER_NAME is required unless --no-db is given.' if db_server_name.nil?
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
- server = create_server
19
- server.breeze_data(:name => public_server_name, :db => db_server_name)
20
- if options[:elastic_ip]
21
- thor("server:address:create #{server.id}")
22
- server.reload until server.addresses.first
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 DB_SERVER_NAME BRANCH', 'Deploy a new version by replacing old servers with new ones'
56
- def deploy(public_server_name, db_server_name, branch)
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(:name => public_server_name, :db => db_server_name)
60
- deploy_command([new_server], public_server_name, db_server_name, branch)
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
- desc 'rollback PUBLIC_SERVER_NAME', 'Rollback a deploy'
76
- def rollback(public_server_name)
77
- old_server = spare_servers(public_server_name).first
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
- puts("Old server does not have a public ip. Allocating a temporary address:")
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
- private
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
- thor("app:deploy \#{PUBLIC_SERVER_NAME} \#{DB_SERVER_NAME} \#{BRANCH}")
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
- thor("app:rollback \#{PUBLIC_SERVER_NAME}")
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
- log_in_to(PUBLIC_SERVER_NAME)
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
@@ -86,5 +86,13 @@ module Breeze
86
86
  @rds ||= Breeze::FogWrapper.connection(:rds)
87
87
  end
88
88
 
89
+ def elasticache
90
+ @elasticache ||= Breeze::FogWrapper.connection(:elasticache)
91
+ end
92
+
93
+ def elb
94
+ @elb ||= Breeze::FogWrapper.connection(:elb)
95
+ end
96
+
89
97
  end
90
98
  end
@@ -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.1.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: 2012-10-28 00:00:00.000000000 Z
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: ! 'Breeze makes it easy to automate server installation and configuration.
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
- - .rbenv-version
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: 1.8.23
149
+ rubygems_version: 2.2.2
169
150
  signing_key:
170
- specification_version: 3
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
@@ -1 +0,0 @@
1
- 1.9.3-p286