mkit 0.7.2 → 0.9.0
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 +6 -4
- data/bin/mkit +5 -5
- data/lib/mkit/app/controllers/mkit_controller.rb +1 -1
- data/lib/mkit/app/controllers/pods_controller.rb +35 -9
- data/lib/mkit/app/controllers/services_controller.rb +40 -4
- data/lib/mkit/app/helpers/params_helper.rb +15 -0
- data/lib/mkit/app/helpers/pods_helper.rb +14 -0
- data/lib/mkit/app/helpers/services_helper.rb +10 -7
- data/lib/mkit/app/model/pod.rb +11 -2
- data/lib/mkit/app/model/service.rb +54 -0
- data/lib/mkit/client/command_parser.rb +41 -2
- data/lib/mkit/client/commands.yaml +106 -11
- data/lib/mkit/client/console_websocket_client.rb +57 -0
- data/lib/mkit/client/http_client.rb +4 -2
- data/lib/mkit/client/log_websocket_client.rb +46 -0
- data/lib/mkit/client/mkitd_client.rb +3 -1
- data/lib/mkit/client/websocket_client.rb +12 -37
- data/lib/mkit/pods/docker_exec_command.rb +38 -0
- data/lib/mkit/version.rb +1 -1
- data/lib/mkit.rb +1 -2
- metadata +9 -5
- data/samples/soketi.yaml +0 -32
- /data/lib/mkit/{docker_listener.rb → pods/docker_listener.rb} +0 -0
- /data/lib/mkit/{docker_log_listener.rb → pods/docker_log_listener.rb} +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 567f1ce28fb7c14d9eb23ddd36c4f98f68516b1c967450ec11188bfc460f5fdb
|
4
|
+
data.tar.gz: 389a9060968047e9efb35ba47cdf3492d4ed47d8f92ce5e82203bb0668dd5ec1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c86fc61f402f4559bbda5eb4bb89fa1a11073e0ad228f954a0cee370c50d3d3367469f64acf6073bb702985dcb99a9c655c4b38cc95f9a010e8623102742a2cd
|
7
|
+
data.tar.gz: 9387d17b7394fa1619ad0ca7b03cda17ff4b98d1de7a56624a60fe96382a95b2501a11c07f41cbe36b7f3a2d569253903b2288aebb71430ed6d671ceebd17464
|
data/README.md
CHANGED
@@ -9,7 +9,7 @@ The database is a simple sqlite3 db and the server is a Sinatra based applicatio
|
|
9
9
|
|
10
10
|
A client is also included to access the API, e.g. `mkit ps`.
|
11
11
|
|
12
|
-
The daemon is responsible for HAProxy pods routing configuration. It also provides the cluster DNS and manages the internal host interface and the
|
12
|
+
The daemon is responsible for HAProxy pods routing configuration. It also provides the cluster DNS and manages the internal host interface and the pod instances.
|
13
13
|
|
14
14
|
## Requirements
|
15
15
|
|
@@ -124,7 +124,7 @@ my_id: unique_id # this id is generated running mkit init
|
|
124
124
|
|
125
125
|
```
|
126
126
|
service:
|
127
|
-
name: rabbitmq # unique
|
127
|
+
name: rabbitmq # unique. Available on internal DNS as 'rabbitmq'
|
128
128
|
image: rabbitmq:3-management-alpine # image
|
129
129
|
network: bridge # docker network - it will be created if it does not exists
|
130
130
|
ports: # haproxy port mapping
|
@@ -140,7 +140,7 @@ service:
|
|
140
140
|
- 5672:5672:tcp:round_robin
|
141
141
|
- 80:15672:http:round_robin
|
142
142
|
resources:
|
143
|
-
min_replicas: 1 # default value
|
143
|
+
min_replicas: 1 # default value. Pods will be available on internal DNS as '<service_name>.internal'
|
144
144
|
max_replicas: 1 # default value
|
145
145
|
volumes:
|
146
146
|
- docker://mkit_rabbitmq_data:/var/lib/rabbitmq # a docker volume - it will be created if it does not exists
|
@@ -191,9 +191,11 @@ stop stop service
|
|
191
191
|
restart restart service
|
192
192
|
create create new service
|
193
193
|
update update service
|
194
|
+
get print service configuration
|
194
195
|
rm remove service
|
196
|
+
exec execute a command in a running pod
|
195
197
|
logs view service logs
|
196
|
-
version prints mkit server version
|
198
|
+
version prints mkit client and server version
|
197
199
|
proxy haproxy status and control
|
198
200
|
profile mkit client configuration profile
|
199
201
|
|
data/bin/mkit
CHANGED
@@ -13,6 +13,7 @@ require 'uri'
|
|
13
13
|
require 'fileutils'
|
14
14
|
require 'mkit/client/command_parser'
|
15
15
|
require 'mkit/client/mkitd_client'
|
16
|
+
require 'mkit/version'
|
16
17
|
|
17
18
|
class InvalidConfigurationException < Exception
|
18
19
|
attr_reader :command
|
@@ -91,6 +92,10 @@ class MKItClient
|
|
91
92
|
client.request(request, request_data)
|
92
93
|
end
|
93
94
|
|
95
|
+
def version(request, request_data)
|
96
|
+
puts "MKIt Client version #{MKIt::VERSION}"
|
97
|
+
request(request, request_data)
|
98
|
+
end
|
94
99
|
#
|
95
100
|
# commands
|
96
101
|
#
|
@@ -174,8 +179,3 @@ end
|
|
174
179
|
#
|
175
180
|
client = MKItClient.new
|
176
181
|
client.doIt(ARGV.dup)
|
177
|
-
#
|
178
|
-
# if ARGV.any?
|
179
|
-
# parse args
|
180
|
-
# host, socket, config file
|
181
|
-
# end
|
@@ -1,16 +1,42 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
3
|
+
require 'mkit/app/model/pod'
|
4
|
+
require 'mkit/app/helpers/pods_helper'
|
5
|
+
require 'mkit/app/helpers/params_helper'
|
6
|
+
require 'mkit/pods/docker_exec_command'
|
7
|
+
require 'mkit/exceptions'
|
7
8
|
|
8
|
-
|
9
|
-
|
10
|
-
|
9
|
+
class PodsController < MKIt::Server
|
10
|
+
helpers MKIt::PodsHelper
|
11
|
+
helpers MKIt::ParamsHelper
|
11
12
|
|
12
|
-
|
13
|
-
|
13
|
+
get '/pods/:id/exec' do
|
14
|
+
pod = find_by_id_or_name
|
15
|
+
if request.websocket?
|
16
|
+
options_parameter = build_options_hash(params: params, options: [:varargs])
|
17
|
+
raise MKIt::BaseException.new(400, "Missing parameters") unless options_parameter[:varargs]
|
18
|
+
options_parameter[:varargs] = JSON.parse(params['varargs'])
|
19
|
+
request.websocket do |ws|
|
20
|
+
listener = nil
|
21
|
+
ws.onopen do
|
22
|
+
settings.sockets << ws
|
23
|
+
listener = MKIt::DockerExecCommand.new(pod, ws, options: options_parameter)
|
24
|
+
settings.listeners << listener
|
25
|
+
listener.register
|
26
|
+
end
|
27
|
+
ws.onclose do
|
28
|
+
MKItLogger.info("websocket closed [#{listener}]")
|
29
|
+
settings.sockets.delete(ws)
|
30
|
+
if listener
|
31
|
+
MKItLogger.info("unregister [#{listener}]")
|
32
|
+
settings.listeners.delete(listener)
|
33
|
+
listener.unregister
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
else
|
38
|
+
raise MKIt::BaseException.new(400, "Bad request")
|
39
|
+
end
|
14
40
|
end
|
15
41
|
|
16
42
|
delete '/services/:service_id/pods/:pod_id' do
|
@@ -2,10 +2,13 @@
|
|
2
2
|
|
3
3
|
require 'mkit/app/model/service'
|
4
4
|
require 'mkit/app/helpers/services_helper'
|
5
|
-
require 'mkit/
|
5
|
+
require 'mkit/app/helpers/params_helper'
|
6
|
+
require 'mkit/pods/docker_log_listener'
|
7
|
+
require 'mkit/pods/docker_exec_command'
|
6
8
|
|
7
9
|
class ServicesController < MKIt::Server
|
8
10
|
helpers MKIt::ServicesHelper
|
11
|
+
helpers MKIt::ParamsHelper
|
9
12
|
|
10
13
|
# curl localhost:4567/services
|
11
14
|
get '/services' do
|
@@ -24,8 +27,10 @@ class ServicesController < MKIt::Server
|
|
24
27
|
|
25
28
|
get '/services/:id' do
|
26
29
|
srv = find_by_id_or_name
|
27
|
-
resp = if
|
28
|
-
srv.
|
30
|
+
resp = if params[:format] == 'yaml'
|
31
|
+
srv.to_h({details: params[:details] == 'true'}).to_yaml
|
32
|
+
elsif params[:format] == 'json'
|
33
|
+
JSON.pretty_generate(srv.to_h({details: params[:details] == 'true'}))
|
29
34
|
else
|
30
35
|
format_response(srv)
|
31
36
|
end
|
@@ -37,13 +42,14 @@ class ServicesController < MKIt::Server
|
|
37
42
|
if !request.websocket?
|
38
43
|
srv.log
|
39
44
|
else
|
45
|
+
pod = find_srv_pod_by_id_or_name(srv)
|
40
46
|
options_parameter = build_options_hash(params: params, options: [:nr_lines, :pods, :follow])
|
41
47
|
request.websocket do |ws|
|
42
48
|
listener = nil
|
43
49
|
ws.onopen do
|
44
50
|
settings.sockets << ws
|
45
51
|
ws.send("<<<< %s | %s >>>>\n" % [srv.name, srv.pod.first.name])
|
46
|
-
listener = MKIt::DockerLogListener.new(
|
52
|
+
listener = MKIt::DockerLogListener.new(pod, ws, options: options_parameter)
|
47
53
|
settings.listeners << listener
|
48
54
|
listener.register
|
49
55
|
end
|
@@ -115,4 +121,34 @@ class ServicesController < MKIt::Server
|
|
115
121
|
MkitJob.publish(topic: :start_service, service_id: srv.id)
|
116
122
|
format_response(srv)
|
117
123
|
end
|
124
|
+
|
125
|
+
get '/services/:id/pods/exec' do
|
126
|
+
srv = find_by_id_or_name
|
127
|
+
if request.websocket?
|
128
|
+
pod = find_srv_pod_by_id_or_name(srv)
|
129
|
+
options_parameter = build_options_hash(params: params, options: [:varargs, :interactive, :detached])
|
130
|
+
raise MKIt::BaseException.new(400, "Missing parameters") unless options_parameter[:varargs]
|
131
|
+
options_parameter[:varargs] = JSON.parse(params['varargs'])
|
132
|
+
request.websocket do |ws|
|
133
|
+
listener = nil
|
134
|
+
ws.onopen do
|
135
|
+
settings.sockets << ws
|
136
|
+
listener = MKIt::DockerExecCommand.new(pod, ws, options: options_parameter)
|
137
|
+
settings.listeners << listener
|
138
|
+
listener.register
|
139
|
+
end
|
140
|
+
ws.onclose do
|
141
|
+
MKItLogger.info("websocket closed [#{listener}]")
|
142
|
+
settings.sockets.delete(ws)
|
143
|
+
if listener
|
144
|
+
MKItLogger.info("unregister [#{listener}]")
|
145
|
+
settings.listeners.delete(listener)
|
146
|
+
listener.unregister
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
150
|
+
else
|
151
|
+
raise MKIt::BaseException.new(400, "Bad request")
|
152
|
+
end
|
153
|
+
end
|
118
154
|
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module MKIt
|
4
|
+
module PodsHelper
|
5
|
+
|
6
|
+
def find_by_id_or_name
|
7
|
+
pod = Pod.find_by_id(params[:id])
|
8
|
+
pod ||= Pod.find_by_name(params[:id])
|
9
|
+
error 404, "Couldn't find Pod '#{params[:id]}'\n" unless pod
|
10
|
+
pod
|
11
|
+
end
|
12
|
+
|
13
|
+
end
|
14
|
+
end
|
@@ -16,13 +16,6 @@ module MKIt
|
|
16
16
|
table.to_s
|
17
17
|
end
|
18
18
|
|
19
|
-
def build_options_hash(params:, options:)
|
20
|
-
hash = {}
|
21
|
-
options.each do |option|
|
22
|
-
hash[option] = params[option]
|
23
|
-
end
|
24
|
-
hash
|
25
|
-
end
|
26
19
|
def find_by_id_or_name
|
27
20
|
srv = Service.find_by_id(params[:id])
|
28
21
|
srv ||= Service.find_by_name(params[:id])
|
@@ -30,6 +23,16 @@ module MKIt
|
|
30
23
|
srv
|
31
24
|
end
|
32
25
|
|
26
|
+
def find_srv_pod_by_id_or_name(srv)
|
27
|
+
if params[:pod_id]
|
28
|
+
pod = srv.find_pod_by_id_or_name(params[:pod_id])
|
29
|
+
error 404, "Service pod not found." unless pod
|
30
|
+
else
|
31
|
+
pod = srv.pod.first
|
32
|
+
end
|
33
|
+
pod
|
34
|
+
end
|
35
|
+
|
33
36
|
def build_table_row(data)
|
34
37
|
ports = data.service_port&.each.map { |p| build_port(p) }.join(',')
|
35
38
|
pods = data.pod.each.map { |p| p.name.to_s }.join(' ')
|
data/lib/mkit/app/model/pod.rb
CHANGED
@@ -32,7 +32,7 @@ class Pod < ActiveRecord::Base
|
|
32
32
|
def update_dns
|
33
33
|
self.dns_host ||= DnsHost.new(
|
34
34
|
service: self.service,
|
35
|
-
name: "#{
|
35
|
+
name: "#{self.service.name}.internal",
|
36
36
|
ip: self.ip
|
37
37
|
)
|
38
38
|
self.dns_host.ip = self.ip
|
@@ -40,7 +40,7 @@ class Pod < ActiveRecord::Base
|
|
40
40
|
end
|
41
41
|
|
42
42
|
def set_status_from_docker
|
43
|
-
if self.instance
|
43
|
+
if !self.instance.nil?
|
44
44
|
if instance.State.Running
|
45
45
|
self.status = MKIt::Status::RUNNING
|
46
46
|
else
|
@@ -85,5 +85,14 @@ class Pod < ActiveRecord::Base
|
|
85
85
|
end
|
86
86
|
MkitJob.publish(topic: :pod_destroyed, service_id: self.service.id, data: {pod_id: self.id})
|
87
87
|
end
|
88
|
+
|
89
|
+
def to_h
|
90
|
+
{
|
91
|
+
'name' => self.name,
|
92
|
+
'ip' => self.dns_host.nil? || self.dns_host.ip.nil? ? self.ip : self.dns_host.ip,
|
93
|
+
'dns' => self.dns_host.nil? || self.dns_host.name.nil? ? self.ip : self.dns_host.name,
|
94
|
+
'status' => self.status
|
95
|
+
}
|
96
|
+
end
|
88
97
|
end
|
89
98
|
|
@@ -222,6 +222,11 @@ class Service < ActiveRecord::Base
|
|
222
222
|
MkitJob.publish(topic: :destroy_proxy_config, data: {filename: filename})
|
223
223
|
end
|
224
224
|
|
225
|
+
def find_pod_by_id_or_name(pod_id)
|
226
|
+
pod = self.pod.find_by(id: pod_id)
|
227
|
+
pod = self.pod.find_by(name: pod_id) unless pod
|
228
|
+
pod
|
229
|
+
end
|
225
230
|
#
|
226
231
|
# ctrl
|
227
232
|
#
|
@@ -245,6 +250,55 @@ class Service < ActiveRecord::Base
|
|
245
250
|
}
|
246
251
|
out
|
247
252
|
end
|
253
|
+
def to_h(options = {})
|
254
|
+
details = options[:details] || false
|
255
|
+
yaml = {}
|
256
|
+
yaml['service'] = {}
|
257
|
+
srv = yaml['service']
|
258
|
+
srv['name'] = self.name
|
259
|
+
srv['image'] = self.image
|
260
|
+
srv['command'] = self.command
|
261
|
+
srv['network'] = self.pods_network
|
262
|
+
if details
|
263
|
+
srv['status'] = self.status
|
264
|
+
srv['version'] = self.version
|
265
|
+
srv['ip'] = self.lease.ip
|
266
|
+
srv['dns'] = self.dns_host.name
|
267
|
+
srv['pods'] = []
|
268
|
+
self.pod.each { |p|
|
269
|
+
srv['pods'] << p.to_h
|
270
|
+
}
|
271
|
+
end
|
272
|
+
srv['ports'] = []
|
273
|
+
self.service_port.each { |p|
|
274
|
+
"#{p.internal_port}:#{p.external_port}:#{p.mode}:#{p.load_bal}".tap { |x|
|
275
|
+
if p.ssl == 'true'
|
276
|
+
x << ':ssl'
|
277
|
+
if !p.crt.nil? && p.crt != MKIt::Utils.proxy_cert
|
278
|
+
x << ":#{p.crt}"
|
279
|
+
end
|
280
|
+
end
|
281
|
+
srv['ports'] << x
|
282
|
+
}
|
283
|
+
}
|
284
|
+
srv['resources'] = {}
|
285
|
+
srv['resources']['min_replicas'] = self.min_replicas
|
286
|
+
srv['resources']['max_replicas'] = self.max_replicas
|
287
|
+
srv['volumes'] = []
|
288
|
+
self.volume.each { |v|
|
289
|
+
if v.ctype == MKIt::CType::DOCKER_STORAGE.to_s
|
290
|
+
srv['volumes'] << "docker://#{v.name}:#{v.path}"
|
291
|
+
elsif v.ctype == MKIt::CType::LOCAL_STORAGE.to_s
|
292
|
+
srv['volumes'] << "#{v.name}:#{v.path}"
|
293
|
+
end
|
294
|
+
}
|
295
|
+
srv['environment'] = {}
|
296
|
+
self.service_config.each { |c|
|
297
|
+
srv['environment'][c.key] = "#{c.value}"
|
298
|
+
}
|
299
|
+
yaml
|
300
|
+
end
|
301
|
+
|
248
302
|
def as_json(options = {})
|
249
303
|
srv = super
|
250
304
|
a=[:pod, :volume, :service_config, :service_port]
|
@@ -56,6 +56,8 @@ class CommandParser
|
|
56
56
|
end
|
57
57
|
raise InvalidParametersException.new('Invalid command or parameters.', c) if request.nil?
|
58
58
|
|
59
|
+
fill_request_defaults(request, request_data)
|
60
|
+
|
59
61
|
validate_command(command, request_data)
|
60
62
|
#
|
61
63
|
{
|
@@ -65,16 +67,41 @@ class CommandParser
|
|
65
67
|
}
|
66
68
|
end
|
67
69
|
|
70
|
+
def fill_request_defaults(request, request_data)
|
71
|
+
if !request.nil? && !request[:defaults].nil?
|
72
|
+
request[:defaults].each do |key, value|
|
73
|
+
request[:params] ||= []
|
74
|
+
unless request[:params].include?(key.to_sym)
|
75
|
+
request[:params] << key.to_sym
|
76
|
+
request_data[key.to_sym] = value
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
68
82
|
# args = command[:args]
|
69
83
|
# argv = ARGV.dup - cmd
|
70
84
|
# request = command[:request]
|
71
85
|
# request_data = {}
|
72
86
|
def fill_cmd_args(args, argv, request, request_data)
|
73
87
|
return if args.nil?
|
74
|
-
# add to schema
|
75
88
|
args.each do |arg|
|
76
89
|
arg[:type] = 'value' unless arg[:type]
|
77
90
|
end
|
91
|
+
split = split_argv(argv)
|
92
|
+
argv = split[0]
|
93
|
+
varargs = split[1]
|
94
|
+
varargs = nil if varargs.empty?
|
95
|
+
|
96
|
+
# find vararg and fill it
|
97
|
+
vararg = args.select { |arg| arg[:type].to_sym == :varargs }.first
|
98
|
+
if vararg
|
99
|
+
request_data[vararg[:name].to_sym] = varargs
|
100
|
+
request[:params] ||= []
|
101
|
+
request[:params] << vararg[:name].to_sym unless request[:params].include?(vararg[:name].to_sym)
|
102
|
+
request_data[vararg[:name].to_sym] = varargs
|
103
|
+
end
|
104
|
+
|
78
105
|
# flag and options
|
79
106
|
fill_flag_and_options_args(args, argv, request, request_data)
|
80
107
|
idx = 0
|
@@ -88,6 +115,18 @@ class CommandParser
|
|
88
115
|
end
|
89
116
|
end
|
90
117
|
|
118
|
+
def split_argv(argv)
|
119
|
+
separator_index = argv.index('--')
|
120
|
+
if separator_index
|
121
|
+
left_side = argv[0...separator_index]
|
122
|
+
right_side = argv[(separator_index + 1)..-1]
|
123
|
+
else
|
124
|
+
left_side = argv
|
125
|
+
right_side = []
|
126
|
+
end
|
127
|
+
[left_side, right_side]
|
128
|
+
end
|
129
|
+
|
91
130
|
def fill_flag_and_options_args(args, argv, request, request_data)
|
92
131
|
# flags
|
93
132
|
# checking flags first, avoids -n -f, with -f being the value of -n
|
@@ -122,7 +161,7 @@ class CommandParser
|
|
122
161
|
request[:uri] = request[:uri] + arg[:uri] unless arg[:uri].nil?
|
123
162
|
unless arg[:param].nil?
|
124
163
|
request[:params] ||= []
|
125
|
-
request[:params] <<
|
164
|
+
request[:params] << arg[:name].to_sym unless request[:params].include?(arg[:name].to_sym)
|
126
165
|
end
|
127
166
|
end
|
128
167
|
|
@@ -95,6 +95,57 @@
|
|
95
95
|
request:
|
96
96
|
verb: put
|
97
97
|
uri: "/services/<%=id%>"
|
98
|
+
- cmd: get
|
99
|
+
request:
|
100
|
+
verb: get
|
101
|
+
uri: "/services/<%=id%>"
|
102
|
+
defaults:
|
103
|
+
format: yaml
|
104
|
+
usage:
|
105
|
+
- "<service_id_or_name> [options]"
|
106
|
+
help: print service configuration
|
107
|
+
args:
|
108
|
+
- name: id
|
109
|
+
help:
|
110
|
+
- id
|
111
|
+
- Service id or name
|
112
|
+
mandatory: true
|
113
|
+
- name: format
|
114
|
+
help:
|
115
|
+
- -y
|
116
|
+
- ...as yaml format (default)
|
117
|
+
mandatory: false
|
118
|
+
param: "yaml"
|
119
|
+
type: flag
|
120
|
+
switch:
|
121
|
+
- "-y"
|
122
|
+
- name: format
|
123
|
+
help:
|
124
|
+
- -j
|
125
|
+
- ...as json format
|
126
|
+
mandatory: false
|
127
|
+
param: "json"
|
128
|
+
type: flag
|
129
|
+
switch:
|
130
|
+
- "-j"
|
131
|
+
- name: format
|
132
|
+
help:
|
133
|
+
- -t
|
134
|
+
- ...as table format (i.e. status format)
|
135
|
+
mandatory: false
|
136
|
+
param: "table"
|
137
|
+
type: flag
|
138
|
+
switch:
|
139
|
+
- "-t"
|
140
|
+
- name: details
|
141
|
+
help:
|
142
|
+
- -d
|
143
|
+
- include service dynamic details
|
144
|
+
mandatory: false
|
145
|
+
param: "<%=true%>"
|
146
|
+
type: flag
|
147
|
+
switch:
|
148
|
+
- "-d"
|
98
149
|
- cmd: rm
|
99
150
|
usage:
|
100
151
|
- "<service_id_or_name>"
|
@@ -108,9 +159,53 @@
|
|
108
159
|
request:
|
109
160
|
verb: delete
|
110
161
|
uri: "/services/<%=id%>"
|
162
|
+
- cmd: exec
|
163
|
+
usage:
|
164
|
+
- "<service_id_or_name> [options] -- <command> [args...]"
|
165
|
+
help: execute a command in a running pod
|
166
|
+
request:
|
167
|
+
verb: ws_console
|
168
|
+
uri: "/services/<%=id%>/pods/exec"
|
169
|
+
args:
|
170
|
+
- name: id
|
171
|
+
help:
|
172
|
+
- id
|
173
|
+
- Service id or name
|
174
|
+
mandatory: true
|
175
|
+
- name: pod_id
|
176
|
+
help:
|
177
|
+
- -p <pod_id>
|
178
|
+
- Execute command for specified pod (default first)
|
179
|
+
mandatory: false
|
180
|
+
param: "<%=pod_id%>"
|
181
|
+
type: option
|
182
|
+
switch:
|
183
|
+
- "-p"
|
184
|
+
- name: detached
|
185
|
+
help:
|
186
|
+
- -d
|
187
|
+
- Run command in background
|
188
|
+
mandatory: false
|
189
|
+
param: "<%=true%>"
|
190
|
+
type: flag
|
191
|
+
switch:
|
192
|
+
- "-d"
|
193
|
+
- name: separator
|
194
|
+
help:
|
195
|
+
- --
|
196
|
+
- Ends mkit options and starts the command
|
197
|
+
mandatory: false
|
198
|
+
type: separator
|
199
|
+
- name: varargs
|
200
|
+
help:
|
201
|
+
- command
|
202
|
+
- Command and options
|
203
|
+
mandatory: true
|
204
|
+
type: varargs
|
205
|
+
param: <%=varargs%>
|
111
206
|
- cmd: logs
|
112
207
|
usage:
|
113
|
-
- "<service_id_or_name> [-f] [-n <lines>]"
|
208
|
+
- "<service_id_or_name> [-p <pod_id>] [-f] [-n <lines>]"
|
114
209
|
help: view service logs
|
115
210
|
request:
|
116
211
|
verb: ws # new type
|
@@ -123,6 +218,15 @@
|
|
123
218
|
help:
|
124
219
|
- id
|
125
220
|
- Service id or name
|
221
|
+
- name: pod_id
|
222
|
+
help:
|
223
|
+
- -p <pod_id>
|
224
|
+
- Show logs for specified pod (default first)
|
225
|
+
mandatory: false
|
226
|
+
param: "<%=pod_id%>"
|
227
|
+
type: option
|
228
|
+
switch:
|
229
|
+
- "-p"
|
126
230
|
- name: follow
|
127
231
|
help:
|
128
232
|
- -f
|
@@ -141,17 +245,8 @@
|
|
141
245
|
type: option
|
142
246
|
switch:
|
143
247
|
- "-n"
|
144
|
-
- name: pods
|
145
|
-
help:
|
146
|
-
- -p <[pods]>
|
147
|
-
- Show logs for specified pods, e.g. pod1, pod2 (default first)
|
148
|
-
mandatory: false
|
149
|
-
param: "<%=pods%>"
|
150
|
-
type: option
|
151
|
-
switch:
|
152
|
-
- "-n"
|
153
248
|
- cmd: version
|
154
|
-
help: prints mkit server version
|
249
|
+
help: prints mkit client and server version
|
155
250
|
request:
|
156
251
|
verb: get
|
157
252
|
uri: "/mkit/version"
|
@@ -0,0 +1,57 @@
|
|
1
|
+
# # frozen_string_literal: true
|
2
|
+
require 'faye/websocket'
|
3
|
+
require 'eventmachine'
|
4
|
+
require 'json'
|
5
|
+
require 'io/console'
|
6
|
+
|
7
|
+
module MKIt
|
8
|
+
class ConsoleWebSocketClient
|
9
|
+
|
10
|
+
def initialize(uri, options)
|
11
|
+
@uri = uri
|
12
|
+
@options = options
|
13
|
+
end
|
14
|
+
|
15
|
+
def doIt
|
16
|
+
EM.run {
|
17
|
+
ws = Faye::WebSocket::Client.new(@uri, nil, @options)
|
18
|
+
|
19
|
+
ws.on :open do |_event|
|
20
|
+
puts "Connected to remote server"
|
21
|
+
puts "\r\n"
|
22
|
+
end
|
23
|
+
|
24
|
+
ws.on :message do |event|
|
25
|
+
print event.data
|
26
|
+
end
|
27
|
+
|
28
|
+
ws.on :error do |event|
|
29
|
+
p [:error, event.message]
|
30
|
+
ws = nil
|
31
|
+
EventMachine.stop
|
32
|
+
end
|
33
|
+
|
34
|
+
ws.on :close do |_event|
|
35
|
+
ws = nil
|
36
|
+
puts "\r\n"
|
37
|
+
EventMachine.stop
|
38
|
+
end
|
39
|
+
|
40
|
+
Thread.new do
|
41
|
+
STDIN.raw do
|
42
|
+
loop do
|
43
|
+
input = STDIN.getc.chr
|
44
|
+
# if input == "\u0003" # Ctrl+C
|
45
|
+
# puts "bye..."
|
46
|
+
# EventMachine.stop
|
47
|
+
# break
|
48
|
+
# else
|
49
|
+
ws.send(input)
|
50
|
+
# end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
}
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -38,15 +38,17 @@ module MKIt
|
|
38
38
|
@client.request(req)
|
39
39
|
end
|
40
40
|
|
41
|
-
def request(request, request_data =
|
41
|
+
def request(request, request_data = {})
|
42
42
|
req = nil
|
43
43
|
uri = request[:uri]
|
44
44
|
request[:file] = request_data[:file]
|
45
45
|
|
46
46
|
unless request[:params].nil? || request[:params].empty?
|
47
|
-
uri = uri + '?' + request[:params].map { |k
|
47
|
+
uri = uri + '?' + request[:params].map { |k| "#{k}=#{request_data[k]}" }.join('&')
|
48
48
|
end
|
49
49
|
uri = ERB.new(uri).result_with_hash(request_data)
|
50
|
+
# puts "Request URI: #{uri}"
|
51
|
+
|
50
52
|
case request[:verb].to_sym
|
51
53
|
when :post
|
52
54
|
req = Net::HTTP::Post.new(uri)
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# # frozen_string_literal: true
|
2
|
+
require 'faye/websocket'
|
3
|
+
require 'eventmachine'
|
4
|
+
require 'json'
|
5
|
+
require 'io/console'
|
6
|
+
|
7
|
+
module MKIt
|
8
|
+
class LogWebSocketClient
|
9
|
+
|
10
|
+
def initialize(uri, options)
|
11
|
+
@uri = uri
|
12
|
+
@options = options
|
13
|
+
trap("SIGINT") do
|
14
|
+
puts "Bye..."
|
15
|
+
EventMachine.stop
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def doIt
|
20
|
+
EM.run {
|
21
|
+
ws = Faye::WebSocket::Client.new(@uri, nil, @options)
|
22
|
+
|
23
|
+
ws.on :open do |_event|
|
24
|
+
puts "Connected to remote server"
|
25
|
+
puts "\r\n"
|
26
|
+
end
|
27
|
+
|
28
|
+
ws.on :message do |event|
|
29
|
+
puts event.data
|
30
|
+
end
|
31
|
+
|
32
|
+
ws.on :error do |event|
|
33
|
+
p [:error, event.message]
|
34
|
+
ws = nil
|
35
|
+
EventMachine.stop
|
36
|
+
end
|
37
|
+
|
38
|
+
ws.on :close do |_event|
|
39
|
+
ws = nil
|
40
|
+
puts "\r\n"
|
41
|
+
EventMachine.stop
|
42
|
+
end
|
43
|
+
}
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -6,7 +6,7 @@ module MKIt
|
|
6
6
|
class MKItdClient
|
7
7
|
def initialize(request, server_url, my_id)
|
8
8
|
case request[:verb].to_sym
|
9
|
-
when :ws
|
9
|
+
when :ws, :ws_console
|
10
10
|
@client = MKIt::WebSocketClient.new(server_url, my_id)
|
11
11
|
else
|
12
12
|
@client = MKIt::HttpClient.new(server_url, my_id)
|
@@ -14,6 +14,8 @@ module MKIt
|
|
14
14
|
end
|
15
15
|
|
16
16
|
def request(request, request_data)
|
17
|
+
# puts "Request: #{request}"
|
18
|
+
# puts "Request data: #{request_data}"
|
17
19
|
@client.request(request, request_data)
|
18
20
|
end
|
19
21
|
end
|
@@ -2,9 +2,13 @@
|
|
2
2
|
require 'faye/websocket'
|
3
3
|
require 'eventmachine'
|
4
4
|
require 'json'
|
5
|
+
require 'io/console'
|
6
|
+
require 'mkit/client/console_websocket_client'
|
7
|
+
require 'mkit/client/log_websocket_client'
|
5
8
|
|
6
9
|
module MKIt
|
7
10
|
class WebSocketClient
|
11
|
+
|
8
12
|
def initialize(server_url, my_id)
|
9
13
|
@server_url = server_url
|
10
14
|
@my_id = my_id
|
@@ -14,52 +18,23 @@ module MKIt
|
|
14
18
|
@options[:headers] = { 'X-API-KEY' => @my_id }
|
15
19
|
url_prefix = use_ssl ? "wss" : "ws"
|
16
20
|
@ws_url = "#{url_prefix}://#{uri.host}:#{uri.port}"
|
17
|
-
trap("SIGINT") do
|
18
|
-
puts "Bye..."
|
19
|
-
EventMachine.stop
|
20
|
-
end
|
21
21
|
end
|
22
22
|
|
23
23
|
def request(request, request_data)
|
24
24
|
uri = request[:uri]
|
25
25
|
unless request[:params].nil? || request[:params].empty?
|
26
|
-
uri = uri + '?' + request[:params].map { |k
|
26
|
+
uri = uri + '?' + request[:params].map { |k| "#{k}=#{request_data[k]}" }.join('&')
|
27
27
|
end
|
28
28
|
uri = ERB.new("#{@ws_url}#{uri}").result_with_hash(request_data)
|
29
|
-
|
30
|
-
EM.run {
|
31
|
-
ws = Faye::WebSocket::Client.new(uri, nil, @options)
|
32
|
-
|
33
|
-
ws.on :open do |event|
|
34
|
-
# no op
|
35
|
-
end
|
36
29
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
return
|
45
|
-
end
|
46
|
-
|
47
|
-
ws.on :close do |event|
|
48
|
-
ws = nil
|
49
|
-
EventMachine.stop
|
50
|
-
end
|
30
|
+
case request[:verb].to_sym
|
31
|
+
when :ws_console
|
32
|
+
client = ConsoleWebSocketClient.new(uri, @options)
|
33
|
+
when :ws
|
34
|
+
client = LogWebSocketClient.new(uri, @options)
|
35
|
+
end
|
36
|
+
client.doIt
|
51
37
|
|
52
|
-
Thread.new do
|
53
|
-
loop do
|
54
|
-
input = STDIN.gets.chomp
|
55
|
-
if input == 'exit'
|
56
|
-
puts "bye..."
|
57
|
-
EventMachine.stop
|
58
|
-
break
|
59
|
-
end
|
60
|
-
end
|
61
|
-
end
|
62
|
-
}
|
63
38
|
end
|
64
39
|
end
|
65
40
|
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require "mkit/cmd/shell_client"
|
2
|
+
|
3
|
+
module MKIt
|
4
|
+
class DockerExecCommand < MKIt::ShellClient
|
5
|
+
|
6
|
+
def initialize(pod, ws, options: {})
|
7
|
+
puts "DockerExecCommand: #{options}"
|
8
|
+
@pod = pod
|
9
|
+
@ws = ws
|
10
|
+
command = "docker exec"
|
11
|
+
command += " -it" unless options[:detached] == 'true'
|
12
|
+
command += " -d" if options[:detached] == 'true'
|
13
|
+
command += " #{@pod.name}"
|
14
|
+
command += " #{options[:varargs].join(' ')}" if options[:varargs]
|
15
|
+
super(command: command)
|
16
|
+
end
|
17
|
+
|
18
|
+
def register
|
19
|
+
super do |stdout, stdin, pid|
|
20
|
+
@stdout_thread = Thread.new do
|
21
|
+
stdout.each_char { |line| @ws.send(line) }
|
22
|
+
end
|
23
|
+
|
24
|
+
@stdin_thread = Thread.new do
|
25
|
+
@ws.onmessage do |msg|
|
26
|
+
stdin.putc msg
|
27
|
+
end
|
28
|
+
end
|
29
|
+
@stdout_thread.join
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def close
|
34
|
+
@ws.close_websocket unless @ws.nil?
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
data/lib/mkit/version.rb
CHANGED
data/lib/mkit.rb
CHANGED
@@ -16,7 +16,7 @@ require 'mkit/config/load_default_configs'
|
|
16
16
|
require_relative 'mkit/version'
|
17
17
|
require_relative 'mkit/mkit_interface'
|
18
18
|
require_relative 'mkit/mkit_dns'
|
19
|
-
require_relative 'mkit/docker_listener'
|
19
|
+
require_relative 'mkit/pods/docker_listener'
|
20
20
|
require 'mkit/app/helpers/haproxy'
|
21
21
|
require 'mkit/app/controllers/services_controller'
|
22
22
|
require 'mkit/app/controllers/mkitjobs_controller'
|
@@ -26,7 +26,6 @@ require 'mkit/mkit_dns'
|
|
26
26
|
require 'mkit/job_manager'
|
27
27
|
require 'mkit/workers/worker_manager'
|
28
28
|
require 'mkit/sagas/saga_manager'
|
29
|
-
require 'mkit/docker_listener'
|
30
29
|
require 'mkit/app/helpers/haproxy'
|
31
30
|
require 'active_record/tasks/database_tasks'
|
32
31
|
require 'mkit/utils'
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mkit
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.9.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Vasco Santos
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-12-
|
11
|
+
date: 2024-12-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: async-dns
|
@@ -385,6 +385,8 @@ files:
|
|
385
385
|
- lib/mkit/app/helpers/erb_helper.rb
|
386
386
|
- lib/mkit/app/helpers/haproxy.rb
|
387
387
|
- lib/mkit/app/helpers/interface_helper.rb
|
388
|
+
- lib/mkit/app/helpers/params_helper.rb
|
389
|
+
- lib/mkit/app/helpers/pods_helper.rb
|
388
390
|
- lib/mkit/app/helpers/services_helper.rb
|
389
391
|
- lib/mkit/app/mkit_server.rb
|
390
392
|
- lib/mkit/app/model/dns_host.rb
|
@@ -402,7 +404,9 @@ files:
|
|
402
404
|
- lib/mkit/app/templates/haproxy/xapp_haproxy.cfg.erb
|
403
405
|
- lib/mkit/client/command_parser.rb
|
404
406
|
- lib/mkit/client/commands.yaml
|
407
|
+
- lib/mkit/client/console_websocket_client.rb
|
405
408
|
- lib/mkit/client/http_client.rb
|
409
|
+
- lib/mkit/client/log_websocket_client.rb
|
406
410
|
- lib/mkit/client/mkitd_client.rb
|
407
411
|
- lib/mkit/client/websocket_client.rb
|
408
412
|
- lib/mkit/cmd/shell_client.rb
|
@@ -414,12 +418,13 @@ files:
|
|
414
418
|
- lib/mkit/config/load_default_configs.rb
|
415
419
|
- lib/mkit/config/the_config.yml
|
416
420
|
- lib/mkit/ctypes.rb
|
417
|
-
- lib/mkit/docker_listener.rb
|
418
|
-
- lib/mkit/docker_log_listener.rb
|
419
421
|
- lib/mkit/exceptions.rb
|
420
422
|
- lib/mkit/job_manager.rb
|
421
423
|
- lib/mkit/mkit_dns.rb
|
422
424
|
- lib/mkit/mkit_interface.rb
|
425
|
+
- lib/mkit/pods/docker_exec_command.rb
|
426
|
+
- lib/mkit/pods/docker_listener.rb
|
427
|
+
- lib/mkit/pods/docker_log_listener.rb
|
423
428
|
- lib/mkit/sagas/asaga.rb
|
424
429
|
- lib/mkit/sagas/create_pod_saga.rb
|
425
430
|
- lib/mkit/sagas/saga_manager.rb
|
@@ -447,7 +452,6 @@ files:
|
|
447
452
|
- samples/apps/redis.yml
|
448
453
|
- samples/daemontools/log/run
|
449
454
|
- samples/daemontools/run
|
450
|
-
- samples/soketi.yaml
|
451
455
|
- samples/systemd/mkitd.service
|
452
456
|
homepage: https://github.com/valexsantos/mkit
|
453
457
|
licenses:
|
data/samples/soketi.yaml
DELETED
@@ -1,32 +0,0 @@
|
|
1
|
-
service:
|
2
|
-
name: soketi
|
3
|
-
image: quay.io/soketi/soketi:0.17-16-alpine
|
4
|
-
# image: giovannedev/soketi:latest
|
5
|
-
ports:
|
6
|
-
#- 80:6001:http:round_robin
|
7
|
-
- 6001:6001:tcp:round_robin
|
8
|
-
- 6002:6001:tcp:round_robin:ssl
|
9
|
-
- 9601:9601:tcp:round_robin
|
10
|
-
resources:
|
11
|
-
max_replicas: 1
|
12
|
-
min_replicas: 1
|
13
|
-
environment:
|
14
|
-
SOKETI_PORT: 6001
|
15
|
-
SOKETI_METRICS_SERVER_PORT: 9601
|
16
|
-
SOKETI_DEBUG: 1
|
17
|
-
SOKETI_MODE: full
|
18
|
-
SOKETI_APP_ID: app-id
|
19
|
-
SOKETI_APP_KEY: app-key
|
20
|
-
SOKETI_APP_SECRET: app-secret
|
21
|
-
# PUSHER_HOST: 127.0.0.1
|
22
|
-
# PUSHER_PORT: 6001
|
23
|
-
# PUSHER_SCHEME: http # or https
|
24
|
-
SOKETI_PORT: 6001
|
25
|
-
SOKETI_SCHEME: http # or https
|
26
|
-
METRICS_SERVER_PORT: 9601
|
27
|
-
SOKETI_DEFAULT_APP_ENABLED: true
|
28
|
-
SOKETI_DEFAULT_APP_ENABLE_CLIENT_MESSAGES: true
|
29
|
-
DEFAULT_APP_ENABLE_CLIENT_MESSAGES: true
|
30
|
-
#SOKETI_DB_REDIS_HOST: redis
|
31
|
-
#SOKETI_DB_REDIS_PORT: 6379
|
32
|
-
#SOKETI_DB_REDIS_PASSWORD: password
|
File without changes
|
File without changes
|