squared 0.5.2 → 0.5.4

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.
@@ -55,15 +55,15 @@ module Squared
55
55
  commit: %w[a|author=q c|change=q m|message=q pause=b?].freeze,
56
56
  inspect: %w[s|size f|format=q].freeze,
57
57
  start: %w[a|attach i|interactive detach-keys=q].freeze,
58
- stop: %w[s|signal=b t|time=i].freeze,
59
- restart: %w[s|signal=b t|time=i].freeze,
58
+ stop: %w[s|signal=b t|time=i t|timeout=i].freeze,
59
+ restart: %w[s|signal=b t|time=i t|timeout=i].freeze,
60
60
  kill: %w[s|signal=b].freeze,
61
61
  stats: %w[no-trunc format|q].freeze
62
62
  }.freeze,
63
63
  image: {
64
64
  list: %w[a|all digests no-trunc f|filter=q format=q].freeze,
65
65
  push: %w[a|all-tags disable-content-trust=b? platform=b q|quiet].freeze,
66
- rm: %w[f|force no-prune].freeze,
66
+ rm: %w[f|force no-prune platform=b].freeze,
67
67
  save: %w[o|output=p platform=b].freeze
68
68
  }.freeze,
69
69
  network: {
@@ -73,8 +73,11 @@ module Squared
73
73
  }.freeze
74
74
  VAL_DOCKER = {
75
75
  run: {
76
- bind: %w[type source src destination dst target readonly ro bind-propagation].freeze,
77
- tmpfs: %w[type destination dst target tmpfs-size tmpfs-mode].freeze
76
+ common: %w[source src destination dst target readonly ro].freeze,
77
+ bind: %w[bind-propagation].freeze,
78
+ volume: %w[volume-subpath volume-nocopy volume-opt].freeze,
79
+ tmpfs: %w[tmpfs-size tmpfs-mode].freeze,
80
+ image: %w[image-path].freeze
78
81
  }.freeze
79
82
  }.freeze
80
83
  private_constant :COMPOSEFILE, :BAKEFILE, :OPT_DOCKER, :VAL_DOCKER
@@ -92,8 +95,9 @@ module Squared
92
95
  end
93
96
 
94
97
  subtasks({
95
- 'build' => %i[tag context bake].freeze,
98
+ 'build' => %i[tag context].freeze,
96
99
  'compose' => %i[build run exec up].freeze,
100
+ 'bake' => %i[build check].freeze,
97
101
  'image' => %i[list rm push tag save].freeze,
98
102
  'container' => %i[run create exec update commit inspect diff start stop restart pause unpause top stats kill
99
103
  rm].freeze,
@@ -112,7 +116,6 @@ module Squared
112
116
  @mounts = mounts
113
117
  @secrets = secrets
114
118
  @registry = tagjoin registry, kwargs[:username]
115
- @file = nil
116
119
  initialize_ref Docker.ref
117
120
  initialize_logger(**kwargs)
118
121
  initialize_env(**kwargs)
@@ -125,11 +128,11 @@ module Squared
125
128
 
126
129
  def populate(*, **)
127
130
  super
128
- return unless ref?(Docker.ref)
131
+ return unless ref?(Docker.ref) || @only
129
132
 
130
133
  namespace name do
131
134
  Docker.subtasks do |action, flags|
132
- next if @pass.include?(action)
135
+ next if task_pass?(action)
133
136
 
134
137
  namespace action do
135
138
  flags.each do |flag|
@@ -142,18 +145,31 @@ module Squared
142
145
  param = param_guard(action, flag, args: args, key: flag)
143
146
  buildx(:build, args.extras, "#{flag}": param)
144
147
  end
145
- when :bake
148
+ end
149
+ when 'bake'
150
+ next unless bake?
151
+
152
+ case flag
153
+ when :build
146
154
  format_desc action, flag, ':?,opts*,target*,context?'
147
155
  task flag do |_, args|
148
156
  args = args.to_a
149
157
  if args.first == ':'
150
158
  choice_command :bake
151
159
  else
152
- buildx flag, args
160
+ buildx :bake, args
153
161
  end
154
162
  end
163
+ when :check
164
+ format_desc action, flag, 'target'
165
+ task flag, [:target] do |_, args|
166
+ target = param_guard(action, flag, args: args, key: :target)
167
+ buildx :bake, ['allow=fs.read=*', 'call=check', target]
168
+ end
155
169
  end
156
170
  when 'compose'
171
+ next unless compose?
172
+
157
173
  case flag
158
174
  when :build, :up
159
175
  format_desc action, flag, 'opts*,service*'
@@ -306,7 +322,7 @@ module Squared
306
322
  op.parse(OPT_DOCKER[:buildx][flag == :bake ? :bake : :build] + OPT_DOCKER[:buildx][:shared])
307
323
  case flag
308
324
  when :build, :context
309
- append_tag(tag || option('tag', ignore: false) || @tag)
325
+ append_tag(tag || option('tag', ignore: false) || self.tag)
310
326
  append_context context
311
327
  when :bake
312
328
  unless op.empty?
@@ -316,7 +332,7 @@ module Squared
316
332
  if projectpath?(val = args.pop)
317
333
  context = val
318
334
  else
319
- op.extras << val
335
+ op.push(val)
320
336
  end
321
337
  end
322
338
  op.append(args, escape: true)
@@ -338,7 +354,7 @@ module Squared
338
354
  when :build, :up
339
355
  op.append(escape: true)
340
356
  when :exec, :run
341
- append_command(flag, service, op.extras, from: from)
357
+ append_command flag, service, op.extras
342
358
  end
343
359
  run(from: from)
344
360
  end
@@ -355,44 +371,54 @@ module Squared
355
371
  when :run, :create, :exec
356
372
  if rc && !op.arg?('mount')
357
373
  run = VAL_DOCKER[:run]
358
- both = run[:bind] + run[:tmpfs]
359
- diff = run[:bind].reject { |val| run[:tmpfs].include?(val) }
360
- delim = Regexp.new(",\\s*(?=#{both.join('|')})")
374
+ all = collect_hash VAL_DOCKER[:run]
375
+ delim = Regexp.new(",\\s*(?=#{all.join('|')})")
361
376
  Array(@mounts).each do |val|
362
377
  args = []
363
- tmpfs = true
378
+ type = nil
364
379
  val.split(delim).each do |opt|
365
380
  k, v, q = split_option opt
366
- next unless both.include?(k)
367
-
368
381
  if k == 'type'
369
- tmpfs = false if v == 'bind'
370
- next
371
- elsif diff.include?(k)
372
- tmpfs = false
373
- end
374
- case k
375
- when 'readonly', 'ro'
376
- args << k
377
- next
378
- when 'source', 'src', 'destination', 'dst', 'target'
379
- v = path + v
380
- v = shell_quote(v, option: false, force: false) if q == ''
381
- tmpfs = false if k[0] == 's'
382
+ case v
383
+ when 'bind', 'volume', 'image', 'tmpfs'
384
+ type = v
385
+ else
386
+ raise_error("unknown type: #{v}", hint: flag)
387
+ end
388
+ elsif all.include?(k)
389
+ unless type
390
+ run.each_pair do |key, val|
391
+ if val.include?(k)
392
+ type = key.to_s unless key == :common
393
+ break
394
+ end
395
+ end
396
+ end
397
+ case k
398
+ when 'readonly', 'ro'
399
+ args << k
400
+ next
401
+ when 'source', 'src', 'destination', 'dst', 'target', 'volume-subpath', 'image-path'
402
+ v = path + v
403
+ v = shell_quote(v, option: false, force: false) if q == ''
404
+ end
405
+ args << "#{k}=#{q + v + q}"
406
+ elsif verbose
407
+ log_message(Logger::INFO, 'unrecognized option', subject: from, hint: k)
382
408
  end
383
- args << "#{k}=#{q + v + q}"
384
409
  end
385
- cmd << "--mount type=#{tmpfs ? 'tmpfs' : 'bind'},#{args.join(',')}"
410
+ raise_error('missing type', hint: flag) unless type
411
+ cmd << "--mount type=#{type},#{args.join(',')}"
386
412
  end
387
413
  end
388
- append_command(flag, id || tagmain, op.extras, from: from)
414
+ append_command(flag, id || tagmain, op.extras)
389
415
  when :update
390
- raise_error('missing container', hint: from) if op.empty?
416
+ raise_error('missing container', hint: flag) if op.empty?
391
417
  op.append(escape: true)
392
418
  when :commit
393
419
  latest = op.shift || tagmain
394
420
  cmd << id << latest
395
- raise_error("unknown args: #{op.join(', ')}", hint: from) unless op.empty?
421
+ raise_error("unknown args: #{op.join(', ')}", hint: flag) unless op.empty?
396
422
  return unless confirm_command(cmd.to_s, title: from, target: id, as: latest)
397
423
 
398
424
  registry = option('registry') || @registry
@@ -435,7 +461,7 @@ module Squared
435
461
  when :rm
436
462
  status = %w[created exited dead]
437
463
  end
438
- ps = docker_output('ps -a', *status.map { |s| "--filter=\"status=#{s}\"" })
464
+ ps = docker_output('ps -a', *status.map { |s| quote_option('filter', "status=#{s}") })
439
465
  list_image(flag, ps, no: no, hint: "status: #{status.join(', ')}", from: from) do |img|
440
466
  run(cmd.temp(img), from: from)
441
467
  end
@@ -499,8 +525,8 @@ module Squared
499
525
  when :push
500
526
  id ||= option('tag', ignore: false) || tagmain
501
527
  registry ||= op.shift || option('registry') || @registry
502
- raise_error(id ? "unknown args: #{op.join(', ')}" : 'no id/tag given', hint: from) unless id && op.empty?
503
- raise_error('username/registry not provided', hint: from) unless registry
528
+ raise_error(id ? "unknown args: #{op.join(', ')}" : 'no id/tag given', hint: flag) unless id && op.empty?
529
+ raise_error('username/registry not provided', hint: flag) unless registry
504
530
  registry.chomp!('/')
505
531
  uri = shell_quote "#{registry}/#{id}"
506
532
  op << uri
@@ -534,6 +560,14 @@ module Squared
534
560
  super || dockerfile.exist?
535
561
  end
536
562
 
563
+ def compose?(file = dockerfile)
564
+ COMPOSEFILE.include?(File.basename(file))
565
+ end
566
+
567
+ def bake?(file = dockerfile)
568
+ BAKEFILE.include?(File.basename(file))
569
+ end
570
+
537
571
  def dockerfile(val = nil)
538
572
  if val == 'Dockerfile'
539
573
  @file = false
@@ -563,7 +597,7 @@ module Squared
563
597
  session('docker', *cmd, main: false, options: false, **kwargs)
564
598
  end
565
599
 
566
- def append_command(flag, val, list, target: @session, from: nil)
600
+ def append_command(flag, val, list, target: @session)
567
601
  if list.delete(':')
568
602
  list << readline('Enter command [args]', force: true)
569
603
  elsif (args = env('DOCKER_ARGS'))
@@ -572,15 +606,10 @@ module Squared
572
606
  case flag
573
607
  when :run
574
608
  unless session_arg?('name', target: target)
575
- target << basic_option('name', dnsname("#{name}_%s" % if RUBY_VERSION >= '3.1'
576
- require 'random/formatter'
577
- Random.new.alphanumeric(6)
578
- else
579
- (0...6).map { rand(97..122).chr }.join
580
- end))
609
+ target << basic_option('name', dnsname("#{name}_%s" % rand_s(6)))
581
610
  end
582
611
  when :exec
583
- raise_error('no command args', hint: from) if list.empty?
612
+ raise_error('no command args', hint: flag) if list.empty?
584
613
  end
585
614
  target << val << list.shift
586
615
  target << list.join(' && ') unless list.empty?
@@ -628,7 +657,7 @@ module Squared
628
657
  index = 0
629
658
  all = option('all', prefix: 'docker')
630
659
  y = from == :'image:rm' && option('y', prefix: 'docker')
631
- pat = /^(?:#{dnsname(name)}|#{tagname(project)}|#{tagmain.split(':', 2).first})(?:[_.,:-]|$)/
660
+ pat = /\b(?:#{dnsname(name)}|#{tagname(project)}|#{tagmain.split(':', 2).first})\b/
632
661
  IO.popen(session_done(cmd << '--format=json')).each do |line|
633
662
  data = JSON.parse(line)
634
663
  id = data['ID']
@@ -676,14 +705,10 @@ module Squared
676
705
  end
677
706
  yield id
678
707
  end
679
- puts log_message(Logger::INFO, 'none detected', subject: "#{name}:#{from}", hint: hint) if found || y
708
+ puts log_message(Logger::INFO, 'none detected', subject: name, hint: hint || from) if !found && !y
680
709
  end
681
710
  rescue StandardError => e
682
- log.error e
683
- ret = on :error, from, e
684
- raise if exception && ret != true
685
-
686
- warn log_message(Logger::WARN, e, pass: true) if warning?
711
+ on_error e, from
687
712
  end
688
713
 
689
714
  def confirm_command(*args, title: nil, target: nil, as: nil)
@@ -740,7 +765,7 @@ module Squared
740
765
  cmd = docker_output ctx
741
766
  case flag
742
767
  when :tag
743
- args = tagjoin @registry, @tag
768
+ args = tagjoin @registry, tag
744
769
  when :save
745
770
  opts = "#{opts}.tar" unless opts.end_with?('.tar')
746
771
  cmd << quote_option('output', File.expand_path(opts))
@@ -751,11 +776,7 @@ module Squared
751
776
  else
752
777
  cmd << opts << '--'
753
778
  end
754
- cmd.merge(if out.is_a?(Array)
755
- out.map! { |val| parse.call(val) }
756
- else
757
- [parse.call(out)]
758
- end)
779
+ cmd.merge(Array(out).map! { |val| parse.call(val) })
759
780
  cmd << args
760
781
  print_success if success?(run(cmd)) && ctx.start_with?(/(?:network|tag|save)/)
761
782
  end
@@ -804,14 +825,6 @@ module Squared
804
825
  def tagmain
805
826
  tag.is_a?(Array) ? tag.first : tag
806
827
  end
807
-
808
- def compose?(file = dockerfile)
809
- COMPOSEFILE.include?(File.basename(file))
810
- end
811
-
812
- def bake?(file = dockerfile)
813
- BAKEFILE.include?(File.basename(file))
814
- end
815
828
  end
816
829
 
817
830
  Application.implement Docker