flapjack_configurator 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (39) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +2 -0
  3. data/.rubocop.yml +47 -0
  4. data/Dockerfile +11 -0
  5. data/Gemfile +3 -0
  6. data/README.md +139 -0
  7. data/Rakefile +19 -0
  8. data/bin/flapjack_configurator +82 -0
  9. data/example.yml +121 -0
  10. data/flapjack_configurator.gemspec +29 -0
  11. data/lib/flapjack_configurator.rb +32 -0
  12. data/lib/flapjack_configurator/entity_mapper.rb +70 -0
  13. data/lib/flapjack_configurator/flapjack_config.rb +72 -0
  14. data/lib/flapjack_configurator/flapjack_contact.rb +156 -0
  15. data/lib/flapjack_configurator/flapjack_media.rb +23 -0
  16. data/lib/flapjack_configurator/flapjack_notification_rule.rb +39 -0
  17. data/lib/flapjack_configurator/flapjack_object_base.rb +86 -0
  18. data/lib/flapjack_configurator/flapjack_pagerduty.rb +28 -0
  19. data/lib/flapjack_configurator/flapjack_sub_object_base.rb +33 -0
  20. data/lib/flapjack_configurator/user_configuration.rb +107 -0
  21. data/lib/flapjack_configurator/version.rb +6 -0
  22. data/spec/docker_test_wrapper.rb +52 -0
  23. data/spec/functional/all_entity_spec.rb +19 -0
  24. data/spec/functional/config_test_common.rb +58 -0
  25. data/spec/functional/configuration_contact_attributes_spec.rb +18 -0
  26. data/spec/functional/configuration_contact_entities_spec.rb +116 -0
  27. data/spec/functional/configuration_contact_notification_media_spec.rb +73 -0
  28. data/spec/functional/configuration_contact_notification_rules_spec.rb +58 -0
  29. data/spec/functional/configuration_contact_removal_spec.rb +83 -0
  30. data/spec/functional/test_configs/changes/attributes.yaml +24 -0
  31. data/spec/functional/test_configs/changes/notification_media.yaml +155 -0
  32. data/spec/functional/test_configs/changes/notification_rules.yaml +143 -0
  33. data/spec/functional/test_configs/entities.yaml +71 -0
  34. data/spec/functional/test_configs/initial/attributes.yaml +24 -0
  35. data/spec/functional/test_configs/initial/notification_media.yaml +155 -0
  36. data/spec/functional/test_configs/initial/notification_rules.yaml +143 -0
  37. data/spec/functional/test_configs/obj_removal_setup.yaml +106 -0
  38. data/spec/spec_helper.rb +9 -0
  39. 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
@@ -0,0 +1,2 @@
1
+ pkg/*
2
+ coverage/*
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
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
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