landrush 0.3.1 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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