comsat 0.0.1 → 0.0.2
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.md +20 -2
- data/Rakefile +8 -2
- data/comsat.gemspec +7 -3
- data/lib/comsat/helpers/auth_helper.rb +28 -0
- data/lib/comsat/log.rb +16 -0
- data/lib/comsat/route.rb +23 -0
- data/lib/comsat/service.rb +15 -0
- data/lib/comsat/services/campfire.rb +33 -0
- data/lib/comsat/services/pagerduty.rb +31 -0
- data/lib/comsat/version.rb +1 -1
- data/lib/comsat.rb +50 -75
- data/spec/client_spec.rb +39 -0
- data/spec/service_spec.rb +10 -0
- data/spec/spec_helper.rb +6 -0
- metadata +56 -11
data/README.md
CHANGED
@@ -14,6 +14,19 @@ for Campfire might look like:
|
|
14
14
|
The schema name maps to the service name, the rest we pass to the service to
|
15
15
|
deal with.
|
16
16
|
|
17
|
+
## Routes
|
18
|
+
|
19
|
+
Routes allow the user to create aliases for contacting one or more services
|
20
|
+
for a specific event. An event is one of 'notice', 'alert' or 'resolve'.
|
21
|
+
Routes should be named according to their function, and initially are not
|
22
|
+
stored longer than a session, but will eventually be created and reside on
|
23
|
+
the server.
|
24
|
+
|
25
|
+
It is our intention to start developing usage patterns consistent with our
|
26
|
+
defined design goals.
|
27
|
+
|
28
|
+
The examples below show how routes are created.
|
29
|
+
|
17
30
|
## Messages
|
18
31
|
|
19
32
|
Messages should be one of three types, 'notice', 'alert', 'resolve'.
|
@@ -56,8 +69,13 @@ Or install it yourself as:
|
|
56
69
|
## Usage
|
57
70
|
|
58
71
|
```
|
59
|
-
client = Comsat::Client.new
|
60
|
-
client.
|
72
|
+
client = Comsat::Client.new
|
73
|
+
client.create_route("notify_on_exception", "notice", ["campfire://<api_key>:X@blossom.campfirenow.com/Test%20Room"])
|
74
|
+
client.notify("notify_on_exception", {
|
75
|
+
:message => "Exception reached in #function",
|
76
|
+
:source => "my_app",
|
77
|
+
:message_id => "exception-#{rand(1_000)}"
|
78
|
+
})
|
61
79
|
```
|
62
80
|
|
63
81
|
## Contributing
|
data/Rakefile
CHANGED
data/comsat.gemspec
CHANGED
@@ -2,10 +2,10 @@
|
|
2
2
|
require File.expand_path('../lib/comsat/version', __FILE__)
|
3
3
|
|
4
4
|
Gem::Specification.new do |gem|
|
5
|
-
gem.authors = ["
|
5
|
+
gem.authors = ["Curt Micol", "Michael Gorsuch"]
|
6
6
|
gem.email = ["ops@heroku.com"]
|
7
|
-
gem.description = "
|
8
|
-
gem.summary = "
|
7
|
+
gem.description = "Notifications as a Gem"
|
8
|
+
gem.summary = "Notifications as a Gem"
|
9
9
|
gem.homepage = ""
|
10
10
|
|
11
11
|
gem.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
@@ -16,5 +16,9 @@ Gem::Specification.new do |gem|
|
|
16
16
|
gem.version = Comsat::VERSION
|
17
17
|
|
18
18
|
gem.add_runtime_dependency('rest-client')
|
19
|
+
gem.add_runtime_dependency('scrolls')
|
19
20
|
gem.add_runtime_dependency('tinder')
|
21
|
+
|
22
|
+
gem.add_development_dependency('rake')
|
23
|
+
gem.add_development_dependency('rspec')
|
20
24
|
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'cgi'
|
2
|
+
require 'ostruct'
|
3
|
+
require 'uri'
|
4
|
+
|
5
|
+
module Comsat
|
6
|
+
module AuthHelper
|
7
|
+
|
8
|
+
def self.parse(url)
|
9
|
+
parse_url(url)
|
10
|
+
OpenStruct.new(to_hash)
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.parse_url(url)
|
14
|
+
@uri = URI.parse(url)
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.to_hash
|
18
|
+
{
|
19
|
+
:name => @uri.scheme,
|
20
|
+
:api_key => @uri.user,
|
21
|
+
:username => @uri.user,
|
22
|
+
:password => @uri.password,
|
23
|
+
:host => @uri.host,
|
24
|
+
:scope => CGI.unescape(@uri.path.gsub(/\A\//, ''))
|
25
|
+
}
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
data/lib/comsat/log.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
module Comsat
|
2
|
+
module Log
|
3
|
+
def self.start
|
4
|
+
Scrolls::Log.start
|
5
|
+
log(ns: "log", fn: "start")
|
6
|
+
end
|
7
|
+
|
8
|
+
def self.merge(data1, data2)
|
9
|
+
data1.merge(data2)
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.log(data, &blk)
|
13
|
+
Scrolls.log(merge({app: "comsat"}, data), &blk)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
data/lib/comsat/route.rb
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
module Comsat
|
2
|
+
class Route
|
3
|
+
attr_accessor :name, :services, :event_type
|
4
|
+
|
5
|
+
def initialize(route, et, urls)
|
6
|
+
@name = route
|
7
|
+
@event_type = et if %w(alert notice resolve).include?(et)
|
8
|
+
@services = []
|
9
|
+
urls.each do |url|
|
10
|
+
svc = ServiceFactory.create(url)
|
11
|
+
if svc.respond_to?("send_#{@event_type}")
|
12
|
+
@services << svc
|
13
|
+
else
|
14
|
+
next
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def to_s
|
20
|
+
"#<#{self.class} @name='#{@name}', @event='#{@event_type}', @services=#{@services.each {|s| s.to_s }}>"
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module Comsat
|
2
|
+
module Service
|
3
|
+
class Base
|
4
|
+
attr_reader :credentials
|
5
|
+
|
6
|
+
def initialize(url)
|
7
|
+
@credentials = Comsat::AuthHelper.parse(url)
|
8
|
+
end
|
9
|
+
|
10
|
+
def to_s
|
11
|
+
"#<#{self.class} @host='#{@credentials.host}', @scope='#{@credentials.scope}'>"
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module Comsat
|
2
|
+
class Campfire < Service::Base
|
3
|
+
def send_notice(data)
|
4
|
+
# {:messages, :source, :message_id}
|
5
|
+
messages = []
|
6
|
+
messages << "[#{data[:source]}] #{data[:message]}"
|
7
|
+
send_message(messages)
|
8
|
+
end
|
9
|
+
alias :send_alert :send_notice
|
10
|
+
alias :send_resolve :send_notice
|
11
|
+
|
12
|
+
private
|
13
|
+
|
14
|
+
def send_message(msgs)
|
15
|
+
unless room = find_room
|
16
|
+
raise "Unable to find room"
|
17
|
+
end
|
18
|
+
Array(msgs).each {|line| room.speak line }
|
19
|
+
end
|
20
|
+
|
21
|
+
def campfire
|
22
|
+
@campfire = ::Tinder::Campfire.new(
|
23
|
+
@credentials.host.split('.')[0],
|
24
|
+
:ssl => true,
|
25
|
+
:token => @credentials.api_key
|
26
|
+
)
|
27
|
+
end
|
28
|
+
|
29
|
+
def find_room
|
30
|
+
campfire.find_room_by_name(@credentials.scope)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Comsat
|
2
|
+
class PagerDuty < Service::Base
|
3
|
+
PAGERDUTY_ENDPOINT = 'https://events.pagerduty.com/generic/2010-04-15/create_event.json'
|
4
|
+
|
5
|
+
def send_notice(data)
|
6
|
+
contact_pagerduty(:trigger, data)
|
7
|
+
end
|
8
|
+
alias :send_alert :send_notice
|
9
|
+
|
10
|
+
def send_resolve(data)
|
11
|
+
contact_pagerduty(:resolve, data)
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
def contact_pagerduty(event_type, data)
|
17
|
+
id = data[:message_id] || SecureRandom.uuid
|
18
|
+
message = data[:message]
|
19
|
+
source = data[:source]
|
20
|
+
message = "#{source}: #{message}"
|
21
|
+
|
22
|
+
data = {
|
23
|
+
:service_key => @credentials.api_key,
|
24
|
+
:incident_key => id,
|
25
|
+
:event_type => event_type,
|
26
|
+
:description => message
|
27
|
+
}
|
28
|
+
RestClient.post PAGERDUTY_ENDPOINT, data.to_json, :content_type => :json
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
data/lib/comsat/version.rb
CHANGED
data/lib/comsat.rb
CHANGED
@@ -1,107 +1,82 @@
|
|
1
1
|
require "cgi"
|
2
|
-
require "comsat/version"
|
3
2
|
require "json"
|
4
3
|
require "rest_client"
|
4
|
+
require "scrolls"
|
5
5
|
require "securerandom"
|
6
|
+
|
7
|
+
# Service includes
|
6
8
|
require "tinder"
|
7
9
|
|
10
|
+
require "comsat/log"
|
11
|
+
require "comsat/route"
|
12
|
+
require "comsat/service"
|
13
|
+
require "comsat/version"
|
14
|
+
|
15
|
+
require "comsat/helpers/auth_helper"
|
16
|
+
|
17
|
+
require "comsat/services/campfire"
|
18
|
+
require "comsat/services/pagerduty"
|
19
|
+
|
8
20
|
module Comsat
|
9
21
|
class Client
|
10
|
-
def initialize(urls)
|
11
|
-
@urls = urls
|
12
|
-
end
|
13
22
|
|
14
|
-
|
15
|
-
@urls.each do |url|
|
16
|
-
ServiceFactory.create(url).send_notice(data)
|
17
|
-
end
|
18
|
-
end
|
23
|
+
attr_accessor :routes
|
19
24
|
|
20
|
-
def
|
21
|
-
|
22
|
-
ServiceFactory.create(url).send_alert(data)
|
23
|
-
end
|
25
|
+
def initialize
|
26
|
+
@@routes = []
|
24
27
|
end
|
25
28
|
|
26
|
-
def
|
27
|
-
|
28
|
-
ServiceFactory.create(url).send_resolve(data)
|
29
|
-
end
|
29
|
+
def routes
|
30
|
+
@@routes
|
30
31
|
end
|
31
|
-
end
|
32
32
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
case uri.scheme
|
37
|
-
when 'campfire'
|
38
|
-
Campfire.new(uri)
|
39
|
-
when 'pagerduty'
|
40
|
-
PagerDuty.new(uri)
|
33
|
+
def create_route(route, event_type, services)
|
34
|
+
unless routes.detect {|r| r.name == route }
|
35
|
+
routes << Route.new(route, event_type, services)
|
41
36
|
end
|
42
37
|
end
|
43
|
-
end
|
44
|
-
|
45
|
-
class Campfire
|
46
|
-
def initialize(uri)
|
47
|
-
@acct = uri.host.split('.')[0]
|
48
|
-
@api_key = uri.user
|
49
|
-
@room = CGI.unescape(uri.path.gsub(/\A\//, ''))
|
50
|
-
end
|
51
|
-
|
52
|
-
def send_notice(data)
|
53
|
-
# {:messages, :source, :message_id}
|
54
|
-
messages = []
|
55
|
-
messages << "[#{data[:source]}] #{data[:message]}"
|
56
|
-
send_message(messages)
|
57
|
-
end
|
58
|
-
alias :send_alert :send_notice
|
59
|
-
alias :send_resolve :send_notice
|
60
38
|
|
61
|
-
def
|
62
|
-
|
63
|
-
|
39
|
+
def notify(route, message={})
|
40
|
+
notify_route = @@routes.detect {|r| r.name == route } if message
|
41
|
+
event = notify_route.event_type
|
42
|
+
notify_route.services.each do |svc|
|
43
|
+
svc.send("send_#{event}".to_sym, message)
|
64
44
|
end
|
65
|
-
Array(msgs).each {|line| room.speak line }
|
66
45
|
end
|
67
46
|
|
68
|
-
def
|
69
|
-
|
70
|
-
@acct,
|
71
|
-
:ssl => true,
|
72
|
-
:token => @api_key
|
73
|
-
)
|
47
|
+
def send_notice(data)
|
48
|
+
send_event(:notice, data)
|
74
49
|
end
|
75
50
|
|
76
|
-
def
|
77
|
-
|
51
|
+
def send_alert(data)
|
52
|
+
send_event(:alert, data)
|
78
53
|
end
|
79
|
-
end
|
80
54
|
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
def initialize(uri)
|
85
|
-
@api_key = uri.user
|
55
|
+
def send_resolve(data)
|
56
|
+
send_event(:resolve, data)
|
86
57
|
end
|
87
58
|
|
88
|
-
|
89
|
-
id = data[:message_id] || SecureRandom.uuid
|
90
|
-
message = data[:message]
|
91
|
-
source = data[:source]
|
92
|
-
message = "#{source}: #{message}"
|
59
|
+
private
|
93
60
|
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
61
|
+
def send_event(event_type, data)
|
62
|
+
@urls.each do |url|
|
63
|
+
service = ServiceFactory.create(url)
|
64
|
+
if service.respond_to?("send_#{event_type}")
|
65
|
+
service.send("send_#{event_type}".to_sym, data)
|
66
|
+
else
|
67
|
+
next
|
68
|
+
end
|
69
|
+
end
|
100
70
|
end
|
101
|
-
|
71
|
+
end
|
102
72
|
|
103
|
-
|
104
|
-
|
73
|
+
class ServiceFactory
|
74
|
+
def self.create(url)
|
75
|
+
svc_name = URI.parse(url).scheme
|
76
|
+
if Comsat.const_defined?(svc_name.capitalize)
|
77
|
+
svc = Comsat.const_get(svc_name.capitalize)
|
78
|
+
svc.new(url)
|
79
|
+
end
|
105
80
|
end
|
106
81
|
end
|
107
82
|
end
|
data/spec/client_spec.rb
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Comsat::Client do
|
4
|
+
subject { described_class.new }
|
5
|
+
let(:undefined_svc) { "svc://api_key:X@host/scope" }
|
6
|
+
let(:defined_svc) { "campfire://api_key:X@blossom.campfirenow.com/scope" }
|
7
|
+
|
8
|
+
describe "#routes" do
|
9
|
+
it "has zero routes configured by default" do
|
10
|
+
subject.routes.should be_empty
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
describe "#create_route" do
|
15
|
+
before do
|
16
|
+
subject.create_route("test_route", "notice", [undefined_svc, defined_svc])
|
17
|
+
end
|
18
|
+
|
19
|
+
it "should register a route with base class" do
|
20
|
+
subject.routes.should_not be_empty
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should create a route" do
|
24
|
+
subject.routes.first.name.should == "test_route"
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should have one service initiated" do
|
28
|
+
subject.routes.first.services.length.should == 1
|
29
|
+
end
|
30
|
+
|
31
|
+
it "should have a campfire service initiated" do
|
32
|
+
subject.routes.first.services.first.class.should == Comsat::Campfire
|
33
|
+
end
|
34
|
+
|
35
|
+
it "should provide an event type" do
|
36
|
+
subject.routes.first.event_type == "notice"
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Comsat::Service::Base do
|
4
|
+
let(:unsupported) { "svc://api_key:X@host/scope" }
|
5
|
+
subject { described_class.new(unsupported) }
|
6
|
+
|
7
|
+
it "should provide credentials in an object" do
|
8
|
+
subject.credentials.class.should == OpenStruct
|
9
|
+
end
|
10
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
CHANGED
@@ -1,20 +1,20 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: comsat
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
|
-
-
|
9
|
-
-
|
8
|
+
- Curt Micol
|
9
|
+
- Michael Gorsuch
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2012-04-
|
13
|
+
date: 2012-04-11 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: rest-client
|
17
|
-
requirement: &
|
17
|
+
requirement: &70287816065340 !ruby/object:Gem::Requirement
|
18
18
|
none: false
|
19
19
|
requirements:
|
20
20
|
- - ! '>='
|
@@ -22,10 +22,21 @@ dependencies:
|
|
22
22
|
version: '0'
|
23
23
|
type: :runtime
|
24
24
|
prerelease: false
|
25
|
-
version_requirements: *
|
25
|
+
version_requirements: *70287816065340
|
26
|
+
- !ruby/object:Gem::Dependency
|
27
|
+
name: scrolls
|
28
|
+
requirement: &70287816064720 !ruby/object:Gem::Requirement
|
29
|
+
none: false
|
30
|
+
requirements:
|
31
|
+
- - ! '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: *70287816064720
|
26
37
|
- !ruby/object:Gem::Dependency
|
27
38
|
name: tinder
|
28
|
-
requirement: &
|
39
|
+
requirement: &70287816064080 !ruby/object:Gem::Requirement
|
29
40
|
none: false
|
30
41
|
requirements:
|
31
42
|
- - ! '>='
|
@@ -33,8 +44,30 @@ dependencies:
|
|
33
44
|
version: '0'
|
34
45
|
type: :runtime
|
35
46
|
prerelease: false
|
36
|
-
version_requirements: *
|
37
|
-
|
47
|
+
version_requirements: *70287816064080
|
48
|
+
- !ruby/object:Gem::Dependency
|
49
|
+
name: rake
|
50
|
+
requirement: &70287816063540 !ruby/object:Gem::Requirement
|
51
|
+
none: false
|
52
|
+
requirements:
|
53
|
+
- - ! '>='
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: '0'
|
56
|
+
type: :development
|
57
|
+
prerelease: false
|
58
|
+
version_requirements: *70287816063540
|
59
|
+
- !ruby/object:Gem::Dependency
|
60
|
+
name: rspec
|
61
|
+
requirement: &70287816063020 !ruby/object:Gem::Requirement
|
62
|
+
none: false
|
63
|
+
requirements:
|
64
|
+
- - ! '>='
|
65
|
+
- !ruby/object:Gem::Version
|
66
|
+
version: '0'
|
67
|
+
type: :development
|
68
|
+
prerelease: false
|
69
|
+
version_requirements: *70287816063020
|
70
|
+
description: Notifications as a Gem
|
38
71
|
email:
|
39
72
|
- ops@heroku.com
|
40
73
|
executables: []
|
@@ -48,7 +81,16 @@ files:
|
|
48
81
|
- Rakefile
|
49
82
|
- comsat.gemspec
|
50
83
|
- lib/comsat.rb
|
84
|
+
- lib/comsat/helpers/auth_helper.rb
|
85
|
+
- lib/comsat/log.rb
|
86
|
+
- lib/comsat/route.rb
|
87
|
+
- lib/comsat/service.rb
|
88
|
+
- lib/comsat/services/campfire.rb
|
89
|
+
- lib/comsat/services/pagerduty.rb
|
51
90
|
- lib/comsat/version.rb
|
91
|
+
- spec/client_spec.rb
|
92
|
+
- spec/service_spec.rb
|
93
|
+
- spec/spec_helper.rb
|
52
94
|
homepage: ''
|
53
95
|
licenses: []
|
54
96
|
post_install_message:
|
@@ -72,5 +114,8 @@ rubyforge_project:
|
|
72
114
|
rubygems_version: 1.8.11
|
73
115
|
signing_key:
|
74
116
|
specification_version: 3
|
75
|
-
summary:
|
76
|
-
test_files:
|
117
|
+
summary: Notifications as a Gem
|
118
|
+
test_files:
|
119
|
+
- spec/client_spec.rb
|
120
|
+
- spec/service_spec.rb
|
121
|
+
- spec/spec_helper.rb
|