specter 0.1.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 +17 -0
- data/.rspec +2 -0
- data/.travis.yml +3 -0
- data/CHANGELOG.md +6 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +37 -0
- data/Rakefile +27 -0
- data/bin/specter +5 -0
- data/lib/specter.rb +10 -0
- data/lib/specter/cli.rb +94 -0
- data/lib/specter/env.rb +22 -0
- data/lib/specter/fixtures/coin.json +21 -0
- data/lib/specter/fixtures/config.json +28 -0
- data/lib/specter/fixtures/devdetails.json +41 -0
- data/lib/specter/fixtures/devs.json +113 -0
- data/lib/specter/fixtures/gpu.json +47 -0
- data/lib/specter/fixtures/gpucount.json +17 -0
- data/lib/specter/fixtures/notify.json +68 -0
- data/lib/specter/fixtures/pools.json +110 -0
- data/lib/specter/fixtures/stats.json +161 -0
- data/lib/specter/fixtures/summary.json +43 -0
- data/lib/specter/fixtures/version.json +18 -0
- data/lib/specter/middleware.rb +22 -0
- data/lib/specter/middleware/base.rb +14 -0
- data/lib/specter/middleware/fixture.rb +32 -0
- data/lib/specter/middleware/missing.rb +25 -0
- data/lib/specter/middleware/proxy.rb +25 -0
- data/lib/specter/request.rb +40 -0
- data/lib/specter/server.rb +77 -0
- data/lib/specter/version.rb +3 -0
- data/specter.gemspec +28 -0
- metadata +165 -0
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'middleware'
|
2
|
+
|
3
|
+
require 'specter/middleware/base'
|
4
|
+
require 'specter/middleware/fixture'
|
5
|
+
require 'specter/middleware/missing'
|
6
|
+
require 'specter/middleware/proxy'
|
7
|
+
|
8
|
+
module Specter
|
9
|
+
module Middleware
|
10
|
+
|
11
|
+
def self.new(server)
|
12
|
+
::Middleware::Builder.new do
|
13
|
+
use Fixture, server
|
14
|
+
use Proxy, server if server.options[:proxy]
|
15
|
+
|
16
|
+
yield if block_given?
|
17
|
+
|
18
|
+
use Missing, server
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end # Middleware
|
22
|
+
end # Specter
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'pathname'
|
2
|
+
|
3
|
+
module Specter
|
4
|
+
module Middleware
|
5
|
+
class Fixture < Base
|
6
|
+
|
7
|
+
ROOT = Pathname.new(File.expand_path('../../fixtures', __FILE__))
|
8
|
+
|
9
|
+
def call(env)
|
10
|
+
data = load_fixture(env)
|
11
|
+
|
12
|
+
if data
|
13
|
+
env.merge!(data)
|
14
|
+
else
|
15
|
+
@app.call(env)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def load_fixture(env)
|
22
|
+
fixture = ROOT.join("#{env.command}.json")
|
23
|
+
return unless fixture.exist?
|
24
|
+
logger.debug "loading fixture for #{env.command.inspect}"
|
25
|
+
JSON.load(File.read(fixture))
|
26
|
+
rescue JSON::ParserError
|
27
|
+
logger.debug "failed to parse fixture for #{env.command.inspect}"
|
28
|
+
nil
|
29
|
+
end
|
30
|
+
end # Fixture
|
31
|
+
end # Middleware
|
32
|
+
end # Specter
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Specter
|
2
|
+
module Middleware
|
3
|
+
class Missing < Base
|
4
|
+
|
5
|
+
def call(env)
|
6
|
+
@app.call(env)
|
7
|
+
|
8
|
+
if env.empty?
|
9
|
+
env.merge!(
|
10
|
+
'STATUS' => [
|
11
|
+
{
|
12
|
+
'STATUS' => 'E',
|
13
|
+
'When' => Time.now.to_i,
|
14
|
+
'Code' => 14,
|
15
|
+
'Msg' => 'Invalid command',
|
16
|
+
'Description' => "specter #{VERSION}"
|
17
|
+
}
|
18
|
+
],
|
19
|
+
'id' => 1
|
20
|
+
)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end # Missing
|
24
|
+
end # Middleware
|
25
|
+
end # Specter
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'expedition'
|
2
|
+
|
3
|
+
module Specter
|
4
|
+
module Middleware
|
5
|
+
class Proxy < Base
|
6
|
+
|
7
|
+
def initialize(app, server)
|
8
|
+
super
|
9
|
+
@miner = Expedition::Client.new(*options[:proxy])
|
10
|
+
end
|
11
|
+
|
12
|
+
def call(env)
|
13
|
+
env.merge!(proxy_command(env))
|
14
|
+
@app.call(env)
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def proxy_command(env)
|
20
|
+
logger.debug "proxying #{env.command}, #{env.args.inspect}"
|
21
|
+
@miner.send(env.command, *env.args).raw
|
22
|
+
end
|
23
|
+
end # Proxy
|
24
|
+
end # Middleware
|
25
|
+
end # Specter
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'json'
|
2
|
+
|
3
|
+
module Specter
|
4
|
+
class Request
|
5
|
+
|
6
|
+
def self.parse(raw)
|
7
|
+
begin
|
8
|
+
message = JSON.parse(raw)
|
9
|
+
rescue JSON::ParserError
|
10
|
+
raise RequestError, $!
|
11
|
+
end
|
12
|
+
|
13
|
+
command = message['command']
|
14
|
+
args = message['parameter'].to_s.split(',')
|
15
|
+
|
16
|
+
new(command, args)
|
17
|
+
end
|
18
|
+
|
19
|
+
attr_reader :command
|
20
|
+
|
21
|
+
attr_reader :args
|
22
|
+
|
23
|
+
def initialize(command, args)
|
24
|
+
if command.nil? || command.empty?
|
25
|
+
raise RequestError, 'command not supplied'
|
26
|
+
end
|
27
|
+
|
28
|
+
@command = command.to_sym
|
29
|
+
@args = args
|
30
|
+
end
|
31
|
+
|
32
|
+
def execute(client)
|
33
|
+
client.send(command, *args)
|
34
|
+
end
|
35
|
+
|
36
|
+
def inspect
|
37
|
+
"#<#{self.class} command:#{command}, args:#{args.inspect}>"
|
38
|
+
end
|
39
|
+
end # Request
|
40
|
+
end # Specer
|
@@ -0,0 +1,77 @@
|
|
1
|
+
require 'socket'
|
2
|
+
require 'logger'
|
3
|
+
|
4
|
+
require 'specter/middleware'
|
5
|
+
require 'specter/request'
|
6
|
+
require 'specter/env'
|
7
|
+
|
8
|
+
module Specter
|
9
|
+
class Server
|
10
|
+
|
11
|
+
attr_reader :cli
|
12
|
+
|
13
|
+
attr_reader :options
|
14
|
+
|
15
|
+
attr_reader :logger
|
16
|
+
|
17
|
+
attr_reader :socket
|
18
|
+
|
19
|
+
attr_reader :stack
|
20
|
+
|
21
|
+
def initialize(cli)
|
22
|
+
@cli = cli
|
23
|
+
@options = cli.options
|
24
|
+
|
25
|
+
@logger = Logger.new(STDOUT)
|
26
|
+
@socket = TCPServer.new(options[:host], options[:port])
|
27
|
+
@stack = Middleware.new(self)
|
28
|
+
end
|
29
|
+
|
30
|
+
def run
|
31
|
+
BasicSocket.do_not_reverse_lookup = true
|
32
|
+
return @thread = Thread.new { handle_requests }
|
33
|
+
end
|
34
|
+
|
35
|
+
def handle_requests
|
36
|
+
loop do
|
37
|
+
client = socket.accept
|
38
|
+
process_request(client)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def process_request(client)
|
43
|
+
Timeout.timeout(5) do
|
44
|
+
req = Request.parse(client.gets)
|
45
|
+
env = Env.new(client, req)
|
46
|
+
log_request(env)
|
47
|
+
@stack.call(env)
|
48
|
+
client.write env.to_str
|
49
|
+
end
|
50
|
+
rescue Timeout::Error
|
51
|
+
log_timeout(client)
|
52
|
+
rescue Object => e
|
53
|
+
log_error(client, e)
|
54
|
+
ensure
|
55
|
+
client.close rescue nil
|
56
|
+
end
|
57
|
+
|
58
|
+
def log_timeout(client)
|
59
|
+
logger.warn "%s - timeout" % [
|
60
|
+
client.remote_address.ip_address
|
61
|
+
]
|
62
|
+
end
|
63
|
+
|
64
|
+
def log_error(client, e)
|
65
|
+
logger.error "%s - %s: %s\n%s" % [
|
66
|
+
client.remote_address.ip_address, e.class, e.message,
|
67
|
+
e.backtrace.join("\n")
|
68
|
+
]
|
69
|
+
end
|
70
|
+
|
71
|
+
def log_request(env)
|
72
|
+
logger.info "%s - %s - %s" % [
|
73
|
+
env.client.remote_address.ip_address, env.request.command, env.request.args.inspect
|
74
|
+
]
|
75
|
+
end
|
76
|
+
end # Server
|
77
|
+
end # Specter
|
data/specter.gemspec
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'specter/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = 'specter'
|
8
|
+
spec.version = Specter::VERSION
|
9
|
+
spec.authors = ['Gabe Evans']
|
10
|
+
spec.email = ['gabe@ga.be']
|
11
|
+
spec.summary = %q{Specter stubs a subset of the cgminer client protocol. It allows you to test your programs against a dummy server when writing programs that interact with cgminer and cgminer-compatibile software.}
|
12
|
+
spec.description = spec.summary
|
13
|
+
spec.homepage = 'https://github.com/gevans/specter'
|
14
|
+
spec.license = 'MIT'
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0")
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = %w(lib)
|
20
|
+
|
21
|
+
spec.add_dependency 'expedition'
|
22
|
+
spec.add_dependency 'middleware'
|
23
|
+
|
24
|
+
spec.add_development_dependency 'bundler', '~> 1.5'
|
25
|
+
spec.add_development_dependency 'rake'
|
26
|
+
spec.add_development_dependency 'rspec'
|
27
|
+
spec.add_development_dependency 'pry'
|
28
|
+
end
|
metadata
ADDED
@@ -0,0 +1,165 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: specter
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Gabe Evans
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-04-09 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: expedition
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: middleware
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: bundler
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '1.5'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '1.5'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rake
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rspec
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: pry
|
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'
|
97
|
+
description: Specter stubs a subset of the cgminer client protocol. It allows you
|
98
|
+
to test your programs against a dummy server when writing programs that interact
|
99
|
+
with cgminer and cgminer-compatibile software.
|
100
|
+
email:
|
101
|
+
- gabe@ga.be
|
102
|
+
executables:
|
103
|
+
- specter
|
104
|
+
extensions: []
|
105
|
+
extra_rdoc_files: []
|
106
|
+
files:
|
107
|
+
- ".gitignore"
|
108
|
+
- ".rspec"
|
109
|
+
- ".travis.yml"
|
110
|
+
- CHANGELOG.md
|
111
|
+
- Gemfile
|
112
|
+
- LICENSE.txt
|
113
|
+
- README.md
|
114
|
+
- Rakefile
|
115
|
+
- bin/specter
|
116
|
+
- lib/specter.rb
|
117
|
+
- lib/specter/cli.rb
|
118
|
+
- lib/specter/env.rb
|
119
|
+
- lib/specter/fixtures/coin.json
|
120
|
+
- lib/specter/fixtures/config.json
|
121
|
+
- lib/specter/fixtures/devdetails.json
|
122
|
+
- lib/specter/fixtures/devs.json
|
123
|
+
- lib/specter/fixtures/gpu.json
|
124
|
+
- lib/specter/fixtures/gpucount.json
|
125
|
+
- lib/specter/fixtures/notify.json
|
126
|
+
- lib/specter/fixtures/pools.json
|
127
|
+
- lib/specter/fixtures/stats.json
|
128
|
+
- lib/specter/fixtures/summary.json
|
129
|
+
- lib/specter/fixtures/version.json
|
130
|
+
- lib/specter/middleware.rb
|
131
|
+
- lib/specter/middleware/base.rb
|
132
|
+
- lib/specter/middleware/fixture.rb
|
133
|
+
- lib/specter/middleware/missing.rb
|
134
|
+
- lib/specter/middleware/proxy.rb
|
135
|
+
- lib/specter/request.rb
|
136
|
+
- lib/specter/server.rb
|
137
|
+
- lib/specter/version.rb
|
138
|
+
- specter.gemspec
|
139
|
+
homepage: https://github.com/gevans/specter
|
140
|
+
licenses:
|
141
|
+
- MIT
|
142
|
+
metadata: {}
|
143
|
+
post_install_message:
|
144
|
+
rdoc_options: []
|
145
|
+
require_paths:
|
146
|
+
- lib
|
147
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
148
|
+
requirements:
|
149
|
+
- - ">="
|
150
|
+
- !ruby/object:Gem::Version
|
151
|
+
version: '0'
|
152
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
153
|
+
requirements:
|
154
|
+
- - ">="
|
155
|
+
- !ruby/object:Gem::Version
|
156
|
+
version: '0'
|
157
|
+
requirements: []
|
158
|
+
rubyforge_project:
|
159
|
+
rubygems_version: 2.2.2
|
160
|
+
signing_key:
|
161
|
+
specification_version: 4
|
162
|
+
summary: Specter stubs a subset of the cgminer client protocol. It allows you to test
|
163
|
+
your programs against a dummy server when writing programs that interact with cgminer
|
164
|
+
and cgminer-compatibile software.
|
165
|
+
test_files: []
|