landrush 0.3.1 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -44,9 +44,9 @@ Linux guests using iptables should automatically have their DNS traffic redirect
44
44
 
45
45
  I'm currently developing this on OS X 10.8, and there's a nice trick you can pull to unobtrusibly add a secondary DNS server only for specific domains.
46
46
 
47
- All you do is drop a file in `/etc/resolvers/$DOMAIN` with information on how to connect to the DNS server you'd like to use for that domain.
47
+ All you do is drop a file in `/etc/resolver/$DOMAIN` with information on how to connect to the DNS server you'd like to use for that domain.
48
48
 
49
- So what I do is name all of my vagrant servers with the pattern `$host.vagrant.dev` and then drop a file called `/etc/resolvers/vagrant.dev` with these contents:
49
+ So what I do is name all of my vagrant servers with the pattern `$host.vagrant.dev` and then drop a file called `/etc/resolver/vagrant.dev` with these contents:
50
50
 
51
51
  ```
52
52
  # Use landrush server for this domain
@@ -54,6 +54,15 @@ nameserver 127.0.0.1
54
54
  port 10053
55
55
  ```
56
56
 
57
+ Once you have done this, you can run `scutil --dns` to confirm that the DNS resolution is working -- you should see something like:
58
+ ```
59
+ resolver #8
60
+ domain : vagrant.dev
61
+ nameserver[0] : 127.0.0.1
62
+ port : 10053
63
+ ```
64
+
65
+
57
66
  This gives us automatic access to the landrush hosts without having to worry about it getting in the way of our normal DNS config.
58
67
 
59
68
  ## Work in Progress - Lots to do!
@@ -0,0 +1,29 @@
1
+ module Landrush
2
+ module Action
3
+ class InstallPrerequisites
4
+ def initialize(app, env)
5
+ @app = app
6
+ end
7
+
8
+ def call(env)
9
+ if env[:global_config].landrush.enabled?
10
+ @machine = env[:machine]
11
+ @machine.ui.info('setting up prerequisites')
12
+
13
+ install_prerequisites
14
+ end
15
+
16
+ @app.call(env)
17
+ end
18
+
19
+ def install_prerequisites
20
+ unless @machine.guest.capability(:iptables_installed)
21
+ @machine.ui.info('iptables not installed, installing it')
22
+ @machine.guest.capability(:install_iptables)
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
28
+
29
+
@@ -1,33 +1,48 @@
1
1
  module Landrush
2
2
  module Action
3
3
  class RedirectDns
4
+ SUPPORTED_PROVIDERS = {
5
+ 'VagrantPlugins::ProviderVirtualBox::Provider' => :virtualbox,
6
+ 'HashiCorp::VagrantVMwarefusion::Provider' => :vmware_fusion,
7
+ }
8
+
4
9
  def initialize(app, env)
5
10
  @app = app
6
11
  end
7
12
 
8
13
  def call(env)
9
- @machine = env[:machine]
14
+ if env[:global_config].landrush.enabled?
15
+ @machine = env[:machine]
16
+
17
+ @machine.ui.info "setting up machine's DNS to point to our server"
18
+ @machine.guest.capability(:redirect_dns, host: _target_host, port: 10053)
10
19
 
11
- @machine.ui.info "setting up machine's DNS to point to our server"
20
+ @machine.config.vm.networks.each do |type, options|
21
+ @machine.ui.info "network: #{type.inspect}, #{options.inspect}"
22
+ end
23
+ end
12
24
 
13
- redirect_dns('10.0.2.3', 53, '10.0.2.2', 10053)
25
+ @app.call(env)
14
26
  end
15
27
 
16
- def redirect_dns(original_server, original_port, target_server, target_port)
17
- %w[tcp udp].each do |protocol|
18
- rule = "OUTPUT -t nat -d #{original_server} -p #{protocol} --dport #{original_port} -j DNAT --to-destination #{target_server}:#{target_port}"
19
- command = %Q(iptables -C #{rule} 2> /dev/null || iptables -A #{rule})
20
- _run_command(command)
28
+ def _target_host
29
+ case _provider
30
+ when :virtualbox then
31
+ '10.0.2.2'
32
+ when :vmware_fusion then
33
+ _gateway_for_ip(@machine.guest.capability(:configured_dns_server))
21
34
  end
22
35
  end
23
36
 
24
- def _run_command(command)
25
- @machine.communicate.sudo(command) do |data, type|
26
- if [:stderr, :stdout].include?(type)
27
- color = (type == :stdout) ? :green : :red
28
- @machine.env.ui.info(data.chomp, :color => color, :prefix => false)
29
- end
30
- end
37
+ def _provider
38
+ SUPPORTED_PROVIDERS.fetch(@machine.provider.class.name) { |key|
39
+ raise "I don't support the #{key} provider yet!"
40
+ }
41
+ end
42
+
43
+ # Poor man's gateway; strip the last octet and jam a 1 on there.
44
+ def _gateway_for_ip(ip)
45
+ ip.split('.').tap(&:pop).push(1).join('.')
31
46
  end
32
47
  end
33
48
  end
@@ -11,7 +11,6 @@ module Landrush
11
11
  start_server_if_necessary(env)
12
12
  setup_machine_dns(env)
13
13
  setup_static_dns(env)
14
- env[:machine].config.vm.provision :landrush
15
14
  end
16
15
  @app.call(env)
17
16
  end
@@ -6,41 +6,43 @@ module Landrush
6
6
  end
7
7
 
8
8
  def call(env)
9
- if env[:global_config].landrush.enabled?
10
- teardown_static_dns(env)
11
- teardown_machine_dns(env)
12
-
13
- DependentVMs.remove(env[:machine])
14
- stop_server_if_necessary(env)
15
- end
16
- @app.call(env)
9
+ @env = env
10
+ teardown if env[:global_config].landrush.enabled?
11
+ @app.call(@env)
17
12
  end
18
13
 
19
- def stop_server_if_necessary(env)
20
- if Server.running?
21
- if DependentVMs.none?
22
- env[:ui].info "[landrush] no dependent vms left, stopping dns server"
23
- Server.stop
24
- else
25
- env[:ui].info "[landrush] there are dependent vms left, leaving dns server"
26
- end
14
+ def teardown
15
+ teardown_machine_dns
16
+ DependentVMs.remove(@env[:machine])
17
+
18
+ if DependentVMs.none?
19
+ teardown_static_dns
20
+ teardown_server
27
21
  else
28
- env[:ui].info "[landrush] dns server already stopped"
22
+ info "there are #{DependentVMs.count} VMs left, leaving DNS server and static entries"
29
23
  end
30
24
  end
31
25
 
32
- def teardown_machine_dns(env)
33
- hostname = Util.hostname(env[:machine])
34
- env[:ui].info "[landrush] removing machine entry: #{hostname}"
26
+ def teardown_machine_dns
27
+ hostname = Util.hostname(@env[:machine])
28
+ info "removing machine entry: #{hostname}"
35
29
  Store.hosts.delete(hostname)
36
30
  end
37
31
 
38
- def teardown_static_dns(env)
39
- env[:global_config].landrush.hosts.each do |hostname, _|
40
- env[:ui].info "[landrush] removing static entry: #{hostname}"
32
+ def teardown_static_dns
33
+ @env[:global_config].landrush.hosts.each do |hostname, _|
34
+ info "removing static entry: #{hostname}"
41
35
  Store.hosts.delete hostname
42
36
  end
43
37
  end
38
+
39
+ def teardown_server
40
+ Server.stop
41
+ end
42
+
43
+ def info(msg)
44
+ @env[:ui].info "[landrush] #{msg}"
45
+ end
44
46
  end
45
47
  end
46
48
  end
@@ -0,0 +1,14 @@
1
+ module Landrush
2
+ module Cap
3
+ module Debian
4
+ module InstallIptables
5
+ def self.install_iptables(machine)
6
+ machine.communicate.tap { |c|
7
+ c.sudo('apt-get update')
8
+ c.sudo('apt-get install -y iptables')
9
+ }
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,11 @@
1
+ module Landrush
2
+ module Cap
3
+ module Debian
4
+ module IptablesInstalled
5
+ def self.iptables_installed(machine)
6
+ machine.communicate.test('dpkg -s iptables')
7
+ end
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,21 @@
1
+ module Landrush
2
+ module Cap
3
+ module Linux
4
+ module AddIptablesRule
5
+ def self.add_iptables_rule(machine, rule)
6
+ _run(machine, %Q(iptables -C #{rule} 2> /dev/null || iptables -A #{rule}))
7
+ end
8
+
9
+ def self._run(machine, command)
10
+ machine.communicate.sudo(command) do |data, type|
11
+ if [:stderr, :stdout].include?(type)
12
+ color = (type == :stdout) ? :green : :red
13
+ machine.env.ui.info(data.chomp, :color => color, :prefix => false)
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
21
+
@@ -0,0 +1,17 @@
1
+ module Landrush
2
+ module Cap
3
+ module Linux
4
+ module ConfiguredDnsServer
5
+ def self.configured_dns_server(machine)
6
+ return @dns_server if @dns_server
7
+ machine.communicate.sudo('cat /etc/resolv.conf | grep ^nameserver') do |type, data|
8
+ if type == :stdout
9
+ @dns_server = data.scan(/\d+\.\d+\.\d+\.\d+/).first
10
+ end
11
+ end
12
+ @dns_server
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,25 @@
1
+ module Landrush
2
+ module Cap
3
+ module Linux
4
+ module RedirectDns
5
+ def self.redirect_dns(machine, target={})
6
+ %w[tcp udp].each do |proto|
7
+ machine.guest.capability(
8
+ :add_iptables_rule,
9
+ _redirect_dns_rule(proto, _current(machine), target.fetch(:host), target.fetch(:port))
10
+ )
11
+ end
12
+ end
13
+
14
+ def self._current(machine)
15
+ machine.guest.capability(:configured_dns_server)
16
+ end
17
+
18
+ def self._redirect_dns_rule(protocol, original_server, target_server, target_port)
19
+ "OUTPUT -t nat -p #{protocol} -d #{original_server} --dport 53 -j DNAT --to-destination #{target_server}:#{target_port}"
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
25
+
@@ -28,5 +28,17 @@ module Landrush
28
28
  result.hosts = @hosts.merge(other.hosts)
29
29
  end
30
30
  end
31
+
32
+ def validate(machine)
33
+ if @enabled
34
+ unless Util.hostname(machine).to_s.length > 0
35
+ return { 'landrush' => ['you must specify a hostname so we can make a DNS entry for it'] }
36
+ end
37
+ unless Util.ip_address(machine)
38
+ return { 'landrush' => ['you must specify a private network or else DNS makes no sense'] }
39
+ end
40
+ end
41
+ {}
42
+ end
31
43
  end
32
44
  end
@@ -14,9 +14,32 @@ module Landrush
14
14
 
15
15
  action_hook 'landrush_setup', :machine_action_up do |hook|
16
16
  require_relative 'action/setup'
17
+ require_relative 'action/install_prerequisites'
17
18
  require_relative 'action/redirect_dns'
18
- hook.before(VagrantPlugins::ProviderVirtualBox::Action::Boot, Action::Setup)
19
- hook.after(VagrantPlugins::ProviderVirtualBox::Action::Boot, Action::RedirectDns)
19
+
20
+ register_boot_hooks = lambda { |boot_action|
21
+ hook.before(boot_action, pre_boot_actions)
22
+ hook.after(boot_action, post_boot_actions)
23
+ }
24
+
25
+ register_boot_hooks.call(VagrantPlugins::ProviderVirtualBox::Action::Boot)
26
+
27
+ if defined?(HashiCorp::VagrantVMwarefusion)
28
+ register_boot_hooks.call(HashiCorp::VagrantVMwarefusion::Action::Boot)
29
+ end
30
+ end
31
+
32
+ def self.pre_boot_actions
33
+ Vagrant::Action::Builder.new.tap do |b|
34
+ b.use Action::Setup
35
+ end
36
+ end
37
+
38
+ def self.post_boot_actions
39
+ Vagrant::Action::Builder.new.tap do |b|
40
+ b.use Action::InstallPrerequisites
41
+ b.use Action::RedirectDns
42
+ end
20
43
  end
21
44
 
22
45
  action_hook 'landrush_teardown', :machine_action_halt do |hook|
@@ -28,5 +51,30 @@ module Landrush
28
51
  require_relative 'action/teardown'
29
52
  hook.after(Vagrant::Action::Builtin::GracefulHalt, Action::Teardown)
30
53
  end
54
+
55
+ guest_capability('debian', 'iptables_installed') do
56
+ require_relative 'cap/debian/iptables_installed'
57
+ Cap::Debian::IptablesInstalled
58
+ end
59
+
60
+ guest_capability('debian', 'install_iptables') do
61
+ require_relative 'cap/debian/install_iptables'
62
+ Cap::Debian::InstallIptables
63
+ end
64
+
65
+ guest_capability('linux', 'configured_dns_server') do
66
+ require_relative 'cap/linux/configured_dns_server'
67
+ Cap::Linux::ConfiguredDnsServer
68
+ end
69
+
70
+ guest_capability('linux', 'redirect_dns') do
71
+ require_relative 'cap/linux/redirect_dns'
72
+ Cap::Linux::RedirectDns
73
+ end
74
+
75
+ guest_capability('linux', 'add_iptables_rule') do
76
+ require_relative 'cap/linux/add_iptables_rule'
77
+ Cap::Linux::AddIptablesRule
78
+ end
31
79
  end
32
80
  end
@@ -1,3 +1,3 @@
1
1
  module Landrush
2
- VERSION = "0.3.1"
2
+ VERSION = "0.4.0"
3
3
  end
@@ -51,9 +51,8 @@ module Landrush
51
51
  app = Proc.new {}
52
52
  teardown = Teardown.new(app, nil)
53
53
  env = fake_environment_with_machine('somehost.vagrant.dev', '1.2.3.4')
54
-
55
- other_env = fake_environment_with_machine('otherhost.vagrant.dev', '1.2.3.4')
56
- DependentVMs.add(other_env[:machine])
54
+ other_machine = fake_machine('otherhost.vagrant.dev', '2.3.4.5')
55
+ DependentVMs.add(other_machine)
57
56
 
58
57
  Server.start
59
58
  teardown.call(env)
@@ -61,6 +60,20 @@ module Landrush
61
60
  Server.running?.must_equal true
62
61
  end
63
62
 
63
+ it "leaves static entries when other dependent vms exist" do
64
+ app = Proc.new {}
65
+ teardown = Teardown.new(app, nil)
66
+ env = fake_environment_with_machine('somehost.vagrant.dev', '1.2.3.4')
67
+ other_machine = fake_machine('otherhost.vagrant.dev', '1.2.3.4')
68
+ DependentVMs.add(other_machine)
69
+
70
+ fake_static_entry(env, 'static.vagrant.dev', '3.4.5.6')
71
+
72
+ teardown.call(env)
73
+
74
+ Store.hosts.get('static.vagrant.dev').must_equal '3.4.5.6'
75
+ end
76
+
64
77
  it "leaves the server alone if it's not running" do
65
78
  app = Proc.new {}
66
79
  teardown = Teardown.new(app, nil)
data/test/test_helper.rb CHANGED
@@ -13,13 +13,17 @@ def fake_environment(extras={})
13
13
  end
14
14
 
15
15
  def fake_environment_with_machine(hostname, ip)
16
+ env = Vagrant::Environment.new
17
+ machine = fake_machine(hostname, ip, env)
18
+ { machine: machine, ui: FakeUI, global_config: env.config_global }
19
+ end
20
+
21
+ def fake_machine(hostname, ip, env = Vagrant::Environment.new)
16
22
  provider_cls = Class.new do
17
23
  def initialize(machine)
18
24
  end
19
25
  end
20
26
 
21
- env = Vagrant::Environment.new
22
-
23
27
  machine = Vagrant::Machine.new(
24
28
  'fake_machine',
25
29
  'fake_provider',
@@ -33,11 +37,15 @@ def fake_environment_with_machine(hostname, ip)
33
37
  )
34
38
 
35
39
  machine.config.landrush.enable
36
-
37
40
  machine.config.vm.hostname = hostname
38
41
  machine.config.vm.network :private_network, ip: ip
39
42
 
40
- { machine: machine, ui: FakeUI, global_config: env.config_global }
43
+ machine
44
+ end
45
+
46
+ def fake_static_entry(env, hostname, ip)
47
+ env[:global_config].landrush.host(hostname, ip)
48
+ Landrush::Store.hosts.set(hostname, ip)
41
49
  end
42
50
 
43
51
  class MiniTest::Spec
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: landrush
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.1
4
+ version: 0.4.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-06-24 00:00:00.000000000 Z
12
+ date: 2013-08-08 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rubydns
@@ -91,9 +91,15 @@ files:
91
91
  - landrush.gemspec
92
92
  - lib/ext/rexec.rb
93
93
  - lib/landrush.rb
94
+ - lib/landrush/action/install_prerequisites.rb
94
95
  - lib/landrush/action/redirect_dns.rb
95
96
  - lib/landrush/action/setup.rb
96
97
  - lib/landrush/action/teardown.rb
98
+ - lib/landrush/cap/debian/install_iptables.rb
99
+ - lib/landrush/cap/debian/iptables_installed.rb
100
+ - lib/landrush/cap/linux/add_iptables_rule.rb
101
+ - lib/landrush/cap/linux/configured_dns_server.rb
102
+ - lib/landrush/cap/linux/redirect_dns.rb
97
103
  - lib/landrush/command.rb
98
104
  - lib/landrush/config.rb
99
105
  - lib/landrush/dependent_vms.rb