squared 0.4.8 → 0.4.10

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.
@@ -4,8 +4,6 @@ module Squared
4
4
  module Workspace
5
5
  module Project
6
6
  class Docker < Base
7
- include Prompt
8
-
9
7
  COMPOSEFILE = %w[compose.yaml compose.yml docker-compose.yaml compose.yml docker-compose.yml].freeze
10
8
  BAKEFILE = %w[docker-bake.json docker-bake.hcl docker-bake.override.json docker-bake.override.hcl].freeze
11
9
  DIR_DOCKER = (COMPOSEFILE + BAKEFILE).freeze
@@ -37,15 +35,15 @@ module Squared
37
35
  run: %w[d|detach init i|interactive no-healthcheck oom-kill-disable privileged P|publish-all q|quiet
38
36
  read-only rm runtime t|tty add-host=q annotation=q a|attach=b blkio-weight-device=i cap-add=b
39
37
  cap-drop=b cgroup-parent=b cgroupns=b cidfile=p detach-keys=q device=q device-cgroup-rule=q
40
- device-read-bps=q device-read-iops=q device-write-bps=q device-write-iops=q
41
- disable-content-trust=b? dns=e dns-option=e dns-search=e domainname=b entrypoint=q e|env=qq
42
- env-file=p expose=e gpus=q group-add=b health-cmd=q health-interval=b health-retries=i
43
- health-start-interval=b health-start-period=b health-timeout=b h|hostname=e io-maxbandwidth=b
44
- io-maxiops=b ip=b ip6=e ipc=b isolation=b kernel-memory=b l|label=q label-file=p link=b
45
- link-local-ip=b log-driver=b log-opt=q mac-address=e memory-swappiness=b mount=qq name=b network=b
46
- network-alias=b oom-score-adj=b pid=b platform=b p|publish=e pull=b restart=b runtime=b
47
- security-opt=q shm-size=b sig-proxy=b? stop-signal=b stop-timeout=i storage-opt=q sysctl=q tmpfs=q
48
- ulimit=q user=e userns=b uts=b v|volume=q volume-driver=b volumes-from=b w|workdir=q].freeze,
38
+ device-read-bps=q device-read-iops=q device-write-bps=q device-write-iops=q disable-content-trust=b?
39
+ dns=e dns-option=e dns-search=e domainname=b entrypoint=q e|env=qq env-file=p expose=e gpus=q
40
+ group-add=b health-cmd=q health-interval=b health-retries=i health-start-interval=b
41
+ health-start-period=b health-timeout=b h|hostname=e io-maxbandwidth=b io-maxiops=b ip=b ip6=e ipc=b
42
+ isolation=b kernel-memory=b l|label=q label-file=p link=b link-local-ip=b log-driver=b log-opt=q
43
+ mac-address=e memory-swappiness=b mount=qq name=b network=b network-alias=b oom-score-adj=b pid=b
44
+ platform=b p|publish=e pull=b restart=b runtime=b security-opt=q shm-size=b sig-proxy=b?
45
+ stop-signal=b stop-timeout=i storage-opt=q sysctl=q tmpfs=q ulimit=q user=e userns=b uts=b
46
+ v|volume=q volume-driver=b volumes-from=b w|workdir=q].freeze,
49
47
  exec: %w[d|detach i|interactive privileged t|tty detach-keys=q e|env=qq env-file=p user=e
50
48
  w|workdir=q].freeze,
51
49
  update: %w[blkio-weight=i cpu-period=i cpu-quota=i cpu-rt-period=i cpu-rt-runtime=i c|cpu-shares=i cpus=f
@@ -163,7 +161,7 @@ module Squared
163
161
  when 'container'
164
162
  case flag
165
163
  when :exec, :commit
166
- format_desc(action, flag, flag == :exec ? 'id/name?,opts*,args+' : 'id/name,tag?,opts*')
164
+ format_desc(action, flag, flag == :exec ? 'id/name,opts*,args+' : 'id/name,tag?,opts*')
167
165
  task flag, [:id] do |_, args|
168
166
  if flag == :exec && !args.id
169
167
  choice_command flag
@@ -173,7 +171,7 @@ module Squared
173
171
  end
174
172
  end
175
173
  when :run
176
- format_desc action, flag, 'image?,opts*,args*'
174
+ format_desc action, flag, 'image,opts*,args*'
177
175
  task flag, [:image] do |_, args|
178
176
  if args.image
179
177
  container(flag, args.extras, id: args.image)
@@ -198,14 +196,19 @@ module Squared
198
196
  when :list, :rm
199
197
  format_desc(action, flag, flag == :rm ? 'id*,opts*' : 'opts*,args*')
200
198
  task flag do |_, args|
201
- image flag, args.to_a
199
+ args = args.to_a
200
+ if flag == :rm && args.empty?
201
+ choice_command :rm
202
+ else
203
+ image flag, args
204
+ end
202
205
  end
203
206
  end
204
207
  when 'network'
205
208
  format_desc action, flag, 'target,opts*'
206
209
  task flag, [:target] do |_, args|
207
- if (target = args.target)
208
- network(flag, args.extras, target: target)
210
+ if args.target
211
+ network(flag, args.extras, target: args.target)
209
212
  else
210
213
  choice_command flag
211
214
  end
@@ -273,7 +276,6 @@ module Squared
273
276
  end
274
277
  if (val = option('tag', ignore: false))
275
278
  append_tag val
276
- ret << basic_option('tag', tagname(val))
277
279
  elsif !session_arg?('t', 'tag')
278
280
  append_tag tag
279
281
  end
@@ -307,7 +309,7 @@ module Squared
307
309
  end
308
310
  end
309
311
  op.append(args, escape: true)
310
- contextdir(context) if context
312
+ contextdir context if context
311
313
  end
312
314
  end
313
315
  op.clear(pass: false)
@@ -333,7 +335,7 @@ module Squared
333
335
  def container(flag, opts = [], id: nil)
334
336
  cmd, opts = docker_session('container', flag, opts: opts)
335
337
  list = OPT_DOCKER[:container].fetch(flag, [])
336
- list.concat(OPT_DOCKER[:container][:update]) if flag == :run
338
+ list += OPT_DOCKER[:container][:update] if flag == :run
337
339
  op = OptionPartition.new(opts, list, cmd, project: self, args: flag == :run || flag == :exec)
338
340
  from = :"container:#{flag}"
339
341
  case flag
@@ -361,7 +363,7 @@ module Squared
361
363
  args << k
362
364
  next
363
365
  when 'source', 'src', 'destination', 'dst', 'target'
364
- v = basepath(v)
366
+ v = path + v
365
367
  v = shell_quote(v, option: false, force: false) if q == ''
366
368
  tmpfs = false if k[0] == 's'
367
369
  end
@@ -420,7 +422,7 @@ module Squared
420
422
  when :rm
421
423
  status = %w[created exited dead]
422
424
  end
423
- ps = docker_output('ps -a', *status.map { |s| "--filter='status=#{s}'" })
425
+ ps = docker_output('ps -a', *status.map { |s| "--filter=\"status=#{s}\"" })
424
426
  list_image(flag, ps, no: no, hint: "status: #{status.join(', ')}", from: from) do |img|
425
427
  run(cmd.temp(img), from: from)
426
428
  end
@@ -435,6 +437,8 @@ module Squared
435
437
  def image(flag, opts = [], sync: true, id: nil, registry: nil)
436
438
  cmd, opts = docker_session('image', flag, opts: opts)
437
439
  op = OptionPartition.new(opts, OPT_DOCKER[:image][flag], cmd, project: self)
440
+ exception = @exception
441
+ banner = true
438
442
  from = :"image:#{flag}"
439
443
  case flag
440
444
  when :list
@@ -457,6 +461,10 @@ module Squared
457
461
  when :rm
458
462
  if id
459
463
  op << id
464
+ if option('y')
465
+ exception = false
466
+ banner = false
467
+ end
460
468
  else
461
469
  if op.empty?
462
470
  list_image(flag, docker_output('image ls -a'), from: from) do |val|
@@ -478,9 +486,12 @@ module Squared
478
486
  img = docker_output 'image', 'tag', id, uri
479
487
  return unless confirm_command(img.to_s, cmd.to_s, target: id, as: registry, title: from)
480
488
 
481
- run(img, exception: true, sync: false, banner: false)
489
+ cmd = img
490
+ sync = false
491
+ exception = true
492
+ banner = false
482
493
  end
483
- run(sync: sync, from: from)
494
+ run(cmd, sync: sync, exception: exception, banner: banner, from: from)
484
495
  end
485
496
 
486
497
  def network(flag, opts = [], target: nil)
@@ -489,7 +500,7 @@ module Squared
489
500
  op.clear
490
501
  from = :"network:#{flag}"
491
502
  list_image(flag, docker_output('ps -a'), from: from) do |img|
492
- puts 'Success' if run(cmd.temp(target, img), from: from) == true && stdout? && banner?
503
+ print_success if success?(run(cmd.temp(target, img), from: from))
493
504
  end
494
505
  end
495
506
 
@@ -537,8 +548,12 @@ module Squared
537
548
  case flag
538
549
  when :run
539
550
  unless session_arg?('name', target: target)
540
- require 'random/formatter'
541
- target << basic_option('name', dnsname("#{name}_#{Random.new.alphanumeric(6)}"))
551
+ target << basic_option('name', dnsname("#{name}_%s" % if RUBY_VERSION >= '3.1'
552
+ require 'random/formatter'
553
+ Random.new.alphanumeric(6)
554
+ else
555
+ (0...6).map { rand(97..122).chr }.join
556
+ end))
542
557
  end
543
558
  when :exec
544
559
  raise_error('no command args', hint: from) if list.empty?
@@ -550,7 +565,7 @@ module Squared
550
565
  def append_file(type, target: @session)
551
566
  return unless type == 2 || type == 4 || @file.is_a?(Array)
552
567
 
553
- files = as_a(@file).map { |val| quote_option('file', basepath(val)) }
568
+ files = as_a(@file).map { |val| quote_option('file', path + val) }
554
569
  if target.is_a?(Set)
555
570
  target.merge(files)
556
571
  else
@@ -585,7 +600,9 @@ module Squared
585
600
  pwd_set do
586
601
  found = false
587
602
  index = 0
588
- pat = /^(?:#{dnsname(name)}|#{tagname(project)}|#{tagmain.split(':').first})(?:[_.,:-]|$)/
603
+ all = option('all', prefix: 'docker')
604
+ y = from == :'image:rm' && option('y', prefix: 'docker')
605
+ pat = /^(?:#{dnsname(name)}|#{tagname(project)}|#{tagmain.split(':', 2).first})(?:[_.,:-]|$)/
589
606
  IO.popen(session_done(cmd << '--format=json')).each do |line|
590
607
  data = JSON.parse(line)
591
608
  id = data['ID']
@@ -598,41 +615,43 @@ module Squared
598
615
  id
599
616
  end)
600
617
  ee = data['Image'] || rt || aa
601
- next unless option('all') || ee.match?(pat) || aa.match?(pat)
602
-
603
- bb = index.succ.to_s
604
- cc = bb.size + 1
605
- a = sub_style(ee, styles: theme[:inline])
606
- b = "Execute #{sub_style(flag, styles: theme[:active])} on #{a}#{ee == id ? '' : " (#{id})"}"
607
- c, d = no ? ['y/N', 'N'] : ['Y/n', 'Y']
608
- e = time_format(time_since(data['CreatedAt']), pass: ['ms'])
609
- f = sub_style(ARG[:BORDER][0], styles: theme[:inline])
610
- g = ' ' * (cc + 1)
611
- h = "#{sub_style(bb.rjust(cc), styles: theme[:current])} #{f} "
612
- puts unless index == 0
613
- puts "#{h + sub_style(aa, styles: theme[:subject])} (created #{e} ago)"
614
- cols = %w[Tag Status Ports]
615
- cols << case flag
616
- when :connect, :disconnect
617
- 'Networks'
618
- else
619
- 'Size'
620
- end
621
- cols.each do |key|
622
- next if (key == 'Tag' && !dd) || (key == 'Size' && data[key] == '0B')
618
+ next unless all || ee.match?(pat) || aa.match?(pat)
619
+
620
+ unless y
621
+ bb = index.succ.to_s
622
+ cc = bb.size + 1
623
+ a = sub_style(ee, styles: theme[:inline])
624
+ b = "Execute #{sub_style(flag, styles: theme[:active])} on #{a}#{ee == id ? '' : " (#{id})"}"
625
+ c, d = no ? ['y/N', 'N'] : ['Y/n', 'Y']
626
+ e = time_format(time_since(data['CreatedAt']), pass: ['ms'])
627
+ f = sub_style(ARG[:BORDER][0], styles: theme[:inline])
628
+ g = ' ' * (cc + 1)
629
+ h = "#{sub_style(bb.rjust(cc), styles: theme[:current])} #{f} "
630
+ puts unless index == 0
631
+ puts "#{h + sub_style(aa, styles: theme[:subject])} (created #{e} ago)"
632
+ cols = %w[Tag Status Ports]
633
+ cols << case flag
634
+ when :connect, :disconnect
635
+ 'Networks'
636
+ else
637
+ 'Size'
638
+ end
639
+ cols.each do |key|
640
+ next if (key == 'Tag' && !dd) || (key == 'Size' && data[key] == '0B')
623
641
 
624
- puts "#{g + f} #{key}: #{as_a(data[key]).join(', ')}" unless data[key].to_s.empty?
625
- end
626
- w = 9 + flag.to_s.size + 4 + ee.size
627
- puts g + sub_style(ARG[:BORDER][6] + (ARG[:BORDER][1] * w), styles: theme[:inline])
628
- found = true
629
- index += 1
630
- next unless confirm("#{h + b}? [#{c}] ", d, timeout: 60)
642
+ puts "#{g + f} #{key}: #{as_a(data[key]).join(', ')}" unless data[key].to_s.empty?
643
+ end
644
+ w = 9 + flag.to_s.size + 4 + ee.size
645
+ puts g + sub_style(ARG[:BORDER][6] + (ARG[:BORDER][1] * w), styles: theme[:inline])
646
+ found = true
647
+ index += 1
648
+ next unless confirm("#{h + b}? [#{c}] ", d, timeout: 60)
631
649
 
632
- puts if @@print_order == 0
650
+ puts if @@print_order == 0
651
+ end
633
652
  yield id
634
653
  end
635
- puts log_message(Logger::INFO, 'none detected', subject: "#{name}:#{from}", hint: hint) unless found
654
+ puts log_message(Logger::INFO, 'none detected', subject: "#{name}:#{from}", hint: hint) unless found || y
636
655
  end
637
656
  rescue StandardError => e
638
657
  log.error e
@@ -660,7 +679,7 @@ module Squared
660
679
 
661
680
  def choice_command(flag)
662
681
  msg, cmd, index = case flag
663
- when :run
682
+ when :run, :rm
664
683
  ['Choose an image', 'images -a', 2]
665
684
  when :exec
666
685
  ['Choose a container', 'ps -a', 0]
@@ -673,17 +692,27 @@ module Squared
673
692
  puts log_message(Logger::INFO, 'none found', subject: name, hint: "docker #{cmd}")
674
693
  else
675
694
  puts " # #{header}"
695
+ multiple = false
696
+ parse = ->(val) { val.split(/\s+/)[index] }
676
697
  case flag
677
698
  when :run, :exec
678
- values = [['Options', flag == :run], ['Command arguments', flag == :exec]]
699
+ values = [['Options', flag == :run], ['Arguments', flag == :exec]]
679
700
  cmd = flag.to_s
701
+ when :rm
702
+ values = ['Options']
703
+ multiple = true
704
+ cmd = "image #{flag}"
680
705
  else
681
- values = [['Options', false], ['Container', true]]
706
+ values = ['Options', ['Container', true]]
682
707
  cmd = "network #{flag}"
683
708
  end
684
- out, opts, args = choice_index(msg, lines, values: values)
685
- ret = run docker_output(cmd, opts, '--', out.split(/\s+/)[index], args)
686
- puts 'Success' if ret && cmd.start_with?('network')
709
+ out, opts, args = choice_index(msg, lines, multiple: multiple, values: values)
710
+ ret = run docker_output(cmd, opts, '--', *(if out.is_a?(Array)
711
+ out.map! { |val| parse.call(val) }
712
+ else
713
+ [parse.call(out)]
714
+ end), args)
715
+ print_success if success?(ret && cmd.start_with?('network'))
687
716
  end
688
717
  end
689
718
 
@@ -703,7 +732,7 @@ module Squared
703
732
  end
704
733
 
705
734
  def contextdir(val = nil)
706
- val && projectpath?(val) ? shell_quote(basepath(val)) : '.'
735
+ val && projectpath?(val) ? shell_quote(path + val) : '.'
707
736
  end
708
737
 
709
738
  def tagname(val)