Class: ShadowPuppet::Manifest

Inherits:
Object
  • Object
show all
Defined in:
lib/shadow_puppet/test.rb,
lib/shadow_puppet/manifest.rb

Overview

A Manifest is an executable collection of Puppet Resources.

Example

class ManifestExample < ShadowPuppet::Manifest
  recipe :sample
  recipe :lamp, :ruby               # queue calls to self.lamp and
                                    # self.ruby when executing

  recipe :mysql, {                  # queue a call to self.mysql
    :root_password => 'OMGSEKRET'   # passing the provided hash
  }                                 # as an option

  def sample
    exec :foo, :command => 'echo "foo" > /tmp/foo.txt'

    package :foo, :ensure => :installed

    file '/tmp/example.txt',
      :ensure   => :present,
      :contents => Facter.to_hash_inspect,
      :require  => package(:foo)
  end

  def lamp
    # install a basic LAMP stack
  end

  def ruby
    # install a ruby interpreter and tools
  end

  def mysql(options)
     # install a mysql server and set the root password to options[:root_password]
  end

end

To execute the above manifest, instantiate it and call execute on it:

m = ManifestExample.new
m.execute

As shown in the sample method in ManifestExample above, instance methods are created for each Puppet::Type available on your system. These methods behave identally to the Puppet Resources methods. See here for documentation on these methods.

To view a list of all defined methods on your system, run:

ruby -rubygems -e 'require "shadow_puppet";puts ShadowPuppet::Manifest.puppet_type_methods'

The use of methods (sample, lamp, ruby, and mysql above) as a container for resources facilitates recipie re-use through the use of Ruby Modules. For example:

module ApachePuppet
  # Required options:
  #   domain
  #   path
  def php_vhost(options)
    #...
  end
 end

class MyWebMainfest < ShadowPuppet::Manifest
  include ApachePuppet
  recipe :php_vhost, {
    :domain => 'foo.com',
    :path => '/var/www/apps/foo'
  }
end

Direct Known Subclasses

Setup

Defined Under Namespace

Classes: Setup

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(config = {}) ⇒ Manifest

Initialize a new instance of this manifest. This can take a config hash, which is immediately passed on to the configure method



85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
# File 'lib/shadow_puppet/manifest.rb', line 85

def initialize(config = {})
  if Process.uid == 0
    Puppet[:confdir] = File.expand_path("/etc/shadow_puppet")
    Puppet[:vardir] = File.expand_path("/var/shadow_puppet")
  else
    Puppet[:confdir] = File.expand_path("~/.shadow_puppet")
    Puppet[:vardir] = File.expand_path("~/.shadow_puppet/var")
  end
  Puppet[:user] = Process.uid
  Puppet[:group] = Process.gid
  Puppet::Util::Log.newdestination(:console)
  Puppet[:diff_args] = "-u"

  configure(config)
  @executed = false
  @catalog = Puppet::Resource::Catalog.new
  @catalog.host_config = false
  @catalog.name = self.name
end

Instance Attribute Details

#catalogObject (readonly)

Returns the value of attribute catalog.



78
79
80
# File 'lib/shadow_puppet/manifest.rb', line 78

def catalog
  @catalog
end

Class Method Details

.configurationObject

A HashWithIndifferentAccess describing any configuration that has been performed on the class. Modify this hash by calling configure:

class SampleManifest < ShadowPuppet::Manifest
  configure(:name => 'test')
end

>> SampleManifest.configuration
=> {:name => 'test'}
 #

Subclasses of the Manifest class properly inherit the parent classes’ configuration.



146
147
148
# File 'lib/shadow_puppet/manifest.rb', line 146

def self.configuration
  __config__.with_indifferent_access
end

.configure(hash) ⇒ Object

Define configuration on this manifest. This is useful for storing things such as hostnames, password, or usernames that may change between different implementations of a shared manifest. Access this hash by calling configuration:

class SampleManifest < ShadowPuppet::Manifest
  configure('name' => 'test')
end

>> SampleManifest.configuration
=> {:name => 'test'}
 #

Subsequent calls to configure perform a deep_merge of the provided hash into the pre-existing configuration.



176
177
178
# File 'lib/shadow_puppet/manifest.rb', line 176

def self.configure(hash)
  __config__.replace(__config__.deep_symbolize_keys.deep_merge(hash.deep_symbolize_keys))
end

.puppet_type_methodsObject

An array of all methods defined for creation of Puppet Resources



195
196
197
# File 'lib/shadow_puppet/manifest.rb', line 195

def self.puppet_type_methods
  Puppet::Type.eachtype { |t| t.name }.keys.map { |n| n.to_s }.sort.inspect
end

.recipe(*methods) ⇒ Object

Declares that the named method or methods will be called whenever execute is called on an instance of this class. If the last argument is a Hash, this hash is passed as an argument to all provided methods. If no options hash is provided, each method is passed the contents of configuration[method].

Subclasses of the Manifest class properly inherit the parent classes’ calls to recipe.



113
114
115
116
117
118
119
120
121
# File 'lib/shadow_puppet/manifest.rb', line 113

def self.recipe(*methods)
  return nil if methods.nil? || methods == [] # TODO can probably replace with if methods.blank?
  options = methods.extract_options!
  methods.each do |meth|
    options = configuration[meth.to_sym] if options == {} # TODO can probably be replaced with options.blank?
    options ||= {}
    recipes << [meth.to_sym, options]
  end
end

.register_puppet_typesObject

Create an instance method for every type that either creates or references a resource



205
206
207
208
209
210
211
212
213
214
# File 'lib/shadow_puppet/manifest.rb', line 205

def self.register_puppet_types
  Puppet::Type.loadall
  Puppet::Type.eachtype do |type|
    # remove the method rdoc placeholders
    remove_method(type.name) rescue nil
    define_method(type.name) do |*args|
      resource_or_reference(type, *args)
    end
  end
end

.register_puppet_types_for_testingObject

Creates an instance method for every puppet type that either creates or references a resource



52
53
54
55
56
57
58
59
60
61
62
63
64
# File 'lib/shadow_puppet/test.rb', line 52

def self.register_puppet_types_for_testing
  Puppet::Type.loadall
  Puppet::Type.eachtype do |type|
    plural_type = type.name.to_s.downcase.pluralize
    #undefine the method rdoc placeholders
    undef_method(plural_type) rescue nil
    define_method(plural_type) do |*args|
      catalog.resources.select { |r| r.type == type.name }.inject({}) do |hash, resource|
        hash[resource.title] = resource; hash
      end
    end
  end
end

Instance Method Details

#configurationObject

Access to the configuration of the class of this instance.

class SampleManifest < ShadowPuppet::Manifest
  configure(:name => 'test')
end

@manifest = SampleManifest.new
@manifest.configuration[:name] => "test"


158
159
160
# File 'lib/shadow_puppet/manifest.rb', line 158

def configuration
  self.class.configuration
end

#configure(hash) ⇒ Object Also known as: configuration=

Update the configuration of this manifest instance’s class.

class SampleManifest < ShadowPuppet::Manifest
  configure({})
end

@manifest = SampleManifest.new
@manifest.configure(:name => "test")
@manifest.configuration[:name] => "test"


189
190
191
# File 'lib/shadow_puppet/manifest.rb', line 189

def configure(hash)
  self.class.configure(hash)
end

#executable?Boolean

Returns true if this Manifest respond_to? all methods named by calls to recipe, and if this Manifest has not been executed before.

Returns:

  • (Boolean)


219
220
221
222
223
224
225
# File 'lib/shadow_puppet/manifest.rb', line 219

def executable?
  self.class.recipes.each do |meth,args|
    return false unless respond_to?(meth)
  end
  return false if executed?
  true
end

#execute(force = false) ⇒ Object

Execute this manifest, applying all resources defined. Execute returns true if successfull, and false if unsucessfull. By default, this will only execute a manifest that has not already been executed?. The force argument, if true, removes this check.



237
238
239
240
241
242
243
244
245
246
247
# File 'lib/shadow_puppet/manifest.rb', line 237

def execute(force=false)
  return false if executed? && !force
  evaluate_recipes
  transaction = apply
rescue Exception => e
  false
else
  not transaction.any_failed?
ensure
  @executed = true
end

#execute!(force = false) ⇒ Object

Execute this manifest, applying all resources defined. Execute returns true if successfull, and raises an exception if not. By default, this will only execute a manifest that has not already been executed?. The force argument, if true, removes this check.



253
254
255
256
257
258
259
260
261
262
263
# File 'lib/shadow_puppet/manifest.rb', line 253

def execute!(force=false)
  return false if executed? && !force
  evaluate_recipes
  transaction = apply
rescue Exception => e
  raise e
else
  not transaction.any_failed?
ensure
  @executed = true
end

#graph_to(name, destination) ⇒ Object



265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
# File 'lib/shadow_puppet/manifest.rb', line 265

def graph_to(name, destination)
  evaluate_recipes

  relationship_graph = @catalog.relationship_graph

  graph = relationship_graph.to_dot_graph("name" => "#{name} Relationships".gsub(/\W+/, '_'))
  graph.options['label'] = "#{name} Relationships"

  # The graph ends up having all of the edges backwards
  graph.each_node do |node|
    next unless node.is_a?(DOT::DOTEdge)
    node.to, node.from = node.from, node.to
  end

  File.open(destination, "w") { |f|
      f.puts graph.to_s
  }
end

#missing_recipesObject



227
228
229
230
231
# File 'lib/shadow_puppet/manifest.rb', line 227

def missing_recipes
  missing = self.class.recipes.each do |meth,args|
    !respond_to?(meth)
  end
end

#nameObject



199
200
201
# File 'lib/shadow_puppet/manifest.rb', line 199

def name
  @name ||= "#{self.class}##{self.object_id}"
end

#recipe(*methods) ⇒ Object

Access to a recipe of the class of this instance.

class SampleManifest < ShadowPuppet::Manifest
  def my_recipe
    recipe :other_recipe
  end
end


130
131
132
# File 'lib/shadow_puppet/manifest.rb', line 130

def recipe(*methods)
  self.class.recipe *methods
end