adminix 0.1.49 → 0.2
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/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
|