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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2ddd1f77569b1f7982812ae1cf236b76816bd6fc31a27cde9067e010a296c981
4
- data.tar.gz: cedb9272ef3c6ce621989c94a2fd08bf917e7a1f242c4f465306d82749af103c
3
+ metadata.gz: 567f1ce28fb7c14d9eb23ddd36c4f98f68516b1c967450ec11188bfc460f5fdb
4
+ data.tar.gz: 389a9060968047e9efb35ba47cdf3492d4ed47d8f92ce5e82203bb0668dd5ec1
5
5
  SHA512:
6
- metadata.gz: 5ae6c65f2c6b68e116c66c8ac5716f5668d7642922869fdccbf55264d9f9bd96bc36320148bcd9e7d0f2909d010f1caf55e18095c301415432e48a2ecb5845dc
7
- data.tar.gz: ad171bc7fa68ac93813dd15675119bc328f929063694c4627c7db013a5ad938dfdbedb0c8a7a9e45fbfc5b2ae834ef11ca4a24fae16ff37cd81c1f9d0a1da2b4
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 docker instances.
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
@@ -4,7 +4,7 @@ require 'mkit/version'
4
4
 
5
5
  class MkitController < MKIt::Server
6
6
  get '/mkit/version' do
7
- "MKIt version #{MKIt::VERSION}\n"
7
+ "MKIt Server version #{MKIt::VERSION}\n"
8
8
  end
9
9
 
10
10
  put '/mkit/proxy/restart' do
@@ -1,16 +1,42 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- class PodsController < MKIt::Server
4
- get '/services/:service_id/pods' do
5
- "Not implemented\n"
6
- end
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
- get '/services/:service_id/pods/:pod_id' do
9
- "Not implemented\n"
10
- end
9
+ class PodsController < MKIt::Server
10
+ helpers MKIt::PodsHelper
11
+ helpers MKIt::ParamsHelper
11
12
 
12
- put '/services/:service_id/pods/:pod_id' do
13
- "Not implemented\n"
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/docker_log_listener'
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 request.env['CONTENT_TYPE'] == 'application/json'
28
- srv.to_json
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(srv.pod.first, ws, options: options_parameter)
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,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module MKIt
4
+ module ParamsHelper
5
+
6
+ def build_options_hash(params:, options:)
7
+ hash = {}
8
+ options.each do |option|
9
+ hash[option] = params[option]
10
+ end
11
+ hash
12
+ end
13
+
14
+ end
15
+ 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(' ')
@@ -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: "#{name}.#{self.service.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] << [ "#{arg[:name]}", "#{arg[:param]}"]
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 = nil)
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, v| "#{k}=#{v}" }.join('&')
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, v| "#{k}=#{v}" }.join('&')
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
- ws.on :message do |event|
38
- puts event.data
39
- end
40
-
41
- ws.on :error do |event|
42
- p [:error, event.message]
43
- ws = nil
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
@@ -1,4 +1,4 @@
1
1
  module MKIt
2
- VERSION = "0.7.2"
2
+ VERSION = "0.9.0"
3
3
  end
4
4
 
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.7.2
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-16 00:00:00.000000000 Z
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