diff options
author | danielsdeleo <dan@opscode.com> | 2013-10-14 15:20:46 -0700 |
---|---|---|
committer | danielsdeleo <dan@opscode.com> | 2013-10-16 13:53:37 -0700 |
commit | dd998f23aa904011fa3aeef40e2fae31273ad4e5 (patch) | |
tree | 0f42bd77f794f7ab91733a2d89ccccfbcfa96114 /lib | |
parent | 3b877d8956531eb18ca5b398e2b2c8b4e33b71ce (diff) | |
download | chef-dd998f23aa904011fa3aeef40e2fae31273ad4e5.tar.gz |
Load client/solo config via ConfigFetcher
* Uses Chef::HTTP::Simple rather than Chef::REST to fetch files
* Re-use error handling logic in ConfigFetcher
Diffstat (limited to 'lib')
-rw-r--r-- | lib/chef/application.rb | 72 | ||||
-rw-r--r-- | lib/chef/config_fetcher.rb | 33 | ||||
-rw-r--r-- | lib/chef/knife.rb | 36 |
3 files changed, 64 insertions, 77 deletions
diff --git a/lib/chef/application.rb b/lib/chef/application.rb index caa6358aa2..7b57556ce2 100644 --- a/lib/chef/application.rb +++ b/lib/chef/application.rb @@ -76,66 +76,18 @@ class Chef::Application # Parse the config file def load_config_file - if !config[:config_file] + config_fetcher = Chef::ConfigFetcher.new(config[:config_file], Chef::Config.config_file_jail) + if config[:config_file].nil? Chef::Log.warn("No config file found or specified on command line, using command line options.") - Chef::Config.merge!(config) - return - end - - if !Chef::Application.config_file_exists?(config[:config_file]) + elsif config_fetcher.config_missing? Chef::Log.warn("*****************************************") - if !File.exists?(config[:config_file]) - Chef::Log.warn("Did not find config file: #{config[:config_file]}, using command line options.") - else - Chef::Log.warn("Config file #{config[:config_file]} not inside the jail #{Chef::Config.config_file_jail}, using command line options.", 2) - end + Chef::Log.warn("Did not find config file: #{config[:config_file]}, using command line options.") Chef::Log.warn("*****************************************") - - Chef::Config.merge!(config) - return - end - - begin - case config[:config_file] - when /^(http|https):\/\// - Chef::REST.new("", nil, nil).fetch(config[:config_file]) { |f| apply_config(f.path) } - else - ::File::open(config[:config_file]) { |f| apply_config(f.path) } - end - rescue SocketError => error - Chef::Application.fatal!("Error getting config file #{config[:config_file]}", 2) - rescue Chef::Exceptions::ConfigurationError => error - Chef::Application.fatal!("Error processing config file #{config[:config_file]} with error #{error.message}", 2) - rescue Exception => error - Chef::Application.fatal!("Unknown error processing config file #{config[:config_file]} with error #{error.message}", 2) - end - end - - # Determines whether a config file exists, taking into account file existence - # as well as Chef::Config.config_file_jail (if they are not under the jail, - # this method will return false). Takes symlinks and relative paths into - # account. - def self.config_file_exists?(config_file) - if config_file =~ /^(http|https):\/\// - return true - end - - begin - real_config_file = Pathname.new(config_file).realpath.to_s - rescue Errno::ENOENT - return false - end - - return true if !Chef::Config.config_file_jail - - begin - jail = Pathname.new(Chef::Config.config_file_jail).realpath.to_s - rescue Errno::ENOENT - Chef::Log.warn("Config file jail #{Chef::Config.config_file_jail} does not exist: will not load any config file.") - return false + else + config_content = config_fetcher.read_config + apply_config(config_content, config[:config_file]) end - - Chef::ChefFS::PathUtils.descendant_of?(real_config_file, jail) + Chef::Config.merge!(config) end # Initialize and configure the logger. @@ -263,9 +215,13 @@ class Chef::Application private - def apply_config(config_file_path) - Chef::Config.from_file(config_file_path) + def apply_config(config_content, config_file_path) + Chef::Config.from_string(config_content, config_file_path) Chef::Config.merge!(config) + rescue Chef::Exceptions::ConfigurationError => error + Chef::Application.fatal!("Error processing config file #{config[:config_file]} with error #{error.message}", 2) + rescue Exception => error + Chef::Application.fatal!("Unknown error processing config file #{config[:config_file]} with error #{error.message}", 2) end class << self diff --git a/lib/chef/config_fetcher.rb b/lib/chef/config_fetcher.rb index 129d8bed62..2400dc6897 100644 --- a/lib/chef/config_fetcher.rb +++ b/lib/chef/config_fetcher.rb @@ -1,11 +1,17 @@ +require 'chef/application' +require 'chef/chef_fs/path_utils' require 'chef/http/simple' +require 'chef/json_compat' + class Chef class ConfigFetcher attr_reader :config_location + attr_reader :config_file_jail - def initialize(config_location) + def initialize(config_location, config_file_jail) @config_location = config_location + @config_file_jail = config_file_jail end def fetch_json @@ -27,7 +33,7 @@ class Chef def fetch_remote_config http.get("") - rescue SocketError, SystemCallError => error + rescue SocketError, SystemCallError, Net::HTTPServerException => error Chef::Application.fatal!("Cannot fetch config '#{config_location}': '#{error.class}: #{error.message}", 2) end @@ -39,6 +45,29 @@ class Chef Chef::Application.fatal!("Permissions are incorrect on #{config_location}. Please chmod a+r #{config_location}", 2) end + def config_missing? + return true if remote_config? + + # Check if the config file exists, and check if it is underneath the config file jail + begin + real_config_file = Pathname.new(config_file).realpath.to_s + rescue Errno::ENOENT + return false + end + + # If realpath succeeded, the file exists + return true if !config_file_jail + + begin + real_jail = Pathname.new(config_file_jail).realpath.to_s + rescue Errno::ENOENT + Chef::Log.warn("Config file jail #{config_file_jail} does not exist: will not load any config file.") + return false + end + + Chef::ChefFS::PathUtils.descendant_of?(real_config_file, real_jail) + end + def http Chef::HTTP::Simple.new(config_location) end diff --git a/lib/chef/knife.rb b/lib/chef/knife.rb index dbb719c30a..5d455f9b24 100644 --- a/lib/chef/knife.rb +++ b/lib/chef/knife.rb @@ -20,6 +20,7 @@ require 'forwardable' require 'chef/version' require 'mixlib/cli' +require 'chef/config_fetcher' require 'chef/mixin/convert_to_class_name' require 'chef/mixin/path_sanity' require 'chef/knife/core/subcommand_loader' @@ -335,7 +336,8 @@ class Chef end candidate_configs.each do | candidate_config | - if Chef::Application.config_file_exists?(candidate_config) + fetcher = Chef::ConfigFetcher.new(candidate_config, Chef::Config::config_file_jail) + if !fetcher.config_missing? return candidate_config end end @@ -402,20 +404,20 @@ class Chef end def configure_chef - if config[:config_file] - if !Chef::Application.config_file_exists?(config[:config_file]) - ui.error("Specified config file #{config[:config_file]} does not exist#{Chef::Config.config_file_jail ? " or is not under config file jail #{Chef::Config.config_file_jail}" : ""}!") - exit 1 - end - else + if !config[:config_file] located_config_file = self.class.locate_config_file config[:config_file] = located_config_file if located_config_file end # Don't try to load a knife.rb if it wasn't specified. if config[:config_file] + fetcher = Chef::ConfigFetcher.new(config[:config_file], Chef::Config.config_file_jail) + if fetcher.config_missing?(config[:config_file]) + ui.error("Specified config file #{config[:config_file]} does not exist#{Chef::Config.config_file_jail ? " or is not under config file jail #{Chef::Config.config_file_jail}" : ""}!") + exit 1 + end Chef::Log.debug("Using configuration from #{config[:config_file]}") - read_config_file(config[:config_file]) + read_config(fetcher.read_config, config[:config_file]) else # ...but do log a message if no config was found. Chef::Config[:color] = config[:color] @@ -426,24 +428,24 @@ class Chef apply_computed_config end - def read_config_file(file) - Chef::Config.from_file(file) + def read_config(config_content, config_file_path) + Chef::Config.from_string(config_content, config_file_path) rescue SyntaxError => e - ui.error "You have invalid ruby syntax in your config file #{file}" + ui.error "You have invalid ruby syntax in your config file #{config_file_path}" ui.info(ui.color(e.message, :red)) - if file_line = e.message[/#{Regexp.escape(file)}:[\d]+/] + if file_line = e.message[/#{Regexp.escape(config_file_path)}:[\d]+/] line = file_line[/:([\d]+)$/, 1].to_i - highlight_config_error(file, line) + highlight_config_error(config_file_path, line) end exit 1 rescue Exception => e - ui.error "You have an error in your config file #{file}" + ui.error "You have an error in your config file #{config_file_path}" ui.info "#{e.class.name}: #{e.message}" - filtered_trace = e.backtrace.grep(/#{Regexp.escape(file)}/) + filtered_trace = e.backtrace.grep(/#{Regexp.escape(config_file_path)}/) filtered_trace.each {|line| ui.msg(" " + ui.color(line, :red))} if !filtered_trace.empty? - line_nr = filtered_trace.first[/#{Regexp.escape(file)}:([\d]+)/, 1] - highlight_config_error(file, line_nr.to_i) + line_nr = filtered_trace.first[/#{Regexp.escape(config_file_path)}:([\d]+)/, 1] + highlight_config_error(config_file_path, line_nr.to_i) end exit 1 |