kennel 1.113.3 → 1.115.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: 1820e573733a40ccb56114ecc6c94f8d7732feb10d556f3bf1107c9d21fab7f0
4
- data.tar.gz: ed5230938e75e643c71b719f6ec4e3e317e9e94d9fb1a2848bbbe881eea56f4e
3
+ metadata.gz: 76e2802df7ab2a6583e3529643deb08c382367dea7f90a7253314959d29a5bec
4
+ data.tar.gz: 4249c23ca2892cc48ce72dbd9e24fc03f38883d6eaed9b509ef75c78cb31afeb
5
5
  SHA512:
6
- metadata.gz: beb8e6d2a60fd3c8ebe26cdd14ca70d89b9a107ee0a831cea52601464b7c13afe058f25eaee76add474e728f404d4c56216eea24e5ce4c5a5b58897da1e43af0
7
- data.tar.gz: 8000438dd34c1e22334283f2e3892379cc08fadeb6085d74ecd41a3b32fdc0aacb28b9a2019d6bdad7a48bcea94084200f69d8c814054fe928aedf16b06b7ea2
6
+ metadata.gz: 8bd1740361932ba4e6dfe4d7aff4ad7cbcdc96796020428902fc6551b9768c6ccc434a279c214a638aa119e012267fd8dfe00e9107052c570789a1e563075505
7
+ data.tar.gz: 266aacb034b8933640c3e95a0319afd5fdc923c857d85a5b039e4e14a2bb47dc1096e8849a1d3060171fed2984d847934465ed845a1e45d27caa465c5ca9fcf4
data/Readme.md CHANGED
@@ -72,6 +72,95 @@ end
72
72
  - `parts/` monitors/dashboards/etc that are used by multiple projects
73
73
  - `generated/` projects as json, to show current state and proposed changes in PRs
74
74
 
75
+ ## About the models
76
+
77
+ Kennel provides several classes which act as models for different purposes:
78
+
79
+ * `Kennel::Models::Dashboard`, `Kennel::Models::Monitor`, `Kennel::Models::Slo`, `Kennel::Models::SyntheticTest`;
80
+ these models represent the various Datadog objects
81
+ * `Kennel::Models::Project`; a container for a collection of Datadog objects
82
+ * `Kennel::Models::Team`; provides defaults and values (e.g. tags, mentions) for the other models.
83
+
84
+ After loading all the `*.rb` files under `projects/`, Kennel's starting point
85
+ is to find all the subclasses of `Kennel::Models::Project`, and for each one,
86
+ create an instance of that subclass (via `.new`) and then call `#parts` on that
87
+ instance. `parts` should return a collection of the Datadog-objects (Dashboard / Monitor / etc).
88
+
89
+ ### Model Settings
90
+
91
+ Each of the models defines various settings; for example, a Monitor has `name`, `message`,
92
+ `type`, `query`, `tags`, and many more.
93
+
94
+ When defining a subclass of a model, one can use `defaults` to provide default values for
95
+ those settings:
96
+
97
+ ```Ruby
98
+ class MyMonitor < Kennel::Models::Monitor
99
+ defaults(
100
+ name: "Error rate",
101
+ type: "query alert",
102
+ critical: 5.0,
103
+ query: -> {
104
+ "some datadog metric expression > #{critical}"
105
+ },
106
+ # ...
107
+ )
108
+ end
109
+ ```
110
+
111
+ This is equivalent to defining instance methods of those names, which return those values:
112
+
113
+ ```Ruby
114
+ class MyMonitor < Kennel::Models::Monitor
115
+ def name
116
+ "Error rate"
117
+ end
118
+
119
+ def type
120
+ "query alert"
121
+ end
122
+
123
+ def critical
124
+ 5.0
125
+ end
126
+
127
+ def query
128
+ "some datadog metric expression > #{critical}"
129
+ end
130
+ end
131
+ ```
132
+
133
+ except that `defaults` will complain if you try to use a setting name which doesn't
134
+ exist. Note also that you can use either plain values (`critical: 5.0`), or procs
135
+ (`query: -> { ... }`). Using a plain value is equivalent to using a proc which returns
136
+ that same value; use whichever suits you best.
137
+
138
+ When you _instantiate_ a model class, you can pass settings in the constructor, after
139
+ the project:
140
+
141
+ ```Ruby
142
+ project = Kennel::Models::Project.new
143
+ my_monitor = MyMonitor.new(
144
+ project,
145
+ critical: 10.0,
146
+ message: -> {
147
+ <<~MESSAGE
148
+ Something bad is happening and you should be worried.
149
+
150
+ #{super()}
151
+ MESSAGE
152
+ },
153
+ )
154
+ ```
155
+
156
+ This works just like `defaults` (it checks the setting names, and it accepts
157
+ either plain values or procs), but it applies just to this instance of the class,
158
+ rather than to the class as a whole (i.e. it defines singleton methods, rather
159
+ than instance methods).
160
+
161
+ Most of the examples in this Readme use the proc syntax (`critical: -> { 5.0 }`) but
162
+ for simple constants you may prefer to use the plain syntax (`critical: 5.0`).
163
+
75
164
  ## Workflows
76
165
  <!-- ONLY IN template/Readme.md
77
166
 
@@ -226,6 +315,8 @@ module ProjectA
226
315
  ...
227
316
  ```
228
317
 
318
+ On the command line, use the projects `kennel_id` (and if none is set then snake_case of the class name) to refer to the project. For example here`PROJECT=project_a` but if it were `Foo::ProjectA` then `foo_project_a`.
319
+
229
320
  ### Skipping validations
230
321
  Some validations might be too strict for your usecase or just wrong, please [open an issue](https://github.com/grosser/kennel/issues) and
231
322
  to unblock use the `validate: -> { false }` option.
@@ -246,7 +337,7 @@ so they can be created in a single update and can be re-created if any of them i
246
337
 
247
338
  ### Debugging changes locally
248
339
  - rebase on updated `master` to not undo other changes
249
- - figure out project name by converting the class name to snake-case
340
+ - figure out project name by converting the class name to snake_case
250
341
  - run `PROJECT=foo bundle exec rake kennel:update_datadog` to test changes for a single project (monitors: remove mentions while debugging to avoid alert spam)
251
342
  - use `PROJECT=foo,bar,...` for multiple projects
252
343
 
@@ -11,18 +11,29 @@ module Kennel
11
11
  def self.file_location
12
12
  @file_location ||= begin
13
13
  method_in_file = instance_methods(false).first
14
+ return if method_in_file.nil?
15
+
14
16
  instance_method(method_in_file).source_location.first.sub("#{Bundler.root}/", "")
15
17
  end
16
18
  end
17
19
 
18
20
  def validated_parts
19
21
  all = parts
22
+ unless all.is_a?(Array) && all.all? { |part| part.is_a?(Record) }
23
+ invalid! "#parts must return an array of Records"
24
+ end
25
+
20
26
  validate_parts(all)
21
27
  all
22
28
  end
23
29
 
24
30
  private
25
31
 
32
+ # let users know which project/resource failed when something happens during diffing where the backtrace is hidden
33
+ def invalid!(message)
34
+ raise ValidationError, "#{kennel_id} #{message}"
35
+ end
36
+
26
37
  # hook for users to add custom validations via `prepend`
27
38
  def validate_parts(parts)
28
39
  end
@@ -3,6 +3,20 @@ module Kennel
3
3
  module SettingsAsMethods
4
4
  SETTING_OVERRIDABLE_METHODS = [].freeze
5
5
 
6
+ AS_PROCS = ->(options) do
7
+ # Fragile; depends on the fact that in both locations where AS_PROCS is
8
+ # used, we're 2 frames away from the user code.
9
+ file, line, = caller(2..2).first.split(":", 3)
10
+
11
+ options.transform_values do |v|
12
+ if v.class == Proc
13
+ v
14
+ else
15
+ eval "-> { v }", nil, file, line.to_i
16
+ end
17
+ end
18
+ end
19
+
6
20
  def self.included(base)
7
21
  base.extend ClassMethods
8
22
  base.instance_variable_set(:@settings, [])
@@ -31,7 +45,7 @@ module Kennel
31
45
  end
32
46
 
33
47
  def defaults(options)
34
- options.each do |name, block|
48
+ AS_PROCS.call(options).each do |name, block|
35
49
  validate_setting_exist name
36
50
  define_method name, &block
37
51
  end
@@ -58,12 +72,7 @@ module Kennel
58
72
  raise ArgumentError, "Expected #{self.class.name}.new options to be a Hash, got a #{options.class}"
59
73
  end
60
74
 
61
- options.each do |k, v|
62
- next if v.class == Proc
63
- raise ArgumentError, "Expected #{self.class.name}.new option :#{k} to be Proc, for example `#{k}: -> { 12 }`"
64
- end
65
-
66
- options.each do |name, block|
75
+ AS_PROCS.call(options).each do |name, block|
67
76
  self.class.send :validate_setting_exist, name
68
77
  define_singleton_method name, &block
69
78
  end
@@ -1,4 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
  module Kennel
3
- VERSION = "1.113.3"
3
+ VERSION = "1.115.0"
4
4
  end
data/template/Readme.md CHANGED
@@ -56,6 +56,95 @@ end
56
56
  - `parts/` monitors/dashboards/etc that are used by multiple projects
57
57
  - `generated/` projects as json, to show current state and proposed changes in PRs
58
58
 
59
+ ## About the models
60
+
61
+ Kennel provides several classes which act as models for different purposes:
62
+
63
+ * `Kennel::Models::Dashboard`, `Kennel::Models::Monitor`, `Kennel::Models::Slo`, `Kennel::Models::SyntheticTest`;
64
+ these models represent the various Datadog objects
65
+ * `Kennel::Models::Project`; a container for a collection of Datadog objects
66
+ * `Kennel::Models::Team`; provides defaults and values (e.g. tags, mentions) for the other models.
67
+
68
+ After loading all the `*.rb` files under `projects/`, Kennel's starting point
69
+ is to find all the subclasses of `Kennel::Models::Project`, and for each one,
70
+ create an instance of that subclass (via `.new`) and then call `#parts` on that
71
+ instance. `parts` should return a collection of the Datadog-objects (Dashboard / Monitor / etc).
72
+
73
+ ### Model Settings
74
+
75
+ Each of the models defines various settings; for example, a Monitor has `name`, `message`,
76
+ `type`, `query`, `tags`, and many more.
77
+
78
+ When defining a subclass of a model, one can use `defaults` to provide default values for
79
+ those settings:
80
+
81
+ ```Ruby
82
+ class MyMonitor < Kennel::Models::Monitor
83
+ defaults(
84
+ name: "Error rate",
85
+ type: "query alert",
86
+ critical: 5.0,
87
+ query: -> {
88
+ "some datadog metric expression > #{critical}"
89
+ },
90
+ # ...
91
+ )
92
+ end
93
+ ```
94
+
95
+ This is equivalent to defining instance methods of those names, which return those values:
96
+
97
+ ```Ruby
98
+ class MyMonitor < Kennel::Models::Monitor
99
+ def name
100
+ "Error rate"
101
+ end
102
+
103
+ def type
104
+ "query alert"
105
+ end
106
+
107
+ def critical
108
+ 5.0
109
+ end
110
+
111
+ def query
112
+ "some datadog metric expression > #{critical}"
113
+ end
114
+ end
115
+ ```
116
+
117
+ except that `defaults` will complain if you try to use a setting name which doesn't
118
+ exist. Note also that you can use either plain values (`critical: 5.0`), or procs
119
+ (`query: -> { ... }`). Using a plain value is equivalent to using a proc which returns
120
+ that same value; use whichever suits you best.
121
+
122
+ When you _instantiate_ a model class, you can pass settings in the constructor, after
123
+ the project:
124
+
125
+ ```Ruby
126
+ project = Kennel::Models::Project.new
127
+ my_monitor = MyMonitor.new(
128
+ project,
129
+ critical: 10.0,
130
+ message: -> {
131
+ <<~MESSAGE
132
+ Something bad is happening and you should be worried.
133
+
134
+ #{super()}
135
+ MESSAGE
136
+ },
137
+ )
138
+ ```
139
+
140
+ This works just like `defaults` (it checks the setting names, and it accepts
141
+ either plain values or procs), but it applies just to this instance of the class,
142
+ rather than to the class as a whole (i.e. it defines singleton methods, rather
143
+ than instance methods).
144
+
145
+ Most of the examples in this Readme use the proc syntax (`critical: -> { 5.0 }`) but
146
+ for simple constants you may prefer to use the plain syntax (`critical: 5.0`).
147
+
59
148
  ## Workflows
60
149
 
61
150
  ### Setup
@@ -208,6 +297,8 @@ module ProjectA
208
297
  ...
209
298
  ```
210
299
 
300
+ On the command line, use the projects `kennel_id` (and if none is set then snake_case of the class name) to refer to the project. For example here`PROJECT=project_a` but if it were `Foo::ProjectA` then `foo_project_a`.
301
+
211
302
  ### Skipping validations
212
303
  Some validations might be too strict for your usecase or just wrong, please [open an issue](https://github.com/grosser/kennel/issues) and
213
304
  to unblock use the `validate: -> { false }` option.
@@ -228,7 +319,7 @@ so they can be created in a single update and can be re-created if any of them i
228
319
 
229
320
  ### Debugging changes locally
230
321
  - rebase on updated `master` to not undo other changes
231
- - figure out project name by converting the class name to snake-case
322
+ - figure out project name by converting the class name to snake_case
232
323
  - run `PROJECT=foo bundle exec rake kennel:update_datadog` to test changes for a single project (monitors: remove mentions while debugging to avoid alert spam)
233
324
  - use `PROJECT=foo,bar,...` for multiple projects
234
325
 
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.113.3
4
+ version: 1.115.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-06-27 00:00:00.000000000 Z
11
+ date: 2022-08-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: faraday