This commit is contained in:
Teemu Matilainen 2013-06-24 08:36:57 -07:00
commit c2fcf4611d
10 changed files with 334 additions and 4 deletions

View file

@ -4,7 +4,8 @@ source 'https://rubygems.org'
gemspec
group :development do
gem 'rake'
gem 'rspec', '~> 2.11'
gem 'vagrant', github: 'mitchellh/vagrant'
gem 'vagrant-lxc', github: 'fgrehm/vagrant-lxc'
gem 'rake'
end

View file

@ -27,6 +27,7 @@ GEM
specs:
childprocess (0.3.9)
ffi (~> 1.0, >= 1.0.11)
diff-lcs (1.2.4)
erubis (2.7.0)
ffi (1.8.1)
i18n (0.6.4)
@ -36,12 +37,21 @@ GEM
net-ssh (>= 2.6.5)
net-ssh (2.6.7)
rake (10.0.4)
rspec (2.13.0)
rspec-core (~> 2.13.0)
rspec-expectations (~> 2.13.0)
rspec-mocks (~> 2.13.0)
rspec-core (2.13.1)
rspec-expectations (2.13.0)
diff-lcs (>= 1.1.3, < 2.0)
rspec-mocks (2.13.1)
PLATFORMS
ruby
DEPENDENCIES
rake
rspec (~> 2.11)
vagrant!
vagrant-cachier!
vagrant-lxc!

View file

@ -1,5 +1,11 @@
Dir['./tasks/**/*.rake'].each { |f| load f }
require 'bundler/gem_tasks'
require 'rspec/core/rake_task'
task :ci => ['spec:unit']
task :default => [:spec]
namespace :spec do
RSpec::Core::RakeTask.new('unit') do |t|
t.pattern = 'spec/unit/**/*_spec.rb'
end
end
task :spec => ['spec:unit']

View file

@ -0,0 +1,53 @@
require 'tempfile'
module VagrantPlugins
module Cachier
class Action
class ConfigureAptProxy
attr_reader :logger
def initialize(app, env)
@app = app
@logger = Log4r::Logger.new("vagrant::cachier::action::configure_apt_proxy")
end
def call(env)
@app.call env
proxy_config = env[:machine].config.apt_proxy
if !proxy_config.enabled?
logger.debug "apt_proxy not enabled or configured"
elsif !proxy_conf_capability?(env[:machine])
env[:ui].info "Skipping Apt proxy config as the machine does not support it"
else
env[:ui].info "Configuring proxy for Apt..."
write_apt_proxy_conf(env[:machine], proxy_config)
end
end
def write_apt_proxy_conf(machine, config)
logger.debug "Configuration:\n#{config}"
temp = Tempfile.new("vagrant")
temp.binmode
temp.write(config)
temp.close
machine.communicate.tap do |comm|
comm.upload(temp.path, "/tmp/vagrant-apt-proxy-conf")
comm.sudo("cat /tmp/vagrant-apt-proxy-conf > #{proxy_conf_path(machine)}")
comm.sudo("rm /tmp/vagrant-apt-proxy-conf")
end
end
def proxy_conf_capability?(machine)
machine.guest.capability?(:apt_proxy_conf)
end
def proxy_conf_path(machine)
machine.guest.capability(:apt_proxy_conf)
end
end
end
end
end

View file

@ -0,0 +1,88 @@
require 'vagrant'
module VagrantPlugins
module Cachier
class AptProxyConfig < Vagrant.plugin("2", :config)
# HTTP proxy for Apt
attr_accessor :http
# HTTPS proxy for Apt
attr_accessor :https
def initialize
@http = UNSET_VALUE
@https = UNSET_VALUE
end
def finalize!
@http = override_from_env_var('http', @http)
@http = nil if @http == UNSET_VALUE
@https = override_from_env_var('https', @https)
@https = nil if @https == UNSET_VALUE
end
def enabled?
!http.nil? || !https.nil?
end
# @return [String] the full configuration stanza
def to_s
"#{config_for('http')}#{config_for('https')}"
end
private
def override_from_env_var(proto, default)
ENV.fetch("APT_PROXY_#{proto.upcase}", default)
end
def config_for(proto)
ConfigValue.new(proto, send(proto.to_sym))
end
class ConfigValue
attr_reader :proto, :value
# @param proto [String] the protocol ("http", "https")
# @param value [Object] the configuration value
def initialize(proto, value)
@proto = proto
@value = value
end
# @return [String] the full Apt configuration line
def to_s
set? ? %Q{Acquire::#{proto}::Proxy "#{proxy_uri}";\n} : ""
end
private
def set?
value && !value.empty?
end
def direct?
value.upcase == "DIRECT"
end
def proxy_uri
direct? ? "DIRECT" : "#{prefix}#{value}#{suffix}"
end
def prefix
"#{proto}://" if value !~ %r{^.*://}
end
def suffix
":#{default_port}" if value !~ %r{:\d+$}
end
def default_port
3142
end
end
end
end
end

View file

@ -0,0 +1,13 @@
module VagrantPlugins
module Cachier
module Cap
module Debian
module AptProxyConf
def self.apt_proxy_conf(machine)
'/etc/apt/apt.conf.d/01proxy'
end
end
end
end
end
end

View file

@ -8,6 +8,11 @@ module VagrantPlugins
Config
end
config 'apt_proxy' do
require_relative 'apt_proxy_config'
AptProxyConfig
end
guest_capability 'linux', 'gemdir' do
require_relative 'cap/linux/gemdir'
Cap::Linux::Gemdir
@ -18,6 +23,11 @@ module VagrantPlugins
Cap::Debian::AptCacheDir
end
guest_capability 'debian', 'apt_proxy_conf' do
require_relative 'cap/debian/apt_proxy_conf'
Cap::Debian::AptProxyConf
end
guest_capability 'redhat', 'yum_cache_dir' do
require_relative 'cap/redhat/yum_cache_dir'
Cap::RedHat::YumCacheDir
@ -30,7 +40,9 @@ module VagrantPlugins
install_action_hook = lambda do |hook|
require_relative 'action'
require_relative 'action/configure_apt_proxy'
hook.after Vagrant::Action::Builtin::Provision, VagrantPlugins::Cachier::Action::Install
hook.after Vagrant::Action::Builtin::Provision, VagrantPlugins::Cachier::Action::ConfigureAptProxy
end
action_hook 'set-shared-cache-on-machine-up', :machine_action_up, &install_action_hook
action_hook 'set-shared-cache-on-machine-reload', :machine_action_reload, &install_action_hook

10
spec/spec_helper.rb Normal file
View file

@ -0,0 +1,10 @@
RSpec.configure do |config|
config.expect_with :rspec do |c|
c.syntax = :expect
end
config.color = true
config.tty = true
end
require 'tempfile'
require 'vagrant-cachier'

View file

@ -0,0 +1,103 @@
def config_with(options)
instance.tap do |c|
options.each_pair { |k, v| c.send("#{k}=".to_sym, v) }
c.finalize!
end
end
def conf_line(proto, name, port = 3142)
if name == :direct
%Q{Acquire::#{proto}::Proxy "DIRECT";\n}
else
%Q{Acquire::#{proto}::Proxy "#{proto}://#{name}:#{port}";\n}
end
end
def conf_line_pattern(proto, name, port = 3142)
"^#{Regexp.escape(conf_line(proto, name, port))}"
end
shared_examples "apt proxy config" do |proto|
context "#{proto} proxy" do
context "with ip" do
subject { config_with(proto => "10.1.2.3") }
its(:enabled?) { should be_true }
its(:to_s) { should eq conf_line(proto, "10.1.2.3") }
end
context "with name" do
subject { config_with(proto => "proxy.example.com") }
its(:enabled?) { should be_true }
its(:to_s) { should eq conf_line(proto, "proxy.example.com") }
end
context "with name and port" do
subject { config_with(proto => "acng:8080") }
its(:enabled?) { should be_true }
its(:to_s) { should eq conf_line(proto, "acng", 8080) }
end
context "with protocol and name" do
subject { config_with(proto => "#{proto}://proxy.foo.tld") }
its(:enabled?) { should be_true }
its(:to_s) { should eq conf_line(proto, "proxy.foo.tld") }
end
context "with protocol and name and port" do
subject { config_with(proto => "#{proto}://prism.nsa.gov:666") }
its(:enabled?) { should be_true }
its(:to_s) { should eq conf_line(proto, "prism.nsa.gov", 666) }
end
["DIRECT", "direct"].each do |direct|
context "with #{direct.inspect}" do
subject { config_with(proto => direct) }
its(:enabled?) { should be_true }
its(:to_s) { should eq conf_line(proto, :direct) }
end
end
[false, ""].each do |unset|
context "with #{unset.inspect}" do
subject { config_with(proto => unset) }
its(:enabled?) { should be_true }
its(:to_s) { should eq "" }
end
end
context "with nil" do
subject { config_with(proto => nil) }
its(:enabled?) { should be_false }
its(:to_s) { should eq "" }
end
end
end
shared_examples "apt proxy env var" do |var, proto|
context var do
let(:conf) { config_with(http: "acng:8080", https: "ssl-proxy:8443") }
it "sets #{proto} proxy" do
ENV[var] = "myproxy"
expect(conf.to_s).to match conf_line_pattern(proto, "myproxy")
end
it "does not set other proxies" do
ENV[var] = "myproxy:2345"
conf = config_with({})
expect(conf.to_s).to eq conf_line(proto, "myproxy", 2345)
end
it "sets empty configuration" do
ENV[var] = ""
expect(conf.to_s).to_not match %r{#{proto}://}
end
it "sets direct configuration" do
ENV[var] = "direct"
expect(conf.to_s).to match conf_line_pattern(proto, :direct)
end
end
end

View file

@ -0,0 +1,34 @@
require 'spec_helper'
require 'unit/support/shared/apt_proxy_config'
require 'vagrant-cachier/apt_proxy_config'
describe VagrantPlugins::Cachier::AptProxyConfig do
let(:instance) { described_class.new }
before :each do
# Ensure tests are not affected by environment variables
%w[APT_PROXY_HTTP APT_PROXY_HTTPS].each { |k| ENV.delete(k) }
end
context "defaults" do
subject { config_with({}) }
its(:enabled?) { should be_false }
its(:to_s) { should eq "" }
end
include_examples "apt proxy config", "http"
include_examples "apt proxy config", "https"
context "with both http and https proxies" do
subject { config_with(http: "10.2.3.4", https: "ssl-proxy:8443") }
its(:enabled?) { should be_true }
its(:to_s) { should match conf_line_pattern("http", "10.2.3.4") }
its(:to_s) { should match conf_line_pattern("https", "ssl-proxy", 8443) }
end
context "with env var" do
include_examples "apt proxy env var", "APT_PROXY_HTTP", "http"
include_examples "apt proxy env var", "APT_PROXY_HTTPS", "https"
end
end