holoserve 0.1.1 → 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/README.rdoc +53 -50
- data/Rakefile +7 -0
- data/bin/holoserve +4 -4
- data/lib/holoserve/configuration.rb +23 -26
- data/lib/holoserve/interface/control.rb +40 -19
- data/lib/holoserve/interface/fake.rb +8 -1
- data/lib/holoserve/request/matcher.rb +2 -2
- data/lib/holoserve/runner.rb +13 -9
- data/lib/holoserve/tool/hash/key_symbolizer.rb +10 -3
- data/lib/holoserve/tool/merger.rb +51 -0
- data/lib/holoserve/tool.rb +1 -0
- data/spec/helper.rb +2 -0
- data/spec/lib/holoserve/tool/merger_spec.rb +61 -0
- metadata +24 -20
data/README.rdoc
CHANGED
@@ -7,12 +7,13 @@ run faster and be independent from other API and network problems.
|
|
7
7
|
== Concept
|
8
8
|
|
9
9
|
HoloServe runs a rack application server, that matches any incoming request to a list of request profiles defined in
|
10
|
-
the server layout. If a match is found, the defined static response is returned. The
|
11
|
-
|
12
|
-
request
|
13
|
-
|
10
|
+
the server layout. If a match is found, the defined static response is returned. The response is defined by a default
|
11
|
+
and the current server situation.
|
12
|
+
The name of the matched request/response pair is saved in a request history. If no match is found, a 404 is returned and
|
13
|
+
the request data is stored in the bucket for unhandeled requests. These informations can be used to extend the server
|
14
|
+
layout with missing request handlers.
|
14
15
|
|
15
|
-
|
16
|
+
The layout, situation, history and bucket can be accessed via control routes, which are described below.
|
16
17
|
|
17
18
|
== Installation
|
18
19
|
|
@@ -26,43 +27,40 @@ To start up an empty Holoserve instance, type...
|
|
26
27
|
|
27
28
|
holoserve
|
28
29
|
|
29
|
-
To load and
|
30
|
+
To load a server layout and define a situation during start up, use these parameters.
|
30
31
|
|
31
|
-
holoserve -
|
32
|
+
holoserve -l layouts.yml -s backend_without_users
|
32
33
|
|
33
34
|
== Control routes
|
34
35
|
|
35
36
|
If you're using Ruby, you can control Holoserve via the
|
36
37
|
{Holoserve Connector}[https://github.com/skrill/holoserve-connector] gem.
|
37
38
|
|
38
|
-
=== POST /_control/
|
39
|
+
=== POST /_control/layout.:format
|
39
40
|
|
40
|
-
It should receive a parameter named <tt>file</tt> that contains
|
41
|
-
|
41
|
+
It should receive a parameter named <tt>file</tt> that contains a file with the server layout. The format of the file
|
42
|
+
should fit the specified format. The format can be <tt>yaml</tt> or <tt>json</tt>. See
|
43
|
+
{Layout file format}[rdoc-label:Layout-file-format] below.
|
42
44
|
|
43
|
-
===
|
45
|
+
=== GET /_control/layout.:format
|
44
46
|
|
45
|
-
|
47
|
+
Returns the server layout in the requested format.
|
46
48
|
|
47
|
-
===
|
49
|
+
=== DELETE /_control/layout
|
48
50
|
|
49
|
-
|
51
|
+
Removes the server layout.
|
50
52
|
|
51
|
-
|
52
|
-
|
53
|
-
[ "one", "two" ]
|
53
|
+
=== PUT /_control/situation/:name
|
54
54
|
|
55
|
-
|
55
|
+
Sets the current situation.
|
56
56
|
|
57
|
-
|
57
|
+
=== GET /_control/situation
|
58
58
|
|
59
|
-
|
60
|
-
|
61
|
-
Returns the id of the current layout.
|
59
|
+
Returns the name of the current situation.
|
62
60
|
|
63
61
|
==== Response example
|
64
62
|
|
65
|
-
|
63
|
+
backend_without_users
|
66
64
|
|
67
65
|
=== GET /_control/bucket/requests
|
68
66
|
|
@@ -106,40 +104,42 @@ Returns a list of all names of pairs that has been triggered.
|
|
106
104
|
|
107
105
|
Removes all entries from the history.
|
108
106
|
|
109
|
-
==
|
110
|
-
|
111
|
-
The server
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
107
|
+
== Layout file format
|
108
|
+
|
109
|
+
The server layout file should have the following format.
|
110
|
+
|
111
|
+
-
|
112
|
+
name: "test_received"
|
113
|
+
request:
|
114
|
+
method: "POST"
|
115
|
+
path: "/test"
|
116
|
+
headers:
|
117
|
+
HTTP_USER_AGENT: "Ruby"
|
118
|
+
HTTP_AUTHORIZATION: "OAuth oauth_token=12345"
|
119
|
+
body:
|
120
|
+
"test=value"
|
121
|
+
parameters:
|
122
|
+
test: "value"
|
123
|
+
oauth:
|
124
|
+
oauth_token: "12345"
|
125
|
+
responses:
|
126
|
+
default:
|
129
127
|
status: 200
|
128
|
+
one:
|
130
129
|
body:
|
131
130
|
"ok"
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
131
|
+
-
|
132
|
+
request:
|
133
|
+
method: "GET"
|
134
|
+
path: "/test"
|
135
|
+
responses:
|
136
|
+
default:
|
137
137
|
status: 200
|
138
138
|
body:
|
139
139
|
"ok too"
|
140
140
|
|
141
|
-
This example would define a server layout
|
142
|
-
|
141
|
+
This example would define a server layout that has two request/response pairs. The first pair would have the name
|
142
|
+
<tt>test_received</tt> and would match a <tt>POST</tt> request to the path <tt>/test</tt>.
|
143
143
|
|
144
144
|
Notice, that the given request attributes are the _minimal_ values that have to match the incomong one. An incoming
|
145
145
|
request may has much more attributes (see bucket example above). If a request is matched, the corresponding pair name is
|
@@ -148,3 +148,6 @@ placed in the history.
|
|
148
148
|
As the sections <tt>headers</tt> and <tt>body</tt> are raw values from the request, the sections <tt>parameters</tt> and
|
149
149
|
<tt>oauth</tt> contain high-level values. The <tt>parameters</tt> hash is taken from the request body or the query and
|
150
150
|
the hash containing the OAuth values is parsed from a fitting <tt>HTTP_AUTHORIZATION</tt> header.
|
151
|
+
|
152
|
+
The response is defined in the <tt>responses</tt> section of each pair. The server will response a merge of default
|
153
|
+
response and the response defined by the current situation.
|
data/Rakefile
CHANGED
data/bin/holoserve
CHANGED
@@ -14,11 +14,11 @@ OptionParser.new do |parser|
|
|
14
14
|
parser.on("-p", "--port PORT", Integer, "The port holoserve should listen to.") do |value|
|
15
15
|
options[:port] = value
|
16
16
|
end
|
17
|
-
parser.on("-
|
18
|
-
options[:
|
17
|
+
parser.on("-l", "--layout-file FILE", "Load the specified layout file on startup.") do |value|
|
18
|
+
options[:layout_filename] = value
|
19
19
|
end
|
20
|
-
parser.on("-
|
21
|
-
options[:
|
20
|
+
parser.on("-s", "--situation SITUATION", "Sets the situation.") do |value|
|
21
|
+
options[:situation] = value
|
22
22
|
end
|
23
23
|
parser.on_tail("-h", "--help", "Shows the help message.") do
|
24
24
|
puts parser
|
@@ -2,47 +2,44 @@ require 'yaml'
|
|
2
2
|
|
3
3
|
class Holoserve::Configuration
|
4
4
|
|
5
|
+
class InvalidFormatError < StandardError; end
|
6
|
+
|
5
7
|
attr_reader :logger
|
6
8
|
|
7
|
-
attr_reader :
|
8
|
-
attr_reader :
|
9
|
+
attr_reader :layout
|
10
|
+
attr_reader :situation
|
9
11
|
|
10
12
|
def initialize(logger)
|
11
13
|
@logger = logger
|
12
14
|
end
|
13
15
|
|
14
|
-
def
|
15
|
-
@
|
16
|
-
end
|
17
|
-
|
18
|
-
def layout_id=(value)
|
19
|
-
@layout_id = value.to_sym
|
20
|
-
logger.info "made '#{value}' the current layout"
|
16
|
+
def layout=(hash_or_array)
|
17
|
+
@layout = Holoserve::Tool::Hash::KeySymbolizer.new(hash_or_array).hash
|
21
18
|
end
|
22
19
|
|
23
|
-
def
|
24
|
-
|
20
|
+
def situation=(value)
|
21
|
+
@situation = value.to_sym
|
22
|
+
logger.info "made '#{value}' the current situation"
|
25
23
|
end
|
26
24
|
|
27
|
-
def
|
28
|
-
self.
|
25
|
+
def clear_layout!
|
26
|
+
self.layout = nil
|
29
27
|
end
|
30
28
|
|
31
|
-
def
|
32
|
-
self.
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
29
|
+
def load_layout_from_yaml_file(file)
|
30
|
+
self.layout = YAML::load_file file
|
31
|
+
logger.info "loaded layouts from yaml file #{file.path}"
|
32
|
+
rescue Psych::SyntaxError => error
|
33
|
+
self.clear_layout!
|
34
|
+
raise InvalidFormatError, error.to_s
|
37
35
|
end
|
38
36
|
|
39
|
-
def
|
40
|
-
self.
|
41
|
-
logger.info "loaded layouts from file #{file.path}"
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
raise error
|
37
|
+
def load_layout_from_json_file(file)
|
38
|
+
self.layout = JSON.parse File.read(file)
|
39
|
+
logger.info "loaded layouts from json file #{file.path}"
|
40
|
+
rescue JSON::ParserError => error
|
41
|
+
self.clear_layout!
|
42
|
+
raise InvalidFormatError, error.to_s
|
46
43
|
end
|
47
44
|
|
48
45
|
end
|
@@ -4,35 +4,47 @@ require 'json'
|
|
4
4
|
|
5
5
|
class Holoserve::Interface::Control < Sinatra::Base
|
6
6
|
|
7
|
-
|
7
|
+
mime_type :yaml, "application/x-yaml"
|
8
|
+
mime_type :json, "application/json"
|
9
|
+
|
10
|
+
post "/_control/layout.:format" do |format|
|
8
11
|
begin
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
+
if format == "yaml"
|
13
|
+
configuration.load_layout_from_yaml_file params["file"][:tempfile]
|
14
|
+
respond_json_acknowledgement
|
15
|
+
elsif format == "json"
|
16
|
+
configuration.load_layout_from_json_file params["file"][:tempfile]
|
17
|
+
respond_json_acknowledgement
|
18
|
+
else
|
19
|
+
not_acceptable
|
20
|
+
end
|
21
|
+
rescue Holoserve::Configuration::InvalidFormatError => error
|
12
22
|
error 400, error.inspect
|
13
23
|
end
|
14
24
|
end
|
15
25
|
|
16
|
-
|
17
|
-
|
18
|
-
|
26
|
+
get "/_control/layout.:format" do |format|
|
27
|
+
if format == "yaml"
|
28
|
+
respond_yaml configuration.layout
|
29
|
+
elsif format == "json"
|
30
|
+
respond_json configuration.layout
|
31
|
+
else
|
32
|
+
not_acceptable
|
33
|
+
end
|
19
34
|
end
|
20
35
|
|
21
|
-
|
22
|
-
|
36
|
+
delete "/_control/layout" do
|
37
|
+
configuration.clear_layout!
|
38
|
+
respond_json_acknowledgement
|
23
39
|
end
|
24
40
|
|
25
|
-
put "/_control/
|
26
|
-
|
27
|
-
|
28
|
-
respond_json_acknowledgement
|
29
|
-
else
|
30
|
-
not_found
|
31
|
-
end
|
41
|
+
put "/_control/situation/:name" do |situation|
|
42
|
+
configuration.situation = situation
|
43
|
+
respond_json_acknowledgement
|
32
44
|
end
|
33
45
|
|
34
|
-
get "/_control/
|
35
|
-
configuration.
|
46
|
+
get "/_control/situation" do
|
47
|
+
configuration.situation.to_s
|
36
48
|
end
|
37
49
|
|
38
50
|
get "/_control/bucket/requests" do
|
@@ -55,10 +67,19 @@ class Holoserve::Interface::Control < Sinatra::Base
|
|
55
67
|
end
|
56
68
|
|
57
69
|
def respond_json(object)
|
58
|
-
content_type
|
70
|
+
content_type :json
|
59
71
|
JSON.dump object
|
60
72
|
end
|
61
73
|
|
74
|
+
def respond_yaml(object)
|
75
|
+
content_type :yaml
|
76
|
+
object.to_yaml
|
77
|
+
end
|
78
|
+
|
79
|
+
def not_acceptable
|
80
|
+
[ 406, { }, [ "format not acceptable" ] ]
|
81
|
+
end
|
82
|
+
|
62
83
|
def bucket
|
63
84
|
Holoserve.instance.bucket
|
64
85
|
end
|
@@ -10,7 +10,14 @@ class Holoserve::Interface::Fake
|
|
10
10
|
history.pair_names << name
|
11
11
|
logger.info "received handled request with name '#{name}'"
|
12
12
|
end
|
13
|
-
|
13
|
+
responses = pair[:responses]
|
14
|
+
response = Holoserve::Tool::Merger.new(responses[:default] || { }, responses[configuration.situation.to_sym] || { }).result
|
15
|
+
if response.empty?
|
16
|
+
logger.warn "received request #{pair[:name]} with undefined response"
|
17
|
+
not_found
|
18
|
+
else
|
19
|
+
Holoserve::Response::Composer.new(response).response_array
|
20
|
+
end
|
14
21
|
else
|
15
22
|
bucket.requests << request
|
16
23
|
logger.error "received unhandled request\n" + request.pretty_inspect
|
@@ -45,7 +45,7 @@ class Holoserve::Request::Matcher
|
|
45
45
|
def match_parameters?
|
46
46
|
match = true
|
47
47
|
(@request_subset[:parameters] || { }).each do |key, value|
|
48
|
-
match &&= @request[:parameters][key] == value
|
48
|
+
match &&= @request[:parameters].is_a?(Hash) && (@request[:parameters][key] == value)
|
49
49
|
end
|
50
50
|
match
|
51
51
|
end
|
@@ -53,7 +53,7 @@ class Holoserve::Request::Matcher
|
|
53
53
|
def match_oauth?
|
54
54
|
match = true
|
55
55
|
(@request_subset[:oauth] || { }).each do |key, value|
|
56
|
-
match &&= @request[:oauth][key] == value
|
56
|
+
match &&= @request[:oauth].is_a?(Hash) && (@request[:oauth][key] == value)
|
57
57
|
end
|
58
58
|
match
|
59
59
|
end
|
data/lib/holoserve/runner.rb
CHANGED
@@ -7,8 +7,8 @@ class Holoserve::Runner
|
|
7
7
|
|
8
8
|
def initialize(options = { })
|
9
9
|
@port = options[:port] || 4250
|
10
|
-
@
|
11
|
-
@
|
10
|
+
@layout_filename = options[:layout_filename]
|
11
|
+
@situation = options[:situation]
|
12
12
|
|
13
13
|
@rackup_options = Unicorn::Configurator::RACKUP
|
14
14
|
@rackup_options[:port] = @port
|
@@ -20,8 +20,8 @@ class Holoserve::Runner
|
|
20
20
|
|
21
21
|
def start
|
22
22
|
@unicorn.start
|
23
|
-
|
24
|
-
|
23
|
+
upload_layout if @layout_filename
|
24
|
+
set_situation if @situation
|
25
25
|
end
|
26
26
|
|
27
27
|
def join
|
@@ -42,18 +42,22 @@ class Holoserve::Runner
|
|
42
42
|
|
43
43
|
private
|
44
44
|
|
45
|
-
def
|
45
|
+
def upload_layout
|
46
|
+
format = File.extname(@layout_filename).sub(/^\./, "")
|
47
|
+
raise ArgumentError, "file extension indicates wrong format '#{format}' (choose yaml or json)" unless [ "yaml", "json" ].include?(format)
|
46
48
|
Holoserve::Tool::Uploader.new(
|
47
|
-
@
|
49
|
+
@layout_filename,
|
48
50
|
:post,
|
49
|
-
"http://localhost:#{port}/_control/
|
51
|
+
"http://localhost:#{port}/_control/layout.#{format}",
|
50
52
|
:expected_status_code => 200
|
51
53
|
).upload
|
52
54
|
nil
|
53
55
|
end
|
54
56
|
|
55
|
-
def
|
56
|
-
Transport::JSON.request :put,
|
57
|
+
def set_situation
|
58
|
+
Transport::JSON.request :put,
|
59
|
+
"http://localhost:#{port}/_control/situation/#{@situation}",
|
60
|
+
:expected_status_code => 200
|
57
61
|
nil
|
58
62
|
end
|
59
63
|
|
@@ -1,12 +1,18 @@
|
|
1
1
|
|
2
2
|
class Holoserve::Tool::Hash::KeySymbolizer
|
3
3
|
|
4
|
-
def initialize(
|
5
|
-
@
|
4
|
+
def initialize(hash_or_array)
|
5
|
+
@hash_or_array = hash_or_array
|
6
6
|
end
|
7
7
|
|
8
8
|
def hash
|
9
|
-
|
9
|
+
if @hash_or_array.is_a?(Hash)
|
10
|
+
symbolize_keys @hash_or_array
|
11
|
+
elsif @hash_or_array.is_a?(Array)
|
12
|
+
symbolize_keys_of_all @hash_or_array
|
13
|
+
else
|
14
|
+
@hash_or_array
|
15
|
+
end
|
10
16
|
end
|
11
17
|
|
12
18
|
private
|
@@ -27,6 +33,7 @@ class Holoserve::Tool::Hash::KeySymbolizer
|
|
27
33
|
end
|
28
34
|
|
29
35
|
def symbolize_keys_of_all(array)
|
36
|
+
return nil unless array.is_a?(Array)
|
30
37
|
array.map do |item|
|
31
38
|
if item.is_a?(Hash)
|
32
39
|
symbolize_keys item
|
@@ -0,0 +1,51 @@
|
|
1
|
+
|
2
|
+
class Holoserve::Tool::Merger
|
3
|
+
|
4
|
+
def initialize(hash_or_array_one, hash_or_array_two)
|
5
|
+
@hash_or_array_one, @hash_or_array_two = hash_or_array_one, hash_or_array_two
|
6
|
+
end
|
7
|
+
|
8
|
+
def result
|
9
|
+
if @hash_or_array_one.is_a?(Hash) && @hash_or_array_two.is_a?(Hash)
|
10
|
+
merged_hash
|
11
|
+
elsif @hash_or_array_one.is_a?(Array) && @hash_or_array_two.is_a?(Array)
|
12
|
+
merged_array
|
13
|
+
else
|
14
|
+
@hash_or_array_two
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def merged_hash
|
21
|
+
result = { }
|
22
|
+
(@hash_or_array_one.keys + @hash_or_array_two.keys).uniq.each do |key|
|
23
|
+
value_one, value_two = @hash_or_array_one[key],@hash_or_array_two[key]
|
24
|
+
result[key] = if values_mergeable?(value_one, value_two)
|
25
|
+
self.class.new(value_one, value_two).result
|
26
|
+
else
|
27
|
+
value_two || value_one
|
28
|
+
end
|
29
|
+
end
|
30
|
+
result
|
31
|
+
end
|
32
|
+
|
33
|
+
def merged_array
|
34
|
+
result = Array.new [ @hash_or_array_one.length, @hash_or_array_two.length ].max
|
35
|
+
result.each_index do |index|
|
36
|
+
value_one, value_two = @hash_or_array_one[index], @hash_or_array_two[index]
|
37
|
+
result[index] = if values_mergeable?(value_one, value_two)
|
38
|
+
self.class.new(value_one, value_two).result
|
39
|
+
else
|
40
|
+
value_two || value_one
|
41
|
+
end
|
42
|
+
end
|
43
|
+
result
|
44
|
+
end
|
45
|
+
|
46
|
+
def values_mergeable?(value_one, value_two)
|
47
|
+
(value_one.is_a?(Hash) && value_two.is_a?(Hash)) ||
|
48
|
+
(value_one.is_a?(Array) && value_two.is_a?(Array))
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
data/lib/holoserve/tool.rb
CHANGED
data/spec/helper.rb
ADDED
@@ -0,0 +1,61 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), "..", "..", "..", "helper"))
|
2
|
+
|
3
|
+
describe Holoserve::Tool::Merger do
|
4
|
+
|
5
|
+
subject { described_class.new argument_one, argument_two }
|
6
|
+
|
7
|
+
describe "result" do
|
8
|
+
|
9
|
+
context "of two hashes" do
|
10
|
+
|
11
|
+
let(:argument_one) { { :test => "value" } }
|
12
|
+
let(:argument_two) { { :test => "another value" } }
|
13
|
+
|
14
|
+
it "should merge nested values" do
|
15
|
+
subject.result.should == { :test => "another value" }
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
|
20
|
+
context "of two nested hashes" do
|
21
|
+
|
22
|
+
let(:argument_one) { { :test => { :regular =>"value", :nested => "value" } } }
|
23
|
+
let(:argument_two) { { :test => { :nested => "another value" } } }
|
24
|
+
|
25
|
+
it "should merge nested values" do
|
26
|
+
subject.result.should == { :test => { :regular => "value", :nested => "another value" } }
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
|
31
|
+
context "of two arrays" do
|
32
|
+
|
33
|
+
let(:argument_one) { [ { :test => "value" }, { :regular => "value", :another_test => "value" } ] }
|
34
|
+
let(:argument_two) { [ { :test => "another value" }, { :another_test => "another value" } ] }
|
35
|
+
|
36
|
+
it "should merge all nested hashes" do
|
37
|
+
subject.result.should == [
|
38
|
+
{ :test => "another value" },
|
39
|
+
{ :regular => "value", :another_test => "another value" }
|
40
|
+
]
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
|
45
|
+
context "of two arrays with different lengths" do
|
46
|
+
|
47
|
+
let(:argument_one) { [ { :test => "value" } ] }
|
48
|
+
let(:argument_two) { [ { :test => "another value" }, { :another_test => "another value" } ] }
|
49
|
+
|
50
|
+
it "should merge all nested hashes" do
|
51
|
+
subject.result.should == [
|
52
|
+
{ :test => "another value" },
|
53
|
+
{ :another_test => "another value" }
|
54
|
+
]
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: holoserve
|
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,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2012-01-16 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rack
|
16
|
-
requirement: &
|
16
|
+
requirement: &70247827043580 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
@@ -21,10 +21,10 @@ dependencies:
|
|
21
21
|
version: '0'
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *70247827043580
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: sinatra
|
27
|
-
requirement: &
|
27
|
+
requirement: &70247827042840 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ! '>='
|
@@ -32,10 +32,10 @@ dependencies:
|
|
32
32
|
version: '0'
|
33
33
|
type: :runtime
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *70247827042840
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
37
|
name: unicorn
|
38
|
-
requirement: &
|
38
|
+
requirement: &70247827042360 !ruby/object:Gem::Requirement
|
39
39
|
none: false
|
40
40
|
requirements:
|
41
41
|
- - ! '>='
|
@@ -43,10 +43,10 @@ dependencies:
|
|
43
43
|
version: '0'
|
44
44
|
type: :runtime
|
45
45
|
prerelease: false
|
46
|
-
version_requirements: *
|
46
|
+
version_requirements: *70247827042360
|
47
47
|
- !ruby/object:Gem::Dependency
|
48
48
|
name: transport
|
49
|
-
requirement: &
|
49
|
+
requirement: &70247827041740 !ruby/object:Gem::Requirement
|
50
50
|
none: false
|
51
51
|
requirements:
|
52
52
|
- - ! '>='
|
@@ -54,10 +54,10 @@ dependencies:
|
|
54
54
|
version: '0'
|
55
55
|
type: :runtime
|
56
56
|
prerelease: false
|
57
|
-
version_requirements: *
|
57
|
+
version_requirements: *70247827041740
|
58
58
|
- !ruby/object:Gem::Dependency
|
59
59
|
name: cucumber
|
60
|
-
requirement: &
|
60
|
+
requirement: &70247827041200 !ruby/object:Gem::Requirement
|
61
61
|
none: false
|
62
62
|
requirements:
|
63
63
|
- - ! '>='
|
@@ -65,10 +65,10 @@ dependencies:
|
|
65
65
|
version: '0'
|
66
66
|
type: :development
|
67
67
|
prerelease: false
|
68
|
-
version_requirements: *
|
68
|
+
version_requirements: *70247827041200
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: rspec
|
71
|
-
requirement: &
|
71
|
+
requirement: &70247827040660 !ruby/object:Gem::Requirement
|
72
72
|
none: false
|
73
73
|
requirements:
|
74
74
|
- - ! '>='
|
@@ -76,10 +76,10 @@ dependencies:
|
|
76
76
|
version: '0'
|
77
77
|
type: :development
|
78
78
|
prerelease: false
|
79
|
-
version_requirements: *
|
79
|
+
version_requirements: *70247827040660
|
80
80
|
- !ruby/object:Gem::Dependency
|
81
81
|
name: transport
|
82
|
-
requirement: &
|
82
|
+
requirement: &70247827040180 !ruby/object:Gem::Requirement
|
83
83
|
none: false
|
84
84
|
requirements:
|
85
85
|
- - ! '>='
|
@@ -87,10 +87,10 @@ dependencies:
|
|
87
87
|
version: '0'
|
88
88
|
type: :development
|
89
89
|
prerelease: false
|
90
|
-
version_requirements: *
|
90
|
+
version_requirements: *70247827040180
|
91
91
|
- !ruby/object:Gem::Dependency
|
92
92
|
name: oauth
|
93
|
-
requirement: &
|
93
|
+
requirement: &70247827039660 !ruby/object:Gem::Requirement
|
94
94
|
none: false
|
95
95
|
requirements:
|
96
96
|
- - ! '>='
|
@@ -98,7 +98,7 @@ dependencies:
|
|
98
98
|
version: '0'
|
99
99
|
type: :development
|
100
100
|
prerelease: false
|
101
|
-
version_requirements: *
|
101
|
+
version_requirements: *70247827039660
|
102
102
|
description: This tool can be used to fake webservice APIs for testing proposals.
|
103
103
|
email: philipp.bruell@skrill.com
|
104
104
|
executables:
|
@@ -127,9 +127,12 @@ files:
|
|
127
127
|
- lib/holoserve/runner.rb
|
128
128
|
- lib/holoserve/tool/hash/key_symbolizer.rb
|
129
129
|
- lib/holoserve/tool/hash.rb
|
130
|
+
- lib/holoserve/tool/merger.rb
|
130
131
|
- lib/holoserve/tool/uploader.rb
|
131
132
|
- lib/holoserve/tool.rb
|
132
133
|
- lib/holoserve.rb
|
134
|
+
- spec/helper.rb
|
135
|
+
- spec/lib/holoserve/tool/merger_spec.rb
|
133
136
|
homepage: http://github.com/skrill/holoserve
|
134
137
|
licenses: []
|
135
138
|
post_install_message:
|
@@ -144,7 +147,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
144
147
|
version: '0'
|
145
148
|
segments:
|
146
149
|
- 0
|
147
|
-
hash:
|
150
|
+
hash: 460979945885990413
|
148
151
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
149
152
|
none: false
|
150
153
|
requirements:
|
@@ -157,4 +160,5 @@ rubygems_version: 1.8.10
|
|
157
160
|
signing_key:
|
158
161
|
specification_version: 3
|
159
162
|
summary: Tool to fake HTTP APIs.
|
160
|
-
test_files:
|
163
|
+
test_files:
|
164
|
+
- spec/lib/holoserve/tool/merger_spec.rb
|