kennel 1.122.0 → 1.123.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|