class ChefApply::Action::GenerateTempCookbook::TempCookbook

This class knows how to create a local cookbook in a temp file, populate it with various recipes, attributes, config, etc. and delete it when the cookbook is no longer necessary

Attributes

descriptor[R]
from[R]
path[R]

Public Class Methods

new() click to toggle source
# File lib/chef_apply/action/generate_temp_cookbook/temp_cookbook.rb, line 31
def initialize
  @path = Dir.mktmpdir("cw")
end

Public Instance Methods

cookbook_for_recipe(existing_recipe_path) click to toggle source
# File lib/chef_apply/action/generate_temp_cookbook/temp_cookbook.rb, line 92
def cookbook_for_recipe(existing_recipe_path)
  metadata = File.expand_path(File.join(existing_recipe_path, "../../metadata.rb"))
  if File.file?(metadata)
    require "chef/cookbook/metadata"
    m = Chef::Cookbook::Metadata.new
    m.from_file(metadata)
    {
      name: m.name,
      recipe_name: File.basename(existing_recipe_path, File.extname(existing_recipe_path)),
      path: File.expand_path(File.join(metadata, "../")),
    }
  else
    nil
  end
end
create_resource_definition(resource_type, resource_name, properties) click to toggle source
# File lib/chef_apply/action/generate_temp_cookbook/temp_cookbook.rb, line 146
def create_resource_definition(resource_type, resource_name, properties)
  r = "#{resource_type} '#{resource_name}'"
  # lets format the properties into the correct syntax Chef expects
  unless properties.empty?
    r += " do\n"
    properties.each do |k, v|
      v = "'#{v}'" if v.is_a? String
      r += "  #{k} #{v}\n"
    end
    r += "end"
  end
  r += "\n"
  r
end
delete() click to toggle source
# File lib/chef_apply/action/generate_temp_cookbook/temp_cookbook.rb, line 88
def delete
  FileUtils.remove_entry path
end
export_path() click to toggle source
# File lib/chef_apply/action/generate_temp_cookbook/temp_cookbook.rb, line 165
def export_path
  File.join(path, "export")
end
from_existing_recipe(existing_recipe_path) click to toggle source
# File lib/chef_apply/action/generate_temp_cookbook/temp_cookbook.rb, line 35
def from_existing_recipe(existing_recipe_path)
  ext_name = File.extname(existing_recipe_path)
  raise UnsupportedExtension.new(ext_name) unless ext_name == ".rb" || ext_name == ".yml"

  cb = cookbook_for_recipe(existing_recipe_path)
  if cb
    # Full existing cookbook - only needs policyfile
    ChefApply::Log.debug("Found full cookbook at path '#{cb[:path]}' and using recipe '#{cb[:recipe_name]}'")
    @descriptor = "#{cb[:name]}::#{cb[:recipe_name]}"
    @from = "#{cb[:path]}"
    recipe_name = cb[:recipe_name]
    cb_name = cb[:name]
    FileUtils.cp_r(cb[:path], path)
    # cp_r copies the whole existing cookbook into the tempdir so need to reset our path
    @path = File.join(path, File.basename(cb[:path]))
  else
    # Cookbook from single recipe not in a cookbook. We create the full cookbook
    # structure including metadata, then generate policyfile. We set the cookbook
    # name to the recipe name so hopefully this gives us better reporting info
    # in the future
    ChefApply::Log.debug("Found single recipe at path '#{existing_recipe_path}'")
    recipe = File.basename(existing_recipe_path)
    recipe_name = File.basename(recipe, ext_name)
    cb_name = "cw_recipe"
    @descriptor = "#{recipe_name}"
    @from = existing_recipe_path
    recipes_dir = generate_recipes_dir
    # This has the potential to break if they specify a recipe without a .rb
    # extension, but lets wait to deal with that bug until we encounter it
    FileUtils.cp(existing_recipe_path, File.join(recipes_dir, recipe))
    generate_metadata(cb_name)
  end
  generate_policyfile(cb_name, recipe_name)
end
from_resource(resource_type, resource_name, properties) click to toggle source
# File lib/chef_apply/action/generate_temp_cookbook/temp_cookbook.rb, line 70
def from_resource(resource_type, resource_name, properties)
  # Generate a cookbook containing a single default recipe with the specified
  # resource in it. Incloud the resource type in the cookbook name so hopefully
  # this gives us better reporting info in the future.
  @descriptor = "#{resource_type}[#{resource_name}]"
  @from = "resource"

  ChefApply::Log.debug("Generating cookbook for single resource '#{resource_type}[#{resource_name}]'")
  name = "cw_#{resource_type}"
  recipe_name = "default"
  recipes_dir = generate_recipes_dir
  File.open(File.join(recipes_dir, "#{recipe_name}.rb"), "w+") do |f|
    f.print(create_resource_definition(resource_type, resource_name, properties))
  end
  generate_metadata(name)
  generate_policyfile(name, recipe_name)
end
generate_metadata(name) click to toggle source
# File lib/chef_apply/action/generate_temp_cookbook/temp_cookbook.rb, line 114
def generate_metadata(name)
  metadata_file = File.join(path, "metadata.rb")
  File.open(metadata_file, "w+") do |f|
    f.print("name \"#{name}\"\n")
  end
  metadata_file
end
generate_policyfile(name, recipe_name) click to toggle source
# File lib/chef_apply/action/generate_temp_cookbook/temp_cookbook.rb, line 122
def generate_policyfile(name, recipe_name)
  policy_file = File.join(path, "Policyfile.rb")
  if File.exist?(policy_file)
    File.open(policy_file, "a") do |f|
      # We override the specified run_list with the run_list we want.
      # We append and put this at the end of the file so it overrides
      # any specified run_list.
      f.print("\n# Overriding run_list with command line specified value\n")
      f.print("run_list \"#{name}::#{recipe_name}\"\n")
    end
  else
    File.open(policy_file, "w+") do |f|
      f.print("name \"#{name}_policy\"\n")
      ChefApply::Config.chef.cookbook_repo_paths.each do |p|
        f.print("default_source :chef_repo, \"#{p}\"\n")
      end
      f.print("default_source :supermarket\n")
      f.print("run_list \"#{name}::#{recipe_name}\"\n")
      f.print("cookbook \"#{name}\", path: \".\"\n")
    end
  end
  policy_file
end
generate_recipes_dir() click to toggle source
# File lib/chef_apply/action/generate_temp_cookbook/temp_cookbook.rb, line 108
def generate_recipes_dir
  recipes_path = File.join(path, "recipes")
  FileUtils.mkdir_p(recipes_path)
  recipes_path
end
policyfile_lock_path() click to toggle source
# File lib/chef_apply/action/generate_temp_cookbook/temp_cookbook.rb, line 161
def policyfile_lock_path
  File.join(path, "Policyfile.lock.json")
end