landrush 1.1.2 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (64) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop_todo.yml +12 -178
  3. data/.travis.yml +6 -1
  4. data/CHANGELOG.md +18 -1
  5. data/CONTRIBUTING.adoc +112 -0
  6. data/Gemfile +6 -9
  7. data/Guardfile +10 -0
  8. data/README.adoc +100 -0
  9. data/Rakefile +14 -2
  10. data/appveyor.yml +20 -0
  11. data/doc/Development.adoc +112 -0
  12. data/doc/ProxyMobile.adoc +66 -0
  13. data/doc/Troubleshooting.adoc +42 -0
  14. data/doc/Usage.adoc +271 -0
  15. data/features/commands.feature +35 -0
  16. data/features/dns_resolution.feature +6 -5
  17. data/features/{landrush-ip.feature → landrush_ip.feature} +0 -0
  18. data/features/step_definitions/landrush_custom_steps.rb +48 -0
  19. data/features/support/env.rb +25 -1
  20. data/landrush.gemspec +3 -3
  21. data/lib/landrush/action/common.rb +3 -11
  22. data/lib/landrush/action/install_prerequisites.rb +2 -3
  23. data/lib/landrush/action/redirect_dns.rb +1 -1
  24. data/lib/landrush/action/setup.rb +25 -30
  25. data/lib/landrush/action/teardown.rb +8 -11
  26. data/lib/landrush/cap/guest/all/read_host_visible_ip_address.rb +28 -4
  27. data/lib/landrush/cap/guest/linux/add_iptables_rule.rb +1 -1
  28. data/lib/landrush/cap/guest/linux/redirect_dns.rb +2 -2
  29. data/lib/landrush/cap/guest/suse/add_iptables_rule.rb +20 -0
  30. data/lib/landrush/cap/guest/suse/install_iptables.rb +14 -0
  31. data/lib/landrush/cap/guest/suse/iptables_installed.rb +11 -0
  32. data/lib/landrush/cap/host/suse/dnsmasq_installed.rb +11 -0
  33. data/lib/landrush/cap/host/suse/install_dnsmasq.rb +14 -0
  34. data/lib/landrush/cap/host/suse/restart_dnsmasq.rb +21 -0
  35. data/lib/landrush/cap/host/windows/configure_visibility_on_host.rb +1 -1
  36. data/lib/landrush/command.rb +42 -17
  37. data/lib/landrush/config.rb +29 -14
  38. data/lib/landrush/plugin.rb +30 -0
  39. data/lib/landrush/server.rb +96 -138
  40. data/lib/landrush/start_server.rb +11 -0
  41. data/lib/landrush/store.rb +6 -2
  42. data/lib/landrush/util/path.rb +32 -0
  43. data/lib/landrush/util/process_helper.rb +46 -0
  44. data/lib/landrush/util/retry.rb +2 -2
  45. data/lib/landrush/version.rb +1 -1
  46. data/test/landrush/action/setup_test.rb +19 -25
  47. data/test/landrush/action/teardown_test.rb +18 -15
  48. data/test/landrush/cap/guest/all/read_host_visible_ip_address_test.rb +35 -1
  49. data/test/landrush/cap/guest/linux/configured_dns_servers_test.rb +8 -8
  50. data/test/landrush/cap/guest/linux/redirect_dns_test.rb +4 -4
  51. data/test/landrush/config_test.rb +23 -2
  52. data/test/landrush/dependent_vms_test.rb +5 -5
  53. data/test/landrush/issues/255.rb +115 -0
  54. data/test/landrush/server_test.rb +22 -4
  55. data/test/landrush/store_test.rb +28 -13
  56. data/test/support/test_server_daemon.rb +2 -4
  57. data/test/test_helper.rb +37 -14
  58. metadata +30 -15
  59. data/CONTRIBUTING.md +0 -103
  60. data/NOTES.md +0 -28
  61. data/README.md +0 -406
  62. data/doc/proxy-mobile/README.md +0 -50
  63. data/features/step_definitions/dns.rb +0 -19
  64. data/features/step_definitions/ip.rb +0 -13
@@ -0,0 +1,11 @@
1
+ # This file gets execute outside the Vagrant (bundled) environment.
2
+ # For that reason we have to put the gems we need ourself onto the LOADPATH.
3
+ # The caller of this file will pass the Vagrant gem dir as first argument which
4
+ # we use as base to find the required gems
5
+
6
+ gem_path = ARGV[2]
7
+ Dir.entries(gem_path).each { |gem_dir| $LOAD_PATH.unshift "#{File.join(ARGV[2], gem_dir)}/lib" }
8
+
9
+ require_relative 'server'
10
+
11
+ Landrush::Server.run(ARGV[0], ARGV[1]) if __FILE__ == $PROGRAM_NAME
@@ -43,7 +43,11 @@ module Landrush
43
43
  end
44
44
 
45
45
  def find(search)
46
- search = IPAddr.new(search).reverse if (IPAddr.new(search) rescue nil)
46
+ search = IPAddr.new(search).reverse if begin
47
+ IPAddr.new(search)
48
+ rescue
49
+ nil
50
+ end
47
51
  current_config.keys.detect do |key|
48
52
  key.casecmp(search) == 0 ||
49
53
  search =~ /#{key}$/i ||
@@ -74,7 +78,7 @@ module Landrush
74
78
  end
75
79
 
76
80
  def write(config)
77
- File.open(backing_file, "w") do |f|
81
+ File.open(backing_file, 'w') do |f|
78
82
  f.write(JSON.pretty_generate(config))
79
83
  end
80
84
  end
@@ -0,0 +1,32 @@
1
+ module Landrush
2
+ module Util
3
+ class Path
4
+ def self.embedded_vagrant_ruby
5
+ bin_dir = embedded_vagrant_bin_dir
6
+ ruby_bin = bin_dir + separator + 'ruby'
7
+ ruby_bin if File.exist?(ruby_bin)
8
+ end
9
+
10
+ def self.ensure_ruby_on_path
11
+ bin_dir = embedded_vagrant_bin_dir
12
+ ENV['PATH'] = bin_dir + File::PATH_SEPARATOR + ENV['PATH'] if File.exist?(bin_dir)
13
+ end
14
+
15
+ def self.embedded_vagrant_bin_dir
16
+ vagrant_binary = Vagrant::Util::Which.which('vagrant')
17
+ vagrant_binary = File.realpath(vagrant_binary) if File.symlink?(vagrant_binary)
18
+ # in a Vagrant installation the Ruby executable is in ../embedded/bin relative to the vagrant executable
19
+ File.dirname(File.dirname(vagrant_binary)) + separator + 'embedded' + separator + 'bin'
20
+ end
21
+
22
+ def self.separator
23
+ # we don't use File.join here, since even on Cygwin we want a Windows path - see https://github.com/vagrant-landrush/landrush/issues/237
24
+ if Vagrant::Util::Platform.windows?
25
+ '\\'
26
+ else
27
+ '/'
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,46 @@
1
+ module Landrush
2
+ module Util
3
+ # A module containing helper classes for dealing with pid files
4
+ module ProcessHelper
5
+ def write_pid(pid, pid_file)
6
+ ensure_path_exits(pid_file)
7
+ File.open(pid_file, 'w') { |f| f << pid.to_s }
8
+ end
9
+
10
+ def read_pid(pid_file)
11
+ IO.read(pid_file).to_i
12
+ rescue
13
+ nil
14
+ end
15
+
16
+ def delete_pid_file(pid_file)
17
+ FileUtils.rm(pid_file) if File.exist? pid_file
18
+ end
19
+
20
+ def process_status(pid_file)
21
+ return running? ? :running : :unknown if File.exist? pid_file
22
+ :stopped
23
+ end
24
+
25
+ def ensure_path_exits(file_name)
26
+ dirname = File.dirname(file_name)
27
+ FileUtils.mkdir_p(dirname) unless File.directory?(dirname)
28
+ end
29
+
30
+ def terminate_process(pid)
31
+ # Kill/Term loop - if the daemon didn't die easily, shoot
32
+ # it a few more times.
33
+ attempts = 5
34
+ while running? && attempts > 0
35
+ sig = (attempts >= 2) ? 'KILL' : 'TERM'
36
+
37
+ puts "Sending #{sig} to process #{pid}..."
38
+ Process.kill(sig, pid)
39
+
40
+ attempts -= 1
41
+ sleep 1
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
@@ -1,8 +1,8 @@
1
1
  module Landrush
2
2
  module Util
3
3
  class Retry
4
- def self.retry(opts=nil)
5
- opts = {tries: 1}.merge(opts || {})
4
+ def self.retry(opts = nil)
5
+ opts = { tries: 1 }.merge(opts || {})
6
6
  n = 0
7
7
  while n < opts[:tries]
8
8
  return true if yield
@@ -1,3 +1,3 @@
1
1
  module Landrush
2
- VERSION = '1.1.2'.freeze
2
+ VERSION = '1.2.0'.freeze
3
3
  end
@@ -7,29 +7,30 @@ module Landrush
7
7
  describe Setup do
8
8
  let(:env) { fake_environment }
9
9
  let(:app) { proc {} }
10
+
10
11
  before do
11
12
  env[:machine].config.landrush.host_redirect_dns = false
12
13
  end
13
14
 
14
- it "calls the next app in the chain" do
15
+ it 'calls the next app in the chain' do
15
16
  app = -> (e) { e[:called] = true }
16
- setup = Setup.new(app, nil)
17
+ setup = Landrush::Action::Setup.new(app, env)
17
18
 
18
19
  setup.call(env)
19
20
 
20
21
  env[:called].must_equal true
21
22
  end
22
23
 
23
- it "records the booting host as a dependent VM" do
24
- setup = Setup.new(app, nil)
24
+ it 'records the booting host as a dependent VM' do
25
+ setup = Landrush::Action::Setup.new(app, env)
25
26
 
26
27
  setup.call(env)
27
28
 
28
- DependentVMs.list.must_equal %w[somehost.vagrant.test]
29
+ DependentVMs.list.must_equal %w(somehost.vagrant.test)
29
30
  end
30
31
 
31
32
  it "starts the landrush server if it's not already started" do
32
- setup = Setup.new(app, nil)
33
+ setup = Landrush::Action::Setup.new(app, env)
33
34
 
34
35
  setup.call(env)
35
36
 
@@ -37,8 +38,10 @@ module Landrush
37
38
  end
38
39
 
39
40
  it "does not attempt to start the server if it's already up" do
40
- setup = Setup.new(app, nil)
41
+ setup = Landrush::Action::Setup.new(app, env)
41
42
 
43
+ Server.working_dir = File.join(env[:home_path], 'data', 'landrush')
44
+ Server.gems_dir = env[:gems_path].to_s + '/gems'
42
45
  Server.start
43
46
  original_pid = Server.pid
44
47
 
@@ -48,8 +51,8 @@ module Landrush
48
51
  Server.pid.must_equal original_pid
49
52
  end
50
53
 
51
- it "does nothing if it is not enabled via config" do
52
- setup = Setup.new(app, nil)
54
+ it 'does nothing if it is not enabled via config' do
55
+ setup = Landrush::Action::Setup.new(app, env)
53
56
 
54
57
  env[:machine].config.landrush.disable
55
58
  setup.call(env)
@@ -57,16 +60,8 @@ module Landrush
57
60
  DependentVMs.list.must_equal []
58
61
  end
59
62
 
60
- it "for single private network IP host visible IP can be retrieved w/o starting the VM" do
61
- setup = Setup.new(app, nil)
62
- env[:machine].config.vm.network :private_network, ip: '42.42.42.42'
63
-
64
- setup.call(env)
65
- Store.hosts.get('somehost.vagrant.test').must_equal '42.42.42.42'
66
- end
67
-
68
- it "for multiple private network IPs host visible IP cant be retrieved if host_ip_address is set" do
69
- setup = Setup.new(app, nil)
63
+ it 'for multiple private network IPs host visible IP cant be retrieved if host_ip_address is set' do
64
+ setup = Landrush::Action::Setup.new(app, env)
70
65
 
71
66
  env[:machine].config.vm.network :private_network, ip: '42.42.42.41'
72
67
  env[:machine].config.vm.network :private_network, ip: '42.42.42.42'
@@ -75,8 +70,8 @@ module Landrush
75
70
  Store.hosts.get('somehost.vagrant.test').must_equal '42.42.42.42'
76
71
  end
77
72
 
78
- it "is possible to add cnames via the config.landrush.host configuration option" do
79
- setup = Setup.new(app, nil)
73
+ it 'is possible to add cnames via the config.landrush.host configuration option' do
74
+ setup = Landrush::Action::Setup.new(app, env)
80
75
 
81
76
  env[:machine].config.landrush.host 'foo', 'bar'
82
77
  setup.call(env)
@@ -86,17 +81,16 @@ module Landrush
86
81
 
87
82
  describe 'after boot' do
88
83
  it "stores the machine's hostname => ip address" do
89
- setup = Setup.new(app, nil)
84
+ setup = Landrush::Action::Setup.new(app, env)
90
85
 
91
86
  setup.call(env)
92
87
 
93
88
  Store.hosts.get('somehost.vagrant.test').must_equal '1.2.3.4'
94
89
  end
95
90
 
96
- it "does nothing if it is not enabled via config" do
97
- setup = Setup.new(app, nil)
98
-
91
+ it 'does nothing if it is not enabled via config' do
99
92
  env = fake_environment(enabled: false)
93
+ setup = Landrush::Action::Setup.new(app, env)
100
94
  setup.call(env)
101
95
 
102
96
  Store.hosts.get('somehost.vagrant.test').must_equal nil
@@ -5,10 +5,10 @@ require 'landrush/action/teardown'
5
5
  module Landrush
6
6
  module Action
7
7
  describe Teardown do
8
- it "calls the next app in the chain" do
8
+ it 'calls the next app in the chain' do
9
9
  env = fake_environment
10
10
  app = -> (e) { e[:called] = true }
11
- teardown = Teardown.new(app, nil)
11
+ teardown = Teardown.new(app, env)
12
12
 
13
13
  teardown.call(env)
14
14
 
@@ -17,8 +17,8 @@ module Landrush
17
17
 
18
18
  it "clears the machine's hostname => ip address" do
19
19
  app = proc {}
20
- teardown = Teardown.new(app, nil)
21
20
  env = fake_environment
21
+ teardown = Teardown.new(app, env)
22
22
 
23
23
  Store.hosts.set('somehost.vagrant.test', '1.2.3.4')
24
24
  teardown.call(env)
@@ -26,10 +26,10 @@ module Landrush
26
26
  Store.hosts.get('somehost.vagrant.test').must_equal nil
27
27
  end
28
28
 
29
- it "removes the machine as a dependent VM" do
29
+ it 'removes the machine as a dependent VM' do
30
30
  app = proc {}
31
- teardown = Teardown.new(app, nil)
32
31
  env = fake_environment
32
+ teardown = Teardown.new(app, env)
33
33
 
34
34
  DependentVMs.add('somehost.vagrant.test')
35
35
  teardown.call(env)
@@ -37,10 +37,10 @@ module Landrush
37
37
  DependentVMs.list.must_equal []
38
38
  end
39
39
 
40
- it "stops the landrush server when there are no dependent machines left" do
40
+ it 'stops the landrush server when there are no dependent machines left' do
41
41
  app = proc {}
42
- teardown = Teardown.new(app, nil)
43
42
  env = fake_environment
43
+ teardown = Teardown.new(app, env)
44
44
 
45
45
  Server.start
46
46
  teardown.call(env)
@@ -48,22 +48,26 @@ module Landrush
48
48
  Server.running?.must_equal false
49
49
  end
50
50
 
51
- it "leaves the landrush server when other dependent vms exist" do
51
+ it 'leaves the landrush server when other dependent vms exist' do
52
52
  app = proc {}
53
- teardown = Teardown.new(app, nil)
54
53
  env = fake_environment
54
+ teardown = Teardown.new(app, env)
55
+
55
56
  DependentVMs.add('otherhost.vagrant.test')
56
57
 
58
+ Server.working_dir = File.join(env[:home_path], 'data', 'landrush')
59
+ Server.gems_dir = env[:gems_path].to_s + '/gems'
57
60
  Server.start
58
61
  teardown.call(env)
59
62
 
60
63
  Server.running?.must_equal true
61
64
  end
62
65
 
63
- it "leaves static entries when other dependent vms exist" do
66
+ it 'leaves static entries when other dependent vms exist' do
64
67
  app = proc {}
65
- teardown = Teardown.new(app, nil)
66
68
  env = fake_environment
69
+ teardown = Teardown.new(app, env)
70
+
67
71
  DependentVMs.add('otherhost.vagrant.test')
68
72
 
69
73
  fake_static_entry(env, 'static.vagrant.test', '3.4.5.6')
@@ -75,23 +79,22 @@ module Landrush
75
79
 
76
80
  it "leaves the server alone if it's not running" do
77
81
  app = proc {}
78
- teardown = Teardown.new(app, nil)
79
82
  env = fake_environment
83
+ teardown = Teardown.new(app, env)
80
84
 
81
85
  teardown.call(env)
82
86
 
83
87
  Server.running?.must_equal false
84
88
  end
85
89
 
86
- it "does nothing when landrush is disabled" do
90
+ it 'does nothing when landrush is disabled' do
87
91
  # somewhat unrealistic since this entry shouldn't be there if it was
88
92
  # disabled in the first place, but oh well
89
93
  Store.hosts.set('somehost.vagrant.test', '1.2.3.4')
90
94
 
91
95
  app = proc {}
92
- teardown = Teardown.new(app, nil)
93
-
94
96
  env = fake_environment
97
+ teardown = Teardown.new(app, env)
95
98
  env[:machine].config.landrush.disable
96
99
 
97
100
  teardown.call(env)
@@ -35,7 +35,6 @@ module Landrush
35
35
 
36
36
  expected = addresses.last['ipv4']
37
37
 
38
- # call_cap(machine).must_equal expected
39
38
  call_cap(machine).must_equal expected
40
39
  end
41
40
 
@@ -81,6 +80,41 @@ module Landrush
81
80
 
82
81
  call_cap(machine).must_equal expected
83
82
  end
83
+
84
+ # Now, let's explicitly test the IPv4/IPv6 selection support, starting with the default (IPv4)
85
+ it 'should return the last non-empty IPv4 address' do
86
+ machine.config.landrush.host_interface = nil
87
+ machine.config.landrush.host_interface_excludes = [/exclude[0-9]+/, /include[0-9]+/]
88
+
89
+ expected = addresses.detect { |a| a['name'] == 'ipv6empty2' }
90
+ expected = expected['ipv4']
91
+
92
+ call_cap(machine).must_equal expected
93
+ end
94
+
95
+ # Test IPv6 selection
96
+ it 'should return the last non-empty IPv6 address' do
97
+ machine.config.landrush.host_interface = nil
98
+ machine.config.landrush.host_interface_class = :ipv6
99
+ machine.config.landrush.host_interface_excludes = [/exclude[0-9]+/, /include[0-9]+/]
100
+
101
+ expected = addresses.detect { |a| a['name'] == 'ipv4empty2' }
102
+ expected = expected['ipv6']
103
+
104
+ call_cap(machine).must_equal expected
105
+ end
106
+
107
+ # Test ANY selection
108
+ it 'should return the last non-empty address of either class' do
109
+ machine.config.landrush.host_interface = nil
110
+ machine.config.landrush.host_interface_class = :any
111
+ machine.config.landrush.host_interface_excludes = [/exclude[0-9]+/, /include[0-9]+/]
112
+
113
+ expected = addresses.detect { |a| a['name'] == 'ipv4empty2' }
114
+ expected = expected['ipv6']
115
+
116
+ call_cap(machine).must_equal expected
117
+ end
84
118
  end
85
119
  end
86
120
  end
@@ -4,30 +4,30 @@ describe Landrush::Cap::Linux::ConfiguredDnsServers do
4
4
  let(:machine) { fake_machine }
5
5
 
6
6
  before do
7
- Landrush::Cap::Linux::ConfiguredDnsServers.instance_variable_set("@dns_servers", nil)
7
+ Landrush::Cap::Linux::ConfiguredDnsServers.instance_variable_set('@dns_servers', nil)
8
8
  end
9
9
 
10
10
  describe 'configured_dns_servers' do
11
11
  it 'parses out a single resolv.conf dns server' do
12
- machine.communicate.stubs(:sudo).yields(:stdout, "nameserver 12.23.34.45")
12
+ machine.communicate.stubs(:sudo).yields(:stdout, 'nameserver 12.23.34.45')
13
13
 
14
14
  dns_servers = Landrush::Cap::Linux::ConfiguredDnsServers.configured_dns_servers(machine)
15
15
 
16
- dns_servers.must_equal(["12.23.34.45"])
16
+ dns_servers.must_equal(['12.23.34.45'])
17
17
  end
18
18
 
19
19
  it 'parses out multiple the resolv.conf dns servers' do
20
20
  machine.communicate.stubs(:sudo).yields(:stdout, [
21
- "nameserver 12.23.34.45",
22
- "nameserver 45.34.23.12"
21
+ 'nameserver 12.23.34.45',
22
+ 'nameserver 45.34.23.12'
23
23
  ].join("\n"))
24
24
 
25
25
  dns_servers = Landrush::Cap::Linux::ConfiguredDnsServers.configured_dns_servers(machine)
26
26
 
27
27
  dns_servers.must_equal([
28
- "12.23.34.45",
29
- "45.34.23.12"
30
- ])
28
+ '12.23.34.45',
29
+ '45.34.23.12'
30
+ ])
31
31
  end
32
32
  end
33
33
  end
@@ -7,10 +7,10 @@ describe Landrush::Cap::Linux::RedirectDns do
7
7
  it 'fetches the dns servers from the machine, and adds one iptables rule per server' do
8
8
  machine.guest.stubs(:capability).with(:configured_dns_servers).returns(%w(1.2.3.4 4.5.6.7))
9
9
 
10
- machine.guest.expects(:capability).with(:add_iptables_rule, "OUTPUT -t nat -p tcp -d 1.2.3.4 --dport 53 -j DNAT --to-destination 2.3.4.5:4321").once
11
- machine.guest.expects(:capability).with(:add_iptables_rule, "OUTPUT -t nat -p udp -d 1.2.3.4 --dport 53 -j DNAT --to-destination 2.3.4.5:4321").once
12
- machine.guest.expects(:capability).with(:add_iptables_rule, "OUTPUT -t nat -p tcp -d 4.5.6.7 --dport 53 -j DNAT --to-destination 2.3.4.5:4321").once
13
- machine.guest.expects(:capability).with(:add_iptables_rule, "OUTPUT -t nat -p udp -d 4.5.6.7 --dport 53 -j DNAT --to-destination 2.3.4.5:4321").once
10
+ machine.guest.expects(:capability).with(:add_iptables_rule, 'OUTPUT -t nat -p tcp -d 1.2.3.4 --dport 53 -j DNAT --to-destination 2.3.4.5:4321').once
11
+ machine.guest.expects(:capability).with(:add_iptables_rule, 'OUTPUT -t nat -p udp -d 1.2.3.4 --dport 53 -j DNAT --to-destination 2.3.4.5:4321').once
12
+ machine.guest.expects(:capability).with(:add_iptables_rule, 'OUTPUT -t nat -p tcp -d 4.5.6.7 --dport 53 -j DNAT --to-destination 2.3.4.5:4321').once
13
+ machine.guest.expects(:capability).with(:add_iptables_rule, 'OUTPUT -t nat -p udp -d 4.5.6.7 --dport 53 -j DNAT --to-destination 2.3.4.5:4321').once
14
14
 
15
15
  Landrush::Cap::Linux::RedirectDns.redirect_dns(
16
16
  machine,