vayacondios-client 0.2.11 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (62) hide show
  1. data/.gitignore +64 -0
  2. data/.travis.yml +13 -0
  3. data/CHANGELOG.md +0 -0
  4. data/Gemfile +21 -0
  5. data/LICENSE.md +95 -0
  6. data/Procfile +2 -0
  7. data/README.md +734 -0
  8. data/Rakefile +93 -0
  9. data/bin/vcd +10 -0
  10. data/config/database.yml +6 -0
  11. data/config/spec.example.yml +18 -0
  12. data/config/vayacondios.example.yml +15 -0
  13. data/examples/configuration.rb +56 -0
  14. data/examples/event_stream.rb +19 -0
  15. data/examples/simple.rb +61 -0
  16. data/features/event.feature +319 -0
  17. data/features/events.feature +208 -0
  18. data/features/stash.feature +840 -0
  19. data/features/stashes.feature +492 -0
  20. data/features/step_definitions/stash_steps.rb +113 -0
  21. data/features/stream.feature +30 -0
  22. data/features/support/em.rb +14 -0
  23. data/features/support/env.rb +13 -0
  24. data/lib/vayacondios/client/cli.rb +456 -0
  25. data/lib/vayacondios/client/configuration.rb +13 -0
  26. data/lib/vayacondios/client/connection.rb +39 -0
  27. data/lib/vayacondios/client/http_client.rb +6 -42
  28. data/lib/vayacondios/client/http_methods.rb +85 -0
  29. data/lib/vayacondios/client.rb +21 -0
  30. data/lib/vayacondios/configuration.rb +63 -0
  31. data/lib/vayacondios-client.rb +16 -17
  32. data/lib/vayacondios.rb +22 -0
  33. data/pom.xml +168 -0
  34. data/spec/client/cli_spec.rb +283 -0
  35. data/spec/client/configuration_spec.rb +11 -0
  36. data/spec/client/http_client_spec.rb +150 -0
  37. data/spec/configuration_spec.rb +41 -0
  38. data/spec/spec_helper.rb +27 -0
  39. data/spec/support/database_helper.rb +42 -0
  40. data/spec/support/log_helper.rb +19 -0
  41. data/spec/support/shared_context_for_events.rb +22 -0
  42. data/spec/support/shared_context_for_stashes.rb +24 -0
  43. data/spec/support/shared_examples_for_handlers.rb +32 -0
  44. data/src/main/java/com/infochimps/vayacondios/BaseClient.java +342 -0
  45. data/src/main/java/com/infochimps/vayacondios/HTTPClient.java +426 -0
  46. data/src/main/java/com/infochimps/vayacondios/VayacondiosClient.java +500 -0
  47. data/src/main/java/com/infochimps/vayacondios/test/IntegrationTest.java +3 -0
  48. data/src/test/java/com/infochimps/vayacondios/BaseClientTest.java +50 -0
  49. data/src/test/java/com/infochimps/vayacondios/HTTPClientIT.java +267 -0
  50. data/vayacondios-client.gemspec +25 -0
  51. metadata +96 -60
  52. checksums.yaml +0 -15
  53. data/lib/vayacondios/client/config.rb +0 -7
  54. data/lib/vayacondios/client/configliere.rb +0 -38
  55. data/lib/vayacondios/client/cube_client.rb +0 -39
  56. data/lib/vayacondios/client/itemset.rb +0 -130
  57. data/lib/vayacondios/client/legacy_switch.rb +0 -43
  58. data/lib/vayacondios/client/notifier.rb +0 -123
  59. data/lib/vayacondios/client/zabbix_client.rb +0 -148
  60. data/spec/client/itemset_legacy_spec.rb +0 -55
  61. data/spec/client/itemset_spec.rb +0 -60
  62. data/spec/client/notifier_spec.rb +0 -120
@@ -0,0 +1,500 @@
1
+ package com.infochimps.vayacondios;
2
+
3
+ import java.util.Map;
4
+ import java.util.List;
5
+
6
+ /** This is interface all concrete Vayacondios client classes
7
+ * implement.
8
+ * <p>
9
+ * Your code should type client instances with this interface, as in
10
+ * the following example, which uses a {@link HTTPClient} but still
11
+ * types <code>client</code> as <code>VayacondiosClient</code>:
12
+ * <blockquote><pre>
13
+ * {@code
14
+ * import com.infochimps.vayacondios.VayacondiosClient;
15
+ * import com.infochimps.vayacondios.HTTPClient;
16
+ *
17
+ * class public HelloClient {
18
+ * public static void main(String[] args) throws Exception {
19
+ * VayacondiosClient client = new HTTPClient("my_organization");
20
+ *
21
+ * // do stuff...
22
+ *
23
+ * Thread.sleep(1000); // ensure all HTTP requests have been sent before closing the client
24
+ * client.close()
25
+ * }
26
+ * }
27
+ * }</pre></blockquote>
28
+ * */
29
+ public interface VayacondiosClient {
30
+
31
+ /**
32
+ * Announce a new event.
33
+ * <p>
34
+ * Here's an example which announces a suspicious intrusion event:
35
+ *
36
+ * <blockquote><pre>
37
+ * {@code
38
+ * Map event = new HashMap();
39
+ * event.put("ip", "10.123.123.123");
40
+ * event.put("priority", 3);
41
+ * event.put("type", "ssh");
42
+ * client.announce("intrusions", event);
43
+ * }</pre></blockquote>
44
+ *
45
+ * Events will be automatically assigned an ID and a timestamp by
46
+ * the server.
47
+ * <p>
48
+ * The timestamp can also be included in the event body:
49
+ *
50
+ * <blockquote><pre>
51
+ * {@code
52
+ * Map event = new HashMap();
53
+ * event.put("ip", "10.123.123.123");
54
+ * event.put("priority", 3);
55
+ * event.put("type", "ssh");
56
+ * event.put("time", "2013-06-18 Tue 16:43 -0500");
57
+ * client.announce("intrusions", event);
58
+ * }</pre></blockquote>
59
+ *
60
+ * @param topic the topic for the event
61
+ * @param event the event body
62
+ */
63
+ void announce(String topic, Map<String,Object> event);
64
+
65
+ /**
66
+ * Announce an event with a specified ID.
67
+ * <p>
68
+ * Here's an example which announces a build using the unique ID
69
+ * assigned by the build system as the ID of the event:
70
+ *
71
+ * <blockquote><pre>
72
+ * {@code
73
+ * Map event = new HashMap();
74
+ * event.put("name", "Little Stinker");
75
+ * event.put("version", "1.2.3");
76
+ * event.put("status", "success");
77
+ * event.put("duration", 183);
78
+ * client.announce("builds", event, "13fe3ff5f13c6b0394cc22501a9617cfe2445c63");
79
+ * }</pre></blockquote>
80
+ *
81
+ * The server will use this ID when saving the event.
82
+ * <p>
83
+ * The server will still generate a timestamp, unless one is
84
+ * included in the event body.
85
+ *
86
+ * @param topic the topic for the event
87
+ * @param event the event body
88
+ * @param id the ID to save the event with
89
+ */
90
+ void announce(String topic, Map<String,Object> event, String id);
91
+
92
+ /**
93
+ * Search for events matching some query.
94
+ * <p>
95
+ * Each element of the returned <code>List</code> of events is a
96
+ * <code>Map</code>.
97
+ * <p>
98
+ * The default search behavior implemented by the server is to
99
+ * return up to 50 full events from the last hour on the given
100
+ * <code>topic</code> sorted by timestamp, with the earliest
101
+ * events first. the last hour with the earliest event first.
102
+ * This will be the response when given an empty query:
103
+ *
104
+ * <pre><blockquote>
105
+ * {@code
106
+ * Map query = new HashMap(); // empty query
107
+ * List<Map> events = client.events("intrusions", query);
108
+ * }</pre></blockquote>
109
+ *
110
+ * Returned events will match each key/value pair in the query.
111
+ * The following example will only return "intrusion" events with
112
+ * the <code>ip</code> key equal to the value "10.123.123.123":
113
+ *
114
+ * <blockquote><pre>{@code
115
+ * Map query = new HashMap(); // empty query
116
+ * query.put("ip", "10.123.123.123")
117
+ * List<Map> events = client.events("intrusions", query);
118
+ * }</pre></blockquote>
119
+ *
120
+ * The number of events returned, the fields within each event,
121
+ * the time period, and sorting behavior can all be changed:
122
+ *
123
+ * <pre><blockquote>
124
+ * {@code
125
+ * // The basic query
126
+ * Map query = new HashMap();
127
+ * query.put("ip", "10.123.123.123")
128
+ *
129
+ * // Change the number of returned events to 1000
130
+ * query.put("limit", 1000);
131
+ *
132
+ * // Change the timeframe from "the last hour" to all of June 9th, CDT
133
+ * query.put("from", "2013-06-09 Tue 00:00:00 -0500");
134
+ * query.put("upto", "2013-06-09 Tue 23:59:59 -0500");
135
+ *
136
+ * // Return just the "type" and "priority" fields
137
+ * List fields = new ArrayList();
138
+ * fields.add("type");
139
+ * fields.add("priority");
140
+ * query.put("fields", fields);
141
+ *
142
+ * // Sort the result set by the "priority" field in ascending order.
143
+ * List sort = new ArrayList();
144
+ * sort.add("priority");
145
+ * sort.add("ascending");
146
+ * query.put("sort", sort);
147
+ *
148
+ * // Perform the search
149
+ * List<Map> events = client.events("intrusions", query);
150
+ * }</pre></blockquote>
151
+ *
152
+ * This method blocks until a response comes back from the server.
153
+ *
154
+ * @param topic the topic within which to search
155
+ * @param query a query to match events
156
+ * @return the matched events
157
+ */
158
+ List<Map<String,Object>> events(String topic, Map<String,Object> query);
159
+
160
+ /**
161
+ * Lookup a stashed value.
162
+ * <p>
163
+ * When given only a topic, Vayacondios server will either return
164
+ * a <code>Map</code> or <code>null</code>.
165
+ *
166
+ * <blockquote><pre>{@code
167
+ * Map firewall = client.get("firewall");
168
+ * if (firewall != null) {
169
+ * // do stuff...
170
+ * }
171
+ * }</pre></blockquote>
172
+ *
173
+ * @param topic the topic to lookup
174
+ * @return the stashed value or <code>null</code> if it is not found
175
+ */
176
+ Map<String,Object> get(String topic);
177
+
178
+ /**
179
+ * Lookup a stashed value that is a <code>Map</code>.
180
+ * <p>
181
+ * When given a topic and an ID, Vayacondios server can return any
182
+ * one of
183
+ *
184
+ * <ul>
185
+ * <li><code>Map</code></li>
186
+ * <li><code>List</code></li>
187
+ * <li><code>String</code></li>
188
+ * <li><code>Double</code></li>
189
+ * <li><code>null</code></li>
190
+ * </ul>
191
+ *
192
+ * The appropriate method should therefore be called by the client
193
+ * when anticipating a response of a given type. This method will
194
+ * treat the response like it is a <code>Map</code>:
195
+ *
196
+ * <pre><blockquote>{@code
197
+ * Map firewallRules = getMap("firewall", "rules");
198
+ * if (firewallRules != null) {
199
+ * // do stuff...
200
+ * }
201
+ * }</pre></blockquote>
202
+ *
203
+ * @param topic the topic of the stashed value
204
+ * @param id the ID of the stashed value
205
+ * @return the stashed value or <code>null</code> if it is not found
206
+ * @see VayacondiosClient#get(String topic)
207
+ * @see VayacondiosClient#getList(String topic, String id)
208
+ * @see VayacondiosClient#getString(String topic, String id)
209
+ * @see VayacondiosClient#getDouble(String topic, String id)
210
+ */
211
+ Map<String,Object> getMap(String topic, String id);
212
+
213
+ /**
214
+ * Lookup a stashed value that is a <code>List</code>.
215
+ * <p>
216
+ * When given a topic and an ID, Vayacondios server can return any
217
+ * one of
218
+ *
219
+ * <ul>
220
+ * <li><code>Map</code></li>
221
+ * <li><code>List</code></li>
222
+ * <li><code>String</code></li>
223
+ * <li><code>Double</code></li>
224
+ * <li><code>null</code></li>
225
+ * </ul>
226
+ *
227
+ * The appropriate method should therefore be called by the client
228
+ * when anticipating a response of a given type. This method will
229
+ * treat the response like it is a <code>List</code>:
230
+ *
231
+ * <pre><blockquote>{@code
232
+ * List firewallServers = getMap("firewall", "servers");
233
+ * if (firewallServers != null) {
234
+ * // do stuff...
235
+ * }
236
+ * }</pre></blockquote>
237
+ *
238
+ * @param topic the topic of the stashed value
239
+ * @param id the ID of the stashed value
240
+ * @return the stashed value or <code>null</code> if it is not found
241
+ * @see VayacondiosClient#get(String topic)
242
+ * @see VayacondiosClient#getMap(String topic, String id)
243
+ * @see VayacondiosClient#getString(String topic, String id)
244
+ * @see VayacondiosClient#getDouble(String topic, String id)
245
+ */
246
+ List<Object> getList(String topic, String id);
247
+
248
+ /**
249
+ * Lookup a stashed value that is a <code>String</code>.
250
+ * <p>
251
+ * When given a topic and an ID, Vayacondios server can return any
252
+ * one of
253
+ *
254
+ * <ul>
255
+ * <li><code>Map</code></li>
256
+ * <li><code>List</code></li>
257
+ * <li><code>String</code></li>
258
+ * <li><code>Double</code></li>
259
+ * <li><code>null</code></li>
260
+ * </ul>
261
+ *
262
+ * The appropriate method should therefore be called by the client
263
+ * when anticipating a response of a given type. This method will
264
+ * treat the response like it is a <code>String</code>:
265
+ *
266
+ * <pre><blockquote>{@code
267
+ * String firewallName = getMap("firewall", "name");
268
+ * if (firewallName != null) {
269
+ * // do stuff...
270
+ * }
271
+ * }</pre></blockquote>
272
+ *
273
+ * @param topic the topic of the stashed value
274
+ * @param id the ID of the stashed value
275
+ * @return the stashed value or <code>null</code> if it is not found
276
+ * @see VayacondiosClient#get(String topic)
277
+ * @see VayacondiosClient#getMap(String topic, String id)
278
+ * @see VayacondiosClient#getList(String topic, String id)
279
+ * @see VayacondiosClient#getDouble(String topic, String id)
280
+ */
281
+ String getString(String topic, String id);
282
+
283
+ /**
284
+ * Lookup a stashed value that is a <code>Double</code>.
285
+ * <p>
286
+ * When given a topic and an ID, Vayacondios server can return any
287
+ * one of
288
+ *
289
+ * <ul>
290
+ * <li><code>Map</code></li>
291
+ * <li><code>List</code></li>
292
+ * <li><code>String</code></li>
293
+ * <li><code>Double</code></li>
294
+ * <li><code>null</code></li>
295
+ * </ul>
296
+ *
297
+ * The appropriate method should therefore be called by the client
298
+ * when anticipating a response of a given type. This method will
299
+ * treat the response like it is a <code>Double</code>:
300
+ *
301
+ * <pre><blockquote>{@code
302
+ * Double firewallAverageLatency = getMap("firewall", "average_latency");
303
+ * if (firewallAverageLatency != null) {
304
+ * // do stuff...
305
+ * }
306
+ * }</pre></blockquote>
307
+ *
308
+ * @param topic the topic of the stashed value
309
+ * @param id the ID of the stashed value
310
+ * @return the stashed value or <code>null</code> if it is not found
311
+ * @see VayacondiosClient#get(String topic)
312
+ * @see VayacondiosClient#getMap(String topic, String id)
313
+ * @see VayacondiosClient#getList(String topic, String id)
314
+ * @see VayacondiosClient#getString(String topic, String id)
315
+ */
316
+ Double getDouble(String topic, String id);
317
+
318
+ /**
319
+ * Search for stashed values matching a query.
320
+ * <p>
321
+ * Each element of the returned <code>List</code> of stashes is a
322
+ * <code>Map</code>.
323
+ *
324
+ * The default search behavior implemented by the server is to
325
+ * return up to 50 full stashes sorted in ascending order by
326
+ * topic. This will be the response when given an empty query:
327
+ *
328
+ * <blockquote><pre>{@code
329
+ * Map query = new HashMap(); // empty query
330
+ * List<Map> events = client.stashes(query);
331
+ * }</pre></blockquote>
332
+ *
333
+ * Returned stashes will match each key/value pair in the query.
334
+ * The following example will only return stashed values which
335
+ * have the <code>environment</code> key equal to the value
336
+ * "production":
337
+ *
338
+ * <blockquote><pre>{@code
339
+ * Map query = new HashMap(); // empty query
340
+ * query.put("environment", "production")
341
+ * List<Map> events = client.stashes(query);
342
+ * }</pre></blockquote>
343
+ *
344
+ * The number of stashes returned, the content of each stash, and
345
+ * sorting behavior can all be changed:
346
+ *
347
+ * <pre><blockquote>
348
+ * {@code
349
+ * // The basic query
350
+ * Map query = new HashMap();
351
+ * query.put("environment", "production");
352
+ *
353
+ * // Change the number of returned stashes to 1000
354
+ * query.put("limit", 1000);
355
+ *
356
+ * // Sort the result set by the "priority" field in ascending order.
357
+ * List sort = new ArrayList();
358
+ * sort.add("priority");
359
+ * sort.add("ascending");
360
+ * query.put("sort", sort);
361
+ *
362
+ * // Perform the search
363
+ * List<Map> events = client.events("intrusions", query);
364
+ * }</pre></blockquote>
365
+ *
366
+ * @param query a query to match stashed values
367
+ * @return the matched stashed values
368
+ */
369
+ List<Map<String,Object>> stashes(Map<String,Object> query);
370
+
371
+ /**
372
+ * Stash the given value for the given topic.
373
+ * <p>
374
+ * The current value for the given topic will be overwritten.
375
+ * <p>
376
+ * When stashing with only a topic, the Vayacondios server
377
+ * requires that the value be a <code>Map</code>:
378
+ *
379
+ * <blockquote><pre>{@code
380
+ * Map value = new HashMap();
381
+ * value.put("host", "localhost");
382
+ * value.put("port", 80);
383
+ * client.set("server", value);
384
+ * }</pre></blockquote>
385
+ *
386
+ * @param topic the topic to stash a value for
387
+ * @param value the value to stash
388
+ */
389
+ void set(String topic, Map<String,Object> value);
390
+
391
+ /**
392
+ * Stash the given value for the given topic and ID.
393
+ * <p>
394
+ * The current value for the given topic and ID will be
395
+ * overwritten.
396
+ * <p>
397
+ * When stashing with a topic and ID, the Vayacondios server
398
+ * accepts as a value any of
399
+ *
400
+ * <ul>
401
+ * <li><code>Map</code></li>
402
+ * <li><code>List</code></li>
403
+ * <li><code>String</code></li>
404
+ * <li><code>Double</code></li>
405
+ * <li><code>null</code></li>
406
+ * </ul>
407
+ *
408
+ * Here is an example:
409
+ *
410
+ * <blockquote><pre>{@code
411
+ * client.set("server", "host", "localhost");
412
+ * client.set("server", "port", 80);
413
+ * }</pre></blockquote>
414
+ *
415
+ * @param topic <doc>
416
+ * @param value <doc>
417
+ */
418
+ void set(String topic, String id, Object value);
419
+
420
+ /**
421
+ * Merge the given value for the given topic.
422
+ * <p>
423
+ * If a value already exists for the given topic, the new value
424
+ * will be merged into the old value.
425
+ * <p>
426
+ * When stashing with only a topic, the Vayacondios server
427
+ * requires that the value be a <code>Map</code>.
428
+ *
429
+ * <blockquote><pre>{@code
430
+ * Map value = new HashMap();
431
+ * value.put("host", "localhost");
432
+ * value.put("port", 80);
433
+ * client.merge("server", value);
434
+ * }</pre></blockquote>
435
+ *
436
+ * @param topic the topic to merge a value for
437
+ * @param value the new value to merge
438
+ */
439
+ void merge(String topic, Map<String,Object> value);
440
+
441
+ /**
442
+ * Merge the given value for the given topic and ID.
443
+ * <p>
444
+ * If a value already exists for the given topic and ID, the new
445
+ * value will be "merged" into the old value in a type-aware way.
446
+ * <p>
447
+ * When stashing with a topic and ID, the Vayacondios server
448
+ * accepts as a value any of
449
+ *
450
+ * <ul>
451
+ * <li><code>Map</code>: merged</li>
452
+ * <li><code>List</code>: concatenated</li>
453
+ * <li><code>String</code>: concatenated</li>
454
+ * <li><code>Double</code>: incremented</li>
455
+ * <li><code>null</code>: set as is</li>
456
+ * </ul>
457
+ *
458
+ * Type-aware merging means that this method can be used for
459
+ * implementing shared counters and other distributed patterns:
460
+ *
461
+ * <blockquote><pre>{@code
462
+ * Map value = new HashMap();
463
+ * client.merge("server", "error_count", 1); // increments error_count by 1
464
+ * }</pre></blockquote>
465
+ *
466
+ * @param topic the topic to merge a value for
467
+ * @param value the new value to merge
468
+ */
469
+ void merge(String topic, String id, Object value);
470
+
471
+ /**
472
+ * Delete the value stashed for a given topic.
473
+ *
474
+ * <blockquote><pre>{@code
475
+ * client.delete("firewall");
476
+ * }</pre></blockquote>
477
+ *
478
+ * @param topic the topic to delete
479
+ */
480
+ void delete(String topic);
481
+
482
+ /**
483
+ * Delete the value stashed for a given topic and ID.
484
+ *
485
+ * <blockquote><pre>{@code
486
+ * client.delete("firewall", "rules");
487
+ * }</pre></blockquote>
488
+ *
489
+ * @param topic the topic to delete
490
+ * @param id the ID to delete
491
+ */
492
+ void delete(String topic, String id);
493
+
494
+
495
+ /** Close this client.
496
+ *
497
+ * */
498
+ void close();
499
+
500
+ }
@@ -0,0 +1,3 @@
1
+ package com.infochimps.vayacondios.test;
2
+
3
+ public interface IntegrationTest {}
@@ -0,0 +1,50 @@
1
+ package com.infochimps.vayacondios;
2
+
3
+ import java.util.Map;
4
+ import java.util.HashMap;
5
+
6
+ import org.junit.Before;
7
+ import org.junit.After;
8
+ import org.junit.Test;
9
+ import org.junit.Ignore;
10
+ import org.junit.runner.RunWith;
11
+ import org.junit.runners.JUnit4;
12
+ import static org.junit.Assert.assertEquals;
13
+
14
+ @RunWith(JUnit4.class)
15
+ public class BaseClientTest {
16
+
17
+ private String organization = "organization";
18
+ private String topic = "topic";
19
+ private String id = "id";
20
+
21
+ private BaseClient client;
22
+ private BaseClient dryClient;
23
+
24
+ @Before
25
+ public void createClient() {
26
+ client = new BaseClient(organization);
27
+ dryClient = new BaseClient(organization, true);
28
+ }
29
+
30
+ @After
31
+ public void closeClient() throws InterruptedException {
32
+ client.close();
33
+ }
34
+
35
+ @Test
36
+ public void canGetSetOrganization() {
37
+ assertEquals(client.organization(), organization);
38
+ }
39
+
40
+ @Test
41
+ public void canGetSetDryRun() {
42
+ assertEquals(dryClient.dryRun(), true);
43
+ }
44
+
45
+ @Test
46
+ public void defaultDryRunFalse() {
47
+ assertEquals(client.dryRun(), false);
48
+ }
49
+
50
+ }