breeze 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -1,4 +1,92 @@
1
1
  # breeze
2
2
 
3
3
  Breeze provides some [Thor](https://github.com/wycats/thor) tasks and example scripts for managing cloud computing resources
4
- on [Amazon's AWS cloud](http://aws.amazon.com/).
4
+ and deployments on [Amazon's AWS cloud](http://aws.amazon.com/). It uses [fog](https://github.com/geemus/fog) for the hard
5
+ work so it should be fairly easy to add support for other cloud computing providers that are supported by fog.
6
+
7
+ Breeze implements zero downtime deployments by moving an elastic ip from one server to another. Db migrations have to be
8
+ compatible with the previous version.
9
+
10
+ ## install
11
+
12
+ gem install breeze
13
+ cd your-project
14
+ breeze init
15
+
16
+ Then edit Thorfile and the stuff that got copied to config/breeze.
17
+
18
+ Management of configuration files is almost compatible with [rubber](https://github.com/wr0ngway/rubber)
19
+ but breeze does not support roles and additives. See [the rubber wiki](https://github.com/wr0ngway/rubber/wiki/Configuration)
20
+ for more information.
21
+
22
+ ## create a server image
23
+
24
+ thor server:image:create
25
+
26
+ The default install.sh compiles ruby, passenger, nginx and image magick. It takes a long time
27
+ (maybe half an hour on a small instance). It will prompt for the image name when completed.
28
+
29
+ ## use it
30
+
31
+ thor describe # List all cloud resources that the current account can control with breeze
32
+
33
+ thor staging:deploy # Deploy a new version by replacing old servers with new ones
34
+ thor staging:disable # Copy maintenance.html to public/system/ on active web servers
35
+ thor staging:enable # Remove system/maintenance.html from active web servers
36
+ thor staging:rollback # Rollback the previous deploy
37
+ thor staging:start # Start web server and db for staging
38
+ thor staging:stop # Stop staging and destroy server and db
39
+
40
+ Define your staging and production in the Thorfile and the same tasks become available for both name spaces.
41
+ These tasks call app tasks with fixed parameters.
42
+
43
+ ## plumbing commands
44
+
45
+ app
46
+ ---
47
+ thor app:deploy PUBLIC_SERVER_NAME DB_SERVER_NAME BRANCH # Deploy a new version by replacing old servers with new ones
48
+ thor app:disable PUBLIC_SERVER_NAME # Upload system/maintenance.html to web servers
49
+ thor app:enable PUBLIC_SERVER_NAME # Remove system/maintenance.html from web servers
50
+ thor app:rollback PUBLIC_SERVER_NAME # Rollback a deploy
51
+ thor app:start PUBLIC_SERVER_NAME [DB_SERVER_NAME] [DB_NAME] # Start a new app with web server and db
52
+ thor app:stop PUBLIC_SERVER_NAME # Destroy web server and db
53
+
54
+ configuration
55
+ -------------
56
+ thor configuration:deploy_to_localhost # Transform and deploy server configuration files to the local file system based on...
57
+
58
+ db
59
+ --
60
+ thor db:clone OLD_DB NEW_DB # Create a new db server using the latest backup of OLD_DB.
61
+ thor db:create SERVER_NAME [DB_NAME] # Create a new database server
62
+ thor db:destroy NAME # Destroy a database server
63
+
64
+ dns
65
+ ---
66
+ thor dns:record:create ZONE_ID NAME TYPE IP [TTL] # Create a new DNS record
67
+ thor dns:record:destroy ZONE_ID NAME [TYPE] # Destroy a DNS record
68
+ thor dns:zone:create DOMAIN # Create a new DNS zone
69
+ thor dns:zone:destroy ZONE_ID # Destroy a DNS zone
70
+ thor dns:zone:import ZONE_ID FILE # Creates dns records specified in FILE
71
+
72
+ describe
73
+ --------
74
+ thor describe:addresses # List allocated ip addresses
75
+ thor describe:cloud_resources # List all cloud resources that the current account can control with breeze
76
+ thor describe:db_servers # List database servers
77
+ thor describe:dns_records ZONE_ID # List all DNS records for the given zone
78
+ thor describe:dns_zones # Describe DNS zones
79
+ thor describe:images # Describe machine images owned by Breeze::CONFIGURATION[:image_owner]
80
+ thor describe:servers # Describe server instances
81
+ thor describe:volumes # Describe block store volumes (EBS)
82
+
83
+ server
84
+ ------
85
+ thor server:address:associate IP NEW_SERVER_ID # Associate an existing IP with a new server
86
+ thor server:address:create SERVER_ID # Create and associate a new elastic ip
87
+ thor server:address:release IP # Release the ip address
88
+ thor server:create # Launch a new server instance
89
+ thor server:destroy INSTANCE_ID # Terminate a running (or stopped) server instance
90
+ thor server:image:create # Launch a server with the base image, wait for it to boot, invoke...
91
+ thor server:tag:create SERVER_ID KEY VALUE # Create or update a tag
92
+ thor server:tag:destroy SERVER_ID KEY # Delete a tag
@@ -1,6 +1,6 @@
1
1
  module Breeze
2
2
 
3
- VERSION = "0.0.1"
3
+ VERSION = "0.0.2"
4
4
  autoload :Veur, 'breeze/veur'
5
5
 
6
6
  end
@@ -1,6 +1,6 @@
1
1
  require 'breeze'
2
2
  require 'breeze/tasks/configuration'
3
- require 'breeze/tasks/list'
3
+ require 'breeze/tasks/describe'
4
4
  require 'breeze/tasks/server'
5
5
  require 'breeze/tasks/server/address'
6
6
  require 'breeze/tasks/server/image'
@@ -57,24 +57,34 @@ module Breeze
57
57
  deploy_command([new_server], public_server_name, db_server_name, branch)
58
58
  puts("The new server should soon be available at #{ip(new_server)}.")
59
59
  if ask("Ready to continue and move the elastic_ip for #{public_server_name} to the new server? [YES/rollback] >") =~ /r|n/i
60
- remote("sudo shutdown -h +#{CONFIGURATION[:rollback_window]}", :host => ip(old_server))
60
+ new_server.destroy
61
+ else
62
+ remote("sudo shutdown -h +#{CONFIGURATION[:rollback_window]} &", :host => ip(old_server))
61
63
  old_server.spare_for_rollback!
62
64
  move_addresses(old_server, new_server)
63
- else
64
- new_server.destroy
65
65
  end
66
66
  end
67
67
 
68
68
  desc 'rollback PUBLIC_SERVER_NAME', 'Rollback a deploy'
69
69
  def rollback(public_server_name)
70
70
  old_server = spare_servers(public_server_name).first
71
+ raise "no running spare server found for #{public_server_name}" unless old_server
72
+ if ip(old_server)
73
+ temp_ip = nil
74
+ else
75
+ puts("Old server does not have a public ip. Allocating a temporary address:")
76
+ thor("server:address:create #{old_server.id}")
77
+ old_server.reload until old_server.addresses.first
78
+ temp_ip = ip(old_server)
79
+ end
71
80
  remote('sudo shutdown -c', :host => ip(old_server))
72
81
  new_server = active_servers(public_server_name).first
73
82
  remote(disable_app_command, :host => ip(new_server))
83
+ thor("server:address:release #{temp_ip}") if temp_ip
74
84
  move_addresses(new_server, old_server)
75
85
  old_server.breeze_state('reactivated')
76
86
  new_server.breeze_state('abandoned_due_to_rollback')
77
- if accept?('Destroy the abandoned server NOW?')
87
+ if accept?('Ready to destroy the abandoned server now?')
78
88
  new_server.destroy
79
89
  end
80
90
  end
@@ -87,16 +97,16 @@ module Breeze
87
97
  end
88
98
  end
89
99
 
90
- def servers(public_server_name)
91
- fog.servers.select{ |s| s.name == public_server_name }
100
+ def running_servers(public_server_name)
101
+ fog.servers.select{ |s| s.ready? and s.name == public_server_name }
92
102
  end
93
103
 
94
104
  def spare_servers(public_server_name)
95
- servers(public_server_name).select{ |s| s.spare_for_rollback? }
105
+ running_servers(public_server_name).select{ |s| s.spare_for_rollback? }
96
106
  end
97
107
 
98
108
  def active_servers(public_server_name)
99
- servers(public_server_name).select{ |s| ! s.spare_for_rollback? }
109
+ running_servers(public_server_name).select{ |s| not s.spare_for_rollback? }
100
110
  end
101
111
 
102
112
  def on_each_server(command, public_server_name)
@@ -106,7 +116,7 @@ module Breeze
106
116
  end
107
117
 
108
118
  def disable_app_command
109
- "cd #{CONFIGURATION[:app_path]} && cp config/breeze/maintenance.html public/system/"
119
+ "cd #{CONFIGURATION[:app_path]} && mkdir -p public/system && cp config/breeze/maintenance.html public/system/"
110
120
  end
111
121
 
112
122
  def enable_app_command
@@ -141,5 +151,28 @@ module Breeze
141
151
  super(task + (options[:force] ? ' --force' : ''))
142
152
  end
143
153
 
154
+ # Don't know how to include or inherit thor tasks and descriptions.
155
+ # These may be included in Staging and Production.
156
+ def self.inherited(c)
157
+ c.class_eval <<-END_TASKS
158
+ desc 'deploy', 'Deploy a new version by replacing old servers with new ones'
159
+ def deploy
160
+ thor("app:deploy \#{PUBLIC_SERVER_NAME} \#{DB_SERVER_NAME} \#{BRANCH}")
161
+ end
162
+ desc 'rollback', 'Rollback the previous deploy'
163
+ def rollback
164
+ thor("app:rollback \#{PUBLIC_SERVER_NAME}")
165
+ end
166
+ desc 'disable', 'Copy maintenance.html to public/system/ on active web servers'
167
+ def disable
168
+ thor("app:disable \#{PUBLIC_SERVER_NAME}")
169
+ end
170
+ desc 'enable', 'Remove system/maintenance.html from active web servers'
171
+ def enable
172
+ thor("app:enable \#{PUBLIC_SERVER_NAME}")
173
+ end
174
+ END_TASKS
175
+ end
176
+
144
177
  end
145
178
  end
@@ -1,6 +1,8 @@
1
1
  module Breeze
2
2
 
3
- class List < Veur
3
+ class Describe < Veur
4
+
5
+ default_task :cloud_resources
4
6
 
5
7
  desc :cloud_resources, 'List all cloud resources that the current account can control with breeze'
6
8
  def cloud_resources
@@ -24,9 +26,9 @@ module Breeze
24
26
  desc :servers, 'Describe server instances'
25
27
  def servers
26
28
  report "SERVER INSTANCES",
27
- ['Name', 'Instance ID', 'IP Address', 'Image ID', 'Instance Type', 'Availability Zone', 'State'],
29
+ ['Name', 'Instance ID', 'IP Address', 'Image ID', 'Type', 'Zone', 'State', 'Info'],
28
30
  fog.servers.map { |i|
29
- [i.name, i.id, i.public_ip_address, i.image_id, i.flavor_id, i.availability_zone, i.state]
31
+ [i.name, i.id, i.public_ip_address, i.image_id, i.flavor_id, i.availability_zone, i.state, i.breeze_state]
30
32
  }
31
33
  end
32
34
 
@@ -45,7 +45,7 @@ module Breeze
45
45
  end
46
46
 
47
47
  def remote_is_available?(host)
48
- execute(:remote_command, :command => 'exit', :host => host)
48
+ execute(:remote_available?, :host => host)
49
49
  end
50
50
 
51
51
  def remote(command, args)
@@ -8,19 +8,24 @@ module Breeze
8
8
  'stop the server, create a new machine image as a snapshot of the root device, and destroy the server.'
9
9
  method_options CONFIGURATION[:default_server_options].merge(CONFIGURATION[:create_image_options])
10
10
  def create
11
- options[:block_device_mapping] = [{:device_name => '/dev/sda1', :ebs_volume_size => options.delete(:root_device_size)}]
11
+ # The commented lines used to work before fog 0.7.0.
12
+ # options[:block_device_mapping] = [{:device_name => '/dev/sda1', :ebs_volume_size => options.delete(:root_device_size)}]
13
+ options[:block_device_mapping] = [{'DeviceName' => '/dev/sda1', 'Ebs.VolumeSize' => options.delete(:root_device_size)}]
12
14
  server = create_server(options)
13
15
  prepare_private_image(server.public_ip_address)
14
16
  print('Stopping the server before saving a snapshot')
15
17
  server.stop
16
18
  wait_until('stopped!') { server.stopped? }
17
- thor('list:images')
18
- image = fog.images.create(:name => ask('Image name >'), :instance_id => server.id)
19
+ thor('describe:images')
20
+ puts('===== Old server images are listed above. Give a name to the new image. =====')
21
+ # image = fog.images.create(:name => ask('Image name >'), :instance_id => server.id)
22
+ fog.create_image(server.id, ask('Image name >'), '')
19
23
  server.destroy
20
24
  puts
21
- puts("===> Created image #{image.id} and terminated temporary server #{server.id}.")
25
+ # puts("===> Created image #{image.id} and terminated temporary server #{server.id}.")
26
+ puts("===> Created a new server image and terminated temporary server #{server.id}.")
22
27
  puts
23
- puts("NOTICE: it may take a while before the new image shows up in list:images")
28
+ puts("NOTICE: it may take a while before the new image shows up in describe:images")
24
29
  end
25
30
 
26
31
  end
@@ -16,6 +16,7 @@ Breeze::CONFIGURATION = {
16
16
  # Remote and upload commands are required in order to create a server image or deploy
17
17
  # an application. Arguments marked with %{} are automatically replaced when the
18
18
  # commands are used. Use "ssh -i /path/to/key" if not using your default ssh key.
19
+ :remote_available? => 'ssh -q ubuntu@%{host} exit',
19
20
  :remote_command => "ssh ubuntu@%{host} '%{command}'",
20
21
  :upload_command => 'rsync -v %{file_pattern} ubuntu@%{host}:%{remote_path}',
21
22
 
@@ -38,7 +39,7 @@ Breeze::CONFIGURATION = {
38
39
  :root_device_size => 15 # in GB
39
40
  },
40
41
 
41
- # machine images owned by this account are included in list:images (provided that you have access to them)
42
+ # machine images owned by this account are included in describe:images (provided that you have access to them)
42
43
  :image_owner => 'YOUR-ACCOUNT-ID-WITHOUT-DASHES', # canonical: '099720109477'
43
44
 
44
45
  # db configuration is required in order to use Amazon RDS
@@ -66,10 +67,10 @@ Breeze::CONFIGURATION = {
66
67
  # with the "thor help" command.
67
68
  require 'breeze/tasks'
68
69
 
70
+ # prepare_private_image is called from server:image:create. Modify this and/or the scripts
71
+ # that are uploaded in order to create your own private machine image.
69
72
  class Breeze::Server::Image
70
73
  private
71
- # This method is called from server:image:create. Modify this and/or the scripts that
72
- # are uploaded in order to create your own private machine image.
73
74
  def prepare_private_image(ip_address)
74
75
  wait_until_host_is_available(ip_address)
75
76
  puts("Uploading scripts...")
@@ -78,8 +79,7 @@ class Breeze::Server::Image
78
79
  end
79
80
  end
80
81
 
81
- # You can define staging:start etc. with fixed parameters below.
82
-
82
+ # deploy_command is called from app:start and app:deploy.
83
83
  class Breeze::App
84
84
  private
85
85
  def deploy_command(servers, public_server_name, db_server_name, branch)
@@ -90,15 +90,18 @@ class Breeze::App
90
90
  end
91
91
  end
92
92
 
93
- # thor staging:start and staging:stop
93
+ # Define staging:start etc. below. The constants are also needed by
94
+ # inherited tasks: deploy, rollback, enable and disable.
95
+
94
96
  class Staging < Breeze::App
95
97
 
96
98
  PUBLIC_SERVER_NAME = 'staging.example.com'
97
99
  DB_SERVER_NAME = 'staging-db'
100
+ BRANCH = 'master'
98
101
 
99
102
  desc 'start', 'Start web server and db for staging'
100
103
  def start
101
- thor("app:start #{PUBLIC_SERVER_NAME} #{DB_SERVER_NAME} --db-to-clone=#{Production::DB_SERVER_NAME} --deploy-branch=master")
104
+ thor("app:start #{PUBLIC_SERVER_NAME} #{DB_SERVER_NAME} --db-to-clone=#{Production::DB_SERVER_NAME} --deploy-branch=#{BRANCH}")
102
105
  end
103
106
 
104
107
  desc 'stop', 'Stop staging and destroy server and db'
@@ -108,15 +111,15 @@ class Staging < Breeze::App
108
111
 
109
112
  end
110
113
 
111
- # thor production:start
112
114
  class Production < Breeze::App
113
115
 
114
- PUBLIC_SERVER_NAME = 'production.example.com'
116
+ PUBLIC_SERVER_NAME = 'www.example.com'
115
117
  DB_SERVER_NAME = 'production-db'
118
+ BRANCH = 'stable'
116
119
 
117
120
  desc 'start', 'Start web server and db for production'
118
121
  def start
119
- thor("app:start #{PUBLIC_SERVER_NAME} #{DB_SERVER_NAME} crags --dns-ttl=300 --deploy-branch=stable")
122
+ thor("app:start #{PUBLIC_SERVER_NAME} #{DB_SERVER_NAME} db_name --dns-ttl=300 --deploy-branch=#{BRANCH}")
120
123
  end
121
124
 
122
125
  end
@@ -3,7 +3,7 @@
3
3
  @owner = 'rails'
4
4
  @group = 'rails'
5
5
  @perms = 0640
6
- @post = 'rake db:migrate'
6
+ @post = 'rake db:migrate RAILS_ENV=production'
7
7
 
8
8
  conf = CONFIGURATION[:default_db_options]
9
9
  %>
@@ -5,9 +5,9 @@
5
5
  system("mkdir -p #{dir} && chown www-data #{dir}") unless File.directory?(dir)
6
6
  end
7
7
 
8
- passenger_version = "3.0.2"
8
+ passenger_version = "3.0.5"
9
9
  server_name = ENV['PUBLIC_SERVER_NAME']
10
- server_root = "/srv/your-app/public"
10
+ server_root = "#{CONFIGURATION[:app_path]}/public"
11
11
 
12
12
  shared_server_conf = <<-END_SHARED_SERVER_CONF
13
13
 
@@ -22,14 +22,10 @@
22
22
  # let browsers cache static assets
23
23
  location ~ ^/(images|javascripts|stylesheets)/ { expires 1y; }
24
24
 
25
- # always display system/maintenance.html if it exists
26
- if ($request_filename ~* \.(js|css|gif|png|jpg)$) { break; }
27
- if (-f $document_root/system/maintenance.html) {
28
- rewrite ^(.*)$ /system/maintenance.html last;
29
- break;
30
- }
25
+ # static files, page caching and maintenance.html
26
+ try_files $uri $uri/index.html $uri.html /system/maintenance.html @passenger;
31
27
 
32
- location / {
28
+ location @passenger {
33
29
  passenger_enabled on;
34
30
  }
35
31
 
@@ -17,7 +17,7 @@ PACKAGES="$SYSTEM_PACKAGES $DB_CLIENT_PACKAGES $RUBY_BUILD_DEPENDENCIES $NGINX_A
17
17
 
18
18
  # the rest is used by install_cust.sh
19
19
  RUBY_PACKAGE=ruby-1.9.2-p180
20
- IMAGE_MAGICK_PACKAGE=ImageMagick-6.6.7-8
20
+ IMAGE_MAGICK_PACKAGE=ImageMagick-6.6.8-6
21
21
  IMAGE_MAGICK_OPTIONS='--disable-static --with-modules --without-perl --without-magick-plus-plus --with-quantum-depth=8'
22
22
  NGINX_OPTIONS="\
23
23
  --conf-path=/etc/nginx/nginx.conf \
@@ -5,7 +5,7 @@
5
5
  download ftp://ftp.ruby-lang.org//pub/ruby/1.9/$RUBY_PACKAGE.tar.gz
6
6
  extract_and_install $RUBY_PACKAGE
7
7
  sudo gem update --system
8
- sudo gem install --no-ri --no-rdoc bundler passenger
8
+ sudo gem install --no-ri --no-rdoc bundler passenger breeze
9
9
 
10
10
  # install nginx and passenger
11
11
  sudo passenger-install-nginx-module --auto --auto-download --prefix=/usr --extra-configure-flags="$NGINX_OPTIONS"
@@ -34,10 +34,10 @@ sudo usermod --groups rails ubuntu
34
34
 
35
35
  wget -q --no-check-certificate --directory-prefix=$HOME --output-document=tarball.tar.gz $DOWNLOAD_URL
36
36
  tar --directory $HOME -xzf tarball.tar.gz
37
-
38
37
  sudo mv $HOME/*$APP_NAME* $DEPLOY_PATH
39
- sudo chown -R rails $DEPLOY_PATH
38
+
40
39
  cd $DEPLOY_PATH
41
- sudo bundle install --without=test development
40
+ bundle install --deployment --without=test development
41
+ sudo chown -R rails:rails $DEPLOY_PATH
42
42
  sudo PUBLIC_SERVER_NAME=$PUBLIC_SERVER_NAME DB_SERVER=$DB_SERVER thor configuration:deploy_to_localhost
43
43
  sudo /etc/init.d/monit start
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 0
7
7
  - 0
8
- - 1
9
- version: 0.0.1
8
+ - 2
9
+ version: 0.0.2
10
10
  platform: ruby
11
11
  authors:
12
12
  - Markus Bengts
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2011-03-20 00:00:00 +01:00
17
+ date: 2011-03-22 00:00:00 +01:00
18
18
  default_executable:
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
@@ -73,8 +73,8 @@ files:
73
73
  - lib/breeze/tasks/app.rb
74
74
  - lib/breeze/tasks/configuration.rb
75
75
  - lib/breeze/tasks/db.rb
76
+ - lib/breeze/tasks/describe.rb
76
77
  - lib/breeze/tasks/dns.rb
77
- - lib/breeze/tasks/list.rb
78
78
  - lib/breeze/tasks/server.rb
79
79
  - lib/breeze/tasks/server/address.rb
80
80
  - lib/breeze/tasks/server/image.rb