pager_tree-integrations 1.1.6 → 1.1.7
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 +4 -4
- data/app/controllers/pager_tree/integrations/live_call_routing/twilio/v3_controller.rb +20 -0
- data/app/jobs/pager_tree/integrations/live_call_routing/twilio/v3/max_wait_time_job.rb +13 -0
- data/app/models/pager_tree/integrations/additional_datum.rb +2 -2
- data/app/models/pager_tree/integrations/alert.rb +2 -2
- data/app/models/pager_tree/integrations/aws_cloudwatch/v3.rb +15 -5
- data/app/models/pager_tree/integrations/boolean_store_accessor.rb +2 -2
- data/app/models/pager_tree/integrations/channel/hangouts/v3.rb +23 -2
- data/app/models/pager_tree/integrations/channel/mattermost/v3.rb +4 -0
- data/app/models/pager_tree/integrations/channel/microsoft_teams/v3.rb +74 -29
- data/app/models/pager_tree/integrations/channel/microsoft_teams/v4.rb +261 -0
- data/app/models/pager_tree/integrations/channel/slack/v3.rb +30 -3
- data/app/models/pager_tree/integrations/cloudflare/v3.rb +75 -0
- data/app/models/pager_tree/integrations/custom_webhook/v3.rb +206 -0
- data/app/models/pager_tree/integrations/custom_webhook/v3_examples/datadog.json +12 -0
- data/app/models/pager_tree/integrations/custom_webhook/v3_examples/datadog.yaml +30 -0
- data/app/models/pager_tree/integrations/custom_webhook/v3_examples/generic_rules_definition.json +9 -0
- data/app/models/pager_tree/integrations/custom_webhook/v3_examples/generic_rules_example.yaml +27 -0
- data/app/models/pager_tree/integrations/custom_webhook/v3_examples/grafana.json +25 -0
- data/app/models/pager_tree/integrations/custom_webhook/v3_examples/grafana.yaml +33 -0
- data/app/models/pager_tree/integrations/custom_webhook/v3_examples/new_relic.json +40 -0
- data/app/models/pager_tree/integrations/custom_webhook/v3_examples/new_relic.yaml +32 -0
- data/app/models/pager_tree/integrations/custom_webhook/v3_examples/pingdom.json +30 -0
- data/app/models/pager_tree/integrations/custom_webhook/v3_examples/pingdom.yaml +23 -0
- data/app/models/pager_tree/integrations/custom_webhook/v3_examples/sns_cloudwatch.json +12 -0
- data/app/models/pager_tree/integrations/custom_webhook/v3_examples/sns_cloudwatch.yaml +48 -0
- data/app/models/pager_tree/integrations/custom_webhook/v3_examples/sns_health_event.json +21 -0
- data/app/models/pager_tree/integrations/custom_webhook/v3_examples/sns_health_event.yaml +43 -0
- data/app/models/pager_tree/integrations/custom_webhook/v3_examples/sns_lambda_monitor.json +31 -0
- data/app/models/pager_tree/integrations/custom_webhook/v3_examples/sns_lambda_monitor.yaml +24 -0
- data/app/models/pager_tree/integrations/datadog/v3.rb +10 -3
- data/app/models/pager_tree/integrations/dynatrace/v3.rb +67 -0
- data/app/models/pager_tree/integrations/echoes_hq/v3.rb +138 -0
- data/app/models/pager_tree/integrations/elast_alert/v3.rb +24 -0
- data/app/models/pager_tree/integrations/email/v3.rb +272 -22
- data/app/models/pager_tree/integrations/email/v3_examples/example.yml +24 -0
- data/app/models/pager_tree/integrations/form/v3.rb +15 -3
- data/app/models/pager_tree/integrations/freshdesk/v3.rb +7 -5
- data/app/models/pager_tree/integrations/freshservice/v3.rb +7 -5
- data/app/models/pager_tree/integrations/grafana/v3.rb +2 -2
- data/app/models/pager_tree/integrations/hetrix_tools/v3.rb +160 -0
- data/app/models/pager_tree/integrations/honeybadger/v3.rb +1 -1
- data/app/models/pager_tree/integrations/hydrozen/v3.rb +6 -0
- data/app/models/pager_tree/integrations/integration.rb +52 -9
- data/app/models/pager_tree/integrations/jira_server/v3.rb +12 -2
- data/app/models/pager_tree/integrations/kapacitor/v3.rb +1 -1
- data/app/models/pager_tree/integrations/live_call_routing/twilio/v3.rb +257 -22
- data/app/models/pager_tree/integrations/logic_monitor/v3.rb +193 -3
- data/app/models/pager_tree/integrations/mattermost/outgoing_webhook/v3.rb +1 -1
- data/app/models/pager_tree/integrations/meta/workplace/v3.rb +230 -0
- data/app/models/pager_tree/integrations/new_relic/v3.rb +9 -5
- data/app/models/pager_tree/integrations/outgoing_event.rb +8 -0
- data/app/models/pager_tree/integrations/outgoing_webhook/v3.rb +108 -13
- data/app/models/pager_tree/integrations/outgoing_webhook_delivery/hook_relay.rb +43 -33
- data/app/models/pager_tree/integrations/outgoing_webhook_delivery.rb +6 -5
- data/app/models/pager_tree/integrations/prtg/v3.rb +2 -1
- data/app/models/pager_tree/integrations/pulsetic/v3.rb +70 -0
- data/app/models/pager_tree/integrations/scom/pagertree.ps1 +153 -0
- data/app/models/pager_tree/integrations/scom/v3.rb +58 -0
- data/app/models/pager_tree/integrations/sentry/v3.rb +477 -0
- data/app/models/pager_tree/integrations/server_guard24/v3.rb +1 -1
- data/app/models/pager_tree/integrations/sixty_six_uptime/v3.rb +118 -0
- data/app/models/pager_tree/integrations/slack/webhook/v3.rb +1 -1
- data/app/models/pager_tree/integrations/solar_winds/v3.rb +66 -2
- data/app/models/pager_tree/integrations/status_gator/v3.rb +69 -0
- data/app/models/pager_tree/integrations/uptime_kuma/v3.rb +76 -0
- data/app/models/pager_tree/integrations/uptime_robot/v3.rb +6 -0
- data/app/models/pager_tree/integrations/webhook/v3.rb +25 -7
- data/app/models/pager_tree/integrations/zabbix/v3.rb +95 -0
- data/app/models/pager_tree/integrations/zendesk/v3.rb +2 -0
- data/app/views/pager_tree/integrations/channel/hangouts/v3/_form_options.html.erb +7 -0
- data/app/views/pager_tree/integrations/channel/hangouts/v3/_show_options.html.erb +10 -0
- data/app/views/pager_tree/integrations/channel/microsoft_teams/v3/_form_options.html.erb +7 -0
- data/app/views/pager_tree/integrations/channel/microsoft_teams/v3/_show_options.html.erb +14 -0
- data/app/views/pager_tree/integrations/channel/microsoft_teams/v4/_form_options.html.erb +41 -0
- data/app/views/pager_tree/integrations/channel/microsoft_teams/v4/_show_options.html.erb +54 -0
- data/app/views/pager_tree/integrations/channel/slack/v3/_form_options.html.erb +6 -3
- data/app/views/pager_tree/integrations/channel/slack/v3/_show_options.html.erb +1 -1
- data/app/views/pager_tree/integrations/cloudflare/v3/_form_options.html.erb +7 -0
- data/app/views/pager_tree/integrations/cloudflare/v3/_show_options.html.erb +12 -0
- data/app/views/pager_tree/integrations/custom_webhook/v3/_form_options.html.erb +8 -0
- data/app/views/pager_tree/integrations/custom_webhook/v3/_show_options.html.erb +0 -0
- data/app/views/pager_tree/integrations/datadog/v3/_form_options.html.erb +7 -0
- data/app/views/pager_tree/integrations/datadog/v3/_show_options.html.erb +12 -0
- data/app/views/pager_tree/integrations/dynatrace/v3/_form_options.html.erb +0 -0
- data/app/views/pager_tree/integrations/dynatrace/v3/_show_options.html.erb +0 -0
- data/app/views/pager_tree/integrations/echoes_hq/v3/_form_options.html.erb +10 -0
- data/app/views/pager_tree/integrations/echoes_hq/v3/_show_options.html.erb +12 -0
- data/app/views/pager_tree/integrations/email/v3/_form_options.html.erb +41 -11
- data/app/views/pager_tree/integrations/email/v3/_show_options.html.erb +18 -0
- data/app/views/pager_tree/integrations/form/v3/_form_options.html.erb +1 -5
- data/app/views/pager_tree/integrations/hetrix_tools/v3/_form_options.html.erb +7 -0
- data/app/views/pager_tree/integrations/hetrix_tools/v3/_show_options.html.erb +12 -0
- data/app/views/pager_tree/integrations/hydrozen/v3/_form_options.html.erb +0 -0
- data/app/views/pager_tree/integrations/hydrozen/v3/_show_options.html.erb +0 -0
- data/app/views/pager_tree/integrations/live_call_routing/twilio/v3/_form_options.html.erb +44 -31
- data/app/views/pager_tree/integrations/live_call_routing/twilio/v3/_show_options.html.erb +93 -8
- data/app/views/pager_tree/integrations/logic_monitor/v3/_form_options.html.erb +31 -0
- data/app/views/pager_tree/integrations/logic_monitor/v3/_show_options.html.erb +60 -0
- data/app/views/pager_tree/integrations/meta/workplace/v3/_form_options.html.erb +44 -0
- data/app/views/pager_tree/integrations/meta/workplace/v3/_show_options.html.erb +68 -0
- data/app/views/pager_tree/integrations/outgoing_webhook/v3/_form_options.html.erb +17 -3
- data/app/views/pager_tree/integrations/outgoing_webhook/v3/_show_options.html.erb +20 -0
- data/app/views/pager_tree/integrations/pulsetic/v3/_form_options.html.erb +0 -0
- data/app/views/pager_tree/integrations/pulsetic/v3/_show_options.html.erb +0 -0
- data/app/views/pager_tree/integrations/scom/v3/_form_options.html.erb +0 -0
- data/app/views/pager_tree/integrations/scom/v3/_show_options.html.erb +0 -0
- data/app/views/pager_tree/integrations/sentry/v3/_form_options.html.erb +9 -0
- data/app/views/pager_tree/integrations/sentry/v3/_show_options.html.erb +15 -0
- data/app/views/pager_tree/integrations/sixty_six_uptime/v3/_form_options.html.erb +0 -0
- data/app/views/pager_tree/integrations/sixty_six_uptime/v3/_show_options.html.erb +0 -0
- data/app/views/pager_tree/integrations/solar_winds/v3/_form_options.html.erb +40 -0
- data/app/views/pager_tree/integrations/solar_winds/v3/_show_options.html.erb +66 -0
- data/app/views/pager_tree/integrations/status_gator/v3/_form_options.html.erb +13 -0
- data/app/views/pager_tree/integrations/status_gator/v3/_show_options.html.erb +24 -0
- data/app/views/pager_tree/integrations/uptime_kuma/v3/_form_options.html.erb +0 -0
- data/app/views/pager_tree/integrations/uptime_kuma/v3/_show_options.html.erb +0 -0
- data/app/views/pager_tree/integrations/webhook/v3/_form_options.html.erb +8 -0
- data/app/views/pager_tree/integrations/webhook/v3/_show_options.html.erb +15 -0
- data/app/views/pager_tree/integrations/zabbix/v3/_form_options.html.erb +7 -0
- data/app/views/pager_tree/integrations/zabbix/v3/_show_options.html.erb +12 -0
- data/config/locales/en.yml +158 -10
- data/config/routes.rb +1 -0
- data/lib/pager_tree/integrations/format_converters/yaml_json_converter.rb +67 -0
- data/lib/pager_tree/integrations/version.rb +1 -1
- data/lib/pager_tree/integrations.rb +11 -3
- metadata +84 -8
|
@@ -0,0 +1,477 @@
|
|
|
1
|
+
module PagerTree::Integrations
|
|
2
|
+
class Sentry::V3 < Integration
|
|
3
|
+
OPTIONS = [
|
|
4
|
+
{key: :client_secret, type: :string, default: nil},
|
|
5
|
+
{key: :authorization_token, type: :string, default: nil},
|
|
6
|
+
{key: :authorization_token_expires_at, type: :string, default: nil},
|
|
7
|
+
{key: :authorization_refresh_token, type: :string, default: nil},
|
|
8
|
+
{key: :code, type: :string, default: nil}
|
|
9
|
+
]
|
|
10
|
+
store_accessor :options, *OPTIONS.map { |x| x[:key] }.map(&:to_s), prefix: "option"
|
|
11
|
+
|
|
12
|
+
after_initialize do
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
after_create_commit do
|
|
16
|
+
verify_installation if initialize_authorization_token!
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def adapter_should_block_incoming?(request)
|
|
20
|
+
should_block = false
|
|
21
|
+
# https://docs.sentry.io/product/integrations/integration-platform/webhooks/#sentry-hook-signature
|
|
22
|
+
client_secret = option_client_secret.presence || PagerTree::Integrations.integration_sentry_v3_client_secret
|
|
23
|
+
if client_secret.present? && request.headers["sentry-hook-signature"].present?
|
|
24
|
+
sentry_signature = request.headers["sentry-hook-signature"]
|
|
25
|
+
data = request.body.read
|
|
26
|
+
digest = OpenSSL::HMAC.hexdigest("SHA256", client_secret, data)
|
|
27
|
+
should_block = sentry_signature != digest
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
should_block
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def adapter_supports_incoming?
|
|
34
|
+
true
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def adapter_supports_outgoing?
|
|
38
|
+
false
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def adapter_incoming_can_defer?
|
|
42
|
+
true
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def adapter_thirdparty_id
|
|
46
|
+
send("_#{hook_resource}_adapter_thirdparty_id")
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def adapter_action
|
|
50
|
+
return :other unless should_process?
|
|
51
|
+
|
|
52
|
+
send("_#{hook_resource}_adapter_action")
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def adapter_process_create
|
|
56
|
+
Alert.new(
|
|
57
|
+
title: _title,
|
|
58
|
+
description: _description,
|
|
59
|
+
thirdparty_id: adapter_thirdparty_id,
|
|
60
|
+
dedup_keys: _dedup_keys,
|
|
61
|
+
additional_data: _additional_datums
|
|
62
|
+
)
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def adapter_process_other
|
|
66
|
+
_installation_process_other if installation?
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def verify_installation
|
|
70
|
+
if thirdparty_id.present?
|
|
71
|
+
HTTParty.put("https://sentry.io/api/0/sentry-app-installations/#{thirdparty_id}/",
|
|
72
|
+
headers: {
|
|
73
|
+
"Content-Type" => "application/json",
|
|
74
|
+
"Authorization" => "Bearer #{option_authorization_token}"
|
|
75
|
+
}, body: {
|
|
76
|
+
status: "installed"
|
|
77
|
+
}.to_json)
|
|
78
|
+
|
|
79
|
+
return true
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
false
|
|
83
|
+
rescue => e
|
|
84
|
+
Rails.logger.error("Error sending Sentry App Installation Confirmation: #{e.message}")
|
|
85
|
+
false
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def initialize_authorization_token!
|
|
89
|
+
if thirdparty_id.present? && option_code.present?
|
|
90
|
+
response = HTTParty.post("https://sentry.io/api/0/sentry-app-installations/#{thirdparty_id}/authorizations/",
|
|
91
|
+
headers: {
|
|
92
|
+
"Content-Type" => "application/json"
|
|
93
|
+
}, body: {
|
|
94
|
+
grant_type: "authorization_code",
|
|
95
|
+
code: option_code,
|
|
96
|
+
client_id: PagerTree::Integrations.integration_sentry_v3_client_id,
|
|
97
|
+
client_secret: PagerTree::Integrations.integration_sentry_v3_client_secret
|
|
98
|
+
}.to_json)
|
|
99
|
+
|
|
100
|
+
if response.code == 201
|
|
101
|
+
json = JSON.parse(response.body)
|
|
102
|
+
self.option_authorization_token = json.dig("token")
|
|
103
|
+
self.option_authorization_refresh_token = json.dig("refreshToken")
|
|
104
|
+
self.option_authorization_token_expires_at = json.dig("expiresAt")
|
|
105
|
+
save!
|
|
106
|
+
|
|
107
|
+
return true
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
false
|
|
112
|
+
rescue => e
|
|
113
|
+
Rails.logger.error("Error initializing Sentry App Authorization Token: #{e.message}")
|
|
114
|
+
false
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
def refresh_authorization_token!
|
|
118
|
+
if thirdparty_id.present? && option_authorization_refresh_token.present?
|
|
119
|
+
response = HTTParty.post("https://sentry.io/api/0/sentry-app-installations/#{thirdparty_id}/authorizations/",
|
|
120
|
+
headers: {
|
|
121
|
+
"Content-Type" => "application/json"
|
|
122
|
+
}, body: {
|
|
123
|
+
grant_type: "refresh_token",
|
|
124
|
+
refresh_token: option_authorization_refresh_token,
|
|
125
|
+
client_id: PagerTree::Integrations.integration_sentry_v3_client_id,
|
|
126
|
+
client_secret: PagerTree::Integrations.integration_sentry_v3_client_secret
|
|
127
|
+
}.to_json)
|
|
128
|
+
|
|
129
|
+
if response.code == 201
|
|
130
|
+
json = JSON.parse(response.body)
|
|
131
|
+
self.option_authorization_token = json.dig("token")
|
|
132
|
+
self.option_authorization_refresh_token = json.dig("refreshToken")
|
|
133
|
+
self.option_authorization_token_expires_at = json.dig("expiresAt")
|
|
134
|
+
save!
|
|
135
|
+
|
|
136
|
+
return true
|
|
137
|
+
end
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
false
|
|
141
|
+
rescue => e
|
|
142
|
+
Rails.logger.error("Error refreshing Sentry App Authorization Token: #{e.message}")
|
|
143
|
+
false
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
private
|
|
147
|
+
|
|
148
|
+
############################
|
|
149
|
+
# START INSTALLATION
|
|
150
|
+
# https://docs.sentry.io/product/integrations/integration-platform/webhooks/installation/
|
|
151
|
+
############################
|
|
152
|
+
|
|
153
|
+
def _installation_adapter_thirdparty_id
|
|
154
|
+
incoming_json.dig("id")
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
def _installation_adapter_action
|
|
158
|
+
:other
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
def _installation_title
|
|
162
|
+
""
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
def _installation_description
|
|
166
|
+
""
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
def _installation_additional_datums
|
|
170
|
+
[]
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
def _installation_dedup_keys
|
|
174
|
+
[]
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
def _installation_process_other
|
|
178
|
+
action = incoming_json.dig("action")
|
|
179
|
+
if action == "created"
|
|
180
|
+
# intentionally left blank
|
|
181
|
+
elsif action == "deleted"
|
|
182
|
+
# clear the thirdparty id off this integration and save
|
|
183
|
+
self.thirdparty_id = nil
|
|
184
|
+
save!
|
|
185
|
+
end
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
############################
|
|
189
|
+
# END Installation
|
|
190
|
+
############################
|
|
191
|
+
|
|
192
|
+
############################
|
|
193
|
+
# START WEBHOOK
|
|
194
|
+
# Undocumented webhook format (this is what you get when you just signup for a trial)
|
|
195
|
+
############################
|
|
196
|
+
|
|
197
|
+
def _webhook_adapter_thirdparty_id
|
|
198
|
+
incoming_json.dig("id")
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
def _webhook_adapter_action
|
|
202
|
+
:create
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
def _webhook_title
|
|
206
|
+
incoming_json.dig("event", "title")
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
def _webhook_description
|
|
210
|
+
web_url = incoming_json.dig("url")
|
|
211
|
+
"Please see <a href='#{web_url}' target='_blank'>Sentry issue</a> for full details." if web_url.present?
|
|
212
|
+
end
|
|
213
|
+
|
|
214
|
+
def _webhook_additional_datums
|
|
215
|
+
[
|
|
216
|
+
AdditionalDatum.new(format: "link", label: "Web URL", value: incoming_json.dig("url")),
|
|
217
|
+
AdditionalDatum.new(format: "text", label: "Project", value: incoming_json.dig("project_name"))
|
|
218
|
+
]
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
def _webhook_dedup_keys
|
|
222
|
+
[]
|
|
223
|
+
end
|
|
224
|
+
|
|
225
|
+
############################
|
|
226
|
+
# END WEBHOOK
|
|
227
|
+
############################
|
|
228
|
+
|
|
229
|
+
############################
|
|
230
|
+
# START ISSUE
|
|
231
|
+
# https://docs.sentry.io/product/integrations/integration-platform/webhooks/issues/
|
|
232
|
+
############################
|
|
233
|
+
|
|
234
|
+
def _issue_adapter_thirdparty_id
|
|
235
|
+
incoming_json.dig("data", "issue", "id")
|
|
236
|
+
end
|
|
237
|
+
|
|
238
|
+
def _issue_adapter_action
|
|
239
|
+
case action
|
|
240
|
+
when "created"
|
|
241
|
+
:create
|
|
242
|
+
when "resolved", "archived"
|
|
243
|
+
:resolve
|
|
244
|
+
when "assigned"
|
|
245
|
+
:acknowledge
|
|
246
|
+
else
|
|
247
|
+
:other
|
|
248
|
+
end
|
|
249
|
+
end
|
|
250
|
+
|
|
251
|
+
def _issue_title
|
|
252
|
+
incoming_json.dig("data", "issue", "title")
|
|
253
|
+
end
|
|
254
|
+
|
|
255
|
+
def _issue_description
|
|
256
|
+
web_url = incoming_json.dig("data", "issue", "web_url")
|
|
257
|
+
"Please see <a href='#{web_url}' target='_blank'>Sentry issue</a> for full details." if web_url.present?
|
|
258
|
+
end
|
|
259
|
+
|
|
260
|
+
def _issue_additional_datums
|
|
261
|
+
[
|
|
262
|
+
AdditionalDatum.new(format: "link", label: "Web URL", value: incoming_json.dig("data", "issue", "web_url"))
|
|
263
|
+
]
|
|
264
|
+
end
|
|
265
|
+
|
|
266
|
+
def _issue_dedup_keys
|
|
267
|
+
[]
|
|
268
|
+
end
|
|
269
|
+
|
|
270
|
+
############################
|
|
271
|
+
# END ISSUE
|
|
272
|
+
############################
|
|
273
|
+
|
|
274
|
+
############################
|
|
275
|
+
# START EVENT ALERTS (ISSUE ALERTS)
|
|
276
|
+
# https://docs.sentry.io/product/integrations/integration-platform/webhooks/issue-alerts/
|
|
277
|
+
############################
|
|
278
|
+
|
|
279
|
+
def _event_alert_adapter_thirdparty_id
|
|
280
|
+
incoming_json.dig("data", "event", "issue_id")
|
|
281
|
+
end
|
|
282
|
+
|
|
283
|
+
def _event_alert_adapter_action
|
|
284
|
+
case action
|
|
285
|
+
when "triggered"
|
|
286
|
+
:create
|
|
287
|
+
else
|
|
288
|
+
:other
|
|
289
|
+
end
|
|
290
|
+
end
|
|
291
|
+
|
|
292
|
+
def _event_alert_title
|
|
293
|
+
incoming_json.dig("data", "event", "title")
|
|
294
|
+
end
|
|
295
|
+
|
|
296
|
+
def _event_alert_description
|
|
297
|
+
web_url = incoming_json.dig("data", "event", "web_url")
|
|
298
|
+
"Please see <a href='#{web_url}' target='_blank'>Sentry event</a> for full details." if web_url.present?
|
|
299
|
+
end
|
|
300
|
+
|
|
301
|
+
def _event_alert_additional_datums
|
|
302
|
+
[
|
|
303
|
+
AdditionalDatum.new(format: "link", label: "Web URL", value: incoming_json.dig("data", "event", "web_url"))
|
|
304
|
+
]
|
|
305
|
+
end
|
|
306
|
+
|
|
307
|
+
def _event_alert_dedup_keys
|
|
308
|
+
[]
|
|
309
|
+
end
|
|
310
|
+
|
|
311
|
+
############################
|
|
312
|
+
# END EVENT ALERTS
|
|
313
|
+
############################
|
|
314
|
+
|
|
315
|
+
############################
|
|
316
|
+
# START METRIC ALERTS
|
|
317
|
+
# https://docs.sentry.io/product/integrations/integration-platform/webhooks/metric-alerts/
|
|
318
|
+
############################
|
|
319
|
+
|
|
320
|
+
def _metric_alert_adapter_thirdparty_id
|
|
321
|
+
incoming_json.dig("data", "metric_alert", "id")
|
|
322
|
+
end
|
|
323
|
+
|
|
324
|
+
def _metric_alert_adapter_action
|
|
325
|
+
case action
|
|
326
|
+
when "resolved"
|
|
327
|
+
:resolve
|
|
328
|
+
when "critical", "warning"
|
|
329
|
+
:create
|
|
330
|
+
else
|
|
331
|
+
:other
|
|
332
|
+
end
|
|
333
|
+
end
|
|
334
|
+
|
|
335
|
+
def _metric_alert_title
|
|
336
|
+
incoming_json.dig("data", "description_title")
|
|
337
|
+
end
|
|
338
|
+
|
|
339
|
+
def _metric_alert_description
|
|
340
|
+
incoming_json.dig("data", "description_text")
|
|
341
|
+
end
|
|
342
|
+
|
|
343
|
+
def _metric_alert_additional_datums
|
|
344
|
+
[
|
|
345
|
+
AdditionalDatum.new(format: "link", label: "Web URL", value: incoming_json.dig("data", "metric_alert", "web_url"))
|
|
346
|
+
]
|
|
347
|
+
end
|
|
348
|
+
|
|
349
|
+
def _metric_alert_dedup_keys
|
|
350
|
+
[]
|
|
351
|
+
end
|
|
352
|
+
|
|
353
|
+
############################
|
|
354
|
+
# END METRIC ALERTS
|
|
355
|
+
############################
|
|
356
|
+
|
|
357
|
+
############################
|
|
358
|
+
# START ERRORS
|
|
359
|
+
# https://docs.sentry.io/product/integrations/integration-platform/webhooks/errors/
|
|
360
|
+
############################
|
|
361
|
+
|
|
362
|
+
def _error_adapter_thirdparty_id
|
|
363
|
+
incoming_json.dig("data", "error", "issue_id")
|
|
364
|
+
end
|
|
365
|
+
|
|
366
|
+
def _error_adapter_action
|
|
367
|
+
case action
|
|
368
|
+
when "created"
|
|
369
|
+
:create
|
|
370
|
+
else
|
|
371
|
+
:other
|
|
372
|
+
end
|
|
373
|
+
end
|
|
374
|
+
|
|
375
|
+
def _error_title
|
|
376
|
+
incoming_json.dig("data", "error", "title")
|
|
377
|
+
end
|
|
378
|
+
|
|
379
|
+
def _error_description
|
|
380
|
+
web_url = incoming_json.dig("data", "error", "web_url")
|
|
381
|
+
"Please see <a href='#{web_url}' target='_blank'>Sentry event</a> for full details." if web_url.present?
|
|
382
|
+
end
|
|
383
|
+
|
|
384
|
+
def _error_additional_datums
|
|
385
|
+
[
|
|
386
|
+
AdditionalDatum.new(format: "link", label: "Web URL", value: incoming_json.dig("data", "error", "web_url"))
|
|
387
|
+
]
|
|
388
|
+
end
|
|
389
|
+
|
|
390
|
+
def _error_dedup_keys
|
|
391
|
+
[]
|
|
392
|
+
end
|
|
393
|
+
|
|
394
|
+
############################
|
|
395
|
+
# END ERRORS
|
|
396
|
+
############################
|
|
397
|
+
|
|
398
|
+
############################
|
|
399
|
+
# START COMMON
|
|
400
|
+
############################
|
|
401
|
+
|
|
402
|
+
def _title
|
|
403
|
+
send("_#{hook_resource}_title")
|
|
404
|
+
end
|
|
405
|
+
|
|
406
|
+
def _description
|
|
407
|
+
send("_#{hook_resource}_description")
|
|
408
|
+
end
|
|
409
|
+
|
|
410
|
+
def _additional_datums
|
|
411
|
+
send("_#{hook_resource}_additional_datums")
|
|
412
|
+
end
|
|
413
|
+
|
|
414
|
+
def _dedup_keys
|
|
415
|
+
send("_#{hook_resource}_dedup_keys")
|
|
416
|
+
end
|
|
417
|
+
|
|
418
|
+
############################
|
|
419
|
+
# END COMMON
|
|
420
|
+
############################
|
|
421
|
+
|
|
422
|
+
############################
|
|
423
|
+
# START DATA ACCESS
|
|
424
|
+
############################
|
|
425
|
+
def incoming_headers
|
|
426
|
+
adapter_incoming_deferred_request.headers
|
|
427
|
+
end
|
|
428
|
+
|
|
429
|
+
def incoming_body
|
|
430
|
+
adapter_incoming_deferred_request.body
|
|
431
|
+
end
|
|
432
|
+
|
|
433
|
+
def incoming_json
|
|
434
|
+
@_json ||= JSON.parse(incoming_body)
|
|
435
|
+
end
|
|
436
|
+
|
|
437
|
+
def hook_resource
|
|
438
|
+
incoming_headers["HTTP_SENTRY_HOOK_RESOURCE"] || "webhook"
|
|
439
|
+
end
|
|
440
|
+
|
|
441
|
+
def issue?
|
|
442
|
+
hook_resource == "issue"
|
|
443
|
+
end
|
|
444
|
+
|
|
445
|
+
def event_alert?
|
|
446
|
+
hook_resource == "event_alert"
|
|
447
|
+
end
|
|
448
|
+
|
|
449
|
+
def metric_alert?
|
|
450
|
+
hook_resource == "metric_alert"
|
|
451
|
+
end
|
|
452
|
+
|
|
453
|
+
def error?
|
|
454
|
+
hook_resource == "error"
|
|
455
|
+
end
|
|
456
|
+
|
|
457
|
+
def installation?
|
|
458
|
+
hook_resource == "installation"
|
|
459
|
+
end
|
|
460
|
+
|
|
461
|
+
def webhook?
|
|
462
|
+
incoming_headers["HTTP_SENTRY_HOOK_RESOURCE"].blank? && (hook_resource == "webhook")
|
|
463
|
+
end
|
|
464
|
+
|
|
465
|
+
def should_process?
|
|
466
|
+
issue? || event_alert? || metric_alert? || error? || installation? || webhook?
|
|
467
|
+
end
|
|
468
|
+
|
|
469
|
+
def action
|
|
470
|
+
incoming_json.dig("action")
|
|
471
|
+
end
|
|
472
|
+
|
|
473
|
+
############################
|
|
474
|
+
# END DATA ACCESS
|
|
475
|
+
############################
|
|
476
|
+
end
|
|
477
|
+
end
|
|
@@ -32,7 +32,7 @@ module PagerTree::Integrations
|
|
|
32
32
|
|
|
33
33
|
if check_result == "CRITICAL"
|
|
34
34
|
:create
|
|
35
|
-
elsif check_result == "OK" || (check_result == "WARNING" &&
|
|
35
|
+
elsif check_result == "OK" || (check_result == "WARNING" && option_resolve_warn == true)
|
|
36
36
|
:resolve
|
|
37
37
|
else
|
|
38
38
|
:other
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
module PagerTree::Integrations
|
|
2
|
+
class SixtySixUptime::V3 < Integration
|
|
3
|
+
OPTIONS = []
|
|
4
|
+
store_accessor :options, *OPTIONS.map { |x| x[:key] }.map(&:to_s), prefix: "option"
|
|
5
|
+
|
|
6
|
+
after_initialize do
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def adapter_supports_incoming?
|
|
10
|
+
true
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def adapter_supports_outgoing?
|
|
14
|
+
false
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def adapter_incoming_can_defer?
|
|
18
|
+
true
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def adapter_thirdparty_id
|
|
22
|
+
id_part = case _webhoook_type
|
|
23
|
+
when "website", "ping", "port" then adapter_incoming_request_params.dig("monitor_id")
|
|
24
|
+
when "heartbeat" then adapter_incoming_request_params.dig("heartbeat_id")
|
|
25
|
+
when "domain-expiry", "ssl-expiry" then adapter_incoming_request_params.dig("domain_name_id")
|
|
26
|
+
else
|
|
27
|
+
SecureRandom.uuid
|
|
28
|
+
end
|
|
29
|
+
"#{_webhoook_type}-#{id_part}"
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def adapter_action
|
|
33
|
+
case _webhoook_type
|
|
34
|
+
when "website", "ping", "port", "heartbeat"
|
|
35
|
+
(adapter_incoming_request_params.dig("is_ok") == 1) ? :resolve : :create
|
|
36
|
+
when "domain-expiry", "ssl-expiry"
|
|
37
|
+
:create
|
|
38
|
+
else
|
|
39
|
+
:other
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def adapter_process_create
|
|
44
|
+
Alert.new(
|
|
45
|
+
title: _title,
|
|
46
|
+
description: _description,
|
|
47
|
+
thirdparty_id: adapter_thirdparty_id,
|
|
48
|
+
dedup_keys: [],
|
|
49
|
+
additional_data: _additional_datums
|
|
50
|
+
)
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
private
|
|
54
|
+
|
|
55
|
+
def _title
|
|
56
|
+
case _webhoook_type
|
|
57
|
+
when "website", "ping", "port" then "#{_webhoook_type.capitalize} monitor #{adapter_incoming_request_params.dig("name")} is DOWN"
|
|
58
|
+
when "heartbeat" then "Heartbeat monitor #{adapter_incoming_request_params.dig("name")} has not checked in"
|
|
59
|
+
when "domain-expiry" then "Domain monitor #{adapter_incoming_request_params.dig("name")} is expiring soon"
|
|
60
|
+
when "ssl-expiry" then "SSL Certificate monitor #{adapter_incoming_request_params.dig("name")} is expiring soon"
|
|
61
|
+
else
|
|
62
|
+
"Unknown Webhook Type"
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def _description
|
|
67
|
+
case _webhoook_type
|
|
68
|
+
when "website", "ping", "port" then "#{_webhoook_type.capitalize} monitor #{adapter_incoming_request_params.dig("name")} (#{adapter_incoming_request_params.dig("target")}) is DOWN"
|
|
69
|
+
when "heartbeat" then "Heartbeat monitor #{adapter_incoming_request_params.dig("name")} has not checked in"
|
|
70
|
+
when "domain-expiry" then "Domain monitor #{adapter_incoming_request_params.dig("name")} (#{adapter_incoming_request_params.dig("target")}) is expiring soon (#{adapter_incoming_request_params.dig("whois_end_datetime")} #{adapter_incoming_request_params.dig("timezone")})"
|
|
71
|
+
when "ssl-expiry" then "SSL Certificate monitor #{adapter_incoming_request_params.dig("name")} (#{adapter_incoming_request_params.dig("target")}) is expiring soon (#{adapter_incoming_request_params.dig("ssl_end_datetime")} #{adapter_incoming_request_params.dig("timezone")})"
|
|
72
|
+
else
|
|
73
|
+
"Unknown Webhook Type"
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def _additional_datums
|
|
78
|
+
case _webhoook_type
|
|
79
|
+
when "website", "ping", "port"
|
|
80
|
+
[
|
|
81
|
+
AdditionalDatum.new(format: "link", label: "URL", value: adapter_incoming_request_params.dig("url")),
|
|
82
|
+
AdditionalDatum.new(format: "text", label: "Name", value: adapter_incoming_request_params.dig("name")),
|
|
83
|
+
AdditionalDatum.new(format: "text", label: "Type", value: adapter_incoming_request_params.dig("type")),
|
|
84
|
+
AdditionalDatum.new(format: "link", label: "Target", value: adapter_incoming_request_params.dig("target")),
|
|
85
|
+
AdditionalDatum.new(format: "text", label: "port", value: adapter_incoming_request_params.dig("port"))
|
|
86
|
+
]
|
|
87
|
+
when "heartbeat"
|
|
88
|
+
[
|
|
89
|
+
AdditionalDatum.new(format: "link", label: "URL", value: adapter_incoming_request_params.dig("url")),
|
|
90
|
+
AdditionalDatum.new(format: "text", label: "Name", value: adapter_incoming_request_params.dig("name")),
|
|
91
|
+
AdditionalDatum.new(format: "text", label: "Type", value: adapter_incoming_request_params.dig("type"))
|
|
92
|
+
]
|
|
93
|
+
when "domain-expiry"
|
|
94
|
+
[
|
|
95
|
+
AdditionalDatum.new(format: "link", label: "URL", value: adapter_incoming_request_params.dig("url")),
|
|
96
|
+
AdditionalDatum.new(format: "text", label: "Name", value: adapter_incoming_request_params.dig("name")),
|
|
97
|
+
AdditionalDatum.new(format: "text", label: "Type", value: adapter_incoming_request_params.dig("type")),
|
|
98
|
+
AdditionalDatum.new(format: "link", label: "Target", value: adapter_incoming_request_params.dig("target")),
|
|
99
|
+
AdditionalDatum.new(format: "text", label: "WHOIS End DateTime", value: "#{adapter_incoming_request_params.dig("whois_end_datetime")} #{adapter_incoming_request_params.dig("timezone")}")
|
|
100
|
+
]
|
|
101
|
+
when "ssl-expiry"
|
|
102
|
+
[
|
|
103
|
+
AdditionalDatum.new(format: "link", label: "URL", value: adapter_incoming_request_params.dig("url")),
|
|
104
|
+
AdditionalDatum.new(format: "text", label: "Name", value: adapter_incoming_request_params.dig("name")),
|
|
105
|
+
AdditionalDatum.new(format: "text", label: "Type", value: adapter_incoming_request_params.dig("type")),
|
|
106
|
+
AdditionalDatum.new(format: "link", label: "Target", value: adapter_incoming_request_params.dig("target")),
|
|
107
|
+
AdditionalDatum.new(format: "text", label: "SSL End DateTime", value: "#{adapter_incoming_request_params.dig("ssl_end_datetime")} #{adapter_incoming_request_params.dig("timezone")}")
|
|
108
|
+
]
|
|
109
|
+
else
|
|
110
|
+
[]
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
def _webhoook_type
|
|
115
|
+
adapter_incoming_request_params.dig("type")
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
end
|
|
@@ -51,7 +51,7 @@ module PagerTree::Integrations
|
|
|
51
51
|
def _urgency
|
|
52
52
|
text = adapter_incoming_request_params.dig("text")&.downcase
|
|
53
53
|
matches = /(?<urgency>low|medium|high|critical)/.match(text)
|
|
54
|
-
matches ? matches[:urgency].
|
|
54
|
+
matches ? matches[:urgency].to_s : nil
|
|
55
55
|
end
|
|
56
56
|
|
|
57
57
|
def _additional_datums
|
|
@@ -1,9 +1,25 @@
|
|
|
1
1
|
module PagerTree::Integrations
|
|
2
2
|
class SolarWinds::V3 < Integration
|
|
3
|
-
OPTIONS = [
|
|
3
|
+
OPTIONS = [
|
|
4
|
+
{key: :alert_acknowledged, type: :boolean, default: false},
|
|
5
|
+
{key: :server_url, type: :string, default: nil},
|
|
6
|
+
{key: :server_username, type: :string, default: nil},
|
|
7
|
+
{key: :server_password, type: :string, default: nil},
|
|
8
|
+
{key: :proxy_url, type: :string, default: nil}
|
|
9
|
+
]
|
|
4
10
|
store_accessor :options, *OPTIONS.map { |x| x[:key] }.map(&:to_s), prefix: "option"
|
|
5
11
|
|
|
12
|
+
validates :option_alert_acknowledged, inclusion: {in: [true, false]}
|
|
13
|
+
validates :option_server_username, presence: true, if: -> { option_alert_acknowledged == true }
|
|
14
|
+
validates :option_server_password, presence: true, if: -> { option_alert_acknowledged == true }
|
|
15
|
+
validates :option_server_url, presence: true, url: {no_local: true}, if: -> { option_alert_acknowledged == true }
|
|
16
|
+
|
|
6
17
|
after_initialize do
|
|
18
|
+
self.option_alert_acknowledged ||= false
|
|
19
|
+
self.option_server_url ||= nil
|
|
20
|
+
self.option_server_username ||= nil
|
|
21
|
+
self.option_server_password ||= nil
|
|
22
|
+
self.option_proxy_url ||= nil
|
|
7
23
|
end
|
|
8
24
|
|
|
9
25
|
def adapter_supports_incoming?
|
|
@@ -11,13 +27,61 @@ module PagerTree::Integrations
|
|
|
11
27
|
end
|
|
12
28
|
|
|
13
29
|
def adapter_supports_outgoing?
|
|
14
|
-
|
|
30
|
+
true
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def adapter_show_outgoing_webhook_delivery?
|
|
34
|
+
true
|
|
15
35
|
end
|
|
16
36
|
|
|
17
37
|
def adapter_incoming_can_defer?
|
|
18
38
|
true
|
|
19
39
|
end
|
|
20
40
|
|
|
41
|
+
def adapter_outgoing_interest?(event_name)
|
|
42
|
+
try("option_#{event_name}") || false
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def adapter_process_outgoing
|
|
46
|
+
try("adapter_process_outgoing_#{adapter_outgoing_event.event_name}")
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def adapter_process_outgoing_alert_acknowledged
|
|
50
|
+
return unless adapter_outgoing_event.alert.source == self
|
|
51
|
+
|
|
52
|
+
ack_url = adapter_outgoing_event.alert&.source_log&.message&.dig("params", "AcknowledgeUrl")
|
|
53
|
+
ack_uri = URI.parse(ack_url)
|
|
54
|
+
server_uri = URI.parse(option_server_url)
|
|
55
|
+
object_id = Rack::Utils.parse_query(ack_uri.query).dig("ObjID")
|
|
56
|
+
url = "#{server_uri.origin}/SolarWinds/InformationService/v3/Json/Invoke/Orion.AlertActive/Acknowledge"
|
|
57
|
+
body = {
|
|
58
|
+
alertObjectIds: [object_id],
|
|
59
|
+
notes: "Acknowledged by #{adapter_outgoing_event.alert&.alert_responders&.where(role: :incident_commander)&.includes(account_user: :user)&.first&.account_user&.user&.name}"
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
auth = {}
|
|
63
|
+
|
|
64
|
+
if option_server_username.present? && option_server_password.present?
|
|
65
|
+
auth = {
|
|
66
|
+
username: option_server_username,
|
|
67
|
+
password: option_server_password
|
|
68
|
+
}
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
outgoing_webhook_delivery = OutgoingWebhookDelivery.factory(
|
|
72
|
+
resource: self,
|
|
73
|
+
url: url,
|
|
74
|
+
body: body,
|
|
75
|
+
auth: auth,
|
|
76
|
+
proxy_url: option_proxy_url.presence
|
|
77
|
+
)
|
|
78
|
+
outgoing_webhook_delivery.save!
|
|
79
|
+
outgoing_webhook_delivery.deliver_later
|
|
80
|
+
|
|
81
|
+
outgoing_webhook_delivery
|
|
82
|
+
rescue
|
|
83
|
+
end
|
|
84
|
+
|
|
21
85
|
def adapter_thirdparty_id
|
|
22
86
|
adapter_incoming_request_params.dig("AlertID")
|
|
23
87
|
end
|