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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +99 -1
- data/README.md +15 -17
- data/README.ruby.md +56 -37
- data/lib/squared/common/format.rb +10 -17
- data/lib/squared/common/prompt.rb +65 -19
- data/lib/squared/common/shell.rb +21 -14
- data/lib/squared/common/system.rb +6 -6
- data/lib/squared/common/utils.rb +1 -1
- data/lib/squared/config.rb +3 -3
- data/lib/squared/version.rb +1 -1
- data/lib/squared/workspace/application.rb +13 -17
- data/lib/squared/workspace/project/base.rb +83 -39
- data/lib/squared/workspace/project/docker.rb +95 -66
- data/lib/squared/workspace/project/git.rb +720 -390
- data/lib/squared/workspace/project/node.rb +39 -38
- data/lib/squared/workspace/project/python.rb +36 -42
- data/lib/squared/workspace/project/ruby.rb +143 -108
- data/lib/squared/workspace/project/support/class.rb +29 -13
- data/lib/squared/workspace/repo.rb +4 -4
- data/lib/squared/workspace/series.rb +9 -6
- data/lib/squared/workspace.rb +1 -1
- metadata +1 -1
@@ -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
|
-
|
42
|
-
|
43
|
-
health-start-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
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
|
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
|
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
|
-
|
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
|
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
|
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
|
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 =
|
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
|
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
|
-
|
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
|
-
|
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
|
-
|
541
|
-
|
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',
|
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
|
-
|
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
|
602
|
-
|
603
|
-
|
604
|
-
|
605
|
-
|
606
|
-
|
607
|
-
|
608
|
-
|
609
|
-
|
610
|
-
|
611
|
-
|
612
|
-
|
613
|
-
|
614
|
-
|
615
|
-
|
616
|
-
|
617
|
-
|
618
|
-
|
619
|
-
|
620
|
-
|
621
|
-
|
622
|
-
|
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
|
-
|
625
|
-
|
626
|
-
|
627
|
-
|
628
|
-
|
629
|
-
|
630
|
-
|
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
|
-
|
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], ['
|
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 = [
|
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.
|
686
|
-
|
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(
|
735
|
+
val && projectpath?(val) ? shell_quote(path + val) : '.'
|
707
736
|
end
|
708
737
|
|
709
738
|
def tagname(val)
|