adminix 0.1.24 → 0.1.25

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 323d686c0df911e68419b1d4a094d07517fc1728
4
- data.tar.gz: b0b3a2c75899feceaa21a2e2cab960475293edbf
3
+ metadata.gz: ed51b6024e1e9da59e6f64d6ec5dc5187d59bd46
4
+ data.tar.gz: d595961de804152a6d571b761e749a0a6ef65f14
5
5
  SHA512:
6
- metadata.gz: '061087a77def56a10ad4f6c47284d609da99a36783ab271a57e3f488176470ef170dee6ff14f2faf05b5444d37b7f09034c7f132cc3dcdf571e36862a766005a'
7
- data.tar.gz: 8c803731f17b32992c68714e9675e5611c5d7df6a2e149faf6375add59a8281e455af6f8f2170ab66cb61d08b8af8335e35b391a4dbb7ee883e2e42ac33845ee
6
+ metadata.gz: ca709fe8f560c59566a2046c59d2c0c06c35efe9192b9d94b81a51c4b09d31386688ed56b331716cef6ac4dfdf81f74c9025d7c81dd5191e4ee52711cabbdb92
7
+ data.tar.gz: fce3a9bed9d92d62e6b70e0b8f4b36e417c0a545ab7189585e58fd4d7a6d49637273c2fd71ce5fb97be5535709e3c7178fd3a2c73b069f72b2927ae3c96289bf
data/exe/adminix CHANGED
@@ -48,9 +48,7 @@ unless options[:action] == "help"
48
48
  config.secret_key = options[:secret_key]
49
49
  config.service_id = options[:service_id]
50
50
  config.daemon = options[:daemonize]
51
- if !config.credentials_defined? && config.creds_file_exists?
52
- config.read_creds_file
53
- end
51
+ config.read_local_config
54
52
  end
55
53
 
56
54
  case options[:action]
@@ -6,35 +6,92 @@ module Adminix
6
6
  include Singleton
7
7
 
8
8
  DEFAULT_HOST = 'https://api.adminix.io'.freeze
9
+ DEFAULT_WEBSOCKET_HOST = 'wss://api.adminix.io/websocket'.freeze
9
10
  DEFAULT_SETUP_SERVER_PORT = '8080'
10
11
 
11
- attr_accessor :service_id, :secret_key, :host, :commands, :daemon, :setup_server_port
12
+ attr_accessor :service_id, :secret_key, :host, :commands, :daemon, :setup_server_port, :scripts, :watch_log_files, :watcher_sync_period, :logs_sync_period, :websocket_path, :mode
12
13
 
13
14
  def initialize
14
- self.host = ENV['ADMINIX_HOST'] || DEFAULT_HOST
15
- self.setup_server_port = ENV['ADMINIX_SETUP_SERVER_PORT'] || DEFAULT_SETUP_SERVER_PORT
16
- self.commands = []
15
+ @host = ENV['ADMINIX_HOST'] || DEFAULT_HOST
16
+ @setup_server_port = ENV['ADMINIX_SETUP_SERVER_PORT'] || DEFAULT_SETUP_SERVER_PORT
17
+ @commands = []
18
+ @watcher_sync_period = 10
19
+ @logs_sync_period = 3
20
+ @websocket_path = ENV['ADMINIX_WEBSOCKET_HOST'] || DEFAULT_WEBSOCKET_HOST
21
+ @mode = 'classic'
22
+ @scripts = {
23
+ watcher_start: 'sudo systemctl start adminix.service',
24
+ watcher_stop: 'sudo systemctl stop adminix.service',
25
+ process_start: 'sudo systemctl start adminix_process.service',
26
+ process_stop: 'sudo systemctl stop adminix_process.service'
27
+ }
28
+ @watch_log_files = []
29
+
30
+ @config_store_path = "#{ENV['HOME']}/.config"
31
+ @root_path = "#{@config_store_path}/adminix"
32
+ @creds_path = "#{@root_path}/credentials"
33
+ @config_path = "#{@root_path}/config"
17
34
  end
18
35
 
19
- def read_creds_file
20
- file_content = IO.read("#{ENV['HOME']}/.adminix")
21
- data = JSON.parse(file_content) rescue nil
22
36
 
23
- unless data.nil?
24
- self.service_id ||= data['service_id']
25
- self.secret_key ||= data['secret_key']
37
+ def read_local_config
38
+ if File.exists?(@creds_path)
39
+ content = IO.read(@creds_path)
40
+ data = JSON.parse(content) rescue {}
41
+
42
+ @service_id ||= data['service_id']
43
+ @secret_key ||= data['secret_key']
26
44
  end
27
45
 
28
- true
46
+ if File.exists?(@config_path)
47
+ content = IO.read(@config_path)
48
+ data = JSON.parse(content) rescue {}
49
+
50
+ @mode = data['mode'] || 'classic'
51
+
52
+ scripts = data['scripts'] || {}
53
+ @scripts = {
54
+ watcher_start: scripts['watcher_start'],
55
+ watcher_stop: scripts['watcher_stop'],
56
+ process_start: scripts['process_start'],
57
+ process_stop: scripts['process_stop']
58
+ }
59
+
60
+ @watch_log_files = data['watch_logs'] || []
61
+ end
62
+ end
63
+
64
+ def export_credentials
65
+ create_config_root_if_not_exists
66
+
67
+ open(@creds_path, 'w') do |f|
68
+ f.puts(credentials.to_json)
69
+ end
29
70
  end
30
71
 
31
72
  def creds_file_exists?
32
- File.exists?("#{ENV['HOME']}/.adminix")
73
+ File.exists?(@creds_path)
33
74
  end
34
75
 
35
76
  def credentials_defined?
36
77
  !service_id.nil? && !secret_key.nil?
37
78
  end
79
+
80
+ private
81
+
82
+ def credentials
83
+ { service_id: @service_id, secret_key: @secret_key }
84
+ end
85
+
86
+ def create_config_root_if_not_exists
87
+ unless Dir.exists?(@config_store_path)
88
+ Dir.mkdir(@config_store_path)
89
+ end
90
+
91
+ unless Dir.exists?(@root_path)
92
+ Dir.mkdir(@root_path)
93
+ end
94
+ end
38
95
  end
39
96
  end
40
97
 
@@ -0,0 +1,23 @@
1
+ module Adminix
2
+ module LogWatchHandler
3
+ def file_modified
4
+ #puts "#{path} modified"
5
+ unless Service.instance.syncing_logs
6
+ Service.instance.new_logs = true
7
+ end
8
+ end
9
+
10
+ def file_moved
11
+ #puts "#{path} moved"
12
+ end
13
+
14
+ def file_deleted
15
+ #puts "#{path} deleted"
16
+ end
17
+
18
+ def unbind
19
+ #puts "#{path} monitoring ceased"
20
+ end
21
+ end
22
+ end
23
+
@@ -1,14 +1,18 @@
1
1
  require 'singleton'
2
2
  require 'net/http'
3
-
3
+ require 'byebug'
4
4
  module Adminix
5
5
  class Service
6
6
  include Singleton
7
7
 
8
- attr_reader :id, :process_id
8
+ attr_accessor :new_logs
9
+ attr_reader :id, :process_id, :watching_logs, :syncing_logs
9
10
 
10
11
  def initialize
11
12
  @id = config.service_id
13
+ @watching_logs = []
14
+ @new_logs = false
15
+ @syncing_logs = false
12
16
  end
13
17
 
14
18
  def to_cable
@@ -37,6 +41,30 @@ module Adminix
37
41
  end
38
42
  end
39
43
 
44
+ def sync_logs(ws_client)
45
+ return unless new_logs
46
+
47
+ @syncing_logs = true
48
+
49
+ @watching_logs.each do |l|
50
+ initial_length = l[:lines]
51
+ current_length = file_lines_number(l[:path])
52
+ new_lines = current_length > initial_length ? current_length - initial_length : 100
53
+ lines = `tail -#{new_lines} #{l[:path]}`.split("\n") rescue []
54
+ payload = lines.map { |line| { created_at: Time.now.to_s, level: 'NOTICE', message: line } }
55
+ begin
56
+ puts "Syncing new logs"
57
+ ws_client.perform(:add_logs, { logs: payload }) if ws_client.subscribed?
58
+ rescue
59
+ end
60
+ end
61
+
62
+ count_logs_lines
63
+
64
+ @new_logs = false
65
+ @syncing_logs = false
66
+ end
67
+
40
68
  def options_to_envs
41
69
  data = fetch_options
42
70
 
@@ -60,7 +88,7 @@ module Adminix
60
88
  end
61
89
 
62
90
  def fetch_options
63
- uri = URI.parse("#{config.host}/api/v1/services/#{id}/options")
91
+ uri = URI.parse("#{config.host}/v1/services/#{id}/options")
64
92
  request = Net::HTTP::Get.new(uri)
65
93
  request["Authorization"] = "Bearer #{config.secret_key}"
66
94
 
@@ -72,13 +100,24 @@ module Adminix
72
100
  JSON.parse(response.body)
73
101
  end
74
102
 
103
+ def count_logs_lines
104
+ @watching_logs = config.watch_log_files.map do |file_path|
105
+ { lines: file_lines_number(file_path), path: file_path }
106
+ end
107
+ end
108
+
75
109
  def restart!
76
110
  stop!
77
111
  end
78
112
 
79
113
  def stop!
80
114
  system.log "Stopping process"
81
- Process.kill('INT', 1) rescue nil
115
+ case config.mode
116
+ when 'classic'
117
+ system.eval("#{config.scripts[:watcher_stop]} && #{config.scripts[:watcher_start]}")
118
+ when 'docker'
119
+ Process.kill('INT', 1) rescue nil
120
+ end
82
121
  end
83
122
 
84
123
  private
@@ -91,6 +130,10 @@ module Adminix
91
130
  System.instance
92
131
  end
93
132
 
133
+ def file_lines_number(file_path)
134
+ `wc -l #{file_path}`.to_i
135
+ end
136
+
94
137
  def execute_command(key, process_id, args)
95
138
  command = config.commands.find { |c| c['key'] == key }
96
139
  script = command['command'].dup
@@ -85,6 +85,10 @@ module Adminix::Setup
85
85
  secret_key = Services.get_secret_key(params[:t])
86
86
  if id_is_valid && !secret_key.nil?
87
87
  Services.import_settings(secret_key, params[:id])
88
+ Thread.start do
89
+ sleep(2)
90
+ Adminix::Service.instance.restart!
91
+ end
88
92
  render('complete')
89
93
  else
90
94
  render('error')
@@ -101,7 +105,7 @@ module Adminix::Setup
101
105
  end
102
106
 
103
107
  set :bind, '0.0.0.0'
104
- set :port, Adminix::Config.instance.setup_server_port
108
+ set :port, Adminix::Config::DEFAULT_SETUP_SERVER_PORT
105
109
 
106
110
  run!
107
111
  end
@@ -127,10 +127,11 @@ module Adminix::Setup
127
127
  end
128
128
 
129
129
  def self.import_settings(secret_key, service_id)
130
- open("#{ENV['HOME']}/.adminix", 'w') do |f|
131
- f.puts({ secret_key: secret_key, service_id: service_id }.to_json)
132
- end
133
-
130
+ config = Adminix::Config.instance
131
+ config.service_id = service_id
132
+ config.secret_key = secret_key
133
+ config.export_credentials
134
+
134
135
  true
135
136
  end
136
137
  end
@@ -1,3 +1,3 @@
1
1
  module Adminix
2
- VERSION = "0.1.24"
2
+ VERSION = "0.1.25"
3
3
  end
@@ -13,30 +13,41 @@ module Adminix
13
13
  end
14
14
  end
15
15
 
16
- SYNC_PERIOD = 5.freeze
17
- DEFAULT_WEBSOCKET_HOST = 'wss://api.adminix.io/websocket'.freeze
18
16
  SERVICE_CHANNEL = 'ServiceChannel'.freeze
19
17
 
20
18
  def initialize(opts)
19
+ @sync_period = config.watcher_sync_period
21
20
  @pid_full = '/tmp/adminix.pid'
22
21
  @service = Service.instance
23
22
 
24
23
  @ws_client = nil
25
- ws_path = opts[:websocket_host] || ENV['ADMINIX_WEBSOCKET_HOST'] || DEFAULT_WEBSOCKET_HOST
26
- @ws_uri = "#{ws_path}?secret_key=#{config.secret_key}"
24
+ @ws_uri = "#{config.websocket_path}?secret_key=#{config.secret_key}"
27
25
  @ws_channel = { channel: 'ServiceChannel', service_id: @service.id }
26
+ @ws_logs_channel = { channel: 'LogsChannel', service_id: @service.id }
27
+
28
+ @watching_files = []
29
+
30
+ if EM.epoll?
31
+ EM.epoll
32
+ elsif EM.kqueue?
33
+ EM.kqueue
34
+ else
35
+ Kernel.warn('Neither epoll nor kqueue are supported.')
36
+ end
28
37
  end
29
38
 
30
39
  def run!
31
40
  trap_signal
32
-
41
+
42
+ Adminix::Service.instance.count_logs_lines
43
+
33
44
  EventMachine.run do
34
45
  @ws_client = ActionCableClient.new(@ws_uri, @ws_channel)
35
46
  @ws_client.connected do |msg|
36
- puts 'Connection established'
47
+ puts 'Service connection established'
37
48
  end
38
49
  @ws_client.disconnected do
39
- system.log 'Disconnected. Reconnecting...'
50
+ system.log 'Service disconnected. Reconnecting...'
40
51
  sleep(2)
41
52
  @ws_client.connect!
42
53
  end
@@ -48,9 +59,30 @@ module Adminix
48
59
  end
49
60
  end
50
61
 
51
- EventMachine.add_periodic_timer(SYNC_PERIOD) do
62
+ @ws_logs_client = ActionCableClient.new(@ws_uri, @ws_logs_channel)
63
+ @ws_logs_client.connected do |msg|
64
+ puts 'Logs connection established'
65
+ end
66
+ @ws_logs_client.disconnected do
67
+ system.log 'Logs disconnected. Reconnecting...'
68
+ sleep(2)
69
+ @ws_logs_client.connect!
70
+ end
71
+ @ws_logs_client.received { |msg| }
72
+
73
+ # Sync watcher
74
+ EventMachine.add_periodic_timer(config.watcher_sync_period) do
52
75
  @ws_client.perform(:sync, @service.to_cable) if @ws_client.subscribed?
53
76
  end
77
+
78
+ # Logs watcher
79
+ config.watch_log_files.each do |file_path|
80
+ EventMachine.watch_file(file_path, Adminix::LogWatchHandler)
81
+ end
82
+
83
+ EventMachine.add_periodic_timer(config.logs_sync_period) do
84
+ Adminix::Service.instance.sync_logs(@ws_logs_client)
85
+ end
54
86
  end
55
87
  end
56
88
 
data/lib/adminix.rb CHANGED
@@ -2,6 +2,7 @@ require 'adminix/version'
2
2
  require 'adminix/config'
3
3
  require 'adminix/service'
4
4
  require 'adminix/system'
5
+ require 'adminix/log_watch_handler'
5
6
  require 'adminix/watcher'
6
7
 
7
8
  module Adminix
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.24
4
+ version: 0.1.25
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-06-18 00:00:00.000000000 Z
11
+ date: 2017-08-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: eventmachine
@@ -157,6 +157,7 @@ files:
157
157
  - lib/adminix.rb
158
158
  - lib/adminix/.service.rb.swn
159
159
  - lib/adminix/config.rb
160
+ - lib/adminix/log_watch_handler.rb
160
161
  - lib/adminix/service.rb
161
162
  - lib/adminix/setup.rb
162
163
  - lib/adminix/setup/routes.rb