Class: ChefApply::Action::GenerateTempCookbook::TempCookbook

Inherits:
Object
  • Object
show all
Defined in:
lib/chef_apply/action/generate_temp_cookbook/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.



31
32
33
# File 'lib/chef_apply/action/generate_temp_cookbook/temp_cookbook.rb', line 31

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

Instance Attribute Details

#descriptorObject (readonly)

Returns the value of attribute descriptor.



30
31
32
# File 'lib/chef_apply/action/generate_temp_cookbook/temp_cookbook.rb', line 30

def descriptor
  @descriptor
end

#fromObject (readonly)

Returns the value of attribute from.



30
31
32
# File 'lib/chef_apply/action/generate_temp_cookbook/temp_cookbook.rb', line 30

def from
  @from
end

#pathObject (readonly)

Returns the value of attribute path.



30
31
32
# File 'lib/chef_apply/action/generate_temp_cookbook/temp_cookbook.rb', line 30

def path
  @path
end

Instance Method Details

#cookbook_for_recipe(existing_recipe_path) ⇒ Object



92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
# File 'lib/chef_apply/action/generate_temp_cookbook/temp_cookbook.rb', line 92

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



146
147
148
149
150
151
152
153
154
155
156
157
158
159
# 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

#deleteObject



88
89
90
# File 'lib/chef_apply/action/generate_temp_cookbook/temp_cookbook.rb', line 88

def delete
  FileUtils.remove_entry path
end

#export_pathObject



165
166
167
# 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) ⇒ Object



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
66
67
68
# 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))
    (cb_name)
  end
  generate_policyfile(cb_name, recipe_name)
end

#from_resource(resource_type, resource_name, properties) ⇒ Object



70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
# 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. Include 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



114
115
116
117
118
119
120
# File 'lib/chef_apply/action/generate_temp_cookbook/temp_cookbook.rb', line 114

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



122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
# 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_dirObject



108
109
110
111
112
# 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_pathObject



161
162
163
# File 'lib/chef_apply/action/generate_temp_cookbook/temp_cookbook.rb', line 161

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