kennel 1.58.0 → 1.59.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: ffd28c1dcb7db623d9e93d2238e143e78c928f76573d97781c1bdcd058c0ab1c
4
- data.tar.gz: 6948f95652b107a8ccf3f58585cd2e3c4e908554a8c99ecade86ad6233eb8d14
3
+ metadata.gz: c20add02263916021ed0498253e11e79193b5bf603651c28cbacbf614b02287c
4
+ data.tar.gz: ec8ff5e6fa15c10b2f3113feb7f3459f48b9520259952ab91786f56001192f53
5
5
  SHA512:
6
- metadata.gz: 3c5bbfb1b9bc9a9c32e9200b3572f01bb201aade69081dc651dbb499d35816d157593a41aa057669f0dc2fd6f9e2cd4d99235b88a7c7e09b70f032a5c2e0ae80
7
- data.tar.gz: fdbfa3f3f8b9c654e60e072909bcb1f6d30580142a03a5365220f781b062e821f6d8313538b2aefc87ed64974f239df0f0c9b4a7798ca5ad4560d5aa3656c907
6
+ metadata.gz: b69a0f24eeca1fb532c4b46f18f398e5df1630ae5f8da96b3ea7a263e68e3a211b31e4762f979ff022290ec5fc54a011ba3177a3ee9156ee4ee20541385b48e8
7
+ data.tar.gz: 30e5d810b9351afb83ec40f29c17d9828bd85d41ecea39c3e273011f3ed32ffa2c1729d495aeaad1668bb958e4b407f696916dd57eb3992da08588cf4bf8576e
data/Readme.md CHANGED
@@ -45,6 +45,7 @@ Keep datadog monitors/dashboards/etc in version control, avoid chaotic managemen
45
45
  - copy any `API Key` and add it to `.env` as `DATADOG_API_KEY`
46
46
  - find or create (check last page) your personal "Application Key" and add it to `.env` as `DATADOG_APP_KEY=`
47
47
  - change the `DATADOG_SUBDOMAIN=app` in `.env` to your companies subdomain if you have one
48
+ - verify it works by running `rake plan`, it might show some diff, but should not crash
48
49
  -->
49
50
 
50
51
  ### Adding a team
@@ -29,6 +29,10 @@ require "kennel/models/project"
29
29
  require "kennel/models/team"
30
30
 
31
31
  module Kennel
32
+ MISSING_ID = 1
33
+ class ValidationError < RuntimeError
34
+ end
35
+
32
36
  @out = $stdout
33
37
  @err = $stderr
34
38
 
@@ -68,7 +72,7 @@ module Kennel
68
72
  Progress.progress "Generating" do
69
73
  load_all
70
74
  parts = Models::Project.recursive_subclasses.flat_map do |project_class|
71
- project_class.new.parts
75
+ project_class.new.validated_parts
72
76
  end
73
77
  parts.map(&:tracking_id).group_by { |id| id }.select do |id, same|
74
78
  raise "#{id} is defined #{same.size} times" if same.size != 1
@@ -13,7 +13,22 @@ module Kennel
13
13
  end
14
14
 
15
15
  def list(api_resource, params = {})
16
- request :get, "/api/v1/#{api_resource}", params: params
16
+ if api_resource == "slo"
17
+ raise ArgumentError if params[:limit] || params[:offset]
18
+ limit = 1000
19
+ offset = 0
20
+ all = []
21
+
22
+ loop do
23
+ result = request :get, "/api/v1/#{api_resource}", params: params.merge(limit: limit, offset: offset)
24
+ data = result.fetch(:data)
25
+ all.concat data
26
+ break all if data.size < limit
27
+ offset += limit
28
+ end
29
+ else
30
+ request :get, "/api/v1/#{api_resource}", params: params
31
+ end
17
32
  end
18
33
 
19
34
  def create(api_resource, attributes)
@@ -101,16 +101,16 @@ module Kennel
101
101
  when "uptime"
102
102
  if ids = definition[:monitor_ids]
103
103
  definition[:monitor_ids] = ids.map do |id|
104
- tracking_id?(id) ? resolve_link(id, id_map, force: false) : id
104
+ tracking_id?(id) ? resolve_link(id, id_map) : id
105
105
  end
106
106
  end
107
107
  when "alert_graph"
108
108
  if (id = definition[:alert_id]) && tracking_id?(id)
109
- definition[:alert_id] = resolve_link(id, id_map, force: false).to_s
109
+ definition[:alert_id] = resolve_link(id, id_map).to_s
110
110
  end
111
111
  when "slo"
112
112
  if (id = definition[:slo_id]) && tracking_id?(id)
113
- definition[:slo_id] = resolve_link(id, id_map, force: false).to_s
113
+ definition[:slo_id] = resolve_link(id, id_map).to_s
114
114
  end
115
115
  end
116
116
  end
@@ -105,6 +105,7 @@ module Kennel
105
105
  def resolve_linked_tracking_ids(id_map)
106
106
  if as_json[:type] == "composite"
107
107
  as_json[:query] = as_json[:query].gsub(/%\{(.*?)\}/) do
108
+ # need force here since it validates the id exists
108
109
  resolve_link($1, id_map, force: true)
109
110
  end
110
111
  end
@@ -14,6 +14,18 @@ module Kennel
14
14
  instance_method(method_in_file).source_location.first.sub("#{Bundler.root}/", "")
15
15
  end
16
16
  end
17
+
18
+ def validated_parts
19
+ all = parts
20
+ validate_parts(all)
21
+ all
22
+ end
23
+
24
+ private
25
+
26
+ # hook for users to add custom validations via `prepend`
27
+ def validate_parts(parts)
28
+ end
17
29
  end
18
30
  end
19
31
  end
@@ -13,9 +13,6 @@ module Kennel
13
13
  }.freeze
14
14
  API_LIST_INCOMPLETE = false
15
15
 
16
- class ValidationError < RuntimeError
17
- end
18
-
19
16
  settings :id, :kennel_id
20
17
 
21
18
  class << self
@@ -81,10 +78,19 @@ module Kennel
81
78
 
82
79
  private
83
80
 
84
- def resolve_link(id, id_map, force:)
85
- id_map[id] || begin
86
- message = "Unable to find #{id} in existing monitors (they need to be created first to link them)"
87
- force ? invalid!(message) : Kennel.err.puts(message)
81
+ def resolve_link(id, id_map, force: false)
82
+ found = id_map[id]
83
+ return found if found && found != :new
84
+
85
+ if found == :new
86
+ if force
87
+ invalid! "Monitor #{id} will be created in the current run and can only be used after that"
88
+ else
89
+ Kennel.err.puts "Monitor #{id} will be created in the current run, the next run will link it properly"
90
+ Kennel::MISSING_ID
91
+ end
92
+ else
93
+ invalid! "Unable to find monitor #{id} (does not exist and is not being created by the current run)"
88
94
  end
89
95
  end
90
96
 
@@ -55,7 +55,7 @@ module Kennel
55
55
 
56
56
  def resolve_linked_tracking_ids(id_map)
57
57
  as_json[:monitor_ids] = as_json[:monitor_ids].map do |id|
58
- id.is_a?(String) ? resolve_link(id, id_map, force: false) || 1 : id
58
+ id.is_a?(String) ? resolve_link(id, id_map) : id
59
59
  end
60
60
  end
61
61
 
@@ -195,6 +195,7 @@ module Kennel
195
195
 
196
196
  def resolve_linked_tracking_ids(actual)
197
197
  map = actual.each_with_object({}) { |a, lookup| lookup[tracking_id(a)] = a.fetch(:id) }
198
+ @expected.each { |e| map[e.tracking_id] ||= :new }
198
199
  @expected.each { |e| e.resolve_linked_tracking_ids(map) }
199
200
  end
200
201
 
@@ -4,12 +4,23 @@ require "kennel"
4
4
  require "kennel/unmuted_alerts"
5
5
  require "kennel/importer"
6
6
 
7
+ module Kennel
8
+ module Tasks
9
+ class << self
10
+ def abort(message = nil)
11
+ Kennel.err.puts message if message
12
+ raise SystemExit.new(1), message
13
+ end
14
+ end
15
+ end
16
+ end
17
+
7
18
  namespace :kennel do
8
19
  desc "Ensure there are no uncommited changes that would be hidden from PR reviewers"
9
20
  task no_diff: :generate do
10
21
  result = `git status --porcelain`.strip
11
- abort "Diff found:\n#{result}\nrun `rake generate` and commit the diff to fix" unless result == ""
12
- abort "Error during diffing" unless $CHILD_STATUS.success?
22
+ Kennel::Tasks.abort "Diff found:\n#{result}\nrun `rake generate` and commit the diff to fix" unless result == ""
23
+ Kennel::Tasks.abort "Error during diffing" unless $CHILD_STATUS.success?
13
24
  end
14
25
 
15
26
  # ideally do this on every run, but it's slow (~1.5s) and brittle (might not find all + might find false-positives)
@@ -38,7 +49,7 @@ namespace :kennel do
38
49
  url = (subdomain ? "https://zendesk.datadoghq.com" : "") + "/account/settings"
39
50
  puts "Invalid mentions found, either ignore them by adding to `KNOWN` env var or add them via #{url}"
40
51
  bad.each { |f, v| puts "Invalid mention #{v} in monitor message of #{f}" }
41
- abort
52
+ Kennel::Tasks.abort
42
53
  end
43
54
  end
44
55
 
@@ -76,16 +87,16 @@ namespace :kennel do
76
87
 
77
88
  desc "show unmuted alerts filtered by TAG, for example TAG=team:foo"
78
89
  task alerts: :environment do
79
- tag = ENV["TAG"] || abort("Call with TAG=foo:bar")
90
+ tag = ENV["TAG"] || Kennel::Tasks.abort("Call with TAG=foo:bar")
80
91
  Kennel::UnmutedAlerts.print(Kennel.send(:api), tag)
81
92
  end
82
93
 
83
94
  desc "show monitors with no data by TAG, for example TAG=team:foo"
84
95
  task nodata: :environment do
85
- tag = ENV["TAG"] || abort("Call with TAG=foo:bar")
96
+ tag = ENV["TAG"] || Kennel::Tasks.abort("Call with TAG=foo:bar")
86
97
  monitors = Kennel.send(:api).list("monitor", monitor_tags: tag, group_states: "no data")
87
98
  monitors.select! { |m| m[:overall_state] == "No Data" }
88
- monitors.reject! { |m| m[:tags].include? ["nodata:ignore"] }
99
+ monitors.reject! { |m| m[:tags].include? "nodata:ignore" }
89
100
  if monitors.any?
90
101
  Kennel.err.puts <<~TEXT
91
102
  This is a useful task to find monitors that have mis-spelled metrics or never received data at any time.
@@ -103,8 +114,8 @@ namespace :kennel do
103
114
 
104
115
  desc "Convert existing resources to copy-pastable definitions to import existing resources RESOURCE=dash ID=1234"
105
116
  task import: :environment do
106
- resource = ENV["RESOURCE"] || abort("Call with RESOURCE=dash") # TODO: add others
107
- id = ENV["ID"] || abort("Call with ID=1234")
117
+ resource = ENV["RESOURCE"] || Kennel::Tasks.abort("Call with RESOURCE=dash") # TODO: add others
118
+ id = ENV["ID"] || Kennel::Tasks.abort("Call with ID=1234")
108
119
  id = Integer(id) if id =~ /^\d+$/ # dashboards can have alphanumeric ids
109
120
  puts Kennel::Importer.new(Kennel.send(:api)).import(resource, id)
110
121
  end
@@ -1,4 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
  module Kennel
3
- VERSION = "1.58.0"
3
+ VERSION = "1.59.0"
4
4
  end
@@ -28,6 +28,7 @@ Keep datadog monitors/dashboards/etc in version control, avoid chaotic managemen
28
28
  - copy any `API Key` and add it to `.env` as `DATADOG_API_KEY`
29
29
  - find or create (check last page) your personal "Application Key" and add it to `.env` as `DATADOG_APP_KEY=`
30
30
  - change the `DATADOG_SUBDOMAIN=app` in `.env` to your companies subdomain if you have one
31
+ - verify it works by running `rake plan`, it might show some diff, but should not crash
31
32
 
32
33
  ### Adding a team
33
34
 
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.58.0
4
+ version: 1.59.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: 2019-11-21 00:00:00.000000000 Z
11
+ date: 2019-12-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: faraday