squared 0.6.10 → 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 +4 -4
- data/CHANGELOG.md +67 -14
- data/README.md +242 -204
- data/lib/squared/common/format.rb +7 -10
- data/lib/squared/common/prompt.rb +23 -24
- data/lib/squared/common/shell.rb +16 -17
- data/lib/squared/common/system.rb +29 -20
- data/lib/squared/common/utils.rb +43 -54
- data/lib/squared/config.rb +17 -16
- data/lib/squared/version.rb +1 -1
- data/lib/squared/workspace/application.rb +290 -175
- data/lib/squared/workspace/project/base.rb +544 -446
- data/lib/squared/workspace/project/docker.rb +162 -155
- data/lib/squared/workspace/project/git.rb +180 -147
- data/lib/squared/workspace/project/node.rb +91 -89
- data/lib/squared/workspace/project/python.rb +245 -151
- data/lib/squared/workspace/project/ruby.rb +403 -291
- data/lib/squared/workspace/project/support/class.rb +12 -6
- data/lib/squared/workspace/project/support/optionpartition.rb +58 -41
- data/lib/squared/workspace/project/support/utils.rb +68 -0
- data/lib/squared/workspace/project.rb +0 -7
- data/lib/squared/workspace/repo.rb +234 -169
- data/lib/squared/workspace/series.rb +91 -86
- data/lib/squared/workspace/support/base.rb +15 -1
- metadata +2 -1
|
@@ -33,7 +33,8 @@ module Squared
|
|
|
33
33
|
d|detach force-recreate menu no-build no-color no-deps no-log-prefix no-recreate no-start quiet-build
|
|
34
34
|
quiet-pull remove-orphans V|renew-anon-volumes timestamps wait w|watch y|yes attach=b
|
|
35
35
|
exit-code-from=b no-attach=b pull=b scale=i t|timeout=i wait-timeout=i].freeze,
|
|
36
|
-
down: %w[remove-orphans v|volumes rmi=b t|timeout=i].freeze
|
|
36
|
+
down: %w[remove-orphans v|volumes rmi=b t|timeout=i].freeze,
|
|
37
|
+
publish: %w[app resolve-image-digests with-env y|yes oci-version=b].freeze
|
|
37
38
|
}.freeze,
|
|
38
39
|
container: {
|
|
39
40
|
create: %w[init i|interactive no-healthcheck oom-kill-disable privileged P|publish-all q|quiet read-only
|
|
@@ -64,6 +65,7 @@ module Squared
|
|
|
64
65
|
}.freeze,
|
|
65
66
|
image: {
|
|
66
67
|
ls: %w[a|all digests no-trunc q|quiet tree f|filter=q format=q].freeze,
|
|
68
|
+
pull: %w[a|all-tags platform=q q|quiet].freeze,
|
|
67
69
|
push: %w[a|all-tags platform=q q|quiet].freeze,
|
|
68
70
|
rm: %w[f|force no-prune platform=q].freeze,
|
|
69
71
|
save: %w[o|output=p platform=q].freeze
|
|
@@ -107,9 +109,9 @@ module Squared
|
|
|
107
109
|
|
|
108
110
|
subtasks({
|
|
109
111
|
'build' => %i[tag context].freeze,
|
|
110
|
-
'compose' => %i[build create run exec up down service].freeze,
|
|
111
|
-
'bake' => %i[build check].freeze,
|
|
112
|
-
'image' => %i[ls rm push tag save].freeze,
|
|
112
|
+
'compose' => %i[build create publish run exec up down service].freeze,
|
|
113
|
+
'bake' => %i[build compose check].freeze,
|
|
114
|
+
'image' => %i[ls rm pull push tag save].freeze,
|
|
113
115
|
'container' => %i[run create exec update commit inspect diff start stop restart pause unpause top stats kill
|
|
114
116
|
rm].freeze,
|
|
115
117
|
'network' => %i[connect disconnect].freeze,
|
|
@@ -119,17 +121,19 @@ module Squared
|
|
|
119
121
|
attr_reader :context
|
|
120
122
|
attr_accessor :tag
|
|
121
123
|
|
|
122
|
-
def initialize(*,
|
|
124
|
+
def initialize(*, mounts: [], **kwargs)
|
|
123
125
|
super
|
|
124
|
-
|
|
126
|
+
self.global = nil
|
|
127
|
+
return unless dockerfile(kwargs[:file]).exist?
|
|
125
128
|
|
|
126
|
-
|
|
127
|
-
|
|
129
|
+
self.tag = kwargs[:tag] || tagname("#{@project}:#{@version || 'latest'}")
|
|
130
|
+
@context = kwargs[:context]
|
|
128
131
|
@mounts = mounts
|
|
129
|
-
@secrets = secrets
|
|
130
|
-
@registry = tagjoin registry, kwargs[:username]
|
|
132
|
+
@secrets = kwargs[:secrets]
|
|
133
|
+
@registry = tagjoin kwargs[:registry], kwargs[:username]
|
|
134
|
+
@oci = tagjoin kwargs[:oci], kwargs[:username]
|
|
131
135
|
initialize_ref Docker.ref
|
|
132
|
-
initialize_logger
|
|
136
|
+
initialize_logger kwargs[:log]
|
|
133
137
|
initialize_env(**kwargs)
|
|
134
138
|
@output[4] = merge_opts(kwargs[:args], @output[4]) if kwargs[:args]
|
|
135
139
|
end
|
|
@@ -163,25 +167,21 @@ module Squared
|
|
|
163
167
|
end
|
|
164
168
|
cmd << '-a' if has_value!(args, 'a', 'all') && command != 'network'
|
|
165
169
|
data = VAL_DOCKER[:ls][command.to_sym]
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
out.replace(choice_index('Select a column', data, multiple: true, attempts: 1))
|
|
182
|
-
end
|
|
183
|
-
end
|
|
184
|
-
cmd << quote_option('format', "table #{cols.map! { |val| "{{.#{val}}}" }.join("\t")}")
|
|
170
|
+
if has_value!(args, 's', 'standard')
|
|
171
|
+
cols = data.first(data.index('CreatedAt'))
|
|
172
|
+
else
|
|
173
|
+
cols = args.each_with_object([]) do |val, out|
|
|
174
|
+
if val =~ /^(\d+)$/
|
|
175
|
+
out << data[$1.to_i.pred]
|
|
176
|
+
elsif val =~ /^(\d+)(-|\.{2,3})(\d+)$/
|
|
177
|
+
j = $1.to_i.pred
|
|
178
|
+
k = $3.to_i - ($2 == '..' ? 2 : 1)
|
|
179
|
+
out.concat(data[j..k]) if k > j
|
|
180
|
+
end
|
|
181
|
+
end
|
|
182
|
+
cols = choice_index('Select a column', data, multiple: true, attempts: 1) if cols.empty?
|
|
183
|
+
end
|
|
184
|
+
cmd << quote_option('format', "table #{cols.map { |val| "{{.#{val}}}" }.join("\t")}")
|
|
185
185
|
run(cmd, banner: false, from: :ls)
|
|
186
186
|
end
|
|
187
187
|
end
|
|
@@ -199,14 +199,14 @@ module Squared
|
|
|
199
199
|
break unless bake?
|
|
200
200
|
|
|
201
201
|
case flag
|
|
202
|
-
when :build
|
|
203
|
-
format_desc action, flag, 'opts*,target*,context
|
|
202
|
+
when :build, :compose
|
|
203
|
+
format_desc action, flag, 'opts*,target*,context?|:'
|
|
204
204
|
task flag do |_, args|
|
|
205
205
|
args = args.to_a
|
|
206
206
|
if args.first == ':'
|
|
207
207
|
choice_command :bake
|
|
208
208
|
else
|
|
209
|
-
buildx
|
|
209
|
+
buildx(:bake, args, from: (:'buildx:bake' if flag == :compose))
|
|
210
210
|
end
|
|
211
211
|
end
|
|
212
212
|
when :check
|
|
@@ -239,6 +239,13 @@ module Squared
|
|
|
239
239
|
compose!(flag, [command], service: service.empty? || service)
|
|
240
240
|
end
|
|
241
241
|
end
|
|
242
|
+
when :publish
|
|
243
|
+
next unless @oci
|
|
244
|
+
|
|
245
|
+
format_desc action, flag, 'tag?,repository?,opts*'
|
|
246
|
+
task flag, [:tag] do |_, args|
|
|
247
|
+
compose! flag, args.to_a
|
|
248
|
+
end
|
|
242
249
|
else
|
|
243
250
|
format_desc action, flag, 'opts*,service*|:'
|
|
244
251
|
task flag do |_, args|
|
|
@@ -275,6 +282,13 @@ module Squared
|
|
|
275
282
|
when 'image'
|
|
276
283
|
case flag
|
|
277
284
|
when :push
|
|
285
|
+
next unless @registry
|
|
286
|
+
|
|
287
|
+
format_desc action, flag, 'tag?,registry/username?,opts*'
|
|
288
|
+
task flag, [:tag] do |_, args|
|
|
289
|
+
image flag, args.to_a
|
|
290
|
+
end
|
|
291
|
+
when :pull
|
|
278
292
|
format_desc action, flag, 'tag,registry/username?,opts*'
|
|
279
293
|
task flag, [:tag] do |_, args|
|
|
280
294
|
id = param_guard(action, flag, args: args, key: :tag)
|
|
@@ -282,18 +296,14 @@ module Squared
|
|
|
282
296
|
end
|
|
283
297
|
else
|
|
284
298
|
format_desc(action, flag, case flag
|
|
285
|
-
when :rm, :save then 'id
|
|
286
|
-
when :tag then 'version'
|
|
299
|
+
when :rm, :save then 'id*,opts*'
|
|
300
|
+
when :tag then 'version?'
|
|
287
301
|
else 'opts*,args*'
|
|
288
|
-
end
|
|
302
|
+
end)
|
|
289
303
|
task flag do |_, args|
|
|
290
304
|
args = args.to_a
|
|
291
|
-
n = args.size
|
|
292
|
-
if (n > 1 || (flag == :ls && n > 0)) && OptionPartition.pattern?(args.first)
|
|
293
|
-
filter = args.shift
|
|
294
|
-
end
|
|
295
305
|
if !args.empty? || flag == :ls
|
|
296
|
-
image
|
|
306
|
+
image flag, args
|
|
297
307
|
else
|
|
298
308
|
choice_command flag
|
|
299
309
|
end
|
|
@@ -319,8 +329,8 @@ module Squared
|
|
|
319
329
|
def clean(*, sync: invoked_sync?('clean'), **)
|
|
320
330
|
if runnable?(@clean)
|
|
321
331
|
super
|
|
322
|
-
|
|
323
|
-
image :
|
|
332
|
+
else
|
|
333
|
+
image(:rm, sync: sync)
|
|
324
334
|
end
|
|
325
335
|
end
|
|
326
336
|
|
|
@@ -353,7 +363,7 @@ module Squared
|
|
|
353
363
|
[args, flags].each_with_index do |item, i|
|
|
354
364
|
next unless item && (data = append_any(item, target: []))
|
|
355
365
|
|
|
356
|
-
ret.merge(data.map
|
|
366
|
+
ret.merge(data.map { |arg| i == 0 ? fill_option(arg) : quote_option('build-arg', arg) })
|
|
357
367
|
end
|
|
358
368
|
case from
|
|
359
369
|
when :run
|
|
@@ -361,13 +371,13 @@ module Squared
|
|
|
361
371
|
when String
|
|
362
372
|
ret << quote_option('secret', @secrets, double: true)
|
|
363
373
|
when Hash
|
|
364
|
-
append = lambda do |
|
|
365
|
-
Array(@secrets[
|
|
374
|
+
append = lambda do |key|
|
|
375
|
+
ret.merge(Array(@secrets[key]).map { |arg| quote_option('secret', "type=#{key},#{arg}", double: true) })
|
|
366
376
|
end
|
|
367
377
|
append.call(:file)
|
|
368
378
|
append.call(:env)
|
|
369
379
|
else
|
|
370
|
-
Array(@secrets).
|
|
380
|
+
ret.merge(Array(@secrets).map { |arg| quote_option('secret', arg) })
|
|
371
381
|
end
|
|
372
382
|
if (val = option('tag', ignore: false))
|
|
373
383
|
append_tag val
|
|
@@ -381,18 +391,18 @@ module Squared
|
|
|
381
391
|
ret
|
|
382
392
|
end
|
|
383
393
|
|
|
384
|
-
def buildx(flag, opts = [], tag: nil, context: nil)
|
|
394
|
+
def buildx(flag, opts = [], tag: nil, context: nil, from: nil)
|
|
385
395
|
cmd, opts = docker_session('buildx', opts: opts)
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
end
|
|
396
|
+
data = OPT_DOCKER[:buildx]
|
|
397
|
+
op = OptionPartition.new(opts, data[:common], cmd, project: self)
|
|
398
|
+
op.append(flag, quote: false)
|
|
399
|
+
.parse(data[flag == :bake ? :bake : :build] + data[:shared])
|
|
391
400
|
case flag
|
|
392
401
|
when :build, :context
|
|
393
402
|
append_tag(tag || option('tag', ignore: false) || self.tag)
|
|
394
403
|
append_context context
|
|
395
404
|
when :bake
|
|
405
|
+
append_file(0, index: 3) unless from || op.arg?('f', 'file') || !anypath?(*COMPOSEFILE)
|
|
396
406
|
unless op.empty?
|
|
397
407
|
args = op.dup
|
|
398
408
|
op.reset
|
|
@@ -408,11 +418,11 @@ module Squared
|
|
|
408
418
|
end
|
|
409
419
|
end
|
|
410
420
|
op.clear(pass: false)
|
|
411
|
-
run(from:
|
|
421
|
+
run(from: from || symjoin('buildx', flag))
|
|
412
422
|
end
|
|
413
423
|
|
|
414
|
-
def compose!(flag, opts = [], service: nil, multiple: false)
|
|
415
|
-
from =
|
|
424
|
+
def compose!(flag, opts = [], id: nil, service: nil, multiple: false)
|
|
425
|
+
from = symjoin 'compose', flag
|
|
416
426
|
if flag == :service
|
|
417
427
|
command = opts.first
|
|
418
428
|
if service == true
|
|
@@ -426,23 +436,31 @@ module Squared
|
|
|
426
436
|
else
|
|
427
437
|
cmd, opts = docker_session('compose', opts: opts)
|
|
428
438
|
op = OptionPartition.new(opts, OPT_DOCKER[:compose][:common], cmd, project: self)
|
|
429
|
-
append_file
|
|
439
|
+
append_file(filetype, force: flag == :publish) unless op.arg?('f', 'file')
|
|
430
440
|
op << flag
|
|
431
441
|
op.parse(OPT_DOCKER[:compose].fetch(flag, []))
|
|
432
|
-
if
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
end
|
|
439
|
-
end
|
|
440
|
-
if multiple
|
|
441
|
-
op.concat(service) if service
|
|
442
|
-
op.append(delim: true, escape: true, strip: /^:/)
|
|
442
|
+
if flag == :publish
|
|
443
|
+
id ||= option('tag', ignore: false) || op.shift || tagmain
|
|
444
|
+
registry ||= option('registry') || op.shift || @oci
|
|
445
|
+
emptyargs op, flag
|
|
446
|
+
op << shell_quote(tagjoin(registry, id))
|
|
447
|
+
return unless confirm_command(op.to_s, title: from, target: id)
|
|
443
448
|
else
|
|
444
|
-
|
|
445
|
-
|
|
449
|
+
if op.remove(':') || service == ':'
|
|
450
|
+
keys = Set.new
|
|
451
|
+
read_composefile('services', target: op.values_of('f', 'file')) { |data| keys.merge(data.keys) }
|
|
452
|
+
service = unless keys.empty?
|
|
453
|
+
choice_index('Add services', keys, multiple: multiple, force: !multiple,
|
|
454
|
+
attempts: multiple ? 1 : 3)
|
|
455
|
+
end
|
|
456
|
+
end
|
|
457
|
+
if multiple
|
|
458
|
+
op.concat(service) if service
|
|
459
|
+
op.append(delim: true, escape: true, strip: /^:/)
|
|
460
|
+
else
|
|
461
|
+
raise_error ArgumentError, 'no service was selected', hint: flag unless service
|
|
462
|
+
append_command(flag, service, op.extras, prompt: '::')
|
|
463
|
+
end
|
|
446
464
|
end
|
|
447
465
|
end
|
|
448
466
|
run(from: from)
|
|
@@ -450,35 +468,32 @@ module Squared
|
|
|
450
468
|
|
|
451
469
|
def container(flag, opts = [], id: nil)
|
|
452
470
|
cmd, opts = docker_session('container', flag, opts: opts)
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
end
|
|
460
|
-
from = :"container:#{flag}"
|
|
471
|
+
data = OPT_DOCKER[:container]
|
|
472
|
+
list = data.fetch(flag, [])
|
|
473
|
+
list += data[:create] if (rc = flag == :run)
|
|
474
|
+
list += data[:update] if rc ||= flag == :create
|
|
475
|
+
op = OptionPartition.new(opts, list, cmd, project: self, args: rc || flag == :exec)
|
|
476
|
+
from = symjoin 'container', flag
|
|
461
477
|
case flag
|
|
462
478
|
when :run, :create, :exec
|
|
463
479
|
if rc && !op.arg?('mount')
|
|
464
480
|
all = collect_hash VAL_DOCKER[:run]
|
|
465
481
|
delim = Regexp.new(",\\s*(?=#{all.join('|')})")
|
|
466
482
|
Array(@mounts).each do |val|
|
|
467
|
-
args = []
|
|
468
483
|
type = nil
|
|
469
|
-
val.split(delim).
|
|
470
|
-
k, v, q =
|
|
484
|
+
args = val.split(delim).each_with_object([]) do |opt, out|
|
|
485
|
+
k, v, q = OptionPartition.parse_option(opt)
|
|
471
486
|
if k == 'type'
|
|
472
487
|
case v
|
|
473
488
|
when 'bind', 'volume', 'image', 'tmpfs'
|
|
474
489
|
type = v
|
|
475
490
|
else
|
|
476
|
-
raise_error TypeError, "unknown: #{v}", hint: flag
|
|
491
|
+
raise_error TypeError, "unknown: #{v || "''"}", hint: flag
|
|
477
492
|
end
|
|
478
493
|
elsif all.include?(k)
|
|
479
494
|
unless type
|
|
480
|
-
VAL_DOCKER[:run].each_pair do |key,
|
|
481
|
-
next unless
|
|
495
|
+
VAL_DOCKER[:run].each_pair do |key, items|
|
|
496
|
+
next unless items.include?(k)
|
|
482
497
|
|
|
483
498
|
type = key.to_s unless key == :common
|
|
484
499
|
break
|
|
@@ -486,13 +501,14 @@ module Squared
|
|
|
486
501
|
end
|
|
487
502
|
case k
|
|
488
503
|
when 'readonly', 'ro'
|
|
489
|
-
|
|
504
|
+
out << k
|
|
490
505
|
next
|
|
491
506
|
when 'source', 'src', 'destination', 'dst', 'target', 'volume-subpath', 'image-path'
|
|
507
|
+
raise_error ArgumentError, "#{k}: no path value", hint: flag unless v
|
|
492
508
|
v = basepath v
|
|
493
509
|
v = shell_quote(v, option: false, force: false) if q == ''
|
|
494
510
|
end
|
|
495
|
-
|
|
511
|
+
out << "#{k}=#{q}#{v}#{q}"
|
|
496
512
|
elsif !silent?
|
|
497
513
|
log_message('unrecognized option', subject: from, hint: k)
|
|
498
514
|
end
|
|
@@ -518,7 +534,7 @@ module Squared
|
|
|
518
534
|
opts = []
|
|
519
535
|
append_option('platform', target: opts, equals: true)
|
|
520
536
|
opts << case option('disable-content-trust', ignore: false)
|
|
521
|
-
when '
|
|
537
|
+
when '0', 'false'
|
|
522
538
|
'--disable-content-trust=false'
|
|
523
539
|
else
|
|
524
540
|
'--disable-content-trust'
|
|
@@ -537,12 +553,12 @@ module Squared
|
|
|
537
553
|
run(from: from)
|
|
538
554
|
end
|
|
539
555
|
|
|
540
|
-
def image(flag, opts = [], sync: true, id: nil, registry: nil
|
|
556
|
+
def image(flag, opts = [], sync: true, id: nil, registry: nil)
|
|
541
557
|
cmd, opts = docker_session('image', flag, opts: opts)
|
|
542
558
|
op = OptionPartition.new(opts, OPT_DOCKER[:image].fetch(flag, []), cmd, project: self)
|
|
543
|
-
exception =
|
|
559
|
+
exception = exception?
|
|
544
560
|
banner = true
|
|
545
|
-
from =
|
|
561
|
+
from = symjoin 'image', flag
|
|
546
562
|
case flag
|
|
547
563
|
when :ls
|
|
548
564
|
if opts.size == op.size
|
|
@@ -555,7 +571,7 @@ module Squared
|
|
|
555
571
|
opts.delete(val)
|
|
556
572
|
break
|
|
557
573
|
end
|
|
558
|
-
list_image(:run,
|
|
574
|
+
list_image(:run, from: from) do |val|
|
|
559
575
|
container(:run, if name
|
|
560
576
|
opts.dup << "name=#{index == 0 ? name : "#{name}-#{index}"}"
|
|
561
577
|
else
|
|
@@ -569,7 +585,7 @@ module Squared
|
|
|
569
585
|
when :rm
|
|
570
586
|
unless id
|
|
571
587
|
if op.empty?
|
|
572
|
-
list_image(:rm,
|
|
588
|
+
list_image(:rm, from: from) { |val| image(:rm, opts, sync: sync, id: val) }
|
|
573
589
|
else
|
|
574
590
|
op.each { |val| run(cmd.temp(val), sync: sync, from: from) }
|
|
575
591
|
end
|
|
@@ -581,51 +597,48 @@ module Squared
|
|
|
581
597
|
banner = false
|
|
582
598
|
end
|
|
583
599
|
when :tag, :save
|
|
584
|
-
|
|
585
|
-
list_image(flag, filter: filter, from: from) do |val|
|
|
600
|
+
list_image(flag, from: from) do |val|
|
|
586
601
|
op << val
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
end
|
|
602
|
+
next unless flag == :tag
|
|
603
|
+
|
|
604
|
+
op << tagname("#{project}:#{op.first}")
|
|
605
|
+
break
|
|
592
606
|
end
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
end
|
|
607
|
+
when :pull
|
|
608
|
+
if !id
|
|
609
|
+
id = tagmain
|
|
610
|
+
elsif !op.arg?('a', 'all-tags') && !id.include?(':')
|
|
611
|
+
id = "#{project}:#{id}"
|
|
612
|
+
end
|
|
613
|
+
unless registry
|
|
614
|
+
registry = op.shift
|
|
615
|
+
registry ||= option('registry') || @registry unless id.include?('/')
|
|
603
616
|
end
|
|
617
|
+
cmd << shell_quote(tagjoin(registry, id))
|
|
618
|
+
when :push
|
|
619
|
+
id ||= option('tag', ignore: false) || op.shift || tagmain
|
|
620
|
+
registry ||= option('registry') || op.shift || @registry
|
|
621
|
+
emptyargs op, flag
|
|
604
622
|
raise_error ArgumentError, 'username/registry not specified', hint: flag unless registry
|
|
605
|
-
registry
|
|
606
|
-
uri = shell_quote "#{registry}/#{id}"
|
|
623
|
+
uri = shell_quote tagjoin(registry, id)
|
|
607
624
|
op << uri
|
|
608
625
|
img = docker_output 'image', 'tag', id, uri
|
|
609
626
|
return unless confirm_command(img.to_s, cmd.to_s, target: id, as: registry, title: from)
|
|
610
627
|
|
|
611
|
-
|
|
628
|
+
@session = img
|
|
612
629
|
sync = false
|
|
613
|
-
exception
|
|
630
|
+
exception ||= true
|
|
614
631
|
banner = false
|
|
615
632
|
end
|
|
616
|
-
run(
|
|
617
|
-
success?(ret, flag == :tag || flag == :save)
|
|
618
|
-
end
|
|
633
|
+
success?(run(sync: sync, exception: exception, banner: banner, from: from), flag == :tag || flag == :save)
|
|
619
634
|
end
|
|
620
635
|
|
|
621
636
|
def network(flag, opts = [], target: nil)
|
|
622
637
|
cmd, opts = docker_session('network', flag, opts: opts)
|
|
623
638
|
OptionPartition.new(opts, OPT_DOCKER[:network].fetch(flag, []), cmd, project: self)
|
|
624
639
|
.clear
|
|
625
|
-
from =
|
|
626
|
-
list_image(flag, docker_output('ps -a'), from: from)
|
|
627
|
-
success?(run(cmd.temp(target, img), from: from))
|
|
628
|
-
end
|
|
640
|
+
from = symjoin 'network', flag
|
|
641
|
+
list_image(flag, docker_output('ps -a'), from: from) { |id| success?(run(cmd.temp(target, id), from: from)) }
|
|
629
642
|
end
|
|
630
643
|
|
|
631
644
|
def build?
|
|
@@ -674,7 +687,7 @@ module Squared
|
|
|
674
687
|
elsif (data = doc.dig(*keys))
|
|
675
688
|
yield data
|
|
676
689
|
end
|
|
677
|
-
rescue
|
|
690
|
+
rescue => e
|
|
678
691
|
log.debug e
|
|
679
692
|
end
|
|
680
693
|
end
|
|
@@ -691,11 +704,11 @@ module Squared
|
|
|
691
704
|
end
|
|
692
705
|
|
|
693
706
|
def append_command(flag, val, list, target: @session, prompt: ':')
|
|
694
|
-
if list.delete(prompt)
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
707
|
+
list << if list.delete(prompt)
|
|
708
|
+
readline('Enter command [args]', force: flag == :exec)
|
|
709
|
+
else
|
|
710
|
+
env('DOCKER_ARGS')
|
|
711
|
+
end
|
|
699
712
|
case flag
|
|
700
713
|
when :run
|
|
701
714
|
unless session_arg?('name', target: target)
|
|
@@ -708,10 +721,10 @@ module Squared
|
|
|
708
721
|
target << list.join(' && ') unless list.empty?
|
|
709
722
|
end
|
|
710
723
|
|
|
711
|
-
def append_file(type, target: @session, index: 2)
|
|
712
|
-
return
|
|
724
|
+
def append_file(type, target: @session, index: 2, force: false)
|
|
725
|
+
return unless @file && !(ENV['COMPOSE_FILE'] && compose?(type))
|
|
713
726
|
|
|
714
|
-
unless @file.is_a?(Array)
|
|
727
|
+
unless @file.is_a?(Array) || force
|
|
715
728
|
case type
|
|
716
729
|
when 2, 4
|
|
717
730
|
return
|
|
@@ -719,14 +732,7 @@ module Squared
|
|
|
719
732
|
return unless COMPOSEFILE.select { |val| basepath!(val) }.size > 1
|
|
720
733
|
end
|
|
721
734
|
end
|
|
722
|
-
|
|
723
|
-
if target.is_a?(Set)
|
|
724
|
-
opts = target.to_a.insert(index, *files)
|
|
725
|
-
target.clear
|
|
726
|
-
.merge(opts)
|
|
727
|
-
else
|
|
728
|
-
target.insert(index, *files)
|
|
729
|
-
end
|
|
735
|
+
target.insert(index, *Array(@file).map { |val| quote_option('file', basepath(val)) })
|
|
730
736
|
end
|
|
731
737
|
|
|
732
738
|
def append_context(ctx = nil, target: @session)
|
|
@@ -740,7 +746,7 @@ module Squared
|
|
|
740
746
|
ver = option('version', target: target, ignore: false)
|
|
741
747
|
case val
|
|
742
748
|
when String
|
|
743
|
-
|
|
749
|
+
val.split(',')
|
|
744
750
|
else
|
|
745
751
|
Array(val)
|
|
746
752
|
end.each do |s|
|
|
@@ -779,20 +785,12 @@ module Squared
|
|
|
779
785
|
[cmd, status, no]
|
|
780
786
|
end
|
|
781
787
|
|
|
782
|
-
def list_image(flag, cmd = docker_output('image ls -a'),
|
|
788
|
+
def list_image(flag, cmd = docker_output('image ls -a'), hint: nil, no: true, from: nil)
|
|
783
789
|
pwd_set(from: from) do
|
|
784
790
|
index = 1
|
|
785
791
|
all = option('all', prefix: 'docker')
|
|
786
792
|
y = from == :'image:rm' && option('y', prefix: 'docker')
|
|
787
|
-
|
|
788
|
-
pat = if OptionPartition.pattern?(filter)
|
|
789
|
-
Regexp.new(filter)
|
|
790
|
-
elsif filter.match?(/[:_-]$/)
|
|
791
|
-
/\b#{Regexp.escape(filter)}/
|
|
792
|
-
else
|
|
793
|
-
filter = filter.empty? ? '(?:[:_-]|$)' : "[:_-]#{filter}"
|
|
794
|
-
/\b(?:#{dnsname(name)}|#{tagname(project)}|#{tagmain.split(':', 2).first})#{filter}/
|
|
795
|
-
end
|
|
793
|
+
pat = /\b(?:#{dnsname(name)}|#{tagname(project)}|#{tagmain.split(':', 2).first})\b/
|
|
796
794
|
IO.popen(cmd.temp('--format=json')).each do |line|
|
|
797
795
|
data = JSON.parse(line)
|
|
798
796
|
id = data['ID']
|
|
@@ -841,7 +839,7 @@ module Squared
|
|
|
841
839
|
end
|
|
842
840
|
list_empty(hint: hint || from) if index == 1 && !y
|
|
843
841
|
end
|
|
844
|
-
rescue
|
|
842
|
+
rescue => e
|
|
845
843
|
on_error e, from
|
|
846
844
|
end
|
|
847
845
|
|
|
@@ -913,18 +911,18 @@ module Squared
|
|
|
913
911
|
when :tag
|
|
914
912
|
args = tagjoin @registry, tag
|
|
915
913
|
when :save
|
|
916
|
-
opts =
|
|
914
|
+
opts = opts.sub_ext('.tar')
|
|
917
915
|
cmd << quote_option('output', File.expand_path(opts))
|
|
918
916
|
if args
|
|
919
|
-
cmd <<
|
|
917
|
+
cmd << quote_option('platform', args)
|
|
920
918
|
args = nil
|
|
921
919
|
end
|
|
922
920
|
else
|
|
923
921
|
cmd << opts << '--'
|
|
924
922
|
end
|
|
925
|
-
cmd.merge(Array(out).map
|
|
923
|
+
cmd.merge(Array(out).map { |val| val.split(/\s+/, 2).first })
|
|
926
924
|
cmd << args
|
|
927
|
-
success?(run(cmd), ctx.start_with?(
|
|
925
|
+
success?(run(cmd), ctx.start_with?('network', 'tag', 'save'))
|
|
928
926
|
end
|
|
929
927
|
|
|
930
928
|
def filetype(val = dockerfile)
|
|
@@ -947,11 +945,12 @@ module Squared
|
|
|
947
945
|
end
|
|
948
946
|
|
|
949
947
|
def tagjoin(*args, char: '/')
|
|
950
|
-
args.
|
|
948
|
+
args.compact!
|
|
949
|
+
args.map { |val| val.chomp(char) }.join(char) unless args.empty?
|
|
951
950
|
end
|
|
952
951
|
|
|
953
952
|
def tagname(val)
|
|
954
|
-
val = val.split(':').map
|
|
953
|
+
val = val.split(':').map { |s| charname(s.sub(/^\W+/, '')) }
|
|
955
954
|
ret = val.join(':')
|
|
956
955
|
ret = val.first if val.size > 1 && ret.size > 128
|
|
957
956
|
ret[0..127]
|
|
@@ -968,6 +967,14 @@ module Squared
|
|
|
968
967
|
def tagmain
|
|
969
968
|
tag.is_a?(Array) ? tag.first : tag
|
|
970
969
|
end
|
|
970
|
+
|
|
971
|
+
def emptyargs(list, hint = nil)
|
|
972
|
+
raise_error ArgumentError, "unrecognized args: #{list.join(', ')}", hint: hint unless list.empty?
|
|
973
|
+
end
|
|
974
|
+
|
|
975
|
+
def anypath?(*args)
|
|
976
|
+
args.any? { |val| basepath!(val) }
|
|
977
|
+
end
|
|
971
978
|
end
|
|
972
979
|
|
|
973
980
|
Application.implement Docker
|