Class: SwitchTower::Configuration

Inherits:
Object
  • Object
show all
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

Instance Method Summary collapse

Constructor Details

#initialize(actor_class = Actor) ⇒ Configuration

:nodoc:



32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
# File 'lib/switchtower/configuration.rb', line 32

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,   Proc.new { "/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,    Proc.new { source.latest_revision }
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(sym, *args, &block) ⇒ Object

:nodoc:



193
194
195
196
197
198
199
# File 'lib/switchtower/configuration.rb', line 193

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

#actorObject (readonly)

The actor created for this configuration instance.



17
18
19
# File 'lib/switchtower/configuration.rb', line 17

def actor
  @actor
end

#load_pathsObject (readonly)

The load paths used for locating recipe files.



26
27
28
# File 'lib/switchtower/configuration.rb', line 26

def load_paths
  @load_paths
end

#loggerObject (readonly)

The logger instance defined for this configuration.



23
24
25
# File 'lib/switchtower/configuration.rb', line 23

def logger
  @logger
end

#nowObject (readonly)

The time (in UTC) at which this configuration was created, used for determining the release path.



30
31
32
# File 'lib/switchtower/configuration.rb', line 30

def now
  @now
end

#rolesObject (readonly)

The list of Role instances defined for this configuration.



20
21
22
# File 'lib/switchtower/configuration.rb', line 20

def roles
  @roles
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.



71
72
73
74
75
76
77
# File 'lib/switchtower/configuration.rb', line 71

def [](variable)
  if @variables[variable].respond_to?(:call)
    self[:original_value][variable] = @variables[variable]
    set variable, @variables[variable].call
  end
  @variables[variable]
end

#current_pathObject

Return the path identifying the current symlink, used to identify the current release.



174
175
176
# File 'lib/switchtower/configuration.rb', line 174

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.



149
150
151
# File 'lib/switchtower/configuration.rb', line 149

def desc(text)
  @next_description = text
end

#load(*args) ⇒ 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.


106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
# File 'lib/switchtower/configuration.rb', line 106

def load(*args)
  options = args.last.is_a?(Hash) ? args.pop : {}
  args.each { |arg| load options.merge(:file => arg) }

  if options[:file]
    file = options[: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 => options[:name] || file
  elsif options[:string]
    logger.debug "loading configuration #{options[:name] || "<eval>"}"
    instance_eval options[:string], options[:name] || "<eval>"
  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).



185
186
187
# File 'lib/switchtower/configuration.rb', line 185

def release_path(release=now.strftime("%Y%m%d%H%M%S"))
  File.join(releases_path, release)
end

#releases_pathObject

Return the path into which releases should be deployed.



168
169
170
# File 'lib/switchtower/configuration.rb', line 168

def releases_path
  File.join(deploy_to, version_dir)
end

#respond_to?(sym) ⇒ Boolean

:nodoc:

Returns:

  • (Boolean)


189
190
191
# File 'lib/switchtower/configuration.rb', line 189

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"

Raises:

  • (ArgumentError)


141
142
143
144
145
# File 'lib/switchtower/configuration.rb', line 141

def role(which, *args)
  options = 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, options) }
end

#set(variable, value) ⇒ Object Also known as: []=

Set a variable to the given value.



62
63
64
# File 'lib/switchtower/configuration.rb', line 62

def set(variable, value)
  @variables[variable] = value
end

#shared_pathObject

Return the path into which shared files should be stored.



179
180
181
# File 'lib/switchtower/configuration.rb', line 179

def shared_path
  File.join(deploy_to, shared_dir)
end

#sourceObject

Based on the current value of the :scm variable, instantiate and return an SCM module representing the desired source control behavior.



81
82
83
84
85
86
87
88
89
90
91
# File 'lib/switchtower/configuration.rb', line 81

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.

Raises:

  • (ArgumentError)


156
157
158
159
160
161
162
163
164
165
# File 'lib/switchtower/configuration.rb', line 156

def task(name, options={}, &block)
  raise ArgumentError, "expected a block" unless block

  if @next_description
    options = options.merge(:desc => @next_description)
    @next_description = nil
  end

  actor.define_task(name, options, &block)
end