squared 0.5.20 → 0.6.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 +87 -157
- data/README.md +104 -72
- data/lib/squared/common/base.rb +1 -22
- data/lib/squared/common/format.rb +40 -34
- data/lib/squared/common/prompt.rb +57 -35
- data/lib/squared/common/shell.rb +71 -56
- data/lib/squared/common/system.rb +69 -36
- data/lib/squared/common/utils.rb +29 -6
- data/lib/squared/config.rb +27 -34
- data/lib/squared/version.rb +1 -1
- data/lib/squared/workspace/application.rb +85 -86
- data/lib/squared/workspace/project/base.rb +538 -394
- data/lib/squared/workspace/project/docker.rb +393 -289
- data/lib/squared/workspace/project/git.rb +350 -339
- data/lib/squared/workspace/project/node.rb +499 -274
- data/lib/squared/workspace/project/python.rb +370 -241
- data/lib/squared/workspace/project/ruby.rb +683 -386
- data/lib/squared/workspace/project/support/class.rb +208 -205
- data/lib/squared/workspace/repo.rb +46 -43
- data/lib/squared/workspace/series.rb +13 -21
- data/lib/squared/workspace/support/base.rb +3 -24
- data/lib/squared/workspace/support/variables.rb +48 -0
- data/lib/squared/workspace/support.rb +1 -1
- data/lib/squared/workspace.rb +4 -6
- metadata +3 -3
- data/lib/squared/workspace/support/data.rb +0 -11
|
@@ -13,17 +13,18 @@ module Squared
|
|
|
13
13
|
buildx: {
|
|
14
14
|
common: %w[builder=b D|debug],
|
|
15
15
|
build: %w[add-host=q annotation=q attest=q build-arg=qq build-context=qq cache-from=q cache-to=q
|
|
16
|
-
cgroup-parent=b iidfile=p label=q network=b no-cache-filter=b o|output=q platform=
|
|
16
|
+
cgroup-parent=b iidfile=p label=q a-file=p network=b no-cache-filter=b o|output=q platform=b
|
|
17
17
|
q|quiet secret=qq shm-size=b ssh=qq t|tag=b target=b ulimit=q].freeze,
|
|
18
18
|
bake: %w[print list=q set=q].freeze,
|
|
19
19
|
shared: %w[check load no-cache pull push allow=q call=b? f|file=p metadata-file=p progress=b provenance=q
|
|
20
20
|
sbom=q].freeze
|
|
21
21
|
}.freeze,
|
|
22
22
|
compose: {
|
|
23
|
-
common: %w[all-resources compatibility dry-run
|
|
23
|
+
common: %w[all-resources ansi|b compatibility dry-run env-file=p f|file=p parallel=n profile=b progress=b
|
|
24
24
|
project-directory=p p|project-name=e].freeze,
|
|
25
25
|
build: %w[check no-cache print pull push with-dependencies q|quiet build-arg=qq builder=b m|memory=b
|
|
26
26
|
provenance=q sbom=q ssh=qq].freeze,
|
|
27
|
+
create: %w[build force-recreate no-build no-recreate quiet-pull remove-orphans y|yes pull=b scale=i].freeze,
|
|
27
28
|
exec: %w[d|detach privileged e|env=qq index=i T|no-TTY=b? user=e w|workdir=q].freeze,
|
|
28
29
|
run: %w[build d|detach no-deps q|quiet quiet-build quiet-pull remove-orphans rm P|service-ports use-aliases
|
|
29
30
|
cap-add=b cap-drop=b entrypoint=q e|env=qq env-from-file=p i|interactive=b? l|label=q name=b
|
|
@@ -41,14 +42,14 @@ module Squared
|
|
|
41
42
|
device-read-bps=q device-read-iops=q device-write-bps=q device-write-iops=q
|
|
42
43
|
disable-content-trust=b? dns=q dns-option=q dns-search=q domainname=b entrypoint=q e|env=qq
|
|
43
44
|
env-file=p expose=q gpus=q group-add=b health-cmd=q health-interval=b health-retries=i
|
|
44
|
-
health-start-interval=q health-start-period=q health-timeout=q
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
memory-
|
|
48
|
-
|
|
49
|
-
stop-
|
|
50
|
-
|
|
51
|
-
run: %w[d|detach detach-keys=q sig-proxy=b?].freeze,
|
|
45
|
+
health-start-interval=q health-start-period=q health-timeout=q io-maxbandwidth=b io-maxiops=b
|
|
46
|
+
ip=b ip6=q ipc=b isolation=b kernel-memory=b l|label=q label-file=q link=b link-local-ip=q
|
|
47
|
+
log-driver=b log-opt=q mac-address=q m|memory=b memory-reservation=b memory-swap=n
|
|
48
|
+
memory-swappiness=n mount=qq name=b network=b network-alias=b oom-score-adj=b pid=b pids-limit=n
|
|
49
|
+
platform=b p|publish=q pull=b restart=b runtime=b security-opt=q shm-size=b stop-signal=b
|
|
50
|
+
stop-timeout=i storage-opt=q sysctl=q tmpfs=q ulimit=q u|user=b userns=b uts=b v|volume=q
|
|
51
|
+
volume-driver=b volumes-from=b w|workdir=q].freeze,
|
|
52
|
+
run: %w[d|detach detach-keys=q hostname=q sig-proxy=b?].freeze,
|
|
52
53
|
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
|
|
53
54
|
cpuset-cpus=b cpuset-mems=b m|memory=b memory-reservation=b memory-swap=b pids-limit=n
|
|
54
55
|
restart=q].freeze,
|
|
@@ -57,16 +58,16 @@ module Squared
|
|
|
57
58
|
commit: %w[a|author=q c|change=q m|message=q pause=b?].freeze,
|
|
58
59
|
inspect: %w[s|size f|format=q type=b].freeze,
|
|
59
60
|
start: %w[a|attach i|interactive detach-keys=q].freeze,
|
|
60
|
-
stop: %w[s|signal=b t|
|
|
61
|
-
restart: %w[s|signal=b t|
|
|
61
|
+
stop: %w[s|signal=b t|timeout=i].freeze,
|
|
62
|
+
restart: %w[s|signal=b t|timeout=i].freeze,
|
|
62
63
|
kill: %w[s|signal=b].freeze,
|
|
63
64
|
stats: %w[a|all no-stream no-trunc format|q].freeze
|
|
64
65
|
}.freeze,
|
|
65
66
|
image: {
|
|
66
|
-
|
|
67
|
-
push: %w[a|all-tags disable-content-trust=b? platform=
|
|
68
|
-
rm: %w[f|force no-prune platform=
|
|
69
|
-
save: %w[o|output=p platform=
|
|
67
|
+
ls: %w[a|all digests no-trunc q|quiet tree f|filter=q format=q].freeze,
|
|
68
|
+
push: %w[a|all-tags disable-content-trust=b? platform=b q|quiet].freeze,
|
|
69
|
+
rm: %w[f|force no-prune platform=b].freeze,
|
|
70
|
+
save: %w[o|output=p platform=b].freeze
|
|
70
71
|
}.freeze,
|
|
71
72
|
network: {
|
|
72
73
|
connect: %w[alias=b driver-opt=q gw-priority=n ip=b ip6=q link=b link-local-ip=q].freeze,
|
|
@@ -80,6 +81,15 @@ module Squared
|
|
|
80
81
|
volume: %w[volume-subpath volume-nocopy volume-opt].freeze,
|
|
81
82
|
tmpfs: %w[tmpfs-size tmpfs-mode].freeze,
|
|
82
83
|
image: %w[image-path].freeze
|
|
84
|
+
}.freeze,
|
|
85
|
+
ls: {
|
|
86
|
+
compose: %w[Name Image Command Service RunningFor Status Ports CreatedAt ExitCode Health ID Labels
|
|
87
|
+
LocalVolumes Mounts Names Networks Project Publishers Size State].freeze,
|
|
88
|
+
container: %w[ID Image Command RunningFor Status Ports Names CreatedAt Labels LocalVolumes Mounts Networks
|
|
89
|
+
Platform Size State].freeze,
|
|
90
|
+
image: %w[Repository Tag ID Containers CreatedSince Size CreatedAt Digest SharedSize UniqueSize
|
|
91
|
+
VirtualSize].freeze,
|
|
92
|
+
network: %w[ID Name Driver Scope CreatedAt IPv4 IPv6 Internal Labels].freeze
|
|
83
93
|
}.freeze
|
|
84
94
|
}.freeze
|
|
85
95
|
private_constant :COMPOSEFILE, :BAKEFILE, :OPT_DOCKER, :VAL_DOCKER
|
|
@@ -98,12 +108,13 @@ module Squared
|
|
|
98
108
|
|
|
99
109
|
subtasks({
|
|
100
110
|
'build' => %i[tag context].freeze,
|
|
101
|
-
'compose' => %i[build run exec up down].freeze,
|
|
111
|
+
'compose' => %i[build create run exec up down service].freeze,
|
|
102
112
|
'bake' => %i[build check].freeze,
|
|
103
|
-
'image' => %i[
|
|
113
|
+
'image' => %i[ls rm push tag save].freeze,
|
|
104
114
|
'container' => %i[run create exec update commit inspect diff start stop restart pause unpause top stats kill
|
|
105
115
|
rm].freeze,
|
|
106
|
-
'network' => %i[connect disconnect].freeze
|
|
116
|
+
'network' => %i[connect disconnect].freeze,
|
|
117
|
+
'ls' => nil
|
|
107
118
|
})
|
|
108
119
|
|
|
109
120
|
attr_reader :context
|
|
@@ -136,114 +147,168 @@ module Squared
|
|
|
136
147
|
Docker.subtasks do |action, flags|
|
|
137
148
|
next if task_pass?(action)
|
|
138
149
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
150
|
+
if flags.nil?
|
|
151
|
+
case action
|
|
152
|
+
when 'ls'
|
|
153
|
+
format_desc(action, nil, VAL_DOCKER[:ls].keys, after: 'a/ll?,s/tandard?,range*', arg: nil)
|
|
154
|
+
task action, [:command] do |_, args|
|
|
155
|
+
command = param_guard(action, 'command', args: args, key: :command)
|
|
156
|
+
args = args.extras
|
|
157
|
+
a = args.delete('a') || args.delete('all')
|
|
158
|
+
ls = case command
|
|
159
|
+
when 'network'
|
|
160
|
+
a = nil
|
|
161
|
+
'ls'
|
|
162
|
+
when 'image', 'container'
|
|
163
|
+
'ls'
|
|
164
|
+
when 'compose'
|
|
165
|
+
'ps'
|
|
166
|
+
else
|
|
167
|
+
raise_error ArgumentError, 'unrecognized command', hint: command
|
|
168
|
+
end
|
|
169
|
+
data = VAL_DOCKER[:ls][command.to_sym]
|
|
170
|
+
if args.delete('s') || args.delete('standard')
|
|
171
|
+
cols = data.first(data.index('CreatedAt'))
|
|
172
|
+
else
|
|
173
|
+
cols = []
|
|
174
|
+
args.each do |val|
|
|
175
|
+
if val =~ /^(\d+)$/
|
|
176
|
+
cols << data[$1.to_i.pred]
|
|
177
|
+
elsif val =~ /^(\d+)(-|\.{2,3})(\d+)$/
|
|
178
|
+
j = $1.to_i.pred
|
|
179
|
+
k = $3.to_i - ($2 == '..' ? 2 : 1)
|
|
180
|
+
cols.concat(data[j..k]) if k > j
|
|
181
|
+
end
|
|
182
|
+
end
|
|
183
|
+
if cols.empty?
|
|
184
|
+
cols = choice_index('Select a column', data, multiple: true, force: true, attempts: 1)
|
|
185
|
+
end
|
|
186
|
+
end
|
|
187
|
+
cmd = docker_output(command, ls, a && '-a')
|
|
188
|
+
cmd << quote_option('format', "table #{cols.map! { |val| "{{.#{val}}}" }.join("\t")}")
|
|
189
|
+
run(cmd, banner: false, from: :ls)
|
|
190
|
+
end
|
|
191
|
+
end
|
|
192
|
+
else
|
|
193
|
+
namespace action do
|
|
194
|
+
flags.each do |flag|
|
|
195
|
+
case action
|
|
196
|
+
when 'build'
|
|
145
197
|
format_desc(action, flag, 'opts*', before: flag == :tag ? 'name' : 'dir')
|
|
146
198
|
task flag, [flag] do |_, args|
|
|
147
199
|
param = param_guard(action, flag, args: args, key: flag)
|
|
148
200
|
buildx(:build, args.extras, "#{flag}": param)
|
|
149
201
|
end
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
202
|
+
when 'bake'
|
|
203
|
+
break unless bake?
|
|
204
|
+
|
|
205
|
+
case flag
|
|
206
|
+
when :build
|
|
207
|
+
format_desc action, flag, 'opts*,target*,context?|:'
|
|
208
|
+
task flag do |_, args|
|
|
209
|
+
args = args.to_a
|
|
210
|
+
if args.first == ':'
|
|
211
|
+
choice_command :bake
|
|
212
|
+
else
|
|
213
|
+
buildx :bake, args
|
|
214
|
+
end
|
|
163
215
|
end
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
buildx :bake, ['allow=fs.read=*', 'call=check', target]
|
|
170
|
-
end
|
|
171
|
-
end
|
|
172
|
-
when 'compose'
|
|
173
|
-
break unless compose?
|
|
174
|
-
|
|
175
|
-
case flag
|
|
176
|
-
when :build, :up, :down
|
|
177
|
-
format_desc action, flag, 'opts*,service*|:'
|
|
178
|
-
task flag do |_, args|
|
|
179
|
-
compose! flag, args.to_a
|
|
180
|
-
end
|
|
181
|
-
when :exec, :run
|
|
182
|
-
format_desc action, flag, "service|:,command#{flag == :exec ? '' : '?'}|::,args*,opts*"
|
|
183
|
-
task flag, [:service] do |_, args|
|
|
184
|
-
service = param_guard(action, flag, args: args, key: :service)
|
|
185
|
-
compose!(flag, args.extras, service: service)
|
|
186
|
-
end
|
|
187
|
-
end
|
|
188
|
-
when 'container'
|
|
189
|
-
case flag
|
|
190
|
-
when :exec, :commit
|
|
191
|
-
format_desc(action, flag, flag == :exec ? 'id/name,opts*,args+|:' : 'id/name,tag?,opts*')
|
|
192
|
-
task flag, [:id] do |_, args|
|
|
193
|
-
if flag == :exec && !args.id
|
|
194
|
-
choice_command flag
|
|
195
|
-
else
|
|
196
|
-
id = param_guard(action, flag, args: args, key: :id)
|
|
197
|
-
container(flag, args.extras, id: id)
|
|
216
|
+
when :check
|
|
217
|
+
format_desc action, flag, 'target'
|
|
218
|
+
task flag, [:target] do |_, args|
|
|
219
|
+
target = param_guard(action, flag, args: args, key: :target)
|
|
220
|
+
buildx :bake, ['allow=fs.read=*', 'call=check', target]
|
|
198
221
|
end
|
|
199
222
|
end
|
|
200
|
-
when
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
223
|
+
when 'compose'
|
|
224
|
+
break unless compose?
|
|
225
|
+
|
|
226
|
+
case flag
|
|
227
|
+
when :exec, :run
|
|
228
|
+
format_desc action, flag, "service|:,command#{flag == :exec ? '' : '?'}|::,args*,opts*"
|
|
229
|
+
task flag, [:service] do |_, args|
|
|
230
|
+
service = param_guard(action, flag, args: args, key: :service)
|
|
231
|
+
compose!(flag, args.extras, service: service)
|
|
232
|
+
end
|
|
233
|
+
when :service
|
|
234
|
+
cmds = %w[down kill pause restart rm start stop top unpause watch].freeze
|
|
235
|
+
format_desc(action, flag, cmds, arg: nil, after: 'name+|:')
|
|
236
|
+
task flag, [:command] do |_, args|
|
|
237
|
+
command = param_guard(action, flag, args: args, key: :command)
|
|
238
|
+
raise_error ArgumentError, 'unrecognized command', hint: command unless cmds.include?(command)
|
|
239
|
+
service = args.extras
|
|
240
|
+
if service.first == ':'
|
|
241
|
+
choice_command flag, command
|
|
242
|
+
else
|
|
243
|
+
compose!(flag, [command], service: service.empty? || service)
|
|
244
|
+
end
|
|
245
|
+
end
|
|
246
|
+
else
|
|
247
|
+
format_desc action, flag, 'opts*,service*|:'
|
|
248
|
+
task flag do |_, args|
|
|
249
|
+
compose!(flag, args.to_a, multiple: true)
|
|
207
250
|
end
|
|
208
251
|
end
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
252
|
+
when 'container'
|
|
253
|
+
case flag
|
|
254
|
+
when :exec, :commit
|
|
255
|
+
format_desc(action, flag, flag == :exec ? 'id/name,opts*,args+|:' : 'id/name,tag?,opts*')
|
|
256
|
+
task flag, [:id] do |_, args|
|
|
257
|
+
if flag == :exec && !args.id
|
|
258
|
+
choice_command flag
|
|
259
|
+
else
|
|
260
|
+
id = param_guard(action, flag, args: args, key: :id)
|
|
261
|
+
container(flag, args.extras, id: id)
|
|
262
|
+
end
|
|
263
|
+
end
|
|
264
|
+
when :run, :create
|
|
265
|
+
format_desc action, flag, 'image,opts*,args*|:'
|
|
266
|
+
task flag, [:image] do |_, args|
|
|
267
|
+
if args.image
|
|
268
|
+
container(flag, args.extras, id: args.image)
|
|
269
|
+
else
|
|
270
|
+
choice_command flag
|
|
271
|
+
end
|
|
272
|
+
end
|
|
273
|
+
else
|
|
274
|
+
format_desc action, flag, "opts*,id/name#{flag == :update ? '+' : '*'}"
|
|
275
|
+
task flag do |_, args|
|
|
276
|
+
container flag, args.to_a
|
|
277
|
+
end
|
|
213
278
|
end
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
279
|
+
when 'image'
|
|
280
|
+
case flag
|
|
281
|
+
when :push
|
|
282
|
+
format_desc action, flag, 'tag,registry/username?,opts*'
|
|
283
|
+
task flag, [:tag] do |_, args|
|
|
284
|
+
id = param_guard(action, flag, args: args, key: :tag)
|
|
285
|
+
image(flag, args.extras, id: id)
|
|
286
|
+
end
|
|
287
|
+
else
|
|
288
|
+
format_desc(action, flag, case flag
|
|
289
|
+
when :rm, :save then 'id*,opts*'
|
|
290
|
+
when :tag then 'version?'
|
|
291
|
+
else 'opts*,args*'
|
|
292
|
+
end)
|
|
293
|
+
task flag do |_, args|
|
|
294
|
+
args = args.to_a
|
|
295
|
+
if !args.empty? || flag == :ls
|
|
296
|
+
image flag, args
|
|
297
|
+
else
|
|
298
|
+
choice_command flag
|
|
299
|
+
end
|
|
300
|
+
end
|
|
222
301
|
end
|
|
223
|
-
|
|
224
|
-
format_desc
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
end)
|
|
229
|
-
task flag do |_, args|
|
|
230
|
-
args = args.to_a
|
|
231
|
-
if args.empty? && flag != :list
|
|
232
|
-
choice_command flag
|
|
302
|
+
when 'network'
|
|
303
|
+
format_desc action, flag, 'target,opts*'
|
|
304
|
+
task flag, [:target] do |_, args|
|
|
305
|
+
if args.target
|
|
306
|
+
network(flag, args.extras, target: args.target)
|
|
233
307
|
else
|
|
234
|
-
|
|
308
|
+
choice_command flag
|
|
235
309
|
end
|
|
236
310
|
end
|
|
237
311
|
end
|
|
238
|
-
when 'network'
|
|
239
|
-
format_desc action, flag, 'target,opts*'
|
|
240
|
-
task flag, [:target] do |_, args|
|
|
241
|
-
if args.target
|
|
242
|
-
network(flag, args.extras, target: args.target)
|
|
243
|
-
else
|
|
244
|
-
choice_command flag
|
|
245
|
-
end
|
|
246
|
-
end
|
|
247
312
|
end
|
|
248
313
|
end
|
|
249
314
|
end
|
|
@@ -260,22 +325,23 @@ module Squared
|
|
|
260
325
|
end
|
|
261
326
|
|
|
262
327
|
def compose(opts, flags = nil, script: false, args: nil, from: :run, **)
|
|
263
|
-
return opts
|
|
328
|
+
return opts unless script
|
|
264
329
|
|
|
330
|
+
ret = docker_session
|
|
265
331
|
if from == :run
|
|
266
332
|
if bake?(n = filetype)
|
|
267
|
-
ret
|
|
333
|
+
ret << 'buildx bake'
|
|
268
334
|
append_file n
|
|
269
335
|
from = :bake
|
|
270
336
|
elsif compose?(n)
|
|
271
|
-
ret
|
|
337
|
+
ret << 'compose build'
|
|
272
338
|
append_file n
|
|
273
339
|
from = :compose
|
|
274
340
|
else
|
|
275
|
-
ret
|
|
341
|
+
ret << 'build'
|
|
276
342
|
end
|
|
277
343
|
else
|
|
278
|
-
ret
|
|
344
|
+
ret << from
|
|
279
345
|
end
|
|
280
346
|
case opts
|
|
281
347
|
when String
|
|
@@ -285,10 +351,10 @@ module Squared
|
|
|
285
351
|
when Enumerable
|
|
286
352
|
ret.merge(opts.to_a)
|
|
287
353
|
end
|
|
288
|
-
[args, flags].each_with_index do |
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
354
|
+
[args, flags].each_with_index do |item, i|
|
|
355
|
+
next unless item && (data = append_any(item, target: []))
|
|
356
|
+
|
|
357
|
+
ret.merge(data.map! { |arg| i == 0 ? fill_option(arg) : quote_option('build-arg', arg) })
|
|
292
358
|
end
|
|
293
359
|
case from
|
|
294
360
|
when :run
|
|
@@ -311,8 +377,8 @@ module Squared
|
|
|
311
377
|
end
|
|
312
378
|
append_context
|
|
313
379
|
when :bake, :compose
|
|
314
|
-
option(from == :bake ? 'target' : 'service', ignore: false) do |
|
|
315
|
-
ret.merge(split_escape(
|
|
380
|
+
option(from == :bake ? 'target' : 'service', ignore: false) do |val|
|
|
381
|
+
ret.merge(split_escape(val).map! { |s| shell_quote(s) })
|
|
316
382
|
end
|
|
317
383
|
end
|
|
318
384
|
ret
|
|
@@ -320,9 +386,11 @@ module Squared
|
|
|
320
386
|
|
|
321
387
|
def buildx(flag, opts = [], tag: nil, context: nil)
|
|
322
388
|
cmd, opts = docker_session('buildx', opts: opts)
|
|
323
|
-
op =
|
|
324
|
-
|
|
325
|
-
|
|
389
|
+
op = OPT_DOCKER[:buildx].yield_self do |data|
|
|
390
|
+
OptionPartition.new(opts, data[:common], cmd, project: self)
|
|
391
|
+
.append(flag, quote: false)
|
|
392
|
+
.parse(data[flag == :bake ? :bake : :build] + data[:shared])
|
|
393
|
+
end
|
|
326
394
|
case flag
|
|
327
395
|
when :build, :context
|
|
328
396
|
append_tag(tag || option('tag', ignore: false) || self.tag)
|
|
@@ -346,41 +414,52 @@ module Squared
|
|
|
346
414
|
run(from: :"buildx:#{flag}")
|
|
347
415
|
end
|
|
348
416
|
|
|
349
|
-
def compose!(flag, opts = [], service: nil)
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
read_composefile('services', target: op.values_of('f', 'file')) { |data| keys.merge(data.keys) }
|
|
362
|
-
service = unless keys.empty?
|
|
363
|
-
choice_index('Add services', keys, multiple: multiple, force: !multiple,
|
|
364
|
-
attempts: multiple ? 1 : 5)
|
|
365
|
-
end
|
|
366
|
-
end
|
|
367
|
-
if multiple
|
|
368
|
-
op.concat(service) if service
|
|
369
|
-
op.append(delim: true, escape: true, strip: /^:/)
|
|
417
|
+
def compose!(flag, opts = [], service: nil, multiple: false)
|
|
418
|
+
from = :"compose:#{flag}"
|
|
419
|
+
if flag == :service
|
|
420
|
+
command = opts.first
|
|
421
|
+
if service == true
|
|
422
|
+
cmd, status = filter_ps command, from
|
|
423
|
+
lines = IO.popen(cmd.temp('--services')).map(&:strip).reject(&:empty?)
|
|
424
|
+
return list_empty(hint: status) if lines.empty?
|
|
425
|
+
|
|
426
|
+
service = choice_index('Choose a service', lines, multiple: true, force: true, attempts: 1)
|
|
427
|
+
end
|
|
428
|
+
docker_session('compose', command, '--', *service)
|
|
370
429
|
else
|
|
371
|
-
|
|
372
|
-
|
|
430
|
+
cmd, opts = docker_session('compose', opts: opts)
|
|
431
|
+
op = OptionPartition.new(opts, OPT_DOCKER[:compose][:common], cmd, project: self)
|
|
432
|
+
append_file filetype unless op.arg?('f', 'file')
|
|
433
|
+
op << flag
|
|
434
|
+
op.parse(OPT_DOCKER[:compose].fetch(flag, []))
|
|
435
|
+
if op.remove(':') || service == ':'
|
|
436
|
+
keys = Set.new
|
|
437
|
+
read_composefile('services', target: op.values_of('f', 'file')) { |data| keys.merge(data.keys) }
|
|
438
|
+
service = unless keys.empty?
|
|
439
|
+
choice_index('Add services', keys, multiple: multiple, force: !multiple,
|
|
440
|
+
attempts: multiple ? 1 : 3)
|
|
441
|
+
end
|
|
442
|
+
end
|
|
443
|
+
if multiple
|
|
444
|
+
op.concat(service) if service
|
|
445
|
+
op.append(delim: true, escape: true, strip: /^:/)
|
|
446
|
+
else
|
|
447
|
+
raise_error ArgumentError, 'no service was selected', hint: flag unless service
|
|
448
|
+
append_command(flag, service, op.extras, prompt: '::')
|
|
449
|
+
end
|
|
373
450
|
end
|
|
374
|
-
run(from:
|
|
451
|
+
run(from: from)
|
|
375
452
|
end
|
|
376
453
|
|
|
377
454
|
def container(flag, opts = [], id: nil)
|
|
378
455
|
cmd, opts = docker_session('container', flag, opts: opts)
|
|
379
456
|
rc = flag == :run || flag == :create
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
457
|
+
op = OPT_DOCKER[:container].yield_self do |data|
|
|
458
|
+
list = data.fetch(flag, [])
|
|
459
|
+
list += data[:create] if flag == :run
|
|
460
|
+
list += data[:update] if rc
|
|
461
|
+
OptionPartition.new(opts, list, cmd, project: self, args: rc || flag == :exec)
|
|
462
|
+
end
|
|
384
463
|
from = :"container:#{flag}"
|
|
385
464
|
case flag
|
|
386
465
|
when :run, :create, :exec
|
|
@@ -397,12 +476,12 @@ module Squared
|
|
|
397
476
|
when 'bind', 'volume', 'image', 'tmpfs'
|
|
398
477
|
type = v
|
|
399
478
|
else
|
|
400
|
-
raise_error
|
|
479
|
+
raise_error TypeError, "unknown: #{v}", hint: flag
|
|
401
480
|
end
|
|
402
481
|
elsif all.include?(k)
|
|
403
482
|
unless type
|
|
404
|
-
VAL_DOCKER[:run].each_pair do |key,
|
|
405
|
-
next unless
|
|
483
|
+
VAL_DOCKER[:run].each_pair do |key, val|
|
|
484
|
+
next unless val.include?(k)
|
|
406
485
|
|
|
407
486
|
type = key.to_s unless key == :common
|
|
408
487
|
break
|
|
@@ -421,18 +500,18 @@ module Squared
|
|
|
421
500
|
log_message(Logger::INFO, 'unrecognized option', subject: from, hint: k)
|
|
422
501
|
end
|
|
423
502
|
end
|
|
424
|
-
raise_error
|
|
503
|
+
raise_error TypeError, 'none specified', hint: flag unless type
|
|
425
504
|
cmd << "--mount type=#{type},#{args.join(',')}"
|
|
426
505
|
end
|
|
427
506
|
end
|
|
428
507
|
append_command(flag, id || tagmain, op.extras)
|
|
429
508
|
when :update
|
|
430
|
-
raise_error
|
|
509
|
+
raise_error ArgumentError, 'missing container', hint: flag if op.empty?
|
|
431
510
|
op.append(escape: true, strip: /^:/)
|
|
432
511
|
when :commit
|
|
433
512
|
latest = op.shift || tagmain
|
|
434
513
|
cmd << id << latest
|
|
435
|
-
raise_error
|
|
514
|
+
raise_error ArgumentError, "unrecognized args: #{op.join(', ')}", hint: flag unless op.empty?
|
|
436
515
|
return unless confirm_command(cmd.to_s, title: from, target: id, as: latest)
|
|
437
516
|
|
|
438
517
|
registry = option('registry') || @registry
|
|
@@ -451,38 +530,12 @@ module Squared
|
|
|
451
530
|
return image(:push, opts, id: latest, registry: registry)
|
|
452
531
|
else
|
|
453
532
|
if op.empty?
|
|
454
|
-
status =
|
|
455
|
-
no
|
|
456
|
-
|
|
457
|
-
when :inspect, :diff
|
|
458
|
-
no = false
|
|
459
|
-
when :start
|
|
460
|
-
status = %w[created exited]
|
|
461
|
-
no = false
|
|
462
|
-
when :stop, :pause
|
|
463
|
-
status = %w[running restarting]
|
|
464
|
-
when :restart
|
|
465
|
-
status = %w[running paused exited]
|
|
466
|
-
when :unpause
|
|
467
|
-
status << 'paused'
|
|
468
|
-
no = false
|
|
469
|
-
when :top, :stats
|
|
470
|
-
status << 'running'
|
|
471
|
-
cmd << '--no-stream' if flag == :stats
|
|
472
|
-
no = false
|
|
473
|
-
when :kill
|
|
474
|
-
status = %w[running restarting paused]
|
|
475
|
-
when :rm
|
|
476
|
-
status = %w[created exited dead]
|
|
477
|
-
end
|
|
478
|
-
ps = docker_output('ps -a', *status.map { |s| quote_option('filter', "status=#{s}") })
|
|
479
|
-
list_image(flag, ps, no: no, hint: "status: #{status.join(', ')}", from: from) do |img|
|
|
480
|
-
run(cmd.temp(img), from: from)
|
|
481
|
-
end
|
|
533
|
+
ps, status, no = filter_ps flag, from
|
|
534
|
+
cmd << '--no-stream' if flag == :stats
|
|
535
|
+
list_image(flag, ps, no: no, hint: status, from: from) { |img| run(cmd.temp(img), from: from) }
|
|
482
536
|
return
|
|
483
|
-
else
|
|
484
|
-
op.append(escape: true, strip: /^:/)
|
|
485
537
|
end
|
|
538
|
+
op.append(escape: true, strip: /^:/)
|
|
486
539
|
end
|
|
487
540
|
run(from: from)
|
|
488
541
|
end
|
|
@@ -490,16 +543,21 @@ module Squared
|
|
|
490
543
|
def image(flag, opts = [], sync: true, id: nil, registry: nil)
|
|
491
544
|
cmd, opts = docker_session('image', flag, opts: opts)
|
|
492
545
|
op = OptionPartition.new(opts, OPT_DOCKER[:image].fetch(flag, []), cmd, project: self)
|
|
493
|
-
exception =
|
|
546
|
+
exception = self.exception
|
|
494
547
|
banner = true
|
|
495
548
|
from = :"image:#{flag}"
|
|
496
549
|
case flag
|
|
497
|
-
when :
|
|
550
|
+
when :ls
|
|
498
551
|
if opts.size == op.size
|
|
499
552
|
index = 0
|
|
500
553
|
name = nil
|
|
501
|
-
opts.reverse_each
|
|
502
|
-
|
|
554
|
+
opts.reverse_each do |opt|
|
|
555
|
+
if (name = opt[/^name=["']?(.+?)["']?$/, 1])
|
|
556
|
+
opts.delete(opt)
|
|
557
|
+
break
|
|
558
|
+
end
|
|
559
|
+
end
|
|
560
|
+
list_image(:run, from: from) do |val|
|
|
503
561
|
container(:run, if name
|
|
504
562
|
opts.dup << "name=#{index == 0 ? name : "#{name}-#{index}"}"
|
|
505
563
|
else
|
|
@@ -508,19 +566,12 @@ module Squared
|
|
|
508
566
|
index += 1
|
|
509
567
|
end
|
|
510
568
|
return
|
|
511
|
-
else
|
|
512
|
-
op.clear
|
|
513
569
|
end
|
|
570
|
+
op.clear
|
|
514
571
|
when :rm
|
|
515
|
-
|
|
516
|
-
op << id
|
|
517
|
-
if option('y')
|
|
518
|
-
exception = false
|
|
519
|
-
banner = false
|
|
520
|
-
end
|
|
521
|
-
else
|
|
572
|
+
unless id
|
|
522
573
|
if op.empty?
|
|
523
|
-
list_image(:rm,
|
|
574
|
+
list_image(:rm, from: from) do |val|
|
|
524
575
|
image(:rm, opts, sync: sync, id: val)
|
|
525
576
|
end
|
|
526
577
|
else
|
|
@@ -528,8 +579,13 @@ module Squared
|
|
|
528
579
|
end
|
|
529
580
|
return
|
|
530
581
|
end
|
|
582
|
+
op << id
|
|
583
|
+
if option('y')
|
|
584
|
+
exception = false
|
|
585
|
+
banner = false
|
|
586
|
+
end
|
|
531
587
|
when :tag, :save
|
|
532
|
-
list_image(flag,
|
|
588
|
+
list_image(flag, from: from) do |val|
|
|
533
589
|
op << val
|
|
534
590
|
if flag == :tag
|
|
535
591
|
op << tagname("#{project}:#{op.first}")
|
|
@@ -539,8 +595,14 @@ module Squared
|
|
|
539
595
|
when :push
|
|
540
596
|
id ||= option('tag', ignore: false) || tagmain
|
|
541
597
|
registry ||= op.shift || option('registry') || @registry
|
|
542
|
-
|
|
543
|
-
|
|
598
|
+
unless id && op.empty?
|
|
599
|
+
if id
|
|
600
|
+
raise_error ArgumentError, "unrecognized args: #{op.join(', ')}", hint: flag
|
|
601
|
+
else
|
|
602
|
+
raise_error 'no id/tag', hint: flag
|
|
603
|
+
end
|
|
604
|
+
end
|
|
605
|
+
raise_error ArgumentError, 'username/registry not specified', hint: flag unless registry
|
|
544
606
|
registry.chomp!('/')
|
|
545
607
|
uri = shell_quote "#{registry}/#{id}"
|
|
546
608
|
op << uri
|
|
@@ -552,17 +614,18 @@ module Squared
|
|
|
552
614
|
exception = true
|
|
553
615
|
banner = false
|
|
554
616
|
end
|
|
555
|
-
|
|
556
|
-
|
|
617
|
+
run(cmd, sync: sync, exception: exception, banner: banner, from: from).tap do |ret|
|
|
618
|
+
success?(ret, flag == :tag || flag == :save)
|
|
619
|
+
end
|
|
557
620
|
end
|
|
558
621
|
|
|
559
622
|
def network(flag, opts = [], target: nil)
|
|
560
623
|
cmd, opts = docker_session('network', flag, opts: opts)
|
|
561
|
-
|
|
562
|
-
|
|
624
|
+
OptionPartition.new(opts, OPT_DOCKER[:network].fetch(flag, []), cmd, project: self)
|
|
625
|
+
.clear
|
|
563
626
|
from = :"network:#{flag}"
|
|
564
627
|
list_image(flag, docker_output('ps -a'), from: from) do |img|
|
|
565
|
-
|
|
628
|
+
success?(run(cmd.temp(target, img), from: from))
|
|
566
629
|
end
|
|
567
630
|
end
|
|
568
631
|
|
|
@@ -589,10 +652,10 @@ module Squared
|
|
|
589
652
|
def dockerfile(val = nil)
|
|
590
653
|
if val
|
|
591
654
|
@file = if val.is_a?(Array)
|
|
592
|
-
val = val.select { |file|
|
|
655
|
+
val = val.select { |file| exist?(file) }
|
|
593
656
|
val.size > 1 ? val : val.first
|
|
594
657
|
elsif val == true
|
|
595
|
-
DIR_DOCKER.find { |file|
|
|
658
|
+
DIR_DOCKER.find { |file| exist?(file) }
|
|
596
659
|
elsif val != 'Dockerfile'
|
|
597
660
|
val
|
|
598
661
|
end
|
|
@@ -621,8 +684,7 @@ module Squared
|
|
|
621
684
|
return session('docker', *cmd) unless opts
|
|
622
685
|
|
|
623
686
|
op = OptionPartition.new(opts, OPT_DOCKER[:common], project: self)
|
|
624
|
-
|
|
625
|
-
[ret, op.extras]
|
|
687
|
+
[session('docker', *op.to_a, *cmd), op.extras]
|
|
626
688
|
end
|
|
627
689
|
|
|
628
690
|
def docker_output(*cmd, **kwargs)
|
|
@@ -632,8 +694,8 @@ module Squared
|
|
|
632
694
|
def append_command(flag, val, list, target: @session, prompt: ':')
|
|
633
695
|
if list.delete(prompt)
|
|
634
696
|
list << readline('Enter command [args]', force: flag == :exec)
|
|
635
|
-
|
|
636
|
-
list << args
|
|
697
|
+
else
|
|
698
|
+
env('DOCKER_ARGS') { |args| list << args }
|
|
637
699
|
end
|
|
638
700
|
case flag
|
|
639
701
|
when :run
|
|
@@ -641,7 +703,7 @@ module Squared
|
|
|
641
703
|
target << basic_option('name', dnsname("#{name}_%s" % rand_s(6)))
|
|
642
704
|
end
|
|
643
705
|
when :exec
|
|
644
|
-
raise_error
|
|
706
|
+
raise_error ArgumentError, 'nothing to execute', hint: flag if list.empty?
|
|
645
707
|
end
|
|
646
708
|
target << val << list.shift
|
|
647
709
|
target << list.join(' && ') unless list.empty?
|
|
@@ -693,17 +755,45 @@ module Squared
|
|
|
693
755
|
end
|
|
694
756
|
end
|
|
695
757
|
|
|
696
|
-
def
|
|
758
|
+
def filter_ps(flag, from = :'container:ps')
|
|
759
|
+
no = false
|
|
760
|
+
status = case flag.to_sym
|
|
761
|
+
when :start
|
|
762
|
+
%w[created exited]
|
|
763
|
+
when :stop, :pause
|
|
764
|
+
no = true
|
|
765
|
+
%w[running restarting]
|
|
766
|
+
when :restart
|
|
767
|
+
no = true
|
|
768
|
+
%w[running paused exited]
|
|
769
|
+
when :unpause
|
|
770
|
+
%w[paused]
|
|
771
|
+
when :top, :stats, :watch
|
|
772
|
+
%w[running]
|
|
773
|
+
when :kill
|
|
774
|
+
no = true
|
|
775
|
+
%w[running paused restarting]
|
|
776
|
+
when :rm
|
|
777
|
+
no = true
|
|
778
|
+
%w[created exited dead]
|
|
779
|
+
else
|
|
780
|
+
[]
|
|
781
|
+
end
|
|
782
|
+
cmd = docker_output("#{from.to_s.split(':').first} ps -a",
|
|
783
|
+
*status.map { |s| quote_option('filter', "status=#{s}") })
|
|
784
|
+
[cmd, status, no]
|
|
785
|
+
end
|
|
786
|
+
|
|
787
|
+
def list_image(flag, cmd = docker_output('image ls -a'), hint: nil, from: nil, no: true)
|
|
697
788
|
pwd_set do
|
|
698
|
-
|
|
699
|
-
index = 0
|
|
789
|
+
index = 1
|
|
700
790
|
all = option('all', prefix: 'docker')
|
|
701
791
|
y = from == :'image:rm' && option('y', prefix: 'docker')
|
|
702
792
|
pat = /\b(?:#{dnsname(name)}|#{tagname(project)}|#{tagmain.split(':', 2).first})\b/
|
|
703
|
-
IO.popen(
|
|
793
|
+
IO.popen(cmd.temp('--format=json')).each do |line|
|
|
704
794
|
data = JSON.parse(line)
|
|
705
795
|
id = data['ID']
|
|
706
|
-
rt = [data['Repository'], data['Tag']].reject { |val| val == '<none>' }.join(':')
|
|
796
|
+
rt = [data['Repository'], data['Tag']].reject { |val| val.to_s.empty? || val == '<none>' }.join(':')
|
|
707
797
|
rt = nil if rt.empty?
|
|
708
798
|
aa = data['Names'] || (if rt && data['Repository']
|
|
709
799
|
dd = true
|
|
@@ -715,16 +805,16 @@ module Squared
|
|
|
715
805
|
next unless all || ee.match?(pat) || aa.match?(pat)
|
|
716
806
|
|
|
717
807
|
unless y
|
|
718
|
-
bb = index.
|
|
719
|
-
cc = bb.size
|
|
808
|
+
bb = index.to_s
|
|
809
|
+
cc = bb.size.succ
|
|
720
810
|
a = sub_style(ee, styles: theme[:inline])
|
|
721
|
-
b = "Execute #{sub_style(flag, styles: theme[:active])} on #{a
|
|
811
|
+
b = "Execute #{sub_style(flag, styles: theme[:active])} on #{a.subhint(ee == id ? nil : id)}"
|
|
722
812
|
e = time_format(time_since(data['CreatedAt']), pass: ['ms'])
|
|
723
813
|
f = sub_style(ARG[:BORDER][0], styles: theme[:inline])
|
|
724
|
-
g = ' ' *
|
|
814
|
+
g = ' ' * cc.succ
|
|
725
815
|
h = "#{sub_style(bb.rjust(cc), styles: theme[:current])} #{f} "
|
|
726
|
-
puts unless index ==
|
|
727
|
-
puts
|
|
816
|
+
puts unless index == 1
|
|
817
|
+
puts (h + sub_style(aa, styles: theme[:subject])).subhint("created #{e} ago")
|
|
728
818
|
cols = %w[Tag Status Ports]
|
|
729
819
|
cols << case flag
|
|
730
820
|
when :connect, :disconnect
|
|
@@ -739,89 +829,104 @@ module Squared
|
|
|
739
829
|
end
|
|
740
830
|
w = 9 + flag.to_s.size + 4 + ee.size
|
|
741
831
|
puts g + sub_style(ARG[:BORDER][6] + (ARG[:BORDER][1] * w), styles: theme[:inline])
|
|
742
|
-
found = true
|
|
743
832
|
index += 1
|
|
744
|
-
next unless confirm("#{h + b}?", no ? 'N' : 'Y'
|
|
833
|
+
next unless confirm("#{h + b}?", no ? 'N' : 'Y')
|
|
745
834
|
|
|
746
835
|
puts if printfirst?
|
|
747
836
|
end
|
|
748
837
|
yield id
|
|
749
838
|
end
|
|
750
|
-
|
|
839
|
+
list_empty(hint: hint || from) if index == 1 && !y
|
|
751
840
|
end
|
|
752
841
|
rescue StandardError => e
|
|
753
842
|
on_error e, from
|
|
754
843
|
end
|
|
755
844
|
|
|
845
|
+
def list_empty(subject: name, hint: nil, **kwargs)
|
|
846
|
+
hint = "status: #{hint.join(', ')}" if hint.is_a?(Array)
|
|
847
|
+
puts log_message(Logger::INFO, 'none detected', subject: subject, hint: hint, **kwargs)
|
|
848
|
+
end
|
|
849
|
+
|
|
756
850
|
def confirm_command(*args, title: nil, target: nil, as: nil)
|
|
757
851
|
return false unless title && target
|
|
758
852
|
|
|
759
853
|
puts unless printfirst?
|
|
760
854
|
t = title.to_s.split(':')
|
|
761
855
|
emphasize(args, title: message(t.first.upcase, *t.drop(1)), border: borderstyle, sub: [
|
|
762
|
-
|
|
763
|
-
|
|
856
|
+
opt_style(theme[:header], /\A(\w+(?: => \w+)+)(.*)\z/),
|
|
857
|
+
opt_style(theme[:caution], /\A(.+)\z/)
|
|
764
858
|
])
|
|
765
859
|
printsucc
|
|
766
860
|
a = t.last.capitalize
|
|
767
861
|
b = sub_style(target, styles: theme[:subject])
|
|
768
862
|
c = as && sub_style(as, styles: theme[:inline])
|
|
769
|
-
confirm
|
|
770
|
-
end
|
|
771
|
-
|
|
772
|
-
def choice_command(flag)
|
|
773
|
-
msg, cmd
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
863
|
+
confirm "#{a} #{b}#{c ? " as #{c}" : ''}?", 'N'
|
|
864
|
+
end
|
|
865
|
+
|
|
866
|
+
def choice_command(flag, *action)
|
|
867
|
+
msg, cmd = case flag
|
|
868
|
+
when :exec
|
|
869
|
+
['Choose a container', 'ps -a']
|
|
870
|
+
when :bake
|
|
871
|
+
['Choose a target', 'buildx bake --list=type=targets']
|
|
872
|
+
when :connect, :disconnect
|
|
873
|
+
['Choose a network', 'network ls']
|
|
874
|
+
when :service
|
|
875
|
+
['Choose a service',
|
|
876
|
+
'compose ps -a ' \
|
|
877
|
+
"--format='table {{.Service}}\t{{.Name}}\t{{.Image}}\t{{.Command}}\t{{.Status}}\t{{.Ports}}'"]
|
|
878
|
+
else
|
|
879
|
+
['Choose an image',
|
|
880
|
+
'images -a ' \
|
|
881
|
+
"--format='table {{.ID}}\t{{.Repository}}\t{{.Tag}}\t{{.CreatedSince}}\t{{.Size}}'"]
|
|
882
|
+
end
|
|
783
883
|
lines = `#{docker_output(cmd)}`.lines
|
|
784
884
|
header = lines.shift
|
|
785
885
|
if lines.empty?
|
|
786
|
-
puts log_message(Logger::INFO, 'none found', subject: name,
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
886
|
+
puts log_message(Logger::INFO, 'none found', subject: name,
|
|
887
|
+
hint: "docker #{cmd.split(' ', 3)[0...2].join(' ')}")
|
|
888
|
+
return
|
|
889
|
+
end
|
|
890
|
+
puts " # #{header}"
|
|
891
|
+
multiple = false
|
|
892
|
+
parse = ->(val) { val.split(/\s+/)[0] }
|
|
893
|
+
ctx = flag.to_s
|
|
894
|
+
case flag
|
|
895
|
+
when :run, :exec
|
|
896
|
+
values = [['Options', flag == :run], ['Arguments', flag == :exec]]
|
|
897
|
+
when :rm, :bake
|
|
898
|
+
values = ['Options']
|
|
899
|
+
multiple = true
|
|
900
|
+
ctx = flag == :rm ? 'image rm' : "buildx bake -f #{shell_quote(dockerfile)}"
|
|
901
|
+
when :save
|
|
902
|
+
values = [['Output', true], 'Platform']
|
|
903
|
+
multiple = true
|
|
904
|
+
when :service
|
|
905
|
+
values = []
|
|
906
|
+
multiple = true
|
|
907
|
+
ctx = 'compose'
|
|
908
|
+
when :connect, :disconnect
|
|
909
|
+
values = ['Options', ['Container', true]]
|
|
910
|
+
ctx = "network #{flag}"
|
|
911
|
+
end
|
|
912
|
+
out, opts, args = choice_index(msg, lines, multiple: multiple, values: values)
|
|
913
|
+
cmd = docker_output(ctx, *action)
|
|
914
|
+
case flag
|
|
915
|
+
when :tag
|
|
916
|
+
args = tagjoin @registry, tag
|
|
917
|
+
when :save
|
|
918
|
+
opts = "#{opts}.tar" unless opts.end_with?('.tar')
|
|
919
|
+
cmd << quote_option('output', File.expand_path(opts))
|
|
920
|
+
if args
|
|
921
|
+
cmd << basic_option('platform', args)
|
|
922
|
+
args = nil
|
|
820
923
|
end
|
|
821
|
-
|
|
822
|
-
cmd <<
|
|
823
|
-
print_success if success?(run(cmd), ctx.start_with?(/network|tag|save/))
|
|
924
|
+
else
|
|
925
|
+
cmd << opts << '--'
|
|
824
926
|
end
|
|
927
|
+
cmd.merge(Array(out).map! { |val| parse.call(val) })
|
|
928
|
+
cmd << args
|
|
929
|
+
success?(run(cmd), ctx.start_with?(/(?:network|tag|save)/))
|
|
825
930
|
end
|
|
826
931
|
|
|
827
932
|
def filetype(val = dockerfile)
|
|
@@ -850,10 +955,9 @@ module Squared
|
|
|
850
955
|
|
|
851
956
|
def tagname(val)
|
|
852
957
|
val = val.split(':').map! { |s| charname(s.sub(/^\W+/, '')) }
|
|
853
|
-
val.join(':')
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
end
|
|
958
|
+
ret = val.join(':')
|
|
959
|
+
ret = val.first if val.size > 1 && ret.size > 128
|
|
960
|
+
ret[0..127]
|
|
857
961
|
end
|
|
858
962
|
|
|
859
963
|
def dnsname(val)
|