summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThom May <thom@chef.io>2017-04-04 13:56:54 +0100
committerThom May <thom@chef.io>2017-04-04 14:01:44 +0100
commit35cf4e57a6d0c44547d0a0ecd69ea64eba33bf38 (patch)
tree0139d401ce22594e2aa5845c1c9f4151e1c0584c
parent6c7c5e9de89ab127ce3375240c55f8a3c494566a (diff)
downloadchef-35cf4e57a6d0c44547d0a0ecd69ea64eba33bf38.tar.gz
RFC 59: Load Ohai plugins
This adds a new phase in the compilation of the run context, and bubbles up the ohai object from the client to the run_context. Signed-off-by: Thom May <thom@chef.io>
-rw-r--r--Gemfile4
-rw-r--r--Gemfile.lock17
-rw-r--r--chef-config/lib/chef-config/config.rb4
-rw-r--r--lib/chef/client.rb2
-rw-r--r--lib/chef/event_dispatch/base.rb16
-rw-r--r--lib/chef/node.rb5
-rw-r--r--lib/chef/policy_builder/dynamic.rb10
-rw-r--r--lib/chef/policy_builder/expand_node_object.rb10
-rw-r--r--lib/chef/policy_builder/policyfile.rb10
-rw-r--r--lib/chef/run_context.rb5
-rw-r--r--lib/chef/run_context/cookbook_compiler.rb30
-rw-r--r--spec/functional/resource/base.rb2
-rw-r--r--spec/integration/client/client_spec.rb33
13 files changed, 122 insertions, 26 deletions
diff --git a/Gemfile b/Gemfile
index 343c1f3f9f..761990dbcf 100644
--- a/Gemfile
+++ b/Gemfile
@@ -12,12 +12,12 @@ source "https://rubygems.org"
gem "chef", path: "."
# tracking master of ohai for chef-13.0 development, this should be able to be deleted after release
-gem "ohai", git: "https://github.com/chef/ohai.git"
+gem "ohai", git: "https://github.com/chef/ohai.git", branch: "tm/load_additional_plugins"
gem "chef-config", path: File.expand_path("../chef-config", __FILE__) if File.exist?(File.expand_path("../chef-config", __FILE__))
gem "rake"
gem "bundler"
-gem "cheffish", "~> 13" # required for rspec tests
+gem "cheffish", "~> 13", git: "https://github.com/chef/cheffish.git", branch: "tm/ohai_run_context"# required for rspec tests
group(:omnibus_package) do
gem "appbundler"
diff --git a/Gemfile.lock b/Gemfile.lock
index 8d9447bee3..e6c353ef23 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -15,6 +15,15 @@ GIT
rspec_junit_formatter (~> 0.2)
GIT
+ remote: https://github.com/chef/cheffish.git
+ revision: d088e7a10b4289cfb1410b92388e8bc5972a6be2
+ branch: tm/ohai_run_context
+ specs:
+ cheffish (13.0.0)
+ chef-zero (~> 13.0)
+ net-ssh
+
+GIT
remote: https://github.com/chef/chefstyle.git
revision: b2bf89dd11270e169fd2315495c98095d4a19090
branch: master
@@ -37,7 +46,8 @@ GIT
GIT
remote: https://github.com/chef/ohai.git
- revision: 58296dc0035e4f94a7b7cdc1db01887a3c3c1e30
+ revision: 0b4cab6d491a5b1e52995a65e0039c6fa1ba8e9f
+ branch: tm/load_additional_plugins
specs:
ohai (13.0.0)
chef-config (>= 12.5.0.alpha.1, < 14)
@@ -228,9 +238,6 @@ GEM
mixlib-log (~> 1.3)
rack (~> 2.0)
uuidtools (~> 2.1)
- cheffish (13.0.0)
- chef-zero (~> 13.0)
- net-ssh
chefspec (5.4.0)
chef (>= 12.0)
fauxhai (~> 3.6)
@@ -571,7 +578,7 @@ DEPENDENCIES
chef!
chef-config!
chef-sugar
- cheffish (~> 13)
+ cheffish (~> 13)!
chefspec
chefstyle!
cucumber (>= 2.4.0)
diff --git a/chef-config/lib/chef-config/config.rb b/chef-config/lib/chef-config/config.rb
index 9bffb66eca..7e66bae981 100644
--- a/chef-config/lib/chef-config/config.rb
+++ b/chef-config/lib/chef-config/config.rb
@@ -450,6 +450,10 @@ module ChefConfig
# most of our testing scenarios)
default :minimal_ohai, false
+ # When consuming Ohai plugins from cookbook segments, we place those plugins in this directory.
+ # Subsequent chef client runs will wipe and re-populate the directory to ensure cleanliness
+ default(:ohai_segment_plugin_path) { PathHelper.join(config_dir, "ohai", "cookbook_plugins") }
+
###
# Policyfile Settings
#
diff --git a/lib/chef/client.rb b/lib/chef/client.rb
index b219fdfdd6..af3a7566bb 100644
--- a/lib/chef/client.rb
+++ b/lib/chef/client.rb
@@ -522,7 +522,7 @@ class Chef
# @api private
#
def policy_builder
- @policy_builder ||= Chef::PolicyBuilder::Dynamic.new(node_name, ohai.data, json_attribs, override_runlist, events)
+ @policy_builder ||= Chef::PolicyBuilder::Dynamic.new(node_name, ohai, json_attribs, override_runlist, events)
end
#
diff --git a/lib/chef/event_dispatch/base.rb b/lib/chef/event_dispatch/base.rb
index 926bbe24b5..caad03df49 100644
--- a/lib/chef/event_dispatch/base.rb
+++ b/lib/chef/event_dispatch/base.rb
@@ -179,6 +179,22 @@ class Chef
def library_load_complete
end
+ # Called when an ohai plugin file loading starts
+ def ohai_plugin_load_start(file_count)
+ end
+
+ # Called when an ohai plugin file has been loaded
+ def ohai_plugin_file_loaded(path)
+ end
+
+ # Called when an ohai plugin file has an error on load.
+ def ohai_plugin_file_load_failed(path, exception)
+ end
+
+ # Called when an ohai plugin file loading has finished
+ def ohai_plugin_load_complete
+ end
+
# Called when LWRP loading starts
def lwrp_load_start(lwrp_file_count)
end
diff --git a/lib/chef/node.rb b/lib/chef/node.rb
index 92bdb5887b..59958beb9a 100644
--- a/lib/chef/node.rb
+++ b/lib/chef/node.rb
@@ -329,7 +329,6 @@ class Chef
def consume_external_attrs(ohai_data, json_cli_attrs)
Chef::Log.debug("Extracting run list from JSON attributes provided on command line")
consume_attributes(json_cli_attrs)
-
self.automatic_attrs = ohai_data
platform, version = Chef::Platform.find_platform_and_version(self)
@@ -338,6 +337,10 @@ class Chef
automatic[:platform_version] = version
end
+ def consume_ohai_data(ohai_data)
+ self.automatic_attrs = Chef::Mixin::DeepMerge.merge(automatic_attrs, ohai_data)
+ end
+
# Consumes the combined run_list and other attributes in +attrs+
def consume_attributes(attrs)
normal_attrs_to_merge = consume_run_list(attrs)
diff --git a/lib/chef/policy_builder/dynamic.rb b/lib/chef/policy_builder/dynamic.rb
index 5b6bc40f9e..929202ab26 100644
--- a/lib/chef/policy_builder/dynamic.rb
+++ b/lib/chef/policy_builder/dynamic.rb
@@ -35,16 +35,16 @@ class Chef
attr_reader :node
attr_reader :node_name
- attr_reader :ohai_data
+ attr_reader :ohai
attr_reader :json_attribs
attr_reader :override_runlist
attr_reader :events
- def initialize(node_name, ohai_data, json_attribs, override_runlist, events)
+ def initialize(node_name, ohai, json_attribs, override_runlist, events)
@implementation = nil
+ @ohai = ohai
@node_name = node_name
- @ohai_data = ohai_data
@json_attribs = json_attribs
@override_runlist = override_runlist
@events = events
@@ -152,9 +152,9 @@ class Chef
policyfile_attribs_in_node_json? ||
node_has_policyfile_attrs?(node) ||
policyfile_compat_mode_config?
- @implementation = Policyfile.new(node_name, ohai_data, json_attribs, override_runlist, events)
+ @implementation = Policyfile.new(node_name, ohai, json_attribs, override_runlist, events)
else
- @implementation = ExpandNodeObject.new(node_name, ohai_data, json_attribs, override_runlist, events)
+ @implementation = ExpandNodeObject.new(node_name, ohai, json_attribs, override_runlist, events)
end
end
diff --git a/lib/chef/policy_builder/expand_node_object.rb b/lib/chef/policy_builder/expand_node_object.rb
index 26f39e8b73..835b7ab412 100644
--- a/lib/chef/policy_builder/expand_node_object.rb
+++ b/lib/chef/policy_builder/expand_node_object.rb
@@ -41,15 +41,15 @@ class Chef
attr_reader :events
attr_reader :node
attr_reader :node_name
- attr_reader :ohai_data
+ attr_reader :ohai
attr_reader :json_attribs
attr_reader :override_runlist
attr_reader :run_context
attr_reader :run_list_expansion
- def initialize(node_name, ohai_data, json_attribs, override_runlist, events)
+ def initialize(node_name, ohai, json_attribs, override_runlist, events)
@node_name = node_name
- @ohai_data = ohai_data
+ @ohai = ohai
@json_attribs = json_attribs
@override_runlist = override_runlist
@events = events
@@ -77,7 +77,7 @@ class Chef
cookbook_collection.validate!
cookbook_collection.install_gems(events)
- run_context = Chef::RunContext.new(node, cookbook_collection, @events)
+ run_context = Chef::RunContext.new(node, cookbook_collection, @events, ohai)
else
Chef::Cookbook::FileVendor.fetch_from_remote(api_service)
cookbook_hash = sync_cookbooks
@@ -85,7 +85,7 @@ class Chef
cookbook_collection.validate!
cookbook_collection.install_gems(events)
- run_context = Chef::RunContext.new(node, cookbook_collection, @events)
+ run_context = Chef::RunContext.new(node, cookbook_collection, @events, ohai)
end
# TODO: this is really obviously not the place for this
diff --git a/lib/chef/policy_builder/policyfile.rb b/lib/chef/policy_builder/policyfile.rb
index f84e1dc68e..92dd012688 100644
--- a/lib/chef/policy_builder/policyfile.rb
+++ b/lib/chef/policy_builder/policyfile.rb
@@ -56,13 +56,13 @@ class Chef
attr_reader :events
attr_reader :node
attr_reader :node_name
- attr_reader :ohai_data
+ attr_reader :ohai
attr_reader :json_attribs
attr_reader :run_context
- def initialize(node_name, ohai_data, json_attribs, override_runlist, events)
+ def initialize(node_name, ohai, json_attribs, override_runlist, events)
@node_name = node_name
- @ohai_data = ohai_data
+ @ohai = ohai
@json_attribs = json_attribs
@events = events
@@ -128,7 +128,7 @@ class Chef
# determine which versions of cookbooks to use.
node.reset_defaults_and_overrides
- node.consume_external_attrs(ohai_data, json_attribs)
+ node.consume_external_attrs(ohai.data, json_attribs)
expand_run_list
apply_policyfile_attributes
@@ -155,7 +155,7 @@ class Chef
cookbook_collection.validate!
cookbook_collection.install_gems(events)
- run_context = Chef::RunContext.new(node, cookbook_collection, events)
+ run_context = Chef::RunContext.new(node, cookbook_collection, events, ohai)
setup_chef_class(run_context)
diff --git a/lib/chef/run_context.rb b/lib/chef/run_context.rb
index a606585e80..0d78f66fe6 100644
--- a/lib/chef/run_context.rb
+++ b/lib/chef/run_context.rb
@@ -149,6 +149,7 @@ class Chef
#
attr_reader :delayed_actions
+ attr_reader :ohai
# Creates a new Chef::RunContext object and populates its fields. This object gets
# used by the Chef Server to generate a fully compiled recipe list for a node.
#
@@ -158,10 +159,11 @@ class Chef
# @param events [EventDispatch::Dispatcher] The event dispatcher for this
# run.
#
- def initialize(node, cookbook_collection, events)
+ def initialize(node, cookbook_collection, events, ohai)
@node = node
@cookbook_collection = cookbook_collection
@events = events
+ @ohai = ohai
node.run_context = self
node.set_cookbook_attribute
@@ -603,6 +605,7 @@ ERROR_MESSAGE
loaded_recipes
loaded_recipes_hash
node
+ ohai
open_stream
reboot_info
reboot_info=
diff --git a/lib/chef/run_context/cookbook_compiler.rb b/lib/chef/run_context/cookbook_compiler.rb
index 94635be03d..6adee1c109 100644
--- a/lib/chef/run_context/cookbook_compiler.rb
+++ b/lib/chef/run_context/cookbook_compiler.rb
@@ -57,6 +57,7 @@ class Chef
# Run the compile phase of the chef run. Loads files in the following order:
# * Libraries
+ # * Ohai Plugins
# * Attributes
# * LWRPs
# * Resource Definitions
@@ -69,6 +70,7 @@ class Chef
# #cookbook_order for more information.
def compile
compile_libraries
+ install_ohai_plugins
compile_attributes
compile_lwrps
compile_resource_definitions
@@ -101,6 +103,21 @@ class Chef
@events.library_load_complete
end
+ # Install ohai plugins and ensure that ones not associated with a cookbook
+ # are properly removed.
+ def install_ohai_plugins
+ @events.ohai_plugin_load_start(count_files_by_segment(:ohai))
+ FileUtils.rm_rf(Chef::Config[:ohai_segment_plugin_path])
+ cookbook_order.each do |cookbook|
+ install_ohai_plugins_from_cookbook(cookbook)
+ end
+
+ @run_context.ohai.run_additional_plugins(Chef::Config[:ohai_segment_plugin_path])
+ node.consume_ohai_data(@run_context.ohai.data)
+
+ @events.ohai_plugin_load_complete
+ end
+
# Loads attributes files from cookbooks. Attributes files are loaded
# according to #cookbook_order; within a cookbook, +default.rb+ is loaded
# first, then the remaining attributes files in lexical sort order.
@@ -185,6 +202,19 @@ class Chef
raise
end
+ def install_ohai_plugins_from_cookbook(cookbook_name)
+ target = Chef::Config[:ohai_segment_plugin_path]
+ files_in_cookbook_by_segment(cookbook_name, :ohai).each do |filename|
+ next unless File.extname(filename) == ".rb"
+
+ target_name = File.join(target, cookbook_name.to_s, File.basename(filename))
+ Chef::Log.debug "Installing ohai file: #{filename} from #{cookbook_name} to #{target_name}"
+
+ FileUtils.mkdir_p(File.dirname(target_name))
+ FileUtils.cp(filename, target_name)
+ end
+ end
+
def load_libraries_from_cookbook(cookbook_name)
files_in_cookbook_by_segment(cookbook_name, :libraries).each do |filename|
next unless File.extname(filename) == ".rb"
diff --git a/spec/functional/resource/base.rb b/spec/functional/resource/base.rb
index 38175e81c0..8b9dfa8b2f 100644
--- a/spec/functional/resource/base.rb
+++ b/spec/functional/resource/base.rb
@@ -23,6 +23,6 @@ def run_context
node.default[:platform_version] = ohai[:platform_version]
node.default[:os] = ohai[:os]
events = Chef::EventDispatch::Dispatcher.new
- Chef::RunContext.new(node, {}, events)
+ Chef::RunContext.new(node, {}, events, Ohai::System.new)
end
end
diff --git a/spec/integration/client/client_spec.rb b/spec/integration/client/client_spec.rb
index 2a31638c0f..1cd74a6fd1 100644
--- a/spec/integration/client/client_spec.rb
+++ b/spec/integration/client/client_spec.rb
@@ -465,6 +465,39 @@ end
end
end
+ when_the_repository "has a cookbook with an ohai plugin" do
+ before do
+ file "cookbooks/x/recipes/default.rb", <<-RECIPE
+file #{path_to('tempfile.txt').inspect} do
+ content node["english"]["version"]
+end
+ RECIPE
+
+ file "cookbooks/x/ohai/english.rb", <<-OHAI
+ Ohai.plugin(:English) do
+ provides 'english'
+
+ collect_data do
+ english Mash.new
+ english[:version] = "2014"
+ end
+ end
+ OHAI
+
+ file "config/client.rb", <<EOM
+local_mode true
+cookbook_path "#{path_to('cookbooks')}"
+EOM
+ end
+
+ it "should run the ohai plugin" do
+ result = shell_out("#{chef_client} -l debug -c \"#{path_to('config/client.rb')}\" -o 'x::default' --no-fork", :cwd => chef_dir)
+ result.error!
+
+ expect(IO.read(path_to("tempfile.txt"))).to eq("2014")
+ end
+ end
+
# Fails on appveyor, but works locally on windows and on windows hosts in Ci.
context "when using recipe-url", :skip_appveyor do
before(:each) do