kennel 2.6.0 → 2.7.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/models/dashboard.rb +4 -3
- data/lib/kennel/models/monitor.rb +5 -6
- data/lib/kennel/models/record.rb +2 -6
- data/lib/kennel/syncer/matched_expected.rb +7 -1
- data/lib/kennel/syncer/plan_printer.rb +1 -1
- data/lib/kennel/syncer.rb +17 -20
- data/lib/kennel/version.rb +1 -1
- data/lib/kennel.rb +4 -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: fb759ae2d81d962a137b9ff0485135f0995cf4e31542f0ab4f284eef9ea1c109
|
|
4
|
+
data.tar.gz: d1fafb3a5d44c746280967f752e4eb124510a823c7ac2bd51ca2e935517afbb6
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: bf576a0739a2cb98e7098c71bbf222d202766dbb479f9fd3c7b13bc0561b3f699cd1396faf4ef070c34be3bbed102aa8f8ca153d6c8c2c43e4767d945fe8df13
|
|
7
|
+
data.tar.gz: 2f2de90e0ad97900b86d92b168c1065f0128c15a0039eec3f4e611364e650a9faff20c4f6890b375fa15b3321c3e399d4a7a76fd648bcf56083675599ecb9c14
|
|
@@ -208,9 +208,10 @@ module Kennel
|
|
|
208
208
|
end
|
|
209
209
|
end
|
|
210
210
|
|
|
211
|
-
def
|
|
212
|
-
|
|
213
|
-
|
|
211
|
+
def allowed_update_error(actual)
|
|
212
|
+
actual_type = actual[:layout_type]
|
|
213
|
+
return if actual_type == layout_type
|
|
214
|
+
"cannot update layout_type from #{actual_type} to #{layout_type}"
|
|
214
215
|
end
|
|
215
216
|
|
|
216
217
|
private
|
|
@@ -180,12 +180,11 @@ module Kennel
|
|
|
180
180
|
end
|
|
181
181
|
end
|
|
182
182
|
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
if
|
|
187
|
-
|
|
188
|
-
end
|
|
183
|
+
# ensure type does not change, but not if it's metric->query which is supported and used by importer.rb
|
|
184
|
+
def allowed_update_error(actual)
|
|
185
|
+
actual_type = actual[:type]
|
|
186
|
+
return if actual_type == type || (actual_type == "metric alert" && type == "query alert")
|
|
187
|
+
"cannot update type from #{actual_type} to #{type}"
|
|
189
188
|
end
|
|
190
189
|
|
|
191
190
|
def self.api_resource
|
data/lib/kennel/models/record.rb
CHANGED
|
@@ -142,12 +142,8 @@ module Kennel
|
|
|
142
142
|
@as_json
|
|
143
143
|
end
|
|
144
144
|
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
end
|
|
148
|
-
|
|
149
|
-
def invalid_update!(field, old_value, new_value)
|
|
150
|
-
raise DisallowedUpdateError, "#{safe_tracking_id} Datadog does not allow update of #{field} (#{old_value.inspect} -> #{new_value.inspect})"
|
|
145
|
+
def allowed_update_error(_a)
|
|
146
|
+
nil
|
|
151
147
|
end
|
|
152
148
|
|
|
153
149
|
# For use during error handling
|
|
@@ -36,7 +36,13 @@ module Kennel
|
|
|
36
36
|
|
|
37
37
|
def matching_expected(a, map)
|
|
38
38
|
klass = a.fetch(:klass)
|
|
39
|
-
|
|
39
|
+
full_id = "#{klass.api_resource}:#{a.fetch(:id)}"
|
|
40
|
+
if (e = map[full_id]) # we try to update and the user has set the id
|
|
41
|
+
return e unless (error = e.allowed_update_error(a))
|
|
42
|
+
raise DisallowedUpdateError, "#{full_id} Datadog does not allow update: #{error}"
|
|
43
|
+
elsif (e = map[a.fetch(:tracking_id)])
|
|
44
|
+
e.allowed_update_error(a) ? nil : e # force a re-create if we can't update
|
|
45
|
+
end
|
|
40
46
|
end
|
|
41
47
|
end
|
|
42
48
|
end
|
|
@@ -12,9 +12,9 @@ module Kennel
|
|
|
12
12
|
if plan.empty?
|
|
13
13
|
Kennel.out.puts Console.color(:green, "Nothing to do")
|
|
14
14
|
else
|
|
15
|
+
print_changes "Delete", plan.deletes, :red
|
|
15
16
|
print_changes "Create", plan.creates, :green
|
|
16
17
|
print_changes "Update", plan.updates, :yellow
|
|
17
|
-
print_changes "Delete", plan.deletes, :red
|
|
18
18
|
end
|
|
19
19
|
end
|
|
20
20
|
|
data/lib/kennel/syncer.rb
CHANGED
|
@@ -20,7 +20,6 @@ module Kennel
|
|
|
20
20
|
|
|
21
21
|
@resolver = Resolver.new(expected: expected, filter: filter)
|
|
22
22
|
@plan = Plan.new(*calculate_changes(expected: expected, actual: actual))
|
|
23
|
-
validate_changes
|
|
24
23
|
end
|
|
25
24
|
|
|
26
25
|
def print_plan
|
|
@@ -126,21 +125,19 @@ module Kennel
|
|
|
126
125
|
# if there is a new item that has the same name or title as an "to be deleted" item,
|
|
127
126
|
# update it instead to avoid old urls from becoming invalid
|
|
128
127
|
# - careful with unmatched_actual being huge since it has all api resources
|
|
129
|
-
# - don't do it when
|
|
130
|
-
# - when using a filter and updating the kennel_id of an existing item, old and new must be in the filter
|
|
128
|
+
# - don't do it when update is not allowed
|
|
129
|
+
# - when using a filter and updating the kennel_id of an existing item, old and new must be in the filter (PROJECT= works, but not TRACKING_ID)
|
|
131
130
|
def convert_replace_into_update!(matching, unmatched_actual, unmatched_expected)
|
|
132
131
|
unmatched_expected.reject! do |e|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
break [field, value]
|
|
136
|
-
end
|
|
137
|
-
raise unless e_field # uncovered: should never happen ...
|
|
138
|
-
e_monitor_type = e.as_json[:type]
|
|
139
|
-
|
|
132
|
+
# find actual by title
|
|
133
|
+
e_field, e_value = title_field_and_value(e)
|
|
140
134
|
actual = unmatched_actual.detect do |a|
|
|
141
|
-
a[:klass].api_resource == e.class.api_resource &&
|
|
135
|
+
a[:klass].api_resource == e.class.api_resource &&
|
|
136
|
+
a[e_field] == e_value
|
|
142
137
|
end
|
|
143
|
-
|
|
138
|
+
|
|
139
|
+
# keep unmatched if we could not find or can't update
|
|
140
|
+
next false if !actual || e.allowed_update_error(actual)
|
|
144
141
|
|
|
145
142
|
# add as update and remove from unmatched
|
|
146
143
|
unmatched_actual.delete(actual)
|
|
@@ -150,6 +147,14 @@ module Kennel
|
|
|
150
147
|
end
|
|
151
148
|
end
|
|
152
149
|
|
|
150
|
+
def title_field_and_value(e)
|
|
151
|
+
Kennel::Models::Record::TITLE_FIELDS.detect do |field|
|
|
152
|
+
next unless (value = e.as_json[field])
|
|
153
|
+
return [field, value]
|
|
154
|
+
end
|
|
155
|
+
raise # uncovered: should never happen ...
|
|
156
|
+
end
|
|
157
|
+
|
|
153
158
|
# fill details of things we need to compare
|
|
154
159
|
def fill_details!(details_needed)
|
|
155
160
|
details_needed = details_needed.map { |e, a| a if e && e.class.api_resource == "dashboard" }.compact
|
|
@@ -169,14 +174,6 @@ module Kennel
|
|
|
169
174
|
end
|
|
170
175
|
end
|
|
171
176
|
|
|
172
|
-
# We've already validated the desired objects ('generated') in isolation.
|
|
173
|
-
# Now that we have made the plan, we can perform some more validation.
|
|
174
|
-
def validate_changes
|
|
175
|
-
@plan.updates.each do |item|
|
|
176
|
-
item.expected.validate_update!(item.diff)
|
|
177
|
-
end
|
|
178
|
-
end
|
|
179
|
-
|
|
180
177
|
def filter_actual!(actual)
|
|
181
178
|
return unless filter.filtering? # minor optimization
|
|
182
179
|
|
data/lib/kennel/version.rb
CHANGED
data/lib/kennel.rb
CHANGED
|
@@ -143,7 +143,10 @@ module Kennel
|
|
|
143
143
|
def definitions(**kwargs)
|
|
144
144
|
@definitions ||= Progress.progress("Downloading definitions", **kwargs) do
|
|
145
145
|
Utils.parallel(Models::Record.subclasses) do |klass|
|
|
146
|
-
|
|
146
|
+
# lookup monitors without adding unnecessary downtime information
|
|
147
|
+
params = (klass.api_resource == "monitor" ? { with_downtimes: false } : {})
|
|
148
|
+
|
|
149
|
+
api.list(klass.api_resource, params)
|
|
147
150
|
end.flatten(1)
|
|
148
151
|
end
|
|
149
152
|
end
|
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: 2.
|
|
4
|
+
version: 2.7.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-10
|
|
11
|
+
date: 2025-11-10 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: diff-lcs
|