kennel 1.113.3 → 1.115.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 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