kennel 1.89.1 → 1.91.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/kennel.rb +20 -3
- data/lib/kennel/api.rb +19 -2
- data/lib/kennel/importer.rb +4 -5
- data/lib/kennel/models/synthetic_test.rb +63 -0
- data/lib/kennel/syncer.rb +9 -14
- data/lib/kennel/version.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 78b7b57805cf2c4730b6a1320342240fe03e9cf786f07380210bb558361b7192
|
4
|
+
data.tar.gz: e56d5211430862f20dc92e4d3538be0befdd630a401bf1605de064b6ab9468b8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2631017430f4d33639317f56be0d639d1d60cf33e568f5b0b4f8031a4cc0d981ca2cc793a18864049cdfc7bb3cf9d852a8ca5f90e6a37779faa37a5cafdb3212
|
7
|
+
data.tar.gz: 9fa908dd061892c13b40e5cf1ab1de7d406ec7a99ed6a718c1cadee5ca5ecd17ec72e8c498c3b4bdf977542a51e1871fbb743e2b4296bcc5d0d071be6aba7d3c
|
data/lib/kennel.rb
CHANGED
@@ -23,6 +23,7 @@ require "kennel/models/record"
|
|
23
23
|
require "kennel/models/dashboard"
|
24
24
|
require "kennel/models/monitor"
|
25
25
|
require "kennel/models/slo"
|
26
|
+
require "kennel/models/synthetic_test"
|
26
27
|
|
27
28
|
# settings
|
28
29
|
require "kennel/models/project"
|
@@ -55,7 +56,7 @@ module Kennel
|
|
55
56
|
|
56
57
|
def store(parts)
|
57
58
|
Progress.progress "Storing" do
|
58
|
-
old = Dir["generated
|
59
|
+
old = Dir["generated/#{project_filter || "**"}/*"]
|
59
60
|
used = []
|
60
61
|
|
61
62
|
Utils.parallel(parts, max: 2) do |part|
|
@@ -83,7 +84,7 @@ module Kennel
|
|
83
84
|
end
|
84
85
|
|
85
86
|
def syncer
|
86
|
-
@syncer ||= Syncer.new(api, generated, project:
|
87
|
+
@syncer ||= Syncer.new(api, generated, project: project_filter)
|
87
88
|
end
|
88
89
|
|
89
90
|
def api
|
@@ -94,9 +95,21 @@ module Kennel
|
|
94
95
|
@generated ||= begin
|
95
96
|
Progress.progress "Generating" do
|
96
97
|
load_all
|
98
|
+
known = []
|
97
99
|
parts = Models::Project.recursive_subclasses.flat_map do |project_class|
|
98
|
-
project_class.new
|
100
|
+
project = project_class.new
|
101
|
+
kennel_id = project.kennel_id
|
102
|
+
if project_filter
|
103
|
+
known << kennel_id
|
104
|
+
next [] if kennel_id != project_filter
|
105
|
+
end
|
106
|
+
project.validated_parts
|
99
107
|
end
|
108
|
+
|
109
|
+
if project_filter && parts.empty?
|
110
|
+
raise "#{project_filter} does not match any projects, try any of these:\n#{known.uniq.sort.join("\n")}"
|
111
|
+
end
|
112
|
+
|
100
113
|
parts.group_by(&:tracking_id).each do |tracking_id, same|
|
101
114
|
next if same.size == 1
|
102
115
|
raise <<~ERROR
|
@@ -109,6 +122,10 @@ module Kennel
|
|
109
122
|
end
|
110
123
|
end
|
111
124
|
|
125
|
+
def project_filter
|
126
|
+
ENV["PROJECT"]
|
127
|
+
end
|
128
|
+
|
112
129
|
def load_all
|
113
130
|
["teams", "parts", "projects"].each do |folder|
|
114
131
|
Dir["#{folder}/**/*.rb"].sort.each { |f| require "./#{f}" }
|
data/lib/kennel/api.rb
CHANGED
@@ -14,6 +14,7 @@ module Kennel
|
|
14
14
|
def show(api_resource, id, params = {})
|
15
15
|
response = request :get, "/api/v1/#{api_resource}/#{id}", params: params
|
16
16
|
response = response.fetch(:data) if api_resource == "slo"
|
17
|
+
response[:id] = response.delete(:public_id) if api_resource == "synthetics/tests"
|
17
18
|
response
|
18
19
|
end
|
19
20
|
|
@@ -22,6 +23,14 @@ module Kennel
|
|
22
23
|
response = request :get, "/api/v1/#{api_resource}", params: paginated_params
|
23
24
|
response = response.fetch(:dashboards) if api_resource == "dashboard"
|
24
25
|
response = response.fetch(:data) if api_resource == "slo"
|
26
|
+
if api_resource == "synthetics/tests"
|
27
|
+
response = response.fetch(:tests)
|
28
|
+
response.each { |r| r[:id] = r.delete(:public_id) }
|
29
|
+
end
|
30
|
+
|
31
|
+
# ignore monitor synthetics create and that inherit the kennel_id, we do not directly manage them
|
32
|
+
response.reject! { |m| m[:type] == "synthetics alert" } if api_resource == "monitor"
|
33
|
+
|
25
34
|
response
|
26
35
|
end
|
27
36
|
end
|
@@ -29,18 +38,26 @@ module Kennel
|
|
29
38
|
def create(api_resource, attributes)
|
30
39
|
response = request :post, "/api/v1/#{api_resource}", body: attributes
|
31
40
|
response = response.fetch(:data).first if api_resource == "slo"
|
41
|
+
response[:id] = response.delete(:public_id) if api_resource == "synthetics/tests"
|
32
42
|
response
|
33
43
|
end
|
34
44
|
|
35
45
|
def update(api_resource, id, attributes)
|
36
|
-
request :put, "/api/v1/#{api_resource}/#{id}", body: attributes
|
46
|
+
response = request :put, "/api/v1/#{api_resource}/#{id}", body: attributes
|
47
|
+
response[:id] = response.delete(:public_id) if api_resource == "synthetics/tests"
|
48
|
+
response
|
37
49
|
end
|
38
50
|
|
39
51
|
# - force=true to not dead-lock on dependent monitors+slos
|
40
52
|
# external dependency on kennel managed resources is their problem, we don't block on it
|
41
53
|
# (?force=true did not work, force for dashboard is not documented but does not blow up)
|
42
54
|
def delete(api_resource, id)
|
43
|
-
|
55
|
+
if api_resource == "synthetics/tests"
|
56
|
+
# https://docs.datadoghq.com/api/latest/synthetics/#delete-tests
|
57
|
+
request :post, "/api/v1/#{api_resource}/delete", body: { public_ids: [id] }, ignore_404: true
|
58
|
+
else
|
59
|
+
request :delete, "/api/v1/#{api_resource}/#{id}", params: { force: "true" }, ignore_404: true
|
60
|
+
end
|
44
61
|
end
|
45
62
|
|
46
63
|
def fill_details!(api_resource, list)
|
data/lib/kennel/importer.rb
CHANGED
@@ -15,11 +15,8 @@ module Kennel
|
|
15
15
|
end
|
16
16
|
|
17
17
|
model =
|
18
|
-
|
19
|
-
|
20
|
-
rescue NameError
|
21
|
-
raise ArgumentError, "#{resource} is not supported"
|
22
|
-
end
|
18
|
+
Kennel::Models::Record.subclasses.detect { |c| c.api_resource == resource } ||
|
19
|
+
raise(ArgumentError, "#{resource} is not supported")
|
23
20
|
|
24
21
|
data = @api.show(model.api_resource, id)
|
25
22
|
id = data.fetch(:id) # keep native value
|
@@ -70,6 +67,8 @@ module Kennel
|
|
70
67
|
dry_up_widget_metadata!(widget)
|
71
68
|
(widget.dig(:definition, :markers) || []).each { |m| m[:label]&.delete! " " }
|
72
69
|
end
|
70
|
+
when "synthetics/tests"
|
71
|
+
data[:locations] = :all if data[:locations].sort == Kennel::Models::SyntheticTest::LOCATIONS.sort
|
73
72
|
else
|
74
73
|
# noop
|
75
74
|
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module Kennel
|
3
|
+
module Models
|
4
|
+
class SyntheticTest < Record
|
5
|
+
TRACKING_FIELD = :message
|
6
|
+
DEFAULTS = {
|
7
|
+
}.freeze
|
8
|
+
READONLY_ATTRIBUTES = superclass::READONLY_ATTRIBUTES + [:status, :monitor_id]
|
9
|
+
LOCATIONS = ["aws:ca-central-1", "aws:eu-north-1", "aws:eu-west-1", "aws:eu-west-3", "aws:eu-west-2", "aws:ap-south-1", "aws:us-west-2", "aws:us-west-1", "aws:sa-east-1", "aws:us-east-2", "aws:ap-northeast-1", "aws:ap-northeast-2", "aws:eu-central-1", "aws:ap-southeast-2", "aws:ap-southeast-1"].freeze
|
10
|
+
|
11
|
+
settings :tags, :config, :message, :subtype, :type, :name, :locations, :options
|
12
|
+
|
13
|
+
defaults(
|
14
|
+
id: -> { nil },
|
15
|
+
tags: -> { @project.tags },
|
16
|
+
message: -> { "\n\n#{project.mention}" }
|
17
|
+
)
|
18
|
+
|
19
|
+
def as_json
|
20
|
+
return @as_json if @as_json
|
21
|
+
locations = locations()
|
22
|
+
data = {
|
23
|
+
message: message,
|
24
|
+
tags: tags,
|
25
|
+
config: config,
|
26
|
+
type: type,
|
27
|
+
subtype: subtype,
|
28
|
+
options: options,
|
29
|
+
name: name,
|
30
|
+
locations: locations == :all ? LOCATIONS : locations
|
31
|
+
}
|
32
|
+
|
33
|
+
if v = id
|
34
|
+
data[:id] = v
|
35
|
+
end
|
36
|
+
|
37
|
+
@as_json = data
|
38
|
+
end
|
39
|
+
|
40
|
+
def self.api_resource
|
41
|
+
"synthetics/tests"
|
42
|
+
end
|
43
|
+
|
44
|
+
def self.url(id)
|
45
|
+
Utils.path_to_url "/synthetics/details/#{id}"
|
46
|
+
end
|
47
|
+
|
48
|
+
def self.parse_url(url)
|
49
|
+
url[/\/synthetics\/details\/([a-z\d-]{11,})/, 1] # id format is 1ab-2ab-3ab
|
50
|
+
end
|
51
|
+
|
52
|
+
def self.normalize(expected, actual)
|
53
|
+
super
|
54
|
+
|
55
|
+
# tags come in a semi-random order and order is never updated
|
56
|
+
expected[:tags]&.sort!
|
57
|
+
actual[:tags].sort!
|
58
|
+
|
59
|
+
ignore_default(expected, actual, DEFAULTS)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
data/lib/kennel/syncer.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
module Kennel
|
3
3
|
class Syncer
|
4
|
-
DELETE_ORDER = ["dashboard", "slo", "monitor"].freeze # dashboards references monitors + slos, slos reference monitors
|
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
6
|
|
7
7
|
def initialize(api, expected, project: nil)
|
@@ -24,7 +24,14 @@ module Kennel
|
|
24
24
|
end
|
25
25
|
|
26
26
|
def confirm
|
27
|
-
|
27
|
+
return false if noop?
|
28
|
+
return true if ENV["CI"] || !STDIN.tty?
|
29
|
+
if @delete.any? && @project_filter
|
30
|
+
Kennel.out.puts(
|
31
|
+
Utils.color(:red, "WARNING: deleting resources that had `id: -> { ...` breaks master branch")
|
32
|
+
)
|
33
|
+
end
|
34
|
+
Utils.ask("Execute Plan ?")
|
28
35
|
end
|
29
36
|
|
30
37
|
def update
|
@@ -99,7 +106,6 @@ module Kennel
|
|
99
106
|
actual = Progress.progress("Downloading definitions") { download_definitions }
|
100
107
|
|
101
108
|
Progress.progress "Diffing" do
|
102
|
-
filter_expected_by_project! @expected
|
103
109
|
populate_id_map @expected, actual
|
104
110
|
filter_actual_by_project! actual
|
105
111
|
resolve_linked_tracking_ids! @expected # resolve dependencies to avoid diff
|
@@ -244,16 +250,5 @@ module Kennel
|
|
244
250
|
!tracking_id || tracking_id.start_with?("#{@project_filter}:")
|
245
251
|
end
|
246
252
|
end
|
247
|
-
|
248
|
-
def filter_expected_by_project!(expected)
|
249
|
-
return unless @project_filter
|
250
|
-
original = expected.dup
|
251
|
-
expected.select! { |e| e.project.kennel_id == @project_filter }
|
252
|
-
|
253
|
-
if expected.empty?
|
254
|
-
possible = original.map { |e| e.project.kennel_id }.uniq.sort
|
255
|
-
raise "#{@project_filter} does not match any projects, try any of these:\n#{possible.join("\n")}"
|
256
|
-
end
|
257
|
-
end
|
258
253
|
end
|
259
254
|
end
|
data/lib/kennel/version.rb
CHANGED
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.91.2
|
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-07-
|
11
|
+
date: 2021-07-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: faraday
|
@@ -70,6 +70,7 @@ files:
|
|
70
70
|
- lib/kennel/models/project.rb
|
71
71
|
- lib/kennel/models/record.rb
|
72
72
|
- lib/kennel/models/slo.rb
|
73
|
+
- lib/kennel/models/synthetic_test.rb
|
73
74
|
- lib/kennel/models/team.rb
|
74
75
|
- lib/kennel/optional_validations.rb
|
75
76
|
- lib/kennel/progress.rb
|