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:



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

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

  set :application, nil
  set :repository,  nil
  set :gateway,     nil
  set :user,        nil
  set :password,    nil

  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:



185
186
187
188
189
190
191
# File 'lib/switchtower/configuration.rb', line 185

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.



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

def actor
  @actor
end

#load_pathsObject (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

#loggerObject (readonly)

The logger instance defined for this configuration.



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

def logger
  @logger
end

#nowObject (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

#rolesObject (readonly)

The list of Role instances defined for this configuration.



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

def roles
  @roles
end

Instance Method Details

#[](variable) ⇒ Object

Access a named variable. If the value of the variable is a Proc instance, the proc will be invoked and the return value cached and returned.



66
67
68
69
# File 'lib/switchtower/configuration.rb', line 66

def [](variable)
  set variable, @variables[variable].call if Proc === @variables[variable]
  @variables[variable]
end

#current_pathObject

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



166
167
168
# File 'lib/switchtower/configuration.rb', line 166

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.



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

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.


98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
# File 'lib/switchtower/configuration.rb', line 98

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).



177
178
179
# File 'lib/switchtower/configuration.rb', line 177

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.



160
161
162
# File 'lib/switchtower/configuration.rb', line 160

def releases_path
  File.join(deploy_to, version_dir)
end

#respond_to?(sym) ⇒ Boolean

:nodoc:

Returns:

  • (Boolean)


181
182
183
# File 'lib/switchtower/configuration.rb', line 181

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)


133
134
135
136
137
# File 'lib/switchtower/configuration.rb', line 133

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.



58
59
60
# File 'lib/switchtower/configuration.rb', line 58

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

#shared_pathObject

Return the path into which shared files should be stored.



171
172
173
# File 'lib/switchtower/configuration.rb', line 171

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.



73
74
75
76
77
78
79
80
81
82
83
# File 'lib/switchtower/configuration.rb', line 73

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)


148
149
150
151
152
153
154
155
156
157
# File 'lib/switchtower/configuration.rb', line 148

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