lita-pagerduty 1.0.0 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 1fa275bada173401c6fdac456b713176375ae8f5
4
- data.tar.gz: 410ca4278874a6cd332f9e134d982a3f7830c80a
3
+ metadata.gz: 4a28972f5fc4c637f95ea379c642402c8857feca
4
+ data.tar.gz: 2e2622aacc42cdaa1140447a83ad253c6423e2e3
5
5
  SHA512:
6
- metadata.gz: af72dc0772235f9202fc14ebabe43594a56bd2782a4e432b92424e2984383d083cf77e9aa84dd2d561f7716d8a63f7d34e96df9f93877baa9f6ba51beb548727
7
- data.tar.gz: f65a55fb1c4802f2ec3420b0e3af35ee4ed24bd779849f6107f53826fbface9241d2b7b6f0b46807c190bf11f2cd39d2709939b52ca50a2659dc0298bec223ee
6
+ metadata.gz: 0730876673981ee24e02c9a1c00f45bd0689de3bb4ffb06fb4506cb730f1f04c77c55b5fc0c70ba36b998ff10992a14ea54bbe0bf76683ca1741c7cf46adb8c7
7
+ data.tar.gz: 44bfee93a0e97ac22c1d1700cd5f4be54f0e1be66e9d22c1be155212bcf40fbe0c5b39d1e876caad6f84065840d85aa9a75a5f7273ba79dbcc2e37dea06c5083
data/.gitignore CHANGED
@@ -1,3 +1,4 @@
1
+ .ruby-version
1
2
  *.gem
2
3
  *.rbc
3
4
  *.swp
data/README.md CHANGED
@@ -13,21 +13,28 @@ A [PagerDuty](http://pagerduty.com) plugin for [Lita](https://github.com/jimmycu
13
13
 
14
14
  Add lita-pagerduty to your Lita instance's Gemfile:
15
15
 
16
- ``` ruby
16
+ ```ruby
17
17
  gem "lita-pagerduty"
18
18
  ```
19
19
 
20
20
  ## Configuration
21
21
 
22
- Create a PagerDuty api Key(v1 legacy) You will need to give it FullAccess to update incidents
22
+ Create a PagerDuty API key (v2). You will need to give it FullAccess to update incidents.
23
23
 
24
24
  Add the following variables to your Lita config file:
25
25
 
26
- ``` ruby
26
+ ```ruby
27
27
  config.handlers.pagerduty.api_key = ''
28
28
  config.handlers.pagerduty.email = ''
29
29
  ```
30
30
 
31
+ If your account has the teams capability and you want to scope Lita's access to a specific set of
32
+ teams, you can set the list of teams by adding the following to your config file:
33
+
34
+ ```ruby
35
+ config..handlers.pagerduty.teams = [ "team-a", "team-b" ]
36
+ ```
37
+
31
38
  ## Usage
32
39
 
33
40
  ### Misc
@@ -1,14 +1,16 @@
1
1
  require 'lita'
2
+
3
+ Lita.load_locales Dir[File.expand_path(
4
+ File.join('..', '..', 'locales', '*.yml'), __FILE__
5
+ )]
6
+
2
7
  require 'exceptions'
3
8
  require 'pagerduty'
4
9
  require 'store'
5
10
  require 'lita/handlers/pagerduty'
6
11
  require 'lita/commands/base'
7
- Dir[File.join(__dir__, 'lita', 'commands', '*.rb')].each { |file| require file }
8
12
 
9
- Lita.load_locales Dir[File.expand_path(
10
- File.join('..', '..', 'locales', '*.yml'), __FILE__
11
- )]
13
+ Dir[File.join(__dir__, 'lita', 'commands', '*.rb')].each { |file| require file }
12
14
 
13
15
  Lita::Handlers::Pagerduty.template_root File.expand_path(
14
16
  File.join('..', '..', 'templates'), __FILE__
@@ -65,7 +65,12 @@ module Commands
65
65
  end
66
66
 
67
67
  def pagerduty
68
- @pagerduty ||= ::Pagerduty.new(http, config.api_key, config.email)
68
+ @pagerduty ||= ::Pagerduty.new(
69
+ http,
70
+ config.api_key,
71
+ config.email,
72
+ config.teams
73
+ )
69
74
  end
70
75
 
71
76
  def store
@@ -4,6 +4,7 @@ module Lita
4
4
  namespace 'Pagerduty'
5
5
  config :api_key, required: true
6
6
  config :email, required: true
7
+ config :teams, required: false
7
8
 
8
9
  COMMANDS_PATH = File.read("#{File.dirname(__FILE__)}/commands.yml")
9
10
  COMMANDS = YAML.safe_load(COMMANDS_PATH)
@@ -13,8 +14,8 @@ module Lita
13
14
  command['method'].to_sym,
14
15
  command: true,
15
16
  help: {
16
- "help.#{command['method']}.syntax" =>
17
- "help.#{command['method']}.desc"
17
+ t("help.#{command['method']}.syntax") =>
18
+ t("help.#{command['method']}.desc")
18
19
  }
19
20
  )
20
21
  end
@@ -32,7 +33,12 @@ module Lita
32
33
  end
33
34
 
34
35
  def pagerduty
35
- @pagerduty ||= ::Pagerduty.new(http, config.api_key, config.email)
36
+ @pagerduty ||= ::Pagerduty.new(
37
+ http,
38
+ config.api_key,
39
+ config.email,
40
+ config.teams
41
+ )
36
42
  end
37
43
 
38
44
  def store
@@ -1,57 +1,54 @@
1
1
  class Pagerduty
2
- def initialize(http, token, email)
3
- @token = token
2
+ attr_reader :http, :teams
3
+
4
+ def initialize(http, token, email, teams = [])
4
5
  @http = http
6
+ @teams = teams || []
7
+
5
8
  http.url_prefix = 'https://api.pagerduty.com/'
6
- http.headers = headers(email)
9
+ http.headers = auth_headers(email, token)
7
10
  end
8
11
 
9
12
  def get_incidents(params = {})
10
- response = @http.get '/incidents', params
11
- data = JSON.parse(response.body, symbolize_names: true)
12
- .fetch(:incidents, [])
13
+ data = get_resources(:incidents, params)
13
14
  raise Exceptions::IncidentsEmptyList if data.empty?
14
15
 
15
16
  data
16
17
  end
17
18
 
18
19
  def get_users(params = {})
19
- response = @http.get '/users', params
20
- data = JSON.parse(response.body, symbolize_names: true).fetch(:users, [])
20
+ data = get_resources(:users, params)
21
21
  raise Exceptions::UsersEmptyList if data.empty?
22
22
 
23
23
  data
24
24
  end
25
25
 
26
26
  def get_schedules(params = {})
27
- response = @http.get '/schedules', params
28
- data = JSON.parse(response.body, symbolize_names: true)
29
- .fetch(:schedules, [])
27
+ data = get_resources(:schedules, params)
30
28
  raise Exceptions::SchedulesEmptyList if data.empty?
31
29
 
32
30
  data
33
31
  end
34
32
 
35
33
  def get_oncall_user(params = {})
36
- response = @http.get '/oncalls', params
37
- data = JSON.parse(response.body, symbolize_names: true).fetch(:oncalls, [])
34
+ data = get_resources(:oncalls, params)
38
35
  raise Exceptions::NoOncallUser if data.empty?
39
36
 
40
37
  data.first.fetch(:user)
41
38
  end
42
39
 
43
40
  def get_incident(id = '404stub')
44
- response = @http.get "/incidents/#{id}"
41
+ response = http.get "/incidents/#{id}"
45
42
  raise Exceptions::IncidentNotFound if response.status == 404
46
43
 
47
- JSON.parse(response.body, symbolize_names: true).fetch(:incident, nil)
44
+ parse_json_response(response, :incident)
48
45
  end
49
46
 
50
47
  def get_notes_by_incident_id(incident_id)
51
- response = @http.get "/incidents/#{incident_id}/notes"
48
+ response = http.get "/incidents/#{incident_id}/notes"
52
49
  raise Exceptions::IncidentNotFound if response.status == 404
53
50
 
54
- data = JSON.parse(response.body, symbolize_names: true).fetch(:notes, [])
51
+ data = parse_json_response(response, :notes, [])
55
52
  raise Exceptions::NotesEmptyList if data.empty?
56
53
 
57
54
  data
@@ -62,33 +59,60 @@ class Pagerduty
62
59
  { id: id, type: 'incident_reference', status: "#{action}d" }
63
60
  end
64
61
  payload = { incidents: incidents }
65
- response = @http.put '/incidents', payload
62
+ response = http.put '/incidents', payload
66
63
  raise Exceptions::IncidentManageUnsuccess if response.status != 200
67
64
 
68
65
  response
69
66
  end
70
67
 
71
68
  def override(schedule_id, user_id, minutes)
72
- from = ::Time.now.utc + 10
73
- to = from + (60 * minutes)
74
- payload = { override: {
75
- start: from.iso8601,
76
- end: to.iso8601,
77
- user: { id: user_id, type: 'user_reference' }
78
- } }
79
- response = @http.post "/schedules/#{schedule_id}/overrides", payload
69
+ payload = override_payload(user_id, minutes)
70
+ response = http.post("/schedules/#{schedule_id}/overrides", payload)
80
71
  raise Exceptions::OverrideUnsuccess if response.status != 201
81
72
 
82
- JSON.parse(response.body, symbolize_names: true).fetch(:override, nil)
73
+ parse_json_response(response, :override)
83
74
  end
84
75
 
85
76
  private
86
77
 
87
- def headers(email)
78
+ def auth_headers(email, token)
88
79
  {
89
80
  'Accept' => 'application/vnd.pagerduty+json;version=2',
90
- 'Authorization' => "Token token=#{@token}",
81
+ 'Authorization' => "Token token=#{token}",
91
82
  'From' => email
92
83
  }
93
84
  end
85
+
86
+ # Fetches a list of resources from a given collection using Pagerduty REST API
87
+ def get_resources(collection_name, params = {})
88
+ # Scope down to a single team
89
+ params[:team_ids] = teams if teams.any?
90
+
91
+ # Get the resources
92
+ response = http.get("/#{collection_name}", params)
93
+
94
+ # Parse the reponse and get the objects from the collection
95
+ parse_json_response(response, collection_name, [])
96
+ end
97
+
98
+ # Parses a JSON response and fetches a specific key from it
99
+ def parse_json_response(response, response_key, default_value = nil)
100
+ data = JSON.parse(response.body, symbolize_names: true)
101
+ data.fetch(response_key, default_value)
102
+ end
103
+
104
+ # Returns a payload for overriding a schedule and putting the user
105
+ # identified by +user_id+ on-call for the period defined by +minutes+
106
+ def override_payload(user_id, minutes)
107
+ # start 10 sec from now
108
+ from = ::Time.now.utc + 10
109
+ to = from + (60 * minutes)
110
+
111
+ {
112
+ override: {
113
+ start: from.iso8601, end: to.iso8601,
114
+ user: { id: user_id, type: 'user_reference' }
115
+ }
116
+ }
117
+ end
94
118
  end
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |spec|
2
2
  spec.name = 'lita-pagerduty'
3
- spec.version = '1.0.0'
3
+ spec.version = '1.1.0'
4
4
  spec.authors = ['Eric Sigler']
5
5
  spec.email = ['eric@pagerduty.com']
6
6
  spec.description = 'A Lita handler to interact with PagerDuty'
@@ -2,9 +2,10 @@ require 'spec_helper'
2
2
 
3
3
  describe Pagerduty do
4
4
  let(:http) { double }
5
- let(:pagerduty) { Pagerduty.new(http, 'token', 'email') }
5
+ let(:teams) { nil }
6
+ let(:pagerduty) { Pagerduty.new(http, 'token', 'email', teams) }
6
7
 
7
- before :each do
8
+ before do
8
9
  expect(http).to receive(:url_prefix=).with('https://api.pagerduty.com/')
9
10
  expect(http).to receive(:headers=).with({
10
11
  'Accept' => 'application/vnd.pagerduty+json;version=2',
@@ -13,86 +14,127 @@ describe Pagerduty do
13
14
  })
14
15
  end
15
16
 
16
- it 'get_incidents' do
17
- expect(http).to receive(:get).with('/incidents', {}).and_return(
18
- OpenStruct.new(body: { incidents: [{id: 1}]}.to_json)
19
- )
20
- expect(pagerduty.get_incidents).to eq([{ id: 1 }])
17
+ def stub_response(response_hash)
18
+ OpenStruct.new(body: response_hash.to_json)
19
+ end
21
20
 
22
- expect(http).to receive(:get).with('/incidents', {}).and_return(
23
- OpenStruct.new(body: { incidents: []}.to_json)
24
- )
25
- expect{ pagerduty.get_incidents }.to raise_exception Exceptions::IncidentsEmptyList
21
+ def stub_collection_response(collection, params, response)
22
+ uri = "/#{collection}"
23
+ json = stub_response(collection => response)
24
+ expect(http).to receive(:get).with(uri, params).and_return(json)
26
25
  end
27
26
 
28
- it 'get_incident' do
29
- expect(http).to receive(:get).with('/incidents/ABC123').and_return(
30
- OpenStruct.new(body: { incident: {}}.to_json)
31
- )
32
- pagerduty.get_incident('ABC123')
27
+ #-------------------------------------------------------------------------------------------------
28
+ context "without teams filtering" do
29
+ it 'get_incidents' do
30
+ stub_collection_response(:incidents, {}, [{ id: 1 }])
31
+ expect(pagerduty.get_incidents).to eq([{ id: 1 }])
32
+
33
+ stub_collection_response(:incidents, {}, [])
34
+ expect{ pagerduty.get_incidents }.to raise_exception Exceptions::IncidentsEmptyList
35
+ end
36
+
37
+ it 'get_users' do
38
+ stub_collection_response(:users, {}, [{ id: 1 }])
39
+ expect(pagerduty.get_users).to eq [{ id: 1 }]
40
+
41
+ stub_collection_response(:users, {}, [])
42
+ expect{ pagerduty.get_users }.to raise_exception Exceptions::UsersEmptyList
43
+ end
44
+
45
+ it 'get_schedules' do
46
+ stub_collection_response(:schedules, {}, [{ id: 1 }])
47
+ expect(pagerduty.get_schedules).to eq [{ id: 1 }]
48
+
49
+ stub_collection_response(:schedules, {}, [])
50
+ expect{ pagerduty.get_schedules }.to raise_exception Exceptions::SchedulesEmptyList
51
+ end
52
+
53
+ it 'get_oncall_user' do
54
+ stub_collection_response(:oncalls, {}, [{ id: 1, user: 'abc' }])
55
+ expect(pagerduty.get_oncall_user).to eq('abc')
56
+
57
+ stub_collection_response(:oncalls, {}, [])
58
+ expect{ pagerduty.get_oncall_user }.to raise_exception Exceptions::NoOncallUser
59
+ end
33
60
  end
34
61
 
35
- it 'get_users' do
36
- expect(http).to receive(:get).with('/users', {}).and_return(
37
- OpenStruct.new(body: { users: [{ id: 1 }]}.to_json)
38
- )
39
- expect(pagerduty.get_users).to eq [{ id: 1 }]
62
+ #-------------------------------------------------------------------------------------------------
63
+ context "with teams filtering enabled" do
64
+ let(:teams) { [ 'team-a', 'team-b' ] }
65
+ let(:teams_filter) { { team_ids: teams } }
66
+
67
+ it 'get_incidents' do
68
+ stub_collection_response(:incidents, teams_filter, [{ id: 1 }])
69
+ expect(pagerduty.get_incidents).to eq([{ id: 1 }])
70
+
71
+ stub_collection_response(:incidents, teams_filter, [])
72
+ expect{ pagerduty.get_incidents }.to raise_exception Exceptions::IncidentsEmptyList
73
+ end
74
+
75
+ it 'get_users' do
76
+ stub_collection_response(:users, teams_filter, [{ id: 1 }])
77
+ expect(pagerduty.get_users).to eq [{ id: 1 }]
40
78
 
41
- expect(http).to receive(:get).with('/users', {}).and_return(
42
- OpenStruct.new(body: { users: []}.to_json)
79
+ stub_collection_response(:users, teams_filter, [])
80
+ expect{ pagerduty.get_users }.to raise_exception Exceptions::UsersEmptyList
81
+ end
82
+
83
+ it 'get_schedules' do
84
+ stub_collection_response(:schedules, teams_filter, [{ id: 1 }])
85
+ expect(pagerduty.get_schedules).to eq [{ id: 1 }]
86
+
87
+ stub_collection_response(:schedules, teams_filter, [])
88
+ expect{ pagerduty.get_schedules }.to raise_exception Exceptions::SchedulesEmptyList
89
+ end
90
+
91
+ it 'get_oncall_user' do
92
+ stub_collection_response(:oncalls, teams_filter, [{ id: 1, user: 'abc' }])
93
+ expect(pagerduty.get_oncall_user).to eq('abc')
94
+
95
+ stub_collection_response(:oncalls, teams_filter, [])
96
+ expect{ pagerduty.get_oncall_user }.to raise_exception Exceptions::NoOncallUser
97
+ end
98
+ end
99
+
100
+ #-------------------------------------------------------------------------------------------------
101
+ # Methods that do not change their semantics with teams filtering enabled
102
+ #-------------------------------------------------------------------------------------------------
103
+ it 'get_incident' do
104
+ expect(http).to receive(:get).with('/incidents/ABC123').and_return(
105
+ stub_response(incident: {})
43
106
  )
44
- expect{ pagerduty.get_users }.to raise_exception Exceptions::UsersEmptyList
107
+ pagerduty.get_incident('ABC123')
45
108
  end
46
109
 
47
110
  it 'get_notes_by_incident_id' do
48
111
  expect(http).to receive(:get).with('/incidents/ABC123/notes').and_return(
49
- OpenStruct.new(body: { notes: [{ id: 1 }]}.to_json)
112
+ stub_response(notes: [{ id: 1 }])
50
113
  )
51
114
  expect(pagerduty.get_notes_by_incident_id('ABC123')).to eq [{ id: 1 }]
52
115
 
53
116
  expect(http).to receive(:get).with('/incidents/ABC123/notes').and_return(
54
- OpenStruct.new(body: { notes: []}.to_json)
117
+ stub_response(notes: [])
55
118
  )
56
119
  expect{ pagerduty.get_notes_by_incident_id('ABC123') }.to raise_exception Exceptions::NotesEmptyList
57
120
  end
58
121
 
59
122
  it 'manage_incidents' do
60
- params = { incidents: [
61
- { id: 'a', status: 'acknowledged', type: 'incident_reference' },
62
- { id: 'b', status: 'acknowledged', type: 'incident_reference' }
63
- ]}
123
+ params = {
124
+ incidents: [
125
+ { id: 'a', status: 'acknowledged', type: 'incident_reference' },
126
+ { id: 'b', status: 'acknowledged', type: 'incident_reference' },
127
+ ]
128
+ }
64
129
  expect(http).to receive(:put).with('/incidents', params).and_return(
65
130
  OpenStruct.new(body: { users: [] }.to_json, status: 200)
66
131
  )
67
132
  pagerduty.manage_incidents(:acknowledge, ['a', 'b'])
68
133
  end
69
134
 
70
- it 'get_schedules' do
71
- expect(http).to receive(:get).with('/schedules', {}).and_return(
72
- OpenStruct.new(body: { schedules: [{ id: 1 }]}.to_json)
73
- )
74
- expect(pagerduty.get_schedules).to eq [{ id: 1 }]
75
-
76
- expect(http).to receive(:get).with('/schedules', {}).and_return(
77
- OpenStruct.new(body: { incidents: []}.to_json)
78
- )
79
- expect{ pagerduty.get_schedules }.to raise_exception Exceptions::SchedulesEmptyList
80
- end
81
-
82
- it 'get_oncall_user' do
83
- expect(http).to receive(:get).with('/oncalls', {}).and_return(
84
- OpenStruct.new(body: { oncalls: [{ id: 1, user: 'abc' }]}.to_json)
85
- )
86
- expect(pagerduty.get_oncall_user).to eq('abc')
87
-
88
- expect(http).to receive(:get).with('/oncalls', {}).and_return(
89
- OpenStruct.new(body: { incidents: []}.to_json)
90
- )
91
- expect{ pagerduty.get_oncall_user }.to raise_exception Exceptions::NoOncallUser
92
- end
93
135
 
94
136
  it 'override' do
95
- expect(Time).to receive(:now).and_return(Time.new(2000))
137
+ expect(Time).to receive(:now).and_return(Time.new(2000, 1, 1, 0, 0, 0, 0))
96
138
  params = { override: {
97
139
  end: '2000-01-01T00:01:10Z',
98
140
  start: '2000-01-01T00:00:10Z',
@@ -1,3 +1,6 @@
1
+ # We rely on timezone being in UTC
2
+ ENV['TZ'] = 'UTC'
3
+
1
4
  require 'simplecov'
2
5
  require 'coveralls'
3
6
  SimpleCov.formatters = [
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lita-pagerduty
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Eric Sigler
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-10-26 00:00:00.000000000 Z
11
+ date: 2019-03-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: lita