kennel 1.101.0 → 1.103.1
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/id_map.rb +0 -4
- data/lib/kennel/importer.rb +1 -1
- data/lib/kennel/syncer.rb +23 -30
- data/lib/kennel/tasks.rb +37 -6
- data/lib/kennel/version.rb +1 -1
- data/lib/kennel.rb +2 -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: bee3140dd0001488c0ec264244c7a28b30f3a5f877db23438884afca5181aef5
|
4
|
+
data.tar.gz: eb0071ea0aac8be39f1517738093fd61a211cb65e61ccb1f457030b999a58487
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 442611b5ef920684f95c698e654a53c3c367fc6c48a8def218dd40d130dba349ab512e880e88c7d9c0fb7634887bb78b40381314a81a2457a393301cee169b18
|
7
|
+
data.tar.gz: a26df226bd670a252539b4001401cb2d3dc9e32883fc2811b36cb01b26a6a9c23bc5da970c68b71cdac174432f7d4e2df5643b4a893adc9a85ce8908dcbf14e6
|
data/lib/kennel/id_map.rb
CHANGED
data/lib/kennel/importer.rb
CHANGED
@@ -137,7 +137,7 @@ module Kennel
|
|
137
137
|
pretty = convert_strings_to_heredoc(pretty)
|
138
138
|
|
139
139
|
"\n#{pretty}\n "
|
140
|
-
elsif
|
140
|
+
elsif [:message, :description].include?(k)
|
141
141
|
"\n <<~TEXT\n#{v.each_line.map { |l| l.strip.empty? ? "\n" : " #{l}" }.join}\n \#{super()}\n TEXT\n "
|
142
142
|
elsif k == :tags
|
143
143
|
" super() + #{v.inspect} "
|
data/lib/kennel/syncer.rb
CHANGED
@@ -3,7 +3,6 @@ module Kennel
|
|
3
3
|
class Syncer
|
4
4
|
DELETE_ORDER = ["dashboard", "slo", "monitor", "synthetics/tests"].freeze # dashboards references monitors + slos, slos reference monitors
|
5
5
|
LINE_UP = "\e[1A\033[K" # go up and clear
|
6
|
-
DEFAULT_BRANCH = "master"
|
7
6
|
|
8
7
|
def initialize(api, expected, project: nil)
|
9
8
|
@api = api
|
@@ -18,6 +17,7 @@ module Kennel
|
|
18
17
|
if noop?
|
19
18
|
Kennel.out.puts Utils.color(:green, "Nothing to do")
|
20
19
|
else
|
20
|
+
@warnings.each { |message| Kennel.out.puts Utils.color(:yellow, "Warning: #{message}") }
|
21
21
|
print_plan "Create", @create, :green
|
22
22
|
print_plan "Update", @update, :yellow
|
23
23
|
print_plan "Delete", @delete, :red
|
@@ -27,7 +27,6 @@ module Kennel
|
|
27
27
|
def confirm
|
28
28
|
return false if noop?
|
29
29
|
return true if ENV["CI"] || !STDIN.tty?
|
30
|
-
warn_about_deleting_resources_with_id if @project_filter
|
31
30
|
Utils.ask("Execute Plan ?")
|
32
31
|
end
|
33
32
|
|
@@ -60,30 +59,6 @@ module Kennel
|
|
60
59
|
|
61
60
|
private
|
62
61
|
|
63
|
-
# this is brittle/hacky since it relies on knowledge from the generation + git + branch knowledge
|
64
|
-
def warn_about_deleting_resources_with_id
|
65
|
-
@delete.each do |_, _, a|
|
66
|
-
tracking_id = a.fetch(:tracking_id)
|
67
|
-
api_resource = a.fetch(:klass).api_resource
|
68
|
-
|
69
|
-
file = "generated/#{tracking_id.sub(":", "/")}.json"
|
70
|
-
old = `true && git show #{DEFAULT_BRANCH}:#{file.shellescape} 2>&1` # true && to not crash on missing git
|
71
|
-
|
72
|
-
next unless $?.success?
|
73
|
-
old =
|
74
|
-
begin
|
75
|
-
JSON.parse(old)
|
76
|
-
rescue StandardError
|
77
|
-
false
|
78
|
-
end
|
79
|
-
next if !old || !old["id"]
|
80
|
-
|
81
|
-
Kennel.out.puts(
|
82
|
-
Utils.color(:red, "WARNING: deleting #{api_resource} #{tracking_id} will break #{DEFAULT_BRANCH} branch")
|
83
|
-
)
|
84
|
-
end
|
85
|
-
end
|
86
|
-
|
87
62
|
# loop over items until everything is resolved or crash when we get stuck
|
88
63
|
# this solves cases like composite monitors depending on each other or monitor->monitor slo->slo monitor chains
|
89
64
|
def each_resolved(list)
|
@@ -120,6 +95,7 @@ module Kennel
|
|
120
95
|
end
|
121
96
|
|
122
97
|
def calculate_diff
|
98
|
+
@warnings = []
|
123
99
|
@update = []
|
124
100
|
@delete = []
|
125
101
|
@id_map = IdMap.new
|
@@ -181,7 +157,11 @@ module Kennel
|
|
181
157
|
@expected.each do |e|
|
182
158
|
next unless id = e.id
|
183
159
|
resource = e.class.api_resource
|
184
|
-
|
160
|
+
if Kennel.strict_imports
|
161
|
+
raise "Unable to find existing #{resource} with id #{id}\nIf the #{resource} was deleted, remove the `id: -> { #{id} }` line."
|
162
|
+
else
|
163
|
+
@warnings << "#{resource} #{e.tracking_id} specifies id #{id}, but no such #{resource} exists. 'id' will be ignored. Remove the `id: -> { #{id} }` line."
|
164
|
+
end
|
185
165
|
end
|
186
166
|
end
|
187
167
|
|
@@ -254,15 +234,28 @@ module Kennel
|
|
254
234
|
end
|
255
235
|
|
256
236
|
def populate_id_map(expected, actual)
|
237
|
+
# mark everything as new
|
257
238
|
expected.each do |e|
|
258
|
-
@id_map.
|
239
|
+
@id_map.set(e.class.api_resource, e.tracking_id, IdMap::NEW)
|
240
|
+
if e.class.api_resource == "synthetics/tests"
|
241
|
+
@id_map.set(Kennel::Models::Monitor.api_resource, e.tracking_id, IdMap::NEW)
|
242
|
+
end
|
259
243
|
end
|
260
244
|
|
245
|
+
# override resources that exist with their id
|
246
|
+
project_prefix = @project_filter && "#{@project_filter}:"
|
261
247
|
actual.each do |a|
|
248
|
+
# ignore when not managed by kennel
|
262
249
|
next unless tracking_id = a.fetch(:tracking_id)
|
263
|
-
next unless @id_map.get(a.fetch(:klass).api_resource, tracking_id)
|
264
250
|
|
265
|
-
|
251
|
+
# ignore when deleted from the codebase
|
252
|
+
# (when running with project filter we cannot see the other resources in the codebase)
|
253
|
+
api_resource = a.fetch(:klass).api_resource
|
254
|
+
next if
|
255
|
+
!@id_map.get(api_resource, tracking_id) &&
|
256
|
+
(!project_prefix || tracking_id.start_with?(project_prefix))
|
257
|
+
|
258
|
+
@id_map.set(api_resource, tracking_id, a.fetch(:id))
|
266
259
|
if a[:klass].api_resource == "synthetics/tests"
|
267
260
|
@id_map.set(Kennel::Models::Monitor.api_resource, tracking_id, a.fetch(:monitor_id))
|
268
261
|
end
|
data/lib/kennel/tasks.rb
CHANGED
@@ -3,6 +3,7 @@ require "English"
|
|
3
3
|
require "kennel"
|
4
4
|
require "kennel/unmuted_alerts"
|
5
5
|
require "kennel/importer"
|
6
|
+
require "json"
|
6
7
|
|
7
8
|
module Kennel
|
8
9
|
module Tasks
|
@@ -75,6 +76,7 @@ namespace :kennel do
|
|
75
76
|
is_push = (ENV["TRAVIS_PULL_REQUEST"] == "false" || ENV["GITHUB_EVENT_NAME"] == "push")
|
76
77
|
task_name =
|
77
78
|
if on_default_branch && is_push
|
79
|
+
Kennel.strict_imports = false
|
78
80
|
"kennel:update_datadog"
|
79
81
|
else
|
80
82
|
"kennel:plan" # show plan in CI logs
|
@@ -89,7 +91,7 @@ namespace :kennel do
|
|
89
91
|
Kennel::UnmutedAlerts.print(Kennel.send(:api), tag)
|
90
92
|
end
|
91
93
|
|
92
|
-
desc "show monitors with no data by TAG, for example TAG=team:foo"
|
94
|
+
desc "show monitors with no data by TAG, for example TAG=team:foo [THRESHOLD_DAYS=7] [FORMAT=json]"
|
93
95
|
task nodata: :environment do
|
94
96
|
tag = ENV["TAG"] || Kennel::Tasks.abort("Call with TAG=foo:bar")
|
95
97
|
monitors = Kennel.send(:api).list("monitor", monitor_tags: tag, group_states: "no data")
|
@@ -97,16 +99,45 @@ namespace :kennel do
|
|
97
99
|
monitors.reject! { |m| m[:tags].include? "nodata:ignore" }
|
98
100
|
if monitors.any?
|
99
101
|
Kennel.err.puts <<~TEXT
|
100
|
-
|
101
|
-
To ignore monitors with nodata, tag the monitor with "nodata:ignore"
|
102
|
+
To ignore monitors with expected nodata, tag it with "nodata:ignore"
|
102
103
|
|
103
104
|
TEXT
|
104
105
|
end
|
105
106
|
|
107
|
+
now = Time.now
|
106
108
|
monitors.each do |m|
|
107
|
-
|
108
|
-
|
109
|
-
|
109
|
+
m[:days_in_no_data] =
|
110
|
+
if m[:overall_state_modified]
|
111
|
+
since = Date.parse(m[:overall_state_modified]).to_time
|
112
|
+
((now - since) / (24 * 60 * 60)).to_i
|
113
|
+
else
|
114
|
+
999
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
if threshold = ENV["THRESHOLD_DAYS"]
|
119
|
+
monitors.select! { |m| m[:days_in_no_data] > Integer(threshold) }
|
120
|
+
end
|
121
|
+
|
122
|
+
monitors.each { |m| m[:url] = Kennel::Utils.path_to_url("/monitors/#{m[:id]}") }
|
123
|
+
|
124
|
+
if ENV["FORMAT"] == "json"
|
125
|
+
report = monitors.map do |m|
|
126
|
+
match = m[:message].to_s.match(/-- Managed by kennel (\S+:\S+) in (\S+), /) || []
|
127
|
+
m.slice(:url, :name, :tags, :days_in_no_data).merge(
|
128
|
+
kennel_tracking_id: match[1],
|
129
|
+
kennel_source: match[2]
|
130
|
+
)
|
131
|
+
end
|
132
|
+
|
133
|
+
Kennel.out.puts JSON.pretty_generate(report)
|
134
|
+
else
|
135
|
+
monitors.each do |m|
|
136
|
+
Kennel.out.puts m[:name]
|
137
|
+
Kennel.out.puts Kennel::Utils.path_to_url("/monitors/#{m[:id]}")
|
138
|
+
Kennel.out.puts "No data since #{m[:days_in_no_data]}d"
|
139
|
+
Kennel.out.puts
|
140
|
+
end
|
110
141
|
end
|
111
142
|
end
|
112
143
|
|
data/lib/kennel/version.rb
CHANGED
data/lib/kennel.rb
CHANGED
@@ -2,7 +2,6 @@
|
|
2
2
|
require "faraday"
|
3
3
|
require "json"
|
4
4
|
require "zeitwerk"
|
5
|
-
require "shellwords"
|
6
5
|
require "English"
|
7
6
|
|
8
7
|
require "kennel/version"
|
@@ -42,9 +41,10 @@ module Kennel
|
|
42
41
|
|
43
42
|
@out = $stdout
|
44
43
|
@err = $stderr
|
44
|
+
@strict_imports = true
|
45
45
|
|
46
46
|
class << self
|
47
|
-
attr_accessor :out, :err
|
47
|
+
attr_accessor :out, :err, :strict_imports
|
48
48
|
|
49
49
|
def generate
|
50
50
|
store generated
|
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.103.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Michael Grosser
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-11-
|
11
|
+
date: 2021-11-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: faraday
|