diff options
author | Claire McQuin <mcquin@users.noreply.github.com> | 2015-07-24 10:05:16 -0700 |
---|---|---|
committer | Claire McQuin <mcquin@users.noreply.github.com> | 2015-07-24 10:05:16 -0700 |
commit | 114db57c8ae1558f24e8b69c5ae19a59a1ca4b19 (patch) | |
tree | f3baca79fbd8314bc6b3b25e22b3b66906870073 | |
parent | 008d187f572e35a025e68476d3bb449eb7dd3db2 (diff) | |
parent | 68630cdda403271384f6af38bf3af91e2a53a862 (diff) | |
download | ohai-114db57c8ae1558f24e8b69c5ae19a59a1ca4b19.tar.gz |
Merge pull request #588 from chef/mcquin/ohai-config/load-config
Ohai::Application loads configuration file
-rw-r--r-- | CHANGELOG.md | 2 | ||||
-rw-r--r-- | DOC_CHANGES.md | 10 | ||||
-rw-r--r-- | lib/ohai/application.rb | 33 | ||||
-rw-r--r-- | lib/ohai/system.rb | 23 | ||||
-rw-r--r-- | spec/functional/application_spec.rb | 147 | ||||
-rw-r--r-- | spec/unit/application_spec.rb | 81 | ||||
-rw-r--r-- | spec/unit/system_spec.rb | 69 |
7 files changed, 309 insertions, 56 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index 2bf6d901..91f13bda 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,8 @@ Fix Darwin filesystem plugin on newer MacOSX * [**Claire McQuin**](https://github.com/mcquin): Deprecate Ohai::Config in favor of Ohai::Config.ohai. +* [**Claire McQuin**](https://github.com/mcquin): + Load a configuration file while running as an application. ## Release 8.5.0 diff --git a/DOC_CHANGES.md b/DOC_CHANGES.md index 7b832d75..56470c1d 100644 --- a/DOC_CHANGES.md +++ b/DOC_CHANGES.md @@ -20,3 +20,13 @@ subsection of the `client.rb` documentation should be updated to use If there is any mention of the ability to access configuration options via `Ohai::Config`, it should be updated to `Ohai::Config.ohai`. Additionally, it should be mentioned that `Ohai.config` is an alias for `Ohai::Config.ohai`. + +## Load a configuration file while running ohai as an application +You can specify a configuration file for ohai to load while running as an +application. For example, if your configuration file is located at +`~/.chef/config.rb` you can run ohai with that configuration file with +`ohai -c ~/.chef/config.rb`. + +When running ohai as an application and no configuration file is specified +as a command line parameter, ohai will load a configuration file from your +workstation (`config.rb` or `knife.rb`) if one is found. diff --git a/lib/ohai/application.rb b/lib/ohai/application.rb index 4388fdf7..a4b34699 100644 --- a/lib/ohai/application.rb +++ b/lib/ohai/application.rb @@ -15,6 +15,7 @@ # See the License for the specific language governing permissions and # limitations under the License. +require 'chef-config/workstation_config_loader' require 'ohai' require 'ohai/log' require 'mixlib/cli' @@ -22,6 +23,12 @@ require 'mixlib/cli' class Ohai::Application include Mixlib::CLI + option :config_file, + :short => "-c CONFIG", + :long => "--config CONFIG", + :description => "A configuration file to use", + :proc => lambda { |path| File.expand_path(path, Dir.pwd) } + option :directory, :short => "-d DIRECTORY", :long => "--directory DIRECTORY", @@ -66,7 +73,6 @@ class Ohai::Application def run configure_ohai - configure_logging run_application end @@ -74,20 +80,11 @@ class Ohai::Application @attributes = parse_options @attributes = nil if @attributes.empty? - Ohai::Config.merge_deprecated_config - Ohai.config.merge!(config) - if Ohai.config[:directory] - Ohai.config[:plugin_path] << Ohai.config[:directory] - end - end - - def configure_logging - Ohai::Log.init(Ohai.config[:log_location]) - Ohai::Log.level = Ohai.config[:log_level] + load_workstation_config end def run_application - ohai = Ohai::System.new + ohai = Ohai::System.new(config) ohai.all_plugins(@attributes) if @attributes @@ -112,4 +109,16 @@ class Ohai::Application Process.exit err end end + + private + def load_workstation_config + config_loader = ChefConfig::WorkstationConfigLoader.new( + config[:config_file], Ohai::Log + ) + begin + config_loader.load + rescue ChefConfig::ConfigurationError => config_error + Ohai::Application.fatal!(config_error.message) + end + end end diff --git a/lib/ohai/system.rb b/lib/ohai/system.rb index c98ac1af..d733191f 100644 --- a/lib/ohai/system.rb +++ b/lib/ohai/system.rb @@ -34,23 +34,22 @@ module Ohai include Ohai::Mixin::ConstantHelper attr_accessor :data + attr_reader :config attr_reader :provides_map attr_reader :v6_dependency_solver - def initialize + def initialize(config = {}) @plugin_path = "" + @config = config reset_system end def reset_system @data = Mash.new @provides_map = ProvidesMap.new - @v6_dependency_solver = Hash.new - # configure logging - Ohai::Log.init(Ohai.config[:log_location]) - Ohai::Log.level = Ohai.config[:log_level] + configure_ohai @loader = Ohai::Loader.new(self) @runner = Ohai::Runner.new(self, true) @@ -204,5 +203,19 @@ module Ohai raise ArgumentError, "I can only generate JSON for Hashes, Mashes, Arrays and Strings. You fed me a #{data.class}!" end end + + private + def configure_ohai + Ohai::Config.merge_deprecated_config + Ohai.config.merge!(@config) + + if Ohai.config[:directory] && + !Ohai.config[:plugin_path].include?(Ohai::Config[:directory]) + Ohai.config[:plugin_path] << Ohai.config[:directory] + end + + Ohai::Log.init(Ohai.config[:log_location]) + Ohai::Log.level = Ohai.config[:log_level] + end end end diff --git a/spec/functional/application_spec.rb b/spec/functional/application_spec.rb new file mode 100644 index 00000000..33992f5d --- /dev/null +++ b/spec/functional/application_spec.rb @@ -0,0 +1,147 @@ +# +# Author:: Claire McQuin <claire@chef.io> +# Copyright:: Copyright (c) 2015 Chef Software, Inc. +# License:: Apache License, Version 2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +require_relative '../spec_helper' + +require 'ohai/application' + +RSpec.describe 'Ohai::Application' do + + let(:app) { Ohai::Application.new } + let(:argv) { [] } + let(:stderr) { StringIO.new } + + before(:each) do + @original_argv = ARGV.dup + ARGV.replace(argv) + end + + after(:each) do + ARGV.replace(@original_argv) + end + + describe '#configure_ohai' do + + let(:config_content) { '' } + let(:config_dir) { Dir.mktmpdir('.chef') } + let(:config_location) { File.join(config_dir, 'config.rb') } + + before(:each) do + File.open(config_location, 'w+') do |f| + f.write(config_content) + end + end + + after(:each) do + FileUtils.rm_rf(config_dir) + end + + context 'when a configuration file is provided as a command line option' do + + let(:argv) { [ '-c', config_location + '.oops' ] } + + context 'and the configuration file does not exist' do + + it 'logs an error and terminates the application' do + expect(STDERR).to receive(:puts).with(/FATAL:/) + expect(Ohai::Log).to receive(:fatal). + with(/Specified config file #{argv[1]} does not exist/) + expect { app.configure_ohai }.to raise_error(SystemExit) + end + end + end + + context 'when a workstation configuration file exists' do + + let(:config_content) { 'ohai.disabled_plugins = [ :Foo, :Baz ]' } + + # env['KNIFE_HOME']/config.rb is the first config file the workstation + # config loader looks for: + # https://github.com/chef/chef/blob/master/chef-config/lib/chef-config/workstation_config_loader.rb#L102 + let(:env) { { 'KNIFE_HOME' => config_dir } } + + before(:each) do + allow_any_instance_of(ChefConfig::WorkstationConfigLoader). + to receive(:env).and_return(env) + end + + it 'loads the workstation configuration file' do + app.configure_ohai + expect(Ohai.config[:disabled_plugins]).to eq([ :Foo, :Baz ]) + end + end + + context 'when the configuration file contains deprecated config options' do + # For the purpose of these tests it doesn't matter if the configuration + # file was specified via command line or discovered on the local + # workstation. It's easier if we pass the configuration file as a cli + # argument (there's less to stub). + + let(:argv) { [ '-c', config_location ] } + + let(:config_content) do + <<-CONFIG +log_location "#{log_location}" +log_level :#{log_level} +Ohai::Config[:disabled_plugins] = #{disabled_plugins} +Ohai::Config[:plugin_path] << "#{plugin_path}" +CONFIG + end + + # config settings + let(:disabled_plugins) { [ :Foo, :Baz ] } + + let(:log_level) { :debug } + + let(:log_location) { 'path/to/log' } + + let(:plugin_path) { '/path/to/plugins' } + + it 'logs warnings for deprecated top-level options' do + # deprecation warnings for options need to be stubbed in the order + # they are received, in this case it's the order they appear in the + # configuration file. + options = [ :log_location, :log_level, :disabled_plugins ] + options.each do |option| + expect(Ohai::Log).to receive(:warn). + with(/Ohai::Config\[:#{option}\] is deprecated/) + end + app.configure_ohai + end + end + + context 'when the configuration file has a syntax error' do + # For the purpose of these tests it doesn't matter if the configuration + # file was specified via command line or discovered on the local + # workstation. It's easier if we pass the configuration file as a cli + # argument (there's less to stub). + + let(:argv) { [ '-c', config_location ] } + + let(:config_content) { 'config_location "blaaaaa' } + + it 'logs an error and terminates the application' do + expect(STDERR).to receive(:puts).with(/FATAL:/) + expect(Ohai::Log).to receive(:fatal). + with(/You have invalid ruby syntax in your config file/) + expect { app.configure_ohai }.to raise_error(SystemExit) + end + end + + end +end diff --git a/spec/unit/application_spec.rb b/spec/unit/application_spec.rb index 32b6f8e1..3fbb5a2e 100644 --- a/spec/unit/application_spec.rb +++ b/spec/unit/application_spec.rb @@ -35,54 +35,63 @@ RSpec.describe 'Ohai::Application' do end describe '#configure_ohai' do - it 'merges deprecated config settings into the ohai config context' do - expect(Ohai::Config).to receive(:merge_deprecated_config) - app.configure_ohai - end - - context 'when CLI options are provided' do - let(:argv) { [ '-d', directory ] } - let(:directory) { '/some/fantastic/plugins' } - - it 'does not generate deprecated config warnings for cli options' do - expect(Ohai::Log).to_not receive(:warn). - with(/Ohai::Config\[:directory\] is deprecated/) - app.configure_ohai - end - - it 'merges CLI options into the ohai config context' do - app.configure_ohai - expect(Ohai.config[:directory]).to eq(directory) - end - end - - context 'when directory is configured' do - let(:directory) { '/some/fantastic/plugins' } + describe 'loading configuration from a file' do + let(:config_file) { '/local/workstation/config' } + let(:config_loader) { instance_double('ChefConfig::WorkstationConfigLoader') } + + context 'when specified on the command line' do + let(:argv) { [ '-c', config_file ] } + + before(:each) do + if windows? + expect(ChefConfig::WorkstationConfigLoader).to receive(:new). + with("C:#{config_file}", Ohai::Log). + and_return(config_loader) + else + expect(ChefConfig::WorkstationConfigLoader).to receive(:new). + with(config_file, Ohai::Log). + and_return(config_loader) + end + end - shared_examples_for 'directory' do - it 'adds directory to plugin_path' do + it 'loads the configuration file' do + expect(config_loader).to receive(:load) app.configure_ohai - expect(Ohai.config[:plugin_path]).to include(directory) + end + + context 'when the configuration file does not exist' do + it 'terminates the application' do + expect(config_loader).to receive(:load).and_raise(ChefConfig::ConfigurationError) + expect(Ohai::Application).to receive(:fatal!) + app.configure_ohai + end end end - context 'in a configuration file' do - before do - allow(Ohai::Log).to receive(:warn). - with(/Ohai::Config\[:directory\] is deprecated/) - Ohai::Config[:directory] = directory + context 'when a local workstation config exists' do + before(:each) do + expect(ChefConfig::WorkstationConfigLoader).to receive(:new). + with(nil, Ohai::Log). + and_return(config_loader) end - include_examples 'directory' + it 'loads the configuration file' do + expect(config_loader).to receive(:load) + app.configure_ohai + end end + end - context 'as a command line option' do - let(:argv) { ['-d', directory] } + context 'when CLI options are provided' do + let(:argv) { [ '-d', directory ] } + let(:directory) { '/some/fantastic/plugins' } - include_examples 'directory' + it 'does not generate deprecated config warnings for cli options' do + expect(Ohai::Log).to_not receive(:warn). + with(/Ohai::Config\[:directory\] is deprecated/) + app.configure_ohai end end end - end diff --git a/spec/unit/system_spec.rb b/spec/unit/system_spec.rb index 0eb7f439..1d6d65f5 100644 --- a/spec/unit/system_spec.rb +++ b/spec/unit/system_spec.rb @@ -26,17 +26,80 @@ describe "Ohai::System" do let(:ohai) { Ohai::System.new } describe "#initialize" do - it "should return an Ohai::System object" do + it "returns an Ohai::System object" do expect(ohai).to be_a_kind_of(Ohai::System) end - it "should set @attributes to a ProvidesMap" do + it "sets @attributes to a ProvidesMap" do expect(ohai.provides_map).to be_a_kind_of(Ohai::ProvidesMap) end - it "should set @v6_dependency_solver to a Hash" do + it "sets @v6_dependency_solver to a Hash" do expect(ohai.v6_dependency_solver).to be_a_kind_of(Hash) end + + it 'merges deprecated config settings into the ohai config context' do + expect(Ohai::Log).to receive(:warn). + with(/Ohai::Config\[:disabled_plugins\] is deprecated/) + Ohai::Config[:disabled_plugins] = [ :Foo, :Baz ] + expect(Ohai::Config).to receive(:merge_deprecated_config). + and_call_original + Ohai::System.new + expect(Ohai.config[:disabled_plugins]).to eq([ :Foo, :Baz ]) + end + + it 'merges provided configuration options into the ohai config context' do + config = { + disabled_plugins: [ :Foo, :Baz ], + directory: '/some/extra/plugins' + } + allow(Ohai::Config).to receive(:merge_deprecated_config) + expect(Ohai.config).to receive(:merge!).with(config).and_call_original + Ohai::System.new(config) + config.each do |option, value| + expect(Ohai.config[option]).to eq(value) + end + end + + context 'when directory is configured' do + let(:directory) { '/some/fantastic/plugins' } + + it 'adds directory to plugin_path' do + Ohai.config[:directory] = directory + Ohai::System.new + expect(Ohai.config[:plugin_path]).to include(directory) + end + end + + shared_examples_for 'appendable deprecated configuration option' do + it 'logs a warning and configures the option on the ohai config context' do + Ohai::Config[option] << value + expect(Ohai::Log).to receive(:warn). + with(/Ohai::Config\[:#{option}\] is deprecated/) + Ohai::System.new + expect(Ohai.config[option]).to include(value) + end + end + + context 'when a top-level hints_path is configured' do + include_examples 'appendable deprecated configuration option' do + let(:option) { :hints_path } + let(:value) { '/path/to/hints' } + end + end + + context 'when a top-level plugin_path is configured' do + include_examples 'appendable deprecated configuration option' do + let(:option) { :plugin_path } + let(:value) { '/path/to/plugins' } + end + end + + it 'configures logging' do + expect(Ohai::Log).to receive(:init).with(Ohai.config[:log_location]) + expect(Ohai::Log).to receive(:level=).with(Ohai.config[:log_level]) + Ohai::System.new + end end when_plugins_directory "contains v6 and v7 plugins" do |