comsat 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
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(["campfire://<api_key>:X@blossom.campfirenow.com/Test%20Room"])
60
- client.send_notice({:message => "message here", :source => "nagios", :message_id => "unique_id"})
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
@@ -1,2 +1,8 @@
1
- #!/usr/bin/env rake
2
- require "bundler/gem_tasks"
1
+ begin
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
7
+ rescue LoadError
8
+ end
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 = ["curt@heroku.com", "gorsuch@heroku.com"]
5
+ gem.authors = ["Curt Micol", "Michael Gorsuch"]
6
6
  gem.email = ["ops@heroku.com"]
7
- gem.description = "Early notification gem"
8
- gem.summary = "Early notification gem"
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
@@ -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
@@ -1,3 +1,3 @@
1
1
  module Comsat
2
- VERSION = "0.0.1"
2
+ VERSION = "0.0.2"
3
3
  end
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
- def send_notice(data)
15
- @urls.each do |url|
16
- ServiceFactory.create(url).send_notice(data)
17
- end
18
- end
23
+ attr_accessor :routes
19
24
 
20
- def send_alert(data)
21
- @urls.each do |url|
22
- ServiceFactory.create(url).send_alert(data)
23
- end
25
+ def initialize
26
+ @@routes = []
24
27
  end
25
28
 
26
- def send_resolve(data)
27
- @urls.each do |url|
28
- ServiceFactory.create(url).send_resolve(data)
29
- end
29
+ def routes
30
+ @@routes
30
31
  end
31
- end
32
32
 
33
- class ServiceFactory
34
- def self.create(url)
35
- uri = URI.parse(url)
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 send_message(msgs)
62
- unless room = find_room
63
- raise "Unable to find room"
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 campfire
69
- @campfire = ::Tinder::Campfire.new(
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 find_room
77
- campfire.find_room_by_name(@room)
51
+ def send_alert(data)
52
+ send_event(:alert, data)
78
53
  end
79
- end
80
54
 
81
- class PagerDuty
82
- ENDPOINT = 'https://events.pagerduty.com/generic/2010-04-15/create_event.json'
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
- def contact_pagerduty(event_type, data)
89
- id = data[:message_id] || SecureRandom.uuid
90
- message = data[:message]
91
- source = data[:source]
92
- message = "#{source}: #{message}"
59
+ private
93
60
 
94
- data = { :service_key => @api_key, :incident_key => id, :event_type => event_type, :description => message }
95
- RestClient.post ENDPOINT, data.to_json, :content_type => :json
96
- end
97
-
98
- def send_notice(data)
99
- contact_pagerduty(:trigger, data)
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
- alias :send_alert :send_notice
71
+ end
102
72
 
103
- def send_resolve(data)
104
- contact_pagerduty(:resolve, data)
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
@@ -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
@@ -0,0 +1,6 @@
1
+ $: << File.expand_path("../../lib", __FILE__)
2
+
3
+ require 'comsat'
4
+
5
+ RSpec.configure do |c|
6
+ end
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.1
4
+ version: 0.0.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
8
- - curt@heroku.com
9
- - gorsuch@heroku.com
8
+ - Curt Micol
9
+ - Michael Gorsuch
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2012-04-10 00:00:00.000000000 Z
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: &70113286660760 !ruby/object:Gem::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: *70113286660760
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: &70113286659660 !ruby/object:Gem::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: *70113286659660
37
- description: Early notification gem
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: Early notification gem
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