adminix 0.1.13 → 0.1.14
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 +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
|