diff options
author | Lamont Granquist <lamont@scriptkiddie.org> | 2019-06-11 18:02:10 -0700 |
---|---|---|
committer | Lamont Granquist <lamont@scriptkiddie.org> | 2020-02-14 10:38:38 -0800 |
commit | 6805006207c78f48961d24336be2054095a8bd68 (patch) | |
tree | e3991700623dabf67b2a8bea88714dab54a084d5 | |
parent | 5a9f64b83e4605ee4d23190a3afcf08b000e3da1 (diff) | |
download | chef-6805006207c78f48961d24336be2054095a8bd68.tar.gz |
parse yaml recipes
Signed-off-by: Lamont Granquist <lamont@scriptkiddie.org>
-rw-r--r-- | lib/chef/cookbook_version.rb | 39 | ||||
-rw-r--r-- | lib/chef/mixin/from_file.rb | 21 | ||||
-rw-r--r-- | lib/chef/recipe.rb | 16 |
3 files changed, 74 insertions, 2 deletions
diff --git a/lib/chef/cookbook_version.rb b/lib/chef/cookbook_version.rb index 4989fb8d91..ed0c199728 100644 --- a/lib/chef/cookbook_version.rb +++ b/lib/chef/cookbook_version.rb @@ -4,7 +4,7 @@ # Author:: Tim Hinderliter (<tim@chef.io>) # Author:: Seth Falcon (<seth@chef.io>) # Author:: Daniel DeLeo (<dan@chef.io>) -# Copyright:: Copyright 2008-2018, Chef Software Inc. +# Copyright:: Copyright 2008-2019, Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -137,6 +137,18 @@ class Chef end end + def recipe_yml_filenames_by_name + @recipe_ym_filenames_by_name ||= begin + name_map = yml_filenames_by_name(files_for("recipes")) + root_alias = cookbook_manifest.root_files.find { |record| record[:name] == "root_files/recipe.yml" } + if root_alias + Chef::Log.error("Cookbook #{name} contains both recipe.yml and and recipes/default.yml, ignoring recipes/default.yml") if name_map["default"] + name_map["default"] = root_alias[:full_path] + end + name_map + end + end + def recipe_filenames_by_name @recipe_filenames_by_name ||= begin name_map = filenames_by_name(files_for("recipes")) @@ -184,10 +196,29 @@ class Chef # called from DSL def load_recipe(recipe_name, run_context) - unless recipe_filenames_by_name.key?(recipe_name) + if recipe_filenames_by_name.key?(recipe_name) + load_ruby_recipe(recipe_name, run_context) + elsif recipe_yml_filenames_by_name.key?(recipe_name) + load_yml_recipe(recipe_name, run_context) + else raise Chef::Exceptions::RecipeNotFound, "could not find recipe #{recipe_name} for cookbook #{name}" end + end + def load_yml_recipe(recipe_name, run_context) + Chef::Log.trace("Found recipe #{recipe_name} in cookbook #{name}") + recipe = Chef::Recipe.new(name, recipe_name, run_context) + recipe_filename = recipe_yml_filenames_by_name[recipe_name] + + unless recipe_filename + raise Chef::Exceptions::RecipeNotFound, "could not find #{recipe_name} files for cookbook #{name}" + end + + recipe.from_yaml_file(recipe_filename) + recipe + end + + def load_ruby_recipe(recipe_name, run_context) Chef::Log.trace("Found recipe #{recipe_name} in cookbook #{name}") recipe = Chef::Recipe.new(name, recipe_name, run_context) recipe_filename = recipe_filenames_by_name[recipe_name] @@ -551,6 +582,10 @@ class Chef records.select { |record| record[:name] =~ /\.rb$/ }.inject({}) { |memo, record| memo[File.basename(record[:name], ".rb")] = record[:full_path]; memo } end + def yml_filenames_by_name(records) + records.select { |record| record[:name] =~ /\.yml$/ }.inject({}) { |memo, record| memo[File.basename(record[:name], ".yml")] = record[:full_path]; memo } + end + def file_vendor unless @file_vendor @file_vendor = Chef::Cookbook::FileVendor.create_from_manifest(cookbook_manifest) diff --git a/lib/chef/mixin/from_file.rb b/lib/chef/mixin/from_file.rb index b8300340c7..ba034d331e 100644 --- a/lib/chef/mixin/from_file.rb +++ b/lib/chef/mixin/from_file.rb @@ -17,6 +17,8 @@ # limitations under the License. # +require "erb" + class Chef module Mixin module FromFile @@ -37,6 +39,25 @@ class Chef end end + # This will return an array of hashes or something that then needs to get inflated. + def from_yaml_file(filename) + self.source_file = filename + if File.file?(filename) && File.readable?(filename) + tpl = ERB.new(IO.read(filename)) + tpl.filename = filename + res = ::YAML.safe_load(tpl.result) + if res.is_a?(Hash) + from_hash(res) + elsif res.is_a?(Array) + from_array(res) + else + raise "boom" + end + else + raise IOError, "Cannot open or read #{filename}!" + end + end + # Loads a given ruby file, and runs class_eval against it in the context of the current # object. # diff --git a/lib/chef/recipe.rb b/lib/chef/recipe.rb index 154072827e..95b69532f8 100644 --- a/lib/chef/recipe.rb +++ b/lib/chef/recipe.rb @@ -85,6 +85,22 @@ class Chef end end + def from_array(array) + array.each { |e| from_hash(e) } + end + + def from_hash(hash) + hash["resources"].each do |rhash| + type = rhash.delete("type").to_sym + name = rhash.delete("name") + res = declare_resource(type, name) + rhash.each do |key, value| + # FIXME?: we probably need a way to instance_exec a string that contains block code against the property? + res.send(key, value) + end + end + end + def to_s "cookbook: #{cookbook_name ? cookbook_name : "(none)"}, recipe: #{recipe_name ? recipe_name : "(none)"} " end |