pagerduty_utils 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 2734f9242e51882171cf33ec55745551f2ca150d
4
+ data.tar.gz: 82bc1e579955359c49ef711a768f9920239cd911
5
+ SHA512:
6
+ metadata.gz: fb9671f772b4516e211821437a326b46b81d1aa077b5ea5f0ee56493e04294be11d8830854e423103cfde5adfe1e58a8b7af035236b899620f603d72bf685262
7
+ data.tar.gz: aaa11e2a2934c29f44b3fc07f8a20cece9d43c080057385525f5df382007305883af1f41cb5f1e608f4399d968e0e738fa4cd413dd7e8abb53c3ba4139402957
data/bin/pgutils ADDED
@@ -0,0 +1,126 @@
1
+ #!/usr/bin/env ruby -w
2
+ require 'optparse'
3
+ require 'pagerduty/base'
4
+ require 'pagerduty/override'
5
+
6
+ def load_trigger(trigger_name)
7
+ config_file = "#{ENV['PAGERDUTY_CONFIG_DIR'] ? ENV['PAGERDUTY_CONFIG_DIR'] + 'triggers.yml' : ENV['HOME'] + '/.pgutils/triggers.yaml'}"
8
+ if File.readable?(config_file)
9
+ triggers = YAML.load_file(config_file)
10
+ else
11
+ abort("#{config_file} not found")
12
+ end
13
+ pg = TapJoy::PagerDuty::Base.new
14
+ puts pg.post_trigger(**triggers[trigger_name.to_sym])
15
+ end
16
+
17
+ def get_level_one_users(pg)
18
+ return pg.get_users_on_call['escalation_policies'].flat_map do |policy|
19
+ policy['on_call'].map do |oncall|
20
+ oncall['user']['id'] if oncall['start'] and oncall['level'] == 1
21
+ end.compact
22
+ end
23
+ end
24
+
25
+ options = {}
26
+
27
+ subtext = <<HELP
28
+ Supported commands are:
29
+ set_override :
30
+ trigger :
31
+ get_on_call :
32
+
33
+ See '#{File.basename(__FILE__)} COMMAND --help' for more information on a specific command.
34
+ HELP
35
+
36
+ global = OptionParser.new do |opts|
37
+ opts.banner = "Usage: #{File.basename(__FILE__)} [options] [subcommand [options]]"
38
+ opts.on("-v", "--[no-]verbose", "Run verbosely") do |v|
39
+ options[:verbose] = v
40
+ end
41
+ opts.separator ""
42
+ opts.separator subtext
43
+ end
44
+
45
+ subcommands = {
46
+ 'set_override' => OptionParser.new do |opts|
47
+ opts.banner = <<-EOS
48
+
49
+ Usage: #{File.basename(__FILE__)} set_override [options]
50
+
51
+ This code is used to temporarily override the primary person on-call for a given schedule.
52
+
53
+ EOS
54
+
55
+ opts.on('-e', '--email EMAIL', 'Specify email address of override user') do |e|
56
+ options[:email] = e
57
+ end
58
+ opts.on('-s', '--schedule-name SCHEDULE', 'Name of schedule to override') do |s|
59
+ options[:schedule_name] = s
60
+ end
61
+ opts.on('-t', '--override-length TIME', 'Number of seconds to maintain override for') do |t|
62
+ options[:override_length] = t.to_i
63
+ end
64
+ end,
65
+
66
+ 'trigger' => OptionParser.new do |opts|
67
+ opts.banner = <<-EOS
68
+
69
+ Usage: #{File.basename(__FILE__)} trigger [options]
70
+
71
+ This script will create a pagerduty alert, based on the name of the trigger
72
+ hash as specified in 'triggers.yaml'
73
+
74
+ EOS
75
+
76
+ opts.on("-t", "--trigger TRIGGER", 'Name of trigger to alert on') do |t|
77
+ options[:trigger] = t
78
+ end
79
+ end,
80
+
81
+ 'get_on_call' => OptionParser.new do |opts|
82
+ opts.banner = <<-EOS
83
+
84
+ Usage: #{File.basename(__FILE__)} get_on_call
85
+
86
+ This script will return the list of each person on-call sorted by schedule.
87
+ There are no options available for this command at this time.
88
+
89
+ EOS
90
+ end
91
+ }
92
+
93
+ global.order!
94
+ command = ARGV.shift
95
+ begin
96
+ subcommands[command].order!
97
+ rescue NoMethodError
98
+ abort("Invalid Input.\n\n#{subtext}")
99
+ end
100
+
101
+ case command
102
+ when 'trigger'
103
+ raise OptionParser::MissingArgument if options[:trigger].nil?
104
+ load_trigger(options[:trigger])
105
+ when 'set_override'
106
+ raise OptionParser::MissingArgument if options[:email].nil?
107
+ options[:schedule_name] = 'Default' if options[:schedule_name].nil?
108
+ options[:override_length] = 3600 if options[:override_length].nil?
109
+ TapJoy::PagerDuty::Override.new(options[:email], options[:schedule_name], options[:override_length])
110
+ when 'get_on_call'
111
+ pg = TapJoy::PagerDuty::Base.new
112
+ get_level_one_users(pg).each do |u|
113
+ user = pg.get_user_details(u)['user']
114
+ on_call = user['on_call']
115
+ puts "Name: #{user['name']}"
116
+ on_call.each do |oc|
117
+ puts "\tGroup: #{oc['escalation_policy']['name']}"
118
+ puts "\tStart: #{oc['start']}"
119
+ puts "\tEnd: #{oc['end']}"
120
+ puts "\n"
121
+ end
122
+ puts '---'
123
+ end
124
+ else
125
+ abort("Unknown command: #{command}")
126
+ end
@@ -0,0 +1,133 @@
1
+ require 'httparty'
2
+ require 'json'
3
+ require 'yaml'
4
+
5
+ module TapJoy
6
+ module PagerDuty; end
7
+ end
8
+
9
+ class TapJoy::PagerDuty::Base
10
+
11
+ # Initializer services to import values from pg_connect.yaml
12
+ # to configure organization-specific values (currently, subdomain and api_token)
13
+ def initialize
14
+ config_file = "#{ENV['PAGERDUTY_CONFIG_DIR'] ? ENV['PAGERDUTY_CONFIG_DIR'] + 'triggers.yml' : ENV['HOME'] + '/.pgutils/triggers.yaml'}"
15
+ pg_conn = YAML.load_file(config_file) if File.readable?(config_file)
16
+
17
+ @AUTH_HEADER = {
18
+ :subdomain => ENV['PAGERDUTY_SUBDOMAIN'] || pg_conn[:subdomain],
19
+ :token_string => "Token token=#{ENV['PAGERDUTY_API_TOKEN'] || pg_conn[:api_token]}"
20
+ }
21
+
22
+ raise 'Missing subdomain value' if @AUTH_HEADER[:subdomain].nil?
23
+ raise 'Missing API token' if @AUTH_HEADER[:token_string].nil?
24
+ end
25
+
26
+ # Given an email address return the user_id that pagerduty uses for lookups
27
+ def get_user_id(email)
28
+ endpoint = return_pagerduty_url(:users)
29
+ out_array = get_object(endpoint)['users'].select { |i| i['email'].eql?(email) }
30
+ return Hash[*out_array]['id']
31
+ end
32
+
33
+ # Given the name of a schedule return the schedule_id that pagerduty uses for lookups
34
+ def get_schedule_id(schedule_name)
35
+ endpoint = return_pagerduty_url(:schedules)
36
+ out_array = get_object(endpoint)['schedules'].select { |i| i['name'].eql?(schedule_name)}
37
+ return Hash[*out_array]['id']
38
+ end
39
+
40
+ # The set_override method takes in several variables and returns
41
+ # the REST response upon (attempting) completion of an override action
42
+ def set_override(query_start:, query_end:, override_start:, override_end:,
43
+ user_id:, schedule_id:)
44
+ # Ruby 2.x style kw-args is required here to make hash passing easier
45
+
46
+ endpoint = "#{return_pagerduty_url(:schedules)}/#{schedule_id}/overrides?since=#{query_start}&until=#{query_end}"
47
+
48
+ data = {
49
+ override: {
50
+ user_id: user_id,
51
+ start: override_start,
52
+ end: override_end,
53
+ }
54
+ }
55
+
56
+ post_object(endpoint, data)
57
+ end
58
+
59
+ # Return all users on call for all schedules, which we can parse through later
60
+ def get_users_on_call
61
+ endpoint = return_pagerduty_url(:escalation_on_call)
62
+ return get_object(endpoint)
63
+ end
64
+
65
+ # Given a specific user, return all details about the
66
+ # user that we can parse through as needed
67
+ def get_user_details(user_id)
68
+ endpoint = return_pagerduty_url(:users) + "/#{user_id}/on_call"
69
+ return get_object(endpoint)
70
+ end
71
+
72
+ # Create a page to the first person on call for a given service key
73
+ def post_trigger(service_key:, incident_key:, description:, client:,
74
+ client_url:, details:)
75
+
76
+ # Ruby 2.x style kw-args is required here to make hash passing easier
77
+ endpoint = return_pagerduty_url(:create_trigger)
78
+ data = {
79
+ service_key: service_key,
80
+ incident_key: incident_key,
81
+ event_type: 'trigger',
82
+ description: description,
83
+ client: client,
84
+ client_url: client_url,
85
+ details: details,
86
+ }
87
+
88
+ post_object(endpoint, data)
89
+ end
90
+
91
+ private
92
+ # Helper method for all GETs
93
+ def get_object(endpoint)
94
+ response = HTTParty.get(
95
+ endpoint,
96
+ headers: {
97
+ 'Content-Type' => 'application/json', 'Authorization' => @AUTH_HEADER[:token_string]
98
+ }
99
+ )
100
+ return JSON.load(response.body)
101
+ end
102
+
103
+ # Helper method for all PUTs
104
+ def post_object(endpoint, data)
105
+ response = HTTParty.post(
106
+ endpoint,
107
+ body: data.to_json,
108
+ headers: {
109
+ 'Content-Type' => 'application/json', 'Authorization' => @AUTH_HEADER[:token_string]
110
+ }
111
+ )
112
+
113
+ return response.body
114
+ end
115
+
116
+ # Helper method for building PagerDuty URLs
117
+ def return_pagerduty_url(object_type)
118
+ rest_api_url = "https://#{@AUTH_HEADER[:subdomain]}.pagerduty.com/api/v1"
119
+ incident_api_url = 'https://events.pagerduty.com/generic/2010-04-15'
120
+ case object_type
121
+ when :users
122
+ return rest_api_url + '/users'
123
+ when :schedules
124
+ return rest_api_url + '/schedules'
125
+ when :escalation_on_call
126
+ return rest_api_url + '/escalation_policies/on_call'
127
+ when :create_trigger
128
+ return incident_api_url + '/create_event.json'
129
+ else
130
+ abort("Unknown object type: #{object_type}. Can't build URL.")
131
+ end
132
+ end
133
+ end
@@ -0,0 +1,41 @@
1
+ require 'pagerduty/base'
2
+ require 'date'
3
+
4
+ module TapJoy
5
+ module PagerDuty; end
6
+ end
7
+
8
+ class TapJoy::PagerDuty::Override
9
+
10
+ # Initializer services to import values from pg_connect.yaml
11
+ # to configure organization-specific values (currently, subdomain and api_token)
12
+ def initialize(email, schedule_name, override_length)
13
+ pg = TapJoy::PagerDuty::Base.new
14
+ override_window_hash = override_window(override_length)
15
+ puts pg.set_override(**query_dates, **override_window_hash,
16
+ user_id: pg.get_user_id(email),
17
+ schedule_id: pg.get_schedule_id(schedule_name) # case-sensitive
18
+ )
19
+ end
20
+
21
+ private
22
+ def time_string(time_object)
23
+ return time_object.iso8601.to_s
24
+ end
25
+
26
+ def query_dates
27
+ # This shrinks the query to a one-day window
28
+ since_date = time_string(Time.now)
29
+ until_date = time_string((Time.now + (1*86400)))
30
+
31
+ return {query_start: since_date, query_end: until_date}
32
+ end
33
+
34
+ def override_window(override_time)
35
+ from_time = Time.now.iso8601.to_s
36
+ # 3600 is number of seconds, change this to alter the override window
37
+ until_time = (Time.now + override_time).iso8601.to_s
38
+
39
+ return {override_start: from_time, override_end: until_time}
40
+ end
41
+ end
metadata ADDED
@@ -0,0 +1,47 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: pagerduty_utils
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Ali Tayarani
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-11-25 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: A set of tools to make leveraging the PagerDuty APIs easier
14
+ email: ali.tayarani@tapjoy.com
15
+ executables:
16
+ - pgutils
17
+ extensions: []
18
+ extra_rdoc_files: []
19
+ files:
20
+ - bin/pgutils
21
+ - lib/pagerduty/base.rb
22
+ - lib/pagerduty/override.rb
23
+ homepage: https://github.com/tapjoy/pagerduty_utils
24
+ licenses:
25
+ - MIT
26
+ metadata: {}
27
+ post_install_message:
28
+ rdoc_options: []
29
+ require_paths:
30
+ - lib
31
+ required_ruby_version: !ruby/object:Gem::Requirement
32
+ requirements:
33
+ - - ">="
34
+ - !ruby/object:Gem::Version
35
+ version: '0'
36
+ required_rubygems_version: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ requirements: []
42
+ rubyforge_project:
43
+ rubygems_version: 2.2.2
44
+ signing_key:
45
+ specification_version: 4
46
+ summary: TapJoy PagerDuty Tools
47
+ test_files: []