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