squared 0.4.36 → 0.5.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 +64 -529
- data/README.md +1283 -663
- data/README.ruby.md +722 -0
- data/lib/squared/common/base.rb +8 -9
- data/lib/squared/common/format.rb +26 -39
- data/lib/squared/common/prompt.rb +46 -51
- data/lib/squared/common/shell.rb +50 -70
- data/lib/squared/common/system.rb +34 -37
- data/lib/squared/common/utils.rb +3 -28
- data/lib/squared/common.rb +2 -1
- data/lib/squared/config.rb +30 -33
- data/lib/squared/version.rb +1 -1
- data/lib/squared/workspace/application.rb +82 -122
- data/lib/squared/workspace/project/base.rb +432 -578
- data/lib/squared/workspace/project/docker.rb +186 -214
- data/lib/squared/workspace/project/git.rb +368 -512
- data/lib/squared/workspace/project/node.rb +195 -315
- data/lib/squared/workspace/project/python.rb +125 -355
- data/lib/squared/workspace/project/ruby.rb +258 -340
- data/lib/squared/workspace/project/support/class.rb +92 -313
- data/lib/squared/workspace/project.rb +0 -10
- data/lib/squared/workspace/repo.rb +58 -99
- data/lib/squared/workspace/series.rb +41 -47
- data/lib/squared/workspace/support/data.rb +3 -2
- data/lib/squared/workspace/support.rb +0 -1
- data/lib/squared/workspace.rb +3 -5
- data/squared.gemspec +5 -5
- metadata +7 -8
- data/lib/squared/common/class.rb +0 -186
- data/lib/squared/workspace/support/base.rb +0 -32
|
@@ -4,82 +4,76 @@ module Squared
|
|
|
4
4
|
module Workspace
|
|
5
5
|
module Project
|
|
6
6
|
class Docker < Base
|
|
7
|
-
COMPOSEFILE = %w[compose.yaml compose.yml docker-compose.yaml docker-compose.yml].freeze
|
|
7
|
+
COMPOSEFILE = %w[compose.yaml compose.yml docker-compose.yaml compose.yml docker-compose.yml].freeze
|
|
8
8
|
BAKEFILE = %w[docker-bake.json docker-bake.hcl docker-bake.override.json docker-bake.override.hcl].freeze
|
|
9
|
-
DIR_DOCKER = (COMPOSEFILE + BAKEFILE
|
|
9
|
+
DIR_DOCKER = (COMPOSEFILE + BAKEFILE).freeze
|
|
10
10
|
OPT_DOCKER = {
|
|
11
11
|
common: %w[tls tlsverify config=p c|context=b D|debug H|host=q l|log-level=b tlscacert=p tlscert=p
|
|
12
12
|
tlskey=p].freeze,
|
|
13
13
|
buildx: {
|
|
14
14
|
common: %w[builder=b D|debug],
|
|
15
|
-
build: %w[add-host=q annotation=q attest=q build-arg=qq
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
bake: %w[print list=q set=q].freeze,
|
|
19
|
-
shared: %w[check
|
|
20
|
-
sbom=q].freeze
|
|
15
|
+
build: %w[load pull push add-host=q annotation=q attest=q build-arg=qq ent=q iidfile=p label=q a-file=p
|
|
16
|
+
network=b no-cache-filter=b o|output=q platform=b q|quiet secret=qq shm-size=b ssh=qq t|tag=b
|
|
17
|
+
target=b ulimit=q].freeze,
|
|
18
|
+
bake: %w[load print pull push list=q metadata-file=p set=q].freeze,
|
|
19
|
+
shared: %w[check no-cache allow=q call=b? f|file=p progress=b provenance=q sbom=q].freeze
|
|
21
20
|
}.freeze,
|
|
22
21
|
compose: {
|
|
23
|
-
common: %w[all-resources compatibility dry-run ansi|b env-file=p f|file=p parallel=
|
|
22
|
+
common: %w[all-resources compatibility dry-run ansi|b env-file=p f|file=p parallel=b profile=b progress=b
|
|
24
23
|
project-directory=p p|project-name=e].freeze,
|
|
25
|
-
build: %w[
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
exit-code-from=b no-attach=b pull=b scale=i t|timeout=i wait-timeout=i].freeze,
|
|
35
|
-
down: %w[remove-orphans v|volumes rmi=b t|timeout=i].freeze
|
|
24
|
+
build: %w[no-cache pull push with-dependencies q|quiet build-arg=qq builder=b m|memory=b ssh=qq].freeze,
|
|
25
|
+
exec: %w[dry-run privileged d|detach e|env=qq index=i T|no-TTY=b? user=e w|workdir=q].freeze,
|
|
26
|
+
run: %w[build dry-run no-deps quiet-pull remove-orphans rm P|service-ports use-aliases cap-add=b cap-drop=b
|
|
27
|
+
d|detach entrypoint=q e|env=qq i|interactive=b? l|label=q name=b T|no-TTY=b? p|publish=e pull=b
|
|
28
|
+
u|user=e v|volume=q w|workdir=q].freeze,
|
|
29
|
+
up: %w[y abort-on-container-exit abort-on-container-failure always-recreate-deps attach-dependencies build
|
|
30
|
+
d|detach dry-run force-recreate menu no-build no-color no-deps no-log-prefix no-recreate no-start
|
|
31
|
+
quiet-pull remove-orphans V|renew-anon-volumes timestamps wait w|watch attach=b exit-code-from=b
|
|
32
|
+
no-attach=b pull=b scale=i t|timeout=i wait-timeout=i].freeze
|
|
36
33
|
}.freeze,
|
|
37
34
|
container: {
|
|
38
35
|
create: %w[init i|interactive no-healthcheck oom-kill-disable privileged P|publish-all q|quiet read-only
|
|
39
|
-
rm t|tty use-api-socket
|
|
40
|
-
cap-add=b cap-drop=b cgroup-parent=b cgroupns=b
|
|
41
|
-
device-
|
|
42
|
-
disable-content-trust=b? dns=
|
|
43
|
-
env-file=p expose=
|
|
44
|
-
health-start-interval=
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
memory-
|
|
48
|
-
|
|
49
|
-
stop-
|
|
50
|
-
|
|
36
|
+
rm runtime t|tty use-api-socket io-maxbandwidth=b io-maxiops=b add-host=q annotation=q
|
|
37
|
+
a|attach=b blkio-weight=i blkio-weight-device=i cap-add=b cap-drop=b cgroup-parent=b cgroupns=b
|
|
38
|
+
cidfile=p device=q device-cgroup-rule=q device-read-bps=q device-read-iops=q device-write-bps=q
|
|
39
|
+
device-write-iops=q disable-content-trust=b? dns=e dns-option=e dns-search=e domainname=b
|
|
40
|
+
entrypoint=q e|env=qq env-file=p expose=e gpus=q group-add=b health-cmd=q health-interval=b
|
|
41
|
+
health-retries=i health-start-interval=b health-start-period=b health-timeout=b h|hostname=e ip=b
|
|
42
|
+
ip6=e ipc=b isolation=b kernel-memory=b l|label=q label-file=p link=b link-local-ip=b
|
|
43
|
+
log-driver=b log-opt=q mac-address=e m|memory=b memory-reservation=b memory-swap=n
|
|
44
|
+
memory-swappiness=n mount=qq name=b network=b network-alias=b oom-score-adj=b pid=b pids-limit=n
|
|
45
|
+
platform=b p|publish=e pull=b restart=b runtime=b security-opt=q shm-size=b stop-signal=b
|
|
46
|
+
stop-timeout=i storage-opt=q sysctl=q tmpfs=q ulimit=q u|user=b userns=b uts=b v|volume=q
|
|
47
|
+
volume-driver=b volumes-from=b w|workdir=q].freeze,
|
|
51
48
|
run: %w[d|detach detach-keys=q sig-proxy=b?].freeze,
|
|
49
|
+
exec: %w[d|detach i|interactive privileged t|tty detach-keys=q e|env=qq env-file=p user=e
|
|
50
|
+
w|workdir=q].freeze,
|
|
52
51
|
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
52
|
cpuset-cpus=b cpuset-mems=b m|memory=b memory-reservation=b memory-swap=b pids-limit=n
|
|
54
53
|
restart=q].freeze,
|
|
55
|
-
exec: %w[d|detach i|interactive privileged t|tty detach-keys=q e|env=qq env-file=p user=e
|
|
56
|
-
w|workdir=q].freeze,
|
|
57
54
|
commit: %w[a|author=q c|change=q m|message=q pause=b?].freeze,
|
|
58
|
-
inspect: %w[s|size f|format=q
|
|
55
|
+
inspect: %w[s|size f|format=q].freeze,
|
|
59
56
|
start: %w[a|attach i|interactive detach-keys=q].freeze,
|
|
60
|
-
stop: %w[s|signal=b t|time=i
|
|
61
|
-
restart: %w[s|signal=b t|time=i
|
|
57
|
+
stop: %w[s|signal=b t|time=i].freeze,
|
|
58
|
+
restart: %w[s|signal=b t|time=i].freeze,
|
|
62
59
|
kill: %w[s|signal=b].freeze,
|
|
63
|
-
stats: %w[
|
|
60
|
+
stats: %w[no-trunc format|q].freeze
|
|
64
61
|
}.freeze,
|
|
65
62
|
image: {
|
|
66
|
-
list: %w[a|all
|
|
67
|
-
push: %w[a|all-tags disable-content-trust=b? platform=
|
|
68
|
-
rm: %w[f|force no-prune
|
|
69
|
-
save: %w[o|output=p platform=
|
|
63
|
+
list: %w[a|all digests no-trunc f|filter=q format=q].freeze,
|
|
64
|
+
push: %w[a|all-tags disable-content-trust=b? platform=b q|quiet].freeze,
|
|
65
|
+
rm: %w[f|force no-prune].freeze,
|
|
66
|
+
save: %w[o|output=p platform=b].freeze
|
|
70
67
|
}.freeze,
|
|
71
68
|
network: {
|
|
72
|
-
connect: %w[alias=b driver-opt=q gw-priority=n ip=b ip6=
|
|
69
|
+
connect: %w[alias=b driver-opt=q gw-priority=n ip=b ip6=b link=b link-local-ip=b].freeze,
|
|
73
70
|
disconnect: %w[f|force].freeze
|
|
74
71
|
}.freeze
|
|
75
72
|
}.freeze
|
|
76
73
|
VAL_DOCKER = {
|
|
77
74
|
run: {
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
volume: %w[volume-subpath volume-nocopy volume-opt].freeze,
|
|
81
|
-
tmpfs: %w[tmpfs-size tmpfs-mode].freeze,
|
|
82
|
-
image: %w[image-path].freeze
|
|
75
|
+
bind: %w[type source src destination dst target readonly ro bind-propagation].freeze,
|
|
76
|
+
tmpfs: %w[type destination dst target tmpfs-size tmpfs-mode].freeze
|
|
83
77
|
}.freeze
|
|
84
78
|
}.freeze
|
|
85
79
|
private_constant :COMPOSEFILE, :BAKEFILE, :OPT_DOCKER, :VAL_DOCKER
|
|
@@ -92,14 +86,13 @@ module Squared
|
|
|
92
86
|
def config?(val)
|
|
93
87
|
return false unless (val = as_path(val))
|
|
94
88
|
|
|
95
|
-
DIR_DOCKER.any? { |file| val.join(file).exist? }
|
|
89
|
+
val.join('Dockerfile').exist? || DIR_DOCKER.any? { |file| val.join(file).exist? }
|
|
96
90
|
end
|
|
97
91
|
end
|
|
98
92
|
|
|
99
93
|
subtasks({
|
|
100
|
-
'build' => %i[tag context].freeze,
|
|
101
|
-
'compose' => %i[build run exec up
|
|
102
|
-
'bake' => %i[build check].freeze,
|
|
94
|
+
'build' => %i[tag context bake].freeze,
|
|
95
|
+
'compose' => %i[build run exec up].freeze,
|
|
103
96
|
'image' => %i[list rm push tag save].freeze,
|
|
104
97
|
'container' => %i[run create exec update commit inspect diff start stop restart pause unpause top stats kill
|
|
105
98
|
rm].freeze,
|
|
@@ -114,10 +107,11 @@ module Squared
|
|
|
114
107
|
return unless dockerfile(file).exist?
|
|
115
108
|
|
|
116
109
|
@context = context
|
|
117
|
-
|
|
110
|
+
@tag = tag || tagname("#{@project}:#{@version || 'latest'}")
|
|
118
111
|
@mounts = mounts
|
|
119
112
|
@secrets = secrets
|
|
120
113
|
@registry = tagjoin registry, kwargs[:username]
|
|
114
|
+
@file = nil
|
|
121
115
|
initialize_ref Docker.ref
|
|
122
116
|
initialize_logger(**kwargs)
|
|
123
117
|
initialize_env(**kwargs)
|
|
@@ -130,11 +124,11 @@ module Squared
|
|
|
130
124
|
|
|
131
125
|
def populate(*, **)
|
|
132
126
|
super
|
|
133
|
-
return unless ref?(Docker.ref)
|
|
127
|
+
return unless ref?(Docker.ref)
|
|
134
128
|
|
|
135
129
|
namespace name do
|
|
136
130
|
Docker.subtasks do |action, flags|
|
|
137
|
-
next if
|
|
131
|
+
next if @pass.include?(action)
|
|
138
132
|
|
|
139
133
|
namespace action do
|
|
140
134
|
flags.each do |flag|
|
|
@@ -147,39 +141,26 @@ module Squared
|
|
|
147
141
|
param = param_guard(action, flag, args: args, key: flag)
|
|
148
142
|
buildx(:build, args.extras, "#{flag}": param)
|
|
149
143
|
end
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
break unless bake?
|
|
153
|
-
|
|
154
|
-
case flag
|
|
155
|
-
when :build
|
|
156
|
-
format_desc action, flag, 'opts*,target*,context?|:'
|
|
144
|
+
when :bake
|
|
145
|
+
format_desc action, flag, ':?,opts*,target*,context?'
|
|
157
146
|
task flag do |_, args|
|
|
158
147
|
args = args.to_a
|
|
159
148
|
if args.first == ':'
|
|
160
149
|
choice_command :bake
|
|
161
150
|
else
|
|
162
|
-
buildx
|
|
151
|
+
buildx flag, args
|
|
163
152
|
end
|
|
164
153
|
end
|
|
165
|
-
when :check
|
|
166
|
-
format_desc action, flag, 'target'
|
|
167
|
-
task flag, [:target] do |_, args|
|
|
168
|
-
target = param_guard(action, flag, args: args, key: :target)
|
|
169
|
-
buildx :bake, ['allow=fs.read=*', 'call=check', target]
|
|
170
|
-
end
|
|
171
154
|
end
|
|
172
155
|
when 'compose'
|
|
173
|
-
break unless compose?
|
|
174
|
-
|
|
175
156
|
case flag
|
|
176
|
-
when :build, :up
|
|
157
|
+
when :build, :up
|
|
177
158
|
format_desc action, flag, 'opts*,service*'
|
|
178
159
|
task flag do |_, args|
|
|
179
160
|
compose! flag, args.to_a
|
|
180
161
|
end
|
|
181
162
|
when :exec, :run
|
|
182
|
-
format_desc action, flag, "service,command#{flag == :exec ? '' : '?'}
|
|
163
|
+
format_desc action, flag, "service,command#{flag == :exec ? '' : '?'},args*,opts*"
|
|
183
164
|
task flag, [:service] do |_, args|
|
|
184
165
|
service = param_guard(action, flag, args: args, key: :service)
|
|
185
166
|
compose!(flag, args.extras, service: service)
|
|
@@ -207,7 +188,7 @@ module Squared
|
|
|
207
188
|
end
|
|
208
189
|
end
|
|
209
190
|
else
|
|
210
|
-
format_desc
|
|
191
|
+
format_desc(action, flag, 'opts*,id/name', after: flag == :update ? '+' : '*')
|
|
211
192
|
task flag do |_, args|
|
|
212
193
|
container flag, args.to_a
|
|
213
194
|
end
|
|
@@ -217,15 +198,14 @@ module Squared
|
|
|
217
198
|
when :push
|
|
218
199
|
format_desc action, flag, 'tag,registry/username?,opts*'
|
|
219
200
|
task flag, [:tag] do |_, args|
|
|
220
|
-
|
|
221
|
-
image(flag, args.extras, id:
|
|
201
|
+
id = param_guard(action, flag, args: args, key: :tag)
|
|
202
|
+
image(flag, args.extras, id: id)
|
|
222
203
|
end
|
|
223
204
|
else
|
|
224
205
|
format_desc(action, flag, case flag
|
|
225
206
|
when :rm, :save then 'id*,opts*'
|
|
226
207
|
when :tag then 'version?'
|
|
227
|
-
else 'opts*,args*'
|
|
228
|
-
end)
|
|
208
|
+
else 'opts*,args*' end)
|
|
229
209
|
task flag do |_, args|
|
|
230
210
|
args = args.to_a
|
|
231
211
|
if args.empty? && flag != :list
|
|
@@ -252,44 +232,43 @@ module Squared
|
|
|
252
232
|
end
|
|
253
233
|
|
|
254
234
|
def clean(*, sync: invoked_sync?('clean'), **)
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
image :rm
|
|
259
|
-
end
|
|
235
|
+
return super unless @clean.nil?
|
|
236
|
+
|
|
237
|
+
image(:rm, sync: sync)
|
|
260
238
|
end
|
|
261
239
|
|
|
262
240
|
def compose(opts, flags = nil, script: false, args: nil, from: :run, **)
|
|
263
241
|
return opts if script == false
|
|
264
242
|
|
|
243
|
+
ret = docker_session
|
|
265
244
|
if from == :run
|
|
266
|
-
|
|
267
|
-
|
|
245
|
+
case (n = filetype)
|
|
246
|
+
when 1, 2
|
|
247
|
+
ret << 'buildx' << 'bake'
|
|
268
248
|
append_file n
|
|
269
249
|
from = :bake
|
|
270
|
-
|
|
271
|
-
ret
|
|
250
|
+
when 3, 4
|
|
251
|
+
ret << 'compose' << 'build'
|
|
272
252
|
append_file n
|
|
273
253
|
from = :compose
|
|
274
254
|
else
|
|
275
|
-
ret
|
|
255
|
+
ret << 'build'
|
|
276
256
|
end
|
|
277
257
|
else
|
|
278
|
-
ret
|
|
258
|
+
ret << from
|
|
279
259
|
end
|
|
280
260
|
case opts
|
|
281
261
|
when String
|
|
282
262
|
ret << opts
|
|
283
263
|
when Hash
|
|
284
|
-
ret.merge(append_hash(opts,
|
|
264
|
+
ret.merge(append_hash(opts, build: true))
|
|
285
265
|
when Enumerable
|
|
286
266
|
ret.merge(opts.to_a)
|
|
287
267
|
end
|
|
268
|
+
|
|
288
269
|
[args, flags].each_with_index do |target, index|
|
|
289
|
-
if target
|
|
290
|
-
ret
|
|
291
|
-
elsif (target = append_any(target, target: []))
|
|
292
|
-
ret.merge(target.map { |arg| index == 0 ? fill_option(arg) : quote_option('build-arg', arg) })
|
|
270
|
+
if (data = append_any(target, target: []))
|
|
271
|
+
ret.merge(data.map { |arg| index == 0 ? fill_option(arg) : quote_option('build-arg', arg) })
|
|
293
272
|
end
|
|
294
273
|
end
|
|
295
274
|
case from
|
|
@@ -299,12 +278,12 @@ module Squared
|
|
|
299
278
|
ret << quote_option('secret', @secrets, double: true)
|
|
300
279
|
when Hash
|
|
301
280
|
append = lambda do |type|
|
|
302
|
-
|
|
281
|
+
as_a(@secrets[type]).each { |arg| ret << quote_option('secret', "type=#{type},#{arg}", double: true) }
|
|
303
282
|
end
|
|
304
283
|
append.call(:file)
|
|
305
284
|
append.call(:env)
|
|
306
285
|
else
|
|
307
|
-
|
|
286
|
+
as_a(@secrets).each { |arg| ret << quote_option('secret', arg) }
|
|
308
287
|
end
|
|
309
288
|
if (val = option('tag', ignore: false))
|
|
310
289
|
append_tag val
|
|
@@ -313,8 +292,8 @@ module Squared
|
|
|
313
292
|
end
|
|
314
293
|
append_context
|
|
315
294
|
when :bake, :compose
|
|
316
|
-
|
|
317
|
-
ret.merge(split_escape(
|
|
295
|
+
option(from == :bake ? 'target' : 'service', ignore: false) do |a|
|
|
296
|
+
ret.merge(split_escape(a).map! { |b| shell_escape(b) })
|
|
318
297
|
end
|
|
319
298
|
end
|
|
320
299
|
ret
|
|
@@ -327,20 +306,20 @@ module Squared
|
|
|
327
306
|
op.parse(OPT_DOCKER[:buildx][flag == :bake ? :bake : :build] + OPT_DOCKER[:buildx][:shared])
|
|
328
307
|
case flag
|
|
329
308
|
when :build, :context
|
|
330
|
-
append_tag(tag || option('tag', ignore: false) ||
|
|
309
|
+
append_tag(tag || option('tag', ignore: false) || @tag)
|
|
331
310
|
append_context context
|
|
332
311
|
when :bake
|
|
333
312
|
unless op.empty?
|
|
334
313
|
args = op.dup
|
|
335
|
-
op.
|
|
314
|
+
op.extras.clear
|
|
336
315
|
if Dir.exist?(args.last)
|
|
337
316
|
if projectpath?(val = args.pop)
|
|
338
317
|
context = val
|
|
339
318
|
else
|
|
340
|
-
op.
|
|
319
|
+
op.extras << val
|
|
341
320
|
end
|
|
342
321
|
end
|
|
343
|
-
op.append(args, escape: true
|
|
322
|
+
op.append(args, escape: true)
|
|
344
323
|
contextdir context if context
|
|
345
324
|
end
|
|
346
325
|
end
|
|
@@ -353,14 +332,15 @@ module Squared
|
|
|
353
332
|
op = OptionPartition.new(opts, OPT_DOCKER[:compose][:common], cmd, project: self)
|
|
354
333
|
append_file filetype unless op.arg?('f', 'file')
|
|
355
334
|
op << flag
|
|
356
|
-
op.parse(OPT_DOCKER[:compose]
|
|
335
|
+
op.parse(OPT_DOCKER[:compose][flag])
|
|
336
|
+
from = :"compose:#{flag}"
|
|
357
337
|
case flag
|
|
358
|
-
when :build, :up
|
|
359
|
-
op.append(escape: true
|
|
338
|
+
when :build, :up
|
|
339
|
+
op.append(escape: true)
|
|
360
340
|
when :exec, :run
|
|
361
|
-
append_command
|
|
341
|
+
append_command(flag, service, op.extras, from: from)
|
|
362
342
|
end
|
|
363
|
-
run(from:
|
|
343
|
+
run(from: from)
|
|
364
344
|
end
|
|
365
345
|
|
|
366
346
|
def container(flag, opts = [], id: nil)
|
|
@@ -374,54 +354,45 @@ module Squared
|
|
|
374
354
|
case flag
|
|
375
355
|
when :run, :create, :exec
|
|
376
356
|
if rc && !op.arg?('mount')
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
357
|
+
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('|')})")
|
|
361
|
+
as_a(@mounts).each do |val|
|
|
380
362
|
args = []
|
|
381
|
-
|
|
363
|
+
tmpfs = true
|
|
382
364
|
val.split(delim).each do |opt|
|
|
383
365
|
k, v, q = split_option opt
|
|
384
|
-
|
|
385
|
-
case v
|
|
386
|
-
when 'bind', 'volume', 'image', 'tmpfs'
|
|
387
|
-
type = v
|
|
388
|
-
else
|
|
389
|
-
raise_error("unknown type: #{v}", hint: flag)
|
|
390
|
-
end
|
|
391
|
-
elsif all.include?(k)
|
|
392
|
-
unless type
|
|
393
|
-
VAL_DOCKER[:run].each_pair do |key, a|
|
|
394
|
-
next unless a.include?(k)
|
|
366
|
+
next unless both.include?(k)
|
|
395
367
|
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
log_message(Logger::INFO, 'unrecognized option', subject: from, hint: k)
|
|
368
|
+
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'
|
|
411
382
|
end
|
|
383
|
+
args << "#{k}=#{q + v + q}"
|
|
412
384
|
end
|
|
413
|
-
|
|
414
|
-
cmd << "--mount type=#{type},#{args.join(',')}"
|
|
385
|
+
cmd << "--mount type=#{tmpfs ? 'tmpfs' : 'bind'},#{args.join(',')}"
|
|
415
386
|
end
|
|
416
387
|
end
|
|
417
|
-
append_command(flag, id || tagmain, op.extras)
|
|
388
|
+
append_command(flag, id || tagmain, op.extras, from: from)
|
|
418
389
|
when :update
|
|
419
|
-
raise_error('missing container', hint:
|
|
420
|
-
op.append(escape: true
|
|
390
|
+
raise_error('missing container', hint: from) if op.empty?
|
|
391
|
+
op.append(escape: true)
|
|
421
392
|
when :commit
|
|
422
393
|
latest = op.shift || tagmain
|
|
423
394
|
cmd << id << latest
|
|
424
|
-
raise_error("unknown args: #{op.join(', ')}", hint:
|
|
395
|
+
raise_error("unknown args: #{op.join(', ')}", hint: from) unless op.empty?
|
|
425
396
|
return unless confirm_command(cmd.to_s, title: from, target: id, as: latest)
|
|
426
397
|
|
|
427
398
|
registry = option('registry') || @registry
|
|
@@ -464,13 +435,13 @@ module Squared
|
|
|
464
435
|
when :rm
|
|
465
436
|
status = %w[created exited dead]
|
|
466
437
|
end
|
|
467
|
-
ps = docker_output('ps -a', *status.map { |s|
|
|
438
|
+
ps = docker_output('ps -a', *status.map { |s| "--filter=\"status=#{s}\"" })
|
|
468
439
|
list_image(flag, ps, no: no, hint: "status: #{status.join(', ')}", from: from) do |img|
|
|
469
440
|
run(cmd.temp(img), from: from)
|
|
470
441
|
end
|
|
471
442
|
return
|
|
472
443
|
else
|
|
473
|
-
op.append(escape: true
|
|
444
|
+
op.append(escape: true)
|
|
474
445
|
end
|
|
475
446
|
end
|
|
476
447
|
run(from: from)
|
|
@@ -521,17 +492,17 @@ module Squared
|
|
|
521
492
|
list_image(flag, docker_output('image ls -a'), from: from) do |val|
|
|
522
493
|
op << val
|
|
523
494
|
if flag == :tag
|
|
524
|
-
op << tagname("#{project}:#{op.first}")
|
|
495
|
+
op << tagname("#{@project}:#{op.extras.first}")
|
|
525
496
|
break
|
|
526
497
|
end
|
|
527
498
|
end
|
|
528
499
|
when :push
|
|
529
500
|
id ||= option('tag', ignore: false) || tagmain
|
|
530
501
|
registry ||= op.shift || option('registry') || @registry
|
|
531
|
-
raise_error(id ? "unknown args: #{op.join(', ')}" : 'no id/tag given', hint:
|
|
532
|
-
raise_error('username/registry not provided', hint:
|
|
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
|
|
533
504
|
registry.chomp!('/')
|
|
534
|
-
uri = shell_quote
|
|
505
|
+
uri = shell_quote "#{registry}/#{id}"
|
|
535
506
|
op << uri
|
|
536
507
|
img = docker_output 'image', 'tag', id, uri
|
|
537
508
|
return unless confirm_command(img.to_s, cmd.to_s, target: id, as: registry, title: from)
|
|
@@ -547,7 +518,7 @@ module Squared
|
|
|
547
518
|
|
|
548
519
|
def network(flag, opts = [], target: nil)
|
|
549
520
|
cmd, opts = docker_session('network', flag, opts: opts)
|
|
550
|
-
op = OptionPartition.new(opts, OPT_DOCKER[:network]
|
|
521
|
+
op = OptionPartition.new(opts, OPT_DOCKER[:network][flag], cmd, project: self)
|
|
551
522
|
op.clear
|
|
552
523
|
from = :"network:#{flag}"
|
|
553
524
|
list_image(flag, docker_output('ps -a'), from: from) do |img|
|
|
@@ -563,28 +534,17 @@ module Squared
|
|
|
563
534
|
super || dockerfile.exist?
|
|
564
535
|
end
|
|
565
536
|
|
|
566
|
-
def compose?(file = dockerfile)
|
|
567
|
-
return file == 3 || file == 4 if file.is_a?(Numeric)
|
|
568
|
-
|
|
569
|
-
COMPOSEFILE.include?(File.basename(file))
|
|
570
|
-
end
|
|
571
|
-
|
|
572
|
-
def bake?(file = dockerfile)
|
|
573
|
-
return file == 1 || file == 2 if file.is_a?(Numeric)
|
|
574
|
-
|
|
575
|
-
BAKEFILE.include?(File.basename(file))
|
|
576
|
-
end
|
|
577
|
-
|
|
578
537
|
def dockerfile(val = nil)
|
|
579
|
-
if val
|
|
538
|
+
if val == 'Dockerfile'
|
|
539
|
+
@file = false
|
|
540
|
+
elsif val
|
|
580
541
|
@file = if val.is_a?(Array)
|
|
581
542
|
val = val.select { |file| basepath(file).exist? }
|
|
582
543
|
val.size > 1 ? val : val.first
|
|
583
|
-
|
|
584
|
-
DIR_DOCKER.find { |file| basepath(file).exist? }
|
|
585
|
-
elsif val != 'Dockerfile'
|
|
586
|
-
val
|
|
544
|
+
else
|
|
545
|
+
val || DIR_DOCKER.find { |file| basepath(file).exist? }
|
|
587
546
|
end
|
|
547
|
+
@file ||= false
|
|
588
548
|
end
|
|
589
549
|
basepath((@file.is_a?(Array) ? @file.first : @file) || 'Dockerfile')
|
|
590
550
|
end
|
|
@@ -603,42 +563,35 @@ module Squared
|
|
|
603
563
|
session('docker', *cmd, main: false, options: false, **kwargs)
|
|
604
564
|
end
|
|
605
565
|
|
|
606
|
-
def append_command(flag, val, list, target: @session)
|
|
607
|
-
if
|
|
608
|
-
list << readline('Enter command [args]', force: true)
|
|
609
|
-
elsif (args = env('DOCKER_ARGS'))
|
|
566
|
+
def append_command(flag, val, list, target: @session, from: nil)
|
|
567
|
+
if (args = env('DOCKER_ARGS'))
|
|
610
568
|
list << args
|
|
611
569
|
end
|
|
612
570
|
case flag
|
|
613
571
|
when :run
|
|
614
572
|
unless session_arg?('name', target: target)
|
|
615
|
-
target << basic_option('name', dnsname("#{name}_%s" %
|
|
573
|
+
target << basic_option('name', dnsname("#{name}_%s" % if RUBY_VERSION >= '3.1'
|
|
574
|
+
require 'random/formatter'
|
|
575
|
+
Random.new.alphanumeric(6)
|
|
576
|
+
else
|
|
577
|
+
(0...6).map { rand(97..122).chr }.join
|
|
578
|
+
end))
|
|
616
579
|
end
|
|
617
580
|
when :exec
|
|
618
|
-
raise_error('no command args', hint:
|
|
581
|
+
raise_error('no command args', hint: from) if list.empty?
|
|
619
582
|
end
|
|
620
583
|
target << val << list.shift
|
|
621
584
|
target << list.join(' && ') unless list.empty?
|
|
622
585
|
end
|
|
623
586
|
|
|
624
|
-
def append_file(type, target: @session
|
|
625
|
-
return
|
|
587
|
+
def append_file(type, target: @session)
|
|
588
|
+
return unless type == 2 || type == 4 || @file.is_a?(Array)
|
|
626
589
|
|
|
627
|
-
|
|
628
|
-
case type
|
|
629
|
-
when 2, 4
|
|
630
|
-
return
|
|
631
|
-
when 3
|
|
632
|
-
return unless COMPOSEFILE.select { |val| basepath(val).exist? }.size > 1
|
|
633
|
-
end
|
|
634
|
-
end
|
|
635
|
-
files = Array(@file).map { |val| quote_option('file', basepath(val)) }
|
|
590
|
+
files = as_a(@file).map { |val| quote_option('file', path + val) }
|
|
636
591
|
if target.is_a?(Set)
|
|
637
|
-
|
|
638
|
-
target.clear
|
|
639
|
-
.merge(opts)
|
|
592
|
+
target.merge(files)
|
|
640
593
|
else
|
|
641
|
-
target.
|
|
594
|
+
target.concat(files)
|
|
642
595
|
end
|
|
643
596
|
end
|
|
644
597
|
|
|
@@ -650,28 +603,30 @@ module Squared
|
|
|
650
603
|
end
|
|
651
604
|
|
|
652
605
|
def append_tag(val, target: @session)
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
606
|
+
case val
|
|
607
|
+
when String
|
|
608
|
+
val.split(',')
|
|
609
|
+
when Array
|
|
610
|
+
val
|
|
611
|
+
else
|
|
612
|
+
[]
|
|
613
|
+
end.yield_self do |list|
|
|
614
|
+
ver = option('version', target: target, ignore: false)
|
|
615
|
+
list.each do |s|
|
|
616
|
+
s = "#{s}:#{ver}" if ver && (!s.include?(':') || s.delete_suffix!(':latest'))
|
|
617
|
+
target << basic_option('tag', tagname(s))
|
|
618
|
+
end
|
|
619
|
+
target
|
|
665
620
|
end
|
|
666
621
|
end
|
|
667
622
|
|
|
668
|
-
def list_image(flag, cmd, hint: nil,
|
|
669
|
-
pwd_set
|
|
623
|
+
def list_image(flag, cmd, hint: nil, from: nil, no: true)
|
|
624
|
+
pwd_set do
|
|
670
625
|
found = false
|
|
671
626
|
index = 0
|
|
672
627
|
all = option('all', prefix: 'docker')
|
|
673
628
|
y = from == :'image:rm' && option('y', prefix: 'docker')
|
|
674
|
-
pat =
|
|
629
|
+
pat = /^(?:#{dnsname(name)}|#{tagname(project)}|#{tagmain.split(':', 2).first})(?:[_.,:-]|$)/
|
|
675
630
|
IO.popen(session_done(cmd << '--format=json')).each do |line|
|
|
676
631
|
data = JSON.parse(line)
|
|
677
632
|
id = data['ID']
|
|
@@ -708,7 +663,7 @@ module Squared
|
|
|
708
663
|
cols.each do |key|
|
|
709
664
|
next if (key == 'Tag' && !dd) || (key == 'Size' && data[key] == '0B')
|
|
710
665
|
|
|
711
|
-
puts "#{g + f} #{key}: #{
|
|
666
|
+
puts "#{g + f} #{key}: #{as_a(data[key]).join(', ')}" unless data[key].to_s.empty?
|
|
712
667
|
end
|
|
713
668
|
w = 9 + flag.to_s.size + 4 + ee.size
|
|
714
669
|
puts g + sub_style(ARG[:BORDER][6] + (ARG[:BORDER][1] * w), styles: theme[:inline])
|
|
@@ -720,10 +675,14 @@ module Squared
|
|
|
720
675
|
end
|
|
721
676
|
yield id
|
|
722
677
|
end
|
|
723
|
-
puts log_message(Logger::INFO, 'none detected', subject: name, hint: hint
|
|
678
|
+
puts log_message(Logger::INFO, 'none detected', subject: "#{name}:#{from}", hint: hint) if found || y
|
|
724
679
|
end
|
|
725
680
|
rescue StandardError => e
|
|
726
|
-
|
|
681
|
+
log.error e
|
|
682
|
+
ret = on(:error, from, e)
|
|
683
|
+
raise if exception && ret != true
|
|
684
|
+
|
|
685
|
+
warn log_message(Logger::WARN, e, pass: true) if warning?
|
|
727
686
|
end
|
|
728
687
|
|
|
729
688
|
def confirm_command(*args, title: nil, target: nil, as: nil)
|
|
@@ -780,7 +739,7 @@ module Squared
|
|
|
780
739
|
cmd = docker_output ctx
|
|
781
740
|
case flag
|
|
782
741
|
when :tag
|
|
783
|
-
args = tagjoin @registry, tag
|
|
742
|
+
args = tagjoin @registry, @tag
|
|
784
743
|
when :save
|
|
785
744
|
opts = "#{opts}.tar" unless opts.end_with?('.tar')
|
|
786
745
|
cmd << quote_option('output', File.expand_path(opts))
|
|
@@ -791,9 +750,13 @@ module Squared
|
|
|
791
750
|
else
|
|
792
751
|
cmd << opts << '--'
|
|
793
752
|
end
|
|
794
|
-
cmd.merge(
|
|
753
|
+
cmd.merge(if out.is_a?(Array)
|
|
754
|
+
out.map! { |val| parse.call(val) }
|
|
755
|
+
else
|
|
756
|
+
[parse.call(out)]
|
|
757
|
+
end)
|
|
795
758
|
cmd << args
|
|
796
|
-
print_success if success?(run(cmd)) && ctx.
|
|
759
|
+
print_success if success?(run(cmd)) && ctx.start_with?(/(?:network|tag|save)/)
|
|
797
760
|
end
|
|
798
761
|
end
|
|
799
762
|
|
|
@@ -803,7 +766,7 @@ module Squared
|
|
|
803
766
|
bake?(val) ? 1 : 2
|
|
804
767
|
when '.yml', '.yaml'
|
|
805
768
|
if compose?(val)
|
|
806
|
-
|
|
769
|
+
path.children.any? { |file| bake?(file) } ? 1 : 3
|
|
807
770
|
else
|
|
808
771
|
4
|
|
809
772
|
end
|
|
@@ -813,7 +776,7 @@ module Squared
|
|
|
813
776
|
end
|
|
814
777
|
|
|
815
778
|
def contextdir(val = nil)
|
|
816
|
-
val && projectpath?(val) ? shell_quote(
|
|
779
|
+
val && projectpath?(val) ? shell_quote(path + val) : '.'
|
|
817
780
|
end
|
|
818
781
|
|
|
819
782
|
def tagjoin(*args, char: '/')
|
|
@@ -823,9 +786,10 @@ module Squared
|
|
|
823
786
|
|
|
824
787
|
def tagname(val)
|
|
825
788
|
val = val.split(':').map! { |s| charname(s.sub(/^\W+/, '')) }
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
789
|
+
val.join(':').yield_self do |s|
|
|
790
|
+
s = val.first if val.size > 1 && s.size > 128
|
|
791
|
+
s[0..127]
|
|
792
|
+
end
|
|
829
793
|
end
|
|
830
794
|
|
|
831
795
|
def dnsname(val)
|
|
@@ -839,6 +803,14 @@ module Squared
|
|
|
839
803
|
def tagmain
|
|
840
804
|
tag.is_a?(Array) ? tag.first : tag
|
|
841
805
|
end
|
|
806
|
+
|
|
807
|
+
def compose?(file = dockerfile)
|
|
808
|
+
COMPOSEFILE.include?(File.basename(file))
|
|
809
|
+
end
|
|
810
|
+
|
|
811
|
+
def bake?(file = dockerfile)
|
|
812
|
+
BAKEFILE.include?(File.basename(file))
|
|
813
|
+
end
|
|
842
814
|
end
|
|
843
815
|
|
|
844
816
|
Application.implement Docker
|