breeze 0.0.1
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.
- data/.gitignore +6 -0
- data/Gemfile +4 -0
- data/LICENSE +22 -0
- data/README.md +4 -0
- data/Rakefile +2 -0
- data/bin/breeze +17 -0
- data/breeze.gemspec +28 -0
- data/lib/breeze.rb +6 -0
- data/lib/breeze/fog_extensions.rb +2 -0
- data/lib/breeze/fog_extensions/aws.rb +65 -0
- data/lib/breeze/initializer.rb +40 -0
- data/lib/breeze/tasks.rb +10 -0
- data/lib/breeze/tasks/app.rb +145 -0
- data/lib/breeze/tasks/configuration.rb +63 -0
- data/lib/breeze/tasks/db.rb +31 -0
- data/lib/breeze/tasks/dns.rb +67 -0
- data/lib/breeze/tasks/list.rb +74 -0
- data/lib/breeze/tasks/server.rb +72 -0
- data/lib/breeze/tasks/server/address.rb +27 -0
- data/lib/breeze/tasks/server/image.rb +27 -0
- data/lib/breeze/tasks/server/tag.rb +16 -0
- data/lib/breeze/veur.rb +86 -0
- data/lib/templates/Thorfile +122 -0
- data/lib/templates/maintenance.html +23 -0
- data/lib/templates/profiles/minimal/scripts/install_conf.sh +4 -0
- data/lib/templates/profiles/minimal/scripts/install_cust.sh +7 -0
- data/lib/templates/profiles/rails_and_image_magick/configs/database.yml +18 -0
- data/lib/templates/profiles/rails_and_image_magick/configs/memcached.conf +51 -0
- data/lib/templates/profiles/rails_and_image_magick/configs/nginx/logrotate +26 -0
- data/lib/templates/profiles/rails_and_image_magick/configs/nginx/monit +9 -0
- data/lib/templates/profiles/rails_and_image_magick/configs/nginx/nginx.conf +99 -0
- data/lib/templates/profiles/rails_and_image_magick/scripts/install_conf.sh +33 -0
- data/lib/templates/profiles/rails_and_image_magick/scripts/install_cust.sh +24 -0
- data/lib/templates/shared/configs/crontab +10 -0
- data/lib/templates/shared/configs/monitrc +248 -0
- data/lib/templates/shared/scripts/credentials.sh +5 -0
- data/lib/templates/shared/scripts/deploy.sh +43 -0
- data/lib/templates/shared/scripts/install.sh +38 -0
- data/lib/templates/user_data.sh +4 -0
- metadata +133 -0
@@ -0,0 +1,67 @@
|
|
1
|
+
module Breeze
|
2
|
+
module Dns
|
3
|
+
|
4
|
+
class Zone < Veur
|
5
|
+
|
6
|
+
desc 'create DOMAIN', 'Create a new DNS zone'
|
7
|
+
def create(domain)
|
8
|
+
zone = dns.zones.create(:domain => domain)
|
9
|
+
puts "Zone ID: #{zone.id}"
|
10
|
+
puts "Change info: #{zone.change_info}"
|
11
|
+
puts "Name servers: #{zone.nameservers}"
|
12
|
+
end
|
13
|
+
|
14
|
+
desc 'destroy ZONE_ID', 'Destroy a DNS zone'
|
15
|
+
def destroy(zone_id)
|
16
|
+
zone = dns.zones.get(zone_id)
|
17
|
+
if accept?("Destroy DNS zone and records for #{zone.domain}?")
|
18
|
+
zone.records.each(&:destroy)
|
19
|
+
zone.destroy
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
desc 'import ZONE_ID FILE', 'Creates dns records specified in FILE'
|
24
|
+
long_desc <<-END_DESC
|
25
|
+
FILE should be the path to a ruby file that defines DNS_RECORDS like this:
|
26
|
+
DNS_RECORDS = [
|
27
|
+
{:name => 'example.com', :type => 'A', :ip => '1.2.3.4'},
|
28
|
+
{:name => 'www.example.com', :type => 'CNAME', :ip => 'example.com'}
|
29
|
+
]
|
30
|
+
You can also specify :ttl for each record. The default ttl is 3600 (1 hour).
|
31
|
+
END_DESC
|
32
|
+
def import(zone_id, file)
|
33
|
+
load file
|
34
|
+
zone = get_zone(zone_id)
|
35
|
+
DNS_RECORDS.each do |record_hash|
|
36
|
+
zone.records.create(record_hash)
|
37
|
+
puts record_hash.inspect
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
def get_zone(id)
|
44
|
+
dns.zones.get(id)
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
|
49
|
+
class Record < Zone
|
50
|
+
|
51
|
+
desc 'create ZONE_ID NAME TYPE IP [TTL]', 'Create a new DNS record'
|
52
|
+
def create(zone_id, name, type, ip, ttl=3600)
|
53
|
+
get_zone(zone_id).records.create(:name => name, :type => type, :ip => ip, :ttl => ttl)
|
54
|
+
end
|
55
|
+
|
56
|
+
desc 'destroy ZONE_ID NAME [TYPE]', 'Destroy a DNS record'
|
57
|
+
method_options :force => false
|
58
|
+
def destroy(zone_id, name, type=nil)
|
59
|
+
records = get_zone(zone_id).records.select{ |r| r.name == name && (type.nil? || r.type == type) }
|
60
|
+
if force_or_accept?("Destroy #{records.size} record#{records.size == 1 ? '' : 's'}?")
|
61
|
+
records.each(&:destroy)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
module Breeze
|
2
|
+
|
3
|
+
class List < Veur
|
4
|
+
|
5
|
+
desc :cloud_resources, 'List all cloud resources that the current account can control with breeze'
|
6
|
+
def cloud_resources
|
7
|
+
images
|
8
|
+
servers
|
9
|
+
addresses
|
10
|
+
volumes
|
11
|
+
db_servers
|
12
|
+
dns_zones
|
13
|
+
end
|
14
|
+
|
15
|
+
desc :images, 'Describe machine images owned by Breeze::CONFIGURATION[:image_owner]'
|
16
|
+
def images
|
17
|
+
report 'MACHINE IMAGES',
|
18
|
+
['Name or Location', 'Image ID', 'Owner', 'Image Type', 'Public'],
|
19
|
+
fog.images.all('Owner' => Breeze::CONFIGURATION[:image_owner]).map{ |i|
|
20
|
+
[i.name||i.location, i.id, i.owner_id, i.full_type, i.is_public]
|
21
|
+
}
|
22
|
+
end
|
23
|
+
|
24
|
+
desc :servers, 'Describe server instances'
|
25
|
+
def servers
|
26
|
+
report "SERVER INSTANCES",
|
27
|
+
['Name', 'Instance ID', 'IP Address', 'Image ID', 'Instance Type', 'Availability Zone', 'State'],
|
28
|
+
fog.servers.map { |i|
|
29
|
+
[i.name, i.id, i.public_ip_address, i.image_id, i.flavor_id, i.availability_zone, i.state]
|
30
|
+
}
|
31
|
+
end
|
32
|
+
|
33
|
+
desc :addresses, 'List allocated ip addresses'
|
34
|
+
def addresses
|
35
|
+
report "ALLOCATED IP ADDRESSES",
|
36
|
+
['Address', 'Server'],
|
37
|
+
fog.addresses.map{ |a| [a.public_ip, a.server_id] }
|
38
|
+
end
|
39
|
+
|
40
|
+
desc :volumes, 'Describe block store volumes (EBS)'
|
41
|
+
def volumes
|
42
|
+
report "VOLUMES",
|
43
|
+
['Volume ID', 'Size', 'Status', 'Zone', 'Snapshot ID', 'Used by'],
|
44
|
+
fog.volumes.map { |v|
|
45
|
+
[v.id, v.size, v.state, v.availability_zone, v.snapshot_id, v.server_id]
|
46
|
+
}
|
47
|
+
end
|
48
|
+
|
49
|
+
desc :db_servers, 'List database servers'
|
50
|
+
def db_servers
|
51
|
+
report "DATABASE SERVERS",
|
52
|
+
['Name', 'Type', 'Storage', 'State', 'Endpoint'],
|
53
|
+
rds.servers.map{ |s| [s.id, s.flavor_id, s.allocated_storage, s.state, s.endpoint] }
|
54
|
+
end
|
55
|
+
|
56
|
+
desc :dns_zones, 'Describe DNS zones'
|
57
|
+
def dns_zones
|
58
|
+
zones = dns.zones
|
59
|
+
zones.each(&:reload) # necessary in order to get nameservers
|
60
|
+
report "DNS ZONES",
|
61
|
+
['Domain', 'Zone ID', 'Name servers'],
|
62
|
+
zones.map{ |z| [z.domain, z.id, z.nameservers.join(', ')] }
|
63
|
+
end
|
64
|
+
|
65
|
+
desc 'dns_records ZONE_ID', 'List all DNS records for the given zone'
|
66
|
+
def dns_records(zone_id)
|
67
|
+
zone = dns.zones.get(zone_id)
|
68
|
+
report "DNS RECORDS FOR #{zone.domain}",
|
69
|
+
['Name', 'Type', 'TTL', 'Value'],
|
70
|
+
zone.records.map{ |r| [r.name, r.type, r.ttl, r.ip.join(', ')] }
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
74
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
require 'resolv'
|
2
|
+
|
3
|
+
module Breeze
|
4
|
+
|
5
|
+
# Dealing with server instances.
|
6
|
+
class Server < Veur
|
7
|
+
|
8
|
+
desc 'create', 'Launch a new server instance'
|
9
|
+
method_options CONFIGURATION[:default_server_options]
|
10
|
+
def create
|
11
|
+
if options[:user_data_file]
|
12
|
+
options[:user_data] = Base64.encode64(File.read(options[:user_data_file])).strip
|
13
|
+
end
|
14
|
+
create_server(options)
|
15
|
+
end
|
16
|
+
|
17
|
+
desc 'destroy INSTANCE_ID', 'Terminate a running (or stopped) server instance'
|
18
|
+
method_options :force => false
|
19
|
+
def destroy(instance_id)
|
20
|
+
server = fog.servers.get(instance_id)
|
21
|
+
if force_or_accept?("Terminate server #{server.display_name}?")
|
22
|
+
server.destroy
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def create_server(options=nil)
|
29
|
+
options ||= CONFIGURATION[:default_server_options]
|
30
|
+
# puts("Server options: #{options.inspect}")
|
31
|
+
server = fog.servers.create(options)
|
32
|
+
print "Launching server #{server.id}"
|
33
|
+
wait_until('running!') { server.running? }
|
34
|
+
return server
|
35
|
+
end
|
36
|
+
|
37
|
+
def wait_until_host_is_available(host)
|
38
|
+
if Resolv.getaddresses(host).empty?
|
39
|
+
print("Waiting for #{host} to resolve")
|
40
|
+
wait_until('ready!') { Resolv.getaddresses(host).any? }
|
41
|
+
end
|
42
|
+
return true if remote_is_available?(host)
|
43
|
+
print("Waiting for #{host} to accept connections")
|
44
|
+
wait_until('ready!') { remote_is_available?(host) }
|
45
|
+
end
|
46
|
+
|
47
|
+
def remote_is_available?(host)
|
48
|
+
execute(:remote_command, :command => 'exit', :host => host)
|
49
|
+
end
|
50
|
+
|
51
|
+
def remote(command, args)
|
52
|
+
args[:command] = command
|
53
|
+
execute(:remote_command, args)
|
54
|
+
end
|
55
|
+
|
56
|
+
def upload(file_pattern, args)
|
57
|
+
args[:file_pattern] = file_pattern
|
58
|
+
execute(:upload_command, args)
|
59
|
+
end
|
60
|
+
|
61
|
+
def execute(command, args)
|
62
|
+
command = CONFIGURATION[command] if command.is_a?(Symbol)
|
63
|
+
# system(command % args)
|
64
|
+
# rescue ArgumentError # for ruby 1.8 compatibility
|
65
|
+
args.each do |key, value|
|
66
|
+
command = command.gsub("%{#{key}}", value)
|
67
|
+
end
|
68
|
+
system(command)
|
69
|
+
end
|
70
|
+
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Breeze
|
2
|
+
|
3
|
+
# Aka Amazon Elastic IP
|
4
|
+
class Server::Address < Veur
|
5
|
+
|
6
|
+
desc 'create SERVER_ID', 'Create and associate a new elastic ip'
|
7
|
+
def create(server_id)
|
8
|
+
# TODO: fog should take server_id directly when creating an address
|
9
|
+
server = fog.servers.get(server_id)
|
10
|
+
fog.addresses.create(:server => server)
|
11
|
+
end
|
12
|
+
|
13
|
+
desc 'release IP', 'Release the ip address'
|
14
|
+
method_options :force => false
|
15
|
+
def release(ip)
|
16
|
+
if force_or_accept?("Release IP #{ip}?")
|
17
|
+
fog.addresses.get(ip).destroy
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
desc 'associate IP NEW_SERVER_ID', 'Associate an existing IP with a new server'
|
22
|
+
def associate(ip, server_id)
|
23
|
+
fog.associate_address(server_id, ip)
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'breeze/tasks/server'
|
2
|
+
|
3
|
+
module Breeze
|
4
|
+
|
5
|
+
# Dealing with machine images.
|
6
|
+
class Server::Image < Server
|
7
|
+
desc 'create', 'Launch a server with the base image, wait for it to boot, invoke prepare_private_image(ip_address), ' +
|
8
|
+
'stop the server, create a new machine image as a snapshot of the root device, and destroy the server.'
|
9
|
+
method_options CONFIGURATION[:default_server_options].merge(CONFIGURATION[:create_image_options])
|
10
|
+
def create
|
11
|
+
options[:block_device_mapping] = [{:device_name => '/dev/sda1', :ebs_volume_size => options.delete(:root_device_size)}]
|
12
|
+
server = create_server(options)
|
13
|
+
prepare_private_image(server.public_ip_address)
|
14
|
+
print('Stopping the server before saving a snapshot')
|
15
|
+
server.stop
|
16
|
+
wait_until('stopped!') { server.stopped? }
|
17
|
+
thor('list:images')
|
18
|
+
image = fog.images.create(:name => ask('Image name >'), :instance_id => server.id)
|
19
|
+
server.destroy
|
20
|
+
puts
|
21
|
+
puts("===> Created image #{image.id} and terminated temporary server #{server.id}.")
|
22
|
+
puts
|
23
|
+
puts("NOTICE: it may take a while before the new image shows up in list:images")
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Breeze
|
2
|
+
|
3
|
+
class Server::Tag < Veur
|
4
|
+
|
5
|
+
desc 'create SERVER_ID KEY VALUE', 'Create or update a tag'
|
6
|
+
def create(server_id, key, value)
|
7
|
+
fog.tags.create(:resource_id => server_id, :key => key, :value => value)
|
8
|
+
end
|
9
|
+
|
10
|
+
desc 'destroy SERVER_ID KEY', 'Delete a tag'
|
11
|
+
def destroy(server_id, key)
|
12
|
+
fog.tags.get(key).detect{ |tag| tag.resource_id == server_id }.destroy
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
16
|
+
end
|
data/lib/breeze/veur.rb
ADDED
@@ -0,0 +1,86 @@
|
|
1
|
+
require 'breeze/fog_extensions'
|
2
|
+
|
3
|
+
module Breeze
|
4
|
+
|
5
|
+
# Thor is also known as Veur. Veur means "guard of the shrine"
|
6
|
+
# (possibly) according to Wikipedia.
|
7
|
+
class Veur < Thor
|
8
|
+
|
9
|
+
include Thor::Actions
|
10
|
+
|
11
|
+
# shorten the task names
|
12
|
+
def self.inherited(c)
|
13
|
+
c.class_eval do
|
14
|
+
namespace Thor::Util.namespace_from_thor_class(c).sub('breeze:', '')
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
# Thor freezes the options (don't understand why)
|
21
|
+
def options
|
22
|
+
@unfrozen_options ||= super.dup
|
23
|
+
end
|
24
|
+
|
25
|
+
# yes? in thor cannot be accepted with enter
|
26
|
+
def accept?(question)
|
27
|
+
! (ask("#{question} [YES/no] >") =~ /n/i)
|
28
|
+
end
|
29
|
+
|
30
|
+
# don't ask questions if given the --force option
|
31
|
+
def force_or_accept?(question)
|
32
|
+
options[:force] or accept?(question)
|
33
|
+
end
|
34
|
+
|
35
|
+
# Print out dots while waiting for something.
|
36
|
+
# Usage:
|
37
|
+
# print "My task is running..."
|
38
|
+
# wait_until { my_task.completed? }
|
39
|
+
def wait_until(message='completed!')
|
40
|
+
3.times { dot_and_sleep(1) }
|
41
|
+
dot_and_sleep(2) until yield
|
42
|
+
puts message
|
43
|
+
end
|
44
|
+
|
45
|
+
# a helper for wait_until
|
46
|
+
def dot_and_sleep(interval)
|
47
|
+
print('.')
|
48
|
+
sleep(interval)
|
49
|
+
end
|
50
|
+
|
51
|
+
# Print a table with a title and a top border of matching width.
|
52
|
+
def report(title, columns, rows)
|
53
|
+
table = capture_table([columns] + rows)
|
54
|
+
title = "=== #{title} "
|
55
|
+
title << "=" * [(table.lines.max{|s| s.size }.size - title.size), 3].max
|
56
|
+
puts title
|
57
|
+
puts table
|
58
|
+
end
|
59
|
+
|
60
|
+
# capture table in order to determine it's width
|
61
|
+
def capture_table(table)
|
62
|
+
return 'none' if table.size == 1 # the first row is for column titles
|
63
|
+
$stdout = StringIO.new # start capturing the output
|
64
|
+
print_table(table.map{ |row| row.map(&:to_s) })
|
65
|
+
output = $stdout
|
66
|
+
$stdout = STDOUT # restore normal output
|
67
|
+
return output.string
|
68
|
+
end
|
69
|
+
|
70
|
+
def fog
|
71
|
+
@fog ||= Fog::Compute.new(CONFIGURATION[:cloud_service])
|
72
|
+
end
|
73
|
+
|
74
|
+
def dns
|
75
|
+
@dns ||= Fog::DNS.new(CONFIGURATION[:cloud_service])
|
76
|
+
end
|
77
|
+
|
78
|
+
def rds
|
79
|
+
return @rds if @rds
|
80
|
+
credentials = CONFIGURATION[:cloud_service].reject{ |k,v| k == :provider }
|
81
|
+
credentials[:region] = CONFIGURATION[:db_region]
|
82
|
+
@rds = Fog::AWS::RDS.new(credentials)
|
83
|
+
end
|
84
|
+
|
85
|
+
end
|
86
|
+
end
|
@@ -0,0 +1,122 @@
|
|
1
|
+
# Sign up for AWS credentials at http://aws.amazon.com/, and learn how to
|
2
|
+
# upload your own public ssh key at http://alestic.com/2010/10/ec2-ssh-keys.
|
3
|
+
# Use environment variables in this file if you share it with others.
|
4
|
+
|
5
|
+
require 'breeze'
|
6
|
+
|
7
|
+
Breeze::CONFIGURATION = {
|
8
|
+
|
9
|
+
# Access credentials are needed for all tasks.
|
10
|
+
:cloud_service => {
|
11
|
+
:provider => 'AWS',
|
12
|
+
:aws_access_key_id => 'YOUR-ACCESS-KEY-ID',
|
13
|
+
:aws_secret_access_key => 'YOUR-SECTET-ACCESS-KEY'
|
14
|
+
},
|
15
|
+
|
16
|
+
# Remote and upload commands are required in order to create a server image or deploy
|
17
|
+
# an application. Arguments marked with %{} are automatically replaced when the
|
18
|
+
# commands are used. Use "ssh -i /path/to/key" if not using your default ssh key.
|
19
|
+
:remote_command => "ssh ubuntu@%{host} '%{command}'",
|
20
|
+
:upload_command => 'rsync -v %{file_pattern} ubuntu@%{host}:%{remote_path}',
|
21
|
+
|
22
|
+
# :rollback_window specifies the number of minutes to keep old instances running after new ones
|
23
|
+
# have been deployed. Rollback is no longer possible when the old instances have been destroyed.
|
24
|
+
:rollback_window => 60,
|
25
|
+
|
26
|
+
# Default server options are needed when launching new servers.
|
27
|
+
:default_server_options => {
|
28
|
+
:image_id => 'YOUR-PRIVATE-AMI-OR-A-PUBLIC-ONE',
|
29
|
+
:key_name => 'THE-NAME-OF-YOUR-KEYPAIR', # http://alestic.com/2010/10/ec2-ssh-keys
|
30
|
+
:flavor_id => 't1.micro', # t1.micro m1.small c1.medium ...
|
31
|
+
:availability_zone => 'us-east-1a', # us-west-1a eu-west-1a ap-southeast-1a
|
32
|
+
:user_data_file => nil
|
33
|
+
},
|
34
|
+
|
35
|
+
# Override default_server_options when building your own private server image:
|
36
|
+
:create_image_options => {
|
37
|
+
:image_id => 'ami-ccf405a5', # a base AMI from http://alestic.com
|
38
|
+
:root_device_size => 15 # in GB
|
39
|
+
},
|
40
|
+
|
41
|
+
# machine images owned by this account are included in list:images (provided that you have access to them)
|
42
|
+
:image_owner => 'YOUR-ACCOUNT-ID-WITHOUT-DASHES', # canonical: '099720109477'
|
43
|
+
|
44
|
+
# db configuration is required in order to use Amazon RDS
|
45
|
+
:db_region => 'us-east-1', # us-west-1 eu-west-1 ap-southeast-1
|
46
|
+
:default_db_options => {
|
47
|
+
:engine => 'mysql',
|
48
|
+
:engine_version => '5.5',
|
49
|
+
:auto_minor_version_upgrade => true,
|
50
|
+
:allocated_storage => 5, # 5 - 1024 GB
|
51
|
+
:availability_zone => 'us-east-1a',
|
52
|
+
:backup_retention_period => 1, # 0 - 8 days
|
53
|
+
:preferred_backup_window => '05:30-06:00', # daily, times in UTC
|
54
|
+
:preferred_maintenance_window => 'sun:06:00-sun:06:30', # weekly
|
55
|
+
:master_username => 'admin',
|
56
|
+
:password => 'admin'
|
57
|
+
},
|
58
|
+
|
59
|
+
# you can add your own keys and access this hash as CONFIGURATION in the erb templates
|
60
|
+
:admin_email => 'YOUR-EMAIL',
|
61
|
+
:app_path => '/srv/YOUR-APP'
|
62
|
+
}.freeze
|
63
|
+
|
64
|
+
# Define Breeze::CONFIGURATION before requiring the tasks.
|
65
|
+
# This allows us to pick up default options that can be viewed
|
66
|
+
# with the "thor help" command.
|
67
|
+
require 'breeze/tasks'
|
68
|
+
|
69
|
+
class Breeze::Server::Image
|
70
|
+
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
|
+
def prepare_private_image(ip_address)
|
74
|
+
wait_until_host_is_available(ip_address)
|
75
|
+
puts("Uploading scripts...")
|
76
|
+
upload('config/breeze/scripts/*.sh', :host => ip_address, :remote_path => './')
|
77
|
+
remote('chmod 600 credentials.sh; chmod 700 deploy.sh; bash install.sh', :host => ip_address)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
# You can define staging:start etc. with fixed parameters below.
|
82
|
+
|
83
|
+
class Breeze::App
|
84
|
+
private
|
85
|
+
def deploy_command(servers, public_server_name, db_server_name, branch)
|
86
|
+
servers.each do |server|
|
87
|
+
wait_until_host_is_available(ip(server))
|
88
|
+
remote("/home/ubuntu/deploy.sh #{public_server_name} #{db_endpoint(db_server_name)} #{branch}", :host => ip(server))
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
# thor staging:start and staging:stop
|
94
|
+
class Staging < Breeze::App
|
95
|
+
|
96
|
+
PUBLIC_SERVER_NAME = 'staging.example.com'
|
97
|
+
DB_SERVER_NAME = 'staging-db'
|
98
|
+
|
99
|
+
desc 'start', 'Start web server and db for staging'
|
100
|
+
def start
|
101
|
+
thor("app:start #{PUBLIC_SERVER_NAME} #{DB_SERVER_NAME} --db-to-clone=#{Production::DB_SERVER_NAME} --deploy-branch=master")
|
102
|
+
end
|
103
|
+
|
104
|
+
desc 'stop', 'Stop staging and destroy server and db'
|
105
|
+
def stop
|
106
|
+
thor("app:stop #{PUBLIC_SERVER_NAME} --force")
|
107
|
+
end
|
108
|
+
|
109
|
+
end
|
110
|
+
|
111
|
+
# thor production:start
|
112
|
+
class Production < Breeze::App
|
113
|
+
|
114
|
+
PUBLIC_SERVER_NAME = 'production.example.com'
|
115
|
+
DB_SERVER_NAME = 'production-db'
|
116
|
+
|
117
|
+
desc 'start', 'Start web server and db for production'
|
118
|
+
def start
|
119
|
+
thor("app:start #{PUBLIC_SERVER_NAME} #{DB_SERVER_NAME} crags --dns-ttl=300 --deploy-branch=stable")
|
120
|
+
end
|
121
|
+
|
122
|
+
end
|