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 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