forward 0.3.3 → 1.0.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.
- checksums.yaml +7 -0
- data/.gitignore +2 -0
- data/Gemfile +0 -2
- data/README.md +24 -0
- data/Rakefile +3 -1
- data/bin/forward +1 -1
- data/forward.gemspec +17 -11
- data/lib/forward/api/resource.rb +51 -83
- data/lib/forward/api/tunnel.rb +41 -68
- data/lib/forward/api/user.rb +14 -11
- data/lib/forward/api.rb +7 -26
- data/lib/forward/cli.rb +55 -253
- data/lib/forward/command/account.rb +69 -0
- data/lib/forward/command/base.rb +62 -0
- data/lib/forward/command/config.rb +64 -0
- data/lib/forward/command/tunnel.rb +178 -0
- data/lib/forward/common.rb +44 -0
- data/lib/forward/config.rb +75 -118
- data/lib/forward/request.rb +72 -0
- data/lib/forward/socket.rb +125 -0
- data/lib/forward/static/app.rb +157 -0
- data/lib/forward/static/directory.erb +142 -0
- data/lib/forward/tunnel.rb +102 -40
- data/lib/forward/version.rb +1 -1
- data/lib/forward.rb +80 -63
- data/test/api/resource_test.rb +70 -54
- data/test/api/tunnel_test.rb +50 -51
- data/test/api/user_test.rb +33 -20
- data/test/cli_test.rb +0 -126
- data/test/command/account_test.rb +26 -0
- data/test/command/tunnel_test.rb +133 -0
- data/test/config_test.rb +103 -54
- data/test/forward_test.rb +47 -0
- data/test/test_helper.rb +35 -26
- data/test/tunnel_test.rb +50 -22
- metadata +210 -169
- data/forwardhq.crt +0 -112
- data/lib/forward/api/client_log.rb +0 -20
- data/lib/forward/api/tunnel_key.rb +0 -18
- data/lib/forward/client.rb +0 -110
- data/lib/forward/error.rb +0 -12
- data/test/api/tunnel_key_test.rb +0 -28
- data/test/api_test.rb +0 -0
- data/test/client_test.rb +0 -8
data/test/config_test.rb
CHANGED
@@ -3,93 +3,142 @@ require 'test_helper'
|
|
3
3
|
describe Forward::Config do
|
4
4
|
|
5
5
|
before :each do
|
6
|
-
@
|
7
|
-
|
8
|
-
|
9
|
-
}
|
6
|
+
@config = Forward::Config
|
7
|
+
|
8
|
+
FakeFS.activate!
|
10
9
|
FileUtils.mkdir_p(ENV['HOME'])
|
11
10
|
end
|
12
11
|
|
13
12
|
after :each do
|
14
|
-
FileUtils.
|
15
|
-
|
13
|
+
FileUtils.rm_rf(ENV['HOME'])
|
14
|
+
FakeFS.deactivate!
|
16
15
|
end
|
17
16
|
|
18
|
-
it "
|
19
|
-
config
|
20
|
-
|
21
|
-
|
22
|
-
config.send(key).must_equal value
|
17
|
+
it "sets default config values" do
|
18
|
+
@config.set_defaults!
|
19
|
+
@config::DEFAULTS.each do |setting, value|
|
20
|
+
@config.send(setting).must_equal value
|
23
21
|
end
|
24
22
|
end
|
25
23
|
|
26
|
-
it "
|
27
|
-
config
|
28
|
-
config.
|
24
|
+
it "sets a default config value" do
|
25
|
+
@config.set_default!(:auto_open)
|
26
|
+
@config.auto_open.must_equal @config::DEFAULTS[:auto_open]
|
27
|
+
end
|
29
28
|
|
30
|
-
|
31
|
-
|
32
|
-
|
29
|
+
it "has a windows config path if windows" do
|
30
|
+
Forward.expects(:windows?).returns(true)
|
31
|
+
@config.config_path.must_match /config\z/
|
32
|
+
end
|
33
|
+
|
34
|
+
it "has a non-windows config path if windows" do
|
35
|
+
Forward.expects(:windows?).returns(false)
|
36
|
+
@config.config_path.must_match /\.forwardrc\z/
|
33
37
|
end
|
38
|
+
#
|
39
|
+
it "updates a config with a Hash" do
|
40
|
+
@config.set_defaults!
|
41
|
+
@config.update(auto_copy: false, auto_open: true)
|
34
42
|
|
35
|
-
|
36
|
-
config
|
37
|
-
|
43
|
+
@config.auto_copy.must_equal false
|
44
|
+
@config.auto_open.must_equal true
|
45
|
+
end
|
38
46
|
|
39
|
-
|
47
|
+
it "converts current config to a Hash" do
|
48
|
+
@config.set_defaults!
|
40
49
|
|
41
|
-
|
42
|
-
|
50
|
+
@config.to_hash.must_equal @config::DEFAULTS
|
51
|
+
end
|
43
52
|
|
44
|
-
|
45
|
-
|
46
|
-
|
53
|
+
it "knows if a config file is present" do
|
54
|
+
@config.wont_be :present?
|
55
|
+
FileUtils.touch(@config.config_path)
|
56
|
+
@config.must_be :present?
|
47
57
|
end
|
48
58
|
|
49
|
-
it "
|
50
|
-
config
|
51
|
-
config.write
|
59
|
+
it "writes config to config file" do
|
60
|
+
@config.set_defaults!
|
52
61
|
|
53
|
-
|
54
|
-
|
62
|
+
@config.wont_be :present?
|
63
|
+
@config.write
|
64
|
+
@config.must_be :present?
|
65
|
+
YAML.load_file(@config.config_path).must_equal @config::DEFAULTS
|
55
66
|
end
|
56
67
|
|
57
|
-
it "
|
58
|
-
|
59
|
-
|
68
|
+
it "loads a config file" do
|
69
|
+
File.open(@config.config_path, 'w') { |f|
|
70
|
+
f.write(YAML.dump(@config::DEFAULTS))
|
71
|
+
}
|
60
72
|
|
61
|
-
@
|
62
|
-
|
73
|
+
@config.must_be :present?
|
74
|
+
@config.load
|
75
|
+
@config::DEFAULTS.each do |setting, value|
|
76
|
+
@config.send(setting).must_equal value
|
63
77
|
end
|
64
78
|
end
|
65
79
|
|
66
|
-
it "
|
67
|
-
config
|
80
|
+
it "adds an initial account" do
|
81
|
+
@config.set_defaults!
|
82
|
+
account = { foo: '1234' }
|
83
|
+
subdomain, api_key = account.first
|
68
84
|
|
69
|
-
|
85
|
+
@config.add_account(subdomain, api_key)
|
86
|
+
@config.accounts.wont_be :empty?
|
87
|
+
@config.accounts.has_key?(subdomain).must_equal true
|
88
|
+
@config.default_account.must_equal subdomain
|
70
89
|
end
|
71
90
|
|
72
|
-
it "
|
73
|
-
@
|
74
|
-
|
91
|
+
it "removes an account and sets the default account to the next available" do
|
92
|
+
@config.set_defaults!
|
93
|
+
accounts = { foo: '1234', bar: '4321' }
|
75
94
|
|
76
|
-
|
95
|
+
accounts.each do |subdomain, api_key|
|
96
|
+
@config.add_account(subdomain, api_key)
|
97
|
+
end
|
98
|
+
|
99
|
+
@config.default_account.must_equal accounts.keys.last
|
100
|
+
@config.accounts.size.must_equal accounts.size
|
101
|
+
|
102
|
+
@config.remove_account(accounts.keys.last)
|
103
|
+
|
104
|
+
@config.accounts.size.must_equal accounts.size - 1
|
105
|
+
@config.default_account.must_equal accounts.keys.first
|
77
106
|
end
|
78
107
|
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
# lambda { config.write }.must_raise Forward::ConfigError
|
84
|
-
# end
|
108
|
+
it "removes the last account and sets default account to nil" do
|
109
|
+
@config.set_defaults!
|
110
|
+
account = { foo: '1234' }
|
111
|
+
subdomain, api_key = account.first
|
85
112
|
|
86
|
-
|
87
|
-
|
113
|
+
@config.add_account(subdomain, api_key)
|
114
|
+
@config.remove_account(subdomain)
|
115
|
+
|
116
|
+
@config.accounts.must_be :empty?
|
117
|
+
@config.default_account.must_be_nil
|
88
118
|
end
|
89
119
|
|
90
|
-
it "
|
91
|
-
|
92
|
-
|
120
|
+
it "sets the default account to an existing account" do
|
121
|
+
@config.set_defaults!
|
122
|
+
|
123
|
+
accounts = { foo: '1234', bar: '4321' }
|
124
|
+
default_account = accounts.keys.last
|
125
|
+
|
126
|
+
accounts.each do |subdomain, api_key|
|
127
|
+
@config.add_account(subdomain, api_key)
|
128
|
+
end
|
129
|
+
|
130
|
+
@config.accounts.size.must_equal accounts.size
|
131
|
+
@config.set_default_account default_account
|
132
|
+
@config.default_account.must_equal default_account
|
133
|
+
end
|
134
|
+
|
135
|
+
it "gets the api token from the default account" do
|
136
|
+
@config.set_defaults!
|
137
|
+
account = { foo: '1234' }
|
138
|
+
subdomain, api_key = account.first
|
139
|
+
|
140
|
+
@config.add_account(subdomain, api_key)
|
141
|
+
@config.api_key.must_equal api_key
|
93
142
|
end
|
94
143
|
|
95
144
|
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
describe Forward do
|
4
|
+
|
5
|
+
it 'should know what the host OS is' do
|
6
|
+
hosts = {
|
7
|
+
'mswin' => :windows,
|
8
|
+
'mingw' => :windows,
|
9
|
+
'cygwin' => :windows,
|
10
|
+
'darwin' => :osx,
|
11
|
+
'linux' => :unix,
|
12
|
+
'bsd' => :unix,
|
13
|
+
'foo' => :unknown,
|
14
|
+
}
|
15
|
+
|
16
|
+
hosts.each do |name, kind|
|
17
|
+
RbConfig::CONFIG['host_os'] = name
|
18
|
+
Forward.instance_variable_set("@os", nil)
|
19
|
+
Forward.os.must_equal kind
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'should know when the host OS is windows' do
|
24
|
+
RbConfig::CONFIG['host_os'] = 'mswin'
|
25
|
+
Forward.instance_variable_set("@os", nil)
|
26
|
+
Forward.must_be :windows?
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'should set the log level to debug' do
|
30
|
+
Forward.debug!
|
31
|
+
Forward.logger.level.must_equal Logger::DEBUG
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'should instantiate a logger' do
|
35
|
+
Forward.logger.must_be_instance_of ::Logger
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'should produce a client string identfier' do
|
39
|
+
suppress_warnings do
|
40
|
+
RbConfig::CONFIG['host_os'] = 'darwin13.0.0'
|
41
|
+
RUBY_ENGINE = 'ruby'
|
42
|
+
RUBY_VERSION = '2.0.0'
|
43
|
+
|
44
|
+
Forward.client_string.must_equal "(ruby-2.0.0)(darwin13.0.0)(v#{Forward::VERSION})"
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
data/test/test_helper.rb
CHANGED
@@ -1,41 +1,50 @@
|
|
1
|
-
$LOAD_PATH.unshift(File.expand_path('
|
1
|
+
$LOAD_PATH.unshift(File.expand_path('../', __FILE__))
|
2
2
|
|
3
3
|
require 'rubygems'
|
4
|
+
require 'fileutils'
|
4
5
|
require 'yaml'
|
5
6
|
require 'bundler'
|
6
7
|
Bundler.setup
|
7
8
|
|
9
|
+
require 'forward'
|
8
10
|
require 'minitest/autorun'
|
9
11
|
require 'minitest/pride'
|
10
|
-
require '
|
11
|
-
require '
|
12
|
-
require '
|
13
|
-
|
12
|
+
require 'mocha/mini_test'
|
13
|
+
require 'webmock/minitest'
|
14
|
+
require 'fakefs/safe'
|
15
|
+
|
16
|
+
ENV['FORWARD_API_HOST'] = 'http://localhost'
|
14
17
|
|
15
|
-
|
18
|
+
Forward.logger = Logger.new('/dev/null')
|
16
19
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
20
|
+
WebMock.disable_net_connect!
|
21
|
+
|
22
|
+
module Kernel
|
23
|
+
def dev_null(&block)
|
24
|
+
begin
|
25
|
+
orig_stdout = $stdout.dup
|
26
|
+
$stdout.reopen('/dev/null', 'w')
|
27
|
+
yield
|
28
|
+
ensure
|
29
|
+
$stdout.reopen(orig_stdout)
|
30
|
+
end
|
24
31
|
end
|
25
|
-
end
|
26
32
|
|
27
|
-
def
|
28
|
-
|
29
|
-
|
30
|
-
:status => [ 200, 'OK' ],
|
31
|
-
'content-type' => 'application/json'
|
32
|
-
}
|
33
|
-
|
34
|
-
if options.is_a?(Array)
|
35
|
-
options.map! { |o| base_options.merge(o) }
|
36
|
-
else
|
37
|
-
options = base_options.merge(options)
|
33
|
+
def hash_to_forwardfile(hash)
|
34
|
+
yaml = YAML.dump(hash)
|
35
|
+
File.open('Forwardfile', 'w') { |f| f.write(yaml) }
|
38
36
|
end
|
39
37
|
|
40
|
-
|
38
|
+
def suppress_warnings(&block)
|
39
|
+
original_verbosity = $VERBOSE
|
40
|
+
$VERBOSE = nil
|
41
|
+
result = yield
|
42
|
+
$VERBOSE = original_verbosity
|
43
|
+
|
44
|
+
return result
|
45
|
+
end
|
46
|
+
|
47
|
+
def stop_reactor
|
48
|
+
EM.stop if EM.reactor_running?
|
49
|
+
end
|
41
50
|
end
|
data/test/tunnel_test.rb
CHANGED
@@ -1,29 +1,57 @@
|
|
1
1
|
require 'test_helper'
|
2
2
|
|
3
3
|
describe Forward::Tunnel do
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
:
|
8
|
-
:
|
9
|
-
:
|
10
|
-
:
|
11
|
-
:
|
12
|
-
:
|
13
|
-
:tunneler_public => 'test.forwardhq.com',
|
14
|
-
:timeout => 0
|
4
|
+
before :each do
|
5
|
+
@attributes = {
|
6
|
+
id: '1234',
|
7
|
+
cname: 'foo.bar.com',
|
8
|
+
vhost: '127.0.0.1',
|
9
|
+
hostport: '3000',
|
10
|
+
tunneler: 'test.forwardhq.com',
|
11
|
+
timeout: 0,
|
12
|
+
url: 'test.fwd.wf'
|
15
13
|
}
|
14
|
+
end
|
15
|
+
|
16
|
+
it "creates a tunnel instance" do
|
17
|
+
tunnel = Forward::Tunnel.new(@attributes)
|
18
|
+
|
19
|
+
tunnel.id.must_equal @attributes[:id]
|
20
|
+
tunnel.cname.must_equal @attributes[:cname]
|
21
|
+
tunnel.host.must_equal @attributes[:vhost]
|
22
|
+
tunnel.port.must_equal @attributes[:hostport]
|
23
|
+
tunnel.tunneler.must_equal @attributes[:tunneler]
|
24
|
+
tunnel.timeout.must_equal @attributes[:timeout]
|
25
|
+
|
26
|
+
tunnel.requests.must_be :empty?
|
27
|
+
tunnel.wont_be :open?
|
28
|
+
tunnel.socket.wont_be_nil
|
29
|
+
end
|
30
|
+
|
31
|
+
it "knows if the tunnel is forwarding a directory/static" do
|
32
|
+
attributes = @attributes.dup
|
33
|
+
attributes[:static_path] = './'
|
34
|
+
|
35
|
+
tunnel = Forward::Tunnel.new(attributes)
|
36
|
+
tunnel.must_be :static?
|
37
|
+
end
|
38
|
+
|
39
|
+
it "knows if the tunnel is open" do
|
40
|
+
tunnel = Forward::Tunnel.new(@attributes)
|
41
|
+
|
42
|
+
tunnel.wont_be :open?
|
43
|
+
tunnel.instance_variable_set('@open', true)
|
44
|
+
tunnel.must_be :open?
|
45
|
+
end
|
46
|
+
|
47
|
+
it "displays an appopriate message when forwarding" do
|
48
|
+
attributes2 = @attributes.dup
|
49
|
+
attributes2[:static_path] = './'
|
50
|
+
|
51
|
+
tunnel = Forward::Tunnel.new(@attributes)
|
52
|
+
tunnel2 = Forward::Tunnel.new(attributes2)
|
16
53
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
tunnel.id.must_equal tunnel_response[:_id]
|
21
|
-
tunnel.subdomain.must_equal tunnel_response[:subdomain]
|
22
|
-
tunnel.cname.must_equal tunnel_response[:cname]
|
23
|
-
tunnel.vhost.must_equal tunnel_response[:vhost]
|
24
|
-
tunnel.hostport.must_equal tunnel_response[:hostport]
|
25
|
-
tunnel.port.must_equal tunnel_response[:port]
|
26
|
-
tunnel.tunneler.must_equal tunnel_response[:tunneler_public]
|
27
|
-
tunnel.timeout.must_equal tunnel_response[:timeout]
|
54
|
+
capture_io { tunnel.send(:display_ready_message) }.first.wont_match /directory/i
|
55
|
+
capture_io { tunnel2.send(:display_ready_message) }.first.must_match /directory/i
|
28
56
|
end
|
29
57
|
end
|