diff options
author | tyler-ball <tyleraball@gmail.com> | 2015-12-08 17:02:23 -0700 |
---|---|---|
committer | tyler-ball <tyleraball@gmail.com> | 2015-12-09 14:23:54 -0700 |
commit | 85d0407a16fa4dfc479d550a96355a6d11f4f551 (patch) | |
tree | 5be428017e0883fdcaa19c74308bb73783270071 /chef-config | |
parent | 200c3e5b71ec269efffbfb97e94f1a7aada951af (diff) | |
download | chef-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.rb | 61 | ||||
-rw-r--r-- | chef-config/spec/unit/config_spec.rb | 108 |
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 |