adminix 0.1.13 → 0.1.14
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.byebug_history +25 -25
- data/adminix.gemspec +2 -1
- data/exe/adminix +9 -48
- data/lib/adminix/.service.rb.swn +0 -0
- data/lib/adminix/config.rb +6 -122
- data/lib/adminix/service.rb +38 -112
- data/lib/adminix/version.rb +1 -1
- data/lib/adminix/watcher.rb +134 -12
- data/lib/adminix/websocket_client.rb +84 -0
- data/lib/adminix.rb +1 -1
- metadata +21 -6
- data/lib/adminix/entrypoint.rb +0 -68
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 95a49d190d16c14ccd3cccc09e06732568f0e9cd
|
4
|
+
data.tar.gz: 5a2e0e20318f38da17a6e4b118ead094c3ae97a3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9452e2d00bfd6e3ac1aafc78a0293d021050e3018f71dfbe183450ce9a169ec701631c7ad43936a9b747952488ae286a11fb99b0f5d51fc523c1850a1514c559
|
7
|
+
data.tar.gz: f1731de81b7c47a8ad54b841496e188a86535e66f2f35bd29530c725809a95596911cb4dd31c87bd6a60c3ea3a2d9dfd30e6b5e89fc02c1d9980b3efc51e5d4b
|
data/.byebug_history
CHANGED
@@ -1,4 +1,29 @@
|
|
1
1
|
q
|
2
|
+
options
|
3
|
+
options[:action].to_sym
|
4
|
+
parsers[options[:action].to_sym]
|
5
|
+
q
|
6
|
+
parsers[options[:action].to_sym]
|
7
|
+
parsers[:watch]
|
8
|
+
parsers
|
9
|
+
q
|
10
|
+
options
|
11
|
+
q
|
12
|
+
data["id"]
|
13
|
+
data
|
14
|
+
type
|
15
|
+
q
|
16
|
+
message['type']
|
17
|
+
message
|
18
|
+
q
|
19
|
+
message
|
20
|
+
q
|
21
|
+
data["name"]
|
22
|
+
data
|
23
|
+
q
|
24
|
+
response.body
|
25
|
+
data
|
26
|
+
q
|
2
27
|
System.instance.eval(script)
|
3
28
|
script
|
4
29
|
args['args'].each { |hs| script.gsub!("%{#{hs[0]}}", hs[1]) }
|
@@ -229,28 +254,3 @@ service_name
|
|
229
254
|
q
|
230
255
|
service_name
|
231
256
|
self.service_name = hs['service_name']
|
232
|
-
self.service_name
|
233
|
-
hs
|
234
|
-
q
|
235
|
-
hs['service_name']
|
236
|
-
hs = JSON.parse(content)
|
237
|
-
q
|
238
|
-
generate_fake_config_file
|
239
|
-
q
|
240
|
-
generate_fake_config_file
|
241
|
-
q
|
242
|
-
rand(1..10000)
|
243
|
-
1..10000.rand
|
244
|
-
(1..10000).rand
|
245
|
-
Faker::Internet.email(name)
|
246
|
-
name.sub
|
247
|
-
name.join('.')
|
248
|
-
name = Faker::Name.name
|
249
|
-
name = Faker::Name.namename = Faker::Name.name
|
250
|
-
name = Faker::Name.name
|
251
|
-
Faker::Internet.email('chris')
|
252
|
-
Faker::Internet.email
|
253
|
-
q
|
254
|
-
require 'faker'
|
255
|
-
Faker
|
256
|
-
q
|
data/adminix.gemspec
CHANGED
@@ -32,7 +32,8 @@ Gem::Specification.new do |spec|
|
|
32
32
|
|
33
33
|
#spec.add_dependency "daemons", "~> 1.2.4"
|
34
34
|
#spec.add_dependency "action_cable_client", "~> 1.3", ">= 1.3.4"
|
35
|
-
spec.add_dependency "eventmachine", "1.2.
|
35
|
+
spec.add_dependency "eventmachine", "1.2.3"
|
36
|
+
spec.add_dependency "em-websocket-client", "0.1.2"
|
36
37
|
|
37
38
|
spec.add_development_dependency "bundler", "~> 1.14"
|
38
39
|
spec.add_development_dependency "rake", "~> 10.0"
|
data/exe/adminix
CHANGED
@@ -3,7 +3,11 @@
|
|
3
3
|
|
4
4
|
require 'optparse'
|
5
5
|
|
6
|
-
options = {
|
6
|
+
options = {
|
7
|
+
action: "help",
|
8
|
+
daemonize: false,
|
9
|
+
stop_daemon: false
|
10
|
+
}
|
7
11
|
parsers = {}
|
8
12
|
|
9
13
|
parsers[:env] = OptionParser.new do |opts|
|
@@ -15,21 +19,10 @@ end
|
|
15
19
|
parsers[:watch] = OptionParser.new do |opts|
|
16
20
|
opts.banner = "Launch Adminix watcher"
|
17
21
|
opts.separator " Usage: adminix watch"
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
opts.
|
22
|
-
end
|
23
|
-
|
24
|
-
parsers[:generate_daemon] = OptionParser.new do |opts|
|
25
|
-
opts.banner = "Generate upstart script for watcher"
|
26
|
-
opts.separator " Usage: adminix generate_daemon"
|
27
|
-
opts.separator ""
|
28
|
-
end
|
29
|
-
|
30
|
-
parsers[:setup] = OptionParser.new do |opts|
|
31
|
-
opts.banner = "Generage adminix.json"
|
32
|
-
opts.separator " Usage: adminix setup"
|
22
|
+
opts.separator " Usage: adminix watch [options]"
|
23
|
+
opts.separator " Options:"
|
24
|
+
opts.on("-d", "--daemonize", "run watcher in background process") { options[:daemonize] = true }
|
25
|
+
opts.on("-s", "--stop-daemon", "stop daemon watcher") { options[:stop_daemon] = true }
|
33
26
|
opts.separator ""
|
34
27
|
end
|
35
28
|
|
@@ -49,38 +42,6 @@ case options[:action]
|
|
49
42
|
puts Adminix::Service.instance.options_to_envs
|
50
43
|
when "watch"
|
51
44
|
puts Adminix::Watcher.run!(options)
|
52
|
-
when "generate_daemon"
|
53
|
-
path = Adminix::System.instance.generate_daemon
|
54
|
-
puts "# Daemon has been generated in path #{path}\n" +
|
55
|
-
"# Please execute this command to copy adminix.conf to /etc/init folder:\n" +
|
56
|
-
"sudo mv adminix.conf /etc/init/adminix.conf\n"
|
57
|
-
|
58
|
-
when "setup"
|
59
|
-
approved = true
|
60
|
-
if Adminix::Config.instance.file_exists?
|
61
|
-
puts "File \"#{ENV['HOME']}/.adminix.json\" already exists, overwrite config (yes/no):"
|
62
|
-
approved = ['yes', 'y'].include?($stdin.gets.chomp)
|
63
|
-
end
|
64
|
-
|
65
|
-
if approved
|
66
|
-
puts "Enter secret key:"
|
67
|
-
secret_key = $stdin.gets.chomp
|
68
|
-
|
69
|
-
puts "Enter service id (empty to create a new service)"
|
70
|
-
service_id = $stdin.gets.chomp
|
71
|
-
|
72
|
-
service_name = ''
|
73
|
-
if service_id == ''
|
74
|
-
puts "Enter service name"
|
75
|
-
service_name = $stdin.gets.chomp
|
76
|
-
end
|
77
|
-
|
78
|
-
Adminix::Config.setup(
|
79
|
-
secret_key: secret_key,
|
80
|
-
service_id: service_id,
|
81
|
-
service_name: service_name
|
82
|
-
)
|
83
|
-
end
|
84
45
|
when "version"
|
85
46
|
puts "adminix version #{Adminix::VERSION}"
|
86
47
|
else
|
Binary file
|
data/lib/adminix/config.rb
CHANGED
@@ -1,5 +1,4 @@
|
|
1
1
|
require 'singleton'
|
2
|
-
require 'json'
|
3
2
|
|
4
3
|
module Adminix
|
5
4
|
class Config
|
@@ -7,128 +6,13 @@ module Adminix
|
|
7
6
|
|
8
7
|
DEFAULT_HOST = 'http://api.adminix.io'.freeze
|
9
8
|
|
10
|
-
attr_accessor
|
11
|
-
:service_name,
|
12
|
-
:service_id,
|
13
|
-
:service_address,
|
14
|
-
:host,
|
15
|
-
:secret_key,
|
16
|
-
:monitor_logs_paths,
|
17
|
-
:options,
|
18
|
-
:commands
|
19
|
-
)
|
9
|
+
attr_accessor :service_id, :secret_key, :host
|
20
10
|
|
21
|
-
def
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
conf.service_name = opts[:service_name]
|
26
|
-
conf.secret_key = opts[:secret_key] || ENV['ADMINIX_SECRET_KEY']
|
27
|
-
|
28
|
-
conf.export
|
29
|
-
end
|
30
|
-
|
31
|
-
def attributes
|
32
|
-
{
|
33
|
-
service_name: service_name,
|
34
|
-
service_id: service_id,
|
35
|
-
service_address: service_address,
|
36
|
-
secret_key: secret_key,
|
37
|
-
options: options || [],
|
38
|
-
commands: commands || []
|
39
|
-
}
|
40
|
-
end
|
41
|
-
|
42
|
-
def file_exists?
|
43
|
-
File.exists?("#{ENV['HOME']}/.adminix.json")
|
44
|
-
end
|
45
|
-
|
46
|
-
def export(path=nil)
|
47
|
-
file_path = path || "#{ENV['HOME']}/.adminix.json"
|
48
|
-
file_content = JSON.pretty_generate(attributes)
|
49
|
-
File.delete(file_path) if File.exists?(file_path)
|
50
|
-
File.open(file_path, 'w') { |file| file.write(file_content) }
|
51
|
-
end
|
52
|
-
|
53
|
-
def import
|
54
|
-
content = File.read(config_file_path)
|
55
|
-
hs = JSON.parse(content)
|
56
|
-
|
57
|
-
self.service_name = hs['service_name']
|
58
|
-
self.service_id = hs['service_id'] || ENV['ADMINIX_SERVICE_ID']
|
59
|
-
self.service_address = hs['service_address']
|
60
|
-
self.secret_key = hs['secret_key'] || ENV['ADMINIX_SECRET_KEY']
|
61
|
-
self.host = hs['host'] || ENV['ADMINIX_CONFIG_HOST'] || DEFAULT_HOST
|
62
|
-
self.options = hs['options'] || []
|
63
|
-
self.commands = hs['commands'] || []
|
64
|
-
|
65
|
-
valid?
|
66
|
-
end
|
67
|
-
|
68
|
-
def config_file_path
|
69
|
-
return @config_path unless @config_path.nil?
|
70
|
-
|
71
|
-
paths = [
|
72
|
-
"#{ENV['HOME']}/.adminix.json",
|
73
|
-
'.adminix.json'
|
74
|
-
]
|
75
|
-
paths << ENV['ADMINIX_CONFIG_PATH'] if !ENV['ADMINIX_CONFIG_PATH'].nil?
|
76
|
-
|
77
|
-
config_path = nil
|
78
|
-
|
79
|
-
paths.reverse.each do |path|
|
80
|
-
if File.exists?(path)
|
81
|
-
@config_path = path
|
82
|
-
break
|
83
|
-
end
|
84
|
-
end
|
85
|
-
|
86
|
-
@config_path or raise "adminix.json doesn't exists"
|
87
|
-
end
|
88
|
-
|
89
|
-
def valid?
|
90
|
-
errors = {}
|
91
|
-
|
92
|
-
if service_name.nil?
|
93
|
-
errors[:service_name] ||= []
|
94
|
-
errors[:service_name] << "should't be blank"
|
95
|
-
end
|
96
|
-
|
97
|
-
if service_id.nil?
|
98
|
-
errors[:service_id] ||= []
|
99
|
-
errors[:service_id] << "should't be blank"
|
100
|
-
end
|
101
|
-
|
102
|
-
if secret_key.nil?
|
103
|
-
errors[:secret_key] ||= []
|
104
|
-
errors[:secret_key] << "should't be blank"
|
105
|
-
end
|
106
|
-
|
107
|
-
unless monitor_logs_paths.nil?
|
108
|
-
unless monitor_logs_paths.is_a? Array
|
109
|
-
errors[:monitor_logs_paths] << "should be array"
|
110
|
-
end
|
111
|
-
end
|
112
|
-
|
113
|
-
unless options.nil?
|
114
|
-
unless options.is_a? Array
|
115
|
-
errors[:options] << "should be array"
|
116
|
-
end
|
117
|
-
end
|
118
|
-
|
119
|
-
unless commands.nil?
|
120
|
-
unless commands.is_a? Array
|
121
|
-
errors[:commands] << "should be array"
|
122
|
-
end
|
123
|
-
end
|
124
|
-
|
125
|
-
@errors = errors
|
126
|
-
|
127
|
-
errors.count == 0
|
128
|
-
end
|
129
|
-
|
130
|
-
def errors
|
131
|
-
@errors
|
11
|
+
def initialize
|
12
|
+
self.service_id = ENV['ADMINIX_SERVICE_ID']
|
13
|
+
self.secret_key = ENV['ADMINIX_SECRET_KEY']
|
14
|
+
self.host = ENV['ADMINIX_CONFIG_HOST'] || DEFAULT_HOST
|
132
15
|
end
|
133
16
|
end
|
134
17
|
end
|
18
|
+
|
data/lib/adminix/service.rb
CHANGED
@@ -1,132 +1,38 @@
|
|
1
1
|
require 'singleton'
|
2
|
-
require 'json'
|
3
|
-
require 'net/http'
|
4
2
|
|
5
3
|
module Adminix
|
6
4
|
class Service
|
7
5
|
include Singleton
|
8
6
|
|
9
|
-
|
7
|
+
attr_reader :id, :process_id
|
10
8
|
|
11
9
|
def initialize
|
12
|
-
config.
|
13
|
-
|
14
|
-
self.id = config.service_id
|
15
|
-
self.name = config.service_name
|
16
|
-
self.address = config.service_address
|
17
|
-
self.completed_commands = []
|
10
|
+
@id = config.service_id
|
18
11
|
end
|
19
12
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
payload = {
|
28
|
-
service: {
|
29
|
-
id: id,
|
30
|
-
process_id: process_id,
|
31
|
-
completed_commands: completed_commands
|
13
|
+
def to_cable
|
14
|
+
{
|
15
|
+
id: id,
|
16
|
+
process_id: process_id,
|
17
|
+
system: {
|
18
|
+
processor_load: system.processor_load,
|
19
|
+
memory_load: system.memory_load
|
32
20
|
}
|
33
21
|
}
|
22
|
+
end
|
34
23
|
|
35
|
-
|
36
|
-
|
37
|
-
payload[:service][:address] = address
|
38
|
-
payload[:service][:options] = service_options_payload
|
39
|
-
payload[:service][:commands] = service_commands_payload
|
40
|
-
end
|
41
|
-
|
42
|
-
request.body = payload.to_json
|
43
|
-
req_options = {}
|
44
|
-
response = Net::HTTP.start(uri.hostname, uri.port, req_options) do |http|
|
45
|
-
http.request(request)
|
46
|
-
end
|
47
|
-
data = JSON.parse(response.body)['result']
|
48
|
-
|
49
|
-
self.completed_commands = []
|
50
|
-
self.process_id = data['process_id']
|
51
|
-
|
52
|
-
if id.nil?
|
53
|
-
self.id = data['id']
|
54
|
-
config.service_id = id
|
55
|
-
config.export
|
56
|
-
end
|
24
|
+
def sync(watcher, data)
|
25
|
+
@process_id = data['process_id']
|
57
26
|
|
58
27
|
commands_queue = data['commands_queue'] || []
|
59
28
|
commands_queue.each do |q|
|
60
29
|
if q['status'] != 'processed'
|
61
|
-
execute_command(q['command_key'], q['process_id'], q['args'] || {})
|
30
|
+
res = execute_command(q['command_key'], q['process_id'], q['args'] || {})
|
31
|
+
watcher.publish_message(:task_completed, res)
|
62
32
|
end
|
63
33
|
end
|
64
34
|
end
|
65
35
|
|
66
|
-
def run_cmd(cmd)
|
67
|
-
`#{cmd}`
|
68
|
-
end
|
69
|
-
|
70
|
-
def config
|
71
|
-
Config.instance
|
72
|
-
end
|
73
|
-
|
74
|
-
def service_options_payload
|
75
|
-
config.options.map do |o|
|
76
|
-
{
|
77
|
-
key: o['key'],
|
78
|
-
name: o['name'],
|
79
|
-
description: o['description'],
|
80
|
-
value_type: o['type'],
|
81
|
-
options: o['options'],
|
82
|
-
validations: o['validations'],
|
83
|
-
default_value: o['default_value'],
|
84
|
-
value: o['default_value']
|
85
|
-
}
|
86
|
-
end
|
87
|
-
end
|
88
|
-
|
89
|
-
def service_commands_payload
|
90
|
-
config.commands.map do |o|
|
91
|
-
{
|
92
|
-
key: o['key'],
|
93
|
-
name: o['name'],
|
94
|
-
description: o['description'],
|
95
|
-
#command: o['command'],
|
96
|
-
arguments: o['arguments']
|
97
|
-
}
|
98
|
-
end
|
99
|
-
end
|
100
|
-
|
101
|
-
def execute_command(key, process_id, args)
|
102
|
-
command = config.commands.find { |c| c['key'] == key }
|
103
|
-
script = command['command'].dup
|
104
|
-
|
105
|
-
# TODO frontend fix attribute args
|
106
|
-
args['args'].each { |hs| script.gsub!("%{#{hs[0]}}", hs[1]) }
|
107
|
-
|
108
|
-
puts System.instance.eval(script)
|
109
|
-
|
110
|
-
#self.completed_commands << process_id
|
111
|
-
|
112
|
-
uri = URI.parse("#{config.host}/v1/services/#{id}")
|
113
|
-
request = Net::HTTP::Put.new(uri)
|
114
|
-
request.content_type = "application/json"
|
115
|
-
request["Authorization"] = "Bearer #{config.secret_key}"
|
116
|
-
|
117
|
-
payload = {
|
118
|
-
service: {
|
119
|
-
completed_command_process_id: process_id
|
120
|
-
}
|
121
|
-
}
|
122
|
-
request.body = payload.to_json
|
123
|
-
req_options = {}
|
124
|
-
response = Net::HTTP.start(uri.hostname, uri.port, req_options) do |http|
|
125
|
-
http.request(request)
|
126
|
-
end
|
127
|
-
data = JSON.parse(response.body)['result']
|
128
|
-
end
|
129
|
-
|
130
36
|
def options_to_envs
|
131
37
|
uri = URI.parse("#{config.host}/v1/services/#{id}/options")
|
132
38
|
request = Net::HTTP::Get.new(uri)
|
@@ -145,10 +51,30 @@ module Adminix
|
|
145
51
|
"# eval $(adminix env)"
|
146
52
|
end
|
147
53
|
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
54
|
+
private
|
55
|
+
|
56
|
+
def config
|
57
|
+
Config.instance
|
58
|
+
end
|
59
|
+
|
60
|
+
def system
|
61
|
+
System.instance
|
62
|
+
end
|
63
|
+
|
64
|
+
def execute_command(key, process_id, args)
|
65
|
+
command = config.commands.find { |c| c['key'] == key }
|
66
|
+
script = command['command'].dup
|
67
|
+
|
68
|
+
# TODO frontend fix attribute args
|
69
|
+
args['args'].each { |hs| script.gsub!("%{#{hs[0]}}", hs[1]) }
|
70
|
+
|
71
|
+
output = system.eval(script)
|
72
|
+
|
73
|
+
{
|
74
|
+
id: process_id,
|
75
|
+
success: true,
|
76
|
+
output: output
|
77
|
+
}
|
152
78
|
end
|
153
79
|
end
|
154
80
|
end
|
data/lib/adminix/version.rb
CHANGED
data/lib/adminix/watcher.rb
CHANGED
@@ -1,34 +1,156 @@
|
|
1
1
|
require "eventmachine"
|
2
|
+
require "em-websocket-client"
|
2
3
|
|
3
4
|
module Adminix
|
4
5
|
class Watcher
|
5
6
|
def self.run!(options)
|
6
|
-
Watcher.new(options)
|
7
|
-
end
|
7
|
+
watcher = Watcher.new(options)
|
8
8
|
|
9
|
-
|
9
|
+
if options[:stop_daemon]
|
10
|
+
watcher.stop
|
11
|
+
else
|
12
|
+
if options[:daemonize]
|
13
|
+
watcher.start
|
14
|
+
else
|
15
|
+
watcher.run!
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
10
19
|
|
11
|
-
|
20
|
+
SYNC_PERIOD = 5.freeze
|
21
|
+
WEBSOCKET_HOST = 'ws://api.adminix.io/websocket'.freeze
|
22
|
+
SERVICE_CHANNEL = 'ServiceChannel'.freeze
|
12
23
|
|
13
24
|
def initialize(opts)
|
14
|
-
@
|
25
|
+
@socket_url = opts[:websocket_host] || ENV['ADMINIX_WEBSOCKET_HOST'] || WEBSOCKET_HOST
|
26
|
+
@socket_url = "#{@socket_url}?secret_key=#{config.secret_key}"
|
15
27
|
@service = Service.instance
|
28
|
+
@client = nil
|
29
|
+
@pid_full = '/tmp/adminix.pid'
|
16
30
|
end
|
17
31
|
|
18
32
|
def run!
|
19
33
|
trap_signal
|
20
|
-
|
34
|
+
|
21
35
|
EventMachine.run do
|
22
|
-
|
23
|
-
|
36
|
+
@client = WebsocketClient.new(@socket_url) do
|
37
|
+
on_disconnect(@client)
|
24
38
|
end
|
39
|
+
|
40
|
+
@client.connect do |message|
|
41
|
+
puts message
|
42
|
+
on_message_receive(@client, message)
|
43
|
+
end
|
44
|
+
|
45
|
+
EventMachine.add_periodic_timer(SYNC_PERIOD) do
|
46
|
+
publish_message(:sync, @service.to_cable) if @client.connected
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def publish_message(action, data)
|
52
|
+
identifier = { channel: SERVICE_CHANNEL, service_id: @service.id }
|
53
|
+
data = { action: action, data: data }
|
54
|
+
|
55
|
+
@client.publish(identifier, data)
|
56
|
+
end
|
57
|
+
|
58
|
+
def get_pid
|
59
|
+
if File.exists?(@pid_full)
|
60
|
+
file = File.new(@pid_full, "r")
|
61
|
+
pid = file.read
|
62
|
+
file.close
|
63
|
+
|
64
|
+
pid
|
65
|
+
else
|
66
|
+
0
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def start
|
71
|
+
pid = get_pid
|
72
|
+
if pid != 0
|
73
|
+
warn "Daemon is already running"
|
74
|
+
exit -1
|
75
|
+
end
|
76
|
+
|
77
|
+
pid = fork {
|
78
|
+
run!
|
79
|
+
}
|
80
|
+
begin
|
81
|
+
file = File.new(@pid_full, "w")
|
82
|
+
file.write(pid)
|
83
|
+
file.close
|
84
|
+
Process.detach(pid)
|
85
|
+
rescue => exc
|
86
|
+
Process.kill('TERM', pid)
|
87
|
+
warn "Cannot start daemon: #{exc.message}"
|
25
88
|
end
|
26
89
|
end
|
27
90
|
|
28
|
-
def
|
29
|
-
|
30
|
-
|
31
|
-
|
91
|
+
def stop
|
92
|
+
pid = get_pid
|
93
|
+
begin
|
94
|
+
EM.stop
|
95
|
+
rescue
|
96
|
+
end
|
97
|
+
|
98
|
+
if pid != 0
|
99
|
+
Process.kill('HUP', pid.to_i)
|
100
|
+
File.delete(@pid_full)
|
101
|
+
puts "Stopped"
|
102
|
+
else
|
103
|
+
warn "Daemon is not running"
|
104
|
+
exit -1
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
private
|
109
|
+
|
110
|
+
def config
|
111
|
+
Config.instance
|
112
|
+
end
|
113
|
+
|
114
|
+
def on_message_receive(client, message)
|
115
|
+
case message['type']
|
116
|
+
when 'welcome'
|
117
|
+
puts 'connected to server'
|
118
|
+
on_success_connect(client)
|
119
|
+
when 'ping'
|
120
|
+
puts 'ping from server'
|
121
|
+
# do something
|
122
|
+
else
|
123
|
+
# do something
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
def on_disconnect(client)
|
128
|
+
puts 'Disconnected. Reconnecting...'
|
129
|
+
client.connect do |message|
|
130
|
+
puts message
|
131
|
+
on_message_receive(client, message)
|
132
|
+
end
|
133
|
+
|
134
|
+
#EventMachine.stop_event_loop
|
135
|
+
end
|
136
|
+
|
137
|
+
def on_success_connect(client)
|
138
|
+
client.subscribe(channel: SERVICE_CHANNEL, service_id: @service.id) do |message|
|
139
|
+
type = message['type'] || message['message']['type']
|
140
|
+
data = message['message']['data'] rescue {}
|
141
|
+
on_service_message_receive(type, data)
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
def on_service_message_receive(type, data)
|
146
|
+
puts 'on_service_message_receive'
|
147
|
+
puts type
|
148
|
+
puts data
|
149
|
+
case type
|
150
|
+
when 'confirm_subscription'
|
151
|
+
when 'sync'
|
152
|
+
@service.sync(self, data)
|
153
|
+
end
|
32
154
|
end
|
33
155
|
|
34
156
|
def trap_signal
|
@@ -0,0 +1,84 @@
|
|
1
|
+
require 'json'
|
2
|
+
|
3
|
+
module Adminix
|
4
|
+
class WebsocketClient
|
5
|
+
attr_accessor :client
|
6
|
+
attr_accessor :connected
|
7
|
+
attr_accessor :connection_handler
|
8
|
+
attr_accessor :channel_handlers
|
9
|
+
attr_accessor :disconnect_handler
|
10
|
+
attr_accessor :url
|
11
|
+
|
12
|
+
def initialize(url, &disconnect_handler)
|
13
|
+
self.url = url
|
14
|
+
self.disconnect_handler = disconnect_handler
|
15
|
+
end
|
16
|
+
|
17
|
+
def connect(&block)
|
18
|
+
self.connection_handler = block
|
19
|
+
self.channel_handlers = {}
|
20
|
+
self.client = EventMachine::WebSocketClient.connect(url)
|
21
|
+
client.callback do
|
22
|
+
puts "Connected WebSocket to #{url}."
|
23
|
+
self.connected = true
|
24
|
+
end
|
25
|
+
client.stream do |raw|
|
26
|
+
message = parse_message(raw.to_s)
|
27
|
+
if message['identifier']
|
28
|
+
channel_handlers[message['identifier'].to_json].call(message)
|
29
|
+
else
|
30
|
+
connection_handler.call(message)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
client.disconnect do
|
34
|
+
self.connected = false
|
35
|
+
disconnect_handler.call
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def subscribe(identifier, &block)
|
40
|
+
push(create_subscribe_message(identifier))
|
41
|
+
channel_handlers[identifier.to_json] = block
|
42
|
+
end
|
43
|
+
|
44
|
+
def push(msg)
|
45
|
+
client.send_msg(msg)
|
46
|
+
end
|
47
|
+
|
48
|
+
def publish(identifier, data)
|
49
|
+
msg = create_publish_message(identifier, data)
|
50
|
+
# puts "PUSHING: #{msg}"
|
51
|
+
push(msg)
|
52
|
+
end
|
53
|
+
|
54
|
+
def create_publish_message(identifier, data)
|
55
|
+
message = {
|
56
|
+
command: 'message',
|
57
|
+
identifier: identifier
|
58
|
+
}
|
59
|
+
message[:data] = data.to_json if data
|
60
|
+
message[:identifier] = message[:identifier].to_json
|
61
|
+
message.to_json
|
62
|
+
end
|
63
|
+
|
64
|
+
def create_subscribe_message(identifier)
|
65
|
+
message = {
|
66
|
+
command: 'subscribe',
|
67
|
+
identifier: identifier.to_json
|
68
|
+
}
|
69
|
+
# message[:identifier].merge!(data) if data
|
70
|
+
# message[:data] = data.to_json if data
|
71
|
+
# message[:identifier] = message[:identifier].to_json
|
72
|
+
# puts message
|
73
|
+
message.to_json
|
74
|
+
end
|
75
|
+
|
76
|
+
def parse_message(message)
|
77
|
+
result = JSON.parse(message)
|
78
|
+
result['identifier'] = JSON.parse(result['identifier']) if result['identifier']
|
79
|
+
result['data'] = JSON.parse(result['data']) if result['data']
|
80
|
+
result
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
data/lib/adminix.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: adminix
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.14
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Christian Dyl
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-03-
|
11
|
+
date: 2017-03-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: eventmachine
|
@@ -16,14 +16,28 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - '='
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: 1.2.
|
19
|
+
version: 1.2.3
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - '='
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: 1.2.
|
26
|
+
version: 1.2.3
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: em-websocket-client
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - '='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 0.1.2
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - '='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 0.1.2
|
27
41
|
- !ruby/object:Gem::Dependency
|
28
42
|
name: bundler
|
29
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -128,12 +142,13 @@ files:
|
|
128
142
|
- bin/setup
|
129
143
|
- exe/adminix
|
130
144
|
- lib/adminix.rb
|
145
|
+
- lib/adminix/.service.rb.swn
|
131
146
|
- lib/adminix/config.rb
|
132
|
-
- lib/adminix/entrypoint.rb
|
133
147
|
- lib/adminix/service.rb
|
134
148
|
- lib/adminix/system.rb
|
135
149
|
- lib/adminix/version.rb
|
136
150
|
- lib/adminix/watcher.rb
|
151
|
+
- lib/adminix/websocket_client.rb
|
137
152
|
- views/daemon_scripts/upstart.conf.erb
|
138
153
|
homepage: http://adminix.io
|
139
154
|
licenses:
|
@@ -155,7 +170,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
155
170
|
version: '0'
|
156
171
|
requirements: []
|
157
172
|
rubyforge_project:
|
158
|
-
rubygems_version: 2.
|
173
|
+
rubygems_version: 2.6.10
|
159
174
|
signing_key:
|
160
175
|
specification_version: 4
|
161
176
|
summary: Adminix
|
data/lib/adminix/entrypoint.rb
DELETED
@@ -1,68 +0,0 @@
|
|
1
|
-
module Adminix
|
2
|
-
class Entrypoint
|
3
|
-
def self.execute_action(args)
|
4
|
-
action = args[0]
|
5
|
-
case action
|
6
|
-
when 'help' then action_help
|
7
|
-
when 'setup' then action_setup
|
8
|
-
when 'env' then action_env
|
9
|
-
when 'watcher' then action_watcher
|
10
|
-
when 'version' then action_version
|
11
|
-
end
|
12
|
-
end
|
13
|
-
|
14
|
-
def self.action_help
|
15
|
-
puts "Usage: adminix COMMAND\n\n" +
|
16
|
-
"Create and manage Adminix services\n\n" +
|
17
|
-
"Version: #{VERSION}\n\n" +
|
18
|
-
"Author:\n" +
|
19
|
-
" Christian Dyl\n\n" +
|
20
|
-
"Commands:\n" +
|
21
|
-
" env Display the commands to define ENV variables\n" +
|
22
|
-
" watcher Launch Adminix watcher\n" +
|
23
|
-
" setup Generage adminix.json\n" +
|
24
|
-
" version Show the Adminix version"
|
25
|
-
end
|
26
|
-
|
27
|
-
def self.action_setup
|
28
|
-
if Config.instance.file_exists?
|
29
|
-
puts "File \"#{ENV['HOME']}/.adminix.json\" already exists, overwrite config (yes/no):"
|
30
|
-
return unless ['yes', 'y'].include?($stdin.gets.chomp)
|
31
|
-
end
|
32
|
-
|
33
|
-
puts "Enter secret key:"
|
34
|
-
secret_key = $stdin.gets.chomp
|
35
|
-
|
36
|
-
puts "Enter service id (empty to create a new service)"
|
37
|
-
service_id = $stdin.gets.chomp
|
38
|
-
|
39
|
-
service_name = ''
|
40
|
-
if service_id == ''
|
41
|
-
puts "Enter service name"
|
42
|
-
service_name = $stdin.gets.chomp
|
43
|
-
end
|
44
|
-
|
45
|
-
Config.setup(
|
46
|
-
secret_key: secret_key,
|
47
|
-
service_id: service_id,
|
48
|
-
service_name: service_name
|
49
|
-
)
|
50
|
-
end
|
51
|
-
|
52
|
-
def self.action_env
|
53
|
-
Service.instance.options_to_envs
|
54
|
-
end
|
55
|
-
|
56
|
-
def self.action_watcher
|
57
|
-
Service.instance.sync
|
58
|
-
#watcher = Watcher.new
|
59
|
-
#watcher.start
|
60
|
-
|
61
|
-
#watcher
|
62
|
-
end
|
63
|
-
|
64
|
-
def self.action_version
|
65
|
-
puts "The current version is #{VERSION}"
|
66
|
-
end
|
67
|
-
end
|
68
|
-
end
|