Class: Sunshine::App
- Inherits:
-
Object
- Object
- Sunshine::App
- Defined in:
- lib/sunshine/app.rb
Overview
App objects are the core of Sunshine deployment. The Sunshine paradygm is to construct an app object, and run custom deploy code by passing a block to its deploy method. The following is the simplest way to instantiate an app:
app = Sunshine::App.new :remote_shells => "deploy_server.com"
By default, Sunshine will look in the pwd for scm information and will extract the app’s name. The default root deploy path is specified by Sunshine.web_directory, in this case: “/srv/http/app_name”.
More complex setups may look like the following:
someserver = Sunshine::RemoteShell.new "[email protected]",
:roles => [:web, :app]
myapprepo = Sunshine::SvnRepo.new "svn://my_repo/myapp/tags/release"
app = Sunshine::App.new :name => 'myapp',
:repo => myapprepo,
:root_path => '/usr/local/myapp',
:remote_shells => someserver
Note: The instantiation options :repo and :remote_shells support the same data format that their respective initialize methods support. The :remote_shells option also supports arrays of remote shell instance arguments.
Once an App is instantiated it can be manipulated in a variety of ways, including deploying it:
app.deploy do |app|
app_server = Sunshine::Rainbows.new app, :port => 3000
web_server = Sunshine::Nginx.new app, :point_to => app_server
app_server.setup
web_server.setup
end
The constructor also supports reading multi-env configs fom a yaml file, which can also be the deploy script’s DATA, to allow for concise, encapsulated deploy files:
# Load from an explicit yaml file:
Sunshine::App.new "path/to/config.yml"
# Load from the yaml in the script file's DATA:
Sunshine::App.new
Yaml files must define settings on a per-environment basis. The default environment will be used as a base for all other environments:
#config.yml:
---
:default:
:repo:
:type: :svn
:url: http://subversion/repo/tags/release-001
:remote_shells: dev.myserver.com
qa:
:remote_shells:
- qa1.myserver.com
- qa2.myserver.com
qa_special:
:inherits: qa
:root_path: /path/to/application
:deploy_env: qa
By default, App will get the deploy_env value from Sunshine.deploy_env, but it may also be passed in explicitely as an option.
Instance Attribute Summary collapse
-
#checkout_path ⇒ Object
readonly
Returns the value of attribute checkout_path.
-
#current_path ⇒ Object
readonly
Returns the value of attribute current_path.
-
#deploy_env ⇒ Object
readonly
Returns the value of attribute deploy_env.
-
#deploy_name ⇒ Object
readonly
Returns the value of attribute deploy_name.
-
#deploys_path ⇒ Object
readonly
Returns the value of attribute deploys_path.
-
#log_path ⇒ Object
readonly
Returns the value of attribute log_path.
-
#name ⇒ Object
readonly
Returns the value of attribute name.
-
#remote_checkout ⇒ Object
Returns the value of attribute remote_checkout.
-
#repo ⇒ Object
readonly
Returns the value of attribute repo.
-
#root_path ⇒ Object
readonly
Returns the value of attribute root_path.
-
#scripts_path ⇒ Object
readonly
Returns the value of attribute scripts_path.
-
#server_apps ⇒ Object
readonly
Returns the value of attribute server_apps.
-
#shared_path ⇒ Object
readonly
Returns the value of attribute shared_path.
-
#sudo ⇒ Object
Returns the value of attribute sudo.
Class Method Summary collapse
-
.deploy(*args, &block) ⇒ Object
Initialize and deploy an application in a single step.
Instance Method Summary collapse
-
#add_shell_paths(*paths) ⇒ Object
Add paths the the shell $PATH env on all app shells.
-
#add_to_crontab(name, cronjob, options = nil) ⇒ Object
Add a command to the crontab to be generated remotely: add_to_crontab “reboot”, “@reboot /path/to/app/start”, :role => :web.
-
#add_to_script(name, script, options = nil) ⇒ Object
Add a command to a control script to be generated remotely: add_to_script :start, “do this on start” add_to_script :start, “start_mail”, :role => :mail.
-
#after_user_script(&block) ⇒ Object
Define lambdas to run right after the user’s yield.
-
#any_connected?(options = nil) ⇒ Boolean
Check if any server apps are connected and returns a boolean.
-
#build_control_scripts(options = nil) ⇒ Object
Creates and uploads all control scripts for the application.
-
#build_crontab(options = nil) ⇒ Object
Writes the crontab on all or selected server apps.
-
#build_deploy_info_file(options = nil) ⇒ Object
Creates a yaml file with deploy information.
-
#build_erb(erb_file, custom_binding = nil) ⇒ Object
Parse an erb file and return the newly created string.
-
#call(cmd, options = nil, &block) ⇒ Object
Call a command on specified server apps.
-
#checkout_codebase(options = nil) ⇒ Object
Checks out the app’s codebase to one or all deploy servers.
-
#connect(options = nil) ⇒ Object
Start a persistant connection to app servers.
-
#connected?(options = nil) ⇒ Boolean
Check if all server apps are connected and returns a boolean.
-
#console! ⇒ Object
Starts an IRB console with the instance’s binding.
-
#cronjob(name, cronjob, options = nil) ⇒ Object
Add a command to the crontab to be generated remotely: cronjob “reboot”, “@reboot /path/to/app/start”, :role => :web.
-
#deploy(options = nil) ⇒ Object
Deploy the application to deploy servers and call user’s post-deploy code.
-
#deploy_details(options = nil) ⇒ Object
Get a hash of deploy information for each server app.
-
#deployed?(options = nil) ⇒ Boolean
Check if app has been deployed successfully by checking the name of the deploy on every app server with the instance’s deploy name.
-
#disconnect(options = nil) ⇒ Object
Disconnect from app servers.
-
#each(options = nil, &block) ⇒ Object
Iterate over each server app.
-
#find(query = nil) ⇒ Object
Find server apps matching the passed requirements.
-
#handle_exception(exception, state = {}) ⇒ Object
Calls the Apps on_exception hook or the default Sunshine.exception_behavior.
-
#handle_interruption(behavior, state = {}) ⇒ Object
Handles the behavior of a failed or interrupted deploy.
-
#handle_sigint(state = {}) ⇒ Object
Calls the Apps on_sigint hook or the default Sunshine.sigint_behavior.
-
#initialize(config_file = Sunshine::DATA, options = {}) ⇒ App
constructor
App instantiation can be done in several ways: App.new instantiation_hash App.new “path/to/config.yml”, optional_extra_hash App.new #=> will attempt to load ruby’s file DATA as yaml.
-
#install_deps(*deps) ⇒ Object
Install dependencies defined as a Sunshine dependency object: rake = Sunshine.dependencies.gem ‘rake’, :version => ‘~>0.8’ apache = Sunshine.dependencies.yum ‘apache’ app.install_deps rake, apache.
-
#interruptable(options = {}) ⇒ Object
Runs the given block while handling SIGINTs and exceptions according to rules set by Sunshine.sigint_behavior and Sunshine.exception_behavior or with the override hooks App#on_sigint and App#on_exception.
-
#make_app_directories(options = nil) ⇒ Object
Creates the required application directories.
-
#on_exception(&block) ⇒ Object
Set this to define the behavior of exceptions during a deploy.
-
#on_sigint(&block) ⇒ Object
Set this to define the behavior of SIGINT during a deploy.
-
#prefer_pkg_manager(pkg_manager, options = nil) ⇒ Object
Assign the prefered package manager to all server_apps: app.prefer_pkg_manager Sunshine::Yum.
-
#rake(command, options = nil) ⇒ Object
Run a rake task on any or all deploy servers.
-
#register_as_deployed(options = nil) ⇒ Object
Adds the app to the deploy servers deployed-apps list.
-
#remove_cronjob(name, options = nil) ⇒ Object
Remove a cron job from the remote crontabs: remove_cronjob “reboot”, :role => :web remove_cronjob :all #=> deletes all cronjobs related to this app Supports all App#find options.
-
#remove_old_deploys(options = nil) ⇒ Object
Removes old deploys from the checkout_dir based on Sunshine’s max_deploy_versions.
-
#restart(options = nil) ⇒ Object
Run the restart script of a deployed app on the specified deploy servers.
-
#restart!(options = nil) ⇒ Object
Run the restart script of a deployed app on the specified deploy servers.
-
#revert!(options = nil) ⇒ Object
Symlink current directory to previous checkout and remove the current deploy directory.
-
#run_bundler(options = nil) ⇒ Object
Runs bundler on deploy servers.
-
#run_geminstaller(options = nil) ⇒ Object
Runs GemInstaller on deploy servers.
-
#run_post_user_lambdas ⇒ Object
Run lambdas that were saved for after the user’s script.
-
#run_script(name, options = nil) ⇒ Object
Run the given script of a deployed app on the specified deploy servers.
-
#run_script!(name, options = nil) ⇒ Object
Run the given script of a deployed app on the specified deploy servers.
-
#sass(*sass_names) ⇒ Object
Run a sass task on any or all deploy servers.
-
#shell_env(env_hash = nil, options = nil) ⇒ Object
Set and return the remote shell env variables.
-
#start(options = nil) ⇒ Object
Run the start script of a deployed app on the specified deploy servers.
-
#start!(options = nil) ⇒ Object
Run the start script of a deployed app on the specified deploy servers.
-
#status(options = nil) ⇒ Object
Get a hash of which deploy server apps are :running or :down.
-
#stop(options = nil) ⇒ Object
Run the stop script of a deployed app on the specified deploy servers.
-
#stop!(options = nil) ⇒ Object
Run the stop script of a deployed app on the specified deploy servers.
-
#symlink_current_dir(options = nil) ⇒ Object
Creates a symlink to the app’s checkout path.
-
#threaded_each(options = nil, &block) ⇒ Object
Iterate over all deploy servers but create a thread for each deploy server.
-
#with_filter(filter_hash) ⇒ Object
Execute a block with a specified server app filter: app.with_filter :role => :cdn do |app| app.sass ‘file1’, ‘file2’, ‘file3’ app.rake ‘asset:packager:build_all’ end Supports all App#find options.
-
#with_server_apps(search_options, options = {}) ⇒ Object
Calls a method for server_apps found with the passed options, and with an optional log message.
-
#with_session(options = nil) ⇒ Object
Runs block ensuring a connection to remote_shells.
Constructor Details
#initialize(config_file = Sunshine::DATA, options = {}) ⇒ App
App instantiation can be done in several ways:
App.new instantiation_hash
App.new "path/to/config.yml", optional_extra_hash
App.new #=> will attempt to load ruby's file DATA as yaml
Options supported are:
- :deploy_env
-
String - specify the env to deploy with; defaults to
Sunshine#deploy_env.
- :deploy_name
-
String - if you want to specify a name for your deploy and
checkout directory (affects the checkout_path); defaults to Time.now.to_i.
- :remote_checkout
-
Boolean - when true, will checkout the codebase
directly from the deploy servers; defaults to false.
- :remote_shells
-
String|Array|Sunshine::Shell - the shell(s) to use for
deployment. Accepts any single instance or array of a Sunshine::Shell type instance or Sunshine::Shell instantiator-friendly arguments.
- :repo
-
Hash|Sunshine::Repo - the scm and repo to use for deployment.
Accepts any hash that can be passed to Sunshine::Repo::new_of_type or any Sunshine::Repo object.
- :root_path
-
String - the absolute path the deployed application
should live in; defaults to “#Sunshine.web_directory/#@name”.
- :shell_env
-
Hash - environment variables to add to deploy shells.
- :sudo
-
true|false|nil|String - which sudo value should be assigned to
deploy shells; defaults to Sunshine#sudo. For more information on using sudo, see the Using Permissions section in README.txt.
130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 |
# File 'lib/sunshine/app.rb', line 130 def initialize config_file=Sunshine::DATA, ={} , config_file = config_file, Sunshine::DATA if Hash === config_file @deploy_env = [:deploy_env] || Sunshine.deploy_env binder = Binder.new self binder.import_hash binder.forward :deploy_env = config_from_file(config_file, binder.get_binding).merge @repo = repo_from_config [:repo] @name = [:name] || @repo.name @deploy_name = [:deploy_name] || Time.now.to_i.to_s @deploy_env = [:deploy_env] if [:deploy_env] set_deploy_paths [:root_path] @server_apps = server_apps_from_config [:remote_shells] @remote_checkout = [:remote_checkout] || Sunshine.remote_checkouts? self.sudo = [:sudo] || Sunshine.sudo @shell_env = { "RACK_ENV" => @deploy_env.to_s, "RAILS_ENV" => @deploy_env.to_s } shell_env [:shell_env] @post_user_lambdas = [] @on_sigint = @on_exception = nil end |
Instance Attribute Details
#checkout_path ⇒ Object (readonly)
Returns the value of attribute checkout_path.
92 93 94 |
# File 'lib/sunshine/app.rb', line 92 def checkout_path @checkout_path end |
#current_path ⇒ Object (readonly)
Returns the value of attribute current_path.
92 93 94 |
# File 'lib/sunshine/app.rb', line 92 def current_path @current_path end |
#deploy_env ⇒ Object (readonly)
Returns the value of attribute deploy_env.
91 92 93 |
# File 'lib/sunshine/app.rb', line 91 def deploy_env @deploy_env end |
#deploy_name ⇒ Object (readonly)
Returns the value of attribute deploy_name.
91 92 93 |
# File 'lib/sunshine/app.rb', line 91 def deploy_name @deploy_name end |
#deploys_path ⇒ Object (readonly)
Returns the value of attribute deploys_path.
92 93 94 |
# File 'lib/sunshine/app.rb', line 92 def deploys_path @deploys_path end |
#log_path ⇒ Object (readonly)
Returns the value of attribute log_path.
93 94 95 |
# File 'lib/sunshine/app.rb', line 93 def log_path @log_path end |
#name ⇒ Object (readonly)
Returns the value of attribute name.
91 92 93 |
# File 'lib/sunshine/app.rb', line 91 def name @name end |
#remote_checkout ⇒ Object
Returns the value of attribute remote_checkout.
94 95 96 |
# File 'lib/sunshine/app.rb', line 94 def remote_checkout @remote_checkout end |
#repo ⇒ Object (readonly)
Returns the value of attribute repo.
91 92 93 |
# File 'lib/sunshine/app.rb', line 91 def repo @repo end |
#root_path ⇒ Object (readonly)
Returns the value of attribute root_path.
92 93 94 |
# File 'lib/sunshine/app.rb', line 92 def root_path @root_path end |
#scripts_path ⇒ Object (readonly)
Returns the value of attribute scripts_path.
93 94 95 |
# File 'lib/sunshine/app.rb', line 93 def scripts_path @scripts_path end |
#server_apps ⇒ Object (readonly)
Returns the value of attribute server_apps.
91 92 93 |
# File 'lib/sunshine/app.rb', line 91 def server_apps @server_apps end |
#shared_path ⇒ Object (readonly)
Returns the value of attribute shared_path.
93 94 95 |
# File 'lib/sunshine/app.rb', line 93 def shared_path @shared_path end |
#sudo ⇒ Object
Returns the value of attribute sudo.
91 92 93 |
# File 'lib/sunshine/app.rb', line 91 def sudo @sudo end |
Class Method Details
.deploy(*args, &block) ⇒ Object
Initialize and deploy an application in a single step. Takes any arguments supported by the constructor.
84 85 86 87 88 |
# File 'lib/sunshine/app.rb', line 84 def self.deploy(*args, &block) app = new(*args) app.deploy(&block) app end |
Instance Method Details
#add_shell_paths(*paths) ⇒ Object
Add paths the the shell $PATH env on all app shells.
435 436 437 438 439 440 |
# File 'lib/sunshine/app.rb', line 435 def add_shell_paths(*paths) path = @shell_env["PATH"] || "$PATH" paths << path shell_env "PATH" => paths.join(":") end |
#add_to_crontab(name, cronjob, options = nil) ⇒ Object
Add a command to the crontab to be generated remotely:
add_to_crontab "reboot", "@reboot /path/to/app/start", :role => :web
Note: This method will append jobs to already existing cron jobs for this application and job name, including previous deploys.
450 451 452 453 454 |
# File 'lib/sunshine/app.rb', line 450 def add_to_crontab name, cronjob, =nil each do |server_app| server_app.crontab[name] << cronjob end end |
#add_to_script(name, script, options = nil) ⇒ Object
Add a command to a control script to be generated remotely:
add_to_script :start, "do this on start"
add_to_script :start, "start_mail", :role => :mail
476 477 478 479 480 |
# File 'lib/sunshine/app.rb', line 476 def add_to_script name, script, =nil each do |server_app| server_app.scripts[name] << script end end |
#after_user_script(&block) ⇒ Object
Define lambdas to run right after the user’s yield.
app.after_user_script do |app|
...
end
489 490 491 |
# File 'lib/sunshine/app.rb', line 489 def after_user_script &block @post_user_lambdas << block end |
#any_connected?(options = nil) ⇒ Boolean
Check if any server apps are connected and returns a boolean. Supports any App#find options.
214 215 216 217 218 219 220 |
# File 'lib/sunshine/app.rb', line 214 def any_connected? =nil each do |server_app| return true if server_app.shell.connected? end false end |
#build_control_scripts(options = nil) ⇒ Object
Creates and uploads all control scripts for the application. To add to, or define a control script, see App#add_to_script.
498 499 500 501 502 |
# File 'lib/sunshine/app.rb', line 498 def build_control_scripts =nil with_server_apps , :msg => "Building control scripts", :send => :build_control_scripts end |
#build_crontab(options = nil) ⇒ Object
Writes the crontab on all or selected server apps. To add or remove from the crontab, see App#add_to_crontab and App#remove_cronjob.
510 511 512 513 514 515 |
# File 'lib/sunshine/app.rb', line 510 def build_crontab =nil with_server_apps , :msg => "Building the crontab" do |server_app| server_app.crontab.write! end end |
#build_deploy_info_file(options = nil) ⇒ Object
Creates a yaml file with deploy information. To add custom information to the info file, use the app’s info hash attribute:
app.info[:key] = "some value"
523 524 525 526 527 |
# File 'lib/sunshine/app.rb', line 523 def build_deploy_info_file =nil with_server_apps , :msg => "Creating info file", :send => :build_deploy_info_file end |
#build_erb(erb_file, custom_binding = nil) ⇒ Object
Parse an erb file and return the newly created string. Default binding is the app’s binding.
534 535 536 537 |
# File 'lib/sunshine/app.rb', line 534 def build_erb erb_file, custom_binding=nil str = File === erb_file ? erb_file.read : File.read(erb_file) ERB.new(str, nil, '-').result(custom_binding || binding) end |
#call(cmd, options = nil, &block) ⇒ Object
Call a command on specified server apps. Returns an array of responses. Supports any App#find and Shell#call options:
app.call "ls -1", :sudo => true, :host => "web.app.com"
#=> [".\n..\ndir1", ".\n..\ndir1", ".\n..\ndir2"]
177 178 179 180 181 |
# File 'lib/sunshine/app.rb', line 177 def call cmd, =nil, &block with_server_apps , :msg => "Running #{cmd}" do |server_app| server_app.shell.call cmd, , &block end end |
#checkout_codebase(options = nil) ⇒ Object
Checks out the app’s codebase to one or all deploy servers. Supports all App#find options, plus:
- :copy
-
Bool - Checkout locally and rsync; defaults to false.
- :exclude
-
String|Array - Exclude the specified paths during
a deploy via copy.
577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 |
# File 'lib/sunshine/app.rb', line 577 def checkout_codebase =nil copy_option = [:copy] if exclude = .delete :exclude if if RsyncRepo === @repo || (@remote_checkout && !copy_option) with_server_apps , :msg => "Checking out codebase (remotely)", :send => [:checkout_repo, @repo] else Sunshine.logger.info :app, "Checking out codebase (locally)" do tmp_path = File.join Sunshine::TMP_DIR, "#{@name}_checkout" scm_info = @repo.checkout_to tmp_path scm_info[:exclude] = [Sunshine.exclude_paths, exclude].flatten.compact with_server_apps , :send => [:upload_codebase, tmp_path, scm_info] end end end |
#connect(options = nil) ⇒ Object
Start a persistant connection to app servers. Supports any App#find options.
188 189 190 191 192 193 194 |
# File 'lib/sunshine/app.rb', line 188 def connect =nil Sunshine.logger.info :app, "Connecting..." do threaded_each do |server_app| server_app.shell.connect end end end |
#connected?(options = nil) ⇒ Boolean
Check if all server apps are connected and returns a boolean. Supports any App#find options.
201 202 203 204 205 206 207 |
# File 'lib/sunshine/app.rb', line 201 def connected? =nil each do |server_app| return false unless server_app.shell.connected? end true end |
#console! ⇒ Object
Starts an IRB console with the instance’s binding.
543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 |
# File 'lib/sunshine/app.rb', line 543 def console! IRB.setup nil unless defined?(IRB::UnrecognizedSwitch) workspace = IRB::WorkSpace.new binding irb = IRB::Irb.new workspace irb.context.irb_name = "sunshine(#{@name})" irb.context.prompt_c = "%N:%03n:%i* " irb.context.prompt_i = "%N:%03n:%i> " irb.context.prompt_n = "%N:%03n:%i> " IRB.class_eval do @CONF[:IRB_RC].call(irb.context) if @CONF[:IRB_RC] @CONF[:MAIN_CONTEXT] = irb.context end #TODO: remove sigint trap when irb session is closed #trap("INT") do # irb.signal_handle #end catch(:IRB_EXIT) do irb.eval_input end end |
#cronjob(name, cronjob, options = nil) ⇒ Object
Add a command to the crontab to be generated remotely:
cronjob "reboot", "@reboot /path/to/app/start", :role => :web
Note: This method will override already existing cron jobs for this application and job name, including previous deploys.
464 465 466 467 468 |
# File 'lib/sunshine/app.rb', line 464 def cronjob name, cronjob, =nil each do |server_app| server_app.crontab[name] = cronjob end end |
#deploy(options = nil) ⇒ Object
Deploy the application to deploy servers and call user’s post-deploy code. Supports any App#find options.
If the deploy fails or an exception is raised, it will attempt to run the Sunshine.exception_behavior, which is set to :revert by default. However, this is not true of ssh connection failures.
If the deploy is interrupted by a SIGINT, it will attempt to run the Sunshine.sigint_behavior, which is set to :revert by default.
The deploy method will stop the former deploy just before symlink and the passed block is run.
Once deployment is complete, the deploy method will attempt to run App#start! which will run any start script checked into App#scripts_path, or the start script that will have been generated by using Sunshine server setups.
254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 |
# File 'lib/sunshine/app.rb', line 254 def deploy =nil state = { :success => false, :stopped => false, :symlinked => false } Sunshine.logger.info :app, "Beginning #{@name} deploy" with_session do |app| interruptable state do raise DeployError, "No servers defined for #{@name}" if @server_apps.empty? make_app_directories checkout_codebase state[:stopped] = true if stop state[:symlinked] = true if symlink_current_dir yield self if block_given? run_post_user_lambdas build_control_scripts build_deploy_info_file build_crontab register_as_deployed state[:success] = true if start! :force => true end remove_old_deploys if state[:success] rescue Sunshine.logger.error :app, "Could not remove old deploys" state[:success] &&= deployed? end Sunshine.logger.info :app, "Finished #{@name} deploy" if state[:success] state[:success] end |
#deploy_details(options = nil) ⇒ Object
Get a hash of deploy information for each server app. Post-deploy only.
606 607 608 609 610 611 612 613 614 |
# File 'lib/sunshine/app.rb', line 606 def deploy_details =nil details = {} with_server_apps , :msg => "Getting deploy info..." do |server_app| details[server_app.shell.host] = server_app.deploy_details end details end |
#deployed?(options = nil) ⇒ Boolean
Check if app has been deployed successfully by checking the name of the deploy on every app server with the instance’s deploy name.
621 622 623 624 625 626 627 628 |
# File 'lib/sunshine/app.rb', line 621 def deployed? =nil with_server_apps , :msg => "Checking deploy", :no_threads => true do |server_app| return false unless server_app.deployed? end true end |
#disconnect(options = nil) ⇒ Object
Disconnect from app servers. Supports any App#find options.
226 227 228 229 230 231 232 |
# File 'lib/sunshine/app.rb', line 226 def disconnect =nil Sunshine.logger.info :app, "Disconnecting..." do threaded_each do |server_app| server_app.shell.disconnect end end end |
#each(options = nil, &block) ⇒ Object
Iterate over each server app. Supports all App#find options. See Sunshine::ServerApp for more information.
635 636 637 638 |
# File 'lib/sunshine/app.rb', line 635 def each =nil, &block server_apps = find server_apps.each(&block) end |
#find(query = nil) ⇒ Object
Find server apps matching the passed requirements. Returns an array of server apps.
find :user => 'db'
find :host => 'someserver.com'
find :role => :web
The find method also supports passing arrays and will match any server app that matches any one condition:
find :user => ['root', 'john']
Returns all server apps who’s user is either ‘root’ or ‘john’.
654 655 656 657 658 659 660 661 662 663 664 665 |
# File 'lib/sunshine/app.rb', line 654 def find query=nil return @server_apps if query.nil? || query == :all @server_apps.select do |sa| next unless [*query[:user]].include? sa.shell.user if query[:user] next unless [*query[:host]].include? sa.shell.host if query[:host] next unless sa.has_roles?(query[:role], true) if query[:role] true end end |
#handle_exception(exception, state = {}) ⇒ Object
Calls the Apps on_exception hook or the default Sunshine.exception_behavior.
339 340 341 342 |
# File 'lib/sunshine/app.rb', line 339 def handle_exception exception, state={} return @on_exception.call(exception, state) if @on_exception handle_interruption Sunshine.exception_behavior, state end |
#handle_interruption(behavior, state = {}) ⇒ Object
Handles the behavior of a failed or interrupted deploy. Takes a behavior symbol defining how to handle the interruption and a hash representing the state of the deploy when it was interrupted.
Supported bahavior symbols are: ::revert: Revert to previous deploy (default) ::console: Start an interactive console with the app’s binding ::exit: Stop deploy and exit ::prompt: Ask what to do
The state hash supports the following keys: ::stopped: Was the previous deploy stopped. ::symlinked: Was the new deployed symlinked as the current deploy.
393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 |
# File 'lib/sunshine/app.rb', line 393 def handle_interruption behavior, state={} case behavior when :exit Sunshine.exit 1, "Error: Deploy of #{@name} failed" when :revert revert! if state[:symlinked] start if state[:stopped] when Sunshine.interactive? && :console self.console! when Sunshine.interactive? && :prompt Sunshine.shell.choose do || .prompt = "Deploy interrupted:" .choice(:revert) { handle_interruption :revert, state } .choice(:console){ handle_interruption :console, state } .choice(:exit) { handle_interruption :exit, state } end else raise DeployError, "Deploy of #{@name} was interrupted." end end |
#handle_sigint(state = {}) ⇒ Object
Calls the Apps on_sigint hook or the default Sunshine.sigint_behavior.
329 330 331 332 |
# File 'lib/sunshine/app.rb', line 329 def handle_sigint state={} return @on_sigint.call(state) if @on_sigint handle_interruption Sunshine.sigint_behavior, state end |
#install_deps(*deps) ⇒ Object
Install dependencies defined as a Sunshine dependency object:
rake = Sunshine.dependencies.gem 'rake', :version => '~>0.8'
apache = Sunshine.dependencies.yum 'apache'
app.install_deps rake, apache
Deploy servers can also be specified as a dispatcher, array, or single deploy server, by passing standard ‘find’ options:
postgres = Sunshine.dependencies.yum 'postgresql'
pgserver = Sunshine.dependencies.yum 'postgresql-server'
app.install_deps postgres, pgserver, :role => 'db'
If a dependency was already defined in the Sunshine dependency tree, the dependency name may be passed instead of the object:
app.install_deps 'nginx', 'ruby'
684 685 686 687 688 689 690 |
# File 'lib/sunshine/app.rb', line 684 def install_deps(*deps) = Hash === deps[-1] ? deps.delete_at(-1) : {} with_server_apps , :msg => "Installing dependencies: #{deps.map{|d| d.to_s}.join(" ")}", :send => [:install_deps, *deps] end |
#interruptable(options = {}) ⇒ Object
Runs the given block while handling SIGINTs and exceptions according to rules set by Sunshine.sigint_behavior and Sunshine.exception_behavior or with the override hooks App#on_sigint and App#on_exception.
306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 |
# File 'lib/sunshine/app.rb', line 306 def interruptable ={} interrupt_trap = TrapStack.add_trap "Interrupted #{@name}" do handle_sigint end yield if block_given? rescue => e Sunshine.logger.error :app, "#{e.class}: #{e.}" do Sunshine.logger.error '>>', e.backtrace.join("\n") end handle_exception e, ensure TrapStack.delete_trap interrupt_trap end |
#make_app_directories(options = nil) ⇒ Object
Creates the required application directories. Supports all App#find options.
697 698 699 700 701 |
# File 'lib/sunshine/app.rb', line 697 def make_app_directories =nil with_server_apps , :msg => "Creating #{@name} directories", :send => :make_app_directories end |
#on_exception(&block) ⇒ Object
Set this to define the behavior of exceptions during a deploy. Defines what to do when an exception is received when running a proc through App#interruptable. Used primarily to catch exceptions during deploys. Passes the block the exception and a hash with the state of the deploy:
app.on_exception do |exception, deploy_state_hash|
# do something...
end
372 373 374 |
# File 'lib/sunshine/app.rb', line 372 def on_exception &block @on_exception = block end |
#on_sigint(&block) ⇒ Object
Set this to define the behavior of SIGINT during a deploy. Defines what to do when an INT signal is received when running a proc through App#interruptable. Used primarily to catch SIGINTs during deploys. Passes the block a hash with the state of the deploy:
app.on_sigint do |deploy_state_hash|
deploy_state_hash
#=> {:stopped => true, :symlinked => true, :success => false}
end
356 357 358 |
# File 'lib/sunshine/app.rb', line 356 def on_sigint &block @on_sigint = block end |
#prefer_pkg_manager(pkg_manager, options = nil) ⇒ Object
712 713 714 715 |
# File 'lib/sunshine/app.rb', line 712 def prefer_pkg_manager pkg_manager, =nil with_server_apps , :send => [:pkg_manager=, pkg_manager] end |
#rake(command, options = nil) ⇒ Object
Run a rake task on any or all deploy servers. Supports all App#find options.
722 723 724 725 726 |
# File 'lib/sunshine/app.rb', line 722 def rake command, =nil with_server_apps , :msg => "Running Rake task '#{command}'", :send => [:rake, command] end |
#register_as_deployed(options = nil) ⇒ Object
Adds the app to the deploy servers deployed-apps list. Supports all App#find options.
733 734 735 736 737 |
# File 'lib/sunshine/app.rb', line 733 def register_as_deployed =nil with_server_apps , :msg => "Registering app with deploy servers", :send => :register_as_deployed end |
#remove_cronjob(name, options = nil) ⇒ Object
Remove a cron job from the remote crontabs:
remove_cronjob "reboot", :role => :web
remove_cronjob :all
#=> deletes all cronjobs related to this app
Supports all App#find options.
747 748 749 750 751 752 753 754 755 756 |
# File 'lib/sunshine/app.rb', line 747 def remove_cronjob name, =nil with_server_apps , :msg => "Removing cronjob #{name.inspect}" do |server_app| if name == :all server_app.crontab.clear else server_app.crontab.delete(name) end end end |
#remove_old_deploys(options = nil) ⇒ Object
Removes old deploys from the checkout_dir based on Sunshine’s max_deploy_versions. Supports all App#find options.
764 765 766 767 768 |
# File 'lib/sunshine/app.rb', line 764 def remove_old_deploys =nil with_server_apps , :msg => "Removing old deploys (max = #{Sunshine.max_deploy_versions})", :send => :remove_old_deploys end |
#restart(options = nil) ⇒ Object
Run the restart script of a deployed app on the specified deploy servers. Post-deploy only. Supports all App#find options.
776 777 778 779 780 |
# File 'lib/sunshine/app.rb', line 776 def restart =nil with_server_apps , :msg => "Running restart script", :send => :restart end |
#restart!(options = nil) ⇒ Object
Run the restart script of a deployed app on the specified deploy servers. Raises an exception on failure. Post-deploy only. Supports all App#find options.
788 789 790 791 792 |
# File 'lib/sunshine/app.rb', line 788 def restart! =nil with_server_apps , :msg => "Running restart script", :send => :restart! end |
#revert!(options = nil) ⇒ Object
Symlink current directory to previous checkout and remove the current deploy directory. Supports any App#find options.
app.revert! :role => :web
425 426 427 428 429 |
# File 'lib/sunshine/app.rb', line 425 def revert! =nil with_server_apps , :msg => "Reverting to previous deploy.", :send => :revert! end |
#run_bundler(options = nil) ⇒ Object
Runs bundler on deploy servers. Supports all App#find options.
798 799 800 801 802 |
# File 'lib/sunshine/app.rb', line 798 def run_bundler =nil with_server_apps , :msg => "Running Bundler", :send => [:run_bundler, ] end |
#run_geminstaller(options = nil) ⇒ Object
Runs GemInstaller on deploy servers. Supports all App#find options.
808 809 810 811 812 |
# File 'lib/sunshine/app.rb', line 808 def run_geminstaller =nil with_server_apps , :msg => "Running GemInstaller", :send => [:run_geminstaller, ] end |
#run_post_user_lambdas ⇒ Object
Run lambdas that were saved for after the user’s script. See #after_user_script.
819 820 821 822 823 |
# File 'lib/sunshine/app.rb', line 819 def run_post_user_lambdas Sunshine.logger.info :app, "Running post deploy lambdas" do with_session{ @post_user_lambdas.each{|l| l.call self} } end end |
#run_script(name, options = nil) ⇒ Object
Run the given script of a deployed app on the specified deploy servers. Post-deploy only. Supports all App#find options.
831 832 833 834 835 |
# File 'lib/sunshine/app.rb', line 831 def run_script name, =nil with_server_apps , :msg => "Running #{name} script", :send => [:run_script, name, ] end |
#run_script!(name, options = nil) ⇒ Object
Run the given script of a deployed app on the specified deploy servers. Raises an exception on failure. Post-deploy only. Supports all App#find options.
843 844 845 846 847 |
# File 'lib/sunshine/app.rb', line 843 def run_script! name, =nil with_server_apps , :msg => "Running #{name} script", :send => [:run_script!, name, ] end |
#sass(*sass_names) ⇒ Object
Run a sass task on any or all deploy servers. Supports all App#find options.
854 855 856 857 858 859 860 |
# File 'lib/sunshine/app.rb', line 854 def sass *sass_names = sass_names.delete_at(-1) if Hash === sass_names.last with_server_apps , :msg => "Running Sass for #{sass_names.join(' ')}", :send => [:sass, *sass_names] end |
#shell_env(env_hash = nil, options = nil) ⇒ Object
Set and return the remote shell env variables. Also assigns shell environment to the app’s deploy servers. Supports all App#find options.
868 869 870 871 872 873 874 875 876 877 878 879 880 881 |
# File 'lib/sunshine/app.rb', line 868 def shell_env env_hash=nil, =nil env_hash ||= {} @shell_env.merge!(env_hash) with_server_apps , :no_threads => true, :no_session => true, :msg => "Shell env: #{@shell_env.inspect}" do |server_app| server_app.shell_env.merge!(@shell_env) end @shell_env.dup end |
#start(options = nil) ⇒ Object
Run the start script of a deployed app on the specified deploy servers. Post-deploy only. Supports all App#find options.
889 890 891 892 893 |
# File 'lib/sunshine/app.rb', line 889 def start =nil with_server_apps , :msg => "Running start script", :send => [:start, ] end |
#start!(options = nil) ⇒ Object
Run the start script of a deployed app on the specified deploy servers. Raises an exception on failure. Post-deploy only. Supports all App#find options.
901 902 903 904 905 |
# File 'lib/sunshine/app.rb', line 901 def start! =nil with_server_apps , :msg => "Running start script", :send => [:start!, ] end |
#status(options = nil) ⇒ Object
Get a hash of which deploy server apps are :running or :down. Post-deploy only. Supports all App#find options.
912 913 914 915 916 917 918 919 920 |
# File 'lib/sunshine/app.rb', line 912 def status =nil statuses = {} with_server_apps , :msg => "Querying app status..." do |server_app| statuses[server_app.shell.host] = server_app.status end statuses end |
#stop(options = nil) ⇒ Object
Run the stop script of a deployed app on the specified deploy servers. Post-deploy only. Supports all App#find options.
928 929 930 931 932 |
# File 'lib/sunshine/app.rb', line 928 def stop =nil with_server_apps , :msg => "Running stop script", :send => :stop end |
#stop!(options = nil) ⇒ Object
Run the stop script of a deployed app on the specified deploy servers. Raises an exception on failure. Post-deploy only. Supports all App#find options.
940 941 942 943 944 |
# File 'lib/sunshine/app.rb', line 940 def stop! =nil with_server_apps , :msg => "Running stop script", :send => :stop! end |
#symlink_current_dir(options = nil) ⇒ Object
Creates a symlink to the app’s checkout path. Supports all App#find options.
967 968 969 970 971 |
# File 'lib/sunshine/app.rb', line 967 def symlink_current_dir =nil with_server_apps , :msg => "Symlinking #{@checkout_path} -> #{@current_path}", :send => :symlink_current_dir end |
#threaded_each(options = nil, &block) ⇒ Object
Iterate over all deploy servers but create a thread for each deploy server. Means you can’t return from the passed block! Calls App#each if Sunshine.use_threads? is false. Supports all App#find options.
980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 |
# File 'lib/sunshine/app.rb', line 980 def threaded_each =nil, &block return each , &block unless Sunshine.use_threads? mutex = Mutex.new threads = [] error = nil return_val = each() do |server_app| thread = Thread.new do server_app.shell.with_mutex mutex do begin yield server_app rescue => e error = e end end end threads << thread end threads.each{|t| t.join } raise error if error return_val end |
#with_filter(filter_hash) ⇒ Object
Execute a block with a specified server app filter:
app.with_filter :role => :cdn do |app|
app.sass 'file1', 'file2', 'file3'
app.rake 'asset:packager:build_all'
end
Supports all App#find options.
1020 1021 1022 1023 1024 1025 1026 1027 |
# File 'lib/sunshine/app.rb', line 1020 def with_filter filter_hash old_server_apps, @server_apps = @server_apps, find(filter_hash) yield self ensure @server_apps = old_server_apps end |
#with_server_apps(search_options, options = {}) ⇒ Object
Calls a method for server_apps found with the passed options, and with an optional log message. Will attempt to run the methods in a session to avoid multiple ssh login prompts. Supports all App#find options, plus:
- :no_threads
-
bool - disable threaded execution
- :no_session
-
bool - disable auto session creation
- :msg
-
“some message” - log message
app.with_server_apps :all, :msg => "doing something" do |server_app|
# do something here
end
app.with_server_apps :role => :db, :user => "bob" do |server_app|
# do something here
end
Note: App#with_server_apps calls App#with_session. If you do not need or want a server connection you can pass :no_session.
1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 |
# File 'lib/sunshine/app.rb', line 1050 def with_server_apps , ={} = .merge if Hash === = [:msg] method = [:no_threads] ? :each : :threaded_each auto_session = ![:no_session] block = lambda do |*| send(method, ) do |server_app| if block_given? yield(server_app) elsif [:send] server_app.send(*[:send]) end end end msg_block = lambda do |*| if Sunshine.logger.info(:app, , &block) else block.call end end auto_session ? with_session(&msg_block) : msg_block.call end |
#with_session(options = nil) ⇒ Object
Runs block ensuring a connection to remote_shells. Connecting and disconnecting will be ignored if a session already exists. Supports all App#find options.
Ensures that servers are disconnected after the block is run if servers were not previously connected.
1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 |
# File 'lib/sunshine/app.rb', line 1091 def with_session =nil with_filter do prev_connection = connected? begin connect unless prev_connection yield self ensure disconnect unless prev_connection end end end |