Class: Furnish::Provisioner::Vagrant

Inherits:
API
  • Object
show all
Defined in:
lib/furnish/provisioners/vagrant.rb

Overview

Vagrant provisioner; this allows our existing vagrant needs to be satisified with Furnish.

Uses Vagrant::Prison to accomplish sandboxing of Vagrant itself.

A box or box_url must be supplied in the constructor. A number of servers must also be supplied, but will default to 1.

During provisioning, the startup method is expected to get a list of IP addresses to configure vagrant’s boxes with as a part of a host-only network. If the number of servers and the number of IP addresses received are not equal, provisioning will fail.

See Furnish::IP (furnish-ip) gem for a provisioner which can be used to deal with IP allocation and vagrant.

Instance Method Summary collapse

Constructor Details

#initialize(args) ⇒ Vagrant

Construct a new vagrant provisioner – takes a hash of arguments.

args:

  • :box - name of vagrant box

  • :box_url - url of vagrant box to download. box or box_url must exist.

  • :number_of_servers - integer value of servers to exist.

  • :db_name - this is a tag used to create the database where the Vagrant::Prison objects will be stored. “default” by default, intended for more advanced uses.

  • :customziations - an array of arguments that would go to vm.customize. If an array of arrays are supplied, vm.customize is called for each inner array with it as the argument.



112
113
114
115
116
117
118
119
120
121
# File 'lib/furnish/provisioners/vagrant.rb', line 112

def initialize(args)
  super

  normalize_box_args
  normalize_customizations

  @db_name            ||= "default"
  @number_of_servers  ||= 1
  @db                   = Palsy::Map.new('vm_prisons', @db_name)
end

Instance Method Details

#boxObject

:attr: box

Specified a vagrant box name. Will be used for all VMs, will be used from #box_url if unset.



44
45
46
# File 'lib/furnish/provisioners/vagrant.rb', line 44

furnish_property :box,
"Vagrant's box argument. Will be extracted from box_url if unset.",
String

#box_urlObject

:attr: box_url

Specifies vagrant’s box_url. If specified, and #box is not, #box will be extracted from this value.

Boxes will be downloaded on demand if they do not already exist.



34
35
36
# File 'lib/furnish/provisioners/vagrant.rb', line 34

furnish_property :box_url,
"Vagrant's box_url argument",
String

#customizationsObject

:attr: customizations

An array of strings, or array of array of strings, which are passed to vagrant’s vm.customize for each block. These are usually parameters passed directly to VBoxManage.

Example:

# one customization
Furnish::Provisioners::Vagrant.new(
  :customizations => ["modifyvm", :id, "--memory", 1024]
)

# multiple customizations
Furnish::Provisioners::Vagrant.new(
  :customizations => [
    [ "modifyvm", :id, "--memory", 1024 ]
    [ "modifyvm", :id, "--cpus", 4 ]
  ]
)


92
93
94
# File 'lib/furnish/provisioners/vagrant.rb', line 92

furnish_property :customizations,
"an array of arguments that would go to vm.customize. If an array of arrays are supplied, vm.customize is called for each inner array with it as the argument.",
Array

#db_nameObject

:attr: db_name

A tag that namespaces the VMs provisioned here.

The default is “default”.



66
67
68
# File 'lib/furnish/provisioners/vagrant.rb', line 66

furnish_property :db_name,
"'default' by default, a tag namespacing this set of provisions",
String

#normalize_box_argsObject

Helper method to coerce box and box_url into something normal.



141
142
143
144
145
146
147
148
149
# File 'lib/furnish/provisioners/vagrant.rb', line 141

def normalize_box_args
  if box_url
    @box = File.basename(box_url).gsub(/\.box$/, '')
  end

  unless box
    raise ArgumentError, "#{self.class} must be configured with a box or box_url."
  end
end

#normalize_customizationsObject

Helper method to structure supplied customizations.



126
127
128
129
130
131
132
133
134
135
136
# File 'lib/furnish/provisioners/vagrant.rb', line 126

def normalize_customizations
  if customizations
    unless customizations.kind_of?(Array)
      raise ArgumentError, "customizations must be an array of customizations, or array of array of multiple customizations."
    end

    unless customizations.all? { |x| x.kind_of?(Array) }
      @customizations = [customizations]
    end
  end
end

#number_of_serversObject

:attr: number_of_servers

The integer number of boxes to bring up for this provision.

Takes a list of IPs from a previous provisioner’s :ips result. This :ips does not yield a count that matches this number, provisioning will fail.



56
57
58
# File 'lib/furnish/provisioners/vagrant.rb', line 56

furnish_property :number_of_servers,
"The number of boxes to bring up for this provision",
Integer

#reportObject

Report the information on this provisioner. Number of servers and the prison directory used for this provision.



213
214
215
# File 'lib/furnish/provisioners/vagrant.rb', line 213

def report
  ["#{number_of_servers} servers", "prison dir: #{@prison.dir || "unprovisioned"}"]
end

#shutdown(args = {}) ⇒ Object

Deprovision with Vagrant.



197
198
199
200
201
202
203
204
205
206
207
# File 'lib/furnish/provisioners/vagrant.rb', line 197

def shutdown(args={})
  @prison ||= @db[furnish_group_name]

  if @prison
    @prison.configure_environment(:ui_class => Furnish::Vagrant::UI)
    @prison.cleanup
  end

  @db.delete(furnish_group_name)
  return { }
end

#startup(args = {}) ⇒ Object

Provision with vagrant. Expects a set of IP addresses used as its arguments.

During provisioning, the startup method is expected to get a set of IP addresses via :ips to configure vagrant’s boxes with as a part of a host-only network. If the number of servers and the number of IP addresses received are not equal, provisioning will fail.



160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
# File 'lib/furnish/provisioners/vagrant.rb', line 160

def startup(args={})
  ips = args[:ips]

  if ips.count != number_of_servers
    raise "The number of requested IP addresses does not match the number of requested servers"
  end

  @prison = ::Vagrant::Prison.new(Dir.mktmpdir, false)

  @prison.name = furnish_group_name

  @prison.configure do |config|
    config.vm.box_url = box_url
    config.vm.box = box

    if customizations
      customizations.each { |c| config.vm.customize c }
    end

    ips.each_with_index do |ip, x|
      config.vm.define "#{furnish_group_name}-#{x}" do |this_config|
        this_config.vm.network :hostonly, ip
      end
    end
  end

  @prison.construct(:ui_class => Furnish::Vagrant::UI)
  @db[furnish_group_name] = @prison # eager save in case start has issues

  return @prison.start ? { } : false
ensure
  @db[furnish_group_name] = @prison
end