landrush 0.3.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/.gitignore +21 -0
- data/Gemfile +12 -0
- data/LICENSE.txt +22 -0
- data/README.md +72 -0
- data/Rakefile +10 -0
- data/examples/Vagrantfile +26 -0
- data/landrush.gemspec +35 -0
- data/lib/ext/rexec.rb +10 -0
- data/lib/landrush.rb +27 -0
- data/lib/landrush/action/redirect_dns.rb +35 -0
- data/lib/landrush/action/setup.rb +42 -0
- data/lib/landrush/action/teardown.rb +46 -0
- data/lib/landrush/command.rb +45 -0
- data/lib/landrush/config.rb +32 -0
- data/lib/landrush/dependent_vms.rb +40 -0
- data/lib/landrush/plugin.rb +32 -0
- data/lib/landrush/resolver_config.rb +53 -0
- data/lib/landrush/server.rb +69 -0
- data/lib/landrush/store.rb +49 -0
- data/lib/landrush/util.rb +25 -0
- data/lib/landrush/version.rb +3 -0
- data/test/landrush/action/setup_test.rb +73 -0
- data/test/landrush/action/teardown_test.rb +92 -0
- data/test/landrush/dependent_vms_test.rb +33 -0
- data/test/landrush/resolver_config_test.rb +20 -0
- data/test/landrush/server_test.rb +22 -0
- data/test/landrush/store_test.rb +55 -0
- data/test/support/clear_dependent_vms.rb +10 -0
- data/test/support/fake_resolver_config.rb +21 -0
- data/test/support/fake_ui.rb +4 -0
- data/test/support/fake_working_dir.rb +16 -0
- data/test/support/test_server_daemon.rb +40 -0
- data/test/test_helper.rb +54 -0
- metadata +156 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
source 'https://rubygems.org'
|
2
|
+
|
3
|
+
gemspec
|
4
|
+
|
5
|
+
group :development do
|
6
|
+
# We depend on Vagrant for development, but we don't add it as a
|
7
|
+
# gem dependency because we expect to be installed within the
|
8
|
+
# Vagrant environment itself using `vagrant plugin`.
|
9
|
+
gem "vagrant", :git => "git://github.com/mitchellh/vagrant.git"
|
10
|
+
|
11
|
+
gem "debugger"
|
12
|
+
end
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2013 Paul Hinze
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,72 @@
|
|
1
|
+
# Landrush: DNS for Vagrant
|
2
|
+
|
3
|
+
Simple DNS that's visible on both the guest and the host.
|
4
|
+
|
5
|
+
> Because even a Vagrant needs a place to settle down once in a while.
|
6
|
+
|
7
|
+
Spins up a small DNS server and redirects DNS traffic from your VMs to use it,
|
8
|
+
automatically registers/deregisters IP addresseses of guests as they come up
|
9
|
+
and down.
|
10
|
+
|
11
|
+
## Installation
|
12
|
+
|
13
|
+
Install under Vagrant (1.1 or later):
|
14
|
+
|
15
|
+
$ vagrant plugin install landrush
|
16
|
+
|
17
|
+
## Usage
|
18
|
+
|
19
|
+
Enable the plugin in your `Vagrantfile`:
|
20
|
+
|
21
|
+
config.landrush.enable
|
22
|
+
|
23
|
+
Bring up a machine that has a private network IP address and a hostname (see the `Vagrantfile` for an example)
|
24
|
+
|
25
|
+
$ vagrant up
|
26
|
+
|
27
|
+
And you should be able to get your hostname from your host:
|
28
|
+
|
29
|
+
$ dig -p 10053 @localhost myhost.vagrant.dev
|
30
|
+
|
31
|
+
If you shut down your guest, the entries associated with it will be removed.
|
32
|
+
|
33
|
+
You can add static host entries to the DNS server in your `Vagrantfile` like so:
|
34
|
+
|
35
|
+
config.landrush.host 'myhost.example.com', '1.2.3.4'
|
36
|
+
|
37
|
+
Any DNS queries that do not match will be passed through to an upstream DNS server, so this will be able to serve as the one-stop shop for your guests' DNS needs.
|
38
|
+
|
39
|
+
### Visibility on the Guest
|
40
|
+
|
41
|
+
Linux guests using iptables should automatically have their DNS traffic redirected properly to our DNS server. File an issue if this does not work for you.
|
42
|
+
|
43
|
+
### Visibility on the Host
|
44
|
+
|
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
|
+
|
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.
|
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:
|
50
|
+
|
51
|
+
```
|
52
|
+
# Use landrush server for this domain
|
53
|
+
nameserver 127.0.0.1
|
54
|
+
port 10053
|
55
|
+
```
|
56
|
+
|
57
|
+
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
|
+
|
59
|
+
## Work in Progress - Lots to do!
|
60
|
+
|
61
|
+
* The guest visibility strategy assumes iptables-based firewall.
|
62
|
+
* Lots of static values that need configurin' - config location, ports, etc.
|
63
|
+
* VirtualBox only right now, need to support VMWare
|
64
|
+
* Tests tests tests.
|
65
|
+
|
66
|
+
## Contributing
|
67
|
+
|
68
|
+
1. Fork it
|
69
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
70
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
71
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
72
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
#
|
2
|
+
# This serves as a simple example, and it's what I'm using for testing locally.
|
3
|
+
#
|
4
|
+
# If you're doing development and want to run this locally you can simply
|
5
|
+
# `bundle install`, then prefix all your vagrant commands with `bundle exec`, like so:
|
6
|
+
#
|
7
|
+
# VAGRANT_CWD=examples bundle exec vagrant up
|
8
|
+
# VAGRANT_CWD=examples bundle exce vagrant halt
|
9
|
+
#
|
10
|
+
|
11
|
+
# This line is unnecessary when the plugin is installed normally; it's just
|
12
|
+
# here for the development / testing use case.
|
13
|
+
Vagrant.require_plugin "landrush"
|
14
|
+
|
15
|
+
Vagrant.configure("2") do |config|
|
16
|
+
config.vm.box = "precise64"
|
17
|
+
|
18
|
+
config.landrush.enable
|
19
|
+
|
20
|
+
config.vm.network :private_network, ip: '172.16.32.111'
|
21
|
+
|
22
|
+
config.vm.hostname = "myhost.vagrant.dev"
|
23
|
+
|
24
|
+
config.landrush.host 'static1.example.com', '1.2.3.4'
|
25
|
+
config.landrush.host 'static2.example.com', '2.3.4.5'
|
26
|
+
end
|
data/landrush.gemspec
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'landrush/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "landrush"
|
8
|
+
spec.version = Landrush::VERSION
|
9
|
+
spec.authors = ["Paul Hinze"]
|
10
|
+
spec.email = ["paul.t.hinze@gmail.com"]
|
11
|
+
spec.description = <<-DESCRIP.gsub(/^ /, '')
|
12
|
+
Even a Vagrant needs a place to settle down once in a while.
|
13
|
+
|
14
|
+
This Vagrant plugin spins up a lightweight DNS server and makes it visible
|
15
|
+
to your guests and your host, so that you can easily access all your
|
16
|
+
machines without having to fiddle with IP addresses.
|
17
|
+
|
18
|
+
DNS records are automatically added and removed as machines are brought up
|
19
|
+
and down, and you can configure static entries to be returned from the
|
20
|
+
server as well. See the README for more documentation.
|
21
|
+
DESCRIP
|
22
|
+
spec.summary = %q{a vagrant plugin providing consistent DNS visible on host and guests}
|
23
|
+
spec.homepage = "https://github.com/phinze/landrush"
|
24
|
+
spec.license = "MIT"
|
25
|
+
|
26
|
+
spec.files = `git ls-files`.split($/)
|
27
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
28
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
29
|
+
spec.require_paths = ["lib"]
|
30
|
+
|
31
|
+
spec.add_dependency "rubydns"
|
32
|
+
|
33
|
+
spec.add_development_dependency "bundler", "~> 1.3"
|
34
|
+
spec.add_development_dependency "rake"
|
35
|
+
end
|
data/lib/ext/rexec.rb
ADDED
data/lib/landrush.rb
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
begin
|
2
|
+
require 'vagrant'
|
3
|
+
rescue LoadError
|
4
|
+
raise 'The Vagrant landrush plugin must be run within Vagrant.'
|
5
|
+
end
|
6
|
+
|
7
|
+
module Landrush
|
8
|
+
def self.working_dir
|
9
|
+
@working_dir ||= Pathname(File.expand_path('~/.vagrant.d/data/landrush')).tap(&:mkpath)
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.working_dir=(working_dir)
|
13
|
+
@working_dir = Pathname(working_dir).tap(&:mkpath)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
require 'rubydns'
|
18
|
+
|
19
|
+
require 'landrush/dependent_vms'
|
20
|
+
require 'landrush/plugin'
|
21
|
+
require 'landrush/resolver_config'
|
22
|
+
require 'landrush/server'
|
23
|
+
require 'landrush/store'
|
24
|
+
require 'landrush/util'
|
25
|
+
require 'landrush/version'
|
26
|
+
|
27
|
+
require 'ext/rexec'
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module Landrush
|
2
|
+
module Action
|
3
|
+
class RedirectDns
|
4
|
+
def initialize(app, env)
|
5
|
+
@app = app
|
6
|
+
end
|
7
|
+
|
8
|
+
def call(env)
|
9
|
+
@machine = env[:machine]
|
10
|
+
|
11
|
+
@machine.ui.info "setting up machine's DNS to point to our server"
|
12
|
+
|
13
|
+
redirect_dns('10.0.2.3', 53, '10.0.2.2', 10053)
|
14
|
+
end
|
15
|
+
|
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)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
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
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module Landrush
|
2
|
+
module Action
|
3
|
+
class Setup
|
4
|
+
def initialize(app, env)
|
5
|
+
@app = app
|
6
|
+
end
|
7
|
+
|
8
|
+
def call(env)
|
9
|
+
if env[:global_config].landrush.enabled?
|
10
|
+
DependentVMs.add(env[:machine])
|
11
|
+
start_server_if_necessary(env)
|
12
|
+
setup_machine_dns(env)
|
13
|
+
setup_static_dns(env)
|
14
|
+
env[:machine].config.vm.provision :landrush
|
15
|
+
end
|
16
|
+
@app.call(env)
|
17
|
+
end
|
18
|
+
|
19
|
+
def start_server_if_necessary(env)
|
20
|
+
if Server.running?
|
21
|
+
env[:ui].info "[landrush] dns server already running"
|
22
|
+
else
|
23
|
+
env[:ui].info "[landrush] starting dns server"
|
24
|
+
Server.start
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def setup_machine_dns(env)
|
29
|
+
hostname, ip_address = Util.host_and_ip(env[:machine])
|
30
|
+
env[:ui].info "[landrush] adding machine entry: #{hostname} => #{ip_address}"
|
31
|
+
Store.hosts.set(hostname, ip_address)
|
32
|
+
end
|
33
|
+
|
34
|
+
def setup_static_dns(env)
|
35
|
+
env[:global_config].landrush.hosts.each do |hostname, ip_address|
|
36
|
+
env[:ui].info "[landrush] adding static entry: #{hostname} => #{ip_address}"
|
37
|
+
Store.hosts.set hostname, ip_address
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module Landrush
|
2
|
+
module Action
|
3
|
+
class Teardown
|
4
|
+
def initialize(app, env)
|
5
|
+
@app = app
|
6
|
+
end
|
7
|
+
|
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)
|
17
|
+
end
|
18
|
+
|
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
|
27
|
+
else
|
28
|
+
env[:ui].info "[landrush] dns server already stopped"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def teardown_machine_dns(env)
|
33
|
+
hostname = Util.hostname(env[:machine])
|
34
|
+
env[:ui].info "[landrush] removing machine entry: #{hostname}"
|
35
|
+
Store.hosts.delete(hostname)
|
36
|
+
end
|
37
|
+
|
38
|
+
def teardown_static_dns(env)
|
39
|
+
env[:global_config].landrush.hosts.each do |hostname, _|
|
40
|
+
env[:ui].info "[landrush] removing static entry: #{hostname}"
|
41
|
+
Store.hosts.delete hostname
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module Landrush
|
2
|
+
class Command < Vagrant.plugin('2', :command)
|
3
|
+
DAEMON_COMMANDS = %w(start stop restart status)
|
4
|
+
|
5
|
+
def execute
|
6
|
+
ARGV.shift # flush landrush from ARGV, RExec wants to use it for daemon commands
|
7
|
+
|
8
|
+
command = ARGV.first
|
9
|
+
if DAEMON_COMMANDS.include?(command)
|
10
|
+
Server.daemonize
|
11
|
+
elsif command == 'dependentvms'
|
12
|
+
if DependentVMs.any?
|
13
|
+
@env.ui.info(DependentVMs.list.map { |dvm| " - #{dvm}" }.join("\n"))
|
14
|
+
else
|
15
|
+
@env.ui.info("No dependent VMs")
|
16
|
+
end
|
17
|
+
elsif command == 'install'
|
18
|
+
ResolverConfg.ensure_config_exists
|
19
|
+
else
|
20
|
+
boom("'#{command}' is not a command")
|
21
|
+
end
|
22
|
+
|
23
|
+
0 # happy exit code
|
24
|
+
end
|
25
|
+
|
26
|
+
def boom(msg)
|
27
|
+
raise Vagrant::Errors::CLIInvalidOptions, :help => usage(msg)
|
28
|
+
end
|
29
|
+
|
30
|
+
def usage(msg); <<-EOS.gsub(/^ /, '')
|
31
|
+
ERROR: #{msg}
|
32
|
+
|
33
|
+
vagrant landrush <command>
|
34
|
+
|
35
|
+
commands:
|
36
|
+
{start|stop|restart|status}
|
37
|
+
control the landrush server daemon
|
38
|
+
dependentvms
|
39
|
+
list vms currently dependent on the landrush server
|
40
|
+
install
|
41
|
+
install resolver config for host visbility (requires sudo)
|
42
|
+
EOS
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module Landrush
|
2
|
+
class Config < Vagrant.plugin('2', :config)
|
3
|
+
attr_accessor :hosts
|
4
|
+
|
5
|
+
def initialize
|
6
|
+
@hosts = {}
|
7
|
+
@enabled = false
|
8
|
+
end
|
9
|
+
|
10
|
+
def enable(enabled=true)
|
11
|
+
@enabled = true
|
12
|
+
end
|
13
|
+
|
14
|
+
def disable
|
15
|
+
@enabled = false
|
16
|
+
end
|
17
|
+
|
18
|
+
def enabled?
|
19
|
+
@enabled
|
20
|
+
end
|
21
|
+
|
22
|
+
def host(hostname, ip_address)
|
23
|
+
@hosts[hostname] = ip_address
|
24
|
+
end
|
25
|
+
|
26
|
+
def merge(other)
|
27
|
+
super.tap do |result|
|
28
|
+
result.hosts = @hosts.merge(other.hosts)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|