pager_tree-integrations 1.1.5 → 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.
Files changed (127) hide show
  1. checksums.yaml +4 -4
  2. data/app/controllers/pager_tree/integrations/live_call_routing/twilio/v3_controller.rb +20 -0
  3. data/app/jobs/pager_tree/integrations/live_call_routing/twilio/v3/max_wait_time_job.rb +13 -0
  4. data/app/models/pager_tree/integrations/additional_datum.rb +2 -2
  5. data/app/models/pager_tree/integrations/alert.rb +2 -2
  6. data/app/models/pager_tree/integrations/aws_cloudwatch/v3.rb +15 -5
  7. data/app/models/pager_tree/integrations/boolean_store_accessor.rb +2 -2
  8. data/app/models/pager_tree/integrations/channel/hangouts/v3.rb +23 -2
  9. data/app/models/pager_tree/integrations/channel/mattermost/v3.rb +4 -0
  10. data/app/models/pager_tree/integrations/channel/microsoft_teams/v3.rb +74 -29
  11. data/app/models/pager_tree/integrations/channel/microsoft_teams/v4.rb +261 -0
  12. data/app/models/pager_tree/integrations/channel/slack/v3.rb +30 -3
  13. data/app/models/pager_tree/integrations/cloudflare/v3.rb +75 -0
  14. data/app/models/pager_tree/integrations/custom_webhook/v3.rb +206 -0
  15. data/app/models/pager_tree/integrations/custom_webhook/v3_examples/datadog.json +12 -0
  16. data/app/models/pager_tree/integrations/custom_webhook/v3_examples/datadog.yaml +30 -0
  17. data/app/models/pager_tree/integrations/custom_webhook/v3_examples/generic_rules_definition.json +9 -0
  18. data/app/models/pager_tree/integrations/custom_webhook/v3_examples/generic_rules_example.yaml +27 -0
  19. data/app/models/pager_tree/integrations/custom_webhook/v3_examples/grafana.json +25 -0
  20. data/app/models/pager_tree/integrations/custom_webhook/v3_examples/grafana.yaml +33 -0
  21. data/app/models/pager_tree/integrations/custom_webhook/v3_examples/new_relic.json +40 -0
  22. data/app/models/pager_tree/integrations/custom_webhook/v3_examples/new_relic.yaml +32 -0
  23. data/app/models/pager_tree/integrations/custom_webhook/v3_examples/pingdom.json +30 -0
  24. data/app/models/pager_tree/integrations/custom_webhook/v3_examples/pingdom.yaml +23 -0
  25. data/app/models/pager_tree/integrations/custom_webhook/v3_examples/sns_cloudwatch.json +12 -0
  26. data/app/models/pager_tree/integrations/custom_webhook/v3_examples/sns_cloudwatch.yaml +48 -0
  27. data/app/models/pager_tree/integrations/custom_webhook/v3_examples/sns_health_event.json +21 -0
  28. data/app/models/pager_tree/integrations/custom_webhook/v3_examples/sns_health_event.yaml +43 -0
  29. data/app/models/pager_tree/integrations/custom_webhook/v3_examples/sns_lambda_monitor.json +31 -0
  30. data/app/models/pager_tree/integrations/custom_webhook/v3_examples/sns_lambda_monitor.yaml +24 -0
  31. data/app/models/pager_tree/integrations/datadog/v3.rb +10 -3
  32. data/app/models/pager_tree/integrations/dynatrace/v3.rb +67 -0
  33. data/app/models/pager_tree/integrations/echoes_hq/v3.rb +138 -0
  34. data/app/models/pager_tree/integrations/elast_alert/v3.rb +24 -0
  35. data/app/models/pager_tree/integrations/email/v3.rb +272 -22
  36. data/app/models/pager_tree/integrations/email/v3_examples/example.yml +24 -0
  37. data/app/models/pager_tree/integrations/form/v3.rb +15 -3
  38. data/app/models/pager_tree/integrations/freshdesk/v3.rb +7 -5
  39. data/app/models/pager_tree/integrations/freshservice/v3.rb +7 -5
  40. data/app/models/pager_tree/integrations/grafana/v3.rb +2 -2
  41. data/app/models/pager_tree/integrations/hetrix_tools/v3.rb +160 -0
  42. data/app/models/pager_tree/integrations/honeybadger/v3.rb +1 -1
  43. data/app/models/pager_tree/integrations/hydrozen/v3.rb +6 -0
  44. data/app/models/pager_tree/integrations/integration.rb +52 -9
  45. data/app/models/pager_tree/integrations/jira_server/v3.rb +12 -2
  46. data/app/models/pager_tree/integrations/kapacitor/v3.rb +1 -1
  47. data/app/models/pager_tree/integrations/live_call_routing/twilio/v3.rb +276 -25
  48. data/app/models/pager_tree/integrations/logic_monitor/v3.rb +193 -3
  49. data/app/models/pager_tree/integrations/mattermost/outgoing_webhook/v3.rb +1 -1
  50. data/app/models/pager_tree/integrations/meta/workplace/v3.rb +230 -0
  51. data/app/models/pager_tree/integrations/new_relic/v3.rb +9 -5
  52. data/app/models/pager_tree/integrations/outgoing_event.rb +8 -0
  53. data/app/models/pager_tree/integrations/outgoing_webhook/v3.rb +108 -13
  54. data/app/models/pager_tree/integrations/outgoing_webhook_delivery/hook_relay.rb +43 -33
  55. data/app/models/pager_tree/integrations/outgoing_webhook_delivery.rb +6 -5
  56. data/app/models/pager_tree/integrations/prtg/v3.rb +2 -1
  57. data/app/models/pager_tree/integrations/pulsetic/v3.rb +70 -0
  58. data/app/models/pager_tree/integrations/scom/pagertree.ps1 +153 -0
  59. data/app/models/pager_tree/integrations/scom/v3.rb +58 -0
  60. data/app/models/pager_tree/integrations/sentry/v3.rb +477 -0
  61. data/app/models/pager_tree/integrations/server_guard24/v3.rb +1 -1
  62. data/app/models/pager_tree/integrations/sixty_six_uptime/v3.rb +118 -0
  63. data/app/models/pager_tree/integrations/slack/webhook/v3.rb +1 -1
  64. data/app/models/pager_tree/integrations/solar_winds/v3.rb +66 -2
  65. data/app/models/pager_tree/integrations/status_gator/v3.rb +69 -0
  66. data/app/models/pager_tree/integrations/uptime_kuma/v3.rb +76 -0
  67. data/app/models/pager_tree/integrations/uptime_robot/v3.rb +6 -0
  68. data/app/models/pager_tree/integrations/webhook/v3.rb +25 -7
  69. data/app/models/pager_tree/integrations/zabbix/v3.rb +95 -0
  70. data/app/models/pager_tree/integrations/zendesk/v3.rb +2 -0
  71. data/app/views/pager_tree/integrations/channel/hangouts/v3/_form_options.html.erb +7 -0
  72. data/app/views/pager_tree/integrations/channel/hangouts/v3/_show_options.html.erb +10 -0
  73. data/app/views/pager_tree/integrations/channel/microsoft_teams/v3/_form_options.html.erb +7 -0
  74. data/app/views/pager_tree/integrations/channel/microsoft_teams/v3/_show_options.html.erb +14 -0
  75. data/app/views/pager_tree/integrations/channel/microsoft_teams/v4/_form_options.html.erb +41 -0
  76. data/app/views/pager_tree/integrations/channel/microsoft_teams/v4/_show_options.html.erb +54 -0
  77. data/app/views/pager_tree/integrations/channel/slack/v3/_form_options.html.erb +6 -3
  78. data/app/views/pager_tree/integrations/channel/slack/v3/_show_options.html.erb +1 -1
  79. data/app/views/pager_tree/integrations/cloudflare/v3/_form_options.html.erb +7 -0
  80. data/app/views/pager_tree/integrations/cloudflare/v3/_show_options.html.erb +12 -0
  81. data/app/views/pager_tree/integrations/custom_webhook/v3/_form_options.html.erb +8 -0
  82. data/app/views/pager_tree/integrations/custom_webhook/v3/_show_options.html.erb +0 -0
  83. data/app/views/pager_tree/integrations/datadog/v3/_form_options.html.erb +7 -0
  84. data/app/views/pager_tree/integrations/datadog/v3/_show_options.html.erb +12 -0
  85. data/app/views/pager_tree/integrations/dynatrace/v3/_form_options.html.erb +0 -0
  86. data/app/views/pager_tree/integrations/dynatrace/v3/_show_options.html.erb +0 -0
  87. data/app/views/pager_tree/integrations/echoes_hq/v3/_form_options.html.erb +10 -0
  88. data/app/views/pager_tree/integrations/echoes_hq/v3/_show_options.html.erb +12 -0
  89. data/app/views/pager_tree/integrations/email/v3/_form_options.html.erb +41 -11
  90. data/app/views/pager_tree/integrations/email/v3/_show_options.html.erb +18 -0
  91. data/app/views/pager_tree/integrations/form/v3/_form_options.html.erb +1 -5
  92. data/app/views/pager_tree/integrations/hetrix_tools/v3/_form_options.html.erb +7 -0
  93. data/app/views/pager_tree/integrations/hetrix_tools/v3/_show_options.html.erb +12 -0
  94. data/app/views/pager_tree/integrations/hydrozen/v3/_form_options.html.erb +0 -0
  95. data/app/views/pager_tree/integrations/hydrozen/v3/_show_options.html.erb +0 -0
  96. data/app/views/pager_tree/integrations/live_call_routing/twilio/v3/_form_options.html.erb +44 -31
  97. data/app/views/pager_tree/integrations/live_call_routing/twilio/v3/_show_options.html.erb +93 -8
  98. data/app/views/pager_tree/integrations/logic_monitor/v3/_form_options.html.erb +31 -0
  99. data/app/views/pager_tree/integrations/logic_monitor/v3/_show_options.html.erb +60 -0
  100. data/app/views/pager_tree/integrations/meta/workplace/v3/_form_options.html.erb +44 -0
  101. data/app/views/pager_tree/integrations/meta/workplace/v3/_show_options.html.erb +68 -0
  102. data/app/views/pager_tree/integrations/outgoing_webhook/v3/_form_options.html.erb +17 -3
  103. data/app/views/pager_tree/integrations/outgoing_webhook/v3/_show_options.html.erb +20 -0
  104. data/app/views/pager_tree/integrations/pulsetic/v3/_form_options.html.erb +0 -0
  105. data/app/views/pager_tree/integrations/pulsetic/v3/_show_options.html.erb +0 -0
  106. data/app/views/pager_tree/integrations/scom/v3/_form_options.html.erb +0 -0
  107. data/app/views/pager_tree/integrations/scom/v3/_show_options.html.erb +0 -0
  108. data/app/views/pager_tree/integrations/sentry/v3/_form_options.html.erb +9 -0
  109. data/app/views/pager_tree/integrations/sentry/v3/_show_options.html.erb +15 -0
  110. data/app/views/pager_tree/integrations/sixty_six_uptime/v3/_form_options.html.erb +0 -0
  111. data/app/views/pager_tree/integrations/sixty_six_uptime/v3/_show_options.html.erb +0 -0
  112. data/app/views/pager_tree/integrations/solar_winds/v3/_form_options.html.erb +40 -0
  113. data/app/views/pager_tree/integrations/solar_winds/v3/_show_options.html.erb +66 -0
  114. data/app/views/pager_tree/integrations/status_gator/v3/_form_options.html.erb +13 -0
  115. data/app/views/pager_tree/integrations/status_gator/v3/_show_options.html.erb +24 -0
  116. data/app/views/pager_tree/integrations/uptime_kuma/v3/_form_options.html.erb +0 -0
  117. data/app/views/pager_tree/integrations/uptime_kuma/v3/_show_options.html.erb +0 -0
  118. data/app/views/pager_tree/integrations/webhook/v3/_form_options.html.erb +8 -0
  119. data/app/views/pager_tree/integrations/webhook/v3/_show_options.html.erb +15 -0
  120. data/app/views/pager_tree/integrations/zabbix/v3/_form_options.html.erb +7 -0
  121. data/app/views/pager_tree/integrations/zabbix/v3/_show_options.html.erb +12 -0
  122. data/config/locales/en.yml +158 -10
  123. data/config/routes.rb +1 -0
  124. data/lib/pager_tree/integrations/format_converters/yaml_json_converter.rb +67 -0
  125. data/lib/pager_tree/integrations/version.rb +1 -1
  126. data/lib/pager_tree/integrations.rb +11 -3
  127. metadata +84 -8
@@ -4,6 +4,7 @@ module PagerTree::Integrations
4
4
  {key: :webhook_url, type: :string, default: nil},
5
5
  {key: :username, type: :string, default: nil},
6
6
  {key: :password, type: :string, default: nil},
7
+ {key: :proxy_url, type: :string, default: nil},
7
8
  {key: :alert_created, type: :boolean, default: false},
8
9
  {key: :alert_open, type: :boolean, default: false},
9
10
  {key: :alert_acknowledged, type: :boolean, default: false},
@@ -12,6 +13,11 @@ module PagerTree::Integrations
12
13
  {key: :alert_resolved, type: :boolean, default: false},
13
14
  {key: :alert_dropped, type: :boolean, default: false},
14
15
  {key: :alert_handoff, type: :boolean, default: false},
16
+ {key: :event_reminder_going_on_call, type: :boolean, default: false},
17
+ {key: :event_reminder_going_off_call, type: :boolean, default: false},
18
+ {key: :comment_created, type: :boolean, default: false},
19
+ {key: :comment_updated, type: :boolean, default: false},
20
+ {key: :comment_destroyed, type: :boolean, default: false},
15
21
  {key: :template, type: :string, default: nil},
16
22
  {key: :send_linked, type: :boolean, default: false},
17
23
  {key: :outgoing_rules, type: :string, default: nil}
@@ -19,6 +25,7 @@ module PagerTree::Integrations
19
25
  store_accessor :options, *OPTIONS.map { |x| x[:key] }.map(&:to_s), prefix: "option"
20
26
 
21
27
  validates :option_webhook_url, presence: true, url: {no_local: true}
28
+ validates :option_proxy_url, allow_blank: true, url: {no_local: true}
22
29
  validates :option_alert_created, inclusion: {in: [true, false]}
23
30
  validates :option_alert_open, inclusion: {in: [true, false]}
24
31
  validates :option_alert_acknowledged, inclusion: {in: [true, false]}
@@ -27,6 +34,11 @@ module PagerTree::Integrations
27
34
  validates :option_alert_resolved, inclusion: {in: [true, false]}
28
35
  validates :option_alert_dropped, inclusion: {in: [true, false]}
29
36
  validates :option_alert_handoff, inclusion: {in: [true, false]}
37
+ validates :option_event_reminder_going_on_call, inclusion: {in: [true, false]}
38
+ validates :option_event_reminder_going_off_call, inclusion: {in: [true, false]}
39
+ validates :option_comment_created, inclusion: {in: [true, false]}
40
+ validates :option_comment_updated, inclusion: {in: [true, false]}
41
+ validates :option_comment_destroyed, inclusion: {in: [true, false]}
30
42
  validates :option_send_linked, inclusion: {in: [true, false]}
31
43
 
32
44
  after_initialize do
@@ -38,6 +50,11 @@ module PagerTree::Integrations
38
50
  self.option_alert_resolved ||= false
39
51
  self.option_alert_dropped ||= false
40
52
  self.option_alert_handoff ||= false
53
+ self.option_event_reminder_going_on_call ||= false
54
+ self.option_event_reminder_going_off_call ||= false
55
+ self.option_comment_created ||= false
56
+ self.option_comment_updated ||= false
57
+ self.option_comment_destroyed ||= false
41
58
  self.option_send_linked ||= false
42
59
  self.option_template ||= ""
43
60
  self.option_outgoing_rules ||= ""
@@ -59,23 +76,32 @@ module PagerTree::Integrations
59
76
  false
60
77
  end
61
78
 
79
+ def adapter_supports_auto_aggregate?
80
+ false
81
+ end
82
+
83
+ def adapter_supports_auto_resolve?
84
+ false
85
+ end
86
+
62
87
  def adapter_outgoing_interest?(event_name)
63
88
  try("option_#{event_name}") || false
64
89
  end
65
90
 
66
91
  def adapter_process_outgoing
67
92
  body = nil
68
- event_type = adapter_outgoing_event.event_name.to_s.tr("_", ".")
93
+ event_type = _map_event_name(adapter_outgoing_event.event_name)
94
+ handlebars_data = {
95
+ alert: adapter_outgoing_event.alert&.try(:v3_format) || adapter_outgoing_event&.alert,
96
+ event: {
97
+ type: event_type
98
+ }
99
+ }.compact
69
100
 
70
101
  # Do the custom templating portion for outgoing hooks
71
- if self.option_template.present?
102
+ if option_template.present?
72
103
  begin
73
- body = JSON.parse(handlebars(self.option_template, {
74
- alert: adapter_outgoing_event.alert.try(:v3_format) || adapter_outgoing_event.alert,
75
- event: {
76
- type: event_type
77
- }
78
- }))
104
+ body = JSON.parse(handlebars(option_template, handlebars_data))
79
105
  rescue JSON::ParserError => e
80
106
  logs.create(message: "Error parsing JSON, abort custom format for option template. Error: #{e.message}")
81
107
  rescue => e
@@ -83,10 +109,69 @@ module PagerTree::Integrations
83
109
  end
84
110
  end
85
111
 
86
- body ||= {
87
- data: adapter_outgoing_event.alert.try(:v3_format) || adapter_outgoing_event.alert,
88
- type: event_type
89
- }
112
+ if !body.present?
113
+ body = {}
114
+ body[:type] = event_type
115
+ body[:data] = case event_type
116
+ when "comment.destroyed"
117
+ {
118
+ account_id: adapter_outgoing_event.account_id,
119
+ id: adapter_outgoing_event.item_id
120
+ }
121
+ when "comment.created", "comment.updated"
122
+ {
123
+ account_id: adapter_outgoing_event.comment.account_id,
124
+ id: adapter_outgoing_event.comment.id,
125
+ prefix_id: adapter_outgoing_event.comment.prefix_id,
126
+ meta: adapter_outgoing_event.comment.meta,
127
+ commentable_type: adapter_outgoing_event.comment.commentable_type,
128
+ commentable_id: adapter_outgoing_event.comment.commentable_id,
129
+ parent_id: adapter_outgoing_event.comment.parent_id,
130
+ account_user_id: adapter_outgoing_event.comment.account_user_id,
131
+ account_user: {
132
+ id: adapter_outgoing_event.comment.account_user.id,
133
+ prefix_id: adapter_outgoing_event.comment.account_user.prefix_id,
134
+ user: {
135
+ id: adapter_outgoing_event.comment.account_user.user.id,
136
+ prefix_id: adapter_outgoing_event.comment.account_user.user.prefix_id,
137
+ name: adapter_outgoing_event.comment.account_user.user.name,
138
+ email: adapter_outgoing_event.comment.account_user.user.email
139
+ }
140
+ },
141
+ created_by_name: adapter_outgoing_event.comment.created_by_name,
142
+ updated_at: adapter_outgoing_event.comment.updated_at,
143
+ created_at: adapter_outgoing_event.comment.created_at,
144
+ body: adapter_outgoing_event.comment.body.to_plain_text
145
+ }
146
+ when "event_reminder.going_on_call", "event_reminder.going_off_call"
147
+ {
148
+ id: adapter_outgoing_event.event_reminder.id,
149
+ prefix_id: adapter_outgoing_event.event_reminder.prefix_id,
150
+ event: {
151
+ id: adapter_outgoing_event.event_reminder.event.id,
152
+ prefix_id: adapter_outgoing_event.event_reminder.event.prefix_id,
153
+ start_time: adapter_outgoing_event.event_reminder.next_start.in_time_zone(adapter_outgoing_event.event_reminder.event.time_zone),
154
+ end_time: adapter_outgoing_event.event_reminder.next_end.in_time_zone(adapter_outgoing_event.event_reminder.event.time_zone),
155
+ time_zone: adapter_outgoing_event.event_reminder.event.time_zone,
156
+ iana_time_zone: adapter_outgoing_event.event_reminder.event.iana_time_zone,
157
+ layer: adapter_outgoing_event.event_reminder.event.layer,
158
+ teams: adapter_outgoing_event.event_reminder.event.teams.map { |x| {id: x.id, tiny_id: x.tiny_id, prefix_id: x.prefix_id, name: x.name} },
159
+ account_user: {
160
+ id: adapter_outgoing_event.event_reminder.account_user.id,
161
+ prefix_id: adapter_outgoing_event.event_reminder.account_user.prefix_id,
162
+ user: {
163
+ id: adapter_outgoing_event.event_reminder.account_user.user.id,
164
+ prefix_id: adapter_outgoing_event.event_reminder.account_user.user.prefix_id,
165
+ name: adapter_outgoing_event.event_reminder.account_user.user.name,
166
+ email: adapter_outgoing_event.event_reminder.account_user.user.email
167
+ }
168
+ }
169
+ }
170
+ }
171
+ else
172
+ adapter_outgoing_event.alert&.try(:v3_format) || adapter_outgoing_event&.alert
173
+ end
174
+ end
90
175
 
91
176
  url = adapter_outgoing_event.outgoing_rules_data.dig("webhook_url") || option_webhook_url
92
177
  body.merge!(adapter_outgoing_event.outgoing_rules_data.except("webhook_url"))
@@ -95,12 +180,22 @@ module PagerTree::Integrations
95
180
  resource: self,
96
181
  url: url,
97
182
  auth: {username: option_username, password: option_password},
98
- body: body
183
+ body: body,
184
+ proxy_url: option_proxy_url.presence
99
185
  )
100
186
  outgoing_webhook_delivery.save!
101
187
  outgoing_webhook_delivery.deliver_later
102
188
 
103
189
  outgoing_webhook_delivery
104
190
  end
191
+
192
+ def _map_event_name(event_name)
193
+ case event_name
194
+ when "event_reminder_going_on_call" then "event_reminder.going_on_call"
195
+ when "event_reminder_going_off_call" then "event_reminder.going_off_call"
196
+ else
197
+ event_name.to_s.tr("_", ".")
198
+ end
199
+ end
105
200
  end
106
201
  end
@@ -4,6 +4,10 @@ module PagerTree::Integrations
4
4
 
5
5
  define_model_callbacks :deliver
6
6
 
7
+ def self.factory(**params)
8
+ new(**params)
9
+ end
10
+
7
11
  def self.hook_relay_account_id
8
12
  find_value_by_name(:hook_relay, :account_id)
9
13
  end
@@ -31,35 +35,7 @@ module PagerTree::Integrations
31
35
  def deliver
32
36
  run_callbacks :deliver do
33
37
  begin
34
- hook_relay_options = {
35
- headers: {
36
- HR_TARGET_URL: url
37
- }
38
- }
39
-
40
- pagertree_options = {
41
- headers: {
42
- Accept: "*/*",
43
- "User-Agent": "pagertree outgoing webhook service; ref: #{resource&.id}; report: support@pagertree.com",
44
- "Content-Type": "application/json"
45
- }
46
- }
47
-
48
- auth_options = {}
49
- if auth.is_a?(Hash) && (username = auth.dig(:username)).present? && (password = auth.dig(:password)).present?
50
- auth_options = {
51
- headers: {
52
- Authorization: Base64.strict_encode64("#{username}:#{password}")
53
- }
54
- }
55
- end
56
-
57
- options = OutgoingWebhookDelivery::HTTP_OPTIONS
58
- .deep_merge(hook_relay_options)
59
- .deep_merge(pagertree_options)
60
- .deep_merge(auth_options)
61
-
62
- response = HTTParty.post(hook_relay_hook_url, body: body.to_json, **options)
38
+ response = HTTParty.post(hook_relay_hook_url, body: body.to_json, **httparty_opts)
63
39
 
64
40
  self.thirdparty_id = response["id"]
65
41
  self.status = :sent
@@ -71,19 +47,53 @@ module PagerTree::Integrations
71
47
  end # run_callbacks
72
48
  end
73
49
 
50
+ def httparty_opts
51
+ hook_relay_options = {
52
+ headers: {
53
+ "HR_TARGET_URL" => url
54
+ }
55
+ }
56
+
57
+ pagertree_options = {
58
+ headers: {
59
+ "Accept" => "*/*",
60
+ "User-Agent" => "pagertree outgoing webhook service; ref: #{resource&.id}; report: support@pagertree.com",
61
+ "Content-Type" => "application/json"
62
+ }
63
+ }
64
+
65
+ auth_options = {}
66
+ if auth.is_a?(Hash)
67
+ auth_indifferent = auth.with_indifferent_access
68
+ if (username = auth_indifferent.dig(:username)).present? && (password = auth_indifferent.dig(:password)).present?
69
+ auth_options = {
70
+ headers: {
71
+ "Authorization" => Base64.strict_encode64("#{username}:#{password}")
72
+ }
73
+ }
74
+ end
75
+ end
76
+
77
+ OutgoingWebhookDelivery::HTTP_OPTIONS
78
+ .deep_merge(hook_relay_options)
79
+ .deep_merge(pagertree_options)
80
+ .deep_merge(auth_options)
81
+ .deep_merge(options&.symbolize_keys || {})
82
+ end
83
+
74
84
  def delivery
75
85
  return @delivery if @delivery
76
86
  return {} unless thirdparty_id
77
87
 
78
- options = {
88
+ opts = {
79
89
  headers: {
80
- "Content-Type": "application/json",
81
- Authorization: "Bearer #{OutgoingWebhookDelivery::HookRelay.hook_relay_api_key}"
90
+ "Content-Type" => "application/json",
91
+ "Authorization" => "Bearer #{OutgoingWebhookDelivery::HookRelay.hook_relay_api_key}"
82
92
  },
83
93
  timeout: 15
84
94
  }
85
95
 
86
- response = ::HTTParty.get(hook_relay_delivery_url, **options)
96
+ response = ::HTTParty.get(hook_relay_delivery_url, **opts)
87
97
  @delivery = response.parsed_response if response.success?
88
98
 
89
99
  @delivery || {}
@@ -1,14 +1,14 @@
1
1
  module PagerTree::Integrations
2
- class OutgoingWebhookDelivery < PagerTree::Integrations.outgoing_webhook_delivery_parent_class.constantize
2
+ class OutgoingWebhookDelivery < ApplicationRecord
3
3
  self.table_name = PagerTree::Integrations.outgoing_webhook_delivery_table_name
4
4
 
5
- serialize :data, JSON
5
+ serialize :data, coder: JSON
6
6
  encrypts :data
7
7
 
8
- store_accessor :data, *[:url, :body, :auth].map(&:to_s)
8
+ store_accessor :data, *[:url, :body, :auth, :proxy_url, :options].map(&:to_s)
9
9
 
10
10
  HTTP_OPTIONS = {
11
- headers: {"Content-Type": "application/json"},
11
+ headers: {"Content-Type" => "application/json"},
12
12
  timeout: 15
13
13
  }
14
14
 
@@ -16,7 +16,8 @@ module PagerTree::Integrations
16
16
  enum status: {queued: 0, sent: 1, success: 2, failure: 3, retrying: 4, cancelled: 5, stored: 6, insufficent_funds: 7}
17
17
 
18
18
  def self.factory(**params)
19
- PagerTree::Integrations.outgoing_webhook_delivery_factory_class.constantize.new(**params)
19
+ klass = PagerTree::Integrations.outgoing_webhook_delivery_factory_class
20
+ (klass.is_a?(Proc) ? klass.call : klass.to_s).constantize.new(**params)
20
21
  end
21
22
  end
22
23
  end
@@ -25,7 +25,8 @@ module PagerTree::Integrations
25
25
  def adapter_action
26
26
  status = adapter_incoming_request_params.dig("status").to_s.downcase
27
27
 
28
- if status == "down"
28
+ # %status is a special value that PRTG uses to indicate that will be used in the test webhook
29
+ if status == "down" || status == "%status"
29
30
  :create
30
31
  elsif status.include?("now: up")
31
32
  :resolve
@@ -0,0 +1,70 @@
1
+ module PagerTree::Integrations
2
+ class Pulsetic::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 = adapter_incoming_request_params.dig("monitor", "id")
23
+ typ = (_alert_type == "certificate_expires_soon") ? "certificate" : "monitor"
24
+ "#{id}_#{typ}"
25
+ end
26
+
27
+ def adapter_action
28
+ case _alert_type
29
+ when "monitor_offline", "certificate_expires_soon"
30
+ :create
31
+ when "monitor_online"
32
+ :resolve
33
+ else
34
+ :other
35
+ end
36
+ end
37
+
38
+ def adapter_process_create
39
+ Alert.new(
40
+ title: _title,
41
+ thirdparty_id: adapter_thirdparty_id,
42
+ additional_data: _additional_datums
43
+ )
44
+ end
45
+
46
+ private
47
+
48
+ def _title
49
+ case _alert_type
50
+ when "monitor_offline"
51
+ "#{adapter_incoming_request_params.dig("monitor", "url")} OFFLINE"
52
+ when "certificate_expires_soon"
53
+ "#{adapter_incoming_request_params.dig("monitor", "url")} CERTIFICATE EXPIRES SOON"
54
+ else
55
+ "[PULSETIC] UNKNOWN ALERT TYPE"
56
+ end
57
+ end
58
+
59
+ def _alert_type
60
+ adapter_incoming_request_params.dig("alert_type")
61
+ end
62
+
63
+ def _additional_datums
64
+ [
65
+ AdditionalDatum.new(format: "link", label: "Monitor", value: "https://app.pulsetic.com/monitors/#{adapter_incoming_request_params.dig("monitor", "id")}/overview"),
66
+ AdditionalDatum.new(format: "link", label: "URL", value: adapter_incoming_request_params.dig("monitor", "url"))
67
+ ]
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,153 @@
1
+ Param (
2
+ [parameter(Mandatory=$true, HelpMessage="You must provide the Url contained in your SCOM Integration's settings in PagerTree UI.")][String]$Url,
3
+ [String]$AlertID,
4
+ [String]$ResolutionStateLastModified,
5
+ [String]$CreatedByMonitor,
6
+ [String]$ManagedEntitySource,
7
+ [String]$WorkflowId,
8
+ [String]$DataItemCreateTimeLocal,
9
+ [String]$ManagedEntityPath,
10
+ [String]$ManagedEntity,
11
+ [String]$MPElement = "NotPresent",
12
+ [String]$scomModulePath,
13
+ [Switch]$install,
14
+ [Switch]$enableLogging
15
+ )
16
+
17
+ [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
18
+
19
+ $logfile = "C:\scripts\pagertree\log.csv"
20
+ $timeStampFormat = "MM-dd-yyyy HH:mm:ss"
21
+ $IntegrationLogEntry = ""
22
+
23
+
24
+ function Add-PagerTreeIntegrationLogEntry {
25
+ Param (
26
+ [parameter(Mandatory=$true, HelpMessage="This function is expecting log level as a string.")][String]$logLevel,
27
+ [parameter(Mandatory=$true, HelpMessage="This function is expecting a log message as a string.")][String]$logMessage
28
+ )
29
+ $logMessage=$logMessage.Replace('"','""')
30
+ $timestamp = get-date -Format $timeStampFormat
31
+ $script:IntegrationLogEntry = "$($IntegrationLogEntry)`"$($timestamp)`",`"$($logLevel)`",`"$($AlertID)`",`"$($logMessage)`"`n"
32
+ }
33
+
34
+
35
+
36
+ if ($enableLogging){if (-not (Test-Path -LiteralPath $logfile -PathType Leaf)){Write-Output "`"TimeStamp`",`"LogLevel`",`"SCOMAlertId`",`"LogMessage`"" | Out-File $logfile -Append};Add-PagerTreeIntegrationLogEntry -logLevel "INFO" -logMessage "PagerTree integration script has started for alertId $($alertID)"}
37
+
38
+
39
+
40
+ Import-Module OperationsManager
41
+ if ($?){write-host -ForegroundColor Green "Module has been successfully imported.";echo ""; echo ""}
42
+ else {
43
+ if (!$scomModulePath){
44
+ Write-Host "Attempting to locate SCOM installation path."; echo ""; echo ""
45
+ if (Test-Path "C:\Program Files\Microsoft System Center 2012"){$scomModulePath = "C:\Program Files\Microsoft System Center 2012\Operations Manager\Powershell\OperationsManager\OperationsManager.psm1"; Write-Host -NoNewline "Trying to locate 'C:\Program Files\Microsoft System Center 2012' : "; Write-Host -ForegroundColor Green "SCOM 2012 Install path found"}
46
+ if (!$scomModulePath){Write-Host -NoNewline "Trying to locate 'C:\Program Files\Microsoft System Center 2012' : "; Write-Host -ForegroundColor Yellow "SCOM 2012 Install path not found"}
47
+ if (Test-Path "C:\Program Files\Microsoft System Center 2012 R2"){$scomModulePath = "C:\Program Files\Microsoft System Center 2012 R2\Operations Manager\Powershell\OperationsManager\OperationsManager.psm1"; Write-Host -NoNewline "Trying to locate 'C:\Program Files\Microsoft System Center 2012 R2' : "; Write-Host -ForegroundColor Green "SCOM 2012 R2 Install path found"}
48
+ if (!$scomModulePath){Write-Host -NoNewline "Trying to locate 'C:\Program Files\Microsoft System Center 2012 R2' : "; Write-Host -ForegroundColor Yellow "SCOM 2012 R2 Install path not found"}
49
+ if (Test-Path "C:\Program Files\Microsoft System Center 2016"){$scomModulePath = "C:\Program Files\Microsoft System Center 2016\Operations Manager\Powershell\OperationsManager\OperationsManager.psm1"; Write-Host -NoNewline "Trying to locate 'C:\Program Files\Microsoft System Center 2016' : "; Write-Host -ForegroundColor Green "SCOM 2016 Install path found"}
50
+ if (!$scomModulePath){Write-Host -NoNewline "Trying to locate 'C:\Program Files\Microsoft System Center 2016' : "; Write-Host -ForegroundColor Yellow "SCOM 2016 Install path not found"}
51
+ if (Test-Path "C:\Program Files\Microsoft System Center 2019"){$scomModulePath = "C:\Program Files\Microsoft System Center 2019\Operations Manager\Powershell\OperationsManager\OperationsManager.psm1"; Write-Host -NoNewline "Trying to locate 'C:\Program Files\Microsoft System Center 2019' : "; Write-Host -ForegroundColor Green "SCOM 2019 Install path found"}
52
+ if (!$scomModulePath){Write-Host -NoNewline "Trying to locate 'C:\Program Files\Microsoft System Center 2019' : "; Write-Host -ForegroundColor Yellow "SCOM 2019 Install path not found"}
53
+ if (Test-Path "C:\Program Files\Microsoft System Center"){$scomModulePath = "C:\Program Files\Microsoft System Center\Operations Manager\Powershell\OperationsManager\OperationsManager.psm1"; Write-Host -NoNewline "Trying to locate 'C:\Program Files\Microsoft System Center' : "; Write-Host -ForegroundColor Green "SCOM Install path found"}
54
+ if (!$scomModulePath){Write-Host -NoNewline "Trying to locate 'C:\Program Files\Microsoft System Center' : "; Write-Host -ForegroundColor Yellow "SCOM Install path not found"}
55
+ }
56
+ else {Import-Module $scomModulePath}
57
+ echo ""; echo ""; Write-host -NoNewline "Attempting to import Operations Manager Powershell Module : "
58
+ Import-Module $scomModulePath
59
+ if ($?){write-host -ForegroundColor Green "Module has been successfully imported.";echo ""; echo ""} else {echo ""; echo ""; write-host -NoNewline -ForegroundColor Yellow "Could not improt module try specifying it using ";write-host -NoNewline -ForegroundColor Cyan "-scomModulePath <path>";write-host -ForegroundColor yellow " when starting this script.";exit}
60
+ }
61
+
62
+
63
+ function Install-ptIntegration{
64
+ $PsCommandArgs = "-executionpolicy bypass -File `"C:\scripts\pagertree\pagertree.ps1`" -Url `""+$Url+"`" -AlertID `"`$Data[Default='NotPresent']/Context/DataItem/AlertId$`" -CreatedByMonitor `"`$Data[Default='NotPresent']/Context/DataItem/CreatedByMonitor$`" -ManagedEntitySource `"`$Data[Default='NotPresent']/Context/DataItem/ManagedEntityDisplayName$`" -WorkflowId `"`$Data[Default='NotPresent']/Context/DataItem/WorkflowId$`" -DataItemCreateTimeLocal `"`$Data[Default='NotPresent']/Context/DataItem/DataItemCreateTimeLocal$`" -ManagedEntityPath `"`$Data[Default='NotPresent']/Context/DataItem/ManagedEntityPath$`" -ManagedEntity `"`$Data[Default='NotPresent']/Context/DataItem/ManagedEntity$`" -MPElement `"`$MPElement$`""
65
+ Write-host -ForegroundColor Cyan "Creating PagerTree Notification Channel."
66
+ Add-SCOMNotificationChannel -ApplicationPath ($PSHOME+"\Powershell.exe") -Name "PagerTree" -Argument $PsCommandArgs -WorkingDirectory $PSHOME
67
+ if ($?){write-host -ForegroundColor Green "PagerTree Notification Channel has been successfully created.";echo ""; echo ""} else {echo ""; write-host -ForegroundColor Yellow "Failed to create PagerTree Notification Channel!!!";exit}
68
+
69
+ Write-host -ForegroundColor Cyan "Creating PagerTree Notification Subscriber.";echo ""
70
+ Add-SCOMNotificationSubscriber -name "PagerTree" -DeviceList "PagerTree"
71
+ if ($?){write-host -ForegroundColor Green "PagerTree Notification Subscriber has been successfully created.";echo ""; echo ""} else {echo ""; write-host -ForegroundColor Yellow "Failed to create PagerTree Notification Subscriber!!!";exit}
72
+
73
+ Write-host -ForegroundColor Cyan "Creating PagerTree Notification Subscription.";echo ""
74
+ $subscriber = Get-SCOMNotificationSubscriber "PagerTree"
75
+ $channel = Get-SCOMNotificationChannel "PagerTree"
76
+ Add-SCOMNotificationSubscription -Name ("PagerTree"+"_Subscription") -Subscriber $subscriber -Channel $channel
77
+ if ($?){write-host -ForegroundColor Green "PagerTree Notification Subscription has been successfully created.";echo ""} else {echo ""; write-host -ForegroundColor Yellow "Failed to create PagerTree Notification Subscription!!!";exit}
78
+
79
+ Write-Host -ForegroundColor Green "PagerTree Integration setup has completed successfully"
80
+ exit
81
+ }
82
+
83
+
84
+ if ($install){Install-ptIntegration}
85
+
86
+
87
+ try {
88
+ $alert = Get-SCOMAlert -Id $alertID
89
+ if ($enableLogging) {
90
+ $linebreak ="
91
+ "
92
+ if ($enableLogging){Add-PagerTreeIntegrationLogEntry -logLevel "INFO" -logMessage "The following SCOM alert details has been retrieved: alertName='$($alert.name)',alertDescription='$($alert.Description.replace($linebreak," "))',resolutionStateLastModified='$($alert.TimeResolutionStateLastModified)',priority='$($alert.Priority)',owner='$($alert.Owner)',repeatCount='$($alert.RepeatCount)',severity='$($alert.Severity)',category'$($alert.Category)'"}
93
+ }
94
+ }
95
+ catch {
96
+ if ($enableLogging){Add-PagerTreeIntegrationLogEntry -logLevel "ERROR" -logMessage "PagerTree integration script has failed to retrieve SCOM alert: Exception Type='$($_.Exception.GetType().FullName)',Exception Message='$($_.Exception.Message)'"}
97
+ write-output $IntegrationLogEntry | Out-File $logfile -Append
98
+ exit
99
+ }
100
+
101
+
102
+ $params = @{
103
+ alertId = $AlertID
104
+ alertName = if($alert.Name) {$alert.Name} else {"Not Present"}
105
+ alertDescription = if($alert.Description) {$alert.Description} else {"Not Present"}
106
+ resolutionState = if($alert.ResolutionState -eq 0) {"New"} elseif($alert.ResolutionState -eq 255) {"Closed"} else {"Not Present"}
107
+ resolutionStateLastModified = if($alert.TimeResolutionStateLastModified) {$alert.TimeResolutionStateLastModified.ToString()} else {"Not Present"}
108
+ priority = if($alert.Priority) {$alert.Priority.ToString()} else {"Not Present"}
109
+ owner = if($alert.Owner) {$alert.Owner} else {"Not Present"}
110
+ repeatCount = if($alert.RepeatCount) {$alert.RepeatCount.ToString()} else {"Not Present"}
111
+ severity = if($alert.Severity) {$alert.Severity.ToString()} else {"Not Present"}
112
+ category = if($alert.Category) {$alert.Category.ToString()} else {"Not Present"}
113
+ createdByMonitor = $CreatedByMonitor
114
+ managedEntitySource = $ManagedEntitySource
115
+ workflowId = $WorkflowId
116
+ lastModified = if($alert.LastModified) {$alert.LastModified.ToString()} else {"Not Present"}
117
+ timeRaised = if($alert.TimeRaised) {$alert.TimeRaised.ToString()} else {"Not Present"}
118
+ ticketId = if($alert.TicketId) {$alert.TicketId.ToString()} else {"Not Present"}
119
+ dataItemCreateTime = $DataItemCreateTimeLocal
120
+ managedEntityPath = $ManagedEntityPath
121
+ managedEntityGUID = $ManagedEntity
122
+ timeAdded = if($alert.TimeAdded) {$alert.TimeAdded.ToString()} else {"Not Present"}
123
+ mpElement = $MPElement
124
+ customField1 = if($alert.CustomField1) {$alert.CustomField1} else {"Not Present"}
125
+ customField2 = if($alert.CustomField2) {$alert.CustomField2} else {"Not Present"}
126
+ customField3 = if($alert.CustomField3) {$alert.CustomField3} else {"Not Present"}
127
+ customField4 = if($alert.CustomField4) {$alert.CustomField4} else {"Not Present"}
128
+ customField5 = if($alert.CustomField5) {$alert.CustomField5} else {"Not Present"}
129
+ customField6 = if($alert.CustomField6) {$alert.CustomField6} else {"Not Present"}
130
+ customField7 = if($alert.CustomField7) {$alert.CustomField7} else {"Not Present"}
131
+ customField8 = if($alert.CustomField8) {$alert.CustomField8} else {"Not Present"}
132
+ customField9 = if($alert.CustomField9) {$alert.CustomField9} else {"Not Present"}
133
+ customField10 = if($alert.CustomField10) {$alert.CustomField10} else {"Not Present"}
134
+ }
135
+
136
+
137
+ if ($params.resolutionstate -match "Not Present"){
138
+ if ($enableLogging){Add-PagerTreeIntegrationLogEntry -logLevel "WARNING" -logMessage "The following SCOM alert $($alert.id) will not be sent to PagerTree as it does not contain resolutionState `"New`" or `"Closed`"."}
139
+ }
140
+ else {
141
+ $json = ConvertTo-Json -InputObject $params
142
+
143
+
144
+ try {
145
+ $pagertree_Request = Invoke-RestMethod -Method Post -ContentType "application/json" -Body $json -Uri $Url
146
+ if ($enableLogging){Add-PagerTreeIntegrationLogEntry -logLevel "INFO" -logMessage "Successfully posted SCOM alert to PagerTree integration endpoint!"}
147
+ }
148
+
149
+ catch {
150
+ if ($enableLogging){Add-PagerTreeIntegrationLogEntry -logLevel "ERROR" -logMessage "PagerTree integration script has failed to POST SCOM alert details to the PagerTree integration endpoint: Exception Type='$($_.Exception.GetType().FullName)',Exception Message='$($_.Exception.Message)'"}
151
+ }
152
+ }
153
+ if ($enableLogging){write-output $IntegrationLogEntry | Out-File $logfile -Append}
@@ -0,0 +1,58 @@
1
+ module PagerTree::Integrations
2
+ class Scom::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
+ adapter_incoming_request_params.dig("alertId")
23
+ end
24
+
25
+ def adapter_action
26
+ case adapter_incoming_request_params.dig("resolutionState")
27
+ when "New" then :create
28
+ when "Closed" then :resolve
29
+ else
30
+ :other
31
+ end
32
+ end
33
+
34
+ def adapter_process_create
35
+ Alert.new(
36
+ title: _title,
37
+ description: _description,
38
+ thirdparty_id: adapter_thirdparty_id,
39
+ dedup_keys: [],
40
+ additional_data: _additional_datums
41
+ )
42
+ end
43
+
44
+ private
45
+
46
+ def _title
47
+ adapter_incoming_request_params.dig("alertName")
48
+ end
49
+
50
+ def _description
51
+ adapter_incoming_request_params.dig("alertDescription")
52
+ end
53
+
54
+ def _additional_datums
55
+ []
56
+ end
57
+ end
58
+ end