Class: SwitchTower::Configuration
- Inherits:
-
Object
- Object
- SwitchTower::Configuration
- Defined in:
- lib/switchtower/configuration.rb
Overview
Represents a specific SwitchTower configuration. A Configuration instance may be used to load multiple recipe files, define and describe tasks, define roles, create an actor, and set configuration variables.
Defined Under Namespace
Classes: Role
Constant Summary collapse
- DEFAULT_VERSION_DIR_NAME =
:nodoc:
"releases"
- DEFAULT_CURRENT_DIR_NAME =
:nodoc:
"current"
- DEFAULT_SHARED_DIR_NAME =
:nodoc:
"shared"
Instance Attribute Summary collapse
-
#actor ⇒ Object
readonly
The actor created for this configuration instance.
-
#load_paths ⇒ Object
readonly
The load paths used for locating recipe files.
-
#logger ⇒ Object
readonly
The logger instance defined for this configuration.
-
#now ⇒ Object
readonly
The time (in UTC) at which this configuration was created, used for determining the release path.
-
#roles ⇒ Object
readonly
The list of Role instances defined for this configuration.
-
#variables ⇒ Object
readonly
The has of variables currently known by the configuration.
Instance Method Summary collapse
-
#[](variable) ⇒ Object
Access a named variable.
-
#current_path ⇒ Object
Return the path identifying the
current
symlink, used to identify the current release. -
#desc(text) ⇒ Object
Describe the next task to be defined.
-
#initialize(actor_class = Actor) ⇒ Configuration
constructor
:nodoc:.
-
#load(*args, &block) ⇒ Object
Load a configuration file or string into this configuration.
-
#method_missing(sym, *args, &block) ⇒ Object
:nodoc:.
-
#release_path(release = now.strftime("%Y%m%d%H%M%S")) ⇒ Object
Return the full path to the named release.
-
#releases_path ⇒ Object
Return the path into which releases should be deployed.
-
#require(*args) ⇒ Object
Require another file.
-
#respond_to?(sym) ⇒ Boolean
:nodoc:.
-
#role(which, *args) ⇒ Object
Define a new role and its associated servers.
-
#set(variable, value = nil, &block) ⇒ Object
(also: #[]=)
Set a variable to the given value.
-
#shared_path ⇒ Object
Return the path into which shared files should be stored.
-
#source ⇒ Object
Based on the current value of the
:scm
variable, instantiate and return an SCM module representing the desired source control behavior. -
#task(name, options = {}, &block) ⇒ Object
Define a new task.
Constructor Details
#initialize(actor_class = Actor) ⇒ Configuration
:nodoc:
36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 |
# File 'lib/switchtower/configuration.rb', line 36 def initialize(actor_class=Actor) #:nodoc: @roles = Hash.new { |h,k| h[k] = [] } @actor = actor_class.new(self) @logger = Logger.new @load_paths = [".", File.join(File.dirname(__FILE__), "recipes")] @variables = {} @now = Time.now.utc # for preserving the original value of Proc-valued variables set :original_value, Hash.new set :application, nil set :repository, nil set :gateway, nil set :user, nil set :password, nil set :ssh_options, Hash.new set(:deploy_to) { "/u/apps/#{application}" } set :version_dir, DEFAULT_VERSION_DIR_NAME set :current_dir, DEFAULT_CURRENT_DIR_NAME set :shared_dir, DEFAULT_SHARED_DIR_NAME set :scm, :subversion set(:revision) { source.latest_revision } end |
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(sym, *args, &block) ⇒ Object
:nodoc:
235 236 237 238 239 240 241 |
# File 'lib/switchtower/configuration.rb', line 235 def method_missing(sym, *args, &block) #:nodoc: if args.length == 0 && block.nil? && @variables.has_key?(sym) self[sym] else super end end |
Instance Attribute Details
#actor ⇒ Object (readonly)
The actor created for this configuration instance.
18 19 20 |
# File 'lib/switchtower/configuration.rb', line 18 def actor @actor end |
#load_paths ⇒ Object (readonly)
The load paths used for locating recipe files.
27 28 29 |
# File 'lib/switchtower/configuration.rb', line 27 def load_paths @load_paths end |
#logger ⇒ Object (readonly)
The logger instance defined for this configuration.
24 25 26 |
# File 'lib/switchtower/configuration.rb', line 24 def logger @logger end |
#now ⇒ Object (readonly)
The time (in UTC) at which this configuration was created, used for determining the release path.
31 32 33 |
# File 'lib/switchtower/configuration.rb', line 31 def now @now end |
#roles ⇒ Object (readonly)
The list of Role instances defined for this configuration.
21 22 23 |
# File 'lib/switchtower/configuration.rb', line 21 def roles @roles end |
#variables ⇒ Object (readonly)
The has of variables currently known by the configuration
34 35 36 |
# File 'lib/switchtower/configuration.rb', line 34 def variables @variables end |
Instance Method Details
#[](variable) ⇒ Object
Access a named variable. If the value of the variable responds_to? :call, #call will be invoked (without parameters) and the return value cached and returned.
85 86 87 88 89 90 91 |
# File 'lib/switchtower/configuration.rb', line 85 def [](variable) if @variables[variable].respond_to?(:call) self[:original_value][variable] = @variables[variable] set variable, @variables[variable].call end @variables[variable] end |
#current_path ⇒ Object
Return the path identifying the current
symlink, used to identify the current release.
216 217 218 |
# File 'lib/switchtower/configuration.rb', line 216 def current_path File.join(deploy_to, current_dir) end |
#desc(text) ⇒ Object
Describe the next task to be defined. The given text will be attached to the next task that is defined and used as its description.
179 180 181 |
# File 'lib/switchtower/configuration.rb', line 179 def desc(text) @next_description = text end |
#load(*args, &block) ⇒ Object
Load a configuration file or string into this configuration.
Usage:
load("recipe"):
Look for and load the contents of 'recipe.rb' into this
configuration.
load(:file => "recipe"):
same as above
load(:string => "set :scm, :subversion"):
Load the given string as a configuration specification.
load { ... }
Load the block in the context of the configuration.
123 124 125 126 127 128 129 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 |
# File 'lib/switchtower/configuration.rb', line 123 def load(*args, &block) = args.last.is_a?(Hash) ? args.pop : {} args.each { |arg| load .merge(:file => arg) } return unless args.empty? if block raise "loading a block requires 0 parameters" unless args.empty? load(.merge(:proc => block)) elsif [:file] file = [:file] unless file[0] == ?/ load_paths.each do |path| if File.file?(File.join(path, file)) file = File.join(path, file) break elsif File.file?(File.join(path, file) + ".rb") file = File.join(path, file + ".rb") break end end end load :string => File.read(file), :name => [:name] || file elsif [:string] logger.trace "loading configuration #{[:name] || "<eval>"}" instance_eval([:string], [:name] || "<eval>") elsif [:proc] logger.trace "loading configuration #{[:proc].inspect}" instance_eval(&[:proc]) else raise ArgumentError, "don't know how to load #{.inspect}" end end |
#release_path(release = now.strftime("%Y%m%d%H%M%S")) ⇒ Object
Return the full path to the named release. If a release is not specified, now
is used (the time at which the configuration was created).
227 228 229 |
# File 'lib/switchtower/configuration.rb', line 227 def release_path(release=now.strftime("%Y%m%d%H%M%S")) File.join(releases_path, release) end |
#releases_path ⇒ Object
Return the path into which releases should be deployed.
210 211 212 |
# File 'lib/switchtower/configuration.rb', line 210 def releases_path File.join(deploy_to, version_dir) end |
#require(*args) ⇒ Object
Require another file. This is identical to the standard require method, with the exception that it sets the reciever as the “current” configuration so that third-party task bundles can include themselves relative to that configuration.
201 202 203 204 205 206 207 |
# File 'lib/switchtower/configuration.rb', line 201 def require(*args) #:nodoc: original, SwitchTower.configuration = SwitchTower.configuration, self super ensure # restore the original, so that require's can be nested SwitchTower.configuration = original end |
#respond_to?(sym) ⇒ Boolean
:nodoc:
231 232 233 |
# File 'lib/switchtower/configuration.rb', line 231 def respond_to?(sym) #:nodoc: @variables.has_key?(sym) || super end |
#role(which, *args) ⇒ Object
Define a new role and its associated servers. You must specify at least one host for each role. Also, you can specify additional information (in the form of a Hash) which can be used to more uniquely specify the subset of servers specified by this specific role definition.
Usage:
role :db, "db1.example.com", "db2.example.com"
role :db, "master.example.com", :primary => true
role :app, "app1.example.com", "app2.example.com"
171 172 173 174 175 |
# File 'lib/switchtower/configuration.rb', line 171 def role(which, *args) = args.last.is_a?(Hash) ? args.pop : {} raise ArgumentError, "must give at least one host" if args.empty? args.each { |host| roles[which] << Role.new(host, ) } end |
#set(variable, value = nil, &block) ⇒ Object Also known as: []=
Set a variable to the given value.
66 67 68 69 70 71 72 73 74 75 76 77 78 |
# File 'lib/switchtower/configuration.rb', line 66 def set(variable, value=nil, &block) # if the variable is uppercase, then we add it as a constant to the # actor. This is to allow uppercase "variables" to be set and referenced # in recipes. if variable.to_s[0].between?(?A, ?Z) klass = @actor. klass.send(:remove_const, variable) if klass.const_defined?(variable) klass.const_set(variable, value) end value = block if value.nil? && block_given? @variables[variable] = value end |
#shared_path ⇒ Object
Return the path into which shared files should be stored.
221 222 223 |
# File 'lib/switchtower/configuration.rb', line 221 def shared_path File.join(deploy_to, shared_dir) end |
#source ⇒ Object
Based on the current value of the :scm
variable, instantiate and return an SCM module representing the desired source control behavior.
95 96 97 98 99 100 101 102 103 104 105 |
# File 'lib/switchtower/configuration.rb', line 95 def source @source ||= case scm when Class then scm.new(self) when String, Symbol then require "switchtower/scm/#{scm.to_s.downcase}" SwitchTower::SCM.const_get(scm.to_s.downcase.capitalize).new(self) else raise "invalid scm specification: #{scm.inspect}" end end |
#task(name, options = {}, &block) ⇒ Object
Define a new task. If a description is active (see #desc), it is added to the options under the :desc
key. This method ultimately delegates to Actor#define_task.
186 187 188 189 190 191 192 193 194 195 |
# File 'lib/switchtower/configuration.rb', line 186 def task(name, ={}, &block) raise ArgumentError, "expected a block" unless block if @next_description = .merge(:desc => @next_description) @next_description = nil end actor.define_task(name, , &block) end |