sensu-settings 0.0.1
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 +7 -0
- data/.gitignore +22 -0
- data/.travis.yml +14 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +20 -0
- data/README.md +28 -0
- data/Rakefile +6 -0
- data/lib/sensu/settings.rb +15 -0
- data/lib/sensu/settings/constants.rb +5 -0
- data/lib/sensu/settings/loader.rb +255 -0
- data/lib/sensu/settings/rules.rb +154 -0
- data/lib/sensu/settings/validator.rb +76 -0
- data/lib/sensu/settings/validators.rb +23 -0
- data/lib/sensu/settings/validators/api.rb +36 -0
- data/lib/sensu/settings/validators/check.rb +78 -0
- data/lib/sensu/settings/validators/client.rb +113 -0
- data/lib/sensu/settings/validators/filter.rb +18 -0
- data/lib/sensu/settings/validators/handler.rb +133 -0
- data/lib/sensu/settings/validators/mutator.rb +18 -0
- data/lib/sensu/settings/validators/subdue.rb +68 -0
- data/lib/sensu/settings/validators/transport.rb +20 -0
- data/sensu-settings.gemspec +24 -0
- data/spec/assets/conf.d/merger.json +11 -0
- data/spec/assets/conf.d/nested/file.json +11 -0
- data/spec/assets/config.json +126 -0
- data/spec/assets/invalid.json +2 -0
- data/spec/helpers.rb +8 -0
- data/spec/loader_spec.rb +171 -0
- data/spec/rules_spec.rb +65 -0
- data/spec/settings_spec.rb +13 -0
- data/spec/validator_spec.rb +619 -0
- metadata +153 -0
@@ -0,0 +1,76 @@
|
|
1
|
+
require "sensu/settings/rules"
|
2
|
+
require "sensu/settings/validators"
|
3
|
+
require "sensu/settings/constants"
|
4
|
+
|
5
|
+
module Sensu
|
6
|
+
module Settings
|
7
|
+
class Validator
|
8
|
+
include Rules
|
9
|
+
include Validators
|
10
|
+
|
11
|
+
# @!attribute [r] failures
|
12
|
+
# @return [Array] validation failures.
|
13
|
+
attr_reader :failures
|
14
|
+
|
15
|
+
def initialize
|
16
|
+
@failures = []
|
17
|
+
end
|
18
|
+
|
19
|
+
# Run the validator.
|
20
|
+
#
|
21
|
+
# @param settings [Hash] sensu settings to validate.
|
22
|
+
# @param service [String] sensu service to validate for.
|
23
|
+
# @return [Array] validation failures.
|
24
|
+
def run(settings, service=nil)
|
25
|
+
validate_categories(settings)
|
26
|
+
validate_transport(settings[:transport])
|
27
|
+
case service
|
28
|
+
when "client"
|
29
|
+
validate_client(settings[:client])
|
30
|
+
when "api"
|
31
|
+
validate_api(settings[:api])
|
32
|
+
end
|
33
|
+
@failures
|
34
|
+
end
|
35
|
+
|
36
|
+
def reset!
|
37
|
+
failure_count = @failures.size
|
38
|
+
@failures = []
|
39
|
+
failure_count
|
40
|
+
end
|
41
|
+
alias_method :reset, :reset!
|
42
|
+
|
43
|
+
private
|
44
|
+
|
45
|
+
# Validate setting categories: checks, filters, mutators, and
|
46
|
+
# handlers.
|
47
|
+
#
|
48
|
+
# @param settings [Hash] sensu settings to validate.
|
49
|
+
def validate_categories(settings)
|
50
|
+
CATEGORIES.each do |category|
|
51
|
+
if is_a_hash?(settings[category])
|
52
|
+
validate_method = ("validate_" + category.to_s.chop).to_sym
|
53
|
+
settings[category].each do |name, details|
|
54
|
+
send(validate_method, details.merge(:name => name.to_s))
|
55
|
+
end
|
56
|
+
else
|
57
|
+
invalid(settings[category], "#{category} must be a hash")
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
# Record an invalid object with a message.
|
63
|
+
#
|
64
|
+
# @param object [Object] invalid object.
|
65
|
+
# @param message [String] message explaining why the object is
|
66
|
+
# invalid.
|
67
|
+
# @return [Array] current validation failures.
|
68
|
+
def invalid(object, message)
|
69
|
+
@failures << {
|
70
|
+
:object => object,
|
71
|
+
:message => message
|
72
|
+
}
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require "sensu/settings/validators/subdue"
|
2
|
+
require "sensu/settings/validators/check"
|
3
|
+
require "sensu/settings/validators/filter"
|
4
|
+
require "sensu/settings/validators/mutator"
|
5
|
+
require "sensu/settings/validators/handler"
|
6
|
+
require "sensu/settings/validators/client"
|
7
|
+
require "sensu/settings/validators/api"
|
8
|
+
require "sensu/settings/validators/transport"
|
9
|
+
|
10
|
+
module Sensu
|
11
|
+
module Settings
|
12
|
+
module Validators
|
13
|
+
include Subdue
|
14
|
+
include Check
|
15
|
+
include Filter
|
16
|
+
include Mutator
|
17
|
+
include Handler
|
18
|
+
include Client
|
19
|
+
include API
|
20
|
+
include Transport
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module Sensu
|
2
|
+
module Settings
|
3
|
+
module Validators
|
4
|
+
module API
|
5
|
+
# Validate API authentication.
|
6
|
+
# Validates: user, password
|
7
|
+
#
|
8
|
+
# @param api [Hash] sensu api definition.
|
9
|
+
def validate_api_authentication(api)
|
10
|
+
if either_are_set?(api[:user], api[:password])
|
11
|
+
must_be_a_string(api[:user]) ||
|
12
|
+
invalid(api, "api user must be a string")
|
13
|
+
must_be_a_string(api[:password]) ||
|
14
|
+
invalid(api, "api password must be a string")
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
# Validate a Sensu API definition.
|
19
|
+
# Validates: port, bind
|
20
|
+
#
|
21
|
+
# @param api [Hash] sensu api definition.
|
22
|
+
def validate_api(api)
|
23
|
+
if is_a_hash?(api)
|
24
|
+
must_be_an_integer(api[:port]) ||
|
25
|
+
invalid(api, "api port must be an integer")
|
26
|
+
must_be_a_string_if_set(api[:bind]) ||
|
27
|
+
invalid(api, "api bind must be a string")
|
28
|
+
validate_api_authentication(api)
|
29
|
+
else
|
30
|
+
invalid(api, "api must be a hash")
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
module Sensu
|
2
|
+
module Settings
|
3
|
+
module Validators
|
4
|
+
module Check
|
5
|
+
# Validate check scheduling.
|
6
|
+
# Validates: interval, standalone, subscribers
|
7
|
+
#
|
8
|
+
# @param check [Hash] sensu check definition.
|
9
|
+
def validate_check_scheduling(check)
|
10
|
+
must_be_boolean_if_set(check[:publish]) ||
|
11
|
+
invalid(check, "check publish must be boolean")
|
12
|
+
unless check[:publish] == false
|
13
|
+
(must_be_an_integer(check[:interval]) && check[:interval] > 0) ||
|
14
|
+
invalid(check, "check interval must be an integer")
|
15
|
+
end
|
16
|
+
must_be_boolean_if_set(check[:standalone]) ||
|
17
|
+
invalid(check, "check standalone must be boolean")
|
18
|
+
unless check[:standalone]
|
19
|
+
if is_an_array?(check[:subscribers])
|
20
|
+
items_must_be_strings(check[:subscribers]) ||
|
21
|
+
invalid(check, "check subscribers must each be a string")
|
22
|
+
else
|
23
|
+
invalid(check, "check subscribers must be an array")
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
# Validate check handling.
|
29
|
+
# Validates: handler, handlers
|
30
|
+
#
|
31
|
+
# @param check [Hash] sensu check definition.
|
32
|
+
def validate_check_handling(check)
|
33
|
+
must_be_a_string_if_set(check[:handler]) ||
|
34
|
+
invalid(check, "check handler must be a string")
|
35
|
+
must_be_an_array_if_set(check[:handlers]) ||
|
36
|
+
invalid(check, "check handlers must be an array")
|
37
|
+
if is_an_array?(check[:handlers])
|
38
|
+
items_must_be_strings(check[:handlers]) ||
|
39
|
+
invalid(check, "check handlers must each be a string")
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
# Validate check flap detection.
|
44
|
+
# Validates: low_flap_threshold, high_flap_threshold
|
45
|
+
#
|
46
|
+
# @param check [Hash] sensu check definition.
|
47
|
+
def validate_check_flap_detection(check)
|
48
|
+
if either_are_set?(check[:low_flap_threshold], check[:high_flap_threshold])
|
49
|
+
must_be_an_integer(check[:low_flap_threshold]) ||
|
50
|
+
invalid(check, "check low flap threshold must be an integer")
|
51
|
+
must_be_an_integer(check[:high_flap_threshold]) ||
|
52
|
+
invalid(check, "check high flap threshold must be an integer")
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
# Validate a Sensu check definition.
|
57
|
+
#
|
58
|
+
# @param check [Hash] sensu check definition.
|
59
|
+
def validate_check(check)
|
60
|
+
must_be_a_string(check[:name]) ||
|
61
|
+
invalid(check, "check name must be a string")
|
62
|
+
must_match_regex(/^[\w\.-]+$/, check[:name]) ||
|
63
|
+
invalid(check, "check name cannot contain spaces or special characters")
|
64
|
+
must_be_a_string(check[:command]) ||
|
65
|
+
invalid(check, "check command must be a string")
|
66
|
+
must_be_a_numeric_if_set(check[:timeout]) ||
|
67
|
+
invalid(check, "check timeout must be numeric")
|
68
|
+
validate_check_scheduling(check)
|
69
|
+
validate_check_handling(check)
|
70
|
+
validate_check_flap_detection(check)
|
71
|
+
if check[:subdue]
|
72
|
+
validate_subdue(check)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
@@ -0,0 +1,113 @@
|
|
1
|
+
module Sensu
|
2
|
+
module Settings
|
3
|
+
module Validators
|
4
|
+
module Client
|
5
|
+
# Validate client subscriptions.
|
6
|
+
# Validates: subscriptions
|
7
|
+
#
|
8
|
+
# @param client [Hash] sensu client definition.
|
9
|
+
def validate_client_subscriptions(client)
|
10
|
+
if is_an_array?(client[:subscriptions])
|
11
|
+
items_must_be_strings(client[:subscriptions]) ||
|
12
|
+
invalid(client, "client subscriptions must each be a string")
|
13
|
+
else
|
14
|
+
invalid(client, "client subscriptions must be an array")
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
# Validate client socket.
|
19
|
+
# Validates: socket (bind, port)
|
20
|
+
#
|
21
|
+
# @param client [Hash] sensu client definition.
|
22
|
+
def validate_client_socket(client)
|
23
|
+
must_be_a_hash_if_set(client[:socket]) ||
|
24
|
+
invalid(client, "client socket must be a hash")
|
25
|
+
if is_a_hash?(client[:socket])
|
26
|
+
must_be_a_string_if_set(client[:socket][:bind]) ||
|
27
|
+
invalid(client, "client socket bind must be a string")
|
28
|
+
must_be_an_integer_if_set(client[:socket][:port]) ||
|
29
|
+
invalid(client, "client socket port must be an integer")
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
# Validate client keepalive handlers.
|
34
|
+
# Validates: keepalive (handler, handlers)
|
35
|
+
#
|
36
|
+
# @param client [Hash] sensu client definition.
|
37
|
+
def validate_client_keepalive_handlers(client)
|
38
|
+
must_be_a_string_if_set(client[:keepalive][:handler]) ||
|
39
|
+
invalid(client, "client keepalive handler must be a string")
|
40
|
+
must_be_an_array_if_set(client[:keepalive][:handlers]) ||
|
41
|
+
invalid(client, "client keepalive handlers must be an array")
|
42
|
+
if is_an_array?(client[:keepalive][:handlers])
|
43
|
+
items_must_be_strings(client[:keepalive][:handlers]) ||
|
44
|
+
invalid(client, "client keepalive handlers must each be a string")
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
# Validate client keepalive thresholds.
|
49
|
+
# Validates: keepalive (thresholds)
|
50
|
+
#
|
51
|
+
# @param client [Hash] sensu client definition.
|
52
|
+
def validate_client_keepalive_thresholds(client)
|
53
|
+
thresholds = client[:keepalive][:thresholds]
|
54
|
+
must_be_a_hash_if_set(thresholds) ||
|
55
|
+
invalid(client, "client keepalive thresholds must be a hash")
|
56
|
+
if is_a_hash?(thresholds)
|
57
|
+
must_be_an_integer_if_set(thresholds[:warning]) ||
|
58
|
+
invalid(client, "client keepalive warning threshold must be an integer")
|
59
|
+
must_be_an_integer_if_set(thresholds[:critical]) ||
|
60
|
+
invalid(client, "client keepalive critical threshold must be an integer")
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
# Validate client keepalive.
|
65
|
+
# Validates: keepalive
|
66
|
+
#
|
67
|
+
# @param client [Hash] sensu client definition.
|
68
|
+
def validate_client_keepalive(client)
|
69
|
+
must_be_a_hash_if_set(client[:keepalive]) ||
|
70
|
+
invalid(client, "client keepalive must be a hash")
|
71
|
+
if is_a_hash?(client[:keepalive])
|
72
|
+
validate_client_keepalive_handlers(client)
|
73
|
+
validate_client_keepalive_thresholds(client)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
# Validate client redact.
|
78
|
+
# Validates: redact
|
79
|
+
#
|
80
|
+
# @param client [Hash] sensu client definition.
|
81
|
+
def validate_client_redact(client)
|
82
|
+
must_be_an_array_if_set(client[:redact]) ||
|
83
|
+
invalid(client, "client redact must be an array")
|
84
|
+
if is_an_array?(client[:redact])
|
85
|
+
items_must_be_strings(client[:redact]) ||
|
86
|
+
invalid(client, "client redact keys must each be a string")
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
# Validate a Sensu client definition.
|
91
|
+
# Validates: name, address
|
92
|
+
#
|
93
|
+
# @param client [Hash] sensu client definition.
|
94
|
+
def validate_client(client)
|
95
|
+
must_be_a_hash(client) ||
|
96
|
+
invalid(client, "client must be a hash")
|
97
|
+
if is_a_hash?(client)
|
98
|
+
must_be_a_string(client[:name]) ||
|
99
|
+
invalid(client, "client name must be a string")
|
100
|
+
must_match_regex(/^[\w\.-]+$/, client[:name]) ||
|
101
|
+
invalid(client, "client name cannot contain spaces or special characters")
|
102
|
+
must_be_a_string(client[:address]) ||
|
103
|
+
invalid(client, "client address must be a string")
|
104
|
+
validate_client_subscriptions(client)
|
105
|
+
validate_client_socket(client)
|
106
|
+
validate_client_keepalive(client)
|
107
|
+
validate_client_redact(client)
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Sensu
|
2
|
+
module Settings
|
3
|
+
module Validators
|
4
|
+
module Filter
|
5
|
+
# Validate a Sensu filter definition.
|
6
|
+
# Validates: attributes, negate
|
7
|
+
#
|
8
|
+
# @param filter [Hash] sensu filter definition.
|
9
|
+
def validate_filter(filter)
|
10
|
+
must_be_boolean_if_set(filter[:negate]) ||
|
11
|
+
invalid(filter, "filter negate must be boolean")
|
12
|
+
must_be_a_hash(filter[:attributes]) ||
|
13
|
+
invalid(filter, "filter attributes must be a hash")
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,133 @@
|
|
1
|
+
module Sensu
|
2
|
+
module Settings
|
3
|
+
module Validators
|
4
|
+
module Handler
|
5
|
+
# Validate pipe handler.
|
6
|
+
# Validates: command
|
7
|
+
#
|
8
|
+
# @param handler [Hash] sensu handler definition.
|
9
|
+
def validate_pipe_handler(handler)
|
10
|
+
must_be_a_string(handler[:command]) ||
|
11
|
+
invalid(handler, "handler command must be a string")
|
12
|
+
end
|
13
|
+
|
14
|
+
# Validate socket (tcp/udp) handler.
|
15
|
+
# Validates: socket (host, port)
|
16
|
+
#
|
17
|
+
# @param handler [Hash] sensu handler definition.
|
18
|
+
def validate_socket_handler(handler)
|
19
|
+
socket = handler[:socket]
|
20
|
+
if is_a_hash?(socket)
|
21
|
+
must_be_a_string(socket[:host]) ||
|
22
|
+
invalid(handler, "handler host must be a string")
|
23
|
+
must_be_an_integer(socket[:port]) ||
|
24
|
+
invalid(handler, "handler port must be an integer")
|
25
|
+
else
|
26
|
+
invalid(handler, "handler socket must be a hash")
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
# Validate transport handler.
|
31
|
+
# Validates: pipe (type, name, options)
|
32
|
+
#
|
33
|
+
# @param handler [Hash] sensu handler definition.
|
34
|
+
def validate_transport_handler(handler)
|
35
|
+
pipe = handler[:pipe]
|
36
|
+
if is_a_hash?(pipe)
|
37
|
+
must_be_a_string(pipe[:type]) ||
|
38
|
+
invalid(handler, "handler transport pipe type must be a string")
|
39
|
+
must_be_either(%w[direct fanout topic], pipe[:type]) ||
|
40
|
+
invalid(handler, "handler transport pipe type is invalid")
|
41
|
+
must_be_a_string(pipe[:name]) ||
|
42
|
+
invalid(handler, "handler transport pipe name must be a string")
|
43
|
+
must_be_a_hash_if_set(pipe[:options]) ||
|
44
|
+
invalid(handler, "handler transport pipe options must be a hash")
|
45
|
+
else
|
46
|
+
invalid(handler, "handler transport pipe must be a hash")
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
# Validate set handler.
|
51
|
+
# Validates: handlers
|
52
|
+
#
|
53
|
+
# @param handler [Hash] sensu handler definition.
|
54
|
+
def validate_set_handler(handler)
|
55
|
+
if is_an_array?(handler[:handlers])
|
56
|
+
items_must_be_strings(handler[:handlers]) ||
|
57
|
+
invalid(handler, "handler set handlers must each be a string")
|
58
|
+
else
|
59
|
+
invalid(handler, "handler set handlers must be an array")
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
# Validate handler type.
|
64
|
+
# Validates: type
|
65
|
+
#
|
66
|
+
# @param handler [Hash] sensu handler definition.
|
67
|
+
def validate_handler_type(handler)
|
68
|
+
must_be_a_string(handler[:type]) ||
|
69
|
+
invalid(handler, "handler type must be a string")
|
70
|
+
case handler[:type]
|
71
|
+
when "pipe"
|
72
|
+
validate_pipe_handler(handler)
|
73
|
+
when "tcp", "udp"
|
74
|
+
validate_socket_handler(handler)
|
75
|
+
when "transport"
|
76
|
+
validate_transport_handler(handler)
|
77
|
+
when "set"
|
78
|
+
validate_set_handler(handler)
|
79
|
+
else
|
80
|
+
invalid(handler, "unknown handler type")
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
# Validate handler filtering.
|
85
|
+
# Validates: filter, filters
|
86
|
+
#
|
87
|
+
# @param handler [Hash] sensu handler definition.
|
88
|
+
def validate_handler_filtering(handler)
|
89
|
+
must_be_an_array_if_set(handler[:filters]) ||
|
90
|
+
invalid(handler, "handler filters must be an array")
|
91
|
+
if is_an_array?(handler[:filters])
|
92
|
+
items_must_be_strings(handler[:filters]) ||
|
93
|
+
invalid(handler, "handler filters items must be strings")
|
94
|
+
end
|
95
|
+
must_be_a_string_if_set(handler[:filter]) ||
|
96
|
+
invalid(handler, "handler filter must be a string")
|
97
|
+
end
|
98
|
+
|
99
|
+
# Validate handler severities.
|
100
|
+
# Validates: severities
|
101
|
+
#
|
102
|
+
# @param handler [Hash] sensu handler definition.
|
103
|
+
def validate_handler_severities(handler)
|
104
|
+
must_be_an_array_if_set(handler[:severities]) ||
|
105
|
+
invalid(handler, "handler severities must be an array")
|
106
|
+
if is_an_array?(handler[:severities])
|
107
|
+
must_be_either(%w[ok warning critical unknown], handler[:severities]) ||
|
108
|
+
invalid(handler, "handler severities are invalid")
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
# Validate a Sensu handler definition.
|
113
|
+
# Validates: timeout, mutator, handle_flapping
|
114
|
+
#
|
115
|
+
# @param handler [Hash] sensu handler definition.
|
116
|
+
def validate_handler(handler)
|
117
|
+
validate_handler_type(handler)
|
118
|
+
validate_handler_filtering(handler)
|
119
|
+
validate_handler_severities(handler)
|
120
|
+
must_be_a_numeric_if_set(handler[:timeout]) ||
|
121
|
+
invalid(handler, "handler timeout must be numeric")
|
122
|
+
must_be_a_string_if_set(handler[:mutator]) ||
|
123
|
+
invalid(handler, "handler mutator must be a string")
|
124
|
+
must_be_boolean_if_set(handler[:handle_flapping]) ||
|
125
|
+
invalid(handler, "handler handle_flapping must be boolean")
|
126
|
+
if handler[:subdue]
|
127
|
+
validate_subdue(handler)
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|