adminix 0.1.49 → 0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +1 -0
- data/adminix.gemspec +1 -4
- data/app/assets/images/logo.png +0 -0
- data/app/assets/javascripts/application.js +50 -0
- data/app/assets/javascripts/bootstrap.min.js +7 -0
- data/app/assets/javascripts/dataTables.bootstrap4.js +184 -0
- data/app/assets/javascripts/jquery.dataTables.js +15243 -0
- data/app/assets/javascripts/jquery.min.js +2 -0
- data/app/assets/javascripts/sb-admin-2.min.js +6 -0
- data/app/assets/stylesheets/bootstrap.min.css +6 -0
- data/app/assets/stylesheets/dataTables.bootstrap.css +314 -0
- data/app/assets/stylesheets/dataTables.responsive.css +106 -0
- data/app/assets/stylesheets/font-awesome.min.css +4 -0
- data/app/assets/stylesheets/sb-admin-2.min.css +5 -0
- data/app/views/scripts/restart_watcher.sh.erb +9 -0
- data/app/views/scripts/run_script.sh.erb +12 -0
- data/app/views/scripts/start_process.sh.erb +7 -0
- data/app/views/scripts/stop_process.sh.erb +7 -0
- data/app/views/scripts/update_process.sh.erb +24 -0
- data/app/views/scripts/update_watcher.sh.erb +3 -0
- data/app/views/web/dashboard.html.erb +90 -0
- data/app/views/web/job.html.erb +46 -0
- data/app/views/web/link.html.erb +12 -0
- data/app/views/web/loadstamp.html.erb +57 -0
- data/app/views/web/log.html.erb +49 -0
- data/app/views/web/partials/footer.html.erb +11 -0
- data/app/views/web/partials/header.html.erb +50 -0
- data/bin/install_adminix +40 -0
- data/bin/push +13 -0
- data/development.log +0 -0
- data/exe/adminix +91 -28
- data/lib/adminix.rb +42 -5
- data/lib/adminix/config.rb +170 -96
- data/lib/adminix/entities.rb +5 -0
- data/lib/adminix/entities/job.rb +54 -0
- data/lib/adminix/entities/log.rb +21 -0
- data/lib/adminix/entities/service.rb +211 -0
- data/lib/adminix/entities/sysload_stamp.rb +37 -0
- data/lib/adminix/entities/variable.rb +32 -0
- data/lib/adminix/helpers.rb +7 -2
- data/lib/adminix/helpers/command.rb +73 -0
- data/lib/adminix/helpers/files.rb +82 -0
- data/lib/adminix/helpers/log_reader.rb +16 -0
- data/lib/adminix/helpers/net_http.rb +63 -0
- data/lib/adminix/helpers/output.rb +28 -0
- data/lib/adminix/helpers/systemctl.rb +54 -0
- data/lib/adminix/services.rb +3 -0
- data/lib/adminix/services/app_service.rb +143 -0
- data/lib/adminix/services/logs_service.rb +13 -0
- data/lib/adminix/services/system_load_service.rb +16 -0
- data/lib/adminix/version.rb +1 -1
- data/lib/adminix/watcher.rb +76 -144
- data/lib/adminix/web.rb +4 -0
- data/lib/adminix/web/router.rb +98 -0
- data/lib/adminix/web/server.rb +60 -0
- data/lib/adminix/web/view_helper.rb +14 -0
- data/lib/event_machine.rb +2 -0
- data/lib/event_machine/http_server.rb +2 -0
- data/lib/event_machine/http_server/response.rb +314 -0
- data/lib/event_machine/http_server/server.rb +107 -0
- data/lib/event_machine/tail.rb +2 -0
- data/lib/event_machine/tail/filetail.rb +470 -0
- data/lib/event_machine/tail/globwatcher.rb +294 -0
- metadata +60 -45
- data/lib/adminix/errors.rb +0 -7
- data/lib/adminix/helpers/file.rb +0 -13
- data/lib/adminix/helpers/http.rb +0 -19
- data/lib/adminix/log_watch_handler.rb +0 -23
- data/lib/adminix/server_setup.rb +0 -76
- data/lib/adminix/service.rb +0 -179
- data/lib/adminix/setup.rb +0 -3
- data/lib/adminix/setup/routes.rb +0 -113
- data/lib/adminix/setup/services.rb +0 -139
- data/lib/adminix/setup/views.rb +0 -183
- data/lib/adminix/system.rb +0 -106
- data/views/daemon_scripts/upstart.conf.erb +0 -23
@@ -0,0 +1,54 @@
|
|
1
|
+
module Adminix
|
2
|
+
module Entities
|
3
|
+
class Job
|
4
|
+
attr_accessor :id, :script
|
5
|
+
attr_reader :output, :status, :success
|
6
|
+
|
7
|
+
STATUS_IN_QUEUE = 'in_queue'.freeze
|
8
|
+
STATUS_COMPLETED = 'completed'.freeze
|
9
|
+
|
10
|
+
def initialize(id:, script:)
|
11
|
+
@id = id
|
12
|
+
@script = script
|
13
|
+
@status = STATUS_IN_QUEUE
|
14
|
+
@created_at = Time.now
|
15
|
+
@success = false
|
16
|
+
|
17
|
+
filter_script
|
18
|
+
end
|
19
|
+
|
20
|
+
def perform
|
21
|
+
@output = `/bin/bash #{Adminix.config.scripts[:run_script]} #{script}`
|
22
|
+
@success = $?.success?
|
23
|
+
@status = STATUS_COMPLETED
|
24
|
+
@completed_at = Time.now
|
25
|
+
end
|
26
|
+
|
27
|
+
def in_queue?
|
28
|
+
@status == STATUS_IN_QUEUE
|
29
|
+
end
|
30
|
+
|
31
|
+
def completed?
|
32
|
+
@status == STATUS_COMPLETED
|
33
|
+
end
|
34
|
+
|
35
|
+
def filter_script
|
36
|
+
['sudo', 'shutdown', 'kill'].each do |word|
|
37
|
+
@script = @script.gsub('word', '')
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def to_api
|
42
|
+
{
|
43
|
+
id: @id,
|
44
|
+
status: @status,
|
45
|
+
script: @script,
|
46
|
+
success: @success,
|
47
|
+
output: @output,
|
48
|
+
created_at: @created_at,
|
49
|
+
completed_at: @completed_at
|
50
|
+
}
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Adminix
|
2
|
+
module Entities
|
3
|
+
class Log
|
4
|
+
attr_reader :message, :tag, :created_at
|
5
|
+
|
6
|
+
def initialize(message, tag = nil)
|
7
|
+
@message = message
|
8
|
+
@tag = tag || 'default'
|
9
|
+
@created_at = Time.now
|
10
|
+
end
|
11
|
+
|
12
|
+
def to_api
|
13
|
+
{
|
14
|
+
message: message,
|
15
|
+
tag: tag,
|
16
|
+
created_at: created_at
|
17
|
+
}
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,211 @@
|
|
1
|
+
require 'securerandom'
|
2
|
+
|
3
|
+
module Adminix
|
4
|
+
module Entities
|
5
|
+
class Service
|
6
|
+
attr_reader :id, :logs, :load_stamps, :jobs, :device_id, :performed_actions
|
7
|
+
attr_accessor :variables
|
8
|
+
|
9
|
+
def initialize(opts = {})
|
10
|
+
@id = opts[:id]
|
11
|
+
@device_id_path = "#{Helpers::Command.home}/.config/adminix/device_id"
|
12
|
+
@variables = []
|
13
|
+
@jobs = []
|
14
|
+
@logs = []
|
15
|
+
@load_stamps = []
|
16
|
+
@send_logs = false
|
17
|
+
@locked = false
|
18
|
+
@send_system_load = false
|
19
|
+
@performed_actions = {
|
20
|
+
watcher_started: true,
|
21
|
+
watcher_updated: false,
|
22
|
+
process_stopped: false,
|
23
|
+
process_started: false,
|
24
|
+
process_updated: false
|
25
|
+
}
|
26
|
+
|
27
|
+
define_device_id
|
28
|
+
end
|
29
|
+
|
30
|
+
def remove_completed_jobs
|
31
|
+
@jobs.each do |job|
|
32
|
+
@jobs -= [job] if job.completed?
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def clean_sent_logs
|
37
|
+
return unless @send_logs
|
38
|
+
@send_logs = false
|
39
|
+
@logs = []
|
40
|
+
end
|
41
|
+
|
42
|
+
def clean_load_stamps
|
43
|
+
return unless @send_system_load
|
44
|
+
@send_system_load = false
|
45
|
+
@load_stamps = []
|
46
|
+
end
|
47
|
+
|
48
|
+
def add_new_jobs(list)
|
49
|
+
list.each do |data|
|
50
|
+
@jobs << Entities::Job.new(
|
51
|
+
id: data['id'],
|
52
|
+
script: data['script']
|
53
|
+
)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def add_logs(logs)
|
58
|
+
return if locked?
|
59
|
+
@logs += logs
|
60
|
+
end
|
61
|
+
|
62
|
+
def shift_logs(number)
|
63
|
+
@logs.shift(number)
|
64
|
+
end
|
65
|
+
|
66
|
+
def add_variable(new_var)
|
67
|
+
var = @variables.find { |v| v.key == new_var.key }
|
68
|
+
if var
|
69
|
+
index = @variables.index(var)
|
70
|
+
@variables[index] = new_var
|
71
|
+
else
|
72
|
+
@variables << new_var
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def add_system_load(sys_load)
|
77
|
+
@load_stamps << sys_load
|
78
|
+
end
|
79
|
+
|
80
|
+
def shift_load_stamps(number)
|
81
|
+
@load_stamps.shift(number)
|
82
|
+
end
|
83
|
+
|
84
|
+
def allow_sending_logs
|
85
|
+
@send_logs = true
|
86
|
+
return if @logs.count.zero?
|
87
|
+
Adminix.logger.info("Sending #{@logs.count} new logs")
|
88
|
+
end
|
89
|
+
|
90
|
+
def allow_sending_system_load
|
91
|
+
@send_system_load = true
|
92
|
+
return if @load_stamps.count.zero?
|
93
|
+
Adminix.logger.info("Sending #{@load_stamps.count} new system load stamps")
|
94
|
+
end
|
95
|
+
|
96
|
+
def ensure_credentials_exists!
|
97
|
+
return unless id_defined?
|
98
|
+
Helpers::Output.display_error_and_exit('Credentials are not provided')
|
99
|
+
end
|
100
|
+
|
101
|
+
def define_device_id
|
102
|
+
if Helpers::Files.file_exists?(@device_id_path)
|
103
|
+
read_device_id
|
104
|
+
else
|
105
|
+
generate_device_id
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
def read_device_id
|
110
|
+
content = Helpers::Files.read_plain_file(@device_id_path)
|
111
|
+
.split("\n").first.to_s
|
112
|
+
if content.empty?
|
113
|
+
Helpers::Output.display_error_and_exit("Device ID can't be empty")
|
114
|
+
else
|
115
|
+
@device_id = content
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
def generate_device_id(id = nil)
|
120
|
+
@device_id = id || SecureRandom.uuid
|
121
|
+
Helpers::Files.write_plain_file(@device_id_path, @device_id)
|
122
|
+
end
|
123
|
+
|
124
|
+
# TODO: real total memory and disk
|
125
|
+
def sync_payload
|
126
|
+
{
|
127
|
+
device_id: @device_id,
|
128
|
+
watcher_started: @performed_actions[:watcher_started],
|
129
|
+
watcher_updated: @performed_actions[:watcher_updated],
|
130
|
+
process_stopped: @performed_actions[:process_stopped],
|
131
|
+
process_started: @performed_actions[:process_started],
|
132
|
+
process_updated: @performed_actions[:process_updated],
|
133
|
+
completed_jobs: completed_jobs_to_api,
|
134
|
+
logs: logs_to_api,
|
135
|
+
system_load: {
|
136
|
+
stamps: load_stamps_to_api,
|
137
|
+
total: {
|
138
|
+
memory: 1024,
|
139
|
+
disk: 10_240
|
140
|
+
}
|
141
|
+
}
|
142
|
+
}
|
143
|
+
end
|
144
|
+
|
145
|
+
def new_jobs
|
146
|
+
@jobs.select(&:in_queue?)
|
147
|
+
end
|
148
|
+
|
149
|
+
def completed_jobs
|
150
|
+
@jobs.select(&:completed?)
|
151
|
+
end
|
152
|
+
|
153
|
+
def completed_jobs_to_api
|
154
|
+
completed_jobs.map(&:to_api)
|
155
|
+
end
|
156
|
+
|
157
|
+
def logs_to_api
|
158
|
+
@send_logs ? @logs.map(&:to_api) : []
|
159
|
+
end
|
160
|
+
|
161
|
+
def load_stamps_to_api
|
162
|
+
@send_system_load ? @load_stamps.map(&:to_api) : []
|
163
|
+
end
|
164
|
+
|
165
|
+
def reset_performed_actions
|
166
|
+
@performed_actions.keys.map { |key| @performed_actions[key] = false }
|
167
|
+
end
|
168
|
+
|
169
|
+
def define_performed_action(key, value)
|
170
|
+
@performed_actions[key] = value
|
171
|
+
end
|
172
|
+
|
173
|
+
def bash_variables(file = nil)
|
174
|
+
output = ''
|
175
|
+
|
176
|
+
if file
|
177
|
+
content = (variables.map { |v| "#{v.key}=#{v.value}" }).join("\n")
|
178
|
+
Helpers::Files.rm(file)
|
179
|
+
Helpers::Files.write_plain_file(file, content)
|
180
|
+
output = file
|
181
|
+
else
|
182
|
+
variables.each { |v| output << "#{v.to_bash_export}\n" }
|
183
|
+
output << "# Run this command to configure your shell:\n" \
|
184
|
+
'# eval $(adminix env)'
|
185
|
+
end
|
186
|
+
|
187
|
+
output
|
188
|
+
end
|
189
|
+
|
190
|
+
def id_defined?
|
191
|
+
!(id || '').empty?
|
192
|
+
end
|
193
|
+
|
194
|
+
def new_jobs?
|
195
|
+
new_jobs.any?
|
196
|
+
end
|
197
|
+
|
198
|
+
def locked?
|
199
|
+
@locked == true
|
200
|
+
end
|
201
|
+
|
202
|
+
def lock
|
203
|
+
@locked = true
|
204
|
+
end
|
205
|
+
|
206
|
+
def unlock
|
207
|
+
@locked = false
|
208
|
+
end
|
209
|
+
end
|
210
|
+
end
|
211
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Adminix
|
2
|
+
module Entities
|
3
|
+
class SysloadStamp
|
4
|
+
|
5
|
+
attr_reader :memory_usage_mb, :cpu_load_percents, :disk_usage_mb,
|
6
|
+
:temperature, :created_at
|
7
|
+
|
8
|
+
def initialize
|
9
|
+
create_stamp
|
10
|
+
@created_at = Time.now
|
11
|
+
end
|
12
|
+
|
13
|
+
def create_stamp
|
14
|
+
case Adminix.os
|
15
|
+
when 'linux'
|
16
|
+
@memory_usage_mb, = Helpers::Command.debian_memory_load
|
17
|
+
@cpu_load_percents = Helpers::Command.debian_cpu_load
|
18
|
+
@disk_usage_mb, = Helpers::Command.debian_disk_usage
|
19
|
+
@temperature = Helpers::Command.debian_temperature
|
20
|
+
when 'mac'
|
21
|
+
@cpu_load_percents = Helpers::Command.darwin_cpu_load
|
22
|
+
@disk_usage_mb, = Helpers::Command.darwin_disk_usage
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def to_api
|
27
|
+
{
|
28
|
+
memory: memory_usage_mb,
|
29
|
+
cpu: cpu_load_percents,
|
30
|
+
disk: disk_usage_mb,
|
31
|
+
temperature: temperature,
|
32
|
+
created_at: created_at
|
33
|
+
}
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module Adminix
|
2
|
+
module Entities
|
3
|
+
class Variable
|
4
|
+
attr_reader :key, :value
|
5
|
+
|
6
|
+
def self.all(service)
|
7
|
+
return [] unless Adminix.config.credentials_defined?
|
8
|
+
|
9
|
+
success, result = Helpers::NetHTTP.get("services/#{service.id}/options")
|
10
|
+
return [] unless success
|
11
|
+
|
12
|
+
variables = result.map do |o|
|
13
|
+
Variable.new(
|
14
|
+
key: o['key'],
|
15
|
+
value: o['value']
|
16
|
+
)
|
17
|
+
end
|
18
|
+
|
19
|
+
variables
|
20
|
+
end
|
21
|
+
|
22
|
+
def initialize(opts = {})
|
23
|
+
@key = opts[:key]
|
24
|
+
@value = opts[:value]
|
25
|
+
end
|
26
|
+
|
27
|
+
def to_bash_export
|
28
|
+
"export #{key}=\"#{value}\""
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
data/lib/adminix/helpers.rb
CHANGED
@@ -1,2 +1,7 @@
|
|
1
|
-
require_relative 'helpers/
|
2
|
-
require_relative 'helpers/
|
1
|
+
require_relative 'helpers/files'
|
2
|
+
require_relative 'helpers/output'
|
3
|
+
require_relative 'helpers/net_http'
|
4
|
+
require_relative 'helpers/command'
|
5
|
+
require_relative 'helpers/command'
|
6
|
+
require_relative 'helpers/log_reader'
|
7
|
+
require_relative 'helpers/systemctl'
|
@@ -0,0 +1,73 @@
|
|
1
|
+
module Adminix
|
2
|
+
module Helpers
|
3
|
+
module Command
|
4
|
+
def self.which(arg1)
|
5
|
+
output = `which #{arg1}`
|
6
|
+
output = output.split("\n")[0]
|
7
|
+
output.empty? ? nil : output
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.whoami
|
11
|
+
output = `whoami`
|
12
|
+
output.split("\n")[0]
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.home
|
16
|
+
ENV['HOME']
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.git_clone(repo, branch = 'master')
|
20
|
+
bin = 'git'
|
21
|
+
`#{bin} clone #{repo} -b #{branch}`
|
22
|
+
end
|
23
|
+
|
24
|
+
def mkdir_p(dirname)
|
25
|
+
`mkdir -p #{dirname}`
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.run_system_command(command)
|
29
|
+
`#{command}`
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.debian_memory_load
|
33
|
+
output = `free -m | awk 'NR==2{printf "%s/%s", $3,$2,$3*100/$2 }'`
|
34
|
+
output.split('/')
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.systemctl_enabled?
|
38
|
+
!`which systemctl`.length.zero?
|
39
|
+
end
|
40
|
+
|
41
|
+
def self.darwin_memory_load
|
42
|
+
output = `free -m | awk 'NR==2{printf "%s/%s", $3,$2,$3*100/$2 }'`
|
43
|
+
output.split('/')
|
44
|
+
end
|
45
|
+
|
46
|
+
def self.debian_cpu_load
|
47
|
+
`top -bn1 | grep load | awk '{printf "%.2f\\\n", $(NF-2)}'`.to_f
|
48
|
+
end
|
49
|
+
|
50
|
+
def self.darwin_cpu_load
|
51
|
+
`ps -A -o %cpu | awk '{s+=$1} END {print s}'`.to_f
|
52
|
+
end
|
53
|
+
|
54
|
+
def self.debian_disk_usage
|
55
|
+
output = `df -h | awk '$NF=="/"{printf "%d/%d\\\n", $3,$2,$5}'`
|
56
|
+
output.split('/')
|
57
|
+
end
|
58
|
+
|
59
|
+
def self.debian_temperature
|
60
|
+
output = `cat /sys/class/thermal/thermal_zone*/temp`
|
61
|
+
temperatures = output.split("\n").map(&:to_i)
|
62
|
+
return nil if temperatures.empty?
|
63
|
+
temperatures.reduce(:+) / temperatures.size
|
64
|
+
end
|
65
|
+
|
66
|
+
def self.darwin_disk_usage
|
67
|
+
output = `df -h | awk '$NF=="/"{printf "%d/%d", $3,$2,$5}'`
|
68
|
+
used, disk_size = output.split('/')
|
69
|
+
[used.to_f * 1024, disk_size.to_f * 1024]
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|