diff --git a/README.md b/README.md index ab2e594..0a11951 100644 --- a/README.md +++ b/README.md @@ -21,6 +21,7 @@ The plugin can set: * generic `http_proxy` etc. environment variables that many programs support * default proxy configuration for all Chef provisioners * proxy configuration for Apt +* proxy configuration for docker * proxy configuration for npm * proxy configuration for Yum * proxy configuration for PEAR diff --git a/lib/vagrant-proxyconf/action.rb b/lib/vagrant-proxyconf/action.rb index 72ab287..632a448 100644 --- a/lib/vagrant-proxyconf/action.rb +++ b/lib/vagrant-proxyconf/action.rb @@ -1,6 +1,7 @@ require 'vagrant/action/builtin/call' require_relative 'action/configure_apt_proxy' require_relative 'action/configure_chef_proxy' +require_relative 'action/configure_docker_proxy' require_relative 'action/configure_env_proxy' require_relative 'action/configure_git_proxy' require_relative 'action/configure_npm_proxy' @@ -32,6 +33,7 @@ def self.configure_after_provisoner b.use Builtin::Call, IsEnabled do |env, b2| next if !env[:result] + b2.use ConfigureDockerProxy b2.use ConfigureGitProxy b2.use ConfigureNpmProxy b2.use ConfigurePearProxy @@ -51,6 +53,7 @@ def self.config_actions b2.use ConfigureAptProxy b2.use ConfigureChefProxy + b2.use ConfigureDockerProxy b2.use ConfigureEnvProxy b2.use ConfigureGitProxy b2.use ConfigureNpmProxy diff --git a/lib/vagrant-proxyconf/action/configure_docker_proxy.rb b/lib/vagrant-proxyconf/action/configure_docker_proxy.rb new file mode 100644 index 0000000..aee9608 --- /dev/null +++ b/lib/vagrant-proxyconf/action/configure_docker_proxy.rb @@ -0,0 +1,75 @@ +require_relative 'base' +require_relative '../resource' +require_relative '../userinfo_uri' + +module VagrantPlugins + module ProxyConf + class Action + # Action for configuring Docker on the guest + class ConfigureDockerProxy < Base + def config_name + 'docker_proxy' + end + + private + + def config + # Use global proxy config + @config ||= finalize_config(@machine.config.proxy) + end + + def configure_machine + logger.info('Writing the proxy configuration to docker config') + write_docker_config + end + + def docker + if config_path && config_path.include?('docker.io') + 'docker.io' + else + 'docker' + end + end + + def write_docker_config + tmp = "/tmp/vagrant-proxyconf" + path = config_path + + sed_script = docker_sed_script + local_tmp = tempfile(docker_config) + + @machine.communicate.tap do |comm| + comm.sudo("rm #{tmp}", error_check: false) + comm.upload(local_tmp.path, tmp) + comm.sudo("touch #{path}") + comm.sudo("sed -e '#{sed_script}' #{path} > #{path}.new") + comm.sudo("cat #{tmp} >> #{path}.new") + comm.sudo("chmod 0644 #{path}.new") + comm.sudo("chown root:root #{path}.new") + comm.sudo("mv #{path}.new #{path}") + comm.sudo("rm #{tmp}") + comm.sudo("service #{docker} restart || /etc/init.d/#{docker} restart") + end + end + + def docker_sed_script + <<-SED.gsub(/^\s+/, '') + /^export HTTP_PROXY=/ d + /^export NO_PROXY=/ d + /^export http_proxy=/ d + /^export no_proxy=/ d + SED + end + + def docker_config + <<-CONFIG.gsub(/^\s+/, '') + export HTTP_PROXY=#{config.http || ''} + export NO_PROXY=#{config.no_proxy || ''} + export http_proxy=#{config.http || ''} + export no_proxy=#{config.no_proxy || ''} + CONFIG + end + end + end + end +end diff --git a/lib/vagrant-proxyconf/cap/linux/docker_proxy_conf.rb b/lib/vagrant-proxyconf/cap/linux/docker_proxy_conf.rb new file mode 100644 index 0000000..ece2c3a --- /dev/null +++ b/lib/vagrant-proxyconf/cap/linux/docker_proxy_conf.rb @@ -0,0 +1,28 @@ +require_relative '../util' + +module VagrantPlugins + module ProxyConf + module Cap + module Linux + # Capability for docker proxy configuration + module DockerProxyConf + # @return [String, false] the path to docker or `false` if not found + def self.docker_proxy_conf(machine) + docker_command = 'docker' if Util.which(machine, 'docker') + docker_command = 'docker.io' if Util.which(machine, 'docker.io') + + return false if docker_command.nil? + + if machine.communicate.test('cat /etc/redhat-release') + "/etc/sysconfig/#{docker_command}" + elsif machine.communicate.test('ls /var/lib/boot2docker/') + "/var/lib/boot2docker/profile" + else + "/etc/default/#{docker_command}" + end + end + end + end + end + end +end diff --git a/lib/vagrant-proxyconf/capability.rb b/lib/vagrant-proxyconf/capability.rb index 31d2c0c..08d4221 100644 --- a/lib/vagrant-proxyconf/capability.rb +++ b/lib/vagrant-proxyconf/capability.rb @@ -8,6 +8,11 @@ class Plugin < Vagrant.plugin('2') Cap::Debian::AptProxyConf end + guest_capability 'linux', 'docker_proxy_conf' do + require_relative 'cap/linux/docker_proxy_conf' + Cap::Linux::DockerProxyConf + end + guest_capability 'linux', 'env_proxy_conf' do require_relative 'cap/linux/env_proxy_conf' Cap::Linux::EnvProxyConf diff --git a/locales/en.yml b/locales/en.yml index 018aed3..3a11f32 100644 --- a/locales/en.yml +++ b/locales/en.yml @@ -8,6 +8,14 @@ en: configuring: |- Configuring proxy for Apt... + docker_proxy: + not_enabled: |- + docker_proxy not enabled or configured + not_supported: |- + Skipping Docker proxy config as the machine does not support it + configuring: |- + Configuring proxy for Docker... + chef_proxy: no_provisioners: |- No Chef provisioners configured diff --git a/spec/unit/vagrant-proxyconf/action/configure_docker_proxy_spec.rb b/spec/unit/vagrant-proxyconf/action/configure_docker_proxy_spec.rb new file mode 100644 index 0000000..5983ee5 --- /dev/null +++ b/spec/unit/vagrant-proxyconf/action/configure_docker_proxy_spec.rb @@ -0,0 +1,10 @@ +require 'spec_helper' +require 'vagrant-proxyconf/action/configure_docker_proxy' + +describe VagrantPlugins::ProxyConf::Action::ConfigureDockerProxy do + + describe '#config_name' do + subject { described_class.new(double, double).config_name } + it { should eq 'docker_proxy' } + end +end diff --git a/spec/unit/vagrant-proxyconf/cap/linux/docker_proxy_conf_spec.rb b/spec/unit/vagrant-proxyconf/cap/linux/docker_proxy_conf_spec.rb new file mode 100644 index 0000000..790a095 --- /dev/null +++ b/spec/unit/vagrant-proxyconf/cap/linux/docker_proxy_conf_spec.rb @@ -0,0 +1,78 @@ +require 'spec_helper' +require 'vagrant-proxyconf/cap/linux/docker_proxy_conf' +require 'vagrant-proxyconf/cap/util' + +describe VagrantPlugins::ProxyConf::Cap::Linux::DockerProxyConf do + + describe '.docker_proxy_conf' do + let(:machine) { double } + it "returns the path when docker is installed on Redhat" do + VagrantPlugins::ProxyConf::Cap::Util.stub(:which) do |_m, c| + if c == 'docker' + '/path/to/docker' + else + false + end + end + machine.stub_chain(:communicate, :test) do |c| + if c == 'cat /etc/redhat-release' + true + else + false + end + end + + expect(described_class.docker_proxy_conf(machine)).to eq '/etc/sysconfig/docker' + end + + it "returns the path when docker is installed on Debian or Ubuntu" do + VagrantPlugins::ProxyConf::Cap::Util.stub(:which) do |_m, c| + if c == 'docker' + '/path/to/docker' + else + false + end + end + machine.stub_chain(:communicate, :test).and_return(false) + + expect(described_class.docker_proxy_conf(machine)).to eq '/etc/default/docker' + end + + it "returns the path when docker.io is installed on Ubuntu 14.04 or higher" do + VagrantPlugins::ProxyConf::Cap::Util.stub(:which) do |_m, c| + if c == 'docker.io' + '/path/to/docker.io' + else + false + end + end + machine.stub_chain(:communicate, :test).and_return(false) + + expect(described_class.docker_proxy_conf(machine)).to eq '/etc/default/docker.io' + end + + it "returns the path when docker is installed on boot2docker" do + VagrantPlugins::ProxyConf::Cap::Util.stub(:which) do |_m, c| + if c == 'docker' + '/path/to/docker' + else + false + end + end + machine.stub_chain(:communicate, :test) do |c| + if c == 'ls /var/lib/boot2docker' + true + else + false + end + end + + expect(described_class.docker_proxy_conf(machine)).to eq '/etc/default/docker' + end + + it "returns false when docker is not installed" do + VagrantPlugins::ProxyConf::Cap::Util.stub(which: false) + expect(described_class.docker_proxy_conf(machine)).to be_false + end + end +end