kennel 1.129.0 → 1.130.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/api.rb +12 -4
- data/lib/kennel/attribute_differ.rb +6 -6
- data/lib/kennel/console.rb +66 -0
- data/lib/kennel/github_reporter.rb +1 -1
- data/lib/kennel/importer.rb +1 -1
- data/lib/kennel/models/base.rb +1 -1
- data/lib/kennel/string_utils.rb +35 -0
- data/lib/kennel/syncer.rb +5 -6
- data/lib/kennel/unmuted_alerts.rb +1 -1
- data/lib/kennel/utils.rb +0 -94
- data/lib/kennel/version.rb +1 -1
- data/lib/kennel.rb +3 -2
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d6ee3df09b69dd5a7af7285c219f4415c4e94ce2ab4f6533c5fff03be848e9c4
|
4
|
+
data.tar.gz: d7f923b69ad9b63774141ac0e9c6c04de7a26a67abd732c41c5f19d478704656
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7c967bf54743cc757a0c0c911e981701d4b5b393f6ebac66538432541c7c6dfecef2cd8c1c0e5389f90c7d0b91a54e79a29e0e1abf9d16fd67adad4bcd6209fe
|
7
|
+
data.tar.gz: 297239ea9305e4eadbe40a363160b0ca2aaf70dad237f95a448b00b30d3db9ed9f707b2736b2596ef73e8981d333b600af87da40978f5d1c9fc8e0dee3d7f9ea
|
data/lib/kennel/api.rb
CHANGED
@@ -5,6 +5,14 @@ module Kennel
|
|
5
5
|
class Api
|
6
6
|
CACHE_FILE = "tmp/cache/details"
|
7
7
|
|
8
|
+
def self.tag(api_resource, reply)
|
9
|
+
klass = Models::Record.api_resource_map[api_resource]
|
10
|
+
reply.merge(
|
11
|
+
klass: klass,
|
12
|
+
tracking_id: klass.parse_tracking_id(reply)
|
13
|
+
)
|
14
|
+
end
|
15
|
+
|
8
16
|
def initialize(app_key = nil, api_key = nil)
|
9
17
|
@app_key = app_key || ENV.fetch("DATADOG_APP_KEY")
|
10
18
|
@api_key = api_key || ENV.fetch("DATADOG_API_KEY")
|
@@ -16,7 +24,7 @@ module Kennel
|
|
16
24
|
response = request :get, "/api/v1/#{api_resource}/#{id}", params: params
|
17
25
|
response = response.fetch(:data) if api_resource == "slo"
|
18
26
|
response[:id] = response.delete(:public_id) if api_resource == "synthetics/tests"
|
19
|
-
response
|
27
|
+
self.class.tag(api_resource, response)
|
20
28
|
end
|
21
29
|
|
22
30
|
def list(api_resource, params = {})
|
@@ -32,7 +40,7 @@ module Kennel
|
|
32
40
|
# ignore monitor synthetics create and that inherit the kennel_id, we do not directly manage them
|
33
41
|
response.reject! { |m| m[:type] == "synthetics alert" } if api_resource == "monitor"
|
34
42
|
|
35
|
-
response
|
43
|
+
response.map { |r| self.class.tag(api_resource, r) }
|
36
44
|
end
|
37
45
|
end
|
38
46
|
|
@@ -40,13 +48,13 @@ module Kennel
|
|
40
48
|
response = request :post, "/api/v1/#{api_resource}", body: attributes
|
41
49
|
response = response.fetch(:data).first if api_resource == "slo"
|
42
50
|
response[:id] = response.delete(:public_id) if api_resource == "synthetics/tests"
|
43
|
-
response
|
51
|
+
self.class.tag(api_resource, response)
|
44
52
|
end
|
45
53
|
|
46
54
|
def update(api_resource, id, attributes)
|
47
55
|
response = request :put, "/api/v1/#{api_resource}/#{id}", body: attributes
|
48
56
|
response[:id] = response.delete(:public_id) if api_resource == "synthetics/tests"
|
49
|
-
response
|
57
|
+
self.class.tag(api_resource, response)
|
50
58
|
end
|
51
59
|
|
52
60
|
# - force=true to not dead-lock on dependent monitors+slos
|
@@ -46,13 +46,13 @@ module Kennel
|
|
46
46
|
Diff::LCS.sdiff(old.split("\n", -1), new.split("\n", -1)).flat_map do |diff|
|
47
47
|
case diff.action
|
48
48
|
when "-"
|
49
|
-
|
49
|
+
Console.color(:red, "- #{diff.old_element}")
|
50
50
|
when "+"
|
51
|
-
|
51
|
+
Console.color(:green, "+ #{diff.new_element}")
|
52
52
|
when "!"
|
53
53
|
[
|
54
|
-
|
55
|
-
|
54
|
+
Console.color(:red, "- #{diff.old_element}"),
|
55
|
+
Console.color(:green, "+ #{diff.new_element}")
|
56
56
|
]
|
57
57
|
else
|
58
58
|
" #{diff.old_element}"
|
@@ -61,12 +61,12 @@ module Kennel
|
|
61
61
|
end
|
62
62
|
|
63
63
|
def truncate(message)
|
64
|
-
warning =
|
64
|
+
warning = Console.color(
|
65
65
|
:magenta,
|
66
66
|
" (Diff for this item truncated after #{@max_diff_lines} lines. " \
|
67
67
|
"Rerun with MAX_DIFF_LINES=#{@max_diff_lines * 2} to see more)"
|
68
68
|
)
|
69
|
-
|
69
|
+
StringUtils.truncate_lines(message, to: @max_diff_lines, warning: warning)
|
70
70
|
end
|
71
71
|
|
72
72
|
# TODO: use awesome-print or similar, but it has too many monkey-patches
|
@@ -0,0 +1,66 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module Kennel
|
3
|
+
module Console
|
4
|
+
COLORS = { red: 31, green: 32, yellow: 33, cyan: 36, magenta: 35, default: 0 }.freeze
|
5
|
+
|
6
|
+
class TeeIO < IO
|
7
|
+
def initialize(ios)
|
8
|
+
super(0) # called with fake file descriptor 0, so we can call super and get a proper class
|
9
|
+
@ios = ios
|
10
|
+
end
|
11
|
+
|
12
|
+
def write(string)
|
13
|
+
@ios.each { |io| io.write string }
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
class << self
|
18
|
+
def ask?(question)
|
19
|
+
Kennel.err.printf color(:red, "#{question} - press 'y' to continue: ", force: true)
|
20
|
+
begin
|
21
|
+
STDIN.gets.chomp == "y"
|
22
|
+
rescue Interrupt # do not show a backtrace if user decides to Ctrl+C here
|
23
|
+
Kennel.err.print "\n"
|
24
|
+
exit 1
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def color(color, text, force: false)
|
29
|
+
return text unless force || Kennel.out.tty?
|
30
|
+
|
31
|
+
"\e[#{COLORS.fetch(color)}m#{text}\e[0m"
|
32
|
+
end
|
33
|
+
|
34
|
+
def capture_stdout
|
35
|
+
old = Kennel.out
|
36
|
+
Kennel.out = StringIO.new
|
37
|
+
yield
|
38
|
+
Kennel.out.string
|
39
|
+
ensure
|
40
|
+
Kennel.out = old
|
41
|
+
end
|
42
|
+
|
43
|
+
def capture_stderr
|
44
|
+
old = Kennel.err
|
45
|
+
Kennel.err = StringIO.new
|
46
|
+
yield
|
47
|
+
Kennel.err.string
|
48
|
+
ensure
|
49
|
+
Kennel.err = old
|
50
|
+
end
|
51
|
+
|
52
|
+
def tee_output
|
53
|
+
old_stdout = Kennel.out
|
54
|
+
old_stderr = Kennel.err
|
55
|
+
capture = StringIO.new
|
56
|
+
Kennel.out = TeeIO.new([capture, Kennel.out])
|
57
|
+
Kennel.err = TeeIO.new([capture, Kennel.err])
|
58
|
+
yield
|
59
|
+
capture.string
|
60
|
+
ensure
|
61
|
+
Kennel.out = old_stdout
|
62
|
+
Kennel.err = old_stderr
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
data/lib/kennel/importer.rb
CHANGED
data/lib/kennel/models/base.rb
CHANGED
@@ -0,0 +1,35 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module Kennel
|
3
|
+
module StringUtils
|
4
|
+
class << self
|
5
|
+
def snake_case(string)
|
6
|
+
string
|
7
|
+
.gsub(/::/, "_") # Foo::Bar -> foo_bar
|
8
|
+
.gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2') # FOOBar -> foo_bar
|
9
|
+
.gsub(/([a-z\d])([A-Z])/, '\1_\2') # fooBar -> foo_bar
|
10
|
+
.tr("-", "_") # foo-bar -> foo_bar
|
11
|
+
.downcase
|
12
|
+
end
|
13
|
+
|
14
|
+
# for child projects, not used internally
|
15
|
+
def title_case(string)
|
16
|
+
string.split(/[\s_]/).map(&:capitalize) * " "
|
17
|
+
end
|
18
|
+
|
19
|
+
# simplified version of https://apidock.com/rails/ActiveSupport/Inflector/parameterize
|
20
|
+
def parameterize(string)
|
21
|
+
string
|
22
|
+
.downcase
|
23
|
+
.gsub(/[^a-z0-9\-_]+/, "-") # remove unsupported
|
24
|
+
.gsub(/-{2,}/, "-") # remove duplicates
|
25
|
+
.gsub(/^-|-$/, "") # remove leading/trailing
|
26
|
+
end
|
27
|
+
|
28
|
+
def truncate_lines(text, to:, warning:)
|
29
|
+
lines = text.split(/\n/, to + 1)
|
30
|
+
lines[-1] = warning if lines.size > to
|
31
|
+
lines.join("\n")
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
data/lib/kennel/syncer.rb
CHANGED
@@ -22,7 +22,7 @@ module Kennel
|
|
22
22
|
validate_changes
|
23
23
|
prevent_irreversible_partial_updates
|
24
24
|
|
25
|
-
@warnings.each { |message| Kennel.out.puts
|
25
|
+
@warnings.each { |message| Kennel.out.puts Console.color(:yellow, "Warning: #{message}") }
|
26
26
|
end
|
27
27
|
|
28
28
|
def plan
|
@@ -37,7 +37,7 @@ module Kennel
|
|
37
37
|
def print_plan
|
38
38
|
Kennel.out.puts "Plan:"
|
39
39
|
if noop?
|
40
|
-
Kennel.out.puts
|
40
|
+
Kennel.out.puts Console.color(:green, "Nothing to do")
|
41
41
|
else
|
42
42
|
print_changes "Create", @create, :green
|
43
43
|
print_changes "Update", @update, :yellow
|
@@ -48,7 +48,7 @@ module Kennel
|
|
48
48
|
def confirm
|
49
49
|
return false if noop?
|
50
50
|
return true if ENV["CI"] || !STDIN.tty? || !Kennel.err.tty?
|
51
|
-
|
51
|
+
Console.ask?("Execute Plan ?")
|
52
52
|
end
|
53
53
|
|
54
54
|
def update
|
@@ -58,7 +58,6 @@ module Kennel
|
|
58
58
|
message = "#{e.class.api_resource} #{e.tracking_id}"
|
59
59
|
Kennel.out.puts "Creating #{message}"
|
60
60
|
reply = @api.create e.class.api_resource, e.as_json
|
61
|
-
Utils.inline_resource_metadata reply, e.class
|
62
61
|
id = reply.fetch(:id)
|
63
62
|
changes << Change.new(:create, e.class.api_resource, e.tracking_id, id)
|
64
63
|
populate_id_map [], [reply] # allow resolving ids we could previously no resolve
|
@@ -211,7 +210,7 @@ module Kennel
|
|
211
210
|
return if list.empty?
|
212
211
|
list.each do |_, e, a, diff|
|
213
212
|
klass = (e ? e.class : a.fetch(:klass))
|
214
|
-
Kennel.out.puts
|
213
|
+
Kennel.out.puts Console.color(color, "#{step} #{klass.api_resource} #{e&.tracking_id || a.fetch(:tracking_id)}")
|
215
214
|
diff&.each { |args| Kennel.out.puts @attribute_differ.format(*args) } # only for update
|
216
215
|
end
|
217
216
|
end
|
@@ -270,7 +269,7 @@ module Kennel
|
|
270
269
|
(!@tracking_id_filter || @tracking_id_filter.include?(tracking_id))
|
271
270
|
|
272
271
|
@id_map.set(api_resource, tracking_id, a.fetch(:id))
|
273
|
-
if a
|
272
|
+
if a.fetch(:klass).api_resource == "synthetics/tests"
|
274
273
|
@id_map.set(Kennel::Models::Monitor.api_resource, tracking_id, a.fetch(:monitor_id))
|
275
274
|
end
|
276
275
|
end
|
@@ -22,7 +22,7 @@ module Kennel
|
|
22
22
|
m[:state][:groups].each do |g|
|
23
23
|
color = COLORS[g[:status]] || :default
|
24
24
|
since = "\t#{time_since(g[:last_triggered_ts])}"
|
25
|
-
Kennel.out.puts "#{Kennel::
|
25
|
+
Kennel.out.puts "#{Kennel::Console.color(color, g[:status])}\t#{g[:name]}#{since}"
|
26
26
|
end
|
27
27
|
Kennel.out.puts
|
28
28
|
end
|
data/lib/kennel/utils.rb
CHANGED
@@ -1,100 +1,11 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
module Kennel
|
3
3
|
module Utils
|
4
|
-
COLORS = { red: 31, green: 32, yellow: 33, cyan: 36, magenta: 35, default: 0 }.freeze
|
5
|
-
|
6
|
-
class TeeIO < IO
|
7
|
-
def initialize(ios)
|
8
|
-
super(0) # called with fake file descriptor 0, so we can call super and get a proper class
|
9
|
-
@ios = ios
|
10
|
-
end
|
11
|
-
|
12
|
-
def write(string)
|
13
|
-
@ios.each { |io| io.write string }
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
17
4
|
class << self
|
18
|
-
def snake_case(string)
|
19
|
-
string
|
20
|
-
.gsub(/::/, "_") # Foo::Bar -> foo_bar
|
21
|
-
.gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2') # FOOBar -> foo_bar
|
22
|
-
.gsub(/([a-z\d])([A-Z])/, '\1_\2') # fooBar -> foo_bar
|
23
|
-
.tr("-", "_") # foo-bar -> foo_bar
|
24
|
-
.downcase
|
25
|
-
end
|
26
|
-
|
27
|
-
# for child projects, not used internally
|
28
|
-
def title_case(string)
|
29
|
-
string.split(/[\s_]/).map(&:capitalize) * " "
|
30
|
-
end
|
31
|
-
|
32
|
-
# simplified version of https://apidock.com/rails/ActiveSupport/Inflector/parameterize
|
33
|
-
def parameterize(string)
|
34
|
-
string
|
35
|
-
.downcase
|
36
|
-
.gsub(/[^a-z0-9\-_]+/, "-") # remove unsupported
|
37
|
-
.gsub(/-{2,}/, "-") # remove duplicates
|
38
|
-
.gsub(/^-|-$/, "") # remove leading/trailing
|
39
|
-
end
|
40
|
-
|
41
5
|
def presence(value)
|
42
6
|
value.nil? || value.empty? ? nil : value
|
43
7
|
end
|
44
8
|
|
45
|
-
def ask(question)
|
46
|
-
Kennel.err.printf color(:red, "#{question} - press 'y' to continue: ", force: true)
|
47
|
-
begin
|
48
|
-
STDIN.gets.chomp == "y"
|
49
|
-
rescue Interrupt # do not show a backtrace if user decides to Ctrl+C here
|
50
|
-
Kennel.err.print "\n"
|
51
|
-
exit 1
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
|
-
def color(color, text, force: false)
|
56
|
-
return text unless force || Kennel.out.tty?
|
57
|
-
|
58
|
-
"\e[#{COLORS.fetch(color)}m#{text}\e[0m"
|
59
|
-
end
|
60
|
-
|
61
|
-
def truncate_lines(text, to:, warning:)
|
62
|
-
lines = text.split(/\n/, to + 1)
|
63
|
-
lines[-1] = warning if lines.size > to
|
64
|
-
lines.join("\n")
|
65
|
-
end
|
66
|
-
|
67
|
-
def capture_stdout
|
68
|
-
old = Kennel.out
|
69
|
-
Kennel.out = StringIO.new
|
70
|
-
yield
|
71
|
-
Kennel.out.string
|
72
|
-
ensure
|
73
|
-
Kennel.out = old
|
74
|
-
end
|
75
|
-
|
76
|
-
def capture_stderr
|
77
|
-
old = Kennel.err
|
78
|
-
Kennel.err = StringIO.new
|
79
|
-
yield
|
80
|
-
Kennel.err.string
|
81
|
-
ensure
|
82
|
-
Kennel.err = old
|
83
|
-
end
|
84
|
-
|
85
|
-
def tee_output
|
86
|
-
old_stdout = Kennel.out
|
87
|
-
old_stderr = Kennel.err
|
88
|
-
capture = StringIO.new
|
89
|
-
Kennel.out = TeeIO.new([capture, Kennel.out])
|
90
|
-
Kennel.err = TeeIO.new([capture, Kennel.err])
|
91
|
-
yield
|
92
|
-
capture.string
|
93
|
-
ensure
|
94
|
-
Kennel.out = old_stdout
|
95
|
-
Kennel.err = old_stderr
|
96
|
-
end
|
97
|
-
|
98
9
|
def capture_sh(command)
|
99
10
|
result = `#{command} 2>&1`
|
100
11
|
raise "Command failed:\n#{command}\n#{result}" unless $CHILD_STATUS.success?
|
@@ -150,11 +61,6 @@ module Kennel
|
|
150
61
|
else []
|
151
62
|
end
|
152
63
|
end
|
153
|
-
|
154
|
-
def inline_resource_metadata(resource, klass)
|
155
|
-
resource[:klass] = klass
|
156
|
-
resource[:tracking_id] = klass.parse_tracking_id(resource)
|
157
|
-
end
|
158
64
|
end
|
159
65
|
end
|
160
66
|
end
|
data/lib/kennel/version.rb
CHANGED
data/lib/kennel.rb
CHANGED
@@ -5,6 +5,8 @@ require "zeitwerk"
|
|
5
5
|
require "English"
|
6
6
|
|
7
7
|
require "kennel/version"
|
8
|
+
require "kennel/console"
|
9
|
+
require "kennel/string_utils"
|
8
10
|
require "kennel/utils"
|
9
11
|
require "kennel/progress"
|
10
12
|
require "kennel/filter"
|
@@ -133,8 +135,7 @@ module Kennel
|
|
133
135
|
def definitions(**kwargs)
|
134
136
|
@definitions ||= Progress.progress("Downloading definitions", **kwargs) do
|
135
137
|
Utils.parallel(Models::Record.subclasses) do |klass|
|
136
|
-
|
137
|
-
results.each { |a| Utils.inline_resource_metadata(a, klass) }
|
138
|
+
api.list(klass.api_resource, with_downtimes: false) # lookup monitors without adding unnecessary downtime information
|
138
139
|
end.flatten(1)
|
139
140
|
end
|
140
141
|
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: 1.
|
4
|
+
version: 1.130.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-12-
|
11
|
+
date: 2022-12-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: diff-lcs
|
@@ -90,6 +90,7 @@ files:
|
|
90
90
|
- lib/kennel.rb
|
91
91
|
- lib/kennel/api.rb
|
92
92
|
- lib/kennel/attribute_differ.rb
|
93
|
+
- lib/kennel/console.rb
|
93
94
|
- lib/kennel/file_cache.rb
|
94
95
|
- lib/kennel/filter.rb
|
95
96
|
- lib/kennel/github_reporter.rb
|
@@ -108,6 +109,7 @@ files:
|
|
108
109
|
- lib/kennel/progress.rb
|
109
110
|
- lib/kennel/projects_provider.rb
|
110
111
|
- lib/kennel/settings_as_methods.rb
|
112
|
+
- lib/kennel/string_utils.rb
|
111
113
|
- lib/kennel/subclass_tracking.rb
|
112
114
|
- lib/kennel/syncer.rb
|
113
115
|
- lib/kennel/tasks.rb
|