bixby-common 0.4.4 → 0.4.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +4 -0
- data/Gemfile.lock +6 -16
- data/VERSION +1 -1
- data/bixby-common.gemspec +17 -5
- data/lib/bixby-common.rb +0 -1
- data/lib/bixby-common/api/json_request.rb +9 -0
- data/lib/bixby-common/api/rpc_handler.rb +3 -0
- data/lib/bixby-common/util/crypto_util.rb +17 -0
- data/lib/bixby-common/util/debug.rb +6 -2
- data/lib/bixby-common/util/http_client.rb +4 -0
- data/lib/bixby-common/util/log/logger.rb +2 -0
- data/lib/bixby-common/websocket/api_channel.rb +2 -0
- data/lib/bixby-common/websocket/async_response.rb +1 -1
- data/lib/bixby-common/websocket/message.rb +7 -5
- data/lib/bixby-common/websocket/request.rb +1 -2
- data/lib/bixby-common/websocket/response.rb +1 -2
- data/test/api/http_channel_test.rb +65 -0
- data/test/base.rb +16 -0
- data/test/command_response_test.rb +32 -1
- data/test/command_spec_test.rb +2 -2
- data/test/helper.rb +4 -0
- data/test/side_effect.rb +15 -0
- data/test/test_handler.rb +7 -0
- data/test/util/crypto_util_test.rb +34 -0
- data/test/util/http_client_test.rb +2 -1
- data/test/util/log_test.rb +24 -1
- data/test/websocket/api_channel_test.rb +100 -0
- data/test/websocket/async_response_test.rb +43 -0
- data/test/websocket/request_test.rb +65 -0
- data/test/websocket/response_test.rb +45 -0
- metadata +26 -4
- data/lib/bixby-common/websocket/client.rb +0 -125
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 35c3c23073295651e3c85e8e1c6e874890cd0cf2
|
4
|
+
data.tar.gz: 82f4b7036f6ac6b98162dd7c77aed1fec5a66841
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2bbfc1cdbda553922468d37fbc7ad96a3ab709dd1634efcdb972b5e22abda26c8105ff54944be50f1f0c3d40aaaa8547ad5e80d71003dc8ecaeb471b6b2e2387
|
7
|
+
data.tar.gz: d7b1596b8a5cac4d7ab3bf1bc6078ec5bb9a9ad2cf5b825bdbb09c2bed3632d7b472b83176e6d5ac9ae545e82bce43ad4c057d241175cf14b28efa9ed98a855a
|
data/Gemfile
CHANGED
@@ -8,6 +8,10 @@ gem "logging"
|
|
8
8
|
gem "api-auth", :git => "https://github.com/chetan/api_auth.git", :branch => "bixby"
|
9
9
|
|
10
10
|
group :development do
|
11
|
+
|
12
|
+
# for some tests
|
13
|
+
gem "mixlib-shellout"
|
14
|
+
|
11
15
|
gem "yard", "~> 0.8"
|
12
16
|
gem "bundler", "~> 1.1"
|
13
17
|
gem "jeweler", :git => "https://github.com/chetan/jeweler.git", :branch => "bixby"
|
data/Gemfile.lock
CHANGED
@@ -31,12 +31,10 @@ GIT
|
|
31
31
|
|
32
32
|
GIT
|
33
33
|
remote: https://github.com/chetan/test_guard.git
|
34
|
-
revision:
|
34
|
+
revision: b60ce3e2cc47746142f0eba0cff5bcf3b550a88c
|
35
35
|
specs:
|
36
36
|
test_guard (0.2.1)
|
37
37
|
awesome_print
|
38
|
-
debugger
|
39
|
-
debugger-pry
|
40
38
|
growl
|
41
39
|
listen
|
42
40
|
simplecov
|
@@ -54,19 +52,9 @@ GEM
|
|
54
52
|
builder (3.2.2)
|
55
53
|
coderay (1.0.9)
|
56
54
|
colorize (0.5.8)
|
57
|
-
columnize (0.3.6)
|
58
55
|
crack (0.4.1)
|
59
56
|
safe_yaml (~> 0.9.0)
|
60
57
|
curb (0.8.4)
|
61
|
-
debugger (1.6.1)
|
62
|
-
columnize (>= 0.3.1)
|
63
|
-
debugger-linecache (~> 1.2.0)
|
64
|
-
debugger-ruby_core_source (~> 1.2.3)
|
65
|
-
debugger-linecache (1.2.0)
|
66
|
-
debugger-pry (0.1.1)
|
67
|
-
debugger (~> 1)
|
68
|
-
pry (>= 0.9.9)
|
69
|
-
debugger-ruby_core_source (1.2.3)
|
70
58
|
eventmachine (1.0.3)
|
71
59
|
eventmachine (1.0.3-java)
|
72
60
|
faraday (0.8.8)
|
@@ -99,7 +87,7 @@ GEM
|
|
99
87
|
json (1.8.0-java)
|
100
88
|
jwt (0.1.8)
|
101
89
|
multi_json (>= 1.5)
|
102
|
-
listen (1.3.
|
90
|
+
listen (1.3.1)
|
103
91
|
rb-fsevent (>= 0.9.3)
|
104
92
|
rb-inotify (>= 0.9)
|
105
93
|
rb-kqueue (>= 0.2)
|
@@ -110,9 +98,10 @@ GEM
|
|
110
98
|
metaclass (0.0.1)
|
111
99
|
method_source (0.8.2)
|
112
100
|
minitest (4.7.5)
|
101
|
+
mixlib-shellout (1.2.0)
|
113
102
|
mocha (0.14.0)
|
114
103
|
metaclass (~> 0.0.1)
|
115
|
-
multi_json (1.
|
104
|
+
multi_json (1.8.0)
|
116
105
|
multi_xml (0.5.5)
|
117
106
|
multipart-post (1.2.0)
|
118
107
|
nokogiri (1.5.10)
|
@@ -139,7 +128,7 @@ GEM
|
|
139
128
|
rb-fchange (0.0.6)
|
140
129
|
ffi
|
141
130
|
rb-fsevent (0.9.3)
|
142
|
-
rb-inotify (0.9.
|
131
|
+
rb-inotify (0.9.2)
|
143
132
|
ffi (>= 0.5.0)
|
144
133
|
rb-kqueue (0.2.0)
|
145
134
|
ffi (>= 0.5.0)
|
@@ -184,6 +173,7 @@ DEPENDENCIES
|
|
184
173
|
json
|
185
174
|
logging
|
186
175
|
minitest (~> 4.0)
|
176
|
+
mixlib-shellout
|
187
177
|
mocha
|
188
178
|
multi_json
|
189
179
|
oj
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.4.
|
1
|
+
0.4.5
|
data/bixby-common.gemspec
CHANGED
@@ -2,14 +2,15 @@
|
|
2
2
|
# DO NOT EDIT THIS FILE DIRECTLY
|
3
3
|
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
4
|
# -*- encoding: utf-8 -*-
|
5
|
+
# stub: bixby-common 0.4.5 ruby lib
|
5
6
|
|
6
7
|
Gem::Specification.new do |s|
|
7
8
|
s.name = "bixby-common"
|
8
|
-
s.version = "0.4.
|
9
|
+
s.version = "0.4.5"
|
9
10
|
|
10
11
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
12
|
s.authors = ["Chetan Sarva"]
|
12
|
-
s.date = "2013-09-
|
13
|
+
s.date = "2013-09-13"
|
13
14
|
s.description = "Bixby Common files/libs"
|
14
15
|
s.email = "chetan@pixelcop.net"
|
15
16
|
s.extra_rdoc_files = [
|
@@ -48,27 +49,35 @@ Gem::Specification.new do |s|
|
|
48
49
|
"lib/bixby-common/util/log/logger.rb",
|
49
50
|
"lib/bixby-common/websocket/api_channel.rb",
|
50
51
|
"lib/bixby-common/websocket/async_response.rb",
|
51
|
-
"lib/bixby-common/websocket/client.rb",
|
52
52
|
"lib/bixby-common/websocket/message.rb",
|
53
53
|
"lib/bixby-common/websocket/request.rb",
|
54
54
|
"lib/bixby-common/websocket/response.rb",
|
55
|
+
"test/api/http_channel_test.rb",
|
56
|
+
"test/base.rb",
|
55
57
|
"test/bixby_common_test.rb",
|
56
58
|
"test/command_response_test.rb",
|
57
59
|
"test/command_spec_test.rb",
|
58
60
|
"test/helper.rb",
|
61
|
+
"test/side_effect.rb",
|
59
62
|
"test/support/repo/vendor/test_bundle/bin/cat",
|
60
63
|
"test/support/repo/vendor/test_bundle/bin/cat.json",
|
61
64
|
"test/support/repo/vendor/test_bundle/bin/echo",
|
62
65
|
"test/support/repo/vendor/test_bundle/digest",
|
63
66
|
"test/support/repo/vendor/test_bundle/manifest.json",
|
67
|
+
"test/test_handler.rb",
|
68
|
+
"test/util/crypto_util_test.rb",
|
64
69
|
"test/util/http_client_test.rb",
|
65
70
|
"test/util/jsonify_test.rb",
|
66
|
-
"test/util/log_test.rb"
|
71
|
+
"test/util/log_test.rb",
|
72
|
+
"test/websocket/api_channel_test.rb",
|
73
|
+
"test/websocket/async_response_test.rb",
|
74
|
+
"test/websocket/request_test.rb",
|
75
|
+
"test/websocket/response_test.rb"
|
67
76
|
]
|
68
77
|
s.homepage = "http://github.com/chetan/bixby-common"
|
69
78
|
s.licenses = ["MIT"]
|
70
79
|
s.require_paths = ["lib"]
|
71
|
-
s.rubygems_version = "2.0
|
80
|
+
s.rubygems_version = "2.1.0"
|
72
81
|
s.summary = "Bixby Common"
|
73
82
|
|
74
83
|
if s.respond_to? :specification_version then
|
@@ -80,6 +89,7 @@ Gem::Specification.new do |s|
|
|
80
89
|
s.add_runtime_dependency(%q<httpi>, [">= 0"])
|
81
90
|
s.add_runtime_dependency(%q<logging>, [">= 0"])
|
82
91
|
s.add_runtime_dependency(%q<api-auth>, [">= 0"])
|
92
|
+
s.add_development_dependency(%q<mixlib-shellout>, [">= 0"])
|
83
93
|
s.add_development_dependency(%q<yard>, ["~> 0.8"])
|
84
94
|
s.add_development_dependency(%q<bundler>, ["~> 1.1"])
|
85
95
|
s.add_development_dependency(%q<jeweler>, [">= 0"])
|
@@ -106,6 +116,7 @@ Gem::Specification.new do |s|
|
|
106
116
|
s.add_dependency(%q<httpi>, [">= 0"])
|
107
117
|
s.add_dependency(%q<logging>, [">= 0"])
|
108
118
|
s.add_dependency(%q<api-auth>, [">= 0"])
|
119
|
+
s.add_dependency(%q<mixlib-shellout>, [">= 0"])
|
109
120
|
s.add_dependency(%q<yard>, ["~> 0.8"])
|
110
121
|
s.add_dependency(%q<bundler>, ["~> 1.1"])
|
111
122
|
s.add_dependency(%q<jeweler>, [">= 0"])
|
@@ -133,6 +144,7 @@ Gem::Specification.new do |s|
|
|
133
144
|
s.add_dependency(%q<httpi>, [">= 0"])
|
134
145
|
s.add_dependency(%q<logging>, [">= 0"])
|
135
146
|
s.add_dependency(%q<api-auth>, [">= 0"])
|
147
|
+
s.add_dependency(%q<mixlib-shellout>, [">= 0"])
|
136
148
|
s.add_dependency(%q<yard>, ["~> 0.8"])
|
137
149
|
s.add_dependency(%q<bundler>, ["~> 1.1"])
|
138
150
|
s.add_dependency(%q<jeweler>, [">= 0"])
|
data/lib/bixby-common.rb
CHANGED
@@ -17,7 +17,6 @@ module Bixby
|
|
17
17
|
module WebSocket
|
18
18
|
autoload :APIChannel, "bixby-common/websocket/api_channel"
|
19
19
|
autoload :AsyncResponse, "bixby-common/websocket/async_response"
|
20
|
-
autoload :Client, "bixby-common/websocket/client"
|
21
20
|
autoload :Message, "bixby-common/websocket/message"
|
22
21
|
autoload :Request, "bixby-common/websocket/request"
|
23
22
|
autoload :Response, "bixby-common/websocket/response"
|
@@ -36,5 +36,14 @@ class JsonRequest
|
|
36
36
|
MultiJson.dump(self)
|
37
37
|
end
|
38
38
|
|
39
|
+
# Test if this object is equal to some other object
|
40
|
+
#
|
41
|
+
# @param [JsonRequest] other
|
42
|
+
#
|
43
|
+
# @return [Boolean]
|
44
|
+
def ==(other)
|
45
|
+
operation == other.operation && params == other.params
|
46
|
+
end
|
47
|
+
|
39
48
|
end # JsonRequest
|
40
49
|
end # Bixby
|
@@ -66,13 +66,30 @@ module Bixby
|
|
66
66
|
return data.read
|
67
67
|
end
|
68
68
|
|
69
|
+
# Generate a new 2048-bit RSA keypair
|
70
|
+
#
|
71
|
+
# @return [OpenSSL::PKey::RSA]
|
72
|
+
def generate_keypair
|
73
|
+
OpenSSL::PKey::RSA.generate(2048)
|
74
|
+
end
|
75
|
+
|
76
|
+
# Generate a new access key
|
77
|
+
#
|
78
|
+
# @return [String]
|
79
|
+
# :nocov:
|
69
80
|
def generate_access_key
|
70
81
|
Digest.hexencode(Digest::MD5.new.digest(OpenSSL::Random.random_bytes(512)))
|
71
82
|
end
|
83
|
+
# :nocov:
|
72
84
|
|
85
|
+
# Generate a new secret key
|
86
|
+
#
|
87
|
+
# @return [String]
|
88
|
+
# :nocov:
|
73
89
|
def generate_secret_key
|
74
90
|
Digest.hexencode(Digest::SHA2.new(512).digest(OpenSSL::Random.random_bytes(512)))
|
75
91
|
end
|
92
|
+
# :nocov:
|
76
93
|
|
77
94
|
|
78
95
|
private
|
@@ -2,8 +2,10 @@
|
|
2
2
|
module Bixby
|
3
3
|
module Debug
|
4
4
|
|
5
|
+
# :nocov:
|
6
|
+
|
5
7
|
# Simple helper for use in to_s methods
|
6
|
-
def self.pretty_str(str)
|
8
|
+
def self.pretty_str(str)
|
7
9
|
if str.nil? then
|
8
10
|
"nil"
|
9
11
|
elsif str.empty? then
|
@@ -13,7 +15,7 @@ module Bixby
|
|
13
15
|
else
|
14
16
|
'"' + str + '"'
|
15
17
|
end
|
16
|
-
end
|
18
|
+
end
|
17
19
|
|
18
20
|
# Pretty print a hash
|
19
21
|
#
|
@@ -41,5 +43,7 @@ module Bixby
|
|
41
43
|
str.gsub(/\n/, "\n#{indent}")
|
42
44
|
end
|
43
45
|
|
46
|
+
# :nocov:
|
47
|
+
|
44
48
|
end # Debug
|
45
49
|
end # Bixby
|
@@ -22,9 +22,11 @@ module HttpClient
|
|
22
22
|
#
|
23
23
|
# @param [String] url
|
24
24
|
# @return [Object] Result of calling JSON.parse() on the response body
|
25
|
+
# :nocov:
|
25
26
|
def http_get_json(url)
|
26
27
|
MultiJson.load(http_get(url))
|
27
28
|
end
|
29
|
+
# :nocov:
|
28
30
|
|
29
31
|
# Execute an HTTP POST request to the given URL
|
30
32
|
#
|
@@ -41,9 +43,11 @@ module HttpClient
|
|
41
43
|
# @param [String] url
|
42
44
|
# @param [Hash] data Key/Value pairs to POST
|
43
45
|
# @return [Object] Result of calling JSON.parse() on the response body
|
46
|
+
# :nocov:
|
44
47
|
def http_post_json(url, data)
|
45
48
|
MultiJson.load(http_post(url, data))
|
46
49
|
end
|
50
|
+
# :nocov:
|
47
51
|
|
48
52
|
# Execute an HTTP post request and save the response body
|
49
53
|
#
|
@@ -3,6 +3,7 @@
|
|
3
3
|
|
4
4
|
module Logging
|
5
5
|
class Logger
|
6
|
+
# :nocov:
|
6
7
|
|
7
8
|
# Override to pass trace flag from parent to child
|
8
9
|
def initialize( name )
|
@@ -16,6 +17,7 @@ module Logging
|
|
16
17
|
_setup(name, :parent => parent, :trace => parent.trace)
|
17
18
|
end
|
18
19
|
|
20
|
+
# :nocov:
|
19
21
|
end
|
20
22
|
end
|
21
23
|
|
@@ -9,10 +9,7 @@ module Bixby
|
|
9
9
|
def initialize(id=nil, type="rpc", headers=nil)
|
10
10
|
@id = id || SecureRandom.uuid
|
11
11
|
@type = type
|
12
|
-
@
|
13
|
-
|
14
|
-
headers ||= {}
|
15
|
-
@headers = @hash[:headers] = headers
|
12
|
+
@headers = headers || {}
|
16
13
|
end
|
17
14
|
|
18
15
|
def self.from_wire(body)
|
@@ -39,7 +36,12 @@ module Bixby
|
|
39
36
|
end
|
40
37
|
|
41
38
|
def to_wire
|
42
|
-
@
|
39
|
+
hash = { :type => @type,
|
40
|
+
:id => @id,
|
41
|
+
:headers => @headers,
|
42
|
+
:data => @body }
|
43
|
+
|
44
|
+
MultiJson.dump(hash)
|
43
45
|
end
|
44
46
|
|
45
47
|
# Convert object to String, useful for debugging
|
@@ -0,0 +1,65 @@
|
|
1
|
+
|
2
|
+
require 'helper'
|
3
|
+
|
4
|
+
module Bixby
|
5
|
+
module Test
|
6
|
+
module API
|
7
|
+
class TestHttpChannel < TestCase
|
8
|
+
|
9
|
+
def test_exec
|
10
|
+
url = "http://google.com/"
|
11
|
+
|
12
|
+
json_req = JsonRequest.new("exec", {"foo" => "bar"})
|
13
|
+
signed_json_req = SignedJsonRequest.new(json_req, "foo", "bar")
|
14
|
+
|
15
|
+
# setup response stub
|
16
|
+
cr = CommandResponse.new(:status => 0, :stdout => "foobar", :stderr => "")
|
17
|
+
json_res = JsonResponse.new("success", nil, cr.to_hash)
|
18
|
+
res_mock = mock()
|
19
|
+
res_mock.expects(:body).once.returns(json_res.to_wire)
|
20
|
+
HTTPI.expects(:post).with{ |r| r.kind_of?(HTTPI::Request) && r.url.to_s == url }.returns(res_mock)
|
21
|
+
|
22
|
+
chan = HttpChannel.new(url)
|
23
|
+
res = chan.execute(signed_json_req)
|
24
|
+
|
25
|
+
# req should have been modified
|
26
|
+
assert_includes signed_json_req.headers, "Content-Type"
|
27
|
+
assert_equal "application/json", signed_json_req.headers["Content-Type"]
|
28
|
+
|
29
|
+
assert res
|
30
|
+
assert_kind_of JsonResponse, res
|
31
|
+
assert res.success?
|
32
|
+
|
33
|
+
cr = CommandResponse.from_json_response(res)
|
34
|
+
assert cr
|
35
|
+
assert_equal 0, cr.status
|
36
|
+
assert_equal "foobar", cr.stdout
|
37
|
+
assert_equal "", cr.stderr
|
38
|
+
end
|
39
|
+
|
40
|
+
def test_exec_download
|
41
|
+
url = "http://google.com/"
|
42
|
+
|
43
|
+
json_req = JsonRequest.new("exec", {"foo" => "bar"})
|
44
|
+
signed_json_req = SignedJsonRequest.new(json_req, "foo", "bar")
|
45
|
+
|
46
|
+
# setup response stub
|
47
|
+
HTTPI.expects(:post).with{ |r| r.kind_of?(HTTPI::Request) && r.url.to_s == url }
|
48
|
+
|
49
|
+
chan = HttpChannel.new(url)
|
50
|
+
res = chan.execute_download(signed_json_req) do
|
51
|
+
end
|
52
|
+
|
53
|
+
# req should have been modified
|
54
|
+
assert_includes signed_json_req.headers, "Content-Type"
|
55
|
+
assert_equal "application/json", signed_json_req.headers["Content-Type"]
|
56
|
+
|
57
|
+
assert res
|
58
|
+
assert_kind_of JsonResponse, res
|
59
|
+
assert res.success?
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
data/test/base.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
|
2
|
+
module Bixby
|
3
|
+
module Test
|
4
|
+
class TestCase < MiniTest::Unit::TestCase
|
5
|
+
|
6
|
+
def setup
|
7
|
+
ENV["BIXBY_HOME"] = File.join(File.expand_path(File.dirname(__FILE__)), "support")
|
8
|
+
end
|
9
|
+
|
10
|
+
def teardown
|
11
|
+
EM.stop_event_loop if EM.reactor_running?
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -1,10 +1,11 @@
|
|
1
1
|
|
2
2
|
require 'helper'
|
3
|
+
require 'mixlib/shellout'
|
3
4
|
|
4
5
|
module Bixby
|
5
6
|
module Test
|
6
7
|
|
7
|
-
class TestCommandResponse <
|
8
|
+
class TestCommandResponse < TestCase
|
8
9
|
|
9
10
|
def test_from_json_response
|
10
11
|
res = JsonResponse.new("fail", "unknown")
|
@@ -30,6 +31,36 @@ class TestCommandResponse < MiniTest::Unit::TestCase
|
|
30
31
|
assert_nil cr.stderr
|
31
32
|
end
|
32
33
|
|
34
|
+
def test_to_json_response
|
35
|
+
cr = CommandResponse.new(:status => 50, :stdout => "foobar", :stderr => "baz")
|
36
|
+
js = cr.to_json_response
|
37
|
+
|
38
|
+
assert js
|
39
|
+
assert_kind_of JsonResponse, js
|
40
|
+
|
41
|
+
refute js.success?
|
42
|
+
assert js.fail?
|
43
|
+
|
44
|
+
assert_nil js.message
|
45
|
+
assert js.data
|
46
|
+
|
47
|
+
assert_equal 50, js.data[:status]
|
48
|
+
assert_equal "foobar", js.data[:stdout]
|
49
|
+
assert_equal "baz", js.data[:stderr]
|
50
|
+
end
|
51
|
+
|
52
|
+
def test_from_shellout
|
53
|
+
cmd = Mixlib::ShellOut.new("uname")
|
54
|
+
cmd.run_command
|
55
|
+
|
56
|
+
cr = CommandResponse.new(cmd)
|
57
|
+
assert cr
|
58
|
+
|
59
|
+
assert_equal 0, cr.status
|
60
|
+
assert cr.stdout =~ /^Darwin|Linux$/
|
61
|
+
assert_empty cr.stderr
|
62
|
+
end
|
63
|
+
|
33
64
|
def test_status
|
34
65
|
cr = CommandResponse.new
|
35
66
|
cr.status = 0
|
data/test/command_spec_test.rb
CHANGED
@@ -5,10 +5,10 @@ require 'helper'
|
|
5
5
|
module Bixby
|
6
6
|
module Test
|
7
7
|
|
8
|
-
class TestCommandSpec <
|
8
|
+
class TestCommandSpec < TestCase
|
9
9
|
|
10
10
|
def setup
|
11
|
-
|
11
|
+
super
|
12
12
|
h = { :repo => "vendor", :bundle => "test_bundle", 'command' => "echo", :foobar => "baz" }
|
13
13
|
@c = CommandSpec.new(h)
|
14
14
|
@expected_digest = "2bb6900420c87d5a7cbd8acc9dd1978593670f4e31bfa9218bb9c7c31d4472dd"
|
data/test/helper.rb
CHANGED
@@ -29,6 +29,10 @@ $LOAD_PATH.unshift(File.dirname(__FILE__))
|
|
29
29
|
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
30
30
|
require 'bixby-common'
|
31
31
|
|
32
|
+
require "base"
|
33
|
+
require "test_handler"
|
34
|
+
require "side_effect"
|
35
|
+
|
32
36
|
Dir.glob(File.dirname(__FILE__) + "/../lib/**/*.rb").each{ |f| require f }
|
33
37
|
|
34
38
|
MiniTest::Unit.autorun
|
data/test/side_effect.rb
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
|
2
|
+
require 'helper'
|
3
|
+
|
4
|
+
module Bixby
|
5
|
+
module Test
|
6
|
+
|
7
|
+
class TestCryptoUtil < TestCase
|
8
|
+
|
9
|
+
def test_crypto_cycle
|
10
|
+
|
11
|
+
key1 = CryptoUtil.generate_keypair
|
12
|
+
key2 = CryptoUtil.generate_keypair
|
13
|
+
|
14
|
+
data = {"foo" => "bar"}
|
15
|
+
uuid = "123456"
|
16
|
+
|
17
|
+
encrypted = CryptoUtil.encrypt(MultiJson.dump(data), uuid, key1, key2)
|
18
|
+
assert encrypted
|
19
|
+
encrypted_io = StringIO.new(encrypted)
|
20
|
+
assert_equal uuid, encrypted_io.readline.strip
|
21
|
+
|
22
|
+
decrypted = CryptoUtil.decrypt(encrypted_io, key1, key2)
|
23
|
+
assert decrypted
|
24
|
+
data_out = MultiJson.load(decrypted)
|
25
|
+
assert data_out
|
26
|
+
assert_kind_of Hash, data_out
|
27
|
+
assert_equal "bar", data_out["foo"]
|
28
|
+
end
|
29
|
+
|
30
|
+
|
31
|
+
end # TestCryptoUtil
|
32
|
+
|
33
|
+
end # Test
|
34
|
+
end # Bixby
|
data/test/util/log_test.rb
CHANGED
@@ -4,7 +4,7 @@ require 'helper'
|
|
4
4
|
module Bixby
|
5
5
|
module Test
|
6
6
|
|
7
|
-
class TestLog <
|
7
|
+
class TestLog < TestCase
|
8
8
|
|
9
9
|
def test_setup_logger
|
10
10
|
ENV["BIXBY_DEBUG"] = "1"
|
@@ -20,6 +20,29 @@ class TestLog < MiniTest::Unit::TestCase
|
|
20
20
|
assert_equal 1, Logging::Logger.root.level # info
|
21
21
|
end
|
22
22
|
|
23
|
+
def test_filtering_layout
|
24
|
+
|
25
|
+
filter = Bixby::Log::FilteringLayout.new
|
26
|
+
|
27
|
+
f = "foo"
|
28
|
+
assert_equal "foo", filter.format_obj(f)
|
29
|
+
assert filter.format_obj(nil) =~ /NilClass/
|
30
|
+
assert filter.format_obj(3) =~ /Fixnum.*3/
|
31
|
+
|
32
|
+
begin
|
33
|
+
raise "foo"
|
34
|
+
rescue => ex
|
35
|
+
assert filter.format_obj(ex) =~ /turn/
|
36
|
+
|
37
|
+
# filter out all turn lines
|
38
|
+
filter.set_filter do |ex|
|
39
|
+
ex.backtrace.reject{ |s| s =~ /turn/ }
|
40
|
+
end
|
41
|
+
refute filter.format_obj(ex) =~ /turn/
|
42
|
+
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
23
46
|
end # TestLog
|
24
47
|
|
25
48
|
end # Test
|
@@ -0,0 +1,100 @@
|
|
1
|
+
|
2
|
+
require 'helper'
|
3
|
+
|
4
|
+
module Bixby
|
5
|
+
|
6
|
+
|
7
|
+
module WebSocket
|
8
|
+
class APIChannel
|
9
|
+
def responses
|
10
|
+
@responses
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
|
16
|
+
module Test
|
17
|
+
module WebSocket
|
18
|
+
class TestAPIChannel < TestCase
|
19
|
+
|
20
|
+
attr_reader :api_chan, :ws
|
21
|
+
|
22
|
+
def setup
|
23
|
+
@em_thread = Thread.new { EM.run{} }
|
24
|
+
@ws = mock()
|
25
|
+
@api_chan = Bixby::WebSocket::APIChannel.new(ws, TestHandler)
|
26
|
+
end
|
27
|
+
|
28
|
+
def test_open
|
29
|
+
refute api_chan.connected?
|
30
|
+
api_chan.open(nil)
|
31
|
+
assert api_chan.connected?
|
32
|
+
end
|
33
|
+
|
34
|
+
|
35
|
+
def test_exec
|
36
|
+
# test executing a request on the channel
|
37
|
+
json_req = JsonRequest.new("exec", {:foo => "bar"})
|
38
|
+
ws.expects(:send).once().add_side_effect(SideEffect.new{ api_chan.responses.values.first.response = "hi" })
|
39
|
+
assert_equal "hi", api_chan.execute(json_req)
|
40
|
+
end
|
41
|
+
|
42
|
+
def test_message_request
|
43
|
+
# test receiving a request on the channel
|
44
|
+
json_req = JsonRequest.new("exec", {"foo" => "bar"})
|
45
|
+
signed_json_req = SignedJsonRequest.new(json_req, "foo", "bar")
|
46
|
+
req = Bixby::WebSocket::Request.new(signed_json_req)
|
47
|
+
|
48
|
+
cr = CommandResponse.new(:status => 0, :stdout => "foobar", :stderr => "")
|
49
|
+
json_res = JsonResponse.new("success", nil, cr.to_hash)
|
50
|
+
|
51
|
+
event = mock()
|
52
|
+
event.expects(:data).once.returns(req.to_wire)
|
53
|
+
TestHandler.any_instance.expects(:handle).with{ |r| r == json_req }.returns(json_res)
|
54
|
+
ws.expects(:send).once.with { |str|
|
55
|
+
res = Bixby::WebSocket::Message.from_wire(str)
|
56
|
+
!res.nil? && res.json_response.to_wire == json_res.to_wire
|
57
|
+
}
|
58
|
+
api_chan.message(event)
|
59
|
+
end
|
60
|
+
|
61
|
+
def test_message_response
|
62
|
+
# test receiving a response on the channel
|
63
|
+
cr = CommandResponse.new(:status => 0, :stdout => "foobar", :stderr => "")
|
64
|
+
json_res = JsonResponse.new("success", nil, cr.to_hash)
|
65
|
+
res = Bixby::WebSocket::Response.new(json_res, "1234")
|
66
|
+
|
67
|
+
event = mock()
|
68
|
+
event.expects(:data).once.returns(res.to_wire)
|
69
|
+
api_chan.responses["1234"] = Bixby::WebSocket::AsyncResponse.new("1234")
|
70
|
+
api_chan.message(event)
|
71
|
+
ret = api_chan.fetch_response("1234")
|
72
|
+
assert ret
|
73
|
+
assert_kind_of JsonResponse, ret
|
74
|
+
assert_equal json_res.to_wire, ret.to_wire
|
75
|
+
end
|
76
|
+
|
77
|
+
def test_message_connect
|
78
|
+
# test receiving a connect request on the channel
|
79
|
+
json_req = JsonRequest.new("", {})
|
80
|
+
signed_json_req = SignedJsonRequest.new(json_req, "foo", "bar")
|
81
|
+
req = Bixby::WebSocket::Request.new(signed_json_req, nil, "connect")
|
82
|
+
|
83
|
+
event = mock()
|
84
|
+
event.expects(:data).once.returns(req.to_wire)
|
85
|
+
TestHandler.any_instance.expects(:connect).with(json_req, api_chan)
|
86
|
+
api_chan.message(event)
|
87
|
+
end
|
88
|
+
|
89
|
+
def test_close
|
90
|
+
# close
|
91
|
+
api_chan.open(nil)
|
92
|
+
TestHandler.any_instance.expects(:disconnect).with(api_chan).once()
|
93
|
+
api_chan.close(nil)
|
94
|
+
|
95
|
+
end
|
96
|
+
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
|
2
|
+
require 'helper'
|
3
|
+
|
4
|
+
module Bixby
|
5
|
+
module Test
|
6
|
+
module WebSocket
|
7
|
+
class TestAsyncResponse < TestCase
|
8
|
+
|
9
|
+
def test_block
|
10
|
+
|
11
|
+
sync_response = nil
|
12
|
+
cb_response = nil
|
13
|
+
|
14
|
+
res = Bixby::WebSocket::AsyncResponse.new("1234") do |r|
|
15
|
+
cb_response = r
|
16
|
+
end
|
17
|
+
|
18
|
+
assert res
|
19
|
+
assert_equal "1234", res.id
|
20
|
+
refute res.completed?
|
21
|
+
|
22
|
+
# start a thread waiting on the response to be writ ten
|
23
|
+
t = Thread.new {
|
24
|
+
sync_response = res.response
|
25
|
+
}
|
26
|
+
assert t.alive?
|
27
|
+
|
28
|
+
# small sleep here, otherwise execution will continue too quickly, before the thread starts
|
29
|
+
assert_nil t.join(0.001)
|
30
|
+
|
31
|
+
# now write it, thread should complete & callback will fire
|
32
|
+
res.response = "hi"
|
33
|
+
|
34
|
+
t.join
|
35
|
+
refute t.alive?
|
36
|
+
assert_equal "hi", cb_response
|
37
|
+
assert_equal "hi", sync_response
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
|
2
|
+
require 'helper'
|
3
|
+
|
4
|
+
module Bixby
|
5
|
+
module Test
|
6
|
+
module WebSocket
|
7
|
+
class TestRequest < TestCase
|
8
|
+
|
9
|
+
def test_init
|
10
|
+
json_req = JsonRequest.new("exec", {:foo => "bar"})
|
11
|
+
req = Bixby::WebSocket::Request.new(json_req)
|
12
|
+
|
13
|
+
assert req
|
14
|
+
assert req.headers
|
15
|
+
assert_empty req.headers
|
16
|
+
|
17
|
+
h = MultiJson.load(req.to_wire)
|
18
|
+
test_common_props(h)
|
19
|
+
assert_empty h["headers"]
|
20
|
+
end
|
21
|
+
|
22
|
+
def test_signed
|
23
|
+
json_req = JsonRequest.new("exec", {:foo => "bar"})
|
24
|
+
signed_json_req = SignedJsonRequest.new(json_req, "foo", "bar")
|
25
|
+
req = Bixby::WebSocket::Request.new(signed_json_req)
|
26
|
+
|
27
|
+
assert req
|
28
|
+
h = MultiJson.load(req.to_wire)
|
29
|
+
test_common_props(h)
|
30
|
+
refute_empty h["headers"]
|
31
|
+
|
32
|
+
assert_includes h["headers"], "Content-MD5"
|
33
|
+
assert_includes h["headers"], "Date"
|
34
|
+
assert_includes h["headers"], "Authorization"
|
35
|
+
assert h["headers"]["Authorization"] =~ /^APIAuth foo:/
|
36
|
+
end
|
37
|
+
|
38
|
+
def test_json_req
|
39
|
+
json_req = JsonRequest.new("exec", {"foo" => "bar"})
|
40
|
+
req = Bixby::WebSocket::Request.new(json_req)
|
41
|
+
|
42
|
+
assert req.json_request
|
43
|
+
assert_equal json_req, req.json_request
|
44
|
+
assert_equal json_req, Bixby::WebSocket::Message.from_wire(req.to_wire).json_request
|
45
|
+
end
|
46
|
+
|
47
|
+
|
48
|
+
private
|
49
|
+
|
50
|
+
def test_common_props(h)
|
51
|
+
assert h
|
52
|
+
assert_equal "rpc", h["type"]
|
53
|
+
assert h["id"]
|
54
|
+
|
55
|
+
d = MultiJson.load(h["data"])
|
56
|
+
assert_equal "exec", d["operation"]
|
57
|
+
refute_empty d["params"]
|
58
|
+
assert_equal "bar", d["params"]["foo"]
|
59
|
+
h
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
|
2
|
+
require 'helper'
|
3
|
+
|
4
|
+
module Bixby
|
5
|
+
module Test
|
6
|
+
module WebSocket
|
7
|
+
class TestResponse < TestCase
|
8
|
+
|
9
|
+
def test_init
|
10
|
+
cr = CommandResponse.new(:status => 0, :stdout => "foobar", :stderr => "")
|
11
|
+
json_res = JsonResponse.new("success", nil, cr.to_hash)
|
12
|
+
res = Bixby::WebSocket::Response.new(json_res, "1234")
|
13
|
+
|
14
|
+
assert res
|
15
|
+
assert res.headers
|
16
|
+
assert_empty res.headers
|
17
|
+
|
18
|
+
h = MultiJson.load(res.to_wire)
|
19
|
+
assert h
|
20
|
+
assert_equal "rpc_result", h["type"]
|
21
|
+
assert_equal "1234", h["id"]
|
22
|
+
|
23
|
+
d = MultiJson.load(h["data"])
|
24
|
+
assert_equal "success", d["status"]
|
25
|
+
refute d["message"]
|
26
|
+
refute d["code"]
|
27
|
+
assert_equal 0, d["data"]["status"]
|
28
|
+
assert_equal "foobar", d["data"]["stdout"]
|
29
|
+
assert_equal "", d["data"]["stderr"]
|
30
|
+
end
|
31
|
+
|
32
|
+
def test_json_res
|
33
|
+
cr = CommandResponse.new("status" => 0, "stdout" => "foobar", "stderr" => "")
|
34
|
+
json_res = JsonResponse.new("success", nil, cr.to_hash)
|
35
|
+
res = Bixby::WebSocket::Response.new(json_res, "1234")
|
36
|
+
|
37
|
+
assert res.json_response
|
38
|
+
assert_equal json_res.to_wire, res.json_response.to_wire
|
39
|
+
assert_equal json_res.to_wire, Bixby::WebSocket::Message.from_wire(res.to_wire).json_response.to_wire
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: bixby-common
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.4.
|
4
|
+
version: 0.4.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Chetan Sarva
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2013-09-
|
11
|
+
date: 2013-09-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: faye-websocket
|
@@ -80,6 +80,20 @@ dependencies:
|
|
80
80
|
- - '>='
|
81
81
|
- !ruby/object:Gem::Version
|
82
82
|
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: mixlib-shellout
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - '>='
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - '>='
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
83
97
|
- !ruby/object:Gem::Dependency
|
84
98
|
name: yard
|
85
99
|
requirement: !ruby/object:Gem::Requirement
|
@@ -399,22 +413,30 @@ files:
|
|
399
413
|
- lib/bixby-common/util/log/logger.rb
|
400
414
|
- lib/bixby-common/websocket/api_channel.rb
|
401
415
|
- lib/bixby-common/websocket/async_response.rb
|
402
|
-
- lib/bixby-common/websocket/client.rb
|
403
416
|
- lib/bixby-common/websocket/message.rb
|
404
417
|
- lib/bixby-common/websocket/request.rb
|
405
418
|
- lib/bixby-common/websocket/response.rb
|
419
|
+
- test/api/http_channel_test.rb
|
420
|
+
- test/base.rb
|
406
421
|
- test/bixby_common_test.rb
|
407
422
|
- test/command_response_test.rb
|
408
423
|
- test/command_spec_test.rb
|
409
424
|
- test/helper.rb
|
425
|
+
- test/side_effect.rb
|
410
426
|
- test/support/repo/vendor/test_bundle/bin/cat
|
411
427
|
- test/support/repo/vendor/test_bundle/bin/cat.json
|
412
428
|
- test/support/repo/vendor/test_bundle/bin/echo
|
413
429
|
- test/support/repo/vendor/test_bundle/digest
|
414
430
|
- test/support/repo/vendor/test_bundle/manifest.json
|
431
|
+
- test/test_handler.rb
|
432
|
+
- test/util/crypto_util_test.rb
|
415
433
|
- test/util/http_client_test.rb
|
416
434
|
- test/util/jsonify_test.rb
|
417
435
|
- test/util/log_test.rb
|
436
|
+
- test/websocket/api_channel_test.rb
|
437
|
+
- test/websocket/async_response_test.rb
|
438
|
+
- test/websocket/request_test.rb
|
439
|
+
- test/websocket/response_test.rb
|
418
440
|
homepage: http://github.com/chetan/bixby-common
|
419
441
|
licenses:
|
420
442
|
- MIT
|
@@ -435,7 +457,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
435
457
|
version: '0'
|
436
458
|
requirements: []
|
437
459
|
rubyforge_project:
|
438
|
-
rubygems_version: 2.0
|
460
|
+
rubygems_version: 2.1.0
|
439
461
|
signing_key:
|
440
462
|
specification_version: 4
|
441
463
|
summary: Bixby Common
|
@@ -1,125 +0,0 @@
|
|
1
|
-
|
2
|
-
require 'faye/websocket'
|
3
|
-
require 'eventmachine'
|
4
|
-
|
5
|
-
module Bixby
|
6
|
-
module WebSocket
|
7
|
-
|
8
|
-
# WebSocket Client
|
9
|
-
class Client
|
10
|
-
|
11
|
-
include Bixby::Log
|
12
|
-
|
13
|
-
attr_reader :ws, :api
|
14
|
-
|
15
|
-
def initialize(url, handler)
|
16
|
-
@url = url
|
17
|
-
@handler = handler
|
18
|
-
@tries = 0
|
19
|
-
@exiting = false
|
20
|
-
end
|
21
|
-
|
22
|
-
# Start the Client thread
|
23
|
-
#
|
24
|
-
# NOTE: This call never returns!
|
25
|
-
def start
|
26
|
-
|
27
|
-
@exiting = false
|
28
|
-
|
29
|
-
Kernel.trap("EXIT") do
|
30
|
-
@exiting = true
|
31
|
-
end
|
32
|
-
|
33
|
-
logger.debug "connecting to #{@url}"
|
34
|
-
EM.run {
|
35
|
-
connect()
|
36
|
-
}
|
37
|
-
end
|
38
|
-
|
39
|
-
def stop
|
40
|
-
@exiting = true
|
41
|
-
EM.stop_event_loop
|
42
|
-
end
|
43
|
-
|
44
|
-
|
45
|
-
private
|
46
|
-
|
47
|
-
# Connect to the WebSocket endpoint given by @url. Will attempt to keep
|
48
|
-
# the connection open forever, reconnecting as needed.
|
49
|
-
def connect
|
50
|
-
|
51
|
-
@ws = Faye::WebSocket::Client.new(@url, nil, :ping => 60)
|
52
|
-
@api = Bixby::WebSocket::APIChannel.new(@ws, @handler)
|
53
|
-
|
54
|
-
ws.on :open do |e|
|
55
|
-
begin
|
56
|
-
logger.info "connected to manager at #{@url}"
|
57
|
-
api.open(e)
|
58
|
-
@tries = 0
|
59
|
-
|
60
|
-
# send a connection request
|
61
|
-
id = SecureRandom.uuid
|
62
|
-
json_req = JsonRequest.new("", "")
|
63
|
-
signed_req = SignedJsonRequest.new(json_req, Bixby.agent.access_key, Bixby.agent.secret_key)
|
64
|
-
connect_req = Request.new(signed_req, id, "connect")
|
65
|
-
EM.next_tick {
|
66
|
-
ws.send(connect_req.to_wire)
|
67
|
-
}
|
68
|
-
|
69
|
-
rescue Exception => ex
|
70
|
-
logger.error ex
|
71
|
-
end
|
72
|
-
end
|
73
|
-
|
74
|
-
ws.on :message do |e|
|
75
|
-
begin
|
76
|
-
api.message(e)
|
77
|
-
rescue Exception => ex
|
78
|
-
logger.error ex
|
79
|
-
end
|
80
|
-
end
|
81
|
-
|
82
|
-
ws.on :close do |e|
|
83
|
-
begin
|
84
|
-
if api.connected? then
|
85
|
-
logger.info "lost connection to manager"
|
86
|
-
else
|
87
|
-
logger.debug "failed to connect"
|
88
|
-
end
|
89
|
-
api.close(e)
|
90
|
-
backoff()
|
91
|
-
connect()
|
92
|
-
rescue Exception => ex
|
93
|
-
logger.error ex
|
94
|
-
end
|
95
|
-
end
|
96
|
-
end
|
97
|
-
|
98
|
-
# Delay reconnection by a slowly increasing interval
|
99
|
-
def backoff
|
100
|
-
|
101
|
-
if @exiting or not EM.reactor_running? then
|
102
|
-
# shutting down, don't try to reconnect
|
103
|
-
return
|
104
|
-
end
|
105
|
-
|
106
|
-
@tries += 1
|
107
|
-
if @tries == 1 then
|
108
|
-
logger.debug "retrying immediately"
|
109
|
-
elsif @tries == 2 then
|
110
|
-
logger.debug "retrying every 1 sec"
|
111
|
-
sleep 1
|
112
|
-
elsif @tries <= 30 then
|
113
|
-
sleep 1
|
114
|
-
elsif @tries == 31 then
|
115
|
-
logger.debug "retrying every 5 sec"
|
116
|
-
sleep 5
|
117
|
-
else
|
118
|
-
sleep 5
|
119
|
-
end
|
120
|
-
end
|
121
|
-
|
122
|
-
end
|
123
|
-
|
124
|
-
end
|
125
|
-
end
|