kennel 1.121.1 → 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/Readme.md +8 -0
- data/lib/kennel/file_cache.rb +11 -11
- data/lib/kennel/github_reporter.rb +1 -1
- data/lib/kennel/importer.rb +16 -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/progress.rb +22 -3
- data/lib/kennel/syncer.rb +3 -3
- data/lib/kennel/tasks.rb +11 -0
- data/lib/kennel/utils.rb +4 -6
- data/lib/kennel/version.rb +1 -1
- data/lib/kennel.rb +3 -2
- data/template/Readme.md +8 -0
- 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/Readme.md
CHANGED
@@ -406,6 +406,14 @@ https://foo.datadog.com/monitor/123
|
|
406
406
|
### Find all monitors with No-Data
|
407
407
|
`rake kennel:nodata TAG=team:foo`
|
408
408
|
|
409
|
+
### Finding the tracking id of a resource
|
410
|
+
|
411
|
+
When trying to link resources together, this avoids having to go through datadog UI.
|
412
|
+
|
413
|
+
```Bash
|
414
|
+
rake kennel:tracking_id ID=123 RESOURCE=monitor
|
415
|
+
```
|
416
|
+
|
409
417
|
<!-- NOT IN template/Readme.md -->
|
410
418
|
|
411
419
|
## Development
|
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) || {})
|
@@ -60,6 +62,8 @@ module Kennel
|
|
60
62
|
data[:critical] = data[:critical].to_i if data[:type] == "event alert"
|
61
63
|
|
62
64
|
data[:type] = "query alert" if data[:type] == "metric alert"
|
65
|
+
|
66
|
+
link_composite_monitors(data)
|
63
67
|
when "dashboard"
|
64
68
|
widgets = data[:widgets]&.flat_map { |widget| widget.dig(:definition, :widgets) || [widget] }
|
65
69
|
widgets&.each do |widget|
|
@@ -91,6 +95,18 @@ module Kennel
|
|
91
95
|
|
92
96
|
private
|
93
97
|
|
98
|
+
def link_composite_monitors(data)
|
99
|
+
if data[:type] == "composite"
|
100
|
+
data[:query].gsub!(/\d+/) do |id|
|
101
|
+
object = Kennel.send(:api).show("monitor", id)
|
102
|
+
tracking_id = Kennel::Models::Monitor.parse_tracking_id(object)
|
103
|
+
tracking_id ? "%{#{tracking_id}}" : id
|
104
|
+
rescue StandardError # monitor not found
|
105
|
+
id # keep the id
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
94
110
|
# reduce duplication in imports by using dry `q: :metadata` when possible
|
95
111
|
def dry_up_widget_metadata!(widget)
|
96
112
|
(widget.dig(:definition, :requests) || []).each do |request|
|
@@ -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/progress.rb
CHANGED
@@ -4,7 +4,9 @@ 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)
|
7
|
+
def self.progress(name, interval: 0.2, &block)
|
8
|
+
return progress_no_tty(name, &block) unless Kennel.err.tty?
|
9
|
+
|
8
10
|
Kennel.err.print "#{name} ... "
|
9
11
|
|
10
12
|
stop = false
|
@@ -16,15 +18,20 @@ module Kennel
|
|
16
18
|
loop do
|
17
19
|
break if stop
|
18
20
|
Kennel.err.print animation[count % animation.size]
|
19
|
-
sleep
|
21
|
+
sleep interval
|
20
22
|
Kennel.err.print "\b"
|
21
23
|
count += 1
|
22
24
|
end
|
23
25
|
end
|
24
26
|
|
25
|
-
time = Benchmark.realtime { result =
|
27
|
+
time = Benchmark.realtime { result = block.call }
|
26
28
|
|
27
29
|
stop = true
|
30
|
+
begin
|
31
|
+
spinner.run # wake thread, so it stops itself
|
32
|
+
rescue ThreadError
|
33
|
+
# thread was already dead, but we can't check with .alive? since it's a race condition
|
34
|
+
end
|
28
35
|
spinner.join
|
29
36
|
Kennel.err.print "#{time.round(2)}s\n"
|
30
37
|
|
@@ -32,5 +39,17 @@ module Kennel
|
|
32
39
|
ensure
|
33
40
|
stop = true # make thread stop without killing it
|
34
41
|
end
|
42
|
+
|
43
|
+
class << self
|
44
|
+
private
|
45
|
+
|
46
|
+
def progress_no_tty(name)
|
47
|
+
Kennel.err.puts "#{name} ..."
|
48
|
+
result = nil
|
49
|
+
time = Benchmark.realtime { result = yield }
|
50
|
+
Kennel.err.puts "#{name} ... #{time.round(2)}s"
|
51
|
+
result
|
52
|
+
end
|
53
|
+
end
|
35
54
|
end
|
36
55
|
end
|
data/lib/kennel/syncer.rb
CHANGED
@@ -42,7 +42,7 @@ module Kennel
|
|
42
42
|
|
43
43
|
def confirm
|
44
44
|
return false if noop?
|
45
|
-
return true if ENV["CI"] || !STDIN.tty?
|
45
|
+
return true if ENV["CI"] || !STDIN.tty? || !Kennel.err.tty?
|
46
46
|
Utils.ask("Execute Plan ?")
|
47
47
|
end
|
48
48
|
|
@@ -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/tasks.rb
CHANGED
@@ -233,6 +233,17 @@ namespace :kennel do
|
|
233
233
|
end
|
234
234
|
end
|
235
235
|
|
236
|
+
desc "Resolve given id to kennel tracking-id RESOURCE= ID="
|
237
|
+
task tracking_id: "kennel:environment" do
|
238
|
+
resource = ENV.fetch("RESOURCE")
|
239
|
+
id = ENV.fetch("ID")
|
240
|
+
klass =
|
241
|
+
Kennel::Models::Record.subclasses.detect { |s| s.api_resource == resource } ||
|
242
|
+
raise("resource #{resource} not know")
|
243
|
+
object = Kennel.send(:api).show(resource, id)
|
244
|
+
Kennel.out.puts klass.parse_tracking_id(object)
|
245
|
+
end
|
246
|
+
|
236
247
|
task :environment do
|
237
248
|
Kennel::Tasks.load_environment
|
238
249
|
end
|
data/lib/kennel/utils.rb
CHANGED
@@ -42,7 +42,7 @@ module Kennel
|
|
42
42
|
end
|
43
43
|
|
44
44
|
def ask(question)
|
45
|
-
Kennel.err.printf color(:red, "#{question} - press 'y' to continue: ")
|
45
|
+
Kennel.err.printf color(:red, "#{question} - press 'y' to continue: ", force: true)
|
46
46
|
begin
|
47
47
|
STDIN.gets.chomp == "y"
|
48
48
|
rescue Interrupt # do not show a backtrace if user decides to Ctrl+C here
|
@@ -51,12 +51,10 @@ module Kennel
|
|
51
51
|
end
|
52
52
|
end
|
53
53
|
|
54
|
-
def color(color, text)
|
55
|
-
|
56
|
-
end
|
54
|
+
def color(color, text, force: false)
|
55
|
+
return text unless force || Kennel.out.tty?
|
57
56
|
|
58
|
-
|
59
|
-
text.gsub(/\e\[\d+m(.*?)\e\[0m/, "\\1").gsub(/.#{Regexp.escape("\b")}/, "")
|
57
|
+
"\e[#{COLORS.fetch(color)}m#{text}\e[0m"
|
60
58
|
end
|
61
59
|
|
62
60
|
def capture_stdout
|
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
|
|
data/template/Readme.md
CHANGED
@@ -388,3 +388,11 @@ https://foo.datadog.com/monitor/123
|
|
388
388
|
### Find all monitors with No-Data
|
389
389
|
`rake kennel:nodata TAG=team:foo`
|
390
390
|
|
391
|
+
### Finding the tracking id of a resource
|
392
|
+
|
393
|
+
When trying to link resources together, this avoids having to go through datadog UI.
|
394
|
+
|
395
|
+
```Bash
|
396
|
+
rake kennel:tracking_id ID=123 RESOURCE=monitor
|
397
|
+
```
|
398
|
+
|
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-
|
11
|
+
date: 2022-10-21 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: diff-lcs
|