brightbox 0.25 → 2.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/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