summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorClaire McQuin <claire@getchef.com>2014-05-27 10:30:28 -0700
committerClaire McQuin <claire@getchef.com>2014-06-03 09:16:53 -0700
commit5020264ab9a5f33da30a569eff6bb06516f7159c (patch)
tree6b69930a15c96d381f0093270dcf60e133d027d1
parent7588211ecb83c9592065359622ff6cef98d773af (diff)
downloadchef-5020264ab9a5f33da30a569eff6bb06516f7159c.tar.gz
set ENV vars for http proxies
-rw-r--r--lib/chef/application.rb67
-rw-r--r--lib/chef/application/apply.rb1
-rw-r--r--lib/chef/application/windows_service.rb1
-rw-r--r--spec/unit/application_spec.rb105
4 files changed, 174 insertions, 0 deletions
diff --git a/lib/chef/application.rb b/lib/chef/application.rb
index 12e1546627..04ebbba25a 100644
--- a/lib/chef/application.rb
+++ b/lib/chef/application.rb
@@ -44,6 +44,7 @@ class Chef::Application
def reconfigure
configure_chef
configure_logging
+ configure_environment_variables
end
# Get this party started
@@ -165,6 +166,14 @@ class Chef::Application
end
end
+ # Configure and set any environment variables according to the config.
+ def configure_environment_variables
+ configure_http_proxy
+ configure_https_proxy
+ configure_ftp_proxy
+ configure_no_proxy
+ end
+
# Called prior to starting the application, by the run method
def setup_application
raise Chef::Exceptions::Application, "#{self.to_s}: you must override setup_application"
@@ -242,6 +251,64 @@ class Chef::Application
Chef::Application.fatal!("Aborting due to error in '#{config_file_path}'", 2)
end
+ # Set ENV['HTTP_PROXY']
+ def configure_http_proxy
+ env['HTTP_PROXY'] = configure_proxy("http") if Chef::Config[:http_proxy]
+ end
+
+ # Set ENV['HTTPS_PROXY']
+ def configure_https_proxy
+ env['HTTPS_PROXY'] = configure_proxy("https") if Chef::Config[:https_proxy]
+ end
+
+ # Set ENV['FTP_PROXY']
+ def configure_ftp_proxy
+ env['FTP_PROXY'] = configure_proxy("ftp") if Chef::Config[:ftp_proxy]
+ end
+
+ # Set ENV['NO_PROXY']
+ def configure_no_proxy
+ env['NO_PROXY'] = Chef::Config[:no_proxy] if Chef::Config[:no_proxy]
+ end
+
+ # Builds a proxy according to http/https format. Examples:
+ # http://username:password@hostname:port
+ # https://username@hostname:port
+ # ftp://hostname:port
+ # with, when scheme = "http",
+ # hostname:port given via config[:http_proxy]
+ # username given via config[:http_proxy_user]
+ # password given via config[:http_proxy_pass]
+ def configure_proxy(scheme)
+ proxy = Chef::Config["#{scheme}_proxy"].split("#{scheme}://")
+ proxy.shift if proxy[0].empty?
+ proxy = URI.escape(proxy[0])
+
+ full_proxy = "#{scheme}://"
+ if Chef::Config["#{scheme}_proxy_user"]
+ full_proxy << encode_uri_full(Chef::Config["#{scheme}_proxy_user"])
+ if Chef::Config["#{scheme}_proxy_pass"]
+ full_proxy << ":#{encode_uri_full(Chef::Config["#{scheme}_proxy_pass"])}"
+ end
+ full_proxy << "@"
+ end
+
+ full_proxy << proxy
+ return full_proxy
+ end
+
+ # URI doesn't encode/escape reserved characters from the percent encoding set.
+ # For strings such as proxy user and proxy password we need these reserved characters
+ # to be escaped, or else the fully proxy might not be interpreted correctly.
+ def encode_uri_full(uri_str)
+ URI.escape(uri_str, "!#$&'()*+,/:;=?@[]")
+ end
+
+ # This is a hook for testing
+ def env
+ ENV
+ end
+
class << self
def debug_stacktrace(e)
message = "#{e.class}: #{e}\n#{e.backtrace.join("\n")}"
diff --git a/lib/chef/application/apply.rb b/lib/chef/application/apply.rb
index dfec31c51e..983b35d5b7 100644
--- a/lib/chef/application/apply.rb
+++ b/lib/chef/application/apply.rb
@@ -88,6 +88,7 @@ class Chef::Application::Apply < Chef::Application
parse_options
Chef::Config.merge!(config)
configure_logging
+ configure_environment_variables
end
def read_recipe_file(file_name)
diff --git a/lib/chef/application/windows_service.rb b/lib/chef/application/windows_service.rb
index bea5e9fcdc..2f81256a63 100644
--- a/lib/chef/application/windows_service.rb
+++ b/lib/chef/application/windows_service.rb
@@ -211,6 +211,7 @@ class Chef
def reconfigure(startup_parameters=[])
configure_chef startup_parameters
configure_logging
+ configure_environment_variables
Chef::Config[:chef_server_url] = config[:chef_server_url] if config.has_key? :chef_server_url
unless Chef::Config[:exception_handlers].any? {|h| Chef::Handler::ErrorReport === h}
diff --git a/spec/unit/application_spec.rb b/spec/unit/application_spec.rb
index c73ebb2e21..efde6d6690 100644
--- a/spec/unit/application_spec.rb
+++ b/spec/unit/application_spec.rb
@@ -39,6 +39,7 @@ describe Chef::Application do
@app = Chef::Application.new
@app.stub(:configure_chef).and_return(true)
@app.stub(:configure_logging).and_return(true)
+ @app.stub(:configure_environment_variables).and_return(true)
end
it "should configure chef" do
@@ -51,6 +52,10 @@ describe Chef::Application do
@app.reconfigure
end
+ it "should configure environment variables" do
+ @app.should_receive(:configure_environment_variables).and_return(true)
+ @app.reconfigure
+ end
end
describe Chef::Application do
@@ -235,6 +240,106 @@ describe Chef::Application do
end
end
+ describe "when configuring environment variables" do
+ def configure_environment_variables_stubs
+ @app.stub(:configure_http_proxy).and_return(true)
+ @app.stub(:configure_https_proxy).and_return(true)
+ @app.stub(:configure_ftp_proxy).and_return(true)
+ @app.stub(:configure_no_proxy).and_return(true)
+ end
+
+ it "should configure ENV['HTTP_PROXY']" do
+ configure_environment_variables_stubs
+ @app.should_receive(:configure_http_proxy)
+ @app.configure_environment_variables
+ end
+
+ it "should configure ENV['HTTPS_PROXY']" do
+ configure_environment_variables_stubs
+ @app.should_receive(:configure_https_proxy)
+ @app.configure_environment_variables
+ end
+
+ it "should configure ENV['FTP_PROXY']" do
+ configure_environment_variables_stubs
+ @app.should_receive(:configure_ftp_proxy)
+ @app.configure_environment_variables
+ end
+
+ it "should configure ENV['NO_PROXY']" do
+ configure_environment_variables_stubs
+ @app.should_receive(:configure_no_proxy)
+ @app.configure_environment_variables
+ end
+
+ describe "when configuring ENV['HTTP_PROXY']" do
+ before do
+ @env = {}
+ @app.stub(:env).and_return(@env)
+
+ @app.stub(:configure_https_proxy).and_return(true)
+ @app.stub(:configure_ftp_proxy).and_return(true)
+ @app.stub(:configure_no_proxy).and_return(true)
+ end
+
+ describe "when Chef::Config[:http_proxy] is not set" do
+ before do
+ Chef::Config[:http_proxy] = nil
+ end
+
+ it "should not set ENV['HTTP_PROXY']" do
+ @app.configure_environment_variables
+ @env.should == {}
+ end
+ end
+
+ describe "when Chef::Config[:http_proxy] is set" do
+ before do
+ Chef::Config[:http_proxy] = "http://hostname:port"
+ end
+
+ it "should set ENV['HTTP_PROXY'] to http://hostname:port" do
+ @app.configure_environment_variables
+ @env['HTTP_PROXY'].should == "http://hostname:port"
+ end
+
+ describe "when Chef::Config[:http_proxy_user] is set" do
+ before do
+ Chef::Config[:http_proxy_user] = "username"
+ end
+
+ it "should set ENV['HTTP_PROXY'] to http://username@hostname.port" do
+ @app.configure_environment_variables
+ @env['HTTP_PROXY'].should == "http://username@hostname:port"
+ end
+
+ describe "when Chef::Config[:http_proxy_pass] is set" do
+ before do
+ Chef::Config[:http_proxy_pass] = "password"
+ end
+
+ it "should set ENV['HTTP_PROXY'] to http://username:password@hostname:port" do
+ @app.configure_environment_variables
+ @env['HTTP_PROXY'].should == "http://username:password@hostname:port"
+ end
+ end
+ end
+
+ describe "when Chef::Config[:http_proxy_pass] is set (but not Chef::Config[:http_proxy_user])" do
+ before do
+ Chef::Config[:http_proxy_user] = nil
+ Chef::Config[:http_proxy_pass] = "password"
+ end
+
+ it "should set ENV['HTTP_PROXY'] to http://hostname:port" do
+ @app.configure_environment_variables
+ @env['HTTP_PROXY'].should == "http://hostname:port"
+ end
+ end
+ end
+ end
+ end
+
describe "class method: fatal!" do
before do
STDERR.stub(:puts).with("FATAL: blah").and_return(true)