lita-pagerduty 1.0.0 → 1.1.0

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