kldockeragent 0.5.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 +7 -0
- data/.gitignore +2 -0
- data/Rakefile +0 -0
- data/VERSION +1 -0
- data/bin/kldockeragent +41 -0
- data/kldockeragent.gemspec +14 -0
- data/lib/kldockeragent/agent.rb +151 -0
- data/lib/kldockeragent/api.rb +51 -0
- data/lib/kldockeragent/commands.rb +34 -0
- data/lib/kldockeragent/helper.rb +154 -0
- data/lib/kldockeragent/net.rb +23 -0
- data/lib/kldockeragent/notifier.rb +106 -0
- data/lib/kldockeragent/server.rb +43 -0
- data/lib/kldockeragent.rb +17 -0
- metadata +57 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 8c505ae9e35342dd34f178dec5018675e204693b
|
4
|
+
data.tar.gz: 3853d4786fe5aadf6f631cd5cc461b7c8c5a27ee
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 2854427e5768d19dfc27896c8dea49745f81420479cc0ac7cb18003f1a831b2a63d9cb6fd2180df41fc0450274aeb6d441db43503512bb92b469af519f83e411
|
7
|
+
data.tar.gz: 652d7b08dbe57af4e2f0e272937eed0b29a9c6a80eb07669359a6082ed8b844fbaf70c1f481ce2f5cd45d73290cf9f77bf6fb137dcc82201113fad79bcf5421e
|
data/.gitignore
ADDED
data/Rakefile
ADDED
File without changes
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.5.0
|
data/bin/kldockeragent
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require File.dirname(__FILE__) + '/../lib/kldockeragent'
|
4
|
+
|
5
|
+
def version?
|
6
|
+
File.read(File.dirname(__FILE__) + '/../VERSION').strip
|
7
|
+
end
|
8
|
+
|
9
|
+
opts = Trollop::options do
|
10
|
+
version "kldockeragent #{version?} (c) 2016 Kytoonlabs"
|
11
|
+
banner <<-EOS
|
12
|
+
Agent for KL Docker Agent configuration management tool.
|
13
|
+
Usage:
|
14
|
+
kldockeragent [options]
|
15
|
+
|
16
|
+
where [options] are:
|
17
|
+
EOS
|
18
|
+
opt :start, "Start the agent. If --daemon option is set true, then the agent will start as a daemon.", :short => '-s'
|
19
|
+
opt :stop, "Stop the daemon agent.", :short => '-t'
|
20
|
+
opt :restart, "Restart the daemon agent.", :short => '-r'
|
21
|
+
opt :status, "Print the status of the daemon agent.", :short => '-a'
|
22
|
+
end
|
23
|
+
|
24
|
+
if opts[:start]
|
25
|
+
if not KL::Agent.pid.nil?
|
26
|
+
puts "Agent is already running with PID #{KL::Agent.pid}"
|
27
|
+
else
|
28
|
+
opts[:daemon] = true
|
29
|
+
KL::Agent.start(opts)
|
30
|
+
end
|
31
|
+
elsif opts[:stop]
|
32
|
+
KL::Agent.stop(opts)
|
33
|
+
elsif opts[:restart]
|
34
|
+
KL.logger.info '[main] Restart Agent command detected.'
|
35
|
+
opts[:daemon] = true
|
36
|
+
KL::Agent.stop if KL::Agent.pid.to_i > 0
|
37
|
+
KL::Agent.start(opts)
|
38
|
+
elsif opts[:status]
|
39
|
+
KL::Agent.status
|
40
|
+
end
|
41
|
+
|
@@ -0,0 +1,14 @@
|
|
1
|
+
Gem::Specification.new do |s|
|
2
|
+
s.name = 'kldockeragent'
|
3
|
+
s.version = File.read(File.dirname(__FILE__) + '/VERSION').strip
|
4
|
+
s.date = File.mtime(File.dirname(__FILE__) + '/VERSION').strftime("%Y-%m-%d")
|
5
|
+
s.summary = "KL DockerAgent"
|
6
|
+
s.description = "Agent with REST Api to send information about docker containers"
|
7
|
+
s.authors = ["Kytoonlabs"]
|
8
|
+
s.email = 'admin@kytoonlabs.com'
|
9
|
+
s.homepage = 'https://kytoonlabs.com/tools/docker-agent'
|
10
|
+
s.license = 'MIT'
|
11
|
+
s.require_paths = ['lib']
|
12
|
+
s.executables << 'kldockeragent'
|
13
|
+
s.files = `git ls-files`.split("\n").select { |n| !(n =~ /^(modules|test)\/.*/) }
|
14
|
+
end
|
@@ -0,0 +1,151 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'thread'
|
3
|
+
require 'uri'
|
4
|
+
require 'net/http'
|
5
|
+
require 'logger'
|
6
|
+
require 'json'
|
7
|
+
require 'digest/md5'
|
8
|
+
require 'shellwords'
|
9
|
+
require 'trollop'
|
10
|
+
require 'socket'
|
11
|
+
|
12
|
+
module KL
|
13
|
+
module Agent
|
14
|
+
|
15
|
+
PIDFile = "#{KL.home}/kldockeragent.pid"
|
16
|
+
|
17
|
+
@@notifier_engine = KL::Notifier.new
|
18
|
+
@@web_server = KL::Server.new
|
19
|
+
|
20
|
+
@@global_app_uuid = KL.getApplicationId
|
21
|
+
|
22
|
+
# Start the agent.
|
23
|
+
#
|
24
|
+
# options:
|
25
|
+
# :daemon => true if running as a daemon, false if as a console application
|
26
|
+
# :port => port of web server will listen to
|
27
|
+
# :ssl => set true to enable HTTPS
|
28
|
+
# :certfile => certificate file path for HTTPS
|
29
|
+
# :keyfile => key file path for HTTPS
|
30
|
+
#
|
31
|
+
def self.start(opts={})
|
32
|
+
KL.logger.info "[main] Starting agent: #{KL::Agent.getUUID}"
|
33
|
+
puts "Starting agent..."
|
34
|
+
|
35
|
+
@@config = opts
|
36
|
+
|
37
|
+
Process.daemon if opts[:daemon] and not opts[:mock]
|
38
|
+
begin
|
39
|
+
if not is_windows
|
40
|
+
# trap signal
|
41
|
+
['INT', 'KILL', 'HUP'].each do |signal|
|
42
|
+
trap(signal) {
|
43
|
+
KL.logger.info "[main] Shutting down services..."
|
44
|
+
web_server.stop
|
45
|
+
notifier_engine.stop
|
46
|
+
loop do
|
47
|
+
break if notifier_engine.status == :stopped
|
48
|
+
sleep 1
|
49
|
+
end
|
50
|
+
|
51
|
+
self.close
|
52
|
+
}
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
File.open(PIDFile, 'w', 0644) { |f| f.write($$.to_s) }
|
57
|
+
|
58
|
+
notifier_engine.start
|
59
|
+
web_server.start
|
60
|
+
|
61
|
+
@@main_enabled = true
|
62
|
+
while @@main_enabled; end
|
63
|
+
|
64
|
+
rescue Exception => e
|
65
|
+
KL.logger.error "Starting the agent [Failed] #{e}\n#{e.backtrace.join("\n")}"
|
66
|
+
raise e
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
# Stop the agent's daemon.
|
71
|
+
#
|
72
|
+
def self.stop(opts={})
|
73
|
+
begin
|
74
|
+
pid = File.read(PIDFile).to_i
|
75
|
+
puts "Stopping agent with PID #{pid}..."
|
76
|
+
Process.kill 'HUP', pid
|
77
|
+
|
78
|
+
if not opts[:mock]
|
79
|
+
begin
|
80
|
+
sleep (KL::Notifier::SleepTime + 0.5)
|
81
|
+
|
82
|
+
Process.kill 0, pid
|
83
|
+
KL.logger.info "[main] Agent is still running."
|
84
|
+
puts "Agent is still running."
|
85
|
+
|
86
|
+
KL.logger.info "[main] Killing agent."
|
87
|
+
puts "Killing agent."
|
88
|
+
Process.kill 9, pid
|
89
|
+
rescue
|
90
|
+
KL.logger.info "[main] Agent has stopped."
|
91
|
+
puts "Agent has stopped."
|
92
|
+
File.delete(PIDFile) if File.exist?(PIDFile)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
rescue
|
97
|
+
puts "Agent is not running."
|
98
|
+
File.delete(PIDFile) if File.exist?(PIDFile)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
def self.pid
|
103
|
+
begin
|
104
|
+
pid = File.read(PIDFile).to_i
|
105
|
+
return pid if Process.kill 0, pid
|
106
|
+
rescue
|
107
|
+
end
|
108
|
+
nil
|
109
|
+
end
|
110
|
+
|
111
|
+
# Return agent's PID if it is running, otherwise nil.
|
112
|
+
#
|
113
|
+
def self.status
|
114
|
+
if pid.nil?
|
115
|
+
puts "Agent is not running."
|
116
|
+
else
|
117
|
+
puts "Agent is running with PID #{pid}"
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
def self.is_windows
|
122
|
+
(RbConfig::CONFIG['host_os'] =~ /mswin|mingw|cygwin/)
|
123
|
+
end
|
124
|
+
|
125
|
+
def self.is_linux
|
126
|
+
(RbConfig::CONFIG['host_os'] =~ /linux/)
|
127
|
+
end
|
128
|
+
|
129
|
+
def self.notifier_engine
|
130
|
+
@@notifier_engine
|
131
|
+
end
|
132
|
+
|
133
|
+
def self.web_server
|
134
|
+
@@web_server
|
135
|
+
end
|
136
|
+
|
137
|
+
def self.close
|
138
|
+
KL.logger.info "[main] Stopping agent..."
|
139
|
+
@@main_enabled = false
|
140
|
+
end
|
141
|
+
|
142
|
+
def self.getUUID
|
143
|
+
@@global_app_uuid
|
144
|
+
end
|
145
|
+
|
146
|
+
def self.getVersion
|
147
|
+
File.read(File.dirname(__FILE__) + '/../../VERSION').strip
|
148
|
+
end
|
149
|
+
|
150
|
+
end
|
151
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'sinatra'
|
2
|
+
require 'webrick'
|
3
|
+
require 'webrick/https'
|
4
|
+
require 'webrick/ssl'
|
5
|
+
require 'openssl'
|
6
|
+
require 'json'
|
7
|
+
|
8
|
+
class KL::Api < Sinatra::Base
|
9
|
+
|
10
|
+
before do
|
11
|
+
halt 503 if !KL.server_registered
|
12
|
+
pass if ['ping'].include? request.path_info.split('/')[1]
|
13
|
+
if env['HTTP_AUTHORIZATION'] && env['HTTP_AUTHORIZATION'].split(':').length == 2
|
14
|
+
auth_header = env['HTTP_AUTHORIZATION'].split(':')
|
15
|
+
else
|
16
|
+
halt 401
|
17
|
+
end
|
18
|
+
public_key = auth_header[0]
|
19
|
+
signature = auth_header[1]
|
20
|
+
|
21
|
+
registry = KL.getRegistryData
|
22
|
+
|
23
|
+
halt 403 if public_key != registry['server']
|
24
|
+
|
25
|
+
data = request.path
|
26
|
+
data = "#{data}?#{request.query_string}" if request.query_string != ""
|
27
|
+
|
28
|
+
if ['POST', 'PUT', 'PATCH'].include? request.request_method
|
29
|
+
request.body.rewind
|
30
|
+
data += request.body.read
|
31
|
+
end
|
32
|
+
|
33
|
+
computed_signature = OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new('sha1'), registry['agent'], data)
|
34
|
+
if computed_signature == signature
|
35
|
+
KL.logger.info "[api] #{request.request_method} #{request.path}"
|
36
|
+
pass
|
37
|
+
else
|
38
|
+
halt 403
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
get '/ping' do
|
43
|
+
KL.logger.info "[api] Pong! to #{request.ip}"
|
44
|
+
'Pong: ' + `date`
|
45
|
+
end
|
46
|
+
|
47
|
+
get '/api/v1/applications' do
|
48
|
+
KL.publish_json(KL.Request_getDockerListAllApplications)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module KL
|
2
|
+
def KL.Command_registerNewAgent
|
3
|
+
KL.logger.info '[command] Registering new agent...'
|
4
|
+
agent = KL::Agent.getUUID
|
5
|
+
data = KL.prepare_agent_register_data(agent)
|
6
|
+
uri = "#{KL.config['notifier']['server']}/api/1.0/nodes/register"
|
7
|
+
res = KL.net_post_json(uri, data.to_json)
|
8
|
+
|
9
|
+
if res.is_a?(Net::HTTPSuccess)
|
10
|
+
response = JSON.parse(res.body)
|
11
|
+
registry = {
|
12
|
+
agent: agent,
|
13
|
+
server: response['code']
|
14
|
+
}
|
15
|
+
KL.create_registry_file(registry)
|
16
|
+
KL.logger.info '[command] Agent registration has been completed correctly'
|
17
|
+
else
|
18
|
+
KL.logger.info '[command] An error has occurred trying to register agent.'
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def KL.Command_notifyStatus
|
23
|
+
KL.logger.info '[command] Sending instance update...'
|
24
|
+
data = KL.prepare_agent_data
|
25
|
+
uri = "#{KL.config['notifier']['server']}/api/1.0/nodes/data"
|
26
|
+
headers_auth = KL.getAuthorizationHeaders('/api/1.0/nodes/data', data.to_json)
|
27
|
+
res = KL.net_post_json(uri, data.to_json, headers_auth)
|
28
|
+
if res.is_a?(Net::HTTPSuccess)
|
29
|
+
KL.logger.info '[command] Agent notification successfully executed.'
|
30
|
+
else
|
31
|
+
KL.logger.info '[command] An error has occurred trying to notify update.'
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,154 @@
|
|
1
|
+
require 'webrick'
|
2
|
+
require 'webrick/https'
|
3
|
+
require 'usagewatch'
|
4
|
+
|
5
|
+
module KL
|
6
|
+
def KL.create_default_config(file, logger)
|
7
|
+
File.open(file, File::RDWR|File::CREAT, 0644) { |f|
|
8
|
+
f.flock(File::LOCK_EX)
|
9
|
+
value = '{"api":{"port":3344,"ssl":false},"notifier":{"server":"https://hub.kytoonlabs.com:4444","rate":120}}'
|
10
|
+
f.rewind
|
11
|
+
f.write(value.to_s)
|
12
|
+
f.flush
|
13
|
+
f.truncate(f.pos)
|
14
|
+
}
|
15
|
+
logger.info "[config] Default config file has been created at {#{file}}" if logger
|
16
|
+
end
|
17
|
+
|
18
|
+
def KL.logger
|
19
|
+
home = KL.home
|
20
|
+
Dir.mkdir(home, 0700) if not File.exist?(home)
|
21
|
+
logFile = "#{home}/kldockeragent.log"
|
22
|
+
log = WEBrick::Log.new(logFile, WEBrick::BasicLog::INFO ||
|
23
|
+
WEBrick::BasicLog::ERROR ||
|
24
|
+
WEBrick::BasicLog::FATAL ||
|
25
|
+
WEBrick::BasicLog::WARN)
|
26
|
+
log
|
27
|
+
end
|
28
|
+
|
29
|
+
def KL.home
|
30
|
+
home = ((Process.euid == 0 and File.directory?('/var')) ? '/var/kldockerpagent' : File.expand_path(Dir.home + '/.kldockeragent'))
|
31
|
+
home
|
32
|
+
end
|
33
|
+
|
34
|
+
def KL.config
|
35
|
+
configFile = "#{KL.home}/kldockeragent.json"
|
36
|
+
KL.create_default_config(configFile, KL.logger) if !File.exist?(configFile)
|
37
|
+
config_json = File.read(configFile)
|
38
|
+
config_data = JSON.parse(config_json)
|
39
|
+
config_data
|
40
|
+
end
|
41
|
+
|
42
|
+
def KL.server_registered
|
43
|
+
registryFile = "#{KL.home}/kldockeragent.registry"
|
44
|
+
reg = File.exist?(registryFile)
|
45
|
+
reg
|
46
|
+
end
|
47
|
+
|
48
|
+
def KL.publish_json(json_object, st = 200)
|
49
|
+
status st
|
50
|
+
content_type :json
|
51
|
+
json_object.to_json
|
52
|
+
end
|
53
|
+
def KL.prepare_agent_register_data(hash)
|
54
|
+
data = {
|
55
|
+
private_hash: hash,
|
56
|
+
hostname: `hostname`.gsub("\n",""),
|
57
|
+
system_info: `uname -a`.gsub("\n",""),
|
58
|
+
docker_version: `docker --version`.gsub("\n","").gsub("Docker version ",""),
|
59
|
+
agent_version: KL::Agent.getVersion,
|
60
|
+
ip_address: IPSocket.getaddress(Socket.gethostname)
|
61
|
+
}
|
62
|
+
data
|
63
|
+
end
|
64
|
+
|
65
|
+
def KL.create_registry_file(data)
|
66
|
+
file = "#{KL.home}/kldockeragent.registry"
|
67
|
+
File.open(file, File::RDWR|File::CREAT, 0644) { |f|
|
68
|
+
f.flock(File::LOCK_EX)
|
69
|
+
f.rewind
|
70
|
+
f.write(data.to_json.to_s)
|
71
|
+
f.flush
|
72
|
+
f.truncate(f.pos)
|
73
|
+
}
|
74
|
+
logger.info "[config] Registry config file has been created at {#{file}}" if logger
|
75
|
+
end
|
76
|
+
|
77
|
+
def KL.getRegistryData
|
78
|
+
json_reg = JSON.parse(File.open("#{KL.home}/kldockeragent.registry").read)
|
79
|
+
json_reg
|
80
|
+
end
|
81
|
+
|
82
|
+
def KL.getApplicationId
|
83
|
+
if (KL.server_registered)
|
84
|
+
registry = KL.getRegistryData
|
85
|
+
id = registry['agent']
|
86
|
+
else
|
87
|
+
id = SecureRandom.uuid
|
88
|
+
end
|
89
|
+
id
|
90
|
+
end
|
91
|
+
|
92
|
+
def KL.getAuthorizationHeaders(url, json_data)
|
93
|
+
headers = {}
|
94
|
+
if (KL.server_registered)
|
95
|
+
registry = KL.getRegistryData
|
96
|
+
hash_data = KL.generateHash(url, json_data, registry['agent'])
|
97
|
+
auth_code = "#{registry['server']}:#{hash_data}"
|
98
|
+
headers = {}
|
99
|
+
headers['Authorization'] = auth_code
|
100
|
+
end
|
101
|
+
headers
|
102
|
+
end
|
103
|
+
|
104
|
+
def KL.generateHash(url, json_data, private_key)
|
105
|
+
data = "#{url}#{json_data}"
|
106
|
+
hash_data = OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new('sha1'), private_key, data)
|
107
|
+
hash_data
|
108
|
+
end
|
109
|
+
|
110
|
+
def KL.prepare_agent_data
|
111
|
+
data = {
|
112
|
+
system_info: KL.Request_getSystemInfo,
|
113
|
+
docker_info: KL.Request_getDockerListAllApplications,
|
114
|
+
agent_version: KL::Agent.getVersion
|
115
|
+
}
|
116
|
+
data
|
117
|
+
|
118
|
+
end
|
119
|
+
|
120
|
+
def KL.Request_getDockerListAllApplications
|
121
|
+
filter = '_klac'
|
122
|
+
apps = Array.new
|
123
|
+
query = `docker ps --filter="name=#{filter}" --format="{{.ID}}::{{.Names}}::{{.Status}}::{{.Image}}"`
|
124
|
+
query.gsub!(/\r\n?/, "\n")
|
125
|
+
query.each_line do |line|
|
126
|
+
data = line.split('::')
|
127
|
+
apps.push({
|
128
|
+
'id' => data[0],
|
129
|
+
'name' => data[1].gsub(filter,""),
|
130
|
+
'status'=>data[2],
|
131
|
+
'image'=>data[3].gsub("\n","")
|
132
|
+
})
|
133
|
+
end
|
134
|
+
return apps
|
135
|
+
end
|
136
|
+
|
137
|
+
def KL.Request_getSystemInfo
|
138
|
+
usw = Usagewatch
|
139
|
+
info = {}
|
140
|
+
if KL::Agent.is_linux
|
141
|
+
info['os'] = 'linux'
|
142
|
+
info['diskused'] = usw.uw_diskused
|
143
|
+
info['diskused_perc'] = usw.uw_diskused_perc
|
144
|
+
info['cpuused'] = usw.uw_cpuused
|
145
|
+
info['memused'] = usw.uw_memused
|
146
|
+
info['cputop'] = usw.uw_cputop
|
147
|
+
info['memtop'] = usw.uw_memtop
|
148
|
+
else
|
149
|
+
info['os'] = 'not linux'
|
150
|
+
end
|
151
|
+
info
|
152
|
+
end
|
153
|
+
|
154
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'net/http'
|
2
|
+
|
3
|
+
module KL
|
4
|
+
def KL.net_post_json(url, data, headers = [])
|
5
|
+
KL.logger.info "[net] Posting JSON to #{url} => #{data}"
|
6
|
+
|
7
|
+
uri = URI(url)
|
8
|
+
|
9
|
+
req = Net::HTTP::Post.new(uri)
|
10
|
+
req.content_type = 'application/json'
|
11
|
+
req.body = data
|
12
|
+
req['X-Kytoonlabs-Docker-Agent'] = KL::Agent.getUUID[0..13].gsub(/\s\w+\s*$/, '')
|
13
|
+
headers.each do |key, value|
|
14
|
+
req[key] = value
|
15
|
+
end
|
16
|
+
|
17
|
+
Net::HTTP.start(uri.hostname, uri.port, :use_ssl => uri.scheme == 'https') do |http|
|
18
|
+
@res = http.request req
|
19
|
+
end
|
20
|
+
KL.logger.info "[net] Response Code: #{@res.code}, Response Body: #{@res.body}"
|
21
|
+
@res
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,106 @@
|
|
1
|
+
require 'thread'
|
2
|
+
|
3
|
+
class KL::Notifier
|
4
|
+
|
5
|
+
SleepTime = 10
|
6
|
+
|
7
|
+
NotifierLockFile = "#{KL.home}/notifier.lock.#{Time.now.to_i}"
|
8
|
+
|
9
|
+
attr_reader :enabled, :status, :mode
|
10
|
+
|
11
|
+
def initialize(p={})
|
12
|
+
@lock = Mutex.new
|
13
|
+
@enabled = false
|
14
|
+
@status = :stopped
|
15
|
+
@index = 0
|
16
|
+
config = KL.config
|
17
|
+
@rate = config['notifier']['rate']
|
18
|
+
end
|
19
|
+
|
20
|
+
def stop
|
21
|
+
@enabled = false
|
22
|
+
end
|
23
|
+
|
24
|
+
def start
|
25
|
+
@enabled = true
|
26
|
+
@lock.synchronize {
|
27
|
+
return if @status == :running
|
28
|
+
@status = :running
|
29
|
+
}
|
30
|
+
Thread.new {
|
31
|
+
begin
|
32
|
+
register_notifier_thread(:reset)
|
33
|
+
|
34
|
+
system("rm -f #{KL.home}/operator.*.lock")
|
35
|
+
system("rm -f #{KL.home}/notifier.lock.*")
|
36
|
+
|
37
|
+
KL.logger.info "[notifier] Notifier engine is running"
|
38
|
+
|
39
|
+
self.run_notifier
|
40
|
+
|
41
|
+
File.delete(NotifierLockFile) if File.exist?(NotifierLockFile)
|
42
|
+
KL.logger.info "[notifier] Notifier engine has stopped."
|
43
|
+
|
44
|
+
rescue Exception => exp
|
45
|
+
KL.logger.error "Cannot start notifier engine => #{exp}\n#{exp.backtrace.join("\n")}"
|
46
|
+
end
|
47
|
+
@status = :stopped
|
48
|
+
}
|
49
|
+
end
|
50
|
+
|
51
|
+
def run_notifier
|
52
|
+
KL.logger.info "[notifier] Executing notifier engine every #{@rate} seconds"
|
53
|
+
while @enabled
|
54
|
+
begin
|
55
|
+
wait_for_notifier?
|
56
|
+
|
57
|
+
notify_data
|
58
|
+
|
59
|
+
sleep SleepTime
|
60
|
+
|
61
|
+
rescue Exception => e
|
62
|
+
KL.logger.error "Error on executing notifier \n#{e}\n#{e.backtrace.join("\n")}"
|
63
|
+
sleep SleepTime
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def register_notifier_thread(mode=nil)
|
69
|
+
File.open(NotifierLockFile, File::RDWR|File::CREAT, 0644) { |f|
|
70
|
+
f.flock(File::LOCK_EX)
|
71
|
+
value = (mode == :reset ? 0 : (f.read.to_i + 1))
|
72
|
+
f.rewind
|
73
|
+
f.write(value.to_s)
|
74
|
+
f.flush
|
75
|
+
f.truncate(f.pos)
|
76
|
+
}
|
77
|
+
end
|
78
|
+
|
79
|
+
def wait_for_notifier?
|
80
|
+
total_notifier = 1
|
81
|
+
loop do
|
82
|
+
total_notifier = (File.exist?(NotifierLockFile) ? File.read(NotifierLockFile).to_i : 0)
|
83
|
+
return if total_notifier <= 0 or not @enabled
|
84
|
+
sleep 1
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def notify_data
|
89
|
+
KL.logger.info "[heartbeat]"
|
90
|
+
if KL.server_registered
|
91
|
+
if (@index <= (@rate/SleepTime))
|
92
|
+
@index = @index + 1
|
93
|
+
else
|
94
|
+
@index = 0
|
95
|
+
KL.logger.info "[notifier] Executing notifier..."
|
96
|
+
KL.Command_notifyStatus
|
97
|
+
KL.logger.info "[notifier] Notifier executed."
|
98
|
+
end
|
99
|
+
else
|
100
|
+
KL.logger.info "[notifier] Executing notifier..."
|
101
|
+
KL.Command_registerNewAgent
|
102
|
+
KL.logger.info "[notifier] Notifier executed."
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'webrick'
|
2
|
+
require 'webrick/https'
|
3
|
+
require 'openssl'
|
4
|
+
require 'rack/ssl'
|
5
|
+
|
6
|
+
class KL::Server
|
7
|
+
def initialize
|
8
|
+
@config = KL.config
|
9
|
+
if @config['api']['ssl']
|
10
|
+
options = {
|
11
|
+
:Port => @config['api']['port'],
|
12
|
+
:SSLEnable => true,
|
13
|
+
:SSLVerifyClient => OpenSSL::SSL::VERIFY_NONE,
|
14
|
+
:SSLCertificate => OpenSSL::X509::Certificate.new(File.open(@config['api']['cert']['crt']).read),
|
15
|
+
:SSLPrivateKey => OpenSSL::PKey::RSA.new(File.open(@config['api']['cert']['key']).read),
|
16
|
+
:SSLCertName => [[ "CN", WEBrick::Utils::getservername ]]
|
17
|
+
}
|
18
|
+
else
|
19
|
+
options = {
|
20
|
+
:Port => @config['api']['port'],
|
21
|
+
:SSLEnable => false
|
22
|
+
}
|
23
|
+
end
|
24
|
+
@webrick_options = options
|
25
|
+
@server = ::Rack::Handler::WEBrick
|
26
|
+
end
|
27
|
+
def start
|
28
|
+
KL.logger.info '[server] Starting web server...'
|
29
|
+
Thread.new {
|
30
|
+
@server.run KL::Api, @webrick_options
|
31
|
+
}
|
32
|
+
if (@config['api']['ssl'])
|
33
|
+
msg = "[server] Web server listening on #{@config['api']['port']} with SSL"
|
34
|
+
else
|
35
|
+
msg = "[server] Web server listening on #{@config['api']['port']}"
|
36
|
+
end
|
37
|
+
KL.logger.info msg
|
38
|
+
end
|
39
|
+
def stop
|
40
|
+
@server.shutdown
|
41
|
+
KL.logger.info '[server] Web server has stopped.'
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# external dependencies
|
2
|
+
require 'rubygems'
|
3
|
+
require 'json'
|
4
|
+
|
5
|
+
module KL
|
6
|
+
end
|
7
|
+
|
8
|
+
# internal dependencies
|
9
|
+
libdir = File.expand_path(File.dirname(__FILE__))
|
10
|
+
|
11
|
+
require libdir + '/kldockeragent/net.rb'
|
12
|
+
require libdir + '/kldockeragent/commands.rb'
|
13
|
+
require libdir + '/kldockeragent/helper.rb'
|
14
|
+
require libdir + '/kldockeragent/api.rb'
|
15
|
+
require libdir + '/kldockeragent/server.rb'
|
16
|
+
require libdir + '/kldockeragent/notifier.rb'
|
17
|
+
require libdir + '/kldockeragent/agent.rb'
|
metadata
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: kldockeragent
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.5.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Kytoonlabs
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2016-12-11 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description: Agent with REST Api to send information about docker containers
|
14
|
+
email: admin@kytoonlabs.com
|
15
|
+
executables:
|
16
|
+
- kldockeragent
|
17
|
+
extensions: []
|
18
|
+
extra_rdoc_files: []
|
19
|
+
files:
|
20
|
+
- ".gitignore"
|
21
|
+
- Rakefile
|
22
|
+
- VERSION
|
23
|
+
- bin/kldockeragent
|
24
|
+
- kldockeragent.gemspec
|
25
|
+
- lib/kldockeragent.rb
|
26
|
+
- lib/kldockeragent/agent.rb
|
27
|
+
- lib/kldockeragent/api.rb
|
28
|
+
- lib/kldockeragent/commands.rb
|
29
|
+
- lib/kldockeragent/helper.rb
|
30
|
+
- lib/kldockeragent/net.rb
|
31
|
+
- lib/kldockeragent/notifier.rb
|
32
|
+
- lib/kldockeragent/server.rb
|
33
|
+
homepage: https://kytoonlabs.com/tools/docker-agent
|
34
|
+
licenses:
|
35
|
+
- MIT
|
36
|
+
metadata: {}
|
37
|
+
post_install_message:
|
38
|
+
rdoc_options: []
|
39
|
+
require_paths:
|
40
|
+
- lib
|
41
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
42
|
+
requirements:
|
43
|
+
- - ">="
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
47
|
+
requirements:
|
48
|
+
- - ">="
|
49
|
+
- !ruby/object:Gem::Version
|
50
|
+
version: '0'
|
51
|
+
requirements: []
|
52
|
+
rubyforge_project:
|
53
|
+
rubygems_version: 2.0.14.1
|
54
|
+
signing_key:
|
55
|
+
specification_version: 4
|
56
|
+
summary: KL DockerAgent
|
57
|
+
test_files: []
|