flapjack_configurator 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +2 -0
- data/.rubocop.yml +47 -0
- data/Dockerfile +11 -0
- data/Gemfile +3 -0
- data/README.md +139 -0
- data/Rakefile +19 -0
- data/bin/flapjack_configurator +82 -0
- data/example.yml +121 -0
- data/flapjack_configurator.gemspec +29 -0
- data/lib/flapjack_configurator.rb +32 -0
- data/lib/flapjack_configurator/entity_mapper.rb +70 -0
- data/lib/flapjack_configurator/flapjack_config.rb +72 -0
- data/lib/flapjack_configurator/flapjack_contact.rb +156 -0
- data/lib/flapjack_configurator/flapjack_media.rb +23 -0
- data/lib/flapjack_configurator/flapjack_notification_rule.rb +39 -0
- data/lib/flapjack_configurator/flapjack_object_base.rb +86 -0
- data/lib/flapjack_configurator/flapjack_pagerduty.rb +28 -0
- data/lib/flapjack_configurator/flapjack_sub_object_base.rb +33 -0
- data/lib/flapjack_configurator/user_configuration.rb +107 -0
- data/lib/flapjack_configurator/version.rb +6 -0
- data/spec/docker_test_wrapper.rb +52 -0
- data/spec/functional/all_entity_spec.rb +19 -0
- data/spec/functional/config_test_common.rb +58 -0
- data/spec/functional/configuration_contact_attributes_spec.rb +18 -0
- data/spec/functional/configuration_contact_entities_spec.rb +116 -0
- data/spec/functional/configuration_contact_notification_media_spec.rb +73 -0
- data/spec/functional/configuration_contact_notification_rules_spec.rb +58 -0
- data/spec/functional/configuration_contact_removal_spec.rb +83 -0
- data/spec/functional/test_configs/changes/attributes.yaml +24 -0
- data/spec/functional/test_configs/changes/notification_media.yaml +155 -0
- data/spec/functional/test_configs/changes/notification_rules.yaml +143 -0
- data/spec/functional/test_configs/entities.yaml +71 -0
- data/spec/functional/test_configs/initial/attributes.yaml +24 -0
- data/spec/functional/test_configs/initial/notification_media.yaml +155 -0
- data/spec/functional/test_configs/initial/notification_rules.yaml +143 -0
- data/spec/functional/test_configs/obj_removal_setup.yaml +106 -0
- data/spec/spec_helper.rb +9 -0
- metadata +211 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: cd6924183c859202d58b0a39d5bd4ef0a90cfbb5
|
4
|
+
data.tar.gz: f65b30f3d4ecf257a2e964dfa3c27f51d5fde57e
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 05f44c8e5a7c11334478166df466478e905d1a9cacf1346026232834bf2c0251b04b03c3ba4cb965d3e87d3816b104c3df09579d79ee879f8206615c04031f07
|
7
|
+
data.tar.gz: 02d11b88c7a9d5b03dd73ed44940e48b80cf2ceb30e30b24b4cd5d57944b03280a79efaeec0716cb38c8000ca3dc97e228e9f95bc0e044e9f42da449c8f823bd
|
data/.gitignore
ADDED
data/.rubocop.yml
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
# Disable requirement of "encoding" headers on files
|
2
|
+
Encoding:
|
3
|
+
Enabled: false
|
4
|
+
|
5
|
+
# Increase line length, we're not on VT220s anymore
|
6
|
+
LineLength:
|
7
|
+
Max: 180
|
8
|
+
|
9
|
+
# Increase allowed lines in a method. Short methods are good, but 10 lines
|
10
|
+
# is a bit too low.
|
11
|
+
MethodLength:
|
12
|
+
Max: 40
|
13
|
+
|
14
|
+
# Favor explicit over implicit code: don't complain of "redundant returns"
|
15
|
+
RedundantReturn:
|
16
|
+
Enabled: false
|
17
|
+
|
18
|
+
# Don't complain about if/unless modifiers. The merit of this is debatable
|
19
|
+
# and it will likely require building of over-length lines.
|
20
|
+
IfUnlessModifier:
|
21
|
+
Enabled: false
|
22
|
+
|
23
|
+
# Raise allowed CyclomaticComplexity to 10.
|
24
|
+
CyclomaticComplexity:
|
25
|
+
Max: 10
|
26
|
+
|
27
|
+
# Raise allowed parameter count to 8, 5 is a bit low.
|
28
|
+
ParameterLists:
|
29
|
+
Max: 8
|
30
|
+
|
31
|
+
# 123_456 doesn't add value IMO.
|
32
|
+
NumericLiterals:
|
33
|
+
Enabled: false
|
34
|
+
|
35
|
+
# Turn up Assignment Branch Condition size
|
36
|
+
# This baby's gonna be complicated \m/
|
37
|
+
AbcSize:
|
38
|
+
Max: 40
|
39
|
+
|
40
|
+
# Disable the english library substitution cop: What is the value here?
|
41
|
+
SpecialGlobalVars:
|
42
|
+
Enabled: false
|
43
|
+
|
44
|
+
# Turn up the class length
|
45
|
+
# The contact class is big, and isn't easily pared down.
|
46
|
+
ClassLength:
|
47
|
+
Max: 250
|
data/Dockerfile
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
FROM debian:jessie
|
2
|
+
MAINTAINER Tom Noonan II <thomas.noonan@corvisa.com>
|
3
|
+
|
4
|
+
RUN apt-get update && apt-get install -y ruby bundler git
|
5
|
+
|
6
|
+
COPY ./ /gem_build
|
7
|
+
RUN cd /gem_build; rm -r pkg; bundle install && rake install
|
8
|
+
|
9
|
+
RUN useradd -m flapjackconf
|
10
|
+
USER flapjackconf
|
11
|
+
ENTRYPOINT ["/usr/local/bin/flapjack_configurator"]
|
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,139 @@
|
|
1
|
+
Flapjack Configurator
|
2
|
+
=====================
|
3
|
+
|
4
|
+
This gem provides a idempotent, file based fonfigurator for [Flapjack](http://flapjack.io)
|
5
|
+
|
6
|
+
Configuration
|
7
|
+
-------------
|
8
|
+
|
9
|
+
The general config form is:
|
10
|
+
|
11
|
+
```yaml
|
12
|
+
# Example/Demo Flapjack setup file
|
13
|
+
|
14
|
+
baseline_options:
|
15
|
+
notification_media:
|
16
|
+
# Baseline Pagerduty creds
|
17
|
+
# Pagerduty setup takes the domain, a API token to poll for acks, and a service key unique to the Pagerduty service
|
18
|
+
# Define the (common) domain id and API token here
|
19
|
+
# Currently only one PD instance is supported to keep the config handling easy. (/lazy)
|
20
|
+
pagerduty:
|
21
|
+
subdomain: foocorp
|
22
|
+
token: PagerDutyAPIToken
|
23
|
+
|
24
|
+
# Contacts!
|
25
|
+
contacts:
|
26
|
+
TestUser:
|
27
|
+
# Details is a direct map to the Flapjack API arguments (except notification related fields)
|
28
|
+
# http://flapjack.io/docs/1.0/jsonapi/#create-contacts
|
29
|
+
details:
|
30
|
+
first_name: Test
|
31
|
+
last_name: User
|
32
|
+
# Email is required but is only used here for documentation
|
33
|
+
email: test.user@example.com
|
34
|
+
timezone: MST7MDT
|
35
|
+
|
36
|
+
notification_media:
|
37
|
+
defaults:
|
38
|
+
# Re-notify every 30 minutes
|
39
|
+
interval: 1800
|
40
|
+
rollup_threshold: 3
|
41
|
+
|
42
|
+
# Only one of each is allowed in Flapjack 1.x :(
|
43
|
+
pagerduty:
|
44
|
+
service_key: PagerDutyServiceKey
|
45
|
+
|
46
|
+
email:
|
47
|
+
address: test.user@example.com
|
48
|
+
|
49
|
+
jabber:
|
50
|
+
address: room@conf.hipchat.com
|
51
|
+
|
52
|
+
notification_rules:
|
53
|
+
default:
|
54
|
+
warning_media:
|
55
|
+
- jabber
|
56
|
+
- email
|
57
|
+
critical_media:
|
58
|
+
- pagerduty
|
59
|
+
- jabber
|
60
|
+
- email
|
61
|
+
|
62
|
+
# Entities: A list of entities to associate with the contact
|
63
|
+
# Priority ordering is:
|
64
|
+
# 1: Exact entities
|
65
|
+
# 2: Blacklist entities
|
66
|
+
# 3: Blacklist regex
|
67
|
+
# 4: Entities regex
|
68
|
+
#
|
69
|
+
# If entities/default is true the contact will be associated with all entities which would otherwise not be associated with any contact.
|
70
|
+
entities:
|
71
|
+
default: false
|
72
|
+
exact:
|
73
|
+
- foo-app-1
|
74
|
+
regex:
|
75
|
+
- "datagen-[0-9]+"
|
76
|
+
entities_blacklist:
|
77
|
+
exact:
|
78
|
+
- datagen-2
|
79
|
+
regex:
|
80
|
+
- "datagen-[78]"
|
81
|
+
```
|
82
|
+
|
83
|
+
Most (but not all) of the options are passed through directly to the API (This is logged at debug level).
|
84
|
+
notification_media and notification_rules are merged down with the per contact rule with the highest precidence, contact defaults, and then baseline_options.
|
85
|
+
The key must be present in the contact to merge to prevent partial settings from being built off defaults.
|
86
|
+
Complete configs at the baseline_option level with automatic inheritance is not currently supported.
|
87
|
+
|
88
|
+
Use
|
89
|
+
===
|
90
|
+
|
91
|
+
WARNING: Passwords/API tokens will be logged at debug log level!
|
92
|
+
|
93
|
+
Command Line
|
94
|
+
------------
|
95
|
+
|
96
|
+
```
|
97
|
+
$ flapjack_configurator -h
|
98
|
+
Usage: flapjack_configurator [options]
|
99
|
+
|
100
|
+
Specific options:
|
101
|
+
-u, --apiurl URL Flapjack API URL
|
102
|
+
-v, --verbosity [level] Set Verbosity, level corresponds to Ruby logger levels (0: debug, 3: error)
|
103
|
+
-f, --files file1,file2,file3 List of YAML config files to load, increasing precidence
|
104
|
+
-h, --help Show this message
|
105
|
+
--version Show version
|
106
|
+
```
|
107
|
+
|
108
|
+
Files is a comma-separated list of yaml files which are merged together to form the configuration.
|
109
|
+
API URL should be of the form "http://${hostname}:${port}"
|
110
|
+
|
111
|
+
Gem
|
112
|
+
---
|
113
|
+
|
114
|
+
```
|
115
|
+
require 'flapjack_configurator'
|
116
|
+
|
117
|
+
FlapjackConfigurator.configure_flapjack(config, api_base_url, logger)
|
118
|
+
```
|
119
|
+
|
120
|
+
### configure_flapjack method:
|
121
|
+
|
122
|
+
- Arguments:
|
123
|
+
- config (Hash): Configuration hash to apply
|
124
|
+
- api_base_url (String)(Default: http://127.0.0.1:3081): Flapjack API URL string to connect to
|
125
|
+
- logger (Logger)(Default: Logger.new(STDOUT)): Logger class to log to
|
126
|
+
- enable_all_entity (Boolean)(Default: true): Add the ALL magic entity if it doesn't exist
|
127
|
+
- Return value: Boolean: true if changes were applied, false otherwise
|
128
|
+
|
129
|
+
Testing
|
130
|
+
=======
|
131
|
+
|
132
|
+
The Rubocop and Rspec coverage are part of the default rake task.
|
133
|
+
Tests spin up a Flapjack container in Docker and interact with its API, no mocks are used.
|
134
|
+
As such a running Docker daemon is required for tests.
|
135
|
+
|
136
|
+
Authors
|
137
|
+
=======
|
138
|
+
|
139
|
+
- Tom Noonan <thomas.noonan@corvisa.com>
|
data/Rakefile
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'bundler/gem_tasks'
|
2
|
+
|
3
|
+
# https://github.com/bbatsov/rubocop#rake-integration
|
4
|
+
begin
|
5
|
+
require 'rubocop/rake_task'
|
6
|
+
RuboCop::RakeTask.new
|
7
|
+
task default: :rubocop
|
8
|
+
rescue LoadError
|
9
|
+
puts 'WARNING: Rubocop unavailable'
|
10
|
+
end
|
11
|
+
|
12
|
+
# https://www.relishapp.com/rspec/rspec-core/docs/command-line/rake-task
|
13
|
+
begin
|
14
|
+
require 'rspec/core/rake_task'
|
15
|
+
RSpec::Core::RakeTask.new(:spec)
|
16
|
+
task default: :spec
|
17
|
+
rescue LoadError
|
18
|
+
puts 'WARNING: Rspec unavailable'
|
19
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'flapjack_configurator'
|
4
|
+
require 'optparse'
|
5
|
+
require 'ostruct'
|
6
|
+
require 'logger'
|
7
|
+
require 'yaml'
|
8
|
+
require 'deep_merge'
|
9
|
+
|
10
|
+
# Parse the command line arguments
|
11
|
+
def parse_arguments(args, logger)
|
12
|
+
options = OpenStruct.new
|
13
|
+
options.api_url = 'http://127.0.0.1:3081'
|
14
|
+
logger.level = Logger::INFO
|
15
|
+
options.files = []
|
16
|
+
|
17
|
+
parser = OptionParser.new do |opts|
|
18
|
+
opts.banner = 'Usage: flapjack_configurator [options]'
|
19
|
+
|
20
|
+
opts.separator ''
|
21
|
+
opts.separator 'Specific options:'
|
22
|
+
|
23
|
+
opts.on('-u', '--apiurl URL', String, 'Flapjack API URL') do |url|
|
24
|
+
options.api_url = url
|
25
|
+
logger.debug("API URL set to #{url}")
|
26
|
+
end
|
27
|
+
|
28
|
+
opts.on('-v', '--verbosity [level]', Integer, 'Set Verbosity, level corresponds to Ruby logger levels (0: debug, 3: error)') do |level|
|
29
|
+
if level
|
30
|
+
logger.level = level
|
31
|
+
else
|
32
|
+
logger.level -= 1 if logger.level > 0
|
33
|
+
end
|
34
|
+
logger.debug('Log level set to #{logger.level}')
|
35
|
+
end
|
36
|
+
|
37
|
+
opts.on('-f', '--files file1,file2,file3', Array, 'List of YAML config files to load, increasing precidence') do |files|
|
38
|
+
options.files += files
|
39
|
+
end
|
40
|
+
|
41
|
+
opts.on_tail('-h', '--help', 'Show this message') do
|
42
|
+
puts opts
|
43
|
+
exit
|
44
|
+
end
|
45
|
+
|
46
|
+
opts.on_tail('--version', 'Show version') do
|
47
|
+
puts "Flapjack Configurator #{Gem.loaded_specs['flapjack_configurator'].version}"
|
48
|
+
exit
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
parser.parse!(args)
|
53
|
+
|
54
|
+
if options.files.length < 1
|
55
|
+
logger.fatal('Option --files is required')
|
56
|
+
exit
|
57
|
+
end
|
58
|
+
|
59
|
+
return options
|
60
|
+
end
|
61
|
+
|
62
|
+
# Load and merge the configs
|
63
|
+
def load_config(file_list, logger)
|
64
|
+
config = {}
|
65
|
+
file_list.each do |file_name|
|
66
|
+
logger.debug("Loading config file #{file_name}")
|
67
|
+
config.deep_merge!(YAML.load_file(file_name))
|
68
|
+
end
|
69
|
+
|
70
|
+
return config
|
71
|
+
end
|
72
|
+
|
73
|
+
def main
|
74
|
+
logger = Logger.new(STDOUT)
|
75
|
+
options = parse_arguments(ARGV, logger)
|
76
|
+
config = load_config(options.files, logger)
|
77
|
+
|
78
|
+
logger.info('Nothing to do') unless FlapjackConfigurator.configure_flapjack(config, options.api_url, logger)
|
79
|
+
end
|
80
|
+
|
81
|
+
# The __FILE__ $0 trick doesn't work when loaded through the gem wrapper
|
82
|
+
main
|
data/example.yml
ADDED
@@ -0,0 +1,121 @@
|
|
1
|
+
# Example/Demo Flapjack setup file
|
2
|
+
|
3
|
+
baseline_options:
|
4
|
+
notification_media:
|
5
|
+
# Baseline Pagerduty creds
|
6
|
+
# Pagerduty setup takes the domain, a API token to poll for acks, and a service key unique to the Pagerduty service
|
7
|
+
# Define the (common) domain id and API token here
|
8
|
+
# Currently only one PD instance is supported to keep the config handling easy. (/lazy)
|
9
|
+
pagerduty:
|
10
|
+
subdomain: foocorp
|
11
|
+
token: PagerDutyAPIToken
|
12
|
+
|
13
|
+
# Contacts!
|
14
|
+
contacts:
|
15
|
+
TestUser:
|
16
|
+
# Details is a direct map to the Flapjack API arguments (except notification related fields)
|
17
|
+
# http://flapjack.io/docs/1.0/jsonapi/#create-contacts
|
18
|
+
details:
|
19
|
+
first_name: Test
|
20
|
+
last_name: User
|
21
|
+
# Email is required but is only used here for documentation
|
22
|
+
email: test.user@example.com
|
23
|
+
timezone: MST7MDT
|
24
|
+
|
25
|
+
notification_media:
|
26
|
+
defaults:
|
27
|
+
# Re-notify every 30 minutes
|
28
|
+
interval: 1800
|
29
|
+
rollup_threshold: 3
|
30
|
+
|
31
|
+
# Only one of each is allowed in Flapjack 1.x :(
|
32
|
+
pagerduty:
|
33
|
+
service_key: PagerDutyServiceKey
|
34
|
+
|
35
|
+
email:
|
36
|
+
address: test.user@example.com
|
37
|
+
|
38
|
+
jabber:
|
39
|
+
address: room@conf.hipchat.com
|
40
|
+
|
41
|
+
notification_rules:
|
42
|
+
default:
|
43
|
+
warning_media:
|
44
|
+
- jabber
|
45
|
+
- email
|
46
|
+
critical_media:
|
47
|
+
- pagerduty
|
48
|
+
- jabber
|
49
|
+
- email
|
50
|
+
|
51
|
+
# Entities: An exact list of entities
|
52
|
+
# Priority ordering is:
|
53
|
+
# 1: Exact entities
|
54
|
+
# 2: Blacklist entities
|
55
|
+
# 3: Blacklist regex
|
56
|
+
# 4: Entities regex
|
57
|
+
entities:
|
58
|
+
exact:
|
59
|
+
- foo-app-1
|
60
|
+
regex:
|
61
|
+
- "datagen-[0-9]+"
|
62
|
+
entities_blacklist:
|
63
|
+
exact:
|
64
|
+
- datagen-2
|
65
|
+
regex:
|
66
|
+
- "datagen-[78]"
|
67
|
+
|
68
|
+
DefaultUser:
|
69
|
+
details:
|
70
|
+
first_name: Default
|
71
|
+
last_name: User
|
72
|
+
email: default.user@example.com
|
73
|
+
timezone: MST7MDT
|
74
|
+
|
75
|
+
notification_media:
|
76
|
+
defaults:
|
77
|
+
# Re-notify every 30 minutes
|
78
|
+
interval: 1800
|
79
|
+
rollup_threshold: 3
|
80
|
+
|
81
|
+
# Only one of each is allowed in Flapjack 1.x :(
|
82
|
+
email:
|
83
|
+
address: test.user@example.com
|
84
|
+
|
85
|
+
notification_rules:
|
86
|
+
default:
|
87
|
+
warning_media:
|
88
|
+
- email
|
89
|
+
critical_media:
|
90
|
+
- email
|
91
|
+
|
92
|
+
entities:
|
93
|
+
default: true
|
94
|
+
|
95
|
+
Beard:
|
96
|
+
details:
|
97
|
+
first_name: Beard
|
98
|
+
last_name: User
|
99
|
+
email: beard.user@example.com
|
100
|
+
timezone: CST6CDT
|
101
|
+
|
102
|
+
notification_media:
|
103
|
+
defaults:
|
104
|
+
# Re-notify every 30 minutes
|
105
|
+
interval: 1800
|
106
|
+
rollup_threshold: 3
|
107
|
+
|
108
|
+
# Only one of each is allowed in Flapjack 1.x :(
|
109
|
+
email:
|
110
|
+
address: beard.user@example.com
|
111
|
+
|
112
|
+
notification_rules:
|
113
|
+
default:
|
114
|
+
warning_media:
|
115
|
+
- email
|
116
|
+
critical_media:
|
117
|
+
- email
|
118
|
+
|
119
|
+
entities:
|
120
|
+
exact:
|
121
|
+
- ALL
|
@@ -0,0 +1,29 @@
|
|
1
|
+
lib = File.expand_path('../lib', __FILE__)
|
2
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
3
|
+
require 'flapjack_configurator/version'
|
4
|
+
|
5
|
+
Gem::Specification.new do |gem|
|
6
|
+
gem.authors = ['Tom Noonan II']
|
7
|
+
gem.email = 'thomas.noonan@corvisa.com'
|
8
|
+
gem.description = 'FlapjackConfigurator loads a user specified config from YAML files and loads them idempotently into Flapjack via the Flapjack API'
|
9
|
+
gem.summary = 'Flapjack configuration tool'
|
10
|
+
gem.homepage = 'https://github.com/CVTJNII/FlapjackConfigurator'
|
11
|
+
gem.license = 'Apache License, Version 2'
|
12
|
+
|
13
|
+
gem.files = `git ls-files`.split($\) - ['Gemfile.lock']
|
14
|
+
gem.executables = gem.files.grep(%r{^bin/}).map { |f| File.basename(f) }
|
15
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
16
|
+
gem.name = 'flapjack_configurator'
|
17
|
+
gem.require_paths = ['lib']
|
18
|
+
gem.version = FlapjackConfigurator::VERSION
|
19
|
+
|
20
|
+
gem.add_dependency 'flapjack-diner', '~>1.4'
|
21
|
+
gem.add_dependency 'ruby_deep_clone', '~>0.6'
|
22
|
+
gem.add_dependency 'deep_merge', '~>1.0'
|
23
|
+
|
24
|
+
gem.add_development_dependency 'bundler', '~> 1.7'
|
25
|
+
gem.add_development_dependency 'rake', '~> 10.0'
|
26
|
+
gem.add_development_dependency 'rspec'
|
27
|
+
gem.add_development_dependency 'docker-api'
|
28
|
+
gem.add_development_dependency 'simplecov'
|
29
|
+
end
|