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

Returns a new instance of TempCookbook.



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

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

Instance Attribute Details

#descriptorObject (readonly)

Returns the value of attribute descriptor.



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

def descriptor
  @descriptor
end

#fromObject (readonly)

Returns the value of attribute from.



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

def from
  @from
end

#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



89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
# File 'lib/chef_apply/temp_cookbook.rb', line 89

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::Metadata.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_definition(resource_type, resource_name, properties) ⇒ Object



143
144
145
146
147
148
149
150
151
152
153
154
155
156
# File 'lib/chef_apply/temp_cookbook.rb', line 143

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

#deleteObject



85
86
87
# File 'lib/chef_apply/temp_cookbook.rb', line 85

def delete
  FileUtils.remove_entry path
end

#export_pathObject



162
163
164
# File 'lib/chef_apply/temp_cookbook.rb', line 162

def export_path
  File.join(path, "export")
end

#from_existing_recipe(existing_recipe_path) ⇒ Object



33
34
35
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 33

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]}'")
    @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))
    (cb_name)
  end
  generate_policyfile(cb_name, recipe_name)
end

#from_resource(resource_type, resource_name, properties) ⇒ Object



67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
# 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.
  @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
  (name)
  generate_policyfile(name, recipe_name)
end

#generate_metadata(name) ⇒ Object



111
112
113
114
115
116
117
# File 'lib/chef_apply/temp_cookbook.rb', line 111

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



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

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



105
106
107
108
109
# File 'lib/chef_apply/temp_cookbook.rb', line 105

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

#policyfile_lock_pathObject



158
159
160
# File 'lib/chef_apply/temp_cookbook.rb', line 158

def policyfile_lock_path
  File.join(path, "Policyfile.lock.json")
end