kennel 1.124.0 → 1.126.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/models/dashboard.rb +3 -1
- data/lib/kennel/models/monitor.rb +16 -13
- data/lib/kennel/models/record.rb +2 -2
- data/lib/kennel/models/slo.rb +2 -2
- data/lib/kennel/optional_validations.rb +36 -30
- data/lib/kennel/progress.rb +2 -2
- data/lib/kennel/syncer.rb +14 -26
- data/lib/kennel/tasks.rb +2 -1
- data/lib/kennel/template_variables.rb +2 -2
- data/lib/kennel/utils.rb +5 -0
- data/lib/kennel/version.rb +1 -1
- data/lib/kennel.rb +16 -4
- 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: d8254e03670c1874a6f9b85da5fe453200cdcd9aabe2f82dafc424a6301d8416
|
4
|
+
data.tar.gz: 2d1c0b444762941f79fcba893f5cddc9d0119138c5cf0fc04d6fc871f2caf7a8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 32c9cbe7957e0f0652180d9b743e4498f3624231e96907f2aaafe5889b9d2f5cfcac98b21dce058c7e06cd6b719ae21b91d01b478eb21028a333b6e0383732a1
|
7
|
+
data.tar.gz: '068566cb8e89e9c9d993ed451cd174a301ce3976c2240aa8c12c1ebf20b602b9cf245b0eb28267dc9263930ad4659163cb75fee67af1d9c1094a649129fb7e17'
|
@@ -230,7 +230,9 @@ module Kennel
|
|
230
230
|
|
231
231
|
# Avoid diff from datadog presets sorting.
|
232
232
|
presets = data[:template_variable_presets]
|
233
|
-
|
233
|
+
if presets && presets != presets.sort_by { |p| p[:name] }
|
234
|
+
invalid! :template_variable_presets_must_be_sorted, "template_variable_presets must be sorted by name"
|
235
|
+
end
|
234
236
|
end
|
235
237
|
|
236
238
|
def render_definitions(definitions)
|
@@ -21,7 +21,8 @@ module Kennel
|
|
21
21
|
renotify_interval: 0,
|
22
22
|
notify_audit: false,
|
23
23
|
no_data_timeframe: nil, # this works out ok since if notify_no_data is on, it would never be nil
|
24
|
-
groupby_simple_monitor: false
|
24
|
+
groupby_simple_monitor: false,
|
25
|
+
variables: nil
|
25
26
|
}.freeze
|
26
27
|
DEFAULT_ESCALATION_MESSAGE = ["", nil].freeze
|
27
28
|
ALLOWED_PRIORITY_CLASSES = [NilClass, Integer].freeze
|
@@ -30,7 +31,7 @@ module Kennel
|
|
30
31
|
settings(
|
31
32
|
:query, :name, :message, :escalation_message, :critical, :type, :renotify_interval, :warning, :timeout_h, :evaluation_delay,
|
32
33
|
:ok, :no_data_timeframe, :notify_no_data, :notify_audit, :tags, :critical_recovery, :warning_recovery, :require_full_window,
|
33
|
-
:threshold_windows, :new_host_delay, :new_group_delay, :priority, :validate_using_links
|
34
|
+
:threshold_windows, :new_host_delay, :new_group_delay, :priority, :validate_using_links, :variables
|
34
35
|
)
|
35
36
|
|
36
37
|
defaults(
|
@@ -50,7 +51,8 @@ module Kennel
|
|
50
51
|
critical_recovery: -> { nil },
|
51
52
|
warning_recovery: -> { nil },
|
52
53
|
threshold_windows: -> { nil },
|
53
|
-
priority: -> { MONITOR_DEFAULTS.fetch(:priority) }
|
54
|
+
priority: -> { MONITOR_DEFAULTS.fetch(:priority) },
|
55
|
+
variables: -> { MONITOR_OPTION_DEFAULTS.fetch(:variables) }
|
54
56
|
)
|
55
57
|
|
56
58
|
def build_json
|
@@ -73,7 +75,8 @@ module Kennel
|
|
73
75
|
escalation_message: Utils.presence(escalation_message.strip),
|
74
76
|
evaluation_delay: evaluation_delay,
|
75
77
|
locked: false, # setting this to true prevents any edit and breaks updates when using replace workflow
|
76
|
-
renotify_interval: renotify_interval || 0
|
78
|
+
renotify_interval: renotify_interval || 0,
|
79
|
+
variables: variables
|
77
80
|
}
|
78
81
|
)
|
79
82
|
|
@@ -211,26 +214,26 @@ module Kennel
|
|
211
214
|
super
|
212
215
|
|
213
216
|
if data[:name]&.start_with?(" ")
|
214
|
-
invalid! "name cannot start with a space"
|
217
|
+
invalid! :name_must_not_start_with_space, "name cannot start with a space"
|
215
218
|
end
|
216
219
|
|
217
220
|
type = data.fetch(:type)
|
218
221
|
|
219
222
|
# do not allow deprecated type that will be coverted by datadog and then produce a diff
|
220
223
|
if type == "metric alert"
|
221
|
-
invalid! "type 'metric alert' is deprecated, please set to a different type (e.g. 'query alert')"
|
224
|
+
invalid! :metric_alert_is_deprecated, "type 'metric alert' is deprecated, please set to a different type (e.g. 'query alert')"
|
222
225
|
end
|
223
226
|
|
224
227
|
# verify query includes critical value
|
225
228
|
if query_value = data.fetch(:query)[/\s*[<>]=?\s*(\d+(\.\d+)?)\s*$/, 1]
|
226
229
|
if Float(query_value) != Float(data.dig(:options, :thresholds, :critical))
|
227
|
-
invalid! "critical and value used in query must match"
|
230
|
+
invalid! :critical_does_not_match_query, "critical and value used in query must match"
|
228
231
|
end
|
229
232
|
end
|
230
233
|
|
231
234
|
# verify renotify interval is valid
|
232
235
|
unless RENOTIFY_INTERVALS.include? data.dig(:options, :renotify_interval)
|
233
|
-
invalid! "renotify_interval must be one of #{RENOTIFY_INTERVALS.join(", ")}"
|
236
|
+
invalid! :invalid_renotify_interval, "renotify_interval must be one of #{RENOTIFY_INTERVALS.join(", ")}"
|
234
237
|
end
|
235
238
|
|
236
239
|
if ["query alert", "service check"].include?(type) # TODO: most likely more types need this
|
@@ -240,15 +243,15 @@ module Kennel
|
|
240
243
|
validate_using_links(data)
|
241
244
|
|
242
245
|
if type == "service check" && !data[:query].to_s.include?(".by(")
|
243
|
-
invalid! "query must include a .by() at least .by(\"*\")"
|
246
|
+
invalid! :query_must_include_by, "query must include a .by() at least .by(\"*\")"
|
244
247
|
end
|
245
248
|
|
246
249
|
unless ALLOWED_PRIORITY_CLASSES.include?(priority.class)
|
247
|
-
invalid! "priority needs to be an Integer"
|
250
|
+
invalid! :invalid_priority, "priority needs to be an Integer"
|
248
251
|
end
|
249
252
|
|
250
253
|
if data.dig(:options, :timeout_h)&.> 24
|
251
|
-
invalid! "timeout_h must be <= 24"
|
254
|
+
invalid! :invalid_timeout_h, "timeout_h must be <= 24"
|
252
255
|
end
|
253
256
|
end
|
254
257
|
|
@@ -283,7 +286,7 @@ module Kennel
|
|
283
286
|
forbidden = used - allowed
|
284
287
|
return if forbidden.empty?
|
285
288
|
|
286
|
-
invalid! <<~MSG.rstrip
|
289
|
+
invalid! :invalid_variable_used_in_message, <<~MSG.rstrip
|
287
290
|
Used #{forbidden.join(", ")} in the message, but can only be used with #{allowed.join(", ")}.
|
288
291
|
Group or filter the query by #{forbidden.map { |f| f.sub(".name", "") }.join(", ")} to use it.
|
289
292
|
MSG
|
@@ -295,7 +298,7 @@ module Kennel
|
|
295
298
|
ids = data[:query].tr("-", "_").scan(/\b\d+\b/)
|
296
299
|
ids.reject! { |id| ALLOWED_UNLINKED.include?([tracking_id, id]) }
|
297
300
|
if ids.any?
|
298
|
-
invalid! <<~MSG.rstrip
|
301
|
+
invalid! :links_must_be_via_tracking_id, <<~MSG.rstrip
|
299
302
|
Used #{ids} in the query, but should only use links in the form of %{<project id>:<monitor id>}
|
300
303
|
If that is not possible, add `validate_using_links: ->(*){} # linked monitors are not in kennel
|
301
304
|
MSG
|
data/lib/kennel/models/record.rb
CHANGED
@@ -211,8 +211,8 @@ module Kennel
|
|
211
211
|
end
|
212
212
|
end
|
213
213
|
|
214
|
-
def invalid!(message)
|
215
|
-
unfiltered_validation_errors << ValidationMessage.new(message)
|
214
|
+
def invalid!(tag, message)
|
215
|
+
unfiltered_validation_errors << ValidationMessage.new(tag || OptionalValidations::UNIGNORABLE, message)
|
216
216
|
end
|
217
217
|
|
218
218
|
def raise_with_location(error, message)
|
data/lib/kennel/models/slo.rb
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
module Kennel
|
3
3
|
module Models
|
4
4
|
class Slo < Record
|
5
|
-
READONLY_ATTRIBUTES = superclass::READONLY_ATTRIBUTES + [:type_id, :monitor_tags]
|
5
|
+
READONLY_ATTRIBUTES = superclass::READONLY_ATTRIBUTES + [:type_id, :monitor_tags, :target_threshold, :timeframe, :warning_threshold]
|
6
6
|
TRACKING_FIELD = :description
|
7
7
|
DEFAULTS = {
|
8
8
|
description: nil,
|
@@ -85,7 +85,7 @@ module Kennel
|
|
85
85
|
super
|
86
86
|
|
87
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"
|
88
|
+
invalid! :warning_must_be_gt_critical, "Threshold warning must be greater-than critical value"
|
89
89
|
end
|
90
90
|
end
|
91
91
|
end
|
@@ -1,11 +1,13 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
module Kennel
|
3
3
|
module OptionalValidations
|
4
|
-
ValidationMessage = Struct.new(:text)
|
4
|
+
ValidationMessage = Struct.new(:tag, :text)
|
5
|
+
|
6
|
+
UNIGNORABLE = :unignorable
|
5
7
|
|
6
8
|
def self.included(base)
|
7
|
-
base.settings :
|
8
|
-
base.defaults(
|
9
|
+
base.settings :ignored_errors
|
10
|
+
base.defaults(ignored_errors: -> { [] })
|
9
11
|
end
|
10
12
|
|
11
13
|
def self.valid?(parts)
|
@@ -15,14 +17,26 @@ module Kennel
|
|
15
17
|
|
16
18
|
return true if parts_with_errors.empty?
|
17
19
|
|
20
|
+
example_tag = nil
|
21
|
+
|
18
22
|
Kennel.err.puts
|
19
23
|
parts_with_errors.sort_by(&:safe_tracking_id).each do |part|
|
20
24
|
part.filtered_validation_errors.each do |err|
|
21
|
-
Kennel.err.puts "#{part.safe_tracking_id} #{err.text}"
|
25
|
+
Kennel.err.puts "#{part.safe_tracking_id} [#{err.tag.inspect}] #{err.text.gsub("\n", " ")}"
|
26
|
+
example_tag = err.tag unless err.tag == :unignorable
|
22
27
|
end
|
23
28
|
end
|
24
29
|
Kennel.err.puts
|
25
30
|
|
31
|
+
Kennel.err.puts <<~MESSAGE if example_tag
|
32
|
+
If a particular error cannot be fixed, it can be marked as ignored via `ignored_errors`, e.g.:
|
33
|
+
Kennel::Models::Monitor.new(
|
34
|
+
...,
|
35
|
+
ignored_errors: [#{example_tag.inspect}]
|
36
|
+
)
|
37
|
+
|
38
|
+
MESSAGE
|
39
|
+
|
26
40
|
false
|
27
41
|
end
|
28
42
|
|
@@ -32,6 +46,7 @@ module Kennel
|
|
32
46
|
bad = Kennel::Utils.all_keys(data).grep_v(Symbol).sort.uniq
|
33
47
|
return if bad.empty?
|
34
48
|
invalid!(
|
49
|
+
:hash_keys_must_be_symbols,
|
35
50
|
"Only use Symbols as hash keys to avoid permanent diffs when updating.\n" \
|
36
51
|
"Change these keys to be symbols (usually 'foo' => 1 --> 'foo': 1)\n" \
|
37
52
|
"#{bad.map(&:inspect).join("\n")}"
|
@@ -39,39 +54,30 @@ module Kennel
|
|
39
54
|
end
|
40
55
|
|
41
56
|
def filter_validation_errors
|
42
|
-
if
|
43
|
-
|
44
|
-
elsif unfiltered_validation_errors.empty?
|
45
|
-
msg = "`validate` is set to false, but there are no validation errors to suppress. Remove `validate: false`"
|
46
|
-
|
47
|
-
mode = ENV.fetch("UNNECESSARY_VALIDATE_FALSE") do
|
48
|
-
if ENV.key?("PROJECT") || ENV.key?("TRACKING_ID")
|
49
|
-
"fail"
|
50
|
-
else
|
51
|
-
nil
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
|
-
if mode == "fail"
|
56
|
-
[ValidationMessage.new(msg)]
|
57
|
-
else
|
58
|
-
Kennel.out.puts "#{safe_tracking_id} #{msg}" if mode == "show"
|
57
|
+
if unfiltered_validation_errors.empty?
|
58
|
+
if ignored_errors.empty?
|
59
59
|
[]
|
60
|
+
else
|
61
|
+
[ValidationMessage.new(UNIGNORABLE, "`ignored_errors` is non-empty, but there are no errors to ignore. Remove `ignored_errors`")]
|
60
62
|
end
|
61
63
|
else
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
Kennel.out.puts "#{safe_tracking_id} `validate: false` suppressing error: #{err.text.gsub("\n", " ")}"
|
64
|
+
to_report =
|
65
|
+
if ENV["NO_IGNORED_ERRORS"]
|
66
|
+
# Turn off all suppressions, to see what errors are actually being suppressed
|
67
|
+
unfiltered_validation_errors
|
68
|
+
else
|
69
|
+
unfiltered_validation_errors.reject do |err|
|
70
|
+
err.tag != UNIGNORABLE && ignored_errors.include?(err.tag)
|
70
71
|
end
|
71
72
|
end
|
72
73
|
|
73
|
-
|
74
|
+
unused_ignores = ignored_errors - unfiltered_validation_errors.map(&:tag)
|
75
|
+
|
76
|
+
unless unused_ignores.empty?
|
77
|
+
to_report << ValidationMessage.new(UNIGNORABLE, "Unused ignores #{unused_ignores.map(&:inspect).sort.uniq.join(" ")}. Remove these from `ignored_errors`")
|
74
78
|
end
|
79
|
+
|
80
|
+
to_report
|
75
81
|
end
|
76
82
|
end
|
77
83
|
end
|
data/lib/kennel/progress.rb
CHANGED
@@ -4,8 +4,8 @@ require "benchmark"
|
|
4
4
|
module Kennel
|
5
5
|
class Progress
|
6
6
|
# print what we are doing and a spinner until it is done ... then show how long it took
|
7
|
-
def self.progress(name, interval: 0.2, &block)
|
8
|
-
return progress_no_tty(name, &block)
|
7
|
+
def self.progress(name, interval: 0.2, plain: false, &block)
|
8
|
+
return progress_no_tty(name, &block) if plain || !Kennel.err.tty?
|
9
9
|
|
10
10
|
Kennel.err.print "#{name} ... "
|
11
11
|
|
data/lib/kennel/syncer.rb
CHANGED
@@ -6,14 +6,17 @@ module Kennel
|
|
6
6
|
class Syncer
|
7
7
|
DELETE_ORDER = ["dashboard", "slo", "monitor", "synthetics/tests"].freeze # dashboards references monitors + slos, slos reference monitors
|
8
8
|
LINE_UP = "\e[1A\033[K" # go up and clear
|
9
|
+
|
9
10
|
Plan = Struct.new(:changes, keyword_init: true)
|
11
|
+
Change = Struct.new(:type, :api_resource, :tracking_id, :id)
|
10
12
|
|
11
|
-
def initialize(api, expected, kennel:, project_filter: nil, tracking_id_filter: nil)
|
13
|
+
def initialize(api, expected, actual, kennel:, project_filter: nil, tracking_id_filter: nil)
|
12
14
|
@api = api
|
13
15
|
@kennel = kennel
|
14
16
|
@project_filter = project_filter
|
15
17
|
@tracking_id_filter = tracking_id_filter
|
16
18
|
@expected = Set.new expected # need set to speed up deletion
|
19
|
+
@actual = actual
|
17
20
|
calculate_diff
|
18
21
|
validate_plan
|
19
22
|
prevent_irreversible_partial_updates
|
@@ -32,9 +35,9 @@ module Kennel
|
|
32
35
|
|
33
36
|
Plan.new(
|
34
37
|
changes:
|
35
|
-
@create.map { |_id, e|
|
36
|
-
@update.map { |
|
37
|
-
@delete.map { |
|
38
|
+
@create.map { |_id, e, _a| Change.new(:create, e.class.api_resource, e.tracking_id, nil) } +
|
39
|
+
@update.map { |id, e, _a| Change.new(:update, e.class.api_resource, e.tracking_id, id) } +
|
40
|
+
@delete.map { |id, _e, a| Change.new(:delete, a.fetch(:klass).api_resource, a.fetch(:tracking_id), id) }
|
38
41
|
)
|
39
42
|
end
|
40
43
|
|
@@ -51,9 +54,9 @@ module Kennel
|
|
51
54
|
message = "#{e.class.api_resource} #{e.tracking_id}"
|
52
55
|
Kennel.out.puts "Creating #{message}"
|
53
56
|
reply = @api.create e.class.api_resource, e.as_json
|
54
|
-
|
57
|
+
Utils.inline_resource_metadata reply, e.class
|
55
58
|
id = reply.fetch(:id)
|
56
|
-
changes <<
|
59
|
+
changes << Change.new(:create, e.class.api_resource, e.tracking_id, id)
|
57
60
|
populate_id_map [], [reply] # allow resolving ids we could previously no resolve
|
58
61
|
Kennel.out.puts "#{LINE_UP}Created #{message} #{e.class.url(id)}"
|
59
62
|
end
|
@@ -62,7 +65,7 @@ module Kennel
|
|
62
65
|
message = "#{e.class.api_resource} #{e.tracking_id} #{e.class.url(id)}"
|
63
66
|
Kennel.out.puts "Updating #{message}"
|
64
67
|
@api.update e.class.api_resource, id, e.as_json
|
65
|
-
changes <<
|
68
|
+
changes << Change.new(:update, e.class.api_resource, e.tracking_id, id)
|
66
69
|
Kennel.out.puts "#{LINE_UP}Updated #{message}"
|
67
70
|
end
|
68
71
|
|
@@ -71,7 +74,7 @@ module Kennel
|
|
71
74
|
message = "#{klass.api_resource} #{a.fetch(:tracking_id)} #{id}"
|
72
75
|
Kennel.out.puts "Deleting #{message}"
|
73
76
|
@api.delete klass.api_resource, id
|
74
|
-
changes <<
|
77
|
+
changes << Change.new(:delete, klass.api_resource, a.fetch(:tracking_id), id)
|
75
78
|
Kennel.out.puts "#{LINE_UP}Deleted #{message}"
|
76
79
|
end
|
77
80
|
|
@@ -123,17 +126,15 @@ module Kennel
|
|
123
126
|
@delete = []
|
124
127
|
@id_map = IdMap.new
|
125
128
|
|
126
|
-
actual = Progress.progress("Downloading definitions") { download_definitions }
|
127
|
-
|
128
129
|
Progress.progress "Diffing" do
|
129
|
-
populate_id_map @expected, actual
|
130
|
-
filter_actual! actual
|
130
|
+
populate_id_map @expected, @actual
|
131
|
+
filter_actual! @actual
|
131
132
|
resolve_linked_tracking_ids! @expected # resolve dependencies to avoid diff
|
132
133
|
|
133
134
|
@expected.each(&:add_tracking_id) # avoid diff with actual
|
134
135
|
|
135
136
|
lookup_map = matching_expected_lookup_map
|
136
|
-
items = actual.map do |a|
|
137
|
+
items = @actual.map do |a|
|
137
138
|
e = matching_expected(a, lookup_map)
|
138
139
|
if e && @expected.delete?(e)
|
139
140
|
[e, a]
|
@@ -166,19 +167,6 @@ module Kennel
|
|
166
167
|
end
|
167
168
|
end
|
168
169
|
|
169
|
-
def download_definitions
|
170
|
-
Utils.parallel(Models::Record.subclasses) do |klass|
|
171
|
-
results = @api.list(klass.api_resource, with_downtimes: false) # lookup monitors without adding unnecessary downtime information
|
172
|
-
results = results[results.keys.first] if results.is_a?(Hash) # dashboards are nested in {dashboards: []}
|
173
|
-
results.each { |a| cache_metadata(a, klass) }
|
174
|
-
end.flatten(1)
|
175
|
-
end
|
176
|
-
|
177
|
-
def cache_metadata(a, klass)
|
178
|
-
a[:klass] = klass
|
179
|
-
a[:tracking_id] = a.fetch(:klass).parse_tracking_id(a)
|
180
|
-
end
|
181
|
-
|
182
170
|
def ensure_all_ids_found
|
183
171
|
@expected.each do |e|
|
184
172
|
next unless id = e.id
|
data/lib/kennel/tasks.rb
CHANGED
@@ -102,8 +102,9 @@ namespace :kennel do
|
|
102
102
|
|
103
103
|
# also generate parts so users see and commit updated generated automatically
|
104
104
|
desc "show planned datadog changes (scope with PROJECT=name)"
|
105
|
-
task plan: :
|
105
|
+
task plan: :environment do
|
106
106
|
Kennel::Tasks.kennel.plan
|
107
|
+
Kennel::Tasks.kennel.generate
|
107
108
|
end
|
108
109
|
|
109
110
|
desc "update datadog (scope with PROJECT=name)"
|
@@ -29,8 +29,8 @@ module Kennel
|
|
29
29
|
return if queries.empty?
|
30
30
|
|
31
31
|
invalid!(
|
32
|
-
|
33
|
-
"
|
32
|
+
:queries_must_use_template_variables,
|
33
|
+
"queries #{queries.join(", ")} must use the template variables #{variables.join(", ")}"
|
34
34
|
)
|
35
35
|
end
|
36
36
|
|
data/lib/kennel/utils.rb
CHANGED
data/lib/kennel/version.rb
CHANGED
data/lib/kennel.rb
CHANGED
@@ -59,7 +59,7 @@ module Kennel
|
|
59
59
|
attr_accessor :strict_imports
|
60
60
|
|
61
61
|
def generate
|
62
|
-
parts = generated
|
62
|
+
parts = generated(plain: false)
|
63
63
|
parts_serializer.write(parts) if ENV["STORE"] != "false" # quicker when debugging
|
64
64
|
parts
|
65
65
|
end
|
@@ -75,12 +75,24 @@ module Kennel
|
|
75
75
|
|
76
76
|
private
|
77
77
|
|
78
|
+
def download_definitions
|
79
|
+
Progress.progress("Downloading definitions", plain: true) do
|
80
|
+
Utils.parallel(Models::Record.subclasses) do |klass|
|
81
|
+
results = api.list(klass.api_resource, with_downtimes: false) # lookup monitors without adding unnecessary downtime information
|
82
|
+
results.each { |a| Utils.inline_resource_metadata(a, klass) }
|
83
|
+
end.flatten(1)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
78
87
|
def filter
|
79
88
|
@filter ||= Filter.new
|
80
89
|
end
|
81
90
|
|
82
91
|
def syncer
|
83
|
-
@syncer ||=
|
92
|
+
@syncer ||= begin
|
93
|
+
expected, actual = Utils.parallel([:generated, :download_definitions]) { |m| send m }
|
94
|
+
Syncer.new(api, expected, actual, kennel: self, project_filter: filter.project_filter, tracking_id_filter: filter.tracking_id_filter)
|
95
|
+
end
|
84
96
|
end
|
85
97
|
|
86
98
|
def api
|
@@ -95,9 +107,9 @@ module Kennel
|
|
95
107
|
@parts_serializer ||= PartsSerializer.new(filter: filter)
|
96
108
|
end
|
97
109
|
|
98
|
-
def generated
|
110
|
+
def generated(plain: true)
|
99
111
|
@generated ||= begin
|
100
|
-
parts = Progress.progress "Finding parts" do
|
112
|
+
parts = Progress.progress "Finding parts", plain: plain do
|
101
113
|
projects = projects_provider.projects
|
102
114
|
projects = filter.filter_projects projects
|
103
115
|
|
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.126.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-
|
11
|
+
date: 2022-12-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: diff-lcs
|