sensu_generator 0.0.25
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +10 -0
- data/.rspec +2 -0
- data/.travis.yml +4 -0
- data/Gemfile +4 -0
- data/README.md +87 -0
- data/Rakefile +6 -0
- data/bin/console +11 -0
- data/bin/setup +8 -0
- data/exe/sensu-generator +54 -0
- data/lib/sensu_generator/application.rb +134 -0
- data/lib/sensu_generator/check_file.rb +27 -0
- data/lib/sensu_generator/client.rb +60 -0
- data/lib/sensu_generator/config.rb +64 -0
- data/lib/sensu_generator/consul/consul_service.rb +47 -0
- data/lib/sensu_generator/consul/consul_state.rb +45 -0
- data/lib/sensu_generator/consul.rb +66 -0
- data/lib/sensu_generator/exceptions.rb +21 -0
- data/lib/sensu_generator/generator.rb +97 -0
- data/lib/sensu_generator/hash.rb +6 -0
- data/lib/sensu_generator/logger.rb +28 -0
- data/lib/sensu_generator/notifier.rb +15 -0
- data/lib/sensu_generator/restarter.rb +55 -0
- data/lib/sensu_generator/sensu_server.rb +70 -0
- data/lib/sensu_generator/server.rb +69 -0
- data/lib/sensu_generator/trigger.rb +40 -0
- data/lib/sensu_generator/version.rb +3 -0
- data/lib/sensu_generator.rb +18 -0
- data/sensu-generator.config.example +28 -0
- data/sensu_generator.gemspec +33 -0
- metadata +200 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: aa5b40932e162763cc44bfc51cd2051806b3d46a
|
4
|
+
data.tar.gz: 23194a317cde4a606d1358ef06fa70c5e7974bcd
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 5d6afad7404f580509f9f189f92fc70b5ca0c11158fa4561325ed7b2aea4b29abebbd064ebfc5be466693a8de7f5304ae9ea8084c5c90a8f6f9833d308e5bb56
|
7
|
+
data.tar.gz: d818013b9f39db3898ba74924063754c505ed5327f0bc473a05f3e37c922272c25c8724270181b2373180d2d129e3ffcc8adc24dcaf09ddabe61951b9b23248f
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,87 @@
|
|
1
|
+
# SensuGenerator
|
2
|
+
|
3
|
+
SensuGenerator is an intermediate layer between Consul and Sensu. It helps to set up dynamic monitoring systems. It generates check configurations from ERB templates according to *tags* listed in the KV and Consul service properties. It watches for changes Consul services state and special key in the KV. It triggers the following:
|
4
|
+
Sensu check configuration files are generated from the templates, the result will be synced via *rsync* and Sensu servers will be restarted using http Supervisord API. All files are generated when application starts and only changes will be processed.
|
5
|
+
|
6
|
+
All service checks *tag* are stored in the Consul Key-Value storage in *service/kv_tags_path* path, default *kv_tags_path* is "checks". Tag is the beginning of a service check template name and should be specified as a part of the template name in the Consul KV storage. Note that value should be comma-separated tags list. Rsync repo shuold be named as sensu service name.
|
7
|
+
|
8
|
+
It can can be used master server with multiple clients which send processed templates via tcp.
|
9
|
+
|
10
|
+
## Installation
|
11
|
+
|
12
|
+
Add this line to your application's Gemfile:
|
13
|
+
|
14
|
+
```ruby
|
15
|
+
gem 'sensu_generator'
|
16
|
+
```
|
17
|
+
|
18
|
+
Install it yourself as:
|
19
|
+
|
20
|
+
$ gem install sensu_generator
|
21
|
+
|
22
|
+
## Usage
|
23
|
+
|
24
|
+
sensu_generator start|stop|status|run -- [options]
|
25
|
+
|
26
|
+
##### Example:
|
27
|
+
|
28
|
+
**consul_url***/kv/nginx/checks*
|
29
|
+
```
|
30
|
+
check-http, check-tcp
|
31
|
+
```
|
32
|
+
|
33
|
+
Use ***svc*** (contains service data form consul) and ***check*** (contains *tag* name) in the ERB template.
|
34
|
+
***svc.kv_svc_props(key: key)*** can be used to access to ***svc/key*** data.
|
35
|
+
If key is not specified it will be requested the whole ***svc/*** folder.
|
36
|
+
|
37
|
+
Use Slack as notifier if you want.
|
38
|
+
|
39
|
+
##### Check ERB template example:
|
40
|
+
|
41
|
+
```
|
42
|
+
{
|
43
|
+
"checks": {
|
44
|
+
<% svc.properties.each do |instance| %>
|
45
|
+
<% next if instance.ServiceTags.include? "udp" %>
|
46
|
+
"check-ports-tcp-<%= "#{svc.name}-#{instance.ServiceAddress}-#{instance.ServicePort}" %>": {
|
47
|
+
"command": "check-ports.rb -h <%= instance.ServiceAddress %> -p <%= instance.ServicePort %>",
|
48
|
+
"subscribers": ["roundrobin:sensu-checker-node"],
|
49
|
+
"handlers": ["slack"],
|
50
|
+
"source": "<%= svc.name %>.service"
|
51
|
+
}<%= "," if instance != svc.properties.last %>
|
52
|
+
<% end %>
|
53
|
+
}
|
54
|
+
}
|
55
|
+
|
56
|
+
|
57
|
+
```
|
58
|
+
|
59
|
+
## Configuration
|
60
|
+
|
61
|
+
##### server configuration:
|
62
|
+
|
63
|
+
```
|
64
|
+
"mode": "server",
|
65
|
+
"server": {
|
66
|
+
"addr": "", //ip address to listen or left it empty to listen on 0.0.0.0
|
67
|
+
"port": 12345 //listen port
|
68
|
+
}
|
69
|
+
```
|
70
|
+
|
71
|
+
##### client configuration:
|
72
|
+
|
73
|
+
```
|
74
|
+
"mode": "client",
|
75
|
+
"server": {
|
76
|
+
"addr": "", //ip address or domain to connect to
|
77
|
+
"port": 12345 //server port
|
78
|
+
}
|
79
|
+
```
|
80
|
+
|
81
|
+
See *sensu-generator.config.example* for more information.
|
82
|
+
|
83
|
+
## Development
|
84
|
+
|
85
|
+
## Contributing
|
86
|
+
|
87
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/aksentyev/sensu_generator. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the
|
data/Rakefile
ADDED
data/bin/console
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "sensu_generator"
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
require "pry"
|
11
|
+
Pry.start
|
data/bin/setup
ADDED
data/exe/sensu-generator
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'sensu_generator'
|
3
|
+
require 'optparse'
|
4
|
+
require 'daemons'
|
5
|
+
|
6
|
+
module SensuGenerator
|
7
|
+
class << self
|
8
|
+
def parse_args!
|
9
|
+
args = ARGV.dup
|
10
|
+
|
11
|
+
# get elements after '--' because of Daemons
|
12
|
+
args = args[(args.index('--')+1)..-1] if args.include? ('--')
|
13
|
+
config = nil
|
14
|
+
optparse = OptionParser.new do |opts|
|
15
|
+
opts.banner = "sensu-generator run|start|stop|status -- [options]"
|
16
|
+
|
17
|
+
opts.on("-c", "--config File", String, "Path to config file") do |item|
|
18
|
+
config = item
|
19
|
+
end
|
20
|
+
opts.on_tail("--version", "Show version") do
|
21
|
+
puts VERSION
|
22
|
+
exit
|
23
|
+
end
|
24
|
+
|
25
|
+
opts.on_tail("-h", "--help", "Show this message") do
|
26
|
+
puts opts
|
27
|
+
exit
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
optparse.parse!(args)
|
32
|
+
config ? File.expand_path(config) : nil
|
33
|
+
end
|
34
|
+
|
35
|
+
def run(config_file = nil)
|
36
|
+
config = Config.new(config_file)
|
37
|
+
logger = Logger.new(config.get[:logger])
|
38
|
+
logger.level = eval("Logger::#{config.get[:logger][:log_level].upcase}")
|
39
|
+
notifier = Notifier.new(config.get[:slack])
|
40
|
+
trigger = Trigger.new
|
41
|
+
|
42
|
+
Application.new(config: config, logger: logger, notifier: notifier, trigger: trigger).run
|
43
|
+
rescue => e
|
44
|
+
msg = %("Sensu_generator exited with non-zero code.\n #{e.to_s} \n#{e.backtrace.join("\n\t")}")
|
45
|
+
Logger.new(file: STDOUT).fatal msg
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
config = SensuGenerator::parse_args!
|
51
|
+
|
52
|
+
Daemons.run_proc(__FILE__) do
|
53
|
+
SensuGenerator::run(config)
|
54
|
+
end
|
@@ -0,0 +1,134 @@
|
|
1
|
+
require 'thread'
|
2
|
+
|
3
|
+
module SensuGenerator
|
4
|
+
class Application
|
5
|
+
class << self
|
6
|
+
def logger
|
7
|
+
@@logger
|
8
|
+
end
|
9
|
+
|
10
|
+
def notifier
|
11
|
+
@@notifier
|
12
|
+
end
|
13
|
+
|
14
|
+
def config
|
15
|
+
@@config
|
16
|
+
end
|
17
|
+
|
18
|
+
def trigger
|
19
|
+
@@trigger
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def initialize(config:, logger:, notifier:, trigger:)
|
24
|
+
@@logger = logger
|
25
|
+
@@notifier = notifier
|
26
|
+
@@config = config
|
27
|
+
@@trigger = trigger
|
28
|
+
@threads = []
|
29
|
+
end
|
30
|
+
|
31
|
+
def logger
|
32
|
+
@@logger
|
33
|
+
end
|
34
|
+
|
35
|
+
def notifier
|
36
|
+
@@notifier
|
37
|
+
end
|
38
|
+
|
39
|
+
def config
|
40
|
+
@@config
|
41
|
+
end
|
42
|
+
|
43
|
+
def trigger
|
44
|
+
@@trigger
|
45
|
+
end
|
46
|
+
|
47
|
+
def run_restarter
|
48
|
+
logger.info "Starting restarter..."
|
49
|
+
loop do
|
50
|
+
logger.info 'Restarter is alive!'
|
51
|
+
if restarter.need_to_apply_new_configs?
|
52
|
+
restarter.perform_restart
|
53
|
+
end
|
54
|
+
sleep 60
|
55
|
+
end
|
56
|
+
rescue => e
|
57
|
+
raise ApplicationError, "Restarter error:\n\t #{e.to_s}\n\t #{e.backtrace}"
|
58
|
+
end
|
59
|
+
|
60
|
+
def run_generator
|
61
|
+
logger.info "Starting generator..."
|
62
|
+
generator.flush_results if config.get[:mode] == 'server'
|
63
|
+
state = ConsulState.new
|
64
|
+
loop do
|
65
|
+
logger.info 'Generator is alive!'
|
66
|
+
if state.changed? && state.actualized?
|
67
|
+
generator.services = state.changes
|
68
|
+
list = generator.generate!
|
69
|
+
logger.info "#{list.size} files processed: #{list.join(', ')}"
|
70
|
+
if config.get[:mode] == 'server' && list.empty? && state.changes.any? { |svc| svc.name == config.get[:sensu][:service] }
|
71
|
+
logger.info "Sensu-server service state was changed"
|
72
|
+
trigger.touch
|
73
|
+
end
|
74
|
+
end
|
75
|
+
sleep 60
|
76
|
+
state.actualize
|
77
|
+
end
|
78
|
+
rescue => e
|
79
|
+
raise ApplicationError, "Generator error:\n\t #{e.to_s}\n\t #{e.backtrace}"
|
80
|
+
end
|
81
|
+
|
82
|
+
def run_server
|
83
|
+
server = Server.new
|
84
|
+
rescue => e
|
85
|
+
server&.close
|
86
|
+
raise ApplicationError, "Server error:\n\t #{e.to_s}\n\t #{e.backtrace}"
|
87
|
+
end
|
88
|
+
|
89
|
+
def run
|
90
|
+
logger.info "Starting application #{VERSION}v in #{config.get[:mode]} mode"
|
91
|
+
threads = %w(generator)
|
92
|
+
if config.get[:mode] == 'server'
|
93
|
+
threads << 'restarter'
|
94
|
+
threads << 'server' if config.get[:server][:port]
|
95
|
+
end
|
96
|
+
threads.each do |thr|
|
97
|
+
@threads << run_thread(thr)
|
98
|
+
end
|
99
|
+
|
100
|
+
loop do
|
101
|
+
@threads.each do |thr|
|
102
|
+
unless thr.alive?
|
103
|
+
@threads.delete thr
|
104
|
+
@threads << run_thread(thr.name)
|
105
|
+
logger.error "#{thr.name.capitalize} is NOT ALIVE. Trying to restart."
|
106
|
+
end
|
107
|
+
end
|
108
|
+
sleep 60
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
private
|
113
|
+
|
114
|
+
def consul
|
115
|
+
@consul ||= Consul.new
|
116
|
+
end
|
117
|
+
|
118
|
+
def generator
|
119
|
+
@generator ||= Generator.new
|
120
|
+
end
|
121
|
+
|
122
|
+
def restarter
|
123
|
+
list = consul.sensu_servers
|
124
|
+
logger.info "Sensu servers discovered: #{list.map(&:address).join(', ')}"
|
125
|
+
Restarter.new(list)
|
126
|
+
end
|
127
|
+
|
128
|
+
def run_thread(name)
|
129
|
+
thr = eval("Thread.new { run_#{name} }")
|
130
|
+
thr.name = name
|
131
|
+
thr
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
|
3
|
+
module SensuGenerator
|
4
|
+
class CheckFile
|
5
|
+
def self.remove_all_with(prefix)
|
6
|
+
FileUtils.rm(Dir.glob("#{Application.config.result_dir}/#{prefix}*"))
|
7
|
+
end
|
8
|
+
|
9
|
+
def initialize(filename)
|
10
|
+
@config = Application.config
|
11
|
+
@trigger = Application.trigger
|
12
|
+
@filename = filename
|
13
|
+
@fullpath = File.join(@config.result_dir, @filename)
|
14
|
+
end
|
15
|
+
|
16
|
+
def write(data)
|
17
|
+
file = File.open(@fullpath, 'w+')
|
18
|
+
file.write data
|
19
|
+
file.close
|
20
|
+
@trigger.touch
|
21
|
+
end
|
22
|
+
|
23
|
+
def remove
|
24
|
+
FileUtils.rm @fullpath
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'socket'
|
3
|
+
|
4
|
+
module SensuGenerator
|
5
|
+
class Client
|
6
|
+
def initialize
|
7
|
+
@logger = Application.logger
|
8
|
+
@config = Application.config
|
9
|
+
connection
|
10
|
+
end
|
11
|
+
|
12
|
+
attr_reader :config, :logger
|
13
|
+
|
14
|
+
def connection
|
15
|
+
@connection ||= connect
|
16
|
+
end
|
17
|
+
|
18
|
+
def connect
|
19
|
+
logger.info "Client: connecting to server #{server_addr}:#{server_port}"
|
20
|
+
s = TCPSocket.new(server_addr, server_port)
|
21
|
+
logger.info "Client: connected"
|
22
|
+
s
|
23
|
+
rescue => e
|
24
|
+
raise ClientError, "Client: connection failed #{e.inspect} #{e.backtrace}\n"
|
25
|
+
end
|
26
|
+
|
27
|
+
def write_file(data)
|
28
|
+
connection.puts data
|
29
|
+
logger.info "Client: data transferred successfully"
|
30
|
+
true
|
31
|
+
rescue => e
|
32
|
+
close
|
33
|
+
raise ClientError, "Client: write failed #{e.inspect} #{e.backtrace}\n"
|
34
|
+
end
|
35
|
+
|
36
|
+
def flush_results
|
37
|
+
connection.puts JSON.fast_generate({"FLUSH_WITH_PREFIX" => "#{config.file_prefix}" })
|
38
|
+
rescue => e
|
39
|
+
close
|
40
|
+
raise ClientError, "Client: write failed #{e.inspect} #{e.backtrace}\n"
|
41
|
+
close
|
42
|
+
end
|
43
|
+
|
44
|
+
def close
|
45
|
+
@connection.close
|
46
|
+
@connection = nil
|
47
|
+
logger.info "Client: connection closed"
|
48
|
+
end
|
49
|
+
|
50
|
+
private
|
51
|
+
|
52
|
+
def server_addr
|
53
|
+
@server_addr ||= config.get[:server][:addr]
|
54
|
+
end
|
55
|
+
|
56
|
+
def server_port
|
57
|
+
@server_port ||= config.get[:server][:port]
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
require 'socket'
|
2
|
+
require 'json'
|
3
|
+
|
4
|
+
module SensuGenerator
|
5
|
+
class Config
|
6
|
+
@@default = {
|
7
|
+
:sensu => {
|
8
|
+
:check_default_params => {
|
9
|
+
:refresh => 86400,
|
10
|
+
:interval => 60,
|
11
|
+
:aggregate => true
|
12
|
+
},
|
13
|
+
:minimal_to_restart => 2,
|
14
|
+
:service => "sensu-server",
|
15
|
+
:rsync_repo => "sensu-server",
|
16
|
+
:supervisor => {:user => "", :password => ""},
|
17
|
+
},
|
18
|
+
:mode => 'server',
|
19
|
+
:server => {
|
20
|
+
:addr => '',
|
21
|
+
:port => nil
|
22
|
+
},
|
23
|
+
:result_dir => "work/result",
|
24
|
+
:templates_dir => "work/templates",
|
25
|
+
:logger => {
|
26
|
+
:file => STDOUT,
|
27
|
+
:notify_level => "error",
|
28
|
+
:log_level => "debug"
|
29
|
+
},
|
30
|
+
:slack => {
|
31
|
+
:url => nil,
|
32
|
+
:channel => nil,
|
33
|
+
:level => "error"
|
34
|
+
},
|
35
|
+
:kv_tags_path => "checks",
|
36
|
+
# See diplomat documentation to set proper consul parameters
|
37
|
+
:consul => {
|
38
|
+
:url => "http://consul.service.consul:8500"
|
39
|
+
}
|
40
|
+
}
|
41
|
+
|
42
|
+
def initialize(path = nil)
|
43
|
+
@config = process(path)
|
44
|
+
end
|
45
|
+
|
46
|
+
def get
|
47
|
+
@config
|
48
|
+
end
|
49
|
+
|
50
|
+
def process(path)
|
51
|
+
custom = path ? JSON(File.read(path), :symbolize_names => true) : {}
|
52
|
+
@config = @@default.deep_merge(custom)
|
53
|
+
end
|
54
|
+
|
55
|
+
def result_dir
|
56
|
+
raise(GeneratorError, "Result dir is not defined!") unless get[:result_dir]
|
57
|
+
File.expand_path(get[:result_dir])
|
58
|
+
end
|
59
|
+
|
60
|
+
def file_prefix
|
61
|
+
@file_prefix ||= get[:mode] == 'server' ? "local_" : "#{Socket.gethostname}_"
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
module SensuGenerator
|
2
|
+
class ConsulService < Consul
|
3
|
+
|
4
|
+
attr_reader :name, :properties, :checks
|
5
|
+
|
6
|
+
def initialize(name:)
|
7
|
+
@name = name
|
8
|
+
@changed = true
|
9
|
+
super()
|
10
|
+
all_properties
|
11
|
+
self
|
12
|
+
end
|
13
|
+
|
14
|
+
def all_properties
|
15
|
+
properties = get_props.class == Array ? get_props.map {|el| el.to_h} : get_props.to_h
|
16
|
+
@all_properties ||= { checks: get_checks, properties: properties }
|
17
|
+
end
|
18
|
+
|
19
|
+
alias :get_all_properties :all_properties
|
20
|
+
|
21
|
+
def get_checks
|
22
|
+
@checks ||= kv_svc_props(key: config.get[:kv_tags_path])
|
23
|
+
end
|
24
|
+
|
25
|
+
def get_props
|
26
|
+
@properties ||= get_service_props(name)
|
27
|
+
end
|
28
|
+
|
29
|
+
def update
|
30
|
+
old_all_properties = all_properties.clone
|
31
|
+
reset
|
32
|
+
get_all_properties
|
33
|
+
@changed = true if all_properties != old_all_properties
|
34
|
+
end
|
35
|
+
|
36
|
+
def changed?
|
37
|
+
@changed
|
38
|
+
end
|
39
|
+
|
40
|
+
def reset
|
41
|
+
@all_properties = nil
|
42
|
+
@properties = nil
|
43
|
+
@checks = nil
|
44
|
+
@changed = false
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module SensuGenerator
|
2
|
+
class ConsulState < Consul
|
3
|
+
def initialize
|
4
|
+
@actual_state = []
|
5
|
+
super()
|
6
|
+
actualize
|
7
|
+
end
|
8
|
+
|
9
|
+
def show
|
10
|
+
@actual_state
|
11
|
+
end
|
12
|
+
|
13
|
+
def actualize
|
14
|
+
reset
|
15
|
+
@svc_list_diff = services.map {|name, _| name.to_s } - @actual_state.map { |svc| svc.name.to_s}
|
16
|
+
@actual_state.each(&:update)
|
17
|
+
@svc_list_diff.each do |name|
|
18
|
+
@actual_state << ConsulService.new(name: name)
|
19
|
+
end
|
20
|
+
@actualized = true
|
21
|
+
logger.debug "Services actualized list: #{@actual_state.map { |svc| svc.name.to_s} }"
|
22
|
+
self
|
23
|
+
end
|
24
|
+
|
25
|
+
def changed?
|
26
|
+
state = !(@svc_list_diff || []).empty? || !changes.empty?
|
27
|
+
logger.debug "Consul state was changed: #{state.to_s}"
|
28
|
+
state
|
29
|
+
end
|
30
|
+
|
31
|
+
def changes
|
32
|
+
@svc_changes ||= @actual_state.select(&:changed?)
|
33
|
+
end
|
34
|
+
|
35
|
+
def reset
|
36
|
+
@actualized = false
|
37
|
+
@svc_changes = nil
|
38
|
+
@svc_list_diff = nil
|
39
|
+
end
|
40
|
+
|
41
|
+
def actualized?
|
42
|
+
@actualized ? true : false # For the case when nil
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'diplomat'
|
3
|
+
|
4
|
+
module SensuGenerator
|
5
|
+
class Consul
|
6
|
+
attr_writer :config, :logger
|
7
|
+
|
8
|
+
def initialize
|
9
|
+
@config = config
|
10
|
+
Diplomat.configure do |consul|
|
11
|
+
config.get[:consul].each do |k, v|
|
12
|
+
consul.public_send("#{k}=", v)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def sensu_servers
|
18
|
+
get_service_props(config.get[:sensu][:service]).map {|el| el.ServiceAddress}.uniq.
|
19
|
+
map {|addr| SensuServer.new(address: addr)}
|
20
|
+
end
|
21
|
+
|
22
|
+
def services
|
23
|
+
Diplomat::Service.get_all.to_h
|
24
|
+
end
|
25
|
+
|
26
|
+
def get_service_props(svc)
|
27
|
+
result = Diplomat::Service.get(svc, :all)
|
28
|
+
result.class == Array ? result.map {|el| el.remove_consul_indexes} : result.remove_consul_indexes
|
29
|
+
end
|
30
|
+
|
31
|
+
def kv_svc_props(svc: name, key: nil)
|
32
|
+
opts = key ? nil : {recurse: true}
|
33
|
+
response = Diplomat::Kv.get("#{svc}/#{key}", opts)
|
34
|
+
key ? JSON(response) : response # Maybe the feature of JSON check configuration will be implemented
|
35
|
+
rescue
|
36
|
+
if response
|
37
|
+
if response.match(/\s+/) || key.to_s == config.get[:kv_tags_path] # tags value is designed to be a list even if it has only one element
|
38
|
+
response.gsub(/\s+/, '').split(',')
|
39
|
+
else
|
40
|
+
response
|
41
|
+
end
|
42
|
+
else
|
43
|
+
[]
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
private
|
48
|
+
|
49
|
+
def config
|
50
|
+
@config ||= Application.config
|
51
|
+
end
|
52
|
+
|
53
|
+
def logger
|
54
|
+
@logger ||= Application.logger
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
class OpenStruct
|
60
|
+
def remove_consul_indexes
|
61
|
+
%w(CreateIndex ModifyIndex).each do |f|
|
62
|
+
self.delete_field(f) if self.respond_to?(f)
|
63
|
+
end
|
64
|
+
self
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module SensuGenerator
|
2
|
+
%w(ApplicationError RestarterError GeneratorError SensuServerError ClientError ServerError).each do |e|
|
3
|
+
eval(
|
4
|
+
%Q(
|
5
|
+
class #{e} < StandardError
|
6
|
+
def initialize(msg)
|
7
|
+
Application.logger.error msg
|
8
|
+
end
|
9
|
+
end
|
10
|
+
)
|
11
|
+
)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
module Diplomat
|
16
|
+
class PathNotFound < StandardError
|
17
|
+
def initialize(*args)
|
18
|
+
::SensuGenerator::Application.logger.error "Could not connect to consul with provided url"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|