kennel 1.152.2 → 1.153.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 +1 -1
- data/lib/kennel/importer.rb +5 -5
- data/lib/kennel/models/dashboard.rb +6 -6
- data/lib/kennel/models/monitor.rb +6 -6
- data/lib/kennel/models/project.rb +5 -5
- data/lib/kennel/models/record.rb +3 -3
- data/lib/kennel/models/slo.rb +3 -3
- data/lib/kennel/projects_provider.rb +2 -2
- data/lib/kennel/settings_as_methods.rb +2 -2
- data/lib/kennel/string_utils.rb +2 -2
- data/lib/kennel/syncer/resolver.rb +1 -1
- data/lib/kennel/syncer.rb +6 -6
- data/lib/kennel/tasks.rb +3 -3
- data/lib/kennel/unmuted_alerts.rb +1 -1
- data/lib/kennel/version.rb +1 -1
- 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: 494943be7e89773e54b07cafc41725e946bbc2c4038315ce21b123515c4561de
|
4
|
+
data.tar.gz: f9ae76c8cc4a83d04f41c44abb4eb8fee2aefc85f60ee6376de1fcd8e639cdee
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 156d4655d75c82ddac1ac80dad4cd1d480c3a7c277c1bcc115a887c7c6d6b653daf7f73deaa7e42fc46a0a79e1bbc2102acb7e4ffa86c08ab7ce14cbdd9270e9
|
7
|
+
data.tar.gz: fde6bf6493035c908ada35545f4666cf7a7c81090dfef315384180d904f6c904d13dc4e5f47c84b33d21d21bfd851efd4e70542c22a19fdc96233898284552f3
|
data/lib/kennel/api.rb
CHANGED
@@ -146,7 +146,7 @@ module Kennel
|
|
146
146
|
end
|
147
147
|
|
148
148
|
if !response.success? && (response.status != 404 || !ignore_404)
|
149
|
-
message =
|
149
|
+
message = "Error #{response.status} during #{method.upcase} #{path}\n"
|
150
150
|
message << "request:\n#{JSON.pretty_generate(body)}\nresponse:\n" if body
|
151
151
|
message << response.body.encode(message.encoding, invalid: :replace, undef: :replace)
|
152
152
|
raise message
|
data/lib/kennel/importer.rb
CHANGED
@@ -37,7 +37,7 @@ module Kennel
|
|
37
37
|
|
38
38
|
# calculate or reuse kennel_id
|
39
39
|
data[:kennel_id] =
|
40
|
-
if tracking_id = model.parse_tracking_id(data)
|
40
|
+
if (tracking_id = model.parse_tracking_id(data))
|
41
41
|
model.remove_tracking_id(data)
|
42
42
|
tracking_id.split(":").last
|
43
43
|
else
|
@@ -88,7 +88,7 @@ module Kennel
|
|
88
88
|
data.delete(:tags) if data[:tags] == [] # do not create super + [] call
|
89
89
|
|
90
90
|
# simplify template_variables to array of string when possible
|
91
|
-
if vars = data[:template_variables]
|
91
|
+
if (vars = data[:template_variables])
|
92
92
|
vars.map! { |v| v[:default] == "*" && v[:prefix] == v[:name] ? v[:name] : v }
|
93
93
|
end
|
94
94
|
|
@@ -119,10 +119,10 @@ module Kennel
|
|
119
119
|
def dry_up_widget_metadata!(widget)
|
120
120
|
(widget.dig(:definition, :requests) || []).each do |request|
|
121
121
|
next unless request.is_a?(Hash)
|
122
|
-
next unless metadata = request[:metadata]
|
123
|
-
next unless query = request[:q]&.dup
|
122
|
+
next unless (metadata = request[:metadata])
|
123
|
+
next unless (query = request[:q]&.dup)
|
124
124
|
metadata.each do |m|
|
125
|
-
next unless exp = m[:expression]
|
125
|
+
next unless (exp = m[:expression])
|
126
126
|
query.sub!(exp, "")
|
127
127
|
end
|
128
128
|
request[:q] = :metadata if query.delete(", ") == ""
|
@@ -112,7 +112,7 @@ module Kennel
|
|
112
112
|
|
113
113
|
# conditional_formats ordering is randomly changed by datadog, compare a stable ordering
|
114
114
|
def sort_conditional_formats(widget)
|
115
|
-
if formats = widget&.dig(:definition, :conditional_formats)
|
115
|
+
if (formats = widget&.dig(:definition, :conditional_formats))
|
116
116
|
widget[:definition][:conditional_formats] = formats.sort_by(&:hash)
|
117
117
|
end
|
118
118
|
end
|
@@ -120,7 +120,7 @@ module Kennel
|
|
120
120
|
def ignore_widget_defaults(expected, actual)
|
121
121
|
types = [expected&.dig(:definition, :type), actual&.dig(:definition, :type)].uniq.compact
|
122
122
|
return unless types.size == 1
|
123
|
-
return unless defaults = WIDGET_DEFAULTS[types.first]
|
123
|
+
return unless (defaults = WIDGET_DEFAULTS[types.first])
|
124
124
|
ignore_default expected&.[](:definition) || {}, actual&.[](:definition) || {}, defaults
|
125
125
|
end
|
126
126
|
|
@@ -179,21 +179,21 @@ module Kennel
|
|
179
179
|
def resolve_linked_tracking_ids!(id_map, **args)
|
180
180
|
widgets = as_json[:widgets].flat_map { |w| [w, *w.dig(:definition, :widgets) || []] }
|
181
181
|
widgets.each do |widget|
|
182
|
-
next unless definition = widget[:definition]
|
182
|
+
next unless (definition = widget[:definition])
|
183
183
|
case definition[:type]
|
184
184
|
when "uptime"
|
185
|
-
if ids = definition[:monitor_ids]
|
185
|
+
if (ids = definition[:monitor_ids])
|
186
186
|
definition[:monitor_ids] = ids.map do |id|
|
187
187
|
resolve(id, :monitor, id_map, **args) || id
|
188
188
|
end
|
189
189
|
end
|
190
190
|
when "alert_graph"
|
191
|
-
if id = definition[:alert_id]
|
191
|
+
if (id = definition[:alert_id])
|
192
192
|
resolved = resolve(id, :monitor, id_map, **args) || id
|
193
193
|
definition[:alert_id] = resolved.to_s # even though it's a monitor id
|
194
194
|
end
|
195
195
|
when "slo"
|
196
|
-
if id = definition[:slo_id]
|
196
|
+
if (id = definition[:slo_id])
|
197
197
|
definition[:slo_id] = resolve(id, :slo, id_map, **args) || id
|
198
198
|
end
|
199
199
|
when "timeseries"
|
@@ -95,7 +95,7 @@ module Kennel
|
|
95
95
|
|
96
96
|
# warning, ok, critical_recovery, and warning_recovery are optional
|
97
97
|
[:warning, :ok, :critical_recovery, :warning_recovery].each do |key|
|
98
|
-
if value = send(key)
|
98
|
+
if (value = send(key))
|
99
99
|
thresholds[key] = value
|
100
100
|
end
|
101
101
|
end
|
@@ -112,7 +112,7 @@ module Kennel
|
|
112
112
|
end
|
113
113
|
|
114
114
|
# set without causing lots of nulls to be stored
|
115
|
-
if notify_by_value = notify_by
|
115
|
+
if (notify_by_value = notify_by)
|
116
116
|
options[:notify_by] = notify_by_value
|
117
117
|
end
|
118
118
|
|
@@ -122,11 +122,11 @@ module Kennel
|
|
122
122
|
options.delete :no_data_timeframe
|
123
123
|
end
|
124
124
|
|
125
|
-
if windows = threshold_windows
|
125
|
+
if (windows = threshold_windows)
|
126
126
|
options[:threshold_windows] = windows
|
127
127
|
end
|
128
128
|
|
129
|
-
if schedule = scheduling_options
|
129
|
+
if (schedule = scheduling_options)
|
130
130
|
options[:scheduling_options] = schedule
|
131
131
|
end
|
132
132
|
|
@@ -256,7 +256,7 @@ module Kennel
|
|
256
256
|
end
|
257
257
|
|
258
258
|
# verify query includes critical value
|
259
|
-
if query_value = data.fetch(:query)[/\s*[<>]=?\s*(\d+(\.\d+)?)\s*$/, 1]
|
259
|
+
if (query_value = data.fetch(:query)[/\s*[<>]=?\s*(\d+(\.\d+)?)\s*$/, 1])
|
260
260
|
if Float(query_value) != Float(data.dig(:options, :thresholds, :critical))
|
261
261
|
invalid! :critical_does_not_match_query, "critical and value used in query must match"
|
262
262
|
end
|
@@ -298,7 +298,7 @@ module Kennel
|
|
298
298
|
# - also match without by
|
299
299
|
# - separate parsers for query and service
|
300
300
|
# - service must always allow `host`, maybe others
|
301
|
-
return unless match = data.fetch(:query).match(/(?:{([^}]*)}\s*)?by\s*[({]([^})]+)[})]/)
|
301
|
+
return unless (match = data.fetch(:query).match(/(?:{([^}]*)}\s*)?by\s*[({]([^})]+)[})]/))
|
302
302
|
|
303
303
|
allowed =
|
304
304
|
match[1].to_s.split(/\s*,\s*/).map { |k| k.split(":", 2)[-2] } + # {a:b} -> a TODO: does not work for service check
|
@@ -9,11 +9,11 @@ module Kennel
|
|
9
9
|
)
|
10
10
|
|
11
11
|
def self.file_location
|
12
|
-
@file_location
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
12
|
+
return @file_location if defined?(@file_location)
|
13
|
+
if (location = instance_methods(false).first)
|
14
|
+
@file_location = instance_method(location).source_location.first.sub("#{Bundler.root}/", "")
|
15
|
+
else
|
16
|
+
@file_location = nil
|
17
17
|
end
|
18
18
|
end
|
19
19
|
|
data/lib/kennel/models/record.rb
CHANGED
@@ -38,7 +38,7 @@ module Kennel
|
|
38
38
|
class << self
|
39
39
|
def parse_any_url(url)
|
40
40
|
subclasses.detect do |s|
|
41
|
-
if id = s.parse_url(url)
|
41
|
+
if (id = s.parse_url(url))
|
42
42
|
break s.api_resource, id
|
43
43
|
end
|
44
44
|
end
|
@@ -188,7 +188,7 @@ module Kennel
|
|
188
188
|
else
|
189
189
|
nil # will be re-resolved after the linked object was created
|
190
190
|
end
|
191
|
-
elsif id = id_map.get(sought_type.to_s, sought_tracking_id)
|
191
|
+
elsif (id = id_map.get(sought_type.to_s, sought_tracking_id))
|
192
192
|
id
|
193
193
|
else
|
194
194
|
raise UnresolvableIdError, <<~MESSAGE
|
@@ -200,7 +200,7 @@ module Kennel
|
|
200
200
|
end
|
201
201
|
|
202
202
|
def raise_with_location(error, message)
|
203
|
-
super
|
203
|
+
super(error, "#{message} for project #{project.kennel_id}")
|
204
204
|
end
|
205
205
|
end
|
206
206
|
end
|
data/lib/kennel/models/slo.rb
CHANGED
@@ -40,11 +40,11 @@ module Kennel
|
|
40
40
|
|
41
41
|
if type == "time_slice"
|
42
42
|
data[:sli_specification] = sli_specification
|
43
|
-
elsif v = query
|
43
|
+
elsif (v = query)
|
44
44
|
data[:query] = v
|
45
45
|
end
|
46
46
|
|
47
|
-
if v = groups
|
47
|
+
if (v = groups)
|
48
48
|
data[:groups] = v
|
49
49
|
end
|
50
50
|
|
@@ -64,7 +64,7 @@ module Kennel
|
|
64
64
|
end
|
65
65
|
|
66
66
|
def resolve_linked_tracking_ids!(id_map, **args)
|
67
|
-
return unless ids = as_json[:monitor_ids] # ignore_default can remove it
|
67
|
+
return unless (ids = as_json[:monitor_ids]) # ignore_default can remove it
|
68
68
|
as_json[:monitor_ids] = ids.map do |id|
|
69
69
|
resolve(id, :monitor, id_map, **args) || id
|
70
70
|
end
|
@@ -25,11 +25,11 @@ module Kennel
|
|
25
25
|
|
26
26
|
# TODO: also auto-load projects and update expected path too
|
27
27
|
["projects"].each do |folder|
|
28
|
-
Dir["#{folder}/**/*.rb"].
|
28
|
+
Dir["#{folder}/**/*.rb"].each { |f| require "./#{f}" }
|
29
29
|
end
|
30
30
|
rescue NameError => e
|
31
31
|
message = e.message
|
32
|
-
raise unless klass = message[/uninitialized constant (.*)/, 1]
|
32
|
+
raise unless (klass = message[/uninitialized constant (.*)/, 1])
|
33
33
|
|
34
34
|
# inverse of zeitwerk lib/zeitwerk/inflector.rb
|
35
35
|
path = klass.gsub("::", "/").gsub(/([a-z])([A-Z])/, "\\1_\\2").downcase + ".rb"
|
@@ -9,7 +9,7 @@ module Kennel
|
|
9
9
|
file, line, = caller(2..2).first.split(":", 3)
|
10
10
|
|
11
11
|
options.transform_values do |v|
|
12
|
-
if v.
|
12
|
+
if v.instance_of?(Proc)
|
13
13
|
v
|
14
14
|
else
|
15
15
|
eval "-> { v }", nil, file, line.to_i
|
@@ -80,7 +80,7 @@ module Kennel
|
|
80
80
|
# need expand_path so it works wih rake and when run individually
|
81
81
|
pwd = /^#{Regexp.escape(Dir.pwd)}\//
|
82
82
|
@invocation_location = caller.detect do |l|
|
83
|
-
if found = File.expand_path(l).sub!(pwd, "")
|
83
|
+
if (found = File.expand_path(l).sub!(pwd, ""))
|
84
84
|
break found
|
85
85
|
end
|
86
86
|
end
|
data/lib/kennel/string_utils.rb
CHANGED
@@ -4,7 +4,7 @@ module Kennel
|
|
4
4
|
class << self
|
5
5
|
def snake_case(string)
|
6
6
|
string
|
7
|
-
.gsub(
|
7
|
+
.gsub("::", "_") # Foo::Bar -> foo_bar
|
8
8
|
.gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2') # FOOBar -> foo_bar
|
9
9
|
.gsub(/([a-z\d])([A-Z])/, '\1_\2') # fooBar -> foo_bar
|
10
10
|
.tr("-", "_") # foo-bar -> foo_bar
|
@@ -26,7 +26,7 @@ module Kennel
|
|
26
26
|
end
|
27
27
|
|
28
28
|
def truncate_lines(text, to:, warning:)
|
29
|
-
lines = text.split(
|
29
|
+
lines = text.split("\n", to + 1)
|
30
30
|
lines[-1] = warning if lines.size > to
|
31
31
|
lines.join("\n")
|
32
32
|
end
|
@@ -22,7 +22,7 @@ module Kennel
|
|
22
22
|
# override resources that exist with their id
|
23
23
|
actual.each do |a|
|
24
24
|
# ignore when not managed by kennel
|
25
|
-
next unless tracking_id = a.fetch(:tracking_id)
|
25
|
+
next unless (tracking_id = a.fetch(:tracking_id))
|
26
26
|
|
27
27
|
# ignore when deleted from the codebase
|
28
28
|
# (when running with filters we cannot see the other resources in the codebase)
|
data/lib/kennel/syncer.rb
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative "
|
4
|
-
require_relative "
|
5
|
-
require_relative "
|
6
|
-
require_relative "
|
7
|
-
require_relative "
|
3
|
+
require_relative "syncer/matched_expected"
|
4
|
+
require_relative "syncer/plan"
|
5
|
+
require_relative "syncer/plan_printer"
|
6
|
+
require_relative "syncer/resolver"
|
7
|
+
require_relative "syncer/types"
|
8
8
|
|
9
9
|
module Kennel
|
10
10
|
class Syncer
|
@@ -122,7 +122,7 @@ module Kennel
|
|
122
122
|
|
123
123
|
def validate_expected_id_not_missing(expected)
|
124
124
|
expected.each do |e|
|
125
|
-
next unless id = e.id
|
125
|
+
next unless (id = e.id)
|
126
126
|
resource = e.class.api_resource
|
127
127
|
if @strict_imports
|
128
128
|
raise "Unable to find existing #{resource} with id #{id}\nIf the #{resource} was deleted, remove the `id: -> { #{id} }` line."
|
data/lib/kennel/tasks.rb
CHANGED
@@ -81,7 +81,7 @@ namespace :kennel do
|
|
81
81
|
|
82
82
|
bad = []
|
83
83
|
Dir["generated/**/*.json"].each do |f|
|
84
|
-
next unless message = JSON.parse(File.read(f))["message"]
|
84
|
+
next unless (message = JSON.parse(File.read(f))["message"])
|
85
85
|
used = message
|
86
86
|
.scan(/(?:^|\s)(@[^\s{,'"]+)/)
|
87
87
|
.flatten(1)
|
@@ -153,7 +153,7 @@ namespace :kennel do
|
|
153
153
|
end
|
154
154
|
end
|
155
155
|
|
156
|
-
if threshold = ENV["THRESHOLD_DAYS"]
|
156
|
+
if (threshold = ENV["THRESHOLD_DAYS"])
|
157
157
|
monitors.select! { |m| m[:days_in_no_data] > Integer(threshold) }
|
158
158
|
end
|
159
159
|
|
@@ -196,7 +196,7 @@ namespace :kennel do
|
|
196
196
|
desc "Dump ALL of datadog config as raw json ... useful for grep/search [TYPE=slo|monitor|dashboard]"
|
197
197
|
task dump: :environment do
|
198
198
|
resources =
|
199
|
-
if type = ENV["TYPE"]
|
199
|
+
if (type = ENV["TYPE"])
|
200
200
|
[type]
|
201
201
|
else
|
202
202
|
Kennel::Models::Record.api_resource_map.keys
|
@@ -58,7 +58,7 @@ module Kennel
|
|
58
58
|
monitors.reject! { |m| m[:options][:silenced].key?(:*) }
|
59
59
|
|
60
60
|
# only keep groups that are alerting
|
61
|
-
monitors.each { |m| m[:state][:groups].reject! { |_, g|
|
61
|
+
monitors.each { |m| m[:state][:groups].reject! { |_, g| ["OK", "Ignored"].include?(g[:status]) } }
|
62
62
|
|
63
63
|
# only keep alerting groups that are not silenced
|
64
64
|
monitors.each do |m|
|
data/lib/kennel/version.rb
CHANGED
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.153.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-
|
11
|
+
date: 2025-03-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: diff-lcs
|