summaryrefslogtreecommitdiff
path: root/chef-config
diff options
context:
space:
mode:
authortyler-ball <tyleraball@gmail.com>2015-12-08 17:02:23 -0700
committertyler-ball <tyleraball@gmail.com>2015-12-09 14:23:54 -0700
commit85d0407a16fa4dfc479d550a96355a6d11f4f551 (patch)
tree5be428017e0883fdcaa19c74308bb73783270071 /chef-config
parent200c3e5b71ec269efffbfb97e94f1a7aada951af (diff)
downloadchef-85d0407a16fa4dfc479d550a96355a6d11f4f551.tar.gz
Moving the proxy export to environment varibles into Chef::Config
Diffstat (limited to 'chef-config')
-rw-r--r--chef-config/lib/chef-config/config.rb61
-rw-r--r--chef-config/spec/unit/config_spec.rb108
2 files changed, 169 insertions, 0 deletions
diff --git a/chef-config/lib/chef-config/config.rb b/chef-config/lib/chef-config/config.rb
index 49d775232d..113bf481ff 100644
--- a/chef-config/lib/chef-config/config.rb
+++ b/chef-config/lib/chef-config/config.rb
@@ -26,6 +26,7 @@ require 'chef-config/logger'
require 'chef-config/windows'
require 'chef-config/path_helper'
require 'mixlib/shellout'
+require 'uri'
module ChefConfig
@@ -710,6 +711,66 @@ module ChefConfig
config_context :chefdk do
end
+ configurable(:http_proxy)
+ configurable(:http_proxy_user)
+ configurable(:http_proxy_pass)
+ configurable(:https_proxy)
+ configurable(:https_proxy_user)
+ configurable(:https_proxy_pass)
+ configurable(:ftp_proxy)
+ configurable(:ftp_proxy_user)
+ configurable(:ftp_proxy_pass)
+ configurable(:no_proxy)
+
+ # Public method that users should call to export proxies to the appropriate
+ # environment variables. This method should be called after the config file is
+ # parsed and loaded.
+ # TODO add some post-file-parsing logic that automatically calls this so
+ # users don't have to
+ def self.export_proxies
+ export_proxy("http", http_proxy, http_proxy_user, http_proxy_pass) if http_proxy
+ export_proxy("https", https_proxy, https_proxy_user, https_proxy_pass) if https_proxy
+ export_proxy("ftp", ftp_proxy, ftp_proxy_user, ftp_proxy_pass) if ftp_proxy
+ export_no_proxy("no_proxy", no_proxy) if no_proxy
+ end
+
+ # Builds a proxy uri and exports it to the appropriate environment variables. Examples:
+ # http://username:password@hostname:port
+ # https://username@hostname:port
+ # ftp://hostname:port
+ # when
+ # scheme = "http", "https", or "ftp"
+ # hostport = hostname:port or scheme://hostname:port
+ # user = username
+ # pass = password
+ # @api private
+ def self.export_proxy(scheme, path, user, pass)
+ path = "#{scheme}://#{path}" unless path.include?('://')
+ # URI.split returns the following parts:
+ # [scheme, userinfo, host, port, registry, path, opaque, query, fragment]
+ parts = URI.split(URI.encode(path))
+ # URI::Generic.build requires an integer for the port, but URI::split gives
+ # returns a string for the port.
+ parts[3] = parts[3].to_i if parts[3]
+ if user && !user.empty?
+ userinfo = URI.encode(URI.encode(user), '@:')
+ if pass
+ userinfo << ":#{URI.encode(URI.encode(pass), '@:')}"
+ end
+ parts[1] = userinfo
+ end
+
+ path = URI::Generic.build(parts).to_s
+ ENV["#{scheme}_proxy".downcase] = path unless ENV["#{scheme}_proxy".downcase]
+ ENV["#{scheme}_proxy".upcase] = path unless ENV["#{scheme}_proxy".upcase]
+ end
+
+ # @api private
+ def self.export_no_proxy(value)
+ ENV['no_proxy'] = value unless ENV['no_proxy']
+ ENV['NO_PROXY'] = value unless ENV['NO_PROXY']
+ end
+
# Chef requires an English-language UTF-8 locale to function properly. We attempt
# to use the 'locale -a' command and search through a list of preferences until we
# find one that we can use. On Ubuntu systems we should find 'C.UTF-8' and be
diff --git a/chef-config/spec/unit/config_spec.rb b/chef-config/spec/unit/config_spec.rb
index 4af5d4b7c7..0a3dca5b5a 100644
--- a/chef-config/spec/unit/config_spec.rb
+++ b/chef-config/spec/unit/config_spec.rb
@@ -571,6 +571,114 @@ RSpec.describe ChefConfig::Config do
end
end
+ describe "export_proxies" do
+ let(:http_proxy) { "http://localhost:7979" }
+ let(:https_proxy) { "https://localhost:7979" }
+ let(:ftp_proxy) { "ftp://localhost:7979" }
+ let(:proxy_user) { "http_user" }
+ let(:proxy_pass) { "http_pass" }
+
+ context "when http_proxy, proxy_pass and proxy_user are set" do
+ before do
+ ChefConfig::Config.http_proxy = http_proxy
+ ChefConfig::Config.http_proxy_user = proxy_user
+ ChefConfig::Config.http_proxy_pass = proxy_pass
+ end
+ it "exports ENV['http_proxy']" do
+ expect(ENV).to receive(:[]=).with('http_proxy', "http://http_user:http_pass@localhost:7979")
+ expect(ENV).to receive(:[]=).with('HTTP_PROXY', "http://http_user:http_pass@localhost:7979")
+ ChefConfig::Config.export_proxies
+ end
+ end
+
+ context "when https_proxy, proxy_pass and proxy_user are set" do
+ before do
+ ChefConfig::Config.https_proxy = https_proxy
+ ChefConfig::Config.https_proxy_user = proxy_user
+ ChefConfig::Config.https_proxy_pass = proxy_pass
+ end
+ it "exports ENV['https_proxy']" do
+ expect(ENV).to receive(:[]=).with('https_proxy', "https://http_user:http_pass@localhost:7979")
+ expect(ENV).to receive(:[]=).with('HTTPS_PROXY', "https://http_user:http_pass@localhost:7979")
+ ChefConfig::Config.export_proxies
+ end
+ end
+
+ context "when ftp_proxy, proxy_pass and proxy_user are set" do
+ before do
+ ChefConfig::Config.ftp_proxy = ftp_proxy
+ ChefConfig::Config.ftp_proxy_user = proxy_user
+ ChefConfig::Config.ftp_proxy_pass = proxy_pass
+ end
+ it "exports ENV['ftp_proxy']" do
+ expect(ENV).to receive(:[]=).with('ftp_proxy', "ftp://http_user:http_pass@localhost:7979")
+ expect(ENV).to receive(:[]=).with('FTP_PROXY', "ftp://http_user:http_pass@localhost:7979")
+ ChefConfig::Config.export_proxies
+ end
+ end
+
+ shared_examples "no user pass" do
+ it "does not populate the user or password" do
+ expect(ENV).to receive(:[]=).with('http_proxy', "http://localhost:7979")
+ expect(ENV).to receive(:[]=).with('HTTP_PROXY', "http://localhost:7979")
+ ChefConfig::Config.export_proxies
+ end
+ end
+
+ context "when proxy_pass and proxy_user are passed as empty strings" do
+ before do
+ ChefConfig::Config.http_proxy = http_proxy
+ ChefConfig::Config.http_proxy_user = ""
+ ChefConfig::Config.http_proxy_pass = proxy_pass
+ end
+ include_examples "no user pass"
+ end
+
+ context "when proxy_pass and proxy_user are not provided" do
+ before do
+ ChefConfig::Config.http_proxy = http_proxy
+ end
+ include_examples "no user pass"
+ end
+
+ context "when the proxy is provided without a scheme" do
+ before do
+ ChefConfig::Config.http_proxy = "localhost:1111"
+ end
+ it "automatically adds the scheme to the proxy url" do
+ expect(ENV).to receive(:[]=).with('http_proxy', "http://localhost:1111")
+ expect(ENV).to receive(:[]=).with('HTTP_PROXY', "http://localhost:1111")
+ ChefConfig::Config.export_proxies
+ end
+ end
+
+ shared_examples "no export" do
+ it "does not export any proxy settings" do
+ ChefConfig::Config.export_proxies
+ expect(ENV['http_proxy']).to eq(nil)
+ expect(ENV['https_proxy']).to eq(nil)
+ expect(ENV['ftp_proxy']).to eq(nil)
+ expect(ENV['no_proxy']).to eq(nil)
+ end
+ end
+
+ context "when nothing is set" do
+ include_examples "no export"
+ end
+
+ context "when all the users and passwords are set but no proxies are set" do
+ before do
+ ChefConfig::Config.http_proxy_user = proxy_user
+ ChefConfig::Config.http_proxy_pass = proxy_pass
+ ChefConfig::Config.https_proxy_user = proxy_user
+ ChefConfig::Config.https_proxy_pass = proxy_pass
+ ChefConfig::Config.ftp_proxy_user = proxy_user
+ ChefConfig::Config.ftp_proxy_pass = proxy_pass
+ end
+ include_examples "no export"
+ end
+ end
+
describe "allowing chefdk configuration outside of chefdk" do
it "allows arbitrary settings in the chefdk config context" do