mkit 0.6.2 → 0.7.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: 49770b23e6d2af3c26a6b8e32291ad24b60e56f6e6fee0f308e3c96fd54f9591
4
- data.tar.gz: 2fe4f45739fd054f2399f4d1544b0d2bd736a5cc656ffad79da24a97b24e489d
3
+ metadata.gz: f85d1f4b78a2859ecf2646e493cb8f65a379143cf4ec7ac1928e1fd184f58fe6
4
+ data.tar.gz: e8af8e1747b6a5488f1980c57a13947965d4b8762aa8f8a276bcffd5583a7a5f
5
5
  SHA512:
6
- metadata.gz: c35ab575b4bac80ea1291802c1ee09260529eea8d348b51b22adcd582789f1a902e7f6c1350e3b538b16064dbcaeece6afb80623565e0757f2905f8ffe9ddfa3
7
- data.tar.gz: 5a76b2d8f36eb02815674b1b0af00c8508e8f6dec4f978156e58c8587f01a846ce9bb7c3865887b7452ae2c5232fd10758cde62e800b4104410458234e7cf915
6
+ metadata.gz: 5818402f2e7403254e749a9b69588ab99c944639e652eb7a5b66df35e71c921c4f98c7767bee10fb9dc23d6b3ea6871a86cc948962b73bff3cba80417fc26fc4
7
+ data.tar.gz: 2d592b0ee76177beefd71a0d0b0965d229548d638e2207e54b013633055482ebad3226c641a464138103c56adf3084ec38a7706ae35ad3cf27282647975ee31e
data/Gemfile CHANGED
@@ -1,23 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  source 'https://rubygems.org'
4
-
5
- # ruby '3.0.2'
6
-
7
- gem 'dry-container'
8
- gem 'net-ping'
9
- gem 'rake'
10
- gem 'sqlite3'
11
- gem 'standalone_migrations'
12
- gem 'text-table'
13
-
14
- gem 'async-dns'
15
- gem 'pry'
16
- gem 'rack', '>= 2.0.6'
17
- gem 'rubydns'
18
- gem 'sinatra-activerecord'
19
- # rest http server
20
- gem 'net_http_unix' # socket client
21
- gem 'sinatra'
22
- gem 'thin' # socket server
23
- # gem 'puma'
4
+ gemspec
data/README.md CHANGED
@@ -183,21 +183,21 @@ Micro k8s on Ruby - a simple tool to mimic a (very) minimalistic k8 cluster
183
183
 
184
184
  Commands:
185
185
 
186
- init init mkit client
187
- ps show services status (alias for status)
188
- status show services status
189
- logs prints service logs
190
- start start service
191
- stop stop service
192
- restart restart service
193
- create create new service
194
- update update service
195
- rm remove service
196
- version prints mkit server version
197
- proxy haproxy status and control
198
- profile mkit client configuration profile
199
-
200
- Run 'mkit help <command>' for specific command information.
186
+ init init mkit client
187
+ ps show services status (alias for status)
188
+ status show services status
189
+ start start service
190
+ stop stop service
191
+ restart restart service
192
+ create create new service
193
+ update update service
194
+ rm remove service
195
+ logs view service logs
196
+ version prints mkit server version
197
+ proxy haproxy status and control
198
+ profile mkit client configuration profile
199
+
200
+ Run ' mkit help <command>' for specific command information.
201
201
  ```
202
202
 
203
203
  Example:
data/bin/mkit CHANGED
@@ -11,8 +11,10 @@ require 'securerandom'
11
11
  require 'erb'
12
12
  require 'uri'
13
13
  require 'fileutils'
14
+ require 'mkit/client/command_parser'
15
+ require 'mkit/client/mkitd_client'
14
16
 
15
- class InvalidParametersException < Exception
17
+ class InvalidConfigurationException < Exception
16
18
  attr_reader :command
17
19
 
18
20
  def initialize(cause, command = nil)
@@ -21,164 +23,19 @@ class InvalidParametersException < Exception
21
23
  end
22
24
  end
23
25
 
24
- class CommandPalette
25
- def schema
26
- global_args = [
27
- { short: '-v', long: '--verbose', help: 'verbose', mandatory: false, value: nil }
28
- ]
29
- [
30
- {
31
- cmd: 'init',
32
- help: 'init mkit client',
33
- request: { }
34
- },
35
- {
36
- cmd: 'ps',
37
- args: [
38
- { name: 'id', mandatory: false, uri: '/<%=id%>' }
39
- ],
40
- help: 'show services status (alias for status)',
41
- usage: ['[service_id_or_name]'],
42
- request: { verb: :get, uri: '/services' }
43
- },
44
- {
45
- cmd: 'status',
46
- args: [
47
- { name: 'id', mandatory: false, uri: '/<%=id%>' }
48
- ],
49
- help: 'show services status',
50
- usage: ['[service_id_or_name]'],
51
- request: { verb: :get, uri: '/services' }
52
- },
53
- {
54
- cmd: 'logs',
55
- args: [
56
- { name: 'id', mandatory: true }
57
- ],
58
- help: 'prints service logs',
59
- usage: ['<service_id_or_name>'],
60
- request: { verb: :get, uri: '/services/<%=id%>/logs' }
61
- },
62
- {
63
- cmd: 'start',
64
- args: [
65
- { name: 'id', mandatory: true }
66
- ],
67
- help: 'start service',
68
- usage: ['<service_id_or_name>'],
69
- request: { verb: :put, uri: '/services/<%=id%>/start' }
70
- },
71
- {
72
- cmd: 'stop',
73
- args: [
74
- { name: 'id', mandatory: true }
75
- ],
76
- help: 'stop service',
77
- usage: ['<service_id_or_name>'],
78
- request: { verb: :put, uri: '/services/<%=id%>/stop' }
79
- },
80
- {
81
- cmd: 'restart',
82
- args: [
83
- { name: 'id', mandatory: true }
84
- ],
85
- help: 'restart service',
86
- usage: ['<service_id_or_name>'],
87
- request: { verb: :put, uri: '/services/<%=id%>/restart' }
88
- },
89
- {
90
- cmd: 'create',
91
- args: [
92
- { name: 'file', mandatory: true }
93
- ],
94
- help: 'create new service',
95
- usage: ['<service.yaml>'],
96
- request: { verb: :post, uri: '/services' }
97
- },
98
- {
99
- cmd: 'update',
100
- args: [
101
- { name: 'file', mandatory: true }
102
- ],
103
- help: 'update service',
104
- usage: ['<service.yaml>'],
105
- request: { verb: :put, uri: '/services/<%=id%>' }
106
- },
107
- {
108
- cmd: 'rm',
109
- args: [
110
- { name: 'id', mandatory: true }
111
- ],
112
- help: 'remove service',
113
- usage: ['<service_id_or_name>'],
114
- request: { verb: :delete, uri: '/services/<%=id%>' }
115
- },
116
- {
117
- cmd: 'version',
118
- help: 'prints mkit server version',
119
- request: { verb: :get, uri: '/mkit/version' }
120
- },
121
- {
122
- cmd: 'proxy',
123
- options: [
124
- {
125
- cmd: 'start',
126
- request: { verb: :put, uri: '/mkit/proxy/start' },
127
- help: 'start proxy service'
128
- },
129
- {
130
- cmd: 'stop',
131
- request: { verb: :put, uri: '/mkit/proxy/stop' },
132
- help: 'stop proxy service'
133
- },
134
- {
135
- cmd: 'restart',
136
- request: { verb: :put, uri: '/mkit/proxy/restart' },
137
- help: 'restarts proxy service'
138
- },
139
- {
140
- cmd: 'status',
141
- request: { verb: :get, uri: '/mkit/proxy/status' },
142
- help: 'proxy service status'
143
- }
144
- ],
145
- help: 'haproxy status and control',
146
- usage: ['<start|stop|restart|status>']
147
- },
148
- {
149
- cmd: 'profile',
150
- options: [
151
- {
152
- cmd: 'set',
153
- request: { verb: 'set' },
154
- args: [
155
- { name: 'profile_name', mandatory: true }
156
- ],
157
- help: 'set mkit client configuration profile'
158
- },
159
- {
160
- cmd: 'show',
161
- request: { verb: 'show' },
162
- help: 'show mkit client current profile'
163
- }
164
- ],
165
- help: 'mkit client configuration profile',
166
- usage: ['<[set <profile_name>]|[show]>']
167
- }
168
- ]
169
- end
170
- end
171
-
172
26
  class MKItClient
173
27
  def initialize
174
28
  @root = File.expand_path('..', __dir__)
175
29
  @config_dir = "#{ENV['HOME']}/.mkit"
176
30
  @profile_file = "#{@config_dir}/current"
177
- @commands = CommandPalette.new
178
31
  @config_file = "#{@config_dir}/mkitc_config.yml"
32
+ @parser = CommandParser.new
179
33
  create_default_config
180
34
  end
181
35
 
36
+ #
37
+ # client config
38
+ #
182
39
  def create_default_config
183
40
  unless File.exist?(@config_dir)
184
41
  puts "Creating config directory on '#{@config_dir}'..."
@@ -203,187 +60,41 @@ class MKItClient
203
60
 
204
61
  @configuration = cfg['mkit'][current_profile.lstrip]
205
62
  if !init_call && cfg['my_id'].nil?
206
- raise InvalidParametersException.new("Please run ' mkit init' to initialize mkit client.", find_command('init'))
63
+ raise InvalidParametersException.new("Please run ' mkit init' to initialize mkit client.", @parser.find_command('init'))
207
64
  end
208
65
  @my_id = cfg['my_id']
209
66
  cfg
210
67
  end
211
68
 
212
- def client(req)
69
+ #
70
+ # doIt
71
+ #
72
+ def doIt(argv)
213
73
  read_configuration
214
- req['X-API-KEY'] = @my_id
215
- uri = URI(@configuration['server.uri'])
216
- case uri.scheme
217
- when 'https'
218
- @client = NetX::HTTPUnix.new(uri.host, uri.port)
219
- @client.use_ssl = true
220
- @client.verify_mode = OpenSSL::SSL::VERIFY_NONE
221
- when 'http'
222
- @client = NetX::HTTPUnix.new(uri.host, uri.port)
223
- when 'sock'
224
- @client = NetX::HTTPUnix.new("unix://#{uri.path}")
225
- else
226
- raise InvalidParametersException, 'Invalid mkit server uri. Please check configuration'
227
- end
228
- @client.request(req)
229
- end
230
-
231
- def dict
232
- @commands.schema
233
- end
234
-
235
- def find_command(cmd)
236
- dict.select { |k| k[:cmd] == cmd }.first
237
- end
238
-
239
- def parse_args(args)
240
- cmd = args[0]
241
- c = nil
242
- # short circuit for help
243
- if cmd == 'help' || args.empty?
244
- if args.size > 1
245
- c = find_command(args[1])
246
- raise InvalidParametersException, "'#{args[1]}' is not a valid help topic." if c.nil?
247
- end
248
- return help(cmd: c)
249
- else
250
- c = find_command(cmd)
251
- end
252
- raise InvalidParametersException, 'Command not found' if c.nil?
253
-
254
- command = c
255
- myargs = args.dup
256
- myargs.delete(cmd)
257
-
258
- request_hash = {}
259
- request = command[:request]
260
- unless myargs.empty?
261
- # options
262
- unless c[:options].nil?
263
- command = c[:options].select { |o| o[:cmd] == myargs[0] }.first
264
- raise InvalidParametersException.new('Invalid parameters found.', c) if command.nil? || command.empty?
265
-
266
- myargs.delete_at(0)
267
- request = command[:request]
268
- end
269
- fill_cmd_args(command[:args], myargs, request, request_hash)
270
- end
271
- raise InvalidParametersException.new('Invalid command or parameters.', c) if request.nil?
272
-
273
- validate_command(command, request_hash)
274
- if respond_to? c[:cmd]
275
- send(c[:cmd], request, request_hash)
276
- else
277
- request(request, request_hash)
278
- end
279
- end
280
-
281
- def fill_cmd_args(args, myargs, request, request_hash)
282
- return if args.nil?
283
-
284
- idx = 0
285
- args.each do |a|
286
- request_hash[a[:name].to_sym] = myargs[idx]
287
- request[:uri] = request[:uri] + a[:uri] unless a[:uri].nil?
288
- idx += 1
289
- end
290
- end
291
-
292
- def validate_command(command, request_hash)
293
- return if command[:args].nil?
294
-
295
- command[:args].select { |a| a[:mandatory] == true }.each do |a|
296
- if request_hash[a[:name].to_sym].nil?
297
- raise InvalidParametersException.new("Missing mandatory parameter: #{a[:name]}", command)
298
- end
299
- end
300
- end
301
-
302
- def request(request, request_args = nil)
303
- req = nil
304
- uri = ERB.new(request[:uri]).result_with_hash(request_args)
305
- request[:file] = request_args[:file]
306
-
307
- unless request[:params].nil? || request[:params].empty?
308
- uri = uri + '?' + request[:params].map { |k, v| "#{k}=#{v}" }.join('&')
309
- end
310
- case request[:verb]
311
- when :post
312
- req = Net::HTTP::Post.new(uri)
313
- unless request[:file].nil?
314
- (body, boundary) = attach(request[:file])
315
- req.body = body
316
- req['Content-Type'] = "multipart/form-data, boundary=#{boundary}"
317
- end
318
- when :put
319
- req = Net::HTTP::Put.new(uri)
320
- unless request[:file].nil?
321
- (body, boundary) = attach(request[:file])
322
- req.body = body
323
- req['Content-Type'] = "multipart/form-data, boundary=#{boundary}"
324
- end
325
- when :patch
326
- req = Net::HTTP::Patch.new(uri)
327
- when :get
328
- req = Net::HTTP::Get.new(uri)
329
- when :delete
330
- req = Net::HTTP::Delete.new(uri)
331
- end
332
- client(req).body
333
- end
334
-
335
- def attach(file)
336
- boundary = SecureRandom.alphanumeric
337
- body = []
338
- body << "--#{boundary}\r\n"
339
- body << "Content-Disposition: form-data; name=file; filename='#{File.basename(file)}'\r\n"
340
- body << "Content-Type: text/plain\r\n"
341
- body << "\r\n"
342
- body << File.read(file)
343
- body << "\r\n--#{boundary}--\r\n"
344
- [body.join, boundary]
345
- end
346
-
347
- def doIt(args)
348
- result = parse_args(args)
74
+ request = @parser.parse(argv)
75
+ result = execute(request)
349
76
  puts result
350
77
  rescue InvalidParametersException => e
351
- help(cause: e)
78
+ @parser.help(cause: e)
352
79
  end
353
80
 
354
- def help(cause: nil, cmd: nil)
355
- msg = ''
356
- if cause.nil?
357
- my_cmd = cmd
358
- else
359
- msg += "MKItc: #{cause.message}\n"
360
- my_cmd = cause.command
361
- end
362
- if my_cmd.nil?
363
- msg += "\nUsage: mkit <command> [options]\n\n"
364
- msg += "Micro k8s on Ruby - a simple tool to mimic a (very) minimalistic k8 cluster\n\n"
365
- msg += "Commands:\n\n"
366
- dict.each do |c|
367
- msg += format("%-10s %s\n", c[:cmd], c[:help])
368
- end
369
- msg += "\n"
370
- msg += "Run ' mkit help <command>' for specific command information.\n\n"
81
+ def execute(request)
82
+ if respond_to? request[:cmd]
83
+ send(request[:cmd], request[:request], request[:data])
371
84
  else
372
- msg += format("\nUsage: mkit %s %s\n\n", my_cmd[:cmd], my_cmd[:usage].nil? ? '' : my_cmd[:usage].join(' '))
373
- msg += format("%s\n", my_cmd[:help])
374
- unless my_cmd[:options].nil?
375
- msg += "\nOptions:\n"
376
- my_cmd[:options].each do |c|
377
- msg += format("%-10s %s\n", c[:cmd], c[:help])
378
- end
379
- end
380
- msg += "\n"
85
+ request(request[:request], request[:data])
381
86
  end
382
- puts msg
383
- exit 1
384
87
  end
385
88
 
386
- def init(request, request_hash = nil)
89
+ def request(request, request_data)
90
+ client = MKIt::MKItdClient.new(request, @configuration['server.uri'], @my_id)
91
+ client.request(request, request_data)
92
+ end
93
+
94
+ #
95
+ # commands
96
+ #
97
+ def init(request, request_data = nil)
387
98
  cfg = read_configuration(true)
388
99
  if cfg['my_id'].nil?
389
100
  my_id = SecureRandom.uuid.gsub('-','')
@@ -395,37 +106,38 @@ class MKItClient
395
106
  end
396
107
  puts "Your api-key is #{my_id}"
397
108
  end
398
- def create(request, request_hash = nil)
399
- unless File.file?(request_hash[:file])
400
- raise InvalidParametersException.new('File not found.', find_command('create'))
109
+
110
+ def create(request, request_data = nil)
111
+ unless File.file?(request_data[:file])
112
+ raise InvalidParametersException.new('File not found.', @parser.find_command('create'))
401
113
  end
402
114
 
403
- yaml = YAML.load_file(request_hash[:file])
115
+ yaml = YAML.load_file(request_data[:file])
404
116
  if yaml['service'].nil?
405
- raise InvalidParametersException.new('Invalid configuration file', find_command('create'))
117
+ raise InvalidParametersException.new('Invalid configuration file', @parser.find_command('create'))
406
118
  else
407
- request(request, request_hash)
119
+ request(request, request_data)
408
120
  end
409
121
  end
410
122
 
411
- def update(request, request_hash = nil)
412
- unless File.file?(request_hash[:file])
413
- raise InvalidParametersException.new('File not found.', find_command('update'))
123
+ def update(request, request_data = nil)
124
+ unless File.file?(request_data[:file])
125
+ raise InvalidParametersException.new('File not found.', @parser.find_command('update'))
414
126
  end
415
127
 
416
- yaml = YAML.load_file(request_hash[:file])
128
+ yaml = YAML.load_file(request_data[:file])
417
129
  if yaml['service'].nil?
418
- raise InvalidParametersException.new('Invalid configuration file', find_command('update'))
130
+ raise InvalidParametersException.new('Invalid configuration file', @parser.find_command('update'))
419
131
  else
420
132
  id = yaml['service']['name']
421
- request_hash[:id] = id
422
- request(request, request_hash)
133
+ request_data[:id] = id
134
+ request(request, request_data)
423
135
  end
424
136
  end
425
137
 
426
- def profile(request, request_hash = {})
138
+ def profile(request, request_data = {})
427
139
  cfg = YAML.load_file("#{@config_dir}/mkitc_config.yml")
428
- cmd = find_command('profile')
140
+ cmd = @parser.find_command('profile')
429
141
  if cfg['mkit'].nil?
430
142
  raise InvalidParametersException.new(
431
143
  "Invalid configuration on '~/.mkit'\nPlease fix or clean up for defaults apply", cmd
@@ -434,13 +146,13 @@ class MKItClient
434
146
 
435
147
  case request[:verb]
436
148
  when 'set'
437
- profile = request_hash[:profile_name]
149
+ profile = request_data[:profile_name]
438
150
  if cfg['mkit'][profile.lstrip].nil?
439
151
  raise InvalidParametersException.new("Profile not found on '~/.mkit' configuration", cmd)
440
152
  end
441
153
 
442
154
  puts "Setting current profile to #{profile}."
443
- File.write(@profile_file, request_hash[:profile_name])
155
+ File.write(@profile_file, request_data[:profile_name])
444
156
  ''
445
157
  when 'show'
446
158
  active = File.read("#{@config_dir}/current")
@@ -18,12 +18,6 @@ class PodsController < MKIt::Server
18
18
  end
19
19
 
20
20
  post '/services/:service_id/pods' do
21
- xx = 'no file'
22
- if params[:file]
23
- tempfile = params[:file][:tempfile]
24
- xx = YAML.safe_load(tempfile.read)
25
- puts xx
26
- end
27
- JSON.pretty_generate(JSON.parse(xx.to_json))
21
+ "Not implemented\n"
28
22
  end
29
23
  end
@@ -2,6 +2,7 @@
2
2
 
3
3
  require 'mkit/app/model/service'
4
4
  require 'mkit/app/helpers/services_helper'
5
+ require 'mkit/docker_log_listener'
5
6
 
6
7
  class ServicesController < MKIt::Server
7
8
  helpers MKIt::ServicesHelper
@@ -33,7 +34,33 @@ class ServicesController < MKIt::Server
33
34
 
34
35
  get '/services/:id/logs' do
35
36
  srv = find_by_id_or_name
36
- srv.log
37
+ if !request.websocket?
38
+ srv.log
39
+ else
40
+ options_parameter = build_options_hash(params: params, options: [:nr_lines, :pods, :follow])
41
+ request.websocket do |ws|
42
+ listener = nil
43
+ ws.onopen do
44
+ settings.sockets << ws
45
+ ws.send("<<<< %s | %s >>>>\n" % [srv.name, srv.pod.first.name])
46
+ listener = MKIt::DockerLogListener.new(srv.pod.first, ws, options: options_parameter)
47
+ settings.listeners << listener
48
+ listener.register
49
+ end
50
+ ws.onmessage do |msg|
51
+ puts msg
52
+ end
53
+ ws.onclose do
54
+ MKItLogger.info("websocket closed [#{listener}]")
55
+ settings.sockets.delete(ws)
56
+ if listener
57
+ MKItLogger.info("unregister [#{listener}]")
58
+ settings.listeners.delete(listener)
59
+ listener.unregister
60
+ end
61
+ end
62
+ end
63
+ end
37
64
  end
38
65
 
39
66
  # curl -X PUT localhost:4567/services/1 -F "file=@mkit/samples/mkit.yml"
@@ -16,6 +16,13 @@ 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
19
26
  def find_by_id_or_name
20
27
  srv = Service.find_by_id(params[:id])
21
28
  srv ||= Service.find_by_name(params[:id])
@@ -8,6 +8,8 @@ module MKIt
8
8
  set :dump_errors, true
9
9
  set :show_exceptions, false
10
10
  set :raise_errors, false
11
+ set :sockets, []
12
+ set :listeners, []
11
13
 
12
14
  before do
13
15
  api_key = request.env['HTTP_X_API_KEY']
@@ -241,7 +241,6 @@ class Service < ActiveRecord::Base
241
241
  out = ""
242
242
  self.pod.each { |p|
243
243
  out << "<<<< %s | %s >>>>\n" % [self.name, p.name]
244
- puts logs(p.name)
245
244
  out << logs(p.name)
246
245
  }
247
246
  out