diff options
author | Lamont Granquist <lamont@chef.io> | 2020-02-24 10:14:28 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-02-24 10:14:28 -0800 |
commit | e1298393a94212a8c467a7deea7a81c991b73365 (patch) | |
tree | 85c1f314e357a29e4e189c8e7c5b2d32ce2a41a4 | |
parent | dabb4a8bb027b63bb555acb5a057df1ccf5a5584 (diff) | |
parent | fc25d304203409093206ab2a76698932b990641c (diff) | |
download | chef-e1298393a94212a8c467a7deea7a81c991b73365.tar.gz |
Merge pull request #8653 from chef/lcg/yml-recipes
Parse YAML recipes
-rw-r--r-- | lib/chef/cookbook_version.rb | 39 | ||||
-rw-r--r-- | lib/chef/recipe.rb | 37 |
2 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/recipe.rb b/lib/chef/recipe.rb index 154072827e..ddb45de8e3 100644 --- a/lib/chef/recipe.rb +++ b/lib/chef/recipe.rb @@ -85,6 +85,43 @@ class Chef end end + def from_yaml_file(filename) + self.source_file = filename + if File.file?(filename) && File.readable?(filename) + from_yaml(IO.read(filename)) + else + raise IOError, "Cannot open or read #{filename}!" + end + end + + def from_yaml(string) + res = ::YAML.safe_load(string) + if res.is_a?(Hash) + from_hash(res) + elsif res.is_a?(Array) + from_array(res) + else + raise "boom" + end + end + + def from_array(array) + Chef::Log.warn "array yaml files are super duper experimental behavior" + 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 |