landrush 1.1.2 → 1.2.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.
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
@@ -1,7 +1,7 @@
1
1
  require_relative '../test_helper'
2
2
 
3
3
  describe 'Landrush::Config' do
4
- it "supports enabling via accessor style" do
4
+ it 'supports enabling via accessor style' do
5
5
  machine = fake_machine
6
6
  config = machine.config.landrush
7
7
 
@@ -11,7 +11,7 @@ describe 'Landrush::Config' do
11
11
  config.enabled?.must_equal false
12
12
  end
13
13
 
14
- it "is backwards-compatible with the old method call style" do
14
+ it 'is backwards-compatible with the old method call style' do
15
15
  machine = fake_machine
16
16
  config = machine.config.landrush
17
17
 
@@ -20,4 +20,25 @@ describe 'Landrush::Config' do
20
20
  machine.config.landrush.disable
21
21
  config.enabled?.must_equal false
22
22
  end
23
+
24
+ it 'should validate host_interface_class' do
25
+ machine = fake_machine
26
+ config = machine.config.landrush
27
+
28
+ validation_success = []
29
+ validation_error = [Landrush::Config::INTERFACE_CLASS_INVALID, { fields: 'host_interface_class' }]
30
+
31
+ Landrush::Config::INTERFACE_CLASSES.each do |sym|
32
+ machine.config.landrush.host_interface_class = sym
33
+ config.validate(machine).must_equal('landrush' => validation_success)
34
+
35
+ machine.config.landrush.host_interface_class = sym.to_s
36
+ config.validate(machine).must_equal('landrush' => validation_success)
37
+ end
38
+
39
+ [:invalid_symbol, 'invalid_string', 4].each do |v|
40
+ machine.config.landrush.host_interface_class = v
41
+ config.validate(machine).must_equal('landrush' => validation_error)
42
+ end
43
+ end
23
44
  end
@@ -2,23 +2,23 @@ require_relative '../test_helper'
2
2
 
3
3
  module Landrush
4
4
  describe DependentVMs do
5
- describe "any?" do
6
- it "reports false when nothing has happened" do
5
+ describe 'any?' do
6
+ it 'reports false when nothing has happened' do
7
7
  DependentVMs.any?.must_equal false
8
8
  end
9
9
 
10
- it "reports true once a machine has been added" do
10
+ it 'reports true once a machine has been added' do
11
11
  DependentVMs.add('recordme.example.test')
12
12
  DependentVMs.any?.must_equal true
13
13
  end
14
14
 
15
- it "reports false if a machine has been added then removed" do
15
+ it 'reports false if a machine has been added then removed' do
16
16
  DependentVMs.add('recordme.example.test')
17
17
  DependentVMs.remove('recordme.example.test')
18
18
  DependentVMs.any?.must_equal false
19
19
  end
20
20
 
21
- it "reports true if not all machines have been removed" do
21
+ it 'reports true if not all machines have been removed' do
22
22
  DependentVMs.add('recordme.example.test')
23
23
  DependentVMs.add('alsome.example.test')
24
24
  DependentVMs.remove('recordme.example.test')
@@ -0,0 +1,115 @@
1
+ require_relative '../../test_helper'
2
+
3
+ module Landrush
4
+ module Cap
5
+ module All
6
+ describe ReadHostVisibleIpAddress do
7
+ let(:landrush_ip_output) do
8
+ <<YAML
9
+ - name: br-44ba74744d5d
10
+ ipv4: 172.17.0.1
11
+ ipv6: fe80::42:e1ff:fe01:ae98
12
+ - name: br-7884014b4104
13
+ ipv4: 172.19.0.1
14
+ ipv6: fe80::42:c0ff:fe4b:900c
15
+ - name: br-efce9da0c1fd
16
+ ipv4: 172.18.0.1
17
+ ipv6: fe80::42:2ff:fe46:f1d1
18
+ - name: docker0
19
+ ipv4: 172.16.0.1
20
+ ipv6: fe80::42:dbff:fe1b:6e92
21
+ - name: docker_gwbridge
22
+ ipv4: 172.20.0.1
23
+ ipv6: fe80::42:72ff:fe96:c6df
24
+ - name: enp4s0
25
+ ipv4: 192.168.88.97
26
+ ipv6: fe80::323d:9fa0:ef2a:ddf5
27
+ - name: wlp3s0
28
+ ipv4: 192.168.88.118
29
+ ipv6: fe80::6b80:15d4:e83c:a59d
30
+ - name: lo
31
+ ipv4: 127.0.0.1
32
+ ipv6: ::1/128
33
+ - name: veth050aa01
34
+ ipv4: ""
35
+ ipv6: fe80::c83a:8eff:fe7a:3244
36
+ - name: veth1c191f7
37
+ ipv4: ""
38
+ ipv6: fe80::b498:f3ff:fea1:3243
39
+ - name: veth38aa771
40
+ ipv4: ""
41
+ ipv6: fe80::8c97:e2ff:fe1a:b14f
42
+ - name: veth5f49498
43
+ ipv4: ""
44
+ ipv6: fe80::6825:20ff:fef5:a00d
45
+ - name: veth7803c65
46
+ ipv4: ""
47
+ ipv6: fe80::34d7:6cff:fe28:54ce
48
+ - name: veth8a09803
49
+ ipv4: ""
50
+ ipv6: fe80::b436:30ff:fed1:598e
51
+ - name: veth8bf1652
52
+ ipv4: ""
53
+ ipv6: fe80::60a8:67ff:fe85:cce4
54
+ - name: veth95ef8de
55
+ ipv4: ""
56
+ ipv6: fe80::9c45:e8ff:fe69:e62f
57
+ - name: vethc75f284
58
+ ipv4: ""
59
+ ipv6: fe80::78b2:7fff:fe55:59
60
+ - name: vethe533ef0
61
+ ipv4: ""
62
+ ipv6: fe80::b83e:93ff:fe52:aac7
63
+ YAML
64
+ end
65
+
66
+ let(:machine) { fake_machine }
67
+ let(:addresses) { YAML.load(landrush_ip_output) }
68
+
69
+ def call_cap(machine)
70
+ Landrush::Cap::All::ReadHostVisibleIpAddress.read_host_visible_ip_address(machine)
71
+ end
72
+
73
+ before do
74
+ # TODO: Is there a way to only unstub it for read_host_visible_ip_address?
75
+ machine.guest.unstub(:capability)
76
+ machine.guest.stubs(:capability).with(:landrush_ip_installed).returns(true)
77
+ machine.guest.stubs(:capability).with(:landrush_ip_get).returns(addresses)
78
+
79
+ machine.config.landrush.host_interface = nil
80
+ machine.config.landrush.host_interface_excludes = [/lo[0-9]*/, /docker[0-9]+/, /tun[0-9]+/, /br-(.+)/]
81
+ end
82
+
83
+ describe 'Issue 255: read_host_visible_ip_address failure in presence of interface without IPv4, with IPv6 address' do
84
+ # Test IPv4
85
+ it 'should return the last non-empty IPv4 address' do
86
+ expected = addresses.detect { |a| a['name'] == 'wlp3s0' }
87
+ expected = expected['ipv4']
88
+
89
+ call_cap(machine).must_equal expected
90
+ end
91
+
92
+ # Test IPv6 selection
93
+ it 'should return the last non-empty IPv6 address' do
94
+ machine.config.landrush.host_interface_class = :ipv6
95
+
96
+ expected = addresses.detect { |a| a['name'] == 'vethe533ef0' }
97
+ expected = expected['ipv6']
98
+
99
+ call_cap(machine).must_equal expected
100
+ end
101
+
102
+ # Test ANY selection
103
+ it 'should return the last non-empty address of either class' do
104
+ machine.config.landrush.host_interface_class = :any
105
+
106
+ expected = addresses.detect { |a| a['name'] == 'vethe533ef0' }
107
+ expected = expected['ipv6']
108
+
109
+ call_cap(machine).must_equal expected
110
+ end
111
+ end
112
+ end
113
+ end
114
+ end
115
+ end
@@ -1,16 +1,34 @@
1
- require_relative '../test_helper'
2
1
  require 'resolv'
2
+ require 'tmpdir'
3
+ require 'fileutils'
4
+
5
+ require_relative '../test_helper'
3
6
 
4
7
  module Landrush
5
8
  describe Server do
6
9
  def query(host)
7
- Resolv::DNS.open(:nameserver_port => [["127.0.0.1", Server.port]]) do |r|
10
+ Resolv::DNS.open(nameserver_port: [['127.0.0.1', Server.port]]) do |r|
8
11
  r.getaddress(host).to_s
9
12
  end
10
13
  end
11
14
 
12
15
  def wait_for_port
13
- sleep 1 until (TCPSocket.open('127.0.0.1', Server.port) rescue nil)
16
+ sleep 1 until begin
17
+ TCPSocket.open('127.0.0.1', Server.port)
18
+ rescue
19
+ nil
20
+ end
21
+ end
22
+
23
+ before do
24
+ @tmp_dir = Dir.mktmpdir('landrush-server-test-')
25
+ Server.working_dir = @tmp_dir
26
+ Server.gems_dir = gem_dir
27
+ end
28
+
29
+ after do
30
+ Server.stop
31
+ FileUtils.rm_rf(@tmp_dir) if File.exist?(@tmp_dir)
14
32
  end
15
33
 
16
34
  describe 'start/stop' do
@@ -32,7 +50,7 @@ module Landrush
32
50
 
33
51
  wait_for_port
34
52
 
35
- query("phinze.com").must_match(/\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/)
53
+ query('phinze.com').must_match(/\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/)
36
54
  end
37
55
 
38
56
  it 'responds properly to configured machine entries' do
@@ -3,7 +3,7 @@ require_relative '../test_helper'
3
3
  module Landrush
4
4
  describe Store do
5
5
  before do
6
- @temp_file = Tempfile.new(%w[landrush_test_store .json])
6
+ @temp_file = Tempfile.new(%w(landrush_test_store .json))
7
7
  @store = Store.new(@temp_file)
8
8
  end
9
9
 
@@ -11,14 +11,14 @@ module Landrush
11
11
  @temp_file.unlink
12
12
  end
13
13
 
14
- describe "set" do
15
- it "sets the key to the value and makes it available for getting" do
14
+ describe 'set' do
15
+ it 'sets the key to the value and makes it available for getting' do
16
16
  @store.set('foo', 'bar')
17
17
 
18
18
  @store.get('foo').must_equal 'bar'
19
19
  end
20
20
 
21
- it "allows updating keys that already exist" do
21
+ it 'allows updating keys that already exist' do
22
22
  @store.set('foo', 'bar')
23
23
  @store.set('foo', 'qux')
24
24
 
@@ -26,12 +26,12 @@ module Landrush
26
26
  end
27
27
  end
28
28
 
29
- describe "get" do
30
- it "returns nil for unset values" do
29
+ describe 'get' do
30
+ it 'returns nil for unset values' do
31
31
  @store.get('notakey').must_equal nil
32
32
  end
33
33
 
34
- it "returns the latest set value (no caching)" do
34
+ it 'returns the latest set value (no caching)' do
35
35
  @store.set('foo', 'first')
36
36
  @store.get('foo').must_equal 'first'
37
37
  @store.set('foo', 'second')
@@ -41,8 +41,8 @@ module Landrush
41
41
  end
42
42
  end
43
43
 
44
- describe "delete" do
45
- it "removes the key from the store" do
44
+ describe 'delete' do
45
+ it 'removes the key from the store' do
46
46
  @store.set('now', 'you see me')
47
47
 
48
48
  @store.get('now').must_equal 'you see me'
@@ -53,8 +53,8 @@ module Landrush
53
53
  end
54
54
  end
55
55
 
56
- describe "find" do
57
- it "returns the key that matches the end of the search term" do
56
+ describe 'find' do
57
+ it 'returns the key that matches the end of the search term' do
58
58
  @store.set('somehost.vagrant.test', 'here')
59
59
 
60
60
  @store.find('foo.somehost.vagrant.test').must_equal 'somehost.vagrant.test'
@@ -63,12 +63,12 @@ module Landrush
63
63
  @store.find('host.vagrant.test').must_equal nil
64
64
  end
65
65
 
66
- it "returns exact matches too" do
66
+ it 'returns exact matches too' do
67
67
  @store.set('somehost.vagrant.test', 'here')
68
68
  @store.find('somehost.vagrant.test').must_equal 'somehost.vagrant.test'
69
69
  end
70
70
 
71
- it "returns for prefix searches as well" do
71
+ it 'returns for prefix searches as well' do
72
72
  @store.set('somehost.vagrant.test', 'here')
73
73
 
74
74
  @store.find('somehost').must_equal 'somehost.vagrant.test'
@@ -77,5 +77,20 @@ module Landrush
77
77
  @store.find('someh').must_equal nil
78
78
  end
79
79
  end
80
+
81
+ describe 'clear' do
82
+ it 'clears all keys from the store' do
83
+ @store.set('foo', 'bar')
84
+ @store.set('foo', 'qux')
85
+
86
+ @store.clear!
87
+
88
+ count = 0
89
+ @store.each do
90
+ count += 1
91
+ end
92
+ count.must_equal 0
93
+ end
94
+ end
80
95
  end
81
96
  end
@@ -16,7 +16,7 @@ module SilenceOutput
16
16
  def self.included(base)
17
17
  orig_stop_method = base.method(:stop)
18
18
  base.define_singleton_method :stop do
19
- SilenceOutput.silence {orig_stop_method.call}
19
+ SilenceOutput.silence { orig_stop_method.call }
20
20
  end
21
21
  end
22
22
  end
@@ -31,9 +31,7 @@ module TestServerHooks
31
31
  def teardown
32
32
  super
33
33
  # Cleanup any stray server instances from tests
34
- if Landrush::Server.running?
35
- Landrush::Server.stop
36
- end
34
+ Landrush::Server.stop if Landrush::Server.running?
37
35
  Landrush::Store.reset
38
36
  end
39
37
  end
@@ -1,4 +1,4 @@
1
- $:.push(File.expand_path('../../lib', __FILE__))
1
+ $LOAD_PATH.push(File.expand_path('../../lib', __FILE__))
2
2
 
3
3
  require 'bundler/setup'
4
4
  require 'minitest/spec'
@@ -19,32 +19,53 @@ require 'mocha/mini_test'
19
19
  # Putting include/exclude out of order is kind of the point though ;)
20
20
  def fake_addresses
21
21
  [
22
- {'name' => 'exclude1', 'ipv4' => '172.28.128.1', 'ipv6' => '::1'},
23
- {'name' => 'include1', 'ipv4' => '172.28.128.2', 'ipv6' => '::2'},
24
- {'name' => 'include2', 'ipv4' => '172.28.128.3', 'ipv6' => '::3'},
25
- {'name' => 'include3', 'ipv4' => '172.28.128.4', 'ipv6' => '::4'},
26
- {'name' => 'exclude2', 'ipv4' => '172.28.128.5', 'ipv6' => '::5'},
27
- {'name' => 'exclude3', 'ipv4' => '172.28.128.6', 'ipv6' => '::6'}
22
+ { 'name' => 'ipv6empty1', 'ipv4' => '172.28.128.10', 'ipv6' => '' },
23
+ { 'name' => 'ipv4empty1', 'ipv4' => '', 'ipv6' => '::10' },
24
+ { 'name' => 'ipv6empty2', 'ipv4' => '172.28.128.11', 'ipv6' => '' },
25
+ { 'name' => 'ipv4empty2', 'ipv4' => '', 'ipv6' => '::11' },
26
+ { 'name' => 'exclude1', 'ipv4' => '172.28.128.1', 'ipv6' => '::1' },
27
+ { 'name' => 'include1', 'ipv4' => '172.28.128.2', 'ipv6' => '::2' },
28
+ { 'name' => 'include2', 'ipv4' => '172.28.128.3', 'ipv6' => '::3' },
29
+ { 'name' => 'include3', 'ipv4' => '172.28.128.4', 'ipv6' => '::4' },
30
+ { 'name' => 'exclude2', 'ipv4' => '172.28.128.5', 'ipv6' => '::5' },
31
+ { 'name' => 'exclude3', 'ipv4' => '172.28.128.6', 'ipv6' => '::6' }
28
32
  ]
29
33
  end
30
34
 
31
- def fake_environment(options = {enabled: true})
35
+ def fake_environment(options = { enabled: true })
32
36
  # For the home_path we want the base Vagrant directory
33
37
  vagrant_test_home = Pathname(Landrush::Server.working_dir).parent.parent
34
- {machine: fake_machine(options), ui: FakeUI.new, home_path: vagrant_test_home}
38
+ machine = fake_machine(options)
39
+ { machine: machine, ui: FakeUI.new, home_path: vagrant_test_home, gems_path: machine.env.gems_path }
40
+ end
41
+
42
+ # Returns the gem directory for running unit tests
43
+ def gem_dir
44
+ `gem environment gemdir`.strip!
35
45
  end
36
46
 
37
47
  class FakeUI
48
+ attr_reader :received_detail_messages
38
49
  attr_reader :received_info_messages
50
+ attr_reader :received_error_messages
39
51
 
40
52
  def initialize
53
+ @received_detail_messages = []
41
54
  @received_info_messages = []
55
+ @received_error_messages = []
56
+ end
57
+
58
+ def detail(*args)
59
+ @received_detail_messages << args[0]
42
60
  end
43
61
 
44
62
  def info(*args)
45
- # puts "#{args}"
46
63
  @received_info_messages << args[0]
47
64
  end
65
+
66
+ def error(*args)
67
+ @received_error_messages << args[0]
68
+ end
48
69
  end
49
70
 
50
71
  class RecordingCommunicator
@@ -111,8 +132,10 @@ module Landrush
111
132
  end
112
133
  end
113
134
 
114
- def fake_machine(options={})
135
+ def fake_machine(options = {})
136
+ gem_path = Pathname.new(gem_dir)
115
137
  env = options.fetch(:env, Vagrant::Environment.new)
138
+ env.stubs(:gems_path).returns(gem_path)
116
139
  machine = Vagrant::Machine.new(
117
140
  'fake_machine',
118
141
  'fake_provider',
@@ -122,11 +145,11 @@ def fake_machine(options={})
122
145
  env.vagrantfile.config, # config
123
146
  Pathname('data_dir'),
124
147
  'box',
125
- options.fetch(:env, Vagrant::Environment.new),
148
+ env,
126
149
  env.vagrantfile
127
150
  )
128
151
 
129
- machine.instance_variable_set("@communicator", RecordingCommunicator.new)
152
+ machine.instance_variable_set('@communicator', RecordingCommunicator.new)
130
153
 
131
154
  machine.config.landrush.enabled = options.fetch(:enabled, false)
132
155
  machine.config.landrush.host_interface = nil
@@ -145,7 +168,7 @@ end
145
168
 
146
169
  module MiniTest
147
170
  class Spec
148
- alias_method :hush, :capture_io
171
+ alias hush capture_io
149
172
  end
150
173
  end
151
174