class Chef::RunContext

Chef::RunContext

Value object that loads and tracks the context of a Chef run

Attributes

cookbook_collection[R]
definitions[R]

Resource Definitions for this run. Populated when the files in definitions/ are evaluated (this is triggered by load).

delayed_notification_collection[RW]

A Hash containing the delayed (end of run) notifications triggered by resources during the converge phase of the chef run.

events[R]

Event dispatcher for this run.

immediate_notification_collection[RW]

A Hash containing the immediate notifications triggered by resources during the converge phase of the chef run.

node[R]

Chef::Node object for this run

resource_collection[RW]

The Chef::ResourceCollection for this run. Populated by evaluating recipes, which is triggered by load. (See also: CookbookCompiler)

Public Class Methods

new(node, cookbook_collection, events) click to toggle source

Creates a new Chef::RunContext object and populates its fields. This object gets used by the Chef Server to generate a fully compiled recipe list for a node.

Returns

object<Chef::RunContext>

Duh. :)

# File lib/chef/run_context.rb, line 69
def initialize(node, cookbook_collection, events)
  @node = node
  @cookbook_collection = cookbook_collection
  @resource_collection = Chef::ResourceCollection.new
  @immediate_notification_collection = Hash.new {|h,k| h[k] = []}
  @delayed_notification_collection = Hash.new {|h,k| h[k] = []}
  @definitions = Hash.new
  @loaded_recipes = {}
  @loaded_attributes = {}
  @events = events

  @node.run_context = self

  @cookbook_compiler = nil
end

Public Instance Methods

delayed_notifications(resource) click to toggle source
# File lib/chef/run_context.rb, line 123
def delayed_notifications(resource)
  if resource.instance_of?(Chef::Resource)
    return @delayed_notification_collection[resource.name]
  else
    return @delayed_notification_collection[resource.to_s]
  end
end
has_cookbook_file_in_cookbook?(cookbook, cb_file_name) click to toggle source
# File lib/chef/run_context.rb, line 241
def has_cookbook_file_in_cookbook?(cookbook, cb_file_name)
  cookbook = cookbook_collection[cookbook]
  cookbook.has_cookbook_file_for_node?(node, cb_file_name)
end
has_template_in_cookbook?(cookbook, template_name) click to toggle source

Cookbook File Introspection

# File lib/chef/run_context.rb, line 236
def has_template_in_cookbook?(cookbook, template_name)
  cookbook = cookbook_collection[cookbook]
  cookbook.has_template_for_node?(node, template_name)
end
immediate_notifications(resource) click to toggle source
# File lib/chef/run_context.rb, line 115
def immediate_notifications(resource)
  if resource.instance_of?(Chef::Resource)
    return @immediate_notification_collection[resource.name]
  else
    return @immediate_notification_collection[resource.to_s]
  end
end
include_recipe(*recipe_names) click to toggle source

Evaluates the recipes recipe_names. Used by DSL::IncludeRecipe

# File lib/chef/run_context.rb, line 132
def include_recipe(*recipe_names)
  result_recipes = Array.new
  recipe_names.flatten.each do |recipe_name|
    if result = load_recipe(recipe_name)
      result_recipes << result
    end
  end
  result_recipes
end
load(run_list_expansion) click to toggle source

Triggers the compile phase of the chef run. Implemented by Chef::RunContext::CookbookCompiler

# File lib/chef/run_context.rb, line 87
def load(run_list_expansion)
  @cookbook_compiler = CookbookCompiler.new(self, run_list_expansion, events)
  @cookbook_compiler.compile
end
load_recipe(recipe_name) click to toggle source

Evaluates the recipe recipe_name. Used by DSL::IncludeRecipe

# File lib/chef/run_context.rb, line 143
    def load_recipe(recipe_name)
      Chef::Log.debug("Loading Recipe #{recipe_name} via include_recipe")

      cookbook_name, recipe_short_name = Chef::Recipe.parse_recipe_name(recipe_name)

      if unreachable_cookbook?(cookbook_name) # CHEF-4367
        Chef::Log.warn("MissingCookbookDependency:
Recipe `#{recipe_name}` is not in the run_list, and cookbook '#{cookbook_name}'
is not a dependency of any cookbook in the run_list.  To load this recipe,
first add a dependency on cookbook '#{cookbook_name}' in the cookbook you're
including it from in that cookbook's metadata.
")
      end


      if loaded_fully_qualified_recipe?(cookbook_name, recipe_short_name)
        Chef::Log.debug("I am not loading #{recipe_name}, because I have already seen it.")
        false
      else
        loaded_recipe(cookbook_name, recipe_short_name)
        node.loaded_recipe(cookbook_name, recipe_short_name)
        cookbook = cookbook_collection[cookbook_name]
        cookbook.load_recipe(recipe_short_name, self)
      end
    end
load_recipe_file(recipe_file) click to toggle source
# File lib/chef/run_context.rb, line 170
def load_recipe_file(recipe_file)
  if !File.exist?(recipe_file)
    raise Chef::Exceptions::RecipeNotFound, "could not find recipe file #{recipe_file}"
  end

  Chef::Log.debug("Loading Recipe File #{recipe_file}")
  recipe = Chef::Recipe.new('@recipe_files', recipe_file, self)
  recipe.from_file(recipe_file)
  recipe
end
loaded_attribute(cookbook, attribute_file) click to toggle source
# File lib/chef/run_context.rb, line 229
def loaded_attribute(cookbook, attribute_file)
  @loaded_attributes["#{cookbook}::#{attribute_file}"] = true
end
loaded_attributes() click to toggle source

An Array of all attributes files that have been loaded. Stored internally using a Hash, so order is not preserved on ruby 1.8.

Attribute file names are given in fully qualified form, e.g., “nginx::default” instead of “nginx”.

# File lib/chef/run_context.rb, line 209
def loaded_attributes
  @loaded_attributes.keys
end
loaded_fully_qualified_attribute?(cookbook, attribute_file) click to toggle source
# File lib/chef/run_context.rb, line 225
def loaded_fully_qualified_attribute?(cookbook, attribute_file)
  @loaded_attributes.has_key?("#{cookbook}::#{attribute_file}")
end
loaded_fully_qualified_recipe?(cookbook, recipe) click to toggle source
# File lib/chef/run_context.rb, line 213
def loaded_fully_qualified_recipe?(cookbook, recipe)
  @loaded_recipes.has_key?("#{cookbook}::#{recipe}")
end
loaded_recipe?(recipe) click to toggle source

Returns true if recipe has been loaded, false otherwise. Default recipe names are expanded, so `loaded_recipe?(“nginx”)` and `loaded_recipe?(“nginx::default”)` are valid and give identical results.

# File lib/chef/run_context.rb, line 220
def loaded_recipe?(recipe)
  cookbook, recipe_name = Chef::Recipe.parse_recipe_name(recipe)
  loaded_fully_qualified_recipe?(cookbook, recipe_name)
end
loaded_recipes() click to toggle source

An Array of all recipes that have been loaded. This is stored internally as a Hash, so ordering is not preserved when using ruby 1.8.

Recipe names are given in fully qualified form, e.g., the recipe “nginx” will be given as “nginx::default”

To determine if a particular recipe has been loaded, use loaded_recipe?

# File lib/chef/run_context.rb, line 200
def loaded_recipes
  @loaded_recipes.keys
end
notifies_delayed(notification) click to toggle source

Adds a delayed notification to the delayed_notification_collection. The notification should be a Chef::Resource::Notification or duck type.

# File lib/chef/run_context.rb, line 106
def notifies_delayed(notification)
  nr = notification.notifying_resource
  if nr.instance_of?(Chef::Resource)
    @delayed_notification_collection[nr.name] << notification
  else
    @delayed_notification_collection[nr.to_s] << notification
  end
end
notifies_immediately(notification) click to toggle source

Adds an immediate notification to the immediate_notification_collection. The notification should be a Chef::Resource::Notification or duck type.

# File lib/chef/run_context.rb, line 95
def notifies_immediately(notification)
  nr = notification.notifying_resource
  if nr.instance_of?(Chef::Resource)
    @immediate_notification_collection[nr.name] << notification
  else
    @immediate_notification_collection[nr.to_s] << notification
  end
end
open_stream(options = {}) { |stream| ... } click to toggle source

Open a stream object that can be printed into and will dispatch to events

Arguments

options is a hash with these possible options:

  • name: a string that identifies the stream to the user. Preferably short.

Pass a block and the stream will be yielded to it, and close on its own at the end of the block.

# File lib/chef/run_context.rb, line 261
def open_stream(options = {})
  stream = EventDispatch::EventsOutputStream.new(events, options)
  if block_given?
    begin
      yield stream
    ensure
      stream.close
    end
  else
    stream
  end
end
resolve_attribute(cookbook_name, attr_file_name) click to toggle source

Looks up an attribute file given the cookbook_name and attr_file_name. Used by DSL::IncludeAttribute

# File lib/chef/run_context.rb, line 183
def resolve_attribute(cookbook_name, attr_file_name)
  cookbook = cookbook_collection[cookbook_name]
  raise Chef::Exceptions::CookbookNotFound, "could not find cookbook #{cookbook_name} while loading attribute #{name}" unless cookbook

  attribute_filename = cookbook.attribute_filenames_by_short_filename[attr_file_name]
  raise Chef::Exceptions::AttributeNotFound, "could not find filename for attribute #{attr_file_name} in cookbook #{cookbook_name}" unless attribute_filename

  attribute_filename
end
unreachable_cookbook?(cookbook_name) click to toggle source

Delegates to Chef::RunContext::CookbookCompiler#unreachable_cookbook? Used to raise an error when attempting to load a recipe belonging to a cookbook that is not in the dependency graph. See also: CHEF-4367

# File lib/chef/run_context.rb, line 249
def unreachable_cookbook?(cookbook_name)
  @cookbook_compiler.unreachable_cookbook?(cookbook_name)
end

Private Instance Methods

loaded_recipe(cookbook, recipe) click to toggle source
# File lib/chef/run_context.rb, line 276
def loaded_recipe(cookbook, recipe)
  @loaded_recipes["#{cookbook}::#{recipe}"] = true
end