Class: Pot::Package

Inherits:
Object
  • Object
show all
Defined in:
lib/pot/package.rb

Overview

Packages

A package defines one or more things to provision onto the server. There is a lot of flexibility in a way a package is defined but let me give you a basic example:

package :ruby do
  description 'Ruby MRI'
  version '1.8.6'
  apt 'ruby'

  verify { has_executable 'ruby' }
end

The above would define a package named ‘ruby’ and give it a description and explicitly say its version. It is installed via apt and to verify the installation was successful pot will check for the executable ‘ruby’ being availble. Pretty simple, right?

Note: Defining a package does not INSTALL it. To install a package, you must require it in a Pot::Policy block.

Pre-Requirements

Most packages have some sort of pre-requisites in order to be installed. Pot allows you to define the requirements of the package, which will be installed before the package itself. An example below:

package :rubygems do
  source 'http://rubyforge.org/rubygems.tgz'
  requires :ruby
end

In this case, when rubygems is being installed, Pot will first provision the server with Ruby to make sure the requirements are met. In turn, if ruby has requirements, it installs those first, and so on.

Verifications

Most of the time its important to know whether the software you’re attempting to install was installed successfully or not. For this, Pot provides verifications. Verifications are one or more blocks which define rules with which Pot can check if it installed the package successfully. If these verification blocks fail, then Pot will gracefully stop the entire process. An example below:

package :rubygems do
  source 'http://rubyforge.org/rubygems.tgz'
  requires :ruby

  verify { has_executable 'gem' }
end

In addition to verifying an installation was successfully, by default Pot runs these verifications before the installation to check if the package is already installed. If the verifications pass before installing the package, it skips the package. To override this behavior, set the -f flag on the sprinkle script or set the :force option to true in Pot.config

For more information on verifications and to see all the available verifications, see Pot::Verify

Virtual Packages

Sometimes, there are multiple packages available for a single task. An example is a database package. It can contain mySQL, postgres, or sqlite! This is where virtual packages come in handy. They are defined as follows:

package :sqlite3, :provides => :database do
  apt 'sqlite3'
end

The :provides option allows you to reference this package either by :sqlite3 or by :database. But whereas the package name is unique, multiple packages may share the same provision. If this is the case, when running Pot, the script will ask you which provision you want to install. At this time, you can only install one.

Meta-Packages

A package doesn’t require an installer. If you want to define a package which merely encompasses other packages, that is fine too. Example:

package :meta do
  requires :magic_beans
  requires :magic_sauce
end

– FIXME: Should probably document recommendations. ++

Constant Summary collapse

REGISTER =
{}

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(name, metadata = {}, &block) ⇒ Package

Returns a new instance of Package.



104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
# File 'lib/pot/package.rb', line 104

def initialize(name,  = {}, &block)
  raise 'No package name supplied' unless name

  @name = name
  @provides = [:provides]
  @dependencies = []
  @recommends = []
  @optional = []
  @verifications = []
  @installers = []

  REGISTER[name] = self

  if @provides
    (REGISTER[@provides] ||= []) << self
  end

  self.instance_eval &block
end

Instance Attribute Details

#dependenciesObject

Returns the value of attribute dependencies.



97
98
99
# File 'lib/pot/package.rb', line 97

def dependencies
  @dependencies
end

#installersObject

Returns the value of attribute installers.



97
98
99
# File 'lib/pot/package.rb', line 97

def installers
  @installers
end

#nameObject

Returns the value of attribute name.



97
98
99
# File 'lib/pot/package.rb', line 97

def name
  @name
end

#providesObject

Returns the value of attribute provides.



97
98
99
# File 'lib/pot/package.rb', line 97

def provides
  @provides
end

#recommends(*packages) ⇒ Object

Returns the value of attribute recommends.



97
98
99
# File 'lib/pot/package.rb', line 97

def recommends
  @recommends
end

#verificationsObject

Returns the value of attribute verifications.



97
98
99
# File 'lib/pot/package.rb', line 97

def verifications
  @verifications
end

Instance Method Details

#add_group(group, options = {}, &block) ⇒ Object



142
143
144
# File 'lib/pot/package.rb', line 142

def add_group(group, options={},  &block)
  @installers << Pot::Installers::Group.new(self, group, options, &block)
end

#add_user(username, options = {}, &block) ⇒ Object



138
139
140
# File 'lib/pot/package.rb', line 138

def add_user(username, options={},  &block)
  @installers << Pot::Installers::User.new(self, username, options, &block)
end

#apt(*names, &block) ⇒ Object



170
171
172
# File 'lib/pot/package.rb', line 170

def apt(*names, &block)
  @installers << Pot::Installers::Apt.new(self, *names, &block)
end

#binary(source, options = {}, &block) ⇒ Object



204
205
206
# File 'lib/pot/package.rb', line 204

def binary(source, options = {}, &block)
  @installers << Pot::Installers::Binary.new(self, source, options, &block)
end

#brew(*names, &block) ⇒ Object



190
191
192
# File 'lib/pot/package.rb', line 190

def brew(*names, &block)
  @installers << Pot::Installers::Brew.new(self, *names, &block)
end

#bsd_port(port, &block) ⇒ Object



162
163
164
# File 'lib/pot/package.rb', line 162

def bsd_port(port, &block)
  @installers << Pot::Installers::BsdPort.new(self, port, &block)
end

#deb(*names, &block) ⇒ Object



174
175
176
# File 'lib/pot/package.rb', line 174

def deb(*names, &block)
  @installers << Pot::Installers::Deb.new(self, *names, &block)
end

#description(desc = nil) ⇒ Object



124
125
126
127
# File 'lib/pot/package.rb', line 124

def description(desc = nil)
  @description = desc if desc
  @description
end

#freebsd_pkg(*names, &block) ⇒ Object



146
147
148
# File 'lib/pot/package.rb', line 146

def freebsd_pkg(*names, &block)
  @installers << Pot::Installers::FreebsdPkg.new(self, *names, &block)
end

#freebsd_portinstall(port, &block) ⇒ Object



150
151
152
# File 'lib/pot/package.rb', line 150

def freebsd_portinstall(port, &block)
  @installers << Pot::Installers::FreebsdPortinstall.new(self, port, &block)
end

#gem(name, options = {}, &block) ⇒ Object



194
195
196
197
# File 'lib/pot/package.rb', line 194

def gem(name, options = {}, &block)
  @recommends << :rubygems
  @installers << Pot::Installers::Gem.new(self, name, options, &block)
end

#mac_port(port, &block) ⇒ Object



166
167
168
# File 'lib/pot/package.rb', line 166

def mac_port(port, &block)
  @installers << Pot::Installers::MacPort.new(self, port, &block)
end

#noop(&block) ⇒ Object



216
217
218
# File 'lib/pot/package.rb', line 216

def noop(&block)
  @installers << Pot::Installers::Runner.new(self, "echo noop", &block)
end

#openbsd_pkg(*names, &block) ⇒ Object



154
155
156
# File 'lib/pot/package.rb', line 154

def openbsd_pkg(*names, &block)
  @installers << Pot::Installers::OpenbsdPkg.new(self, *names, &block)
end

#opensolaris_pkg(*names, &block) ⇒ Object



158
159
160
# File 'lib/pot/package.rb', line 158

def opensolaris_pkg(*names, &block)
  @installers << Pot::Installers::OpensolarisPkg.new(self, *names, &block)
end

#optional(*packages) ⇒ Object



292
293
294
295
# File 'lib/pot/package.rb', line 292

def optional(*packages)
  @optional << packages
  @optional.flatten!
end

#pacman(*names, &block) ⇒ Object



240
241
242
# File 'lib/pot/package.rb', line 240

def pacman(*names, &block)
  @installers << Pot::Installers::Pacman.new(self, *names, &block)
end

#process(actor) ⇒ Object



244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
# File 'lib/pot/package.rb', line 244

def process(actor)
  Pot.logger.info "  * #{name}"
  return if meta_package?

  # Run a pre-test to see if the software is already installed. If so,
  # we can skip it, unless we have the force option turned on!
  unless @verifications.empty? || Pot.config.force
    begin
      process_verifications(actor, true)

      Pot.logger.info "--> #{self.name} already installed"
      return
    rescue Pot::VerificationFailed => e
      # Continue
    end
  end

  @installers.each do |installer|
    installer.process(actor)
  end

  process_verifications(actor)
end

#process_verifications(actor, pre = false) ⇒ Object



268
269
270
271
272
273
274
275
276
277
278
279
280
# File 'lib/pot/package.rb', line 268

def process_verifications(actor, pre = false)
  return if @verifications.empty?

  if pre
    Pot.logger.info "--> Checking if #{self.name} is already installed"
  else
    Pot.logger.info "--> Verifying #{self.name} was properly installed"
  end

  @verifications.each do |v|
    v.process(actor)
  end
end

#push_text(text, path, options = {}, &block) ⇒ Object



220
221
222
# File 'lib/pot/package.rb', line 220

def push_text(text, path, options = {}, &block)
  @installers << Pot::Installers::PushText.new(self, text, path, options, &block)
end

#rake(name, options = {}, &block) ⇒ Object



208
209
210
# File 'lib/pot/package.rb', line 208

def rake(name, options = {}, &block)
  @installers << Pot::Installers::Rake.new(self, name, options, &block)
end

#replace_text(regex, text, path, options = {}, &block) ⇒ Object



224
225
226
# File 'lib/pot/package.rb', line 224

def replace_text(regex, text, path, options={}, &block)
  @installers << Pot::Installers::ReplaceText.new(self, regex, text, path, options, &block)
end

#requires(*packages) ⇒ Object



282
283
284
285
# File 'lib/pot/package.rb', line 282

def requires(*packages)
  @dependencies << packages
  @dependencies.flatten!
end

#rpm(*names, &block) ⇒ Object



178
179
180
# File 'lib/pot/package.rb', line 178

def rpm(*names, &block)
  @installers << Pot::Installers::Rpm.new(self, *names, &block)
end

#runner(cmd, options = {}, &block) ⇒ Object



232
233
234
# File 'lib/pot/package.rb', line 232

def runner(cmd, options = {}, &block)
	@installers << Pot::Installers::Runner.new(self, cmd, options, &block)
end

#source(source, options = {}, &block) ⇒ Object



199
200
201
202
# File 'lib/pot/package.rb', line 199

def source(source, options = {}, &block)
  @recommends << :build_essential # Ubuntu/Debian
  @installers << Pot::Installers::Source.new(self, source, options, &block)
end

#template(name) ⇒ Object



134
135
136
# File 'lib/pot/package.rb', line 134

def template(name)
  Pot::Template.new(self, name)
end

#thor(name, options = {}, &block) ⇒ Object



212
213
214
# File 'lib/pot/package.rb', line 212

def thor(name, options = {}, &block)
  @installers << Pot::Installers::Thor.new(self, name, options, &block)
end

#to_sObject



328
# File 'lib/pot/package.rb', line 328

def to_s; @name; end

#transfer(source, destination, options = {}, &block) ⇒ Object



228
229
230
# File 'lib/pot/package.rb', line 228

def transfer(source, destination, options = {}, &block)
  @installers << Pot::Installers::Transfer.new(self, source, destination, options, &block)
end

#tree(depth = 1, &block) ⇒ Object



297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
# File 'lib/pot/package.rb', line 297

def tree(depth = 1, &block)
  packages = []

  @recommends.each do |dep|
    package = REGISTER[dep]
    next unless package # skip missing recommended packages as they're allowed to not exist
    block.call(self, package, depth) if block
    packages << package.tree(depth + 1, &block)
  end

  @dependencies.each do |dep|
    package = REGISTER[dep]
    package = select_package(dep, package) if package.is_a? Array

    raise "Package definition not found for key: #{dep}" unless package
    block.call(self, package, depth) if block
    packages << package.tree(depth + 1, &block)
  end

  packages << self

  @optional.each do |dep|
    package = REGISTER[dep]
    next unless package # skip missing optional packages as they're allow to not exist
    block.call(self, package, depth) if block
    packages << package.tree(depth + 1, &block)
  end

  packages
end

#verify(description = '', &block) ⇒ Object



236
237
238
# File 'lib/pot/package.rb', line 236

def verify(description = '', &block)
  @verifications << Pot::Verify.new(self, description, &block)
end

#version(ver = nil) ⇒ Object



129
130
131
132
# File 'lib/pot/package.rb', line 129

def version(ver = nil)
  @version = ver if ver
  @version
end

#yum(*names, &block) ⇒ Object



182
183
184
# File 'lib/pot/package.rb', line 182

def yum(*names, &block)
  @installers << Pot::Installers::Yum.new(self, *names, &block)
end

#zypper(*names, &block) ⇒ Object



186
187
188
# File 'lib/pot/package.rb', line 186

def zypper(*names, &block)
  @installers << Pot::Installers::Zypper.new(self, *names, &block)
end