kennel 1.122.0 → 1.123.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/file_cache.rb +11 -11
- data/lib/kennel/importer.rb +2 -0
- data/lib/kennel/models/dashboard.rb +8 -16
- data/lib/kennel/models/monitor.rb +5 -13
- data/lib/kennel/models/project.rb +1 -6
- data/lib/kennel/models/record.rb +38 -10
- data/lib/kennel/models/slo.rb +15 -16
- data/lib/kennel/models/synthetic_test.rb +4 -11
- data/lib/kennel/syncer.rb +2 -2
- data/lib/kennel/version.rb +1 -1
- data/lib/kennel.rb +3 -2
- 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: f09678f23d63da04d4b5db81eaef471bc0aa437b62ac75082f7bd161f8cd38e4
|
|
4
|
+
data.tar.gz: a570cc2617295581459a5977727049c243d492312554496f0b1beb432ad8efe8
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 560a1daae6cb797b0e53e06a694e5624667b5597d3d6fb5c783e0166154a8f594064d7bfc1f64fb541723e2b633130d4e8039a8caa3434145552a63114a88678
|
|
7
|
+
data.tar.gz: '091c93ee61b87146c69e6f8782aab7a3cf2c349a03936f686a099eaca1a96d762193ee8385220fcc9d8c694edacf89aa57c6751e6e8a17bcffb37b1f913f9591'
|
data/lib/kennel/file_cache.rb
CHANGED
|
@@ -15,11 +15,13 @@ module Kennel
|
|
|
15
15
|
end
|
|
16
16
|
|
|
17
17
|
def open
|
|
18
|
-
load_data
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
18
|
+
@data = load_data || {}
|
|
19
|
+
begin
|
|
20
|
+
expire_old_data
|
|
21
|
+
yield self
|
|
22
|
+
ensure
|
|
23
|
+
persist
|
|
24
|
+
end
|
|
23
25
|
end
|
|
24
26
|
|
|
25
27
|
def fetch(key, key_version)
|
|
@@ -35,12 +37,9 @@ module Kennel
|
|
|
35
37
|
private
|
|
36
38
|
|
|
37
39
|
def load_data
|
|
38
|
-
@
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
rescue StandardError
|
|
42
|
-
{}
|
|
43
|
-
end
|
|
40
|
+
Marshal.load(File.read(@file)) # rubocop:disable Security/MarshalLoad
|
|
41
|
+
rescue Errno::ENOENT, TypeError, ArgumentError
|
|
42
|
+
nil
|
|
44
43
|
end
|
|
45
44
|
|
|
46
45
|
def persist
|
|
@@ -49,6 +48,7 @@ module Kennel
|
|
|
49
48
|
|
|
50
49
|
Tempfile.create "kennel-file-cache", dir do |tmp|
|
|
51
50
|
Marshal.dump @data, tmp
|
|
51
|
+
tmp.flush
|
|
52
52
|
File.rename tmp.path, @file
|
|
53
53
|
end
|
|
54
54
|
end
|
data/lib/kennel/importer.rb
CHANGED
|
@@ -38,6 +38,8 @@ module Kennel
|
|
|
38
38
|
|
|
39
39
|
case resource
|
|
40
40
|
when "monitor"
|
|
41
|
+
raise "Import the synthetic test page and not the monitor" if data[:type] == "synthetics alert"
|
|
42
|
+
|
|
41
43
|
# flatten monitor options so they are all on the base which is how Monitor builds them
|
|
42
44
|
data.merge!(data.delete(:options))
|
|
43
45
|
data.merge!(data.delete(:thresholds) || {})
|
|
@@ -3,7 +3,6 @@ module Kennel
|
|
|
3
3
|
module Models
|
|
4
4
|
class Dashboard < Record
|
|
5
5
|
include TemplateVariables
|
|
6
|
-
include OptionalValidations
|
|
7
6
|
|
|
8
7
|
READONLY_ATTRIBUTES = superclass::READONLY_ATTRIBUTES + [
|
|
9
8
|
:author_handle, :author_name, :modified_at, :deleted_at, :url, :is_read_only, :notify_list, :restricted_roles
|
|
@@ -87,8 +86,7 @@ module Kennel
|
|
|
87
86
|
tags: -> do # not inherited by default to make onboarding to using dashboard tags simple
|
|
88
87
|
team = project.team
|
|
89
88
|
team.tag_dashboards ? team.tags : []
|
|
90
|
-
end
|
|
91
|
-
id: -> { nil }
|
|
89
|
+
end
|
|
92
90
|
)
|
|
93
91
|
|
|
94
92
|
class << self
|
|
@@ -152,29 +150,24 @@ module Kennel
|
|
|
152
150
|
end
|
|
153
151
|
end
|
|
154
152
|
|
|
155
|
-
def
|
|
156
|
-
return @json if @json
|
|
153
|
+
def build_json
|
|
157
154
|
all_widgets = render_definitions(definitions) + widgets
|
|
158
155
|
expand_q all_widgets
|
|
159
156
|
tags = tags()
|
|
160
157
|
tags_as_string = (tags.empty? ? "" : " (#{tags.join(" ")})")
|
|
161
158
|
|
|
162
|
-
|
|
159
|
+
json = super.merge(
|
|
163
160
|
layout_type: layout_type,
|
|
164
161
|
title: "#{title}#{tags_as_string}#{LOCK}",
|
|
165
162
|
description: description,
|
|
166
163
|
template_variables: render_template_variables,
|
|
167
164
|
template_variable_presets: template_variable_presets,
|
|
168
165
|
widgets: all_widgets
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
@json[:reflow_type] = reflow_type if reflow_type # setting nil breaks create with "ordered"
|
|
166
|
+
)
|
|
172
167
|
|
|
173
|
-
|
|
168
|
+
json[:reflow_type] = reflow_type if reflow_type # setting nil breaks create with "ordered"
|
|
174
169
|
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
@json
|
|
170
|
+
json
|
|
178
171
|
end
|
|
179
172
|
|
|
180
173
|
def self.url(id)
|
|
@@ -210,9 +203,8 @@ module Kennel
|
|
|
210
203
|
end
|
|
211
204
|
|
|
212
205
|
def validate_update!(_actuals, diffs)
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
end
|
|
206
|
+
_, path, from, to = diffs.find { |diff| diff[1] == "layout_type" }
|
|
207
|
+
invalid_update!(path, from, to) if path
|
|
216
208
|
end
|
|
217
209
|
|
|
218
210
|
private
|
|
@@ -2,8 +2,6 @@
|
|
|
2
2
|
module Kennel
|
|
3
3
|
module Models
|
|
4
4
|
class Monitor < Record
|
|
5
|
-
include OptionalValidations
|
|
6
|
-
|
|
7
5
|
RENOTIFY_INTERVALS = [0, 10, 20, 30, 40, 50, 60, 90, 120, 180, 240, 300, 360, 720, 1440].freeze # minutes
|
|
8
6
|
OPTIONAL_SERVICE_CHECK_THRESHOLDS = [:ok, :warning].freeze
|
|
9
7
|
READONLY_ATTRIBUTES = superclass::READONLY_ATTRIBUTES + [
|
|
@@ -41,7 +39,6 @@ module Kennel
|
|
|
41
39
|
renotify_interval: -> { project.team.renotify_interval },
|
|
42
40
|
warning: -> { nil },
|
|
43
41
|
ok: -> { nil },
|
|
44
|
-
id: -> { nil },
|
|
45
42
|
notify_no_data: -> { true }, # datadog sets this to false by default, but true is the safer
|
|
46
43
|
no_data_timeframe: -> { 60 },
|
|
47
44
|
notify_audit: -> { MONITOR_OPTION_DEFAULTS.fetch(:notify_audit) },
|
|
@@ -56,9 +53,8 @@ module Kennel
|
|
|
56
53
|
priority: -> { MONITOR_DEFAULTS.fetch(:priority) }
|
|
57
54
|
)
|
|
58
55
|
|
|
59
|
-
def
|
|
60
|
-
|
|
61
|
-
data = {
|
|
56
|
+
def build_json
|
|
57
|
+
data = super.merge(
|
|
62
58
|
name: "#{name}#{LOCK}",
|
|
63
59
|
type: type,
|
|
64
60
|
query: query.strip,
|
|
@@ -79,9 +75,7 @@ module Kennel
|
|
|
79
75
|
locked: false, # setting this to true prevents any edit and breaks updates when using replace workflow
|
|
80
76
|
renotify_interval: renotify_interval || 0
|
|
81
77
|
}
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
data[:id] = id if id
|
|
78
|
+
)
|
|
85
79
|
|
|
86
80
|
options = data[:options]
|
|
87
81
|
if data.fetch(:type) != "composite"
|
|
@@ -120,9 +114,7 @@ module Kennel
|
|
|
120
114
|
options[:renotify_statuses] = statuses
|
|
121
115
|
end
|
|
122
116
|
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
@as_json = data
|
|
117
|
+
data
|
|
126
118
|
end
|
|
127
119
|
|
|
128
120
|
def resolve_linked_tracking_ids!(id_map, **args)
|
|
@@ -140,7 +132,7 @@ module Kennel
|
|
|
140
132
|
# ensure type does not change, but not if it's metric->query which is supported and used by importer.rb
|
|
141
133
|
_, path, from, to = diffs.detect { |_, path, _, _| path == "type" }
|
|
142
134
|
if path && !(from == "metric alert" && to == "query alert")
|
|
143
|
-
|
|
135
|
+
invalid_update!(path, from, to)
|
|
144
136
|
end
|
|
145
137
|
end
|
|
146
138
|
|
|
@@ -20,7 +20,7 @@ module Kennel
|
|
|
20
20
|
def validated_parts
|
|
21
21
|
all = parts
|
|
22
22
|
unless all.is_a?(Array) && all.all? { |part| part.is_a?(Record) }
|
|
23
|
-
|
|
23
|
+
raise "Project #{kennel_id} #parts must return an array of Records"
|
|
24
24
|
end
|
|
25
25
|
|
|
26
26
|
validate_parts(all)
|
|
@@ -29,11 +29,6 @@ module Kennel
|
|
|
29
29
|
|
|
30
30
|
private
|
|
31
31
|
|
|
32
|
-
# let users know which project/resource failed when something happens during diffing where the backtrace is hidden
|
|
33
|
-
def invalid!(message)
|
|
34
|
-
raise ValidationError, "#{kennel_id} #{message}"
|
|
35
|
-
end
|
|
36
|
-
|
|
37
32
|
# hook for users to add custom validations via `prepend`
|
|
38
33
|
def validate_parts(parts)
|
|
39
34
|
end
|
data/lib/kennel/models/record.rb
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
module Kennel
|
|
3
3
|
module Models
|
|
4
4
|
class Record < Base
|
|
5
|
+
include OptionalValidations
|
|
6
|
+
|
|
5
7
|
# Apart from if you just don't like the default for some reason,
|
|
6
8
|
# overriding MARKER_TEXT allows for namespacing within the same
|
|
7
9
|
# Datadog account. If you run one Kennel setup with marker text
|
|
@@ -30,6 +32,8 @@ module Kennel
|
|
|
30
32
|
|
|
31
33
|
settings :id, :kennel_id
|
|
32
34
|
|
|
35
|
+
defaults(id: nil)
|
|
36
|
+
|
|
33
37
|
class << self
|
|
34
38
|
def parse_any_url(url)
|
|
35
39
|
subclasses.detect do |s|
|
|
@@ -96,7 +100,7 @@ module Kennel
|
|
|
96
100
|
@tracking_id ||= begin
|
|
97
101
|
id = "#{project.kennel_id}:#{kennel_id}"
|
|
98
102
|
unless id.match?(ALLOWED_KENNEL_ID_REGEX) # <-> parse_tracking_id
|
|
99
|
-
raise
|
|
103
|
+
raise "#{id} must match #{ALLOWED_KENNEL_ID_REGEX}"
|
|
100
104
|
end
|
|
101
105
|
id
|
|
102
106
|
end
|
|
@@ -108,7 +112,7 @@ module Kennel
|
|
|
108
112
|
def add_tracking_id
|
|
109
113
|
json = as_json
|
|
110
114
|
if self.class.parse_tracking_id(json)
|
|
111
|
-
|
|
115
|
+
raise "#{tracking_id} Remove \"-- #{MARKER_TEXT}\" line from #{self.class::TRACKING_FIELD} to copy a resource"
|
|
112
116
|
end
|
|
113
117
|
json[self.class::TRACKING_FIELD] =
|
|
114
118
|
"#{json[self.class::TRACKING_FIELD]}\n" \
|
|
@@ -119,9 +123,29 @@ module Kennel
|
|
|
119
123
|
self.class.remove_tracking_id(as_json)
|
|
120
124
|
end
|
|
121
125
|
|
|
126
|
+
def build_json
|
|
127
|
+
{
|
|
128
|
+
id: id
|
|
129
|
+
}.compact
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
def as_json
|
|
133
|
+
@as_json ||= begin
|
|
134
|
+
json = build_json
|
|
135
|
+
(id = json.delete(:id)) && json[:id] = id
|
|
136
|
+
validate_json(json) if validate
|
|
137
|
+
json
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
# Can raise DisallowedUpdateError
|
|
122
142
|
def validate_update!(*)
|
|
123
143
|
end
|
|
124
144
|
|
|
145
|
+
def invalid_update!(field, old_value, new_value)
|
|
146
|
+
raise DisallowedUpdateError, "#{tracking_id} Datadog does not allow update of #{field} (#{old_value.inspect} -> #{new_value.inspect})"
|
|
147
|
+
end
|
|
148
|
+
|
|
125
149
|
private
|
|
126
150
|
|
|
127
151
|
def resolve(value, type, id_map, force:)
|
|
@@ -133,20 +157,24 @@ module Kennel
|
|
|
133
157
|
id.is_a?(String) && id.include?(":")
|
|
134
158
|
end
|
|
135
159
|
|
|
136
|
-
def resolve_link(
|
|
137
|
-
if id_map.new?(
|
|
160
|
+
def resolve_link(sought_tracking_id, sought_type, id_map, force:)
|
|
161
|
+
if id_map.new?(sought_type.to_s, sought_tracking_id)
|
|
138
162
|
if force
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
163
|
+
raise UnresolvableIdError, <<~MESSAGE
|
|
164
|
+
#{tracking_id} #{sought_type} #{sought_tracking_id} was referenced but is also created by the current run.
|
|
165
|
+
It could not be created because of a circular dependency. Try creating only some of the resources.
|
|
166
|
+
MESSAGE
|
|
143
167
|
else
|
|
144
168
|
nil # will be re-resolved after the linked object was created
|
|
145
169
|
end
|
|
146
|
-
elsif id = id_map.get(
|
|
170
|
+
elsif id = id_map.get(sought_type.to_s, sought_tracking_id)
|
|
147
171
|
id
|
|
148
172
|
else
|
|
149
|
-
|
|
173
|
+
raise UnresolvableIdError, <<~MESSAGE
|
|
174
|
+
#{tracking_id} Unable to find #{sought_type} #{sought_tracking_id}
|
|
175
|
+
This is either because it doesn't exist, and isn't being created by the current run;
|
|
176
|
+
or it does exist, but is being deleted.
|
|
177
|
+
MESSAGE
|
|
150
178
|
end
|
|
151
179
|
end
|
|
152
180
|
|
data/lib/kennel/models/slo.rb
CHANGED
|
@@ -15,7 +15,6 @@ module Kennel
|
|
|
15
15
|
settings :type, :description, :thresholds, :query, :tags, :monitor_ids, :monitor_tags, :name, :groups
|
|
16
16
|
|
|
17
17
|
defaults(
|
|
18
|
-
id: -> { nil },
|
|
19
18
|
tags: -> { @project.tags },
|
|
20
19
|
query: -> { DEFAULTS.fetch(:query) },
|
|
21
20
|
description: -> { DEFAULTS.fetch(:description) },
|
|
@@ -24,35 +23,25 @@ module Kennel
|
|
|
24
23
|
groups: -> { DEFAULTS.fetch(:groups) }
|
|
25
24
|
)
|
|
26
25
|
|
|
27
|
-
def
|
|
28
|
-
super
|
|
29
|
-
if thresholds.any? { |t| t[:warning] && t[:warning].to_f <= t[:critical].to_f }
|
|
30
|
-
raise ValidationError, "Threshold warning must be greater-than critical value"
|
|
31
|
-
end
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
def as_json
|
|
35
|
-
return @as_json if @as_json
|
|
36
|
-
data = {
|
|
26
|
+
def build_json
|
|
27
|
+
data = super.merge(
|
|
37
28
|
name: "#{name}#{LOCK}",
|
|
38
29
|
description: description,
|
|
39
30
|
thresholds: thresholds,
|
|
40
31
|
monitor_ids: monitor_ids,
|
|
41
32
|
tags: tags.uniq,
|
|
42
33
|
type: type
|
|
43
|
-
|
|
34
|
+
)
|
|
44
35
|
|
|
45
36
|
if v = query
|
|
46
37
|
data[:query] = v
|
|
47
38
|
end
|
|
48
|
-
|
|
49
|
-
data[:id] = v
|
|
50
|
-
end
|
|
39
|
+
|
|
51
40
|
if v = groups
|
|
52
41
|
data[:groups] = v
|
|
53
42
|
end
|
|
54
43
|
|
|
55
|
-
|
|
44
|
+
data
|
|
56
45
|
end
|
|
57
46
|
|
|
58
47
|
def self.api_resource
|
|
@@ -89,6 +78,16 @@ module Kennel
|
|
|
89
78
|
|
|
90
79
|
ignore_default(expected, actual, DEFAULTS)
|
|
91
80
|
end
|
|
81
|
+
|
|
82
|
+
private
|
|
83
|
+
|
|
84
|
+
def validate_json(data)
|
|
85
|
+
super
|
|
86
|
+
|
|
87
|
+
if data[:thresholds].any? { |t| t[:warning] && t[:warning].to_f <= t[:critical].to_f }
|
|
88
|
+
invalid! "Threshold warning must be greater-than critical value"
|
|
89
|
+
end
|
|
90
|
+
end
|
|
92
91
|
end
|
|
93
92
|
end
|
|
94
93
|
end
|
|
@@ -11,15 +11,14 @@ module Kennel
|
|
|
11
11
|
settings :tags, :config, :message, :subtype, :type, :name, :locations, :options
|
|
12
12
|
|
|
13
13
|
defaults(
|
|
14
|
-
id: -> { nil },
|
|
15
14
|
tags: -> { @project.tags },
|
|
16
15
|
message: -> { "\n\n#{project.mention}" }
|
|
17
16
|
)
|
|
18
17
|
|
|
19
|
-
def
|
|
20
|
-
return @as_json if @as_json
|
|
18
|
+
def build_json
|
|
21
19
|
locations = locations()
|
|
22
|
-
|
|
20
|
+
|
|
21
|
+
super.merge(
|
|
23
22
|
message: message,
|
|
24
23
|
tags: tags,
|
|
25
24
|
config: config,
|
|
@@ -28,13 +27,7 @@ module Kennel
|
|
|
28
27
|
options: options,
|
|
29
28
|
name: "#{name}#{LOCK}",
|
|
30
29
|
locations: locations == :all ? LOCATIONS : locations
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
if v = id
|
|
34
|
-
data[:id] = v
|
|
35
|
-
end
|
|
36
|
-
|
|
37
|
-
@as_json = data
|
|
30
|
+
)
|
|
38
31
|
end
|
|
39
32
|
|
|
40
33
|
def self.api_resource
|
data/lib/kennel/syncer.rb
CHANGED
|
@@ -104,11 +104,11 @@ module Kennel
|
|
|
104
104
|
def resolved?(e)
|
|
105
105
|
assert_resolved e
|
|
106
106
|
true
|
|
107
|
-
rescue
|
|
107
|
+
rescue UnresolvableIdError
|
|
108
108
|
false
|
|
109
109
|
end
|
|
110
110
|
|
|
111
|
-
# raises
|
|
111
|
+
# raises UnresolvableIdError when not resolved
|
|
112
112
|
def assert_resolved(e)
|
|
113
113
|
resolve_linked_tracking_ids! [e], force: true
|
|
114
114
|
end
|
data/lib/kennel/version.rb
CHANGED
data/lib/kennel.rb
CHANGED
|
@@ -40,8 +40,9 @@ module Teams
|
|
|
40
40
|
end
|
|
41
41
|
|
|
42
42
|
module Kennel
|
|
43
|
-
|
|
44
|
-
|
|
43
|
+
ValidationError = Class.new(RuntimeError)
|
|
44
|
+
UnresolvableIdError = Class.new(RuntimeError)
|
|
45
|
+
DisallowedUpdateError = Class.new(RuntimeError)
|
|
45
46
|
|
|
46
47
|
include Kennel::Compatibility
|
|
47
48
|
|
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.123.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: 2022-10-
|
|
11
|
+
date: 2022-10-21 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: diff-lcs
|