kennel 1.159.0 → 1.161.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 +4 -4
- data/lib/kennel/api.rb +5 -5
- data/lib/kennel/importer.rb +3 -5
- data/lib/kennel/models/dashboard.rb +2 -1
- data/lib/kennel/models/monitor.rb +4 -1
- data/lib/kennel/syncer.rb +27 -15
- data/lib/kennel/version.rb +1 -1
- data/lib/kennel.rb +7 -7
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 856d925b4aeee8af7171cb092b746c70c8e21cfa06a1987910a25ef193e79a50
|
4
|
+
data.tar.gz: c174845463912362beba00a86f63d11316ec54f0a57459e4c6cd32e0d1d358d4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 328b385c98c37473d65799e1721da32f9a8ff4d4d238be42a37196aea6e880d5ce1ae76dfb5ec8ffd4e6f60c70c99af070566b09c3fa4c34032d431b4e2a6189
|
7
|
+
data.tar.gz: f74557a8ff3fe9ee436034774ed1fe5c5176e9919114e48241f08f3ffbc3950b2a32d25574d9d99c1a3c6470d3381d2880b356a7a54cc2795c2f13b4843980af
|
data/lib/kennel/api.rb
CHANGED
@@ -7,7 +7,7 @@ module Kennel
|
|
7
7
|
|
8
8
|
RateLimitParams = Data.define(:limit, :period, :remaining, :reset, :name)
|
9
9
|
|
10
|
-
def self.
|
10
|
+
def self.with_tracking(api_resource, reply)
|
11
11
|
klass = Models::Record.api_resource_map[api_resource]
|
12
12
|
return reply unless klass # do not blow up on unknown models
|
13
13
|
|
@@ -28,7 +28,7 @@ module Kennel
|
|
28
28
|
response = request :get, "/api/v1/#{api_resource}/#{id}", params: params
|
29
29
|
response = response.fetch(:data) if api_resource == "slo"
|
30
30
|
response[:id] = response.delete(:public_id) if api_resource == "synthetics/tests"
|
31
|
-
self.class.
|
31
|
+
self.class.with_tracking(api_resource, response)
|
32
32
|
end
|
33
33
|
|
34
34
|
def list(api_resource, params = {})
|
@@ -44,7 +44,7 @@ module Kennel
|
|
44
44
|
# ignore monitor synthetics create and that inherit the kennel_id, we do not directly manage them
|
45
45
|
response.reject! { |m| m[:type] == "synthetics alert" } if api_resource == "monitor"
|
46
46
|
|
47
|
-
response.map { |r| self.class.
|
47
|
+
response.map { |r| self.class.with_tracking(api_resource, r) }
|
48
48
|
end
|
49
49
|
end
|
50
50
|
|
@@ -52,13 +52,13 @@ module Kennel
|
|
52
52
|
response = request :post, "/api/v1/#{api_resource}", body: attributes
|
53
53
|
response = response.fetch(:data).first if api_resource == "slo"
|
54
54
|
response[:id] = response.delete(:public_id) if api_resource == "synthetics/tests"
|
55
|
-
self.class.
|
55
|
+
self.class.with_tracking(api_resource, response)
|
56
56
|
end
|
57
57
|
|
58
58
|
def update(api_resource, id, attributes)
|
59
59
|
response = request :put, "/api/v1/#{api_resource}/#{id}", body: attributes
|
60
60
|
response[:id] = response.delete(:public_id) if api_resource == "synthetics/tests"
|
61
|
-
self.class.
|
61
|
+
self.class.with_tracking(api_resource, response)
|
62
62
|
end
|
63
63
|
|
64
64
|
# - force=true to not dead-lock on dependent monitors+slos
|
data/lib/kennel/importer.rb
CHANGED
@@ -14,10 +14,6 @@ module Kennel
|
|
14
14
|
end
|
15
15
|
|
16
16
|
def import(resource, id)
|
17
|
-
if ["screen", "dash"].include?(resource)
|
18
|
-
raise ArgumentError, "resource 'screen' and 'dash' are deprecated, use 'dashboard'"
|
19
|
-
end
|
20
|
-
|
21
17
|
model =
|
22
18
|
Kennel::Models::Record.subclasses.detect { |c| c.api_resource == resource } ||
|
23
19
|
raise(ArgumentError, "#{resource} is not supported")
|
@@ -51,7 +47,9 @@ module Kennel
|
|
51
47
|
data.merge!(data.delete(:thresholds) || {})
|
52
48
|
|
53
49
|
# clean up values that are the default
|
54
|
-
|
50
|
+
if !!data[:notify_no_data] == !Models::Monitor::SKIP_NOTIFY_NO_DATA_TYPES.include?(data[:type])
|
51
|
+
data.delete(:notify_no_data)
|
52
|
+
end
|
55
53
|
data.delete(:notify_audit) unless data[:notify_audit] # Monitor uses false by default
|
56
54
|
|
57
55
|
# keep all values that are settable
|
@@ -30,6 +30,7 @@ module Kennel
|
|
30
30
|
}.freeze
|
31
31
|
DEFAULT_ESCALATION_MESSAGE = ["", nil].freeze
|
32
32
|
ALLOWED_PRIORITY_CLASSES = [NilClass, Integer].freeze
|
33
|
+
SKIP_NOTIFY_NO_DATA_TYPES = ["event alert", "event-v2 alert", "log alert"].freeze
|
33
34
|
|
34
35
|
settings(
|
35
36
|
:query, :name, :message, :escalation_message, :critical, :type, :renotify_interval, :warning, :timeout_h, :evaluation_delay,
|
@@ -44,7 +45,9 @@ module Kennel
|
|
44
45
|
renotify_interval: -> { project.team.renotify_interval },
|
45
46
|
warning: -> { nil },
|
46
47
|
ok: -> { nil },
|
47
|
-
|
48
|
+
# datadog UI sets this to false by default, but true is safer
|
49
|
+
# except for log alerts which will always have "no error" gaps and should default to false
|
50
|
+
notify_no_data: -> { !SKIP_NOTIFY_NO_DATA_TYPES.include?(type) },
|
48
51
|
no_data_timeframe: -> { 60 },
|
49
52
|
notify_audit: -> { MONITOR_OPTION_DEFAULTS.fetch(:notify_audit) },
|
50
53
|
new_host_delay: -> { MONITOR_OPTION_DEFAULTS.fetch(:new_host_delay) },
|
data/lib/kennel/syncer.rb
CHANGED
@@ -91,21 +91,7 @@ module Kennel
|
|
91
91
|
matching, unmatched_expected, unmatched_actual = MatchedExpected.partition(expected, actual)
|
92
92
|
unmatched_actual.select! { |a| a.fetch(:tracking_id) } # ignore items that were never managed by kennel
|
93
93
|
|
94
|
-
|
95
|
-
# careful with unmatched_expected being huge since it has all api resources
|
96
|
-
unmatched_expected.reject! do |e|
|
97
|
-
actual = unmatched_actual.detect do |a|
|
98
|
-
a[:klass] == e.class &&
|
99
|
-
Kennel::Models::Record::TITLE_FIELDS.any? { |f| (set = a[f]) && set == e.as_json.fetch(f) }
|
100
|
-
end
|
101
|
-
next false unless actual # keep in unmatched
|
102
|
-
|
103
|
-
unmatched_actual.delete(actual)
|
104
|
-
actual[:tracking_id] = e.tracking_id
|
105
|
-
matching << [e, actual]
|
106
|
-
|
107
|
-
true # remove from unmatched
|
108
|
-
end
|
94
|
+
convert_replace_into_update!(matching, unmatched_actual, unmatched_expected)
|
109
95
|
|
110
96
|
validate_expected_id_not_missing unmatched_expected
|
111
97
|
fill_details! matching # need details to diff later
|
@@ -137,6 +123,32 @@ module Kennel
|
|
137
123
|
end
|
138
124
|
end
|
139
125
|
|
126
|
+
# if there is a new item that has the same name or title as an "to be deleted" item,
|
127
|
+
# update it instead to avoid old urls from becoming invalid
|
128
|
+
# - careful with unmatched_actual being huge since it has all api resources
|
129
|
+
# - don't do it when a monitor type is changing since that would block the update
|
130
|
+
def convert_replace_into_update!(matching, unmatched_actual, unmatched_expected)
|
131
|
+
unmatched_expected.reject! do |e|
|
132
|
+
e_field, e_value = Kennel::Models::Record::TITLE_FIELDS.detect do |field|
|
133
|
+
next unless (value = e.as_json[field])
|
134
|
+
break [field, value]
|
135
|
+
end
|
136
|
+
raise unless e_field # uncovered: should never happen ...
|
137
|
+
e_monitor_type = e.as_json[:type]
|
138
|
+
|
139
|
+
actual = unmatched_actual.detect do |a|
|
140
|
+
a[:klass] == e.class && a[e_field] == e_value && a[:type] == e_monitor_type
|
141
|
+
end
|
142
|
+
next false unless actual # keep in unmatched
|
143
|
+
|
144
|
+
# add as update and remove from unmatched
|
145
|
+
unmatched_actual.delete(actual)
|
146
|
+
actual[:tracking_id] = e.tracking_id
|
147
|
+
matching << [e, actual]
|
148
|
+
true
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
140
152
|
# fill details of things we need to compare
|
141
153
|
def fill_details!(details_needed)
|
142
154
|
details_needed = details_needed.map { |e, a| a if e && e.class.api_resource == "dashboard" }.compact
|
data/lib/kennel/version.rb
CHANGED
data/lib/kennel.rb
CHANGED
@@ -131,13 +131,13 @@ module Kennel
|
|
131
131
|
|
132
132
|
# performance: this takes ~100ms on large codebases, tried rewriting with Set or Hash but it was slower
|
133
133
|
def validate_unique_tracking_ids(parts)
|
134
|
-
parts.group_by(&:tracking_id).
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
134
|
+
bad = parts.group_by(&:tracking_id).select { |_, same| same.size > 1 }
|
135
|
+
return if bad.empty?
|
136
|
+
raise <<~ERROR
|
137
|
+
#{bad.map { |tracking_id, same| "#{tracking_id} is defined #{same.size} times" }.join("\n")}
|
138
|
+
|
139
|
+
use a different `kennel_id` when defining multiple projects/monitors/dashboards to avoid this conflict
|
140
|
+
ERROR
|
141
141
|
end
|
142
142
|
|
143
143
|
def definitions(**kwargs)
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: kennel
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.161.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Michael Grosser
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2025-04-
|
11
|
+
date: 2025-04-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: diff-lcs
|