brightbox 0.25 → 2.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/Rakefile ADDED
@@ -0,0 +1,23 @@
1
+ require 'rake/gempackagetask'
2
+ require "brightbox-gemspec.rb"
3
+
4
+ namespace :client do
5
+ Rake::GemPackageTask.new(@client).define
6
+
7
+ task :default => [:reinstall, :clobber_package]
8
+
9
+ desc "Reinstall the client gem locally"
10
+ task :reinstall => [:repackage] do
11
+ sh %Q{sudo gem uninstall -x -v #{@client.version} #{@client.name} }
12
+ sh %q{sudo gem install pkg/*.gem}
13
+ end
14
+
15
+ end
16
+
17
+ namespace :server do
18
+ Rake::GemPackageTask.new(@server).define
19
+ end
20
+
21
+ task :clobber_package => "client:clobber_package"
22
+ task :package => ["client:package", "server:package"]
23
+ task :repackage => ["client:repackage", "server:package"]
data/bin/brightbox CHANGED
@@ -1,4 +1,23 @@
1
1
  #!/usr/bin/env ruby
2
+ # Brightbox - Easy Ruby Web Application Deployment
3
+ # Copyright (C) 2008, Neil Wilson, Brightbox Systems
4
+ #
5
+ # This file is part of the Brightbox deployment system
6
+ #
7
+ # Brightbox gem is free software: you can redistribute it and/or modify it
8
+ # under the terms of the GNU Affero General Public License as published
9
+ # by the Free Software Foundation, either version 3 of the License,
10
+ # or (at your option) any later version.
11
+ #
12
+ # This program is distributed in the hope that it will be useful,
13
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15
+ # Affero General Public License for more details.
16
+ #
17
+ # You should have received a copy of the GNU Affero General
18
+ # Public License along with this program. If not, see
19
+ # <http://www.gnu.org/licenses/>.
20
+ #
2
21
 
3
22
  begin
4
23
  require 'rubygems'
@@ -7,32 +26,284 @@ rescue LoadError
7
26
  end
8
27
 
9
28
  require 'optparse'
29
+ require 'brightbox/version'
10
30
 
11
31
  @options = {}
32
+ @progname = File.basename($0)
33
+
34
+ def has_required_options?
35
+ [@server].all?
36
+ end
37
+
12
38
  OptionParser.new do |opts|
13
- opts.banner = "Usage: #{$0} [options] [args]"
14
-
15
- opts.on("-A", "--apply-to DIRECTORY",
16
- "Create a minimal set of scripts and recipes",
17
- "for use with capistrano to configure servers."
18
- ) { |value| @options[:apply_to] = value }
19
- opts.on("-n", "--name APPLICATION_NAME",
20
- "Name of application."
21
- ) { |value| @options[:application] = value }
22
- opts.on("-d", "--domain DOMAIN_NAME",
23
- "Domain name for application."
24
- ) { |value| @options[:domain] = value }
25
- opts.on("-i", "--server SERVER_NAME",
26
- "Hostname or IP address of your Brightbox virtual server"
27
- ) { |value| @options[:server] = value }
39
+ opts.banner = "Set up your Rails application for deployment\n"
40
+ opts.banner << "Usage: #{@progname} [options] <directory_name>\n\n"
41
+
42
+ opts.on("-n APPLICATION_NAME", "--name APPLICATION_NAME",
43
+ "Name of application (a short useful",
44
+ "name for the app such as 'myforum')",
45
+ "(defaults to the short name of the server)\n"
46
+ ) { |value| @application = value }
47
+
48
+ opts.on("-d DOMAIN_NAME", "--domain DOMAIN_NAME",
49
+ "Domain name for application",
50
+ "(e.g: www.example.com)",
51
+ "(defaults to the server name)\n"
52
+ ) { |value| @domain = value }
53
+
54
+ opts.on("-i SERVER_NAME", "--server SERVER_NAME",
55
+ "Hostname or IP address of your",
56
+ "Brightbox virtual server",
57
+ "(e.g: example-001.vm.brightbox.net)\n"
58
+ ) { |value| @server = value }
59
+
60
+ opts.on_tail("-h", "--help", "Displays this help page") do
61
+ puts opts
62
+ exit 0
63
+ end
64
+
65
+ opts.on_tail("-v", "--version", "Displays the version number") do
66
+ puts "#{@progname}: version #{Brightbox::VERSION}"
67
+ exit 0
68
+ end
28
69
 
29
- if ARGV.empty?
70
+ begin
71
+ opts.parse!(ARGV)
72
+ raise OptionParser::ParseError,
73
+ "You must supply the server name" unless has_required_options?
74
+ rescue OptionParser::ParseError => e
75
+ warn e.message
30
76
  puts opts
31
- exit
77
+ exit 1
78
+ end
79
+ end
80
+
81
+
82
+ abort "Please specify the directory containing the Rails app, e.g. '#{@progname} .'" if ARGV.empty?
83
+ abort "Too many arguments; please provide a single directory name." unless ARGV.length == 1
84
+ abort "'#{ARGV.first}' does not exist." unless File.exists?(ARGV.first)
85
+ abort "'#{ARGV.first}' is not a directory." unless File.directory?(ARGV.first)
86
+
87
+ def unindent(string)
88
+ indentation = string[/\A\s*/]
89
+ string.strip.gsub(/^#{indentation}/, "")
90
+ end
91
+
92
+ @domain ||= @server
93
+ @application ||= @server.gsub(/(-\d{3})?\..*\Z/,'')
94
+
95
+ files = {
96
+ "Capfile" => unindent(<<-FILE),
97
+ # Generated with '#{@progname}' on #{Time.now}
98
+ load 'deploy' if respond_to?(:namespace) # cap2 differentiator
99
+ Dir['vendor/plugins/*/recipes/*.rb'].each { |plugin| load(plugin) }
100
+ load 'config/deploy'
101
+ FILE
102
+
103
+ "lib/tasks/bbgem.rake" => unindent(<<-FILE),
104
+ # Generated with '#{@progname}' on #{Time.now}
105
+ unless Rake::Task.task_defined?("gems:install")
106
+ def install_gems
107
+ gems={
108
+ "ferret" => "~> 0.11",
109
+ "will_paginate" => "> 0"
110
+ }
111
+ gems.each_pair do |gem, version|
112
+ puts "Checking for \#{gem} at \#{version}"
113
+ system("gem spec \#{gem} --version '\#{version}' 2>/dev/null|egrep -q '^name:' ||
114
+ sudo gem install -y --no-ri --no-rdoc --version '\#{version}' \#{gem}")
115
+ end
116
+ end
117
+
118
+ def gems_upgrade_notice
119
+ puts "This is a dummy task installed by the Brightbox command"
120
+ puts "If you need gems to make your application work"
121
+ puts "Uncomment the install command and alter the gems on the list"
122
+ puts "... or upgrade to Rails >= 2.1 and use the inbuilt facilities"
123
+ end
124
+
125
+ namespace(:gems) do
126
+ desc "Installs all required gems for this application."
127
+ task :install do
128
+ gems_upgrade_notice
129
+ #install_gems
130
+ end
131
+ end
132
+ end
133
+
134
+ unless Rake::Task.task_defined?("db:create")
135
+
136
+ namespace(:db) do
137
+ task :create do
138
+ puts "This is a dummy task installed by the Brightbox command"
139
+ puts "Your Rails version is too old to support the db:create task"
140
+ puts "Either upgrade to Rails >=2.0 to use the inbuilt facilities"
141
+ puts "Or create the database by hand if you haven't already"
142
+ end
143
+ end
144
+ end
145
+ unless Rake::Task.task_defined?("db:check:config")
146
+
147
+ def pe(message)
148
+ p "\#{RAILS_ENV}: \#{message}"
149
+ end
150
+
151
+ def brightbox_sanity_checks(config)
152
+ %w(username password database host).each do |entry|
153
+ pe "\#{entry} entry missing" unless config[entry]
154
+ end
155
+ db=config['database']
156
+ host=config['host']
157
+ if host && host != 'sqlreadwrite.brightbox.net'
158
+ pe "using '\#{host}', not the 'sqlreadwrite.brightbox.net' cluster"
159
+ elsif db && db !~ /\\A\#{config['username']}/
160
+ pe "database name should start with '\#{config['username']}' if using cluster"
161
+ end
162
+ end
163
+
164
+ namespace(:db) do
165
+ namespace(:check) do
166
+ desc "Check database.yml config"
167
+ task :config => :environment do
168
+ p "Checking database mysql configuration..."
169
+ if config=ActiveRecord::Base.configurations[RAILS_ENV]
170
+ case config['adapter']
171
+ when nil
172
+ pe "adapter entry missing."
173
+ when 'mysql'
174
+ brightbox_sanity_checks(config)
175
+ else
176
+ pe "using \#{config['adapter']} - halting checks"
177
+ end
178
+ else
179
+ pe "section missing."
180
+ end
181
+ end
182
+ end
183
+ end
184
+ end
185
+
186
+
187
+ FILE
188
+
189
+ "config/deploy.rb" => unindent(<<-FILE),
190
+ ## Generated with '#{@progname}' on #{Time.now}
191
+ gem 'brightbox', '>=#{Brightbox::VERSION}'
192
+ require 'brightbox/recipes'
193
+
194
+ # The name of your application. Used for deployment directory and filenames
195
+ # and Apache configs. Should be unique on the Brightbox
196
+ set :application, "#{@application}"
197
+
198
+ # Primary domain name of your application. Used in the Apache configs
199
+ set :domain, "#{@domain}"
200
+
201
+ ## List of servers
202
+ server "#{@server}", :app, :web, :db, :primary => true
203
+
204
+ # Target directory for the application on the web and app servers.
205
+ set(:deploy_to) { File.join("", "home", user, application) }
206
+
207
+ # URL of your source repository. This is the default one that comes on
208
+ # every Brightbox, you can use your own (we'll let you :)
209
+ set :repository, "."
210
+ set :scm, :none
211
+ set :deploy_via, :copy
212
+
213
+ ### Other options you can set ##
214
+ # Comma separated list of additional domains for Apache
215
+ # set :domain_aliases, "www.example.com,dev.example.com"
216
+
217
+ ## Local Shared Area
218
+ # These are the list of files and directories that you want
219
+ # to share between all the releases of your application.
220
+ # So if you have an 'upload' directory in public, add 'public/upload'
221
+ # to the :local_shared_dirs array.
222
+ # If you want to share the database.yml add 'config/database.yml'
223
+ # to the :local_shared_files array.
224
+ # The shared area is prepared with 'deploy:setup' and all the shared
225
+ # items are symlinked in when the code is updated.
226
+ # set :local_shared_dirs, %w(public/upload)
227
+ # set :local_shared_files, %w(config/database.yml)
228
+
229
+ # SSL Certificates. If you specify an SSL certificate name then
230
+ # the gem will create an 'https' configuration for this application
231
+ # TODO: Upload and install the keys on the server
232
+ # set :ssl_certificate, "/path/to/certificate/for/my_app.crt"
233
+ # set :ssl_key, "/path/to/key/for/my_app.key
234
+ # or
235
+ # set :ssl_certificate, "name_of_installed_certificate"
236
+
237
+ # SSH options. The forward agent option is used so that loopback logins
238
+ # with keys work properly
239
+ # ssh_options[:forward_agent] = true
240
+
241
+ # Forces a Pty so that svn+ssh repository access will work. You
242
+ # don't need this if you are using a different SCM system. Note that
243
+ # ptys stop shell startup scripts from running.
244
+ default_run_options[:pty] = true
245
+
246
+ ## Logrotation
247
+ # Where the logs are stored. Defaults to <shared_path>/log
248
+ # set :log_dir, "central/log/path"
249
+ # The size at which to rotate a log. e.g 1G, 100M, 5M. Defaults to 100M
250
+ # set :log_max_size, "100M"
251
+ # How many old compressed logs to keep. Defaults to 10
252
+ # set :log_keep, "10"
253
+
254
+ ## Version Control System
255
+ # Which version control system. Defaults to subversion if there is
256
+ # no 'set :scm' command.
257
+ # set :scm, :git
258
+ # set :scm_username, "rails"
259
+ # set :scm_password, "mysecret"
260
+ # or be explicit
261
+ # set :scm, :subversion
262
+
263
+ ## Mongrel settings
264
+ # Host where mongrel lives. Defaults to the app server
265
+ # set :mongrel_host, "127.0.0.1"
266
+ # Port number where mongrel starts. Defaults to 9200
267
+ # set :mongrel_port, 9200
268
+ # Number of mongrel servers to start. Defaults to 2
269
+ # set :mongrel_servers, 2
270
+
271
+ ## Deployment settings
272
+ # The brightbox gem deploys as the user 'rails' by default and
273
+ # into the 'production' environment. You can change these as required.
274
+ # set :user, "rails"
275
+ # set :rails_env, :production
276
+
277
+ ## Command running settings
278
+ # use_sudo is switched off by default so that commands are run
279
+ # directly as 'user' by the run command. If you switch on sudo
280
+ # make sure you set the :runner variable - which is the user the
281
+ # capistrano default tasks use to execute commands.
282
+ # NB. This just affects the default recipes unless you use the
283
+ # 'try_sudo' command to run your commands.
284
+ # set :use_sudo, false
285
+ # set :runner, user
286
+
287
+ ## Dependencies
288
+ # Set the commands and gems that your application requires. e.g.
289
+ # depend :remote, :gem, "will_paginate", ">=2.2.2"
290
+ # depend :remote, :command, "brightbox"
291
+ FILE
292
+ }
293
+
294
+ base = ARGV.shift
295
+ files.each do |file, content|
296
+ file = File.join(base, file)
297
+ if File.exists?(file)
298
+ warn "[skip] `#{file}' already exists"
299
+ elsif File.exists?(file.downcase)
300
+ warn "[skip] `#{file.downcase}' exists, which could conflict with `#{file}'"
301
+ elsif !File.exists?(File.dirname(file))
302
+ warn "[skip] directory `#{File.dirname(file)}' does not exist"
32
303
  else
33
- opts.parse!(ARGV)
304
+ puts "[add] writing `#{file}'"
305
+ File.open(file, "w") { |f| f.write(content) }
34
306
  end
35
307
  end
36
308
 
37
- require 'brightbox/generators/loader'
38
- Brightbox::Generators::RailsLoader.load! @options
309
+ puts "[done] ready for deployment!"
@@ -0,0 +1,46 @@
1
+ # Brightbox - Easy Ruby Web Application Deployment
2
+ # Copyright (C) 2008, Neil Wilson, Brightbox Systems
3
+ #
4
+ # This file is part of the Brightbox deployment system
5
+ #
6
+ # Brightbox gem is free software: you can redistribute it and/or modify it
7
+ # under the terms of the GNU Affero General Public License as published
8
+ # by the Free Software Foundation, either version 3 of the License,
9
+ # or (at your option) any later version.
10
+ #
11
+ # This program is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14
+ # Affero General Public License for more details.
15
+ #
16
+ # You should have received a copy of the GNU Affero General
17
+ # Public License along with this program. If not, see
18
+ # <http://www.gnu.org/licenses/>.
19
+ #
20
+ require File.join(File.dirname(__FILE__),"lib/brightbox/version")
21
+ def add_common(spec)
22
+ spec.version = Brightbox::VERSION
23
+ spec.authors = ["John Leach","Neil Wilson"]
24
+ spec.email = "support@brightbox.co.uk"
25
+ spec.homepage = "http://wiki.brightbox.co.uk/docs:thebrightboxgem"
26
+ spec.rubyforge_project = 'brightbox'
27
+ spec.has_rdoc = false
28
+ end
29
+
30
+ @server = Gem::Specification.new do |s|
31
+ add_common(s)
32
+ s.name = "brightbox-server-tools"
33
+ s.files = FileList["LICENSE", "Rakefile", "*.rb", "bin/railsapp-*","{lib,spec}/**/*.rb"].exclude(/recipe/).to_a
34
+ s.summary = "Brightbox Server configuration scripts"
35
+ s.executables = FileList["bin/railsapp-*"].sub(/bin\//,'')
36
+ end
37
+
38
+ @client = Gem::Specification.new do |s|
39
+ add_common(s)
40
+ s.name = "brightbox"
41
+ s.files = FileList["LICENSE", "Rakefile", "*.rb", "lib/**/*.rb","bin/brightbox"].exclude("lib/brightbox/webserver-common.rb").to_a
42
+ s.add_dependency("capistrano", ">= 2.3")
43
+ s.summary = "Brightbox rails deployment scripts for Capistrano"
44
+ s.executable = 'brightbox'
45
+ end
46
+
@@ -1,121 +1,22 @@
1
- require 'mongrel_cluster/recipes'
2
- require 'yaml'
3
-
4
- Capistrano.configuration(:must_exist).load do
5
-
6
- desc "Create apache config for this app on your Brightbox web servers"
7
- task :setup_apache, :roles => :web do
8
- sudo "/usr/bin/brightbox-apache -n #{application} -d #{domain} -w #{current_path}/public -h #{mongrel_host} -p #{mongrel_port} -s #{mongrel_servers}"
9
- sudo "/usr/sbin/apache2ctl -t"
10
- end
11
-
12
- desc "Reload apache on your Brightbox web servers"
13
- task :reload_apache, :roles => :web do
14
- sudo "/usr/sbin/apache2ctl -t"
15
- sudo "/usr/sbin/apache2ctl graceful"
16
- end
17
-
18
- desc "Load the rails db schema on the primary db server"
19
- task :load_schema, :roles => :db, :primary => true do
20
- run "cd #{current_path} && #{rake} RAILS_ENV=#{(rails_env||"production").to_s} db:schema:load"
21
- end
22
-
23
- desc "Configure monit to handle the mongrel servers for this app"
24
- task :configure_mongrel_cluster, :roles => :app do
25
- sudo "/usr/bin/brightbox-monit -n #{application} -r #{current_path} -e #{(rails_env||"production").to_s} -p #{mongrel_port} -s #{mongrel_servers} -h #{mongrel_host}"
26
- end
27
-
28
- desc "Restart the mongrel servers using monit"
29
- task :restart_mongrel_cluster, :roles => :app do
30
- sudo "/usr/sbin/monit -g #{application} restart all"
31
- end
32
-
33
- desc "Start the mongrel servers using monit"
34
- task :start_mongrel_cluster, :roles => :app do
35
- sudo "/usr/sbin/monit -g #{application} start all"
36
- end
37
-
38
- desc "Stop the mongrel servers using monit"
39
- task :stop_mongrel_cluster, :roles => :app do
40
- sudo "/usr/sbin/monit -g #{application} stop all"
41
- end
42
-
43
- desc "Display the monit status for this app"
44
- task :monit_status, :roles => :app do
45
- sudo "/usr/sbin/monit -g #{application} status"
46
- end
47
-
48
- desc "Reload the monit daemon"
49
- task :monit_reload, :roles => :app do
50
- sudo "/usr/sbin/monit reload"
51
- sleep 5
52
- end
53
-
54
- desc "Deploy the app to your Brightbox servers for the FIRST TIME. Sets up apache config starts mongrel."
55
- task :cold_deploy do
56
- transaction do
57
- update_code
58
- symlink
59
- end
60
-
61
- create_mysql_database # Fails if already exist to prevent data loss later
62
- load_schema # WARNING: This wipes the tables
63
- migrate
64
- configure_mongrel_cluster
65
- monit_reload
66
- start_mongrel_cluster
67
- setup_apache
68
- reload_apache
69
- end
70
-
71
- desc "Rewrite the Apache and Monit configs and reloads the services"
72
- task :reconfigure do
73
- configure_mongrel_cluster
74
- monit_reload
75
- restart_mongrel_cluster
76
- setup_apache
77
- reload_apache
78
- end
79
-
80
- desc "Deploy the app to your Brightbox servers"
81
- task :deploy do
82
- transaction do
83
- update_code
84
- disable_web
85
- stop_mongrel_cluster
86
- symlink
87
- start_mongrel_cluster
88
- end
89
-
90
- enable_web
91
- end
92
-
93
- desc "Create the mysql database named in the database.yml on the primary db server"
94
- task :create_mysql_database, :roles => :db, :primary => true do
95
- read_db_config
96
- if db_adapter == 'mysql'
97
- run "mysql -h #{db_host} --user=#{db_user} -p --execute=\"CREATE DATABASE #{db_name}\"" do |channel, stream, data|
98
- if data =~ /^Enter password:/
99
- logger.info data, "[database on #{channel[:host]} asked for password]"
100
- channel.send_data "#{db_password}\n"
101
- end
102
- end
103
- end
104
- end
105
-
106
- def read_db_config
107
- db_config = YAML.load_file('config/database.yml')
108
- set :db_adapter, db_config[(rails_env||"production").to_s]["adapter"]
109
- set :db_user, db_config[(rails_env||"production").to_s]["username"]
110
- set :db_password, db_config[(rails_env||"production").to_s]["password"]
111
- set :db_name, db_config[(rails_env||"production").to_s]["database"]
112
- set :db_host, db_config[(rails_env||"production").to_s]["host"]
113
- if db_host !~ /^sqlreadwrite/
114
- logger.important "WARNING: Database host is not sqlreadwrite as per the Brightbox requirements"
115
- end
116
- if db_name !~ /^#{db_user}\_/
117
- logger.important "WARNING: Database name is not prefixed with MySQL username as per the Brightbox requirements"
118
- end
119
- end
120
-
1
+ # Brightbox - Easy Ruby Web Application Deployment
2
+ # Copyright (C) 2008, Neil Wilson, Brightbox Systems
3
+ #
4
+ # This file is part of the Brightbox deployment system
5
+ #
6
+ # Brightbox gem is free software: you can redistribute it and/or modify it
7
+ # under the terms of the GNU Affero General Public License as published
8
+ # by the Free Software Foundation, either version 3 of the License,
9
+ # or (at your option) any later version.
10
+ #
11
+ # This program is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14
+ # Affero General Public License for more details.
15
+ #
16
+ # You should have received a copy of the GNU Affero General
17
+ # Public License along with this program. If not, see
18
+ # <http://www.gnu.org/licenses/>.
19
+ #
20
+ Dir[File.join(File.dirname(__FILE__), 'recipes', '*.rb')].each do |recipe|
21
+ Capistrano::Configuration.instance(true).load recipe
121
22
  end