forward 0.1.6 → 0.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.
- data/lib/forward/api.rb +10 -7
- data/lib/forward/api/client_log.rb +1 -1
- data/lib/forward/api/resource.rb +14 -15
- data/lib/forward/api/tunnel.rb +27 -30
- data/lib/forward/api/tunnel_key.rb +3 -1
- data/lib/forward/api/user.rb +5 -4
- data/lib/forward/client.rb +22 -3
- data/lib/forward/tunnel.rb +9 -4
- data/lib/forward/version.rb +1 -1
- data/test/api/tunnel_key_test.rb +5 -5
- data/test/api/tunnel_test.rb +82 -44
- data/test/api/user_test.rb +19 -6
- data/test/tunnel_test.rb +22 -1
- metadata +2 -2
data/lib/forward/api.rb
CHANGED
@@ -9,12 +9,15 @@ module Forward
|
|
9
9
|
class BadResponse < StandardError; end
|
10
10
|
class ResourceNotFound < StandardError; end
|
11
11
|
class ResourceError < StandardError
|
12
|
-
attr_reader :action, :errors
|
12
|
+
attr_reader :code, :type, :action, :api_message, :errors
|
13
13
|
|
14
|
-
def initialize(action, json)
|
15
|
-
@
|
16
|
-
@
|
17
|
-
@
|
14
|
+
def initialize(code, action, json = {})
|
15
|
+
@code = code
|
16
|
+
@action = action
|
17
|
+
@json = json
|
18
|
+
@type = json[:type]
|
19
|
+
@api_message = json[:message]
|
20
|
+
@errors = json[:errors] || {}
|
18
21
|
end
|
19
22
|
end
|
20
23
|
|
@@ -35,11 +38,11 @@ module Forward
|
|
35
38
|
end
|
36
39
|
|
37
40
|
def self.token=(token)
|
38
|
-
|
41
|
+
@api_token = token
|
39
42
|
end
|
40
43
|
|
41
44
|
def self.token
|
42
|
-
defined?(
|
45
|
+
defined?(@api_token) ? @api_token : nil
|
43
46
|
end
|
44
47
|
end
|
45
48
|
end
|
data/lib/forward/api/resource.rb
CHANGED
@@ -28,8 +28,6 @@ module Forward
|
|
28
28
|
response = @http.request(@request)
|
29
29
|
|
30
30
|
parse_response(response)
|
31
|
-
rescue ResourceError => e
|
32
|
-
self.class.dispatch_error(e)
|
33
31
|
end
|
34
32
|
|
35
33
|
def build_request(method, params = {})
|
@@ -77,10 +75,11 @@ module Forward
|
|
77
75
|
|
78
76
|
def parse_response(response)
|
79
77
|
log(:debug, "Response: [#{response.code}] `#{response.body}'")
|
78
|
+
code = response.code.to_i
|
80
79
|
|
81
|
-
if
|
80
|
+
if code == 404
|
82
81
|
raise ResourceNotFound
|
83
|
-
elsif
|
82
|
+
elsif ![ 200, 422, 401 ].include? code
|
84
83
|
raise BadResponse, "response code was: #{response.code}"
|
85
84
|
elsif response['content-type'] !~ /^application\/json/
|
86
85
|
raise BadResponse, "response was not JSON, unable to parse"
|
@@ -90,22 +89,22 @@ module Forward
|
|
90
89
|
|
91
90
|
if json.is_a? Hash
|
92
91
|
json.symbolize_keys!
|
93
|
-
raise ResourceError.new(@action, json) if
|
92
|
+
raise ResourceError.new(code, @action, json) if code != 200
|
94
93
|
end
|
95
94
|
|
96
95
|
json
|
97
96
|
end
|
98
97
|
|
99
|
-
def self.dispatch_error(error)
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
end
|
98
|
+
# def self.dispatch_error(error)
|
99
|
+
# Forward.log(:debug, "Dispatching ResourceError: action: #{error.action} errors: #{error.errors.inspect}")
|
100
|
+
# method = :"#{error.action}_error"
|
101
|
+
#
|
102
|
+
# if respond_to? method
|
103
|
+
# send(method, error.errors)
|
104
|
+
# else
|
105
|
+
# Forward::Client.cleanup_and_exit!('An error occured, please contact support@forwardhq.com')
|
106
|
+
# end
|
107
|
+
# end
|
109
108
|
|
110
109
|
private
|
111
110
|
|
data/lib/forward/api/tunnel.rb
CHANGED
@@ -4,7 +4,7 @@ module Forward
|
|
4
4
|
|
5
5
|
def self.create(options = {})
|
6
6
|
resource = Tunnel.new(:create)
|
7
|
-
resource.uri = '/api/tunnels'
|
7
|
+
resource.uri = '/api/v2/tunnels'
|
8
8
|
params = {
|
9
9
|
:hostport => options[:port],
|
10
10
|
:vhost => options[:host],
|
@@ -15,35 +15,39 @@ module Forward
|
|
15
15
|
params[param] = options[param] unless options[param].nil?
|
16
16
|
end
|
17
17
|
|
18
|
-
resource.post(params)
|
18
|
+
resource.post(params)[:tunnel].symbolize_keys
|
19
|
+
rescue ResourceError => e
|
20
|
+
error_on_create(e, options)
|
19
21
|
end
|
20
22
|
|
21
23
|
def self.index
|
22
24
|
resource = Tunnel.new(:index)
|
23
|
-
resource.uri = "/api/tunnels"
|
25
|
+
resource.uri = "/api/v2/tunnels"
|
24
26
|
|
25
|
-
resource.get
|
27
|
+
resource.get[:tunnels]
|
26
28
|
end
|
27
29
|
|
28
30
|
def self.destroy(id)
|
29
31
|
resource = Tunnel.new(:destroy)
|
30
|
-
resource.uri = "/api/tunnels/#{id}"
|
32
|
+
resource.uri = "/api/v2/tunnels/#{id}"
|
31
33
|
|
32
34
|
resource.delete
|
35
|
+
rescue ResourceError => e
|
36
|
+
nil
|
33
37
|
end
|
34
38
|
|
35
39
|
def self.show(id)
|
36
40
|
resource = Tunnel.new(:show)
|
37
|
-
resource.uri = "/api/tunnels/#{id}"
|
41
|
+
resource.uri = "/api/v2/tunnels/#{id}"
|
38
42
|
|
39
|
-
resource.get
|
43
|
+
resource.get[:tunnel].symbolize_keys
|
40
44
|
rescue Forward::Api::ResourceNotFound
|
41
45
|
nil
|
42
46
|
end
|
43
47
|
|
44
48
|
private
|
45
49
|
|
46
|
-
def self.ask_to_destroy(message)
|
50
|
+
def self.ask_to_destroy(message, options)
|
47
51
|
tunnels = index
|
48
52
|
|
49
53
|
puts message
|
@@ -51,49 +55,42 @@ module Forward
|
|
51
55
|
menu.prompt = "Choose a tunnel from the list to close or `q' to exit forward "
|
52
56
|
|
53
57
|
tunnels.each do |tunnel|
|
54
|
-
text = "
|
55
|
-
menu.choice(text) { destroy_and_create(tunnel['_id']) }
|
58
|
+
text = "Forwarding port #{tunnel['hostport']}"
|
59
|
+
menu.choice(text) { destroy_and_create(tunnel['_id'], options) }
|
56
60
|
end
|
57
61
|
menu.hidden('quit') { Forward::Client.cleanup_and_exit! }
|
58
62
|
menu.hidden('exit') { Forward::Client.cleanup_and_exit! }
|
59
63
|
end
|
60
64
|
end
|
61
65
|
|
62
|
-
def self.destroy_and_create(id)
|
66
|
+
def self.destroy_and_create(id, options)
|
63
67
|
Forward.log(:debug, "Destroying tunnel: #{id}")
|
64
68
|
destroy(id)
|
65
69
|
puts "tunnel removed, now we're creating a new one"
|
66
|
-
create(
|
70
|
+
create(options)
|
67
71
|
end
|
68
72
|
|
69
|
-
def self.
|
70
|
-
Forward.log(:debug, "An error occured creating tunnel:\n#{
|
71
|
-
base_errors = errors['base']
|
73
|
+
def self.error_on_create(error, options)
|
74
|
+
Forward.log(:debug, "An error occured creating tunnel:\n#{error.inspect}")
|
72
75
|
|
73
|
-
if
|
74
|
-
message = base_errors.select { |e| e.include? 'limit' }.first
|
76
|
+
if error.type == 'tunnel_limit_reached'
|
75
77
|
Forward.log(:debug, 'Tunnel limit reached')
|
76
|
-
ask_to_destroy(
|
78
|
+
ask_to_destroy(error.api_message, options)
|
79
|
+
elsif error.type =~ /(?:account_suspended|trial_expired)/i
|
80
|
+
Forward::Client.cleanup_and_exit!(error.api_message)
|
77
81
|
else
|
78
82
|
message = "We were unable to create your tunnel for the following reasons: \n"
|
79
|
-
errors.each do |key, value|
|
80
|
-
if key
|
81
|
-
message << " #{
|
82
|
-
|
83
|
-
|
84
|
-
message << " #{error}\n"
|
85
|
-
end
|
83
|
+
error.errors.each do |key, value|
|
84
|
+
if key == 'base'
|
85
|
+
message << " #{value.join(', ')}\n"
|
86
|
+
else
|
87
|
+
value.each { |m| message << " #{key} #{m}\n"}
|
86
88
|
end
|
87
89
|
end
|
88
90
|
Forward::Client.cleanup_and_exit!(message)
|
89
91
|
end
|
90
92
|
end
|
91
93
|
|
92
|
-
def self.destroy_error(errors)
|
93
|
-
# TODO: this is where we will tie into the logger
|
94
|
-
nil
|
95
|
-
end
|
96
|
-
|
97
94
|
end
|
98
95
|
end
|
99
96
|
end
|
@@ -4,11 +4,13 @@ module Forward
|
|
4
4
|
|
5
5
|
def self.create
|
6
6
|
resource = TunnelKey.new(:create)
|
7
|
-
resource.uri = '/api/tunnel_keys'
|
7
|
+
resource.uri = '/api/v2/tunnel_keys'
|
8
8
|
|
9
9
|
response = resource.post
|
10
10
|
|
11
11
|
response[:private_key]
|
12
|
+
rescue
|
13
|
+
Forward::Client.cleanup_and_exit!
|
12
14
|
end
|
13
15
|
|
14
16
|
end
|
data/lib/forward/api/user.rb
CHANGED
@@ -4,13 +4,14 @@ module Forward
|
|
4
4
|
|
5
5
|
def self.api_token(email, password)
|
6
6
|
resource = User.new(:api_token)
|
7
|
-
resource.uri = '/api/users/api_token'
|
7
|
+
resource.uri = '/api/v2/users/api_token'
|
8
8
|
params = { :email => email, :password => password }
|
9
9
|
|
10
|
-
resource.post(params)
|
11
|
-
|
10
|
+
user = resource.post(params)[:user].symbolize_keys
|
11
|
+
user[:id] = user.delete(:_id)
|
12
12
|
|
13
|
-
|
13
|
+
user
|
14
|
+
rescue ResourceError => e
|
14
15
|
Forward::Client.cleanup_and_exit!('Unable to authenticate with email and password')
|
15
16
|
end
|
16
17
|
|
data/lib/forward/client.rb
CHANGED
@@ -20,8 +20,9 @@ module Forward
|
|
20
20
|
if @tunnel.id
|
21
21
|
@tunnel.poll_status
|
22
22
|
else
|
23
|
-
cleanup_and_exit!('Unable to create a tunnel. If this continues contact support@forwardhq.com')
|
23
|
+
Forward::Client.cleanup_and_exit!('Unable to create a tunnel. If this continues contact support@forwardhq.com')
|
24
24
|
end
|
25
|
+
Forward.log(:debug, "Tunnel setup: #{@tunnel.inspect}")
|
25
26
|
|
26
27
|
@tunnel
|
27
28
|
end
|
@@ -48,6 +49,23 @@ module Forward
|
|
48
49
|
true
|
49
50
|
end
|
50
51
|
|
52
|
+
def self.forwarding_message(tunnel)
|
53
|
+
remote = "\033[04mhttps://#{@tunnel.subdomain}.fwd.wf\033[0m"
|
54
|
+
|
55
|
+
unless tunnel.cname.nil? || tunnel.cname.empty?
|
56
|
+
remote << " and \033[04mhttp://#{@tunnel.cname}\033[0m"
|
57
|
+
end
|
58
|
+
|
59
|
+
if !tunnel.vhost.nil? && tunnel.vhost !~ /\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/
|
60
|
+
local = tunnel.vhost
|
61
|
+
local << " port #{tunnel.hostport}" unless tunnel.hostport.to_i == 80
|
62
|
+
else
|
63
|
+
local = "port #{tunnel.hostport}"
|
64
|
+
end
|
65
|
+
|
66
|
+
"Forwarding #{local} to #{remote}\nCtrl-C to stop forwarding"
|
67
|
+
end
|
68
|
+
|
51
69
|
def self.start(options = {})
|
52
70
|
Forward.log(:debug, 'Starting client')
|
53
71
|
trap(:INT) { cleanup_and_exit!('closing tunnel and exiting...') }
|
@@ -56,8 +74,9 @@ module Forward
|
|
56
74
|
@tunnel = @client.setup_tunnel
|
57
75
|
@session = Net::SSH.start(@tunnel.tunneler, Forward.ssh_user, @client.ssh_options)
|
58
76
|
|
59
|
-
Forward.log(:debug, "Starting remote forward at #{@tunnel.subdomain}.fwd.wf
|
60
|
-
puts "Forwarding port #{@tunnel.hostport} at \033[04mhttps://#{@tunnel.subdomain}.fwd.wf\033[0m\nCtrl-C to stop forwarding"
|
77
|
+
Forward.log(:debug, "Starting remote forward at #{@tunnel.subdomain}.fwd.wf")
|
78
|
+
# puts "Forwarding port #{@tunnel.hostport} at \033[04mhttps://#{@tunnel.subdomain}.fwd.wf\033[0m\nCtrl-C to stop forwarding"
|
79
|
+
puts forwarding_message(@tunnel)
|
61
80
|
|
62
81
|
@session.forward.remote(@tunnel.hostport, @tunnel.host, @tunnel.port)
|
63
82
|
@session.loop { watch_session(@session) }
|
data/lib/forward/tunnel.rb
CHANGED
@@ -2,20 +2,24 @@ module Forward
|
|
2
2
|
class Tunnel
|
3
3
|
CHECK_INTERVAL = 7
|
4
4
|
|
5
|
-
# The Tunnel resource ID
|
5
|
+
# The Tunnel resource ID
|
6
6
|
attr_reader :id
|
7
|
-
# The domain for the Tunnel
|
7
|
+
# The domain for the Tunnel
|
8
8
|
attr_reader :subdomain
|
9
|
+
# The CNAME for the Tunnel
|
10
|
+
attr_reader :cname
|
9
11
|
# The host
|
10
12
|
attr_reader :host
|
11
13
|
# The vhost
|
12
14
|
attr_reader :vhost
|
13
15
|
# The hostport (local port)
|
14
16
|
attr_reader :hostport
|
15
|
-
# The remote port
|
17
|
+
# The remote port
|
16
18
|
attr_reader :port
|
17
|
-
# The tunneler host
|
19
|
+
# The tunneler host
|
18
20
|
attr_reader :tunneler
|
21
|
+
# The timeout
|
22
|
+
attr_reader :timeout
|
19
23
|
# The amount of time in seconds the Tunnel has be inactive for
|
20
24
|
attr_accessor :inactive_for
|
21
25
|
|
@@ -28,6 +32,7 @@ module Forward
|
|
28
32
|
@response = Forward::Api::Tunnel.create(options)
|
29
33
|
@id = @response[:_id]
|
30
34
|
@subdomain = @response[:subdomain]
|
35
|
+
@cname = @response[:cname]
|
31
36
|
@vhost = @response[:vhost]
|
32
37
|
@hostport = @response[:hostport]
|
33
38
|
@port = @response[:port]
|
data/lib/forward/version.rb
CHANGED
data/test/api/tunnel_key_test.rb
CHANGED
@@ -6,19 +6,19 @@ describe Forward::Api::TunnelKey do
|
|
6
6
|
FakeWeb.allow_net_connect = false
|
7
7
|
end
|
8
8
|
|
9
|
-
it
|
9
|
+
it "retrieves the public_key and returns it" do
|
10
10
|
fake_body = { :private_key => 'ssh-key 1234567890' }
|
11
11
|
|
12
|
-
stub_api_request(:post, '/api/tunnel_keys', :body => fake_body.to_json)
|
12
|
+
stub_api_request(:post, '/api/v2/tunnel_keys', :body => fake_body.to_json)
|
13
13
|
|
14
14
|
response = Api::TunnelKey.create
|
15
15
|
response.must_equal fake_body[:private_key]
|
16
16
|
end
|
17
17
|
|
18
|
-
it
|
19
|
-
fake_body = { :
|
18
|
+
it "exits with message if response has errors" do
|
19
|
+
fake_body = { :type => 'api_error' }
|
20
20
|
|
21
|
-
stub_api_request(:post, '/api/tunnel_keys', :body => fake_body.to_json)
|
21
|
+
stub_api_request(:post, '/api/v2/tunnel_keys', :body => fake_body.to_json, :status => [ 422, 'Unprocessable Entity' ])
|
22
22
|
|
23
23
|
lambda {
|
24
24
|
dev_null { Api::TunnelKey.create }
|
data/test/api/tunnel_test.rb
CHANGED
@@ -7,66 +7,104 @@ describe Forward::Api::Tunnel do
|
|
7
7
|
Forward::Api.token = 'abc123'
|
8
8
|
end
|
9
9
|
|
10
|
-
it
|
11
|
-
|
12
|
-
fake_body = { :_id => '1', :subdomain => 'foo', :port => 56789 }
|
10
|
+
it "creates a tunnel and returns the attributes" do
|
11
|
+
fake_body = { :tunnel => { :_id => '1', :subdomain => 'foo', :port => 56789 }}
|
13
12
|
|
14
|
-
stub_api_request(:post, '/api/tunnels', :body => fake_body.to_json)
|
13
|
+
stub_api_request(:post, '/api/v2/tunnels', :body => fake_body.to_json)
|
15
14
|
|
16
15
|
response = Forward::Api::Tunnel.create(:port => 3000)
|
17
16
|
|
18
|
-
|
19
|
-
|
20
|
-
|
17
|
+
response[:_id].must_equal fake_body[:tunnel][:_id]
|
18
|
+
response[:subdomain].must_equal fake_body[:tunnel][:subdomain]
|
19
|
+
response[:port].must_equal fake_body[:tunnel][:port]
|
21
20
|
end
|
22
21
|
|
23
|
-
it
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
22
|
+
it "exits with message if create response is a resource_error" do
|
23
|
+
fake_body = {
|
24
|
+
:type => 'resource_error',
|
25
|
+
:errors => {
|
26
|
+
:base => [ 'did not work '],
|
27
|
+
:subdomain => [ 'is invalid', 'is too short' ]
|
28
|
+
}
|
29
|
+
}
|
30
|
+
|
31
|
+
stub_api_request(:post, '/api/v2/tunnels', :body => fake_body.to_json, :status => [ 422, 'Unprocessable Entity' ])
|
32
|
+
|
33
|
+
out, err = capture_io do
|
34
|
+
begin
|
35
|
+
Forward::Api::Tunnel.create(:port => 3000)
|
36
|
+
rescue SystemExit; end
|
37
|
+
end
|
38
|
+
out.must_match /did not work/i
|
39
|
+
out.must_match /subdomain is invalid/i
|
40
|
+
out.must_match /subdomain is too short/i
|
32
41
|
end
|
33
42
|
|
34
|
-
it
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
43
|
+
it "exits with message if trial has expired" do
|
44
|
+
fake_body = {
|
45
|
+
:type => 'trial_expired',
|
46
|
+
:message => 'your trial has expired'
|
47
|
+
}
|
48
|
+
|
49
|
+
stub_api_request(:post, '/api/v2/tunnels', :body => fake_body.to_json, :status => [ 422, 'Unprocessable Entity' ])
|
50
|
+
|
51
|
+
out, err = capture_io do
|
52
|
+
begin
|
53
|
+
Forward::Api::Tunnel.create(:port => 3000)
|
54
|
+
rescue SystemExit; end
|
55
|
+
end
|
56
|
+
out.must_match /trial has expired/i
|
57
|
+
end
|
58
|
+
|
59
|
+
it "exits with message if account has been suspended" do
|
60
|
+
fake_body = {
|
61
|
+
:type => 'account_suspended',
|
62
|
+
:message => 'your account has been suspended due for failed payment'
|
63
|
+
}
|
64
|
+
|
65
|
+
stub_api_request(:post, '/api/v2/tunnels', :body => fake_body.to_json, :status => [ 422, 'Unprocessable Entity' ])
|
66
|
+
|
67
|
+
out, err = capture_io do
|
68
|
+
begin
|
69
|
+
Forward::Api::Tunnel.create(:port => 3000)
|
70
|
+
rescue SystemExit; end
|
71
|
+
end
|
72
|
+
out.must_match /account has been suspended/i
|
73
|
+
end
|
74
|
+
|
75
|
+
it "gives a choice and closes a tunnel if limit is reached" do
|
76
|
+
post_options = [
|
77
|
+
{ :body => { :type => 'tunnel_limit_reached', :message => 'you have reached your limit' }.to_json, :status => [ 422, 'Unprocessable Entity' ] },
|
78
|
+
{ :body => { :tunnel => { :_id => '1', :subdomain => 'foo', :port => 56789 } }.to_json }
|
79
|
+
]
|
80
|
+
index_body = { :tunnels => [ { :_id => 'abc123', :hostport => 1234 }, { :_id => 'def456', :hostport => 1235 } ] }
|
41
81
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
82
|
+
stub_api_request(:post, '/api/v2/tunnels', post_options)
|
83
|
+
stub_api_request(:get, '/api/v2/tunnels', :body => index_body.to_json)
|
84
|
+
STDIN.expects(:gets).returns('1')
|
85
|
+
Forward::Api::Tunnel.expects(:destroy).with(index_body[:tunnels].first[:_id])
|
46
86
|
|
47
|
-
|
48
|
-
|
87
|
+
dev_null { Forward::Api::Tunnel.create(:port => 3000) }
|
88
|
+
end
|
49
89
|
|
50
|
-
|
51
|
-
|
52
|
-
fake_body = { :_id => '1', :subdomain => 'foo', :port => 56789 }
|
90
|
+
it 'destroys a tunnel and returns the attributes' do
|
91
|
+
fake_body = { :_id => '1', :subdomain => 'foo', :port => 56789 }
|
53
92
|
|
54
|
-
|
93
|
+
stub_api_request(:delete, '/api/v2/tunnels/1', :body => fake_body.to_json)
|
55
94
|
|
56
|
-
|
95
|
+
response = Forward::Api::Tunnel.destroy(1)
|
57
96
|
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
97
|
+
fake_body.each do |key, value|
|
98
|
+
response[key].must_equal fake_body[key]
|
99
|
+
end
|
100
|
+
end
|
62
101
|
|
63
|
-
|
64
|
-
|
65
|
-
fake_body = { :errors => { :base => 'unable to create tunnel' } }
|
102
|
+
it 'gracefully handles the error if destroy has errors' do
|
103
|
+
fake_body = { :type => 'api_error' }
|
66
104
|
|
67
|
-
|
105
|
+
stub_api_request(:delete, '/api/v2/tunnels/1', :body => fake_body.to_json, :status => [ 422, 'Unprocessable Entity' ])
|
68
106
|
|
69
|
-
|
70
|
-
|
107
|
+
Forward::Api::Tunnel.destroy(1).must_be_nil
|
108
|
+
end
|
71
109
|
|
72
110
|
end
|
data/test/api/user_test.rb
CHANGED
@@ -6,19 +6,32 @@ describe Forward::Api::User do
|
|
6
6
|
FakeWeb.allow_net_connect = false
|
7
7
|
end
|
8
8
|
|
9
|
-
it
|
10
|
-
fake_body
|
9
|
+
it "retrieves the users api token and returns it" do
|
10
|
+
fake_body = { :user => { :api_token => '123abc' } }
|
11
11
|
|
12
|
-
stub_api_request(:post, '/api/users/api_token', :body => fake_body.to_json)
|
12
|
+
stub_api_request(:post, '/api/v2/users/api_token', :body => fake_body.to_json)
|
13
13
|
|
14
14
|
response = Api::User.api_token('guy@example.com', 'secret')
|
15
15
|
response[:api_token].must_equal '123abc'
|
16
16
|
end
|
17
17
|
|
18
|
-
it
|
19
|
-
fake_body
|
18
|
+
it "exits with message if authentication fails" do
|
19
|
+
fake_body = { :type => 'api_error' }
|
20
20
|
|
21
|
-
stub_api_request(:post, '/api/users/api_token', :body => fake_body.to_json)
|
21
|
+
stub_api_request(:post, '/api/v2/users/api_token', :body => fake_body.to_json, :status => [ 401, 'Authentication Failed' ])
|
22
|
+
|
23
|
+
out, err = capture_io do
|
24
|
+
begin
|
25
|
+
Api::User.api_token('guy@example.com', 'secret')
|
26
|
+
rescue SystemExit; end
|
27
|
+
end
|
28
|
+
out.must_match /unable to authenticate/i
|
29
|
+
end
|
30
|
+
|
31
|
+
it "exits with message if response has errors" do
|
32
|
+
fake_body = { :type => 'api_error' }
|
33
|
+
|
34
|
+
stub_api_request(:post, '/api/v2/users/api_token', :body => fake_body.to_json, :status => [ 422, 'Unprocessable Entity' ])
|
22
35
|
|
23
36
|
lambda {
|
24
37
|
dev_null { Api::User.api_token('guy@example.com', 'secret') }
|
data/test/tunnel_test.rb
CHANGED
@@ -2,7 +2,28 @@ require 'test_helper'
|
|
2
2
|
|
3
3
|
describe Forward::Tunnel do
|
4
4
|
|
5
|
-
it
|
5
|
+
it "create a tunnel instance" do
|
6
|
+
tunnel_response = {
|
7
|
+
:_id => '1234',
|
8
|
+
:subdomain => 'foo',
|
9
|
+
:cname => 'foo.bar.com',
|
10
|
+
:vhost => '127.0.0.1',
|
11
|
+
:hostport => '3000',
|
12
|
+
:port => 20000,
|
13
|
+
:tunneler_public => 'test.forwardhq.com',
|
14
|
+
:timeout => 0
|
15
|
+
}
|
6
16
|
|
17
|
+
Forward::Api::Tunnel.expects(:create).returns(tunnel_response)
|
18
|
+
tunnel = Forward::Tunnel.new
|
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]
|
7
28
|
end
|
8
29
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: forward
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.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: 2012-
|
12
|
+
date: 2012-12-12 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: json
|