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.
Files changed (77) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -0
  3. data/adminix.gemspec +1 -4
  4. data/app/assets/images/logo.png +0 -0
  5. data/app/assets/javascripts/application.js +50 -0
  6. data/app/assets/javascripts/bootstrap.min.js +7 -0
  7. data/app/assets/javascripts/dataTables.bootstrap4.js +184 -0
  8. data/app/assets/javascripts/jquery.dataTables.js +15243 -0
  9. data/app/assets/javascripts/jquery.min.js +2 -0
  10. data/app/assets/javascripts/sb-admin-2.min.js +6 -0
  11. data/app/assets/stylesheets/bootstrap.min.css +6 -0
  12. data/app/assets/stylesheets/dataTables.bootstrap.css +314 -0
  13. data/app/assets/stylesheets/dataTables.responsive.css +106 -0
  14. data/app/assets/stylesheets/font-awesome.min.css +4 -0
  15. data/app/assets/stylesheets/sb-admin-2.min.css +5 -0
  16. data/app/views/scripts/restart_watcher.sh.erb +9 -0
  17. data/app/views/scripts/run_script.sh.erb +12 -0
  18. data/app/views/scripts/start_process.sh.erb +7 -0
  19. data/app/views/scripts/stop_process.sh.erb +7 -0
  20. data/app/views/scripts/update_process.sh.erb +24 -0
  21. data/app/views/scripts/update_watcher.sh.erb +3 -0
  22. data/app/views/web/dashboard.html.erb +90 -0
  23. data/app/views/web/job.html.erb +46 -0
  24. data/app/views/web/link.html.erb +12 -0
  25. data/app/views/web/loadstamp.html.erb +57 -0
  26. data/app/views/web/log.html.erb +49 -0
  27. data/app/views/web/partials/footer.html.erb +11 -0
  28. data/app/views/web/partials/header.html.erb +50 -0
  29. data/bin/install_adminix +40 -0
  30. data/bin/push +13 -0
  31. data/development.log +0 -0
  32. data/exe/adminix +91 -28
  33. data/lib/adminix.rb +42 -5
  34. data/lib/adminix/config.rb +170 -96
  35. data/lib/adminix/entities.rb +5 -0
  36. data/lib/adminix/entities/job.rb +54 -0
  37. data/lib/adminix/entities/log.rb +21 -0
  38. data/lib/adminix/entities/service.rb +211 -0
  39. data/lib/adminix/entities/sysload_stamp.rb +37 -0
  40. data/lib/adminix/entities/variable.rb +32 -0
  41. data/lib/adminix/helpers.rb +7 -2
  42. data/lib/adminix/helpers/command.rb +73 -0
  43. data/lib/adminix/helpers/files.rb +82 -0
  44. data/lib/adminix/helpers/log_reader.rb +16 -0
  45. data/lib/adminix/helpers/net_http.rb +63 -0
  46. data/lib/adminix/helpers/output.rb +28 -0
  47. data/lib/adminix/helpers/systemctl.rb +54 -0
  48. data/lib/adminix/services.rb +3 -0
  49. data/lib/adminix/services/app_service.rb +143 -0
  50. data/lib/adminix/services/logs_service.rb +13 -0
  51. data/lib/adminix/services/system_load_service.rb +16 -0
  52. data/lib/adminix/version.rb +1 -1
  53. data/lib/adminix/watcher.rb +76 -144
  54. data/lib/adminix/web.rb +4 -0
  55. data/lib/adminix/web/router.rb +98 -0
  56. data/lib/adminix/web/server.rb +60 -0
  57. data/lib/adminix/web/view_helper.rb +14 -0
  58. data/lib/event_machine.rb +2 -0
  59. data/lib/event_machine/http_server.rb +2 -0
  60. data/lib/event_machine/http_server/response.rb +314 -0
  61. data/lib/event_machine/http_server/server.rb +107 -0
  62. data/lib/event_machine/tail.rb +2 -0
  63. data/lib/event_machine/tail/filetail.rb +470 -0
  64. data/lib/event_machine/tail/globwatcher.rb +294 -0
  65. metadata +60 -45
  66. data/lib/adminix/errors.rb +0 -7
  67. data/lib/adminix/helpers/file.rb +0 -13
  68. data/lib/adminix/helpers/http.rb +0 -19
  69. data/lib/adminix/log_watch_handler.rb +0 -23
  70. data/lib/adminix/server_setup.rb +0 -76
  71. data/lib/adminix/service.rb +0 -179
  72. data/lib/adminix/setup.rb +0 -3
  73. data/lib/adminix/setup/routes.rb +0 -113
  74. data/lib/adminix/setup/services.rb +0 -139
  75. data/lib/adminix/setup/views.rb +0 -183
  76. data/lib/adminix/system.rb +0 -106
  77. data/views/daemon_scripts/upstart.conf.erb +0 -23
@@ -0,0 +1,5 @@
1
+ require_relative 'entities/service'
2
+ require_relative 'entities/variable'
3
+ require_relative 'entities/log'
4
+ require_relative 'entities/sysload_stamp'
5
+ require_relative 'entities/job'
@@ -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
@@ -1,2 +1,7 @@
1
- require_relative 'helpers/file'
2
- require_relative 'helpers/http'
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