multiforecast-client 0.62.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,326 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require 'growthforecast-client'
3
+
4
+ module MultiForecast
5
+ class Error < StandardError; end
6
+ class NotFound < Error; end
7
+ class AlreadyExists < Error; end
8
+
9
+ class Client
10
+ include ::MultiForecast::ConversionRule
11
+ attr_accessor :clients
12
+ attr_accessor :debug_dev
13
+ attr_accessor :short_metrics
14
+
15
+ # @param [Hash] opts
16
+ # [Hash] mapping: Mapping rules from `path` to GrowthForecast's `base_uri`.
17
+ def initialize(opts = {})
18
+ @mapping = opts['mapping'] || { '' => 'http://localhost:5125' }
19
+ @short_metrics = opts['short_metrics'] || true
20
+
21
+ @clients = {}
22
+ @base_uris = {}
23
+ @mapping.each do |path, base_uri|
24
+ if base_uri.kind_of?(Hash)
25
+ base_uri = uri['in_uri']
26
+ out_uri = uri['out_uri']
27
+ end
28
+ @clients[path] = GrowthForecast::Client.new(base_uri)
29
+ @base_uris[path] = out_uri || base_uri
30
+ end
31
+ end
32
+
33
+ # set the `debug_dev` attribute of HTTPClient
34
+ # @param [IO] debug_dev such as STDOUT
35
+ def debug_dev=(debug_dev)
36
+ @debug_dev = debug_dev
37
+ @clients.each {|c| c.debug_dev = debug_dev }
38
+ end
39
+
40
+ def clients(base_path = nil)
41
+ base_path.nil? ? @clients.values : @clients.values_at(*ids(base_path)).compact
42
+ end
43
+
44
+ def client(path)
45
+ @last_client = @clients[id(path)]
46
+ end
47
+
48
+ def last_client
49
+ @last_client
50
+ end
51
+
52
+ def last_response
53
+ @last_client.last_response
54
+ end
55
+
56
+ # GET the JSON API
57
+ # @param [String] path
58
+ # @return [Hash] response body
59
+ def get_json(path)
60
+ client(path).get_json(path)
61
+ end
62
+
63
+ # POST the JSON API
64
+ # @param [String] path
65
+ # @param [Hash] data
66
+ # @return [Hash] response body
67
+ def post_json(path, data = {})
68
+ client(path).post_json(path, data)
69
+ end
70
+
71
+ # POST the non-JSON API
72
+ # @param [String] path
73
+ # @param [Hash] data
74
+ # @return [String] response body
75
+ def post_query(path, data = {})
76
+ client(path).post_query(path, data)
77
+ end
78
+
79
+ # Get the list of graphs, /json/list/graph
80
+ # @return [Hash] list of graphs
81
+ # @example
82
+ # [
83
+ # {"base_uri"=>"xxxxx",
84
+ # "service_name"=>"mbclient",
85
+ # "section_name"=>"mbclient",
86
+ # "graph_name"=>"test%2Fhostname%2F%3C2sec_count",
87
+ # "path"=>"test/hostname/<2sec_count",
88
+ # "id"=>4},
89
+ # {"base_uri"=>"xxxxx",
90
+ # "service_name"=>"mbclient",
91
+ # "section_name"=>"mbclient",
92
+ # "graph_name"=>"test%2Fhostname%2F%3C1sec_count",
93
+ # "path"=>"test/hostname/<1sec_count",
94
+ # "id"=>3},
95
+ # ]
96
+ def list_graph(base_path = nil)
97
+ clients(base_path).inject([]) do |ret, client|
98
+ graphs = []
99
+ client.list_graph.each do |graph|
100
+ graph['base_uri'] = client.base_uri
101
+ graph['path'] = path(graph['service_name'], graph['section_name'], graph['graph_name'])
102
+ graphs << graph if base_path.nil? or graph['path'].index(base_path) == 0
103
+ end
104
+ ret = ret + graphs
105
+ end
106
+ end
107
+
108
+ # Get the propety of a graph, GET /api/:path
109
+ # @param [String] path
110
+ # @return [Hash] the graph property
111
+ # @example
112
+ #{
113
+ # "base_uri" => "xxxxxx",
114
+ # "path" => "test/hostname/<4sec_count",
115
+ # "service_name"=>"mbclient",
116
+ # "section_name"=>"mbclient",
117
+ # "graph_name"=>"test%2Fhostname%2F%3C4sec_count",
118
+ # "number"=>1,
119
+ # "llimit"=>-1000000000,
120
+ # "mode"=>"gauge",
121
+ # "stype"=>"AREA",
122
+ # "adjustval"=>"1",
123
+ # "meta"=>"",
124
+ # "gmode"=>"gauge",
125
+ # "color"=>"#cc6633",
126
+ # "created_at"=>"2013/02/02 00:41:11",
127
+ # "ulimit"=>1000000000,
128
+ # "id"=>21,
129
+ # "description"=>"",
130
+ # "sulimit"=>100000,
131
+ # "unit"=>"",
132
+ # "sort"=>0,
133
+ # "updated_at"=>"2013/02/02 02:32:10",
134
+ # "adjust"=>"*",
135
+ # "type"=>"AREA",
136
+ # "sllimit"=>-100000,
137
+ # "md5"=>"3c59dc048e8850243be8079a5c74d079"}
138
+ def get_graph(path)
139
+ client(path).get_graph(service_name(path), section_name(path), graph_name(path)).tap do |graph|
140
+ graph['base_uri'] = client(path).base_uri
141
+ graph['path'] = path
142
+ end
143
+ end
144
+
145
+ # Post parameters to a graph, POST /api/:path
146
+ # @param [String] path
147
+ # @param [Hash] params The POST parameters. See #get_graph
148
+ def post_graph(path, params)
149
+ client(path).post_graph(service_name(path), section_name(path), graph_name(path), params)
150
+ end
151
+
152
+ # Delete a graph, POST /delete/:path
153
+ # @param [String] path
154
+ def delete_graph(path)
155
+ client(path).delete_graph(service_name(path), section_name(path), graph_name(path))
156
+ end
157
+
158
+ # Update the property of a graph, /json/edit/graph/:id
159
+ # @param [String] path
160
+ # @param [Hash] params
161
+ # All of parameters given by #get_graph are available except `number` and `mode`.
162
+ # @return [Hash] error response
163
+ # @example
164
+ # {"error"=>0} #=> Success
165
+ # {"error"=>1} #=> Error
166
+ def edit_graph(path, params)
167
+ client(path).edit_graph(service_name(path), section_name(path), graph_name(path), params)
168
+ end
169
+
170
+ # Get the list of complex graphs, /json/list/complex
171
+ # @return [Hash] list of complex graphs
172
+ # @example
173
+ # [
174
+ # {"base_uri"=>"xxxxx",
175
+ # "path"=>"test/hostname/<2sec_count",
176
+ # "service_name"=>"mbclient",
177
+ # "section_name"=>"mbclient",
178
+ # "graph_name"=>"test%2Fhostname%2F%3C2sec_count",
179
+ # "id"=>4},
180
+ # {"base_uri"=>"xxxxx",
181
+ # "path"=>"test/hostname/<1sec_count",
182
+ # "service_name"=>"mbclient",
183
+ # "section_name"=>"mbclient",
184
+ # "graph_name"=>"test%2Fhostname%2F%3C1sec_count",
185
+ # "id"=>3},
186
+ # ]
187
+ def list_complex(base_path = nil)
188
+ clients(base_path).inject([]) do |ret, client|
189
+ graphs = []
190
+ client.list_complex.each do |graph|
191
+ graph['base_uri'] = client.base_uri
192
+ graph['path'] = path(graph['service_name'], graph['section_name'], graph['graph_name'])
193
+ graphs << graph if base_path.nil? or graph['path'].index(base_path) == 0
194
+ end
195
+ ret = ret + graphs
196
+ end
197
+ end
198
+
199
+ # Create a complex graph
200
+ #
201
+ # @param [Array] from_graphs Array of graph properties whose keys are
202
+ # ["path", "gmode", "stack", "type"]
203
+ # @param [Hash] to_complex Property of Complex Graph, whose keys are like
204
+ # ["path", "description", "sort"]
205
+ def create_complex(from_graphs, to_complex)
206
+ from_graphs = from_graphs.dup
207
+ to_complex = to_complex.dup
208
+
209
+ from_graphs.each do |from_graph|
210
+ from_graph['service_name'] = service_name(from_graph['path'])
211
+ from_graph['section_name'] = section_name(from_graph['path'])
212
+ from_graph['graph_name'] = graph_name(from_graph['path'])
213
+ from_graph.delete('path')
214
+ from_graph.delete('base_uri')
215
+ end
216
+
217
+ to_complex['service_name'] = service_name(to_complex['path'])
218
+ to_complex['section_name'] = section_name(to_complex['path'])
219
+ to_complex['graph_name'] = graph_name(to_complex['path'])
220
+ path = to_complex.delete('path')
221
+
222
+ # NOTE: FROM_GRAPHS AND TO _COMPLEX MUST BE THE SAME GF SERVER
223
+ client(path).create_complex(from_graphs, to_complex)
224
+ end
225
+
226
+ # Get a complex graph
227
+ #
228
+ # @param [String] path
229
+ # @return [Hash] the graph property
230
+ # @example
231
+ # {"number"=>0,
232
+ # "complex"=>true,
233
+ # "created_at"=>"2013/05/20 15:08:28",
234
+ # "service_name"=>"app name",
235
+ # "section_name"=>"host name",
236
+ # "id"=>18,
237
+ # "graph_name"=>"complex graph test",
238
+ # "data"=>
239
+ # [{"gmode"=>"gauge", "stack"=>false, "type"=>"AREA", "graph_id"=>218},
240
+ # {"gmode"=>"gauge", "stack"=>true, "type"=>"AREA", "graph_id"=>217}],
241
+ # "sumup"=>false,
242
+ # "description"=>"complex graph test",
243
+ # "sort"=>10,
244
+ # "updated_at"=>"2013/05/20 15:08:28"}
245
+ def get_complex(path)
246
+ client(path).get_complex(service_name(path), section_name(path), graph_name(path)).tap do |graph|
247
+ graph['base_uri'] = client(path).base_uri
248
+ graph['path'] = path
249
+ end
250
+ end
251
+
252
+ # Delete a complex graph
253
+ #
254
+ # @param [String] path
255
+ # @return [Hash] error response
256
+ # @example
257
+ # {"error"=>0} #=> Success
258
+ # {"error"=>1} #=> Error
259
+ def delete_complex(path)
260
+ client(path).delete_complex(service_name(path), section_name(path), graph_name(path))
261
+ end
262
+
263
+ # Get graph image uri
264
+ #
265
+ # @param [String] path
266
+ # @param [Hash] params for the query string
267
+ # t [String] the time unit such as 'h' (an hour), '4h' (4 hours), '8h', 'n' (half day), 'd' (a day), '3d', 'w', (a week), 'm' (a month), 'y' (a year).
268
+ # Also, 'sh' 's4h' 's8h', 'sn', 'sd', 's3d' for graphs generated by short period GF worker.
269
+ # Also, this parameter is overrided with 'c' or 'sc' when `from` parameter is set.
270
+ # from [String|Time] the time period to show 'from'. String describing a time, or a Time object
271
+ # to [String|Time] the time period to show 'to'. String describing a time, or a Time Object
272
+ # width [String] the widh of image to show
273
+ # height [String] the height of image to show
274
+ # @return [Hash] error response
275
+ # @example
276
+ def get_graph_uri(path, params = {})
277
+ params = preprocess_time_params(params) if params
278
+ "#{@base_uris[id(path)]}/graph/#{CGI.escape(service_name(path))}/#{CGI.escape(section_name(path))}/#{CGI.escape(graph_name(path))}?#{query_string(params)}"
279
+ end
280
+
281
+ # Get complex graph image uri
282
+ #
283
+ # @param [String] path
284
+ # @param [Hash] params for the query string
285
+ # t [String] the time unit such as 'h' (an hour), '4h' (4 hours), '8h', 'n' (half day), 'd' (a day), '3d', 'w', (a week), 'm' (a month), 'y' (a year).
286
+ # Also, 'sh' 's4h' 's8h', 'sn', 'sd', 's3d' for graphs generated by short period GF worker.
287
+ # Also, this parameter is overrided with 'c' or 'sc' when `from` parameter is set.
288
+ # from [String|Time] the time period to show 'from'. String describing a time, or a Time object
289
+ # to [String|Time] the time period to show 'to'. String describing a time, or a Time Object
290
+ # width [String] the widh of image to show
291
+ # height [String] the height of image to show
292
+ # @return [Hash] error response
293
+ # @example
294
+ def get_complex_uri(path, params = {})
295
+ params = preprocess_time_params(params) if params
296
+ "#{@base_uris[id(path)]}/complex/graph/#{CGI.escape(service_name(path))}/#{CGI.escape(section_name(path))}/#{CGI.escape(graph_name(path))}?#{query_string(params)}"
297
+ end
298
+
299
+ # process the time params (from and to)
300
+ def preprocess_time_params(params)
301
+ params = params.dup
302
+ params['from'] = Time.parse(params['from']) if params['from'].kind_of?(String)
303
+ params['to'] = Time.parse(params['to']) if params['to'].kind_of?(String)
304
+ if params['from'] and params['to']
305
+ # if from is more future than 3 days ago, use 'sc' (short period time worker)
306
+ params['t'] = (@short_metrics && params['from'] > Time.now - 60 * 60 * 24 * 3) ? 'sc' : 'c'
307
+ params['from'] = params['from'].strftime("%F %T %z") # format is determined
308
+ params['to'] = params['to'].strftime("%F %T %z")
309
+ end
310
+ params
311
+ end
312
+
313
+ private
314
+
315
+ # build URI query string
316
+ #
317
+ # @param [Hash] param
318
+ # @return [String] query string
319
+ # @example
320
+ def query_string(params)
321
+ return '' if params.nil?
322
+ params.keys.collect{|key| "#{URI.escape(key.to_s)}=#{URI.escape(params[key].to_s)}" }.join('&')
323
+ end
324
+ end
325
+ end
326
+
@@ -0,0 +1,42 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require 'cgi'
3
+
4
+ module MultiForecast
5
+ module ConversionRule
6
+ def service_name(path)
7
+ return path.split('/')[0] if path.count('/') == 2
8
+ 'multiforecast'
9
+ end
10
+
11
+ def section_name(path)
12
+ return path.split('/')[1] if path.count('/') == 2
13
+ # + => '%20' is to avoid GF (Kossy?) bug
14
+ # . => '%2E' because a/./b is recognized as a/b as URL
15
+ CGI.escape(File.dirname(path)).gsub('+', '%20').gsub('.', '%2E')
16
+ end
17
+
18
+ def graph_name(path)
19
+ File.basename(path)
20
+ end
21
+
22
+ def path(service_name, section_name, graph_name)
23
+ return "#{service_name}/#{section_name}/#{graph_name}" unless service_name == "multiforecast"
24
+ dirname = CGI.unescape(section_name)
25
+ basename = graph_name
26
+ dirname == "." ? basename : "#{dirname}/#{basename}"
27
+ end
28
+
29
+ def id(path)
30
+ @mapping.each do |base_path, base_uri|
31
+ return base_path if path.index(base_path) == 0
32
+ end
33
+ return @mapping.keys.first
34
+ end
35
+
36
+ def ids(path)
37
+ @mapping.map do |base_path, base_uri|
38
+ base_path if path.index(base_path) == 0
39
+ end.compact
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,163 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ base_uri = 'http://localhost:5125'
4
+
5
+ shared_context "stub_list_graph" do
6
+ def list_graph_example
7
+ [
8
+ {"gfuri"=>'http://localhost:5125',
9
+ "path"=>"app name/host name/<1sec count",
10
+ "service_name"=>"multiforecast",
11
+ "section_name"=>"app%20name%2Fhost%20name",
12
+ "graph_name"=>"<1sec count",
13
+ "id"=>1},
14
+ {"gfuri"=>'http://localhost:5125',
15
+ "path"=>"app name/host name/<2sec count",
16
+ "service_name"=>"multiforecast",
17
+ "section_name"=>"app+name%2Fhost+name",
18
+ "graph_name"=>"<2sec count",
19
+ "id"=>2},
20
+ ]
21
+ end
22
+
23
+ proc = Proc.new do
24
+ # WebMock.allow_net_connect!
25
+ stub_request(:get, "#{base_uri}/json/list/graph").to_return(:status => 200, :body => list_graph_example.to_json)
26
+ end
27
+ before(:each, &proc)
28
+ end
29
+
30
+ shared_context "stub_get_graph" do
31
+ def graph_example
32
+ {
33
+ "gfuri"=>"http://localhost:5125",
34
+ "path"=>"app name/host name/<1sec count",
35
+ "number"=>0,
36
+ "llimit"=>-1000000000,
37
+ "mode"=>"gauge",
38
+ "stype"=>"AREA",
39
+ "adjustval"=>"1",
40
+ "meta"=>"",
41
+ "service_name"=>"multiforecast",
42
+ "gmode"=>"gauge",
43
+ "color"=>"#cc6633",
44
+ "created_at"=>"2013/02/02 00:41:11",
45
+ "section_name"=>"app%20name%2Fhost%20name",
46
+ "ulimit"=>1000000000,
47
+ "id"=>1,
48
+ "graph_name"=>"<1sec count",
49
+ "description"=>"",
50
+ "sulimit"=>100000,
51
+ "unit"=>"",
52
+ "sort"=>0,
53
+ "updated_at"=>"2013/02/02 02:32:10",
54
+ "adjust"=>"*",
55
+ "type"=>"AREA",
56
+ "sllimit"=>-100000,
57
+ "md5"=>"3c59dc048e8850243be8079a5c74d079"
58
+ }
59
+ end
60
+
61
+ proc = Proc.new do
62
+ stub_request(:get, "#{base_uri}/api/#{gfpath(graph['path'])}").
63
+ to_return(:status => 200, :body => graph_example.to_json)
64
+ end
65
+ before(:each, &proc)
66
+ end
67
+
68
+ shared_context "stub_post_graph" do
69
+ include_context "stub_get_graph"
70
+ proc = Proc.new do
71
+ stub_request(:post, "#{base_uri}/api/#{gfpath(graph['path'])}").
72
+ to_return(:status => 200, :body => { "error" => 0, "data" => graph_example }.to_json)
73
+ end
74
+ before(:each, &proc)
75
+ end
76
+
77
+ shared_context "stub_delete_graph" do
78
+ proc = Proc.new do
79
+ stub_request(:post, "#{base_uri}/delete/#{gfpath(graph['path'])}").
80
+ to_return(:status => 200, :body => { "error" => 0 }.to_json)
81
+ end
82
+ before(:each, &proc)
83
+ end
84
+
85
+ shared_context "stub_edit_graph" do
86
+ include_context "stub_get_graph"
87
+
88
+ proc = Proc.new do
89
+ stub_request(:post, "#{base_uri}/json/edit/graph/#{graph['id']}").
90
+ to_return(:status => 200, :body => { "error" => 0 }.to_json)
91
+ end
92
+ before(:each, &proc)
93
+ end
94
+
95
+ shared_context "stub_list_complex" do
96
+ def list_complex_example
97
+ [
98
+ {"gfuri"=>"http://localhost:5125",
99
+ "path"=>"app name/host name/complex graph test",
100
+ "service_name"=>"multiforecast",
101
+ "section_name"=>"app%20name%2Fhost%20name",
102
+ "graph_name"=>"<1sec count",
103
+ "id"=>1},
104
+ ]
105
+ end
106
+
107
+ proc = Proc.new do
108
+ stub_request(:get, "#{base_uri}/json/list/complex").
109
+ to_return(:status => 200, :body => list_complex_example.to_json)
110
+ end
111
+ before(:each, &proc)
112
+ end
113
+
114
+ shared_context "stub_get_complex" do
115
+ def complex_example
116
+ {"gfuri"=>"http://localhost:5125",
117
+ "path"=>"app name/host name/complex graph test",
118
+ "service_name"=>"multiforecast",
119
+ "section_name"=>"app%20name%2Fhost%20name",
120
+ "graph_name"=>"complex graph test",
121
+ "number"=>0,
122
+ "complex"=>true,
123
+ "created_at"=>"2013/05/20 15:08:28",
124
+ "id"=>1,
125
+ "data"=>
126
+ [{"gmode"=>"gauge", "stack"=>false, "type"=>"AREA", "graph_id"=>218},
127
+ {"gmode"=>"gauge", "stack"=>true, "type"=>"AREA", "graph_id"=>217}],
128
+ "sumup"=>false,
129
+ "description"=>"complex graph test",
130
+ "sort"=>10,
131
+ "updated_at"=>"2013/05/20 15:08:28"}
132
+ end
133
+
134
+ proc = Proc.new do
135
+ stub_request(:get, "#{base_uri}/json/complex/#{gfpath(to_complex['path'])}").
136
+ to_return(:status => 200, :body => complex_example.to_json)
137
+ end
138
+ before(:each, &proc)
139
+ end
140
+
141
+ shared_context "stub_delete_complex" do
142
+ proc = Proc.new do
143
+ stub_request(:post, "#{base_uri}/json/delete/complex/#{gfpath(to_complex['path'])}").
144
+ to_return(:status => 200, :body => { "error" => 0 }.to_json)
145
+ end
146
+ before(:each, &proc)
147
+ end
148
+
149
+ shared_context "stub_create_complex" do
150
+ include_context "stub_list_complex"
151
+
152
+ proc = Proc.new do
153
+ list_graph_example.each do |graph|
154
+ stub_request(:get, "#{base_uri}/api/#{gfpath(graph['path'])}").
155
+ to_return(:status => 200, :body => graph.to_json)
156
+ end
157
+
158
+ stub_request(:post, "#{base_uri}/json/create/complex").
159
+ to_return(:status => 200, :body => { "error" => 0 }.to_json)
160
+ end
161
+ before(:each, &proc)
162
+ end
163
+
@@ -0,0 +1,62 @@
1
+ # -*- encoding: utf-8 -*-
2
+ shared_context "let_graph" do
3
+ include_context "stub_list_graph" if ENV['MOCK'] == 'on'
4
+ let(:graphs) { multiforecast.list_graph }
5
+ let(:graph) { graphs.first }
6
+ end
7
+
8
+ shared_context "setup_graph" do
9
+ include_context "let_graph"
10
+ include_context "stub_post_graph" if ENV['MOCK'] == 'on'
11
+ include_context "stub_delete_graph" if ENV['MOCK'] == 'on'
12
+ before(:all) {
13
+ multiforecast.delete_graph("app name/host name/<1sec count") rescue nil
14
+ multiforecast.delete_graph("app name/host name/<2sec count") rescue nil
15
+ multiforecast.post_graph("app name/host name/<1sec count", { 'number' => 0 }) rescue nil
16
+ multiforecast.post_graph("app name/host name/<2sec count", { 'number' => 0 }) rescue nil
17
+ }
18
+ after(:all) {
19
+ multiforecast.delete_graph("app name/host name/<1sec count") rescue nil
20
+ multiforecast.delete_graph("app name/host name/<2sec count") rescue nil
21
+ }
22
+ end
23
+
24
+ shared_context "let_complex" do
25
+ include_context "setup_graph"
26
+ let(:from_graphs) do
27
+ [
28
+ {
29
+ "path" => graphs[0]["path"],
30
+ "gmode" => "gauge",
31
+ "stack" => false,
32
+ "type" => "AREA",
33
+ },
34
+ {
35
+ "path" => graphs[1]["path"],
36
+ "gmode" => "gauge",
37
+ "stack" => false,
38
+ "type" => "AREA"
39
+ },
40
+ ]
41
+ end
42
+ let(:to_complex) do
43
+ {
44
+ "path" => "app name/host name/complex graph test",
45
+ "description" => "complex graph test",
46
+ "sort" => 10
47
+ }
48
+ end
49
+ end
50
+
51
+ shared_context "setup_complex" do
52
+ include_context "let_complex"
53
+ include_context "stub_create_complex" if ENV['MOCK'] == 'on'
54
+ include_context "stub_delete_complex" if ENV['MOCK'] == 'on'
55
+ before do
56
+ multiforecast.delete_complex(to_complex["path"]) rescue nil
57
+ multiforecast.create_complex(from_graphs, to_complex) rescue nil
58
+ end
59
+ after do
60
+ multiforecast.delete_complex(to_complex["path"]) rescue nil
61
+ end
62
+ end
@@ -0,0 +1,22 @@
1
+ require 'multiforecast-client'
2
+ require 'multiforecast/shared_context/setup.rb'
3
+ require 'multiforecast/shared_context/mock.rb'
4
+
5
+ include MultiForecast::ConversionRule
6
+
7
+ def e(str)
8
+ CGI.escape(str).gsub('+', '%20') if str
9
+ end
10
+
11
+ def gfpath(path)
12
+ "#{e service_name(path)}/#{e section_name(path)}/#{e graph_name(path)}"
13
+ end
14
+
15
+ def base_uri
16
+ 'http://localhost:5125'
17
+ end
18
+
19
+ def multiforecast(opts = {})
20
+ opts['mapping'] ||= { '' => base_uri }
21
+ MultiForecast::Client.new(opts)
22
+ end
@@ -0,0 +1,30 @@
1
+ shared_examples_for 'graph_uri_long_metrics' do
2
+ it { subject.should match(/(\?|&)t=c(&|$)/) }
3
+ it_should_behave_like 'graph_uri_params_fromto'
4
+ it_should_behave_like 'graph_uri_params_widthheight'
5
+ end
6
+
7
+ shared_examples_for 'graph_uri_short_metrics' do
8
+ it { subject.should match(/(\?|&)t=sc(&|$)/) }
9
+ it_should_behave_like 'graph_uri_params_fromto'
10
+ it_should_behave_like 'graph_uri_params_widthheight'
11
+ end
12
+
13
+ shared_examples_for 'graph_uri_params' do
14
+ it_should_behave_like 'graph_uri_params_term'
15
+ it_should_behave_like 'graph_uri_params_widthheight'
16
+ end
17
+
18
+ shared_examples_for 'graph_uri_params_term' do
19
+ it { subject.should match(/(\?|&)t=#{params['t']}(&|$)/) }
20
+ end
21
+
22
+ shared_examples_for 'graph_uri_params_widthheight' do
23
+ it { subject.should match(/(\?|&)width=#{params['width'].to_s}(&|$)/) }
24
+ it { subject.should match(/(\?|&)height=#{params['height'].to_s}(&|$)/) }
25
+ end
26
+
27
+ shared_examples_for 'graph_uri_params_fromto' do
28
+ it { subject.should match(/(\?|&)from=#{Regexp.escape(URI.escape(params['from'].to_s))}(&|$)/) }
29
+ it { subject.should match(/(\?|&)to=#{Regexp.escape(URI.escape(params['to'].to_s))}(&|$)/) }
30
+ end
@@ -0,0 +1,2 @@
1
+ require 'multiforecast/conversion_rule'
2
+ require 'multiforecast/client'
@@ -0,0 +1,29 @@
1
+ #! /usr/bin/env gem build
2
+ # encoding: utf-8
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.name = 'multiforecast-client'
6
+ gem.version = File.read(File.expand_path('VERSION', File.dirname(__FILE__))).chomp
7
+ gem.authors = ["Naotoshi Seo"]
8
+ gem.email = ["sonots@gmail.com"]
9
+ gem.homepage = "https://github.com/sonots/multiforecast-client"
10
+ gem.summary = "Multiple GrowthForecast Client"
11
+ gem.description = gem.summary
12
+
13
+ gem.files = `git ls-files`.split($\)
14
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
15
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
16
+ gem.require_paths = ["lib"]
17
+
18
+ gem.add_runtime_dependency "growthforecast-client", "~> 0.62.0"
19
+
20
+ # for testing
21
+ gem.add_development_dependency "rake"
22
+ gem.add_development_dependency "rspec", "~> 2.11"
23
+ gem.add_development_dependency "webmock"
24
+
25
+ # for debug
26
+ gem.add_development_dependency "pry"
27
+ gem.add_development_dependency "pry-nav"
28
+ gem.add_development_dependency "tapp"
29
+ end