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 +4 -4
- data/Readme.md +92 -1
- data/lib/kennel/models/project.rb +11 -0
- data/lib/kennel/settings_as_methods.rb +16 -7
- data/lib/kennel/version.rb +1 -1
- data/template/Readme.md +92 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 76e2802df7ab2a6583e3529643deb08c382367dea7f90a7253314959d29a5bec
|
4
|
+
data.tar.gz: 4249c23ca2892cc48ce72dbd9e24fc03f38883d6eaed9b509ef75c78cb31afeb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
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 |
|
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
|
data/lib/kennel/version.rb
CHANGED
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
|
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.
|
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-
|
11
|
+
date: 2022-08-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: faraday
|