Class: ChefApply::TempCookbook

Inherits:
Object
  • Object
show all
Defined in:
lib/chef_apply/temp_cookbook.rb

Overview

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

Defined Under Namespace

Classes: UnsupportedExtension

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeTempCookbook

We expect name to come in as a list of strings - resource/resource_name or cookbook/recipe combination



32
33
34
# File 'lib/chef_apply/temp_cookbook.rb', line 32

def initialize
  @path = Dir.mktmpdir("cw")
end

Instance Attribute Details

#pathObject (readonly)

Returns the value of attribute path.



28
29
30
# File 'lib/chef_apply/temp_cookbook.rb', line 28

def path
  @path
end

Instance Method Details

#cookbook_for_recipe(existing_recipe_path) ⇒ Object



86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
# File 'lib/chef_apply/temp_cookbook.rb', line 86

def cookbook_for_recipe(existing_recipe_path)
   = File.expand_path(File.join(existing_recipe_path, "../../metadata.rb"))
  if File.file?()
    require "chef/cookbook/metadata"
    m = Chef::Cookbook::.new
    m.from_file()
    {
      name: m.name,
      recipe_name: File.basename(existing_recipe_path, File.extname(existing_recipe_path)),
      path: File.expand_path(File.join(, "../"))
    }
  else
    nil
  end
end

#create_resource(resource_type, resource_name, properties) ⇒ Object



140
141
142
143
144
145
146
147
148
149
150
151
152
153
# File 'lib/chef_apply/temp_cookbook.rb', line 140

def create_resource(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

#deleteObject



82
83
84
# File 'lib/chef_apply/temp_cookbook.rb', line 82

def delete
  FileUtils.remove_entry path
end

#from_existing_recipe(existing_recipe_path) ⇒ Object



36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
# File 'lib/chef_apply/temp_cookbook.rb', line 36

def from_existing_recipe(existing_recipe_path)
  ext_name = File.extname(existing_recipe_path)
  raise UnsupportedExtension.new(ext_name) unless ext_name == ".rb"
  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]}'")
    name = cb[:name]
    recipe_name = cb[:recipe_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]))
    generate_policyfile(name, recipe_name)
  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(existing_recipe_path, ext_name)
    name = "cw_recipe"
    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))
    (name)
    generate_policyfile(name, recipe_name)
  end
end

#from_resource(resource_type, resource_name, properties) ⇒ Object



67
68
69
70
71
72
73
74
75
76
77
78
79
80
# File 'lib/chef_apply/temp_cookbook.rb', line 67

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.
  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(resource_type, resource_name, properties))
  end
  (name)
  generate_policyfile(name, recipe_name)
end

#generate_metadata(name) ⇒ Object



108
109
110
111
112
113
114
# File 'lib/chef_apply/temp_cookbook.rb', line 108

def (name)
   = File.join(path, "metadata.rb")
  File.open(, "w+") do |f|
    f.print("name \"#{name}\"\n")
  end
  
end

#generate_policyfile(name, recipe_name) ⇒ Object



116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
# File 'lib/chef_apply/temp_cookbook.rb', line 116

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_dirObject



102
103
104
105
106
# File 'lib/chef_apply/temp_cookbook.rb', line 102

def generate_recipes_dir
  recipes_path = File.join(path, "recipes")
  FileUtils.mkdir_p(recipes_path)
  recipes_path
end