kennel 1.80.0 → 1.81.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0cc9d71dff0d4c4bf8a29d9c58c1b62efbb739f3ebdc0d63fb7bd1a3e1cfec7c
4
- data.tar.gz: 312fbda2e1577d071ba7cad7a6c5571b6b3913517cc3e5e9b92f7858637f96dc
3
+ metadata.gz: 577e1080c2efe476233752e7199c6179b5b2c9f611479a9d36ce23301077a6dd
4
+ data.tar.gz: d4fa1df4c77bd31c9c067c1f2a762ef304502da58fda08add91f651f683a86f2
5
5
  SHA512:
6
- metadata.gz: 8d07c6d405178e7114c1ebaf67ce3f92a09a411208d20353bf7d07f453093e322b98f2e8e2f501cf902a601fafa1b352b5fa19bff9d54f1d042e87fc7ef81277
7
- data.tar.gz: 9d681c94f1d61bbc60a098ea0b6fe12e3efc5b6e3c771ec49743db8e6edaae1c83a64ae322a9f5759fc677465b199842f0401c8a38973d1bbaa14157f53f94da
6
+ metadata.gz: bf160d7bb083a7ad5d1912cd6de95d783203f1b52c8f119a1ab0c7e09a60ca71d2b526346dff1c78cf8710e0b3cb00a63821583a3a7864097c22fc6c6fc27fd9
7
+ data.tar.gz: 3022a0ae8b3d9b37d625ee58402d886f8d29d03ddc6693f2f7331acd2a08d41a16df1ed7942102780e3e2d47b0f0f2afbbf935076de60f4bf54268ecff435a91
data/Readme.md CHANGED
@@ -212,15 +212,20 @@ removing the `id` will cause kennel to create a new resource in datadog.
212
212
  Some validations might be too strict for your usecase or just wrong, please [open an issue](https://github.com/grosser/kennel/issues) and
213
213
  to unblock use the `validate: -> { false }` option.
214
214
 
215
- ### Linking with kennel_ids
216
-
217
- To link to existing monitors via their kennel_id `projects kennel_id` + `:` + `monitors kennel id`
218
-
219
- - Screens `uptime` widgets can use `monitor: {id: "foo:bar"}`
220
- - Screens `alert_graph` widgets can use `alert_id: "foo:bar"`
221
- - Monitors `composite` can use `query: -> { "%{foo:bar} || %{foo:baz}" }`
222
- - Monitors `slo alert` can use `query: -> { "error_budget(\"%{foo:bar}\").over(\"7d\") > 123.0" }`
223
- - Slos can use `monitor_ids: -> ["foo:bar"]`
215
+ ### Linking resources with kennel_id
216
+
217
+ Link resources with their kennel_id in the format `project kennel_id` + `:` + `resource kennel_id`,
218
+ this should be used to create dependent resources like monitor + slos,
219
+ so they can be created in a single update and can be re-created if any of them is deleted.
220
+
221
+ |Resource|Type|Syntax|
222
+ |---|---|---|
223
+ |Dashboard|uptime|`monitor: {id: "foo:bar"}`|
224
+ |Dashboard|alert_graph|`alert_id: "foo:bar"`|
225
+ |Dashboard|slo|`slo_id: "foo:bar"`|
226
+ |Monitor|composite|`query: -> { "%{foo:bar} && %{foo:baz}" }`|
227
+ |Monitor|slo alert|`query: -> { "error_budget(\"%{foo:bar}\").over(\"7d\") > 123.0" }`|
228
+ |Slo|monitor|`monitor_ids: -> ["foo:bar"]`|
224
229
 
225
230
  ### Debugging changes locally
226
231
 
@@ -140,16 +140,16 @@ module Kennel
140
140
  when "uptime"
141
141
  if ids = definition[:monitor_ids]
142
142
  definition[:monitor_ids] = ids.map do |id|
143
- tracking_id?(id) ? resolve_link(id, :monitor, id_map, **args) : id
143
+ tracking_id?(id) ? (resolve_link(id, :monitor, id_map, **args) || id) : id
144
144
  end
145
145
  end
146
146
  when "alert_graph"
147
147
  if (id = definition[:alert_id]) && tracking_id?(id)
148
- definition[:alert_id] = resolve_link(id, :monitor, id_map, **args).to_s
148
+ definition[:alert_id] = (resolve_link(id, :monitor, id_map, **args) || id).to_s
149
149
  end
150
150
  when "slo"
151
151
  if (id = definition[:slo_id]) && tracking_id?(id)
152
- definition[:slo_id] = resolve_link(id, :slo, id_map, **args).to_s
152
+ definition[:slo_id] = (resolve_link(id, :slo, id_map, **args) || id).to_s
153
153
  end
154
154
  end
155
155
  end
@@ -116,7 +116,7 @@ module Kennel
116
116
  when "composite", "slo alert"
117
117
  type = (as_json[:type] == "composite" ? :monitor : :slo)
118
118
  as_json[:query] = as_json[:query].gsub(/%{(.*?)}/) do
119
- resolve_link($1, type, id_map, **args)
119
+ resolve_link($1, type, id_map, **args) || $&
120
120
  end
121
121
  end
122
122
  end
@@ -65,19 +65,18 @@ module Kennel
65
65
 
66
66
  private
67
67
 
68
- def resolve_link(id, type, id_map, force:)
69
- value = id_map[id]
70
- if value == :new
68
+ def resolve_link(tracking_id, type, id_map, force:)
69
+ id = id_map[tracking_id]
70
+ if id == :new
71
71
  if force
72
- # TODO: remove the need for this by sorting monitors by missing resolutions
73
- invalid! "#{id} needs to already exist, try again"
72
+ invalid! "#{type} #{tracking_id} was referenced but is also created by the current run.\nIt could not be created because of a circular dependency, try creating only some of the resources"
74
73
  else
75
- id # will be re-resolved by syncer after the linked object was created
74
+ nil # will be re-resolved after the linked object was created
76
75
  end
77
- elsif value
78
- value
76
+ elsif id
77
+ id
79
78
  else
80
- invalid! "Unable to find #{type} #{id} (does not exist and is not being created by the current run)"
79
+ invalid! "Unable to find #{type} #{tracking_id} (does not exist and is not being created by the current run)"
81
80
  end
82
81
  end
83
82
 
@@ -69,7 +69,7 @@ module Kennel
69
69
  def resolve_linked_tracking_ids!(id_map, **args)
70
70
  return unless as_json[:monitor_ids] # ignore_default can remove it
71
71
  as_json[:monitor_ids] = as_json[:monitor_ids].map do |id|
72
- id.is_a?(String) ? resolve_link(id, :monitor, id_map, **args) : id
72
+ id.is_a?(String) ? (resolve_link(id, :monitor, id_map, **args) || id) : id
73
73
  end
74
74
  end
75
75
 
@@ -38,23 +38,14 @@ module Kennel
38
38
  end
39
39
 
40
40
  def update
41
- changed = (@create + @update).map { |_, e| e }
42
-
43
- @create.each do |_, e|
44
- e.resolve_linked_tracking_ids!({}, force: true)
45
-
41
+ each_resolved @create do |_, e|
46
42
  reply = @api.create e.class.api_resource, e.as_json
47
43
  id = reply.fetch(:id)
48
-
49
- # resolve ids we could previously no resolve
50
- changed.delete e
51
- resolve_linked_tracking_ids! from: [reply], to: changed
52
-
44
+ populate_id_map [reply] # allow resolving ids we could previously no resolve
53
45
  Kennel.out.puts "Created #{e.class.api_resource} #{tracking_id(e.as_json)} #{e.url(id)}"
54
46
  end
55
47
 
56
- @update.each do |id, e|
57
- e.resolve_linked_tracking_ids!({}, force: true)
48
+ each_resolved @update do |id, e|
58
49
  @api.update e.class.api_resource, id, e.as_json
59
50
  Kennel.out.puts "Updated #{e.class.api_resource} #{tracking_id(e.as_json)} #{e.url(id)}"
60
51
  end
@@ -67,6 +58,37 @@ module Kennel
67
58
 
68
59
  private
69
60
 
61
+ # loop over items until everything is resolved or crash when we get stuck
62
+ # this solves cases like composite monitors depending on each other or monitor->monitor slo->slo monitor chains
63
+ def each_resolved(list)
64
+ list = list.dup
65
+ loop do
66
+ return if list.empty?
67
+ list.reject! do |id, e|
68
+ if resolved?(e)
69
+ yield id, e
70
+ true
71
+ else
72
+ false
73
+ end
74
+ end ||
75
+ assert_resolved(list[0][1]) # resolve something or show a circular dependency error
76
+ end
77
+ end
78
+
79
+ # TODO: optimize by storing an instance variable if already resolved
80
+ def resolved?(e)
81
+ assert_resolved e
82
+ true
83
+ rescue ValidationError
84
+ false
85
+ end
86
+
87
+ # raises ValidationError when not resolved
88
+ def assert_resolved(e)
89
+ resolve_linked_tracking_ids! [e], force: true
90
+ end
91
+
70
92
  def noop?
71
93
  @create.empty? && @update.empty? && @delete.empty?
72
94
  end
@@ -74,9 +96,15 @@ module Kennel
74
96
  def calculate_diff
75
97
  @update = []
76
98
  @delete = []
99
+ @id_map = {}
77
100
 
78
101
  actual = Progress.progress("Downloading definitions") { download_definitions }
79
- resolve_linked_tracking_ids! from: actual, to: @expected
102
+
103
+ # resolve dependencies to avoid diff
104
+ populate_id_map actual
105
+ @expected.each { |e| @id_map[e.tracking_id] ||= :new }
106
+ resolve_linked_tracking_ids! @expected
107
+
80
108
  filter_by_project! actual
81
109
 
82
110
  Progress.progress "Diffing" do
@@ -107,7 +135,6 @@ module Kennel
107
135
 
108
136
  ensure_all_ids_found
109
137
  @create = @expected.map { |e| [nil, e] }
110
- @create.sort_by! { |_, e| -DELETE_ORDER.index(e.class.api_resource) }
111
138
  end
112
139
 
113
140
  @delete.sort_by! { |_, _, a| DELETE_ORDER.index a.fetch(:api_resource) }
@@ -214,10 +241,12 @@ module Kennel
214
241
  end
215
242
  end
216
243
 
217
- def resolve_linked_tracking_ids!(from:, to:)
218
- map = from.each_with_object({}) { |a, lookup| lookup[tracking_id(a)] = a.fetch(:id) }
219
- to.each { |e| map[e.tracking_id] ||= :new }
220
- to.each { |e| e.resolve_linked_tracking_ids!(map, force: false) }
244
+ def populate_id_map(actual)
245
+ actual.each { |a| @id_map[tracking_id(a)] = a.fetch(:id) }
246
+ end
247
+
248
+ def resolve_linked_tracking_ids!(list, force: false)
249
+ list.each { |e| e.resolve_linked_tracking_ids!(@id_map, force: force) }
221
250
  end
222
251
 
223
252
  def filter_by_project!(definitions)
@@ -1,4 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
  module Kennel
3
- VERSION = "1.80.0"
3
+ VERSION = "1.81.0"
4
4
  end
@@ -196,13 +196,17 @@ to unblock use the `validate: -> { false }` option.
196
196
 
197
197
  ### Linking with kennel_ids
198
198
 
199
- To link to existing monitors via their kennel_id `projects kennel_id` + `:` + `monitors kennel id`
200
-
201
- - Screens `uptime` widgets can use `monitor: {id: "foo:bar"}`
202
- - Screens `alert_graph` widgets can use `alert_id: "foo:bar"`
203
- - Monitors `composite` can use `query: -> { "%{foo:bar} || %{foo:baz}" }`
204
- - Monitors `slo alert` can use `query: -> { "error_budget(\"%{foo:bar}\").over(\"7d\") > 123.0" }`
205
- - Slos can use `monitor_ids: -> ["foo:bar"]`
199
+ Link resources via their kennel_id `projects kennel_id` + `:` + `monitors kennel id`,
200
+ this should be used to create dependent resources like monitor + slos.
201
+
202
+ |Resource|Type|Syntax|
203
+ |---|---|---|
204
+ |Dashboard|uptime|`monitor: {id: "foo:bar"}`|
205
+ |Dashboard|alert_graph|`alert_id: "foo:bar"`|
206
+ |Dashboard|slo|`slo_id: "foo:bar"`|
207
+ |Monitor|composite|`query: -> { "%{foo:bar} && %{foo:baz}" }`|
208
+ |Monitor|slo alert|`query: -> { "error_budget(\"%{foo:bar}\").over(\"7d\") > 123.0" }`|
209
+ |Slo|monitor|`monitor_ids: -> ["foo:bar"]`|
206
210
 
207
211
  ### Debugging changes locally
208
212
 
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.80.0
4
+ version: 1.81.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: 2021-01-07 00:00:00.000000000 Z
11
+ date: 2021-01-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: faraday