class Chef::RunList::RunListExpansion

Abstract Base class for expanding a run list. Subclasses must handle fetching roles from a data source by defining fetch_role

Attributes

all_missing_roles[R]
better_run_list_trace[R]

Like run list trace but instead of saving the entries as strings it saves their objects The to_json method uses this list to construct json.

default_attrs[R]
environment[R]
missing_roles_with_including_role[R]
override_attrs[R]
recipes[R]

A VersionedRecipeList of recipes. Populated only after expand is called.

role_errors[R]
run_list_items[R]
run_list_trace[R]

Returns a Hash of the form “including_role” => “included_role_or_recipe”. This can be used to show the expanded run list (ordered) graph.

Caveats

  • Duplicate roles are not shown.

source[R]

The data source passed to the constructor. Not used in this class. In subclasses, this is a Chef::ServerAPI object pre-configured to fetch roles from their correct location.

Public Class Methods

new(environment, run_list_items, source = nil) click to toggle source
# File lib/chef/run_list/run_list_expansion.rb, line 65
def initialize(environment, run_list_items, source = nil)
  @environment = environment
  @missing_roles_with_including_role = Array.new

  @run_list_items = run_list_items.dup
  @source = source

  @default_attrs = Mash.new
  @override_attrs = Mash.new

  @recipes = Chef::RunList::VersionedRecipeList.new

  @applied_roles = {}
  @run_list_trace = Hash.new { |h, key| h[key] = [] }
  @better_run_list_trace = Hash.new { |h, key| h[key] = [] }
  @all_missing_roles = {}
  @role_errors = {}
end

Public Instance Methods

applied_role?(role_name) click to toggle source
# File lib/chef/run_list/run_list_expansion.rb, line 114
def applied_role?(role_name)
  @applied_roles.key?(role_name)
end
apply_role_attributes(role) click to toggle source
# File lib/chef/run_list/run_list_expansion.rb, line 109
def apply_role_attributes(role)
  @default_attrs = Chef::Mixin::DeepMerge.merge(@default_attrs, role.default_attributes)
  @override_attrs = Chef::Mixin::DeepMerge.merge(@override_attrs, role.override_attributes)
end
errors() click to toggle source
# File lib/chef/run_list/run_list_expansion.rb, line 142
def errors
  @missing_roles_with_including_role.map { |item| item.first }
end
errors?() click to toggle source

Did we find any errors (expanding roles)?

# File lib/chef/run_list/run_list_expansion.rb, line 85
def errors?
  @missing_roles_with_including_role.length > 0
end
Also aliased as: invalid?
expand() click to toggle source

Recurses over the run list items, expanding roles. After this, recipes will contain the fully expanded recipe list

# File lib/chef/run_list/run_list_expansion.rb, line 93
def expand
  # Sure do miss function arity when being recursive
  expand_run_list_items(@run_list_items)
end
fetch_role(name, included_by) click to toggle source

In subclasses, this method will fetch the role from the data source.

# File lib/chef/run_list/run_list_expansion.rb, line 127
def fetch_role(name, included_by)
  raise NotImplementedError
end
inflate_role(role_name, included_by) click to toggle source

Fetches and inflates a role

Returns

Chef::Role in most cases false if the role has already been applied nil if the role does not exist

# File lib/chef/run_list/run_list_expansion.rb, line 103
def inflate_role(role_name, included_by)
  return false if applied_role?(role_name) # Prevent infinite loops
  applied_role(role_name)
  fetch_role(role_name, included_by)
end
invalid?()
Alias for: errors?
role_not_found(name, included_by) click to toggle source

When a role is not found, an error message is logged, but no exception is raised. We do add an entry in the errors collection.

Returns

nil

# File lib/chef/run_list/run_list_expansion.rb, line 135
def role_not_found(name, included_by)
  Chef::Log.error("Role #{name} (included by '#{included_by}') is in the runlist but does not exist. Skipping expand.")
  @missing_roles_with_including_role << [name, included_by]
  @all_missing_roles[name] = true
  nil
end
roles() click to toggle source

Returns an array of role names that were expanded; this includes any roles that were in the original, pre-expansion run_list as well as roles processed during expansion. Populated only after expand is called.

# File lib/chef/run_list/run_list_expansion.rb, line 122
def roles
  @applied_roles.keys
end
to_h() click to toggle source
# File lib/chef/run_list/run_list_expansion.rb, line 150
def to_h
  seen_items = { recipe: {}, role: {} }
  { id: @environment, run_list: convert_run_list_trace("top level", seen_items) }
end
Also aliased as: to_hash
to_hash()
Alias for: to_h
to_json(*a) click to toggle source
# File lib/chef/run_list/run_list_expansion.rb, line 146
def to_json(*a)
  Chef::JSONCompat.to_json(to_h, *a)
end

Private Instance Methods

applied_role(role_name) click to toggle source

these methods modifies internal state based on arguments, so hide it.

# File lib/chef/run_list/run_list_expansion.rb, line 161
def applied_role(role_name)
  @applied_roles[role_name] = true
end
convert_run_list_trace(base, seen_items) click to toggle source

Recursive helper to decode the non-nested hash form back into a tree

# File lib/chef/run_list/run_list_expansion.rb, line 184
def convert_run_list_trace(base, seen_items)
  @better_run_list_trace[base].map do |item|
    skipped = seen_items[item.type][item.name]
    seen_items[item.type][item.name] = true
    case item.type
      when :recipe
        { type: "recipe", name: item.name, version: item.version, skipped: !!skipped }
      when :role
        error = @role_errors[item.name]
        missing = @all_missing_roles[item.name]
        { type: :role, name: item.name, children: (missing || error || skipped) ? [] : convert_run_list_trace(item.to_s, seen_items),
          missing: missing, error: error, skipped: skipped }
    end
  end
end
expand_run_list_items(items, included_by = "top level") click to toggle source
# File lib/chef/run_list/run_list_expansion.rb, line 165
def expand_run_list_items(items, included_by = "top level")
  if entry = items.shift
    @run_list_trace[included_by.to_s] << entry.to_s
    @better_run_list_trace[included_by.to_s] << entry

    case entry.type
    when :recipe
      recipes.add_recipe(entry.name, entry.version)
    when :role
      if role = inflate_role(entry.name, included_by)
        expand_run_list_items(role.run_list_for(@environment).run_list_items, role)
        apply_role_attributes(role)
      end
    end
    expand_run_list_items(items, included_by)
  end
end