squared 0.4.38 → 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 -565
- 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 +51 -78
- data/lib/squared/common/system.rb +34 -38
- 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 +84 -126
- data/lib/squared/workspace/project/base.rb +438 -595
- data/lib/squared/workspace/project/docker.rb +196 -214
- data/lib/squared/workspace/project/git.rb +376 -521
- data/lib/squared/workspace/project/node.rb +196 -316
- data/lib/squared/workspace/project/python.rb +126 -357
- data/lib/squared/workspace/project/ruby.rb +260 -343
- data/lib/squared/workspace/project/support/class.rb +93 -314
- data/lib/squared/workspace/project.rb +0 -10
- data/lib/squared/workspace/repo.rb +59 -100
- 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
|
|
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,11 +306,22 @@ 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
|
-
op.
|
|
334
|
-
|
|
312
|
+
unless op.empty?
|
|
313
|
+
args = op.dup
|
|
314
|
+
op.extras.clear
|
|
315
|
+
if Dir.exist?(args.last)
|
|
316
|
+
if projectpath?(val = args.pop)
|
|
317
|
+
context = val
|
|
318
|
+
else
|
|
319
|
+
op.extras << val
|
|
320
|
+
end
|
|
321
|
+
end
|
|
322
|
+
op.append(args, escape: true)
|
|
323
|
+
contextdir context if context
|
|
324
|
+
end
|
|
335
325
|
end
|
|
336
326
|
op.clear(pass: false)
|
|
337
327
|
run(from: :"buildx:#{flag}")
|
|
@@ -342,16 +332,16 @@ module Squared
|
|
|
342
332
|
op = OptionPartition.new(opts, OPT_DOCKER[:compose][:common], cmd, project: self)
|
|
343
333
|
append_file filetype unless op.arg?('f', 'file')
|
|
344
334
|
op << flag
|
|
345
|
-
op.parse(OPT_DOCKER[:compose]
|
|
335
|
+
op.parse(OPT_DOCKER[:compose][flag])
|
|
336
|
+
from = :"compose:#{flag}"
|
|
346
337
|
case flag
|
|
347
|
-
when :build, :up
|
|
348
|
-
op.append(escape: true
|
|
338
|
+
when :build, :up
|
|
339
|
+
op.append(escape: true)
|
|
349
340
|
when :exec, :run
|
|
350
|
-
append_command
|
|
341
|
+
append_command(flag, service, op.extras, from: from)
|
|
351
342
|
end
|
|
352
|
-
run(from:
|
|
343
|
+
run(from: from)
|
|
353
344
|
end
|
|
354
|
-
alias compose_ compose!
|
|
355
345
|
|
|
356
346
|
def container(flag, opts = [], id: nil)
|
|
357
347
|
cmd, opts = docker_session('container', flag, opts: opts)
|
|
@@ -364,54 +354,45 @@ module Squared
|
|
|
364
354
|
case flag
|
|
365
355
|
when :run, :create, :exec
|
|
366
356
|
if rc && !op.arg?('mount')
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
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|
|
|
370
362
|
args = []
|
|
371
|
-
|
|
363
|
+
tmpfs = true
|
|
372
364
|
val.split(delim).each do |opt|
|
|
373
365
|
k, v, q = split_option opt
|
|
374
|
-
|
|
375
|
-
case v
|
|
376
|
-
when 'bind', 'volume', 'image', 'tmpfs'
|
|
377
|
-
type = v
|
|
378
|
-
else
|
|
379
|
-
raise_error("unknown type: #{v}", hint: flag)
|
|
380
|
-
end
|
|
381
|
-
elsif all.include?(k)
|
|
382
|
-
unless type
|
|
383
|
-
VAL_DOCKER[:run].each_pair do |key, a|
|
|
384
|
-
next unless a.include?(k)
|
|
366
|
+
next unless both.include?(k)
|
|
385
367
|
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
when 'readonly', 'ro'
|
|
392
|
-
args << k
|
|
393
|
-
next
|
|
394
|
-
when 'source', 'src', 'destination', 'dst', 'target', 'volume-subpath', 'image-path'
|
|
395
|
-
v = basepath v
|
|
396
|
-
v = shell_quote(v, option: false, force: false) if q == ''
|
|
397
|
-
end
|
|
398
|
-
args << "#{k}=#{q + v + q}"
|
|
399
|
-
elsif verbose
|
|
400
|
-
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
|
|
401
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
|
+
end
|
|
383
|
+
args << "#{k}=#{q + v + q}"
|
|
402
384
|
end
|
|
403
|
-
|
|
404
|
-
cmd << "--mount type=#{type},#{args.join(',')}"
|
|
385
|
+
cmd << "--mount type=#{tmpfs ? 'tmpfs' : 'bind'},#{args.join(',')}"
|
|
405
386
|
end
|
|
406
387
|
end
|
|
407
|
-
append_command(flag, id || tagmain, op.extras)
|
|
388
|
+
append_command(flag, id || tagmain, op.extras, from: from)
|
|
408
389
|
when :update
|
|
409
|
-
raise_error('missing container', hint:
|
|
410
|
-
op.append(escape: true
|
|
390
|
+
raise_error('missing container', hint: from) if op.empty?
|
|
391
|
+
op.append(escape: true)
|
|
411
392
|
when :commit
|
|
412
393
|
latest = op.shift || tagmain
|
|
413
394
|
cmd << id << latest
|
|
414
|
-
raise_error("unknown args: #{op.join(', ')}", hint:
|
|
395
|
+
raise_error("unknown args: #{op.join(', ')}", hint: from) unless op.empty?
|
|
415
396
|
return unless confirm_command(cmd.to_s, title: from, target: id, as: latest)
|
|
416
397
|
|
|
417
398
|
registry = option('registry') || @registry
|
|
@@ -454,13 +435,13 @@ module Squared
|
|
|
454
435
|
when :rm
|
|
455
436
|
status = %w[created exited dead]
|
|
456
437
|
end
|
|
457
|
-
ps = docker_output('ps -a', *status.map { |s|
|
|
438
|
+
ps = docker_output('ps -a', *status.map { |s| "--filter=\"status=#{s}\"" })
|
|
458
439
|
list_image(flag, ps, no: no, hint: "status: #{status.join(', ')}", from: from) do |img|
|
|
459
440
|
run(cmd.temp(img), from: from)
|
|
460
441
|
end
|
|
461
442
|
return
|
|
462
443
|
else
|
|
463
|
-
op.append(escape: true
|
|
444
|
+
op.append(escape: true)
|
|
464
445
|
end
|
|
465
446
|
end
|
|
466
447
|
run(from: from)
|
|
@@ -511,17 +492,17 @@ module Squared
|
|
|
511
492
|
list_image(flag, docker_output('image ls -a'), from: from) do |val|
|
|
512
493
|
op << val
|
|
513
494
|
if flag == :tag
|
|
514
|
-
op << tagname("#{project}:#{op.first}")
|
|
495
|
+
op << tagname("#{@project}:#{op.extras.first}")
|
|
515
496
|
break
|
|
516
497
|
end
|
|
517
498
|
end
|
|
518
499
|
when :push
|
|
519
500
|
id ||= option('tag', ignore: false) || tagmain
|
|
520
501
|
registry ||= op.shift || option('registry') || @registry
|
|
521
|
-
raise_error(id ? "unknown args: #{op.join(', ')}" : 'no id/tag given', hint:
|
|
522
|
-
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
|
|
523
504
|
registry.chomp!('/')
|
|
524
|
-
uri = shell_quote
|
|
505
|
+
uri = shell_quote "#{registry}/#{id}"
|
|
525
506
|
op << uri
|
|
526
507
|
img = docker_output 'image', 'tag', id, uri
|
|
527
508
|
return unless confirm_command(img.to_s, cmd.to_s, target: id, as: registry, title: from)
|
|
@@ -537,7 +518,7 @@ module Squared
|
|
|
537
518
|
|
|
538
519
|
def network(flag, opts = [], target: nil)
|
|
539
520
|
cmd, opts = docker_session('network', flag, opts: opts)
|
|
540
|
-
op = OptionPartition.new(opts, OPT_DOCKER[:network]
|
|
521
|
+
op = OptionPartition.new(opts, OPT_DOCKER[:network][flag], cmd, project: self)
|
|
541
522
|
op.clear
|
|
542
523
|
from = :"network:#{flag}"
|
|
543
524
|
list_image(flag, docker_output('ps -a'), from: from) do |img|
|
|
@@ -553,28 +534,17 @@ module Squared
|
|
|
553
534
|
super || dockerfile.exist?
|
|
554
535
|
end
|
|
555
536
|
|
|
556
|
-
def compose?(file = dockerfile)
|
|
557
|
-
return file == 3 || file == 4 if file.is_a?(Numeric)
|
|
558
|
-
|
|
559
|
-
COMPOSEFILE.include?(File.basename(file))
|
|
560
|
-
end
|
|
561
|
-
|
|
562
|
-
def bake?(file = dockerfile)
|
|
563
|
-
return file == 1 || file == 2 if file.is_a?(Numeric)
|
|
564
|
-
|
|
565
|
-
BAKEFILE.include?(File.basename(file))
|
|
566
|
-
end
|
|
567
|
-
|
|
568
537
|
def dockerfile(val = nil)
|
|
569
|
-
if val
|
|
538
|
+
if val == 'Dockerfile'
|
|
539
|
+
@file = false
|
|
540
|
+
elsif val
|
|
570
541
|
@file = if val.is_a?(Array)
|
|
571
542
|
val = val.select { |file| basepath(file).exist? }
|
|
572
543
|
val.size > 1 ? val : val.first
|
|
573
|
-
|
|
574
|
-
DIR_DOCKER.find { |file| basepath(file).exist? }
|
|
575
|
-
elsif val != 'Dockerfile'
|
|
576
|
-
val
|
|
544
|
+
else
|
|
545
|
+
val || DIR_DOCKER.find { |file| basepath(file).exist? }
|
|
577
546
|
end
|
|
547
|
+
@file ||= false
|
|
578
548
|
end
|
|
579
549
|
basepath((@file.is_a?(Array) ? @file.first : @file) || 'Dockerfile')
|
|
580
550
|
end
|
|
@@ -593,42 +563,35 @@ module Squared
|
|
|
593
563
|
session('docker', *cmd, main: false, options: false, **kwargs)
|
|
594
564
|
end
|
|
595
565
|
|
|
596
|
-
def append_command(flag, val, list, target: @session)
|
|
597
|
-
if
|
|
598
|
-
list << readline('Enter command [args]', force: true)
|
|
599
|
-
elsif (args = env('DOCKER_ARGS'))
|
|
566
|
+
def append_command(flag, val, list, target: @session, from: nil)
|
|
567
|
+
if (args = env('DOCKER_ARGS'))
|
|
600
568
|
list << args
|
|
601
569
|
end
|
|
602
570
|
case flag
|
|
603
571
|
when :run
|
|
604
572
|
unless session_arg?('name', target: target)
|
|
605
|
-
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))
|
|
606
579
|
end
|
|
607
580
|
when :exec
|
|
608
|
-
raise_error('no command args', hint:
|
|
581
|
+
raise_error('no command args', hint: from) if list.empty?
|
|
609
582
|
end
|
|
610
583
|
target << val << list.shift
|
|
611
584
|
target << list.join(' && ') unless list.empty?
|
|
612
585
|
end
|
|
613
586
|
|
|
614
|
-
def append_file(type, target: @session
|
|
615
|
-
return
|
|
587
|
+
def append_file(type, target: @session)
|
|
588
|
+
return unless type == 2 || type == 4 || @file.is_a?(Array)
|
|
616
589
|
|
|
617
|
-
|
|
618
|
-
case type
|
|
619
|
-
when 2, 4
|
|
620
|
-
return
|
|
621
|
-
when 3
|
|
622
|
-
return unless COMPOSEFILE.select { |val| basepath(val).exist? }.size > 1
|
|
623
|
-
end
|
|
624
|
-
end
|
|
625
|
-
files = Array(@file).map { |val| quote_option('file', basepath(val)) }
|
|
590
|
+
files = as_a(@file).map { |val| quote_option('file', path + val) }
|
|
626
591
|
if target.is_a?(Set)
|
|
627
|
-
|
|
628
|
-
target.clear
|
|
629
|
-
.merge(opts)
|
|
592
|
+
target.merge(files)
|
|
630
593
|
else
|
|
631
|
-
target.
|
|
594
|
+
target.concat(files)
|
|
632
595
|
end
|
|
633
596
|
end
|
|
634
597
|
|
|
@@ -640,28 +603,30 @@ module Squared
|
|
|
640
603
|
end
|
|
641
604
|
|
|
642
605
|
def append_tag(val, target: @session)
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
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
|
|
655
620
|
end
|
|
656
621
|
end
|
|
657
622
|
|
|
658
|
-
def list_image(flag, cmd, hint: nil,
|
|
659
|
-
pwd_set
|
|
623
|
+
def list_image(flag, cmd, hint: nil, from: nil, no: true)
|
|
624
|
+
pwd_set do
|
|
660
625
|
found = false
|
|
661
626
|
index = 0
|
|
662
627
|
all = option('all', prefix: 'docker')
|
|
663
628
|
y = from == :'image:rm' && option('y', prefix: 'docker')
|
|
664
|
-
pat =
|
|
629
|
+
pat = /^(?:#{dnsname(name)}|#{tagname(project)}|#{tagmain.split(':', 2).first})(?:[_.,:-]|$)/
|
|
665
630
|
IO.popen(session_done(cmd << '--format=json')).each do |line|
|
|
666
631
|
data = JSON.parse(line)
|
|
667
632
|
id = data['ID']
|
|
@@ -698,7 +663,7 @@ module Squared
|
|
|
698
663
|
cols.each do |key|
|
|
699
664
|
next if (key == 'Tag' && !dd) || (key == 'Size' && data[key] == '0B')
|
|
700
665
|
|
|
701
|
-
puts "#{g + f} #{key}: #{
|
|
666
|
+
puts "#{g + f} #{key}: #{as_a(data[key]).join(', ')}" unless data[key].to_s.empty?
|
|
702
667
|
end
|
|
703
668
|
w = 9 + flag.to_s.size + 4 + ee.size
|
|
704
669
|
puts g + sub_style(ARG[:BORDER][6] + (ARG[:BORDER][1] * w), styles: theme[:inline])
|
|
@@ -710,10 +675,14 @@ module Squared
|
|
|
710
675
|
end
|
|
711
676
|
yield id
|
|
712
677
|
end
|
|
713
|
-
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
|
|
714
679
|
end
|
|
715
680
|
rescue StandardError => e
|
|
716
|
-
|
|
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?
|
|
717
686
|
end
|
|
718
687
|
|
|
719
688
|
def confirm_command(*args, title: nil, target: nil, as: nil)
|
|
@@ -770,7 +739,7 @@ module Squared
|
|
|
770
739
|
cmd = docker_output ctx
|
|
771
740
|
case flag
|
|
772
741
|
when :tag
|
|
773
|
-
args = tagjoin @registry, tag
|
|
742
|
+
args = tagjoin @registry, @tag
|
|
774
743
|
when :save
|
|
775
744
|
opts = "#{opts}.tar" unless opts.end_with?('.tar')
|
|
776
745
|
cmd << quote_option('output', File.expand_path(opts))
|
|
@@ -781,9 +750,13 @@ module Squared
|
|
|
781
750
|
else
|
|
782
751
|
cmd << opts << '--'
|
|
783
752
|
end
|
|
784
|
-
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)
|
|
785
758
|
cmd << args
|
|
786
|
-
print_success if success?(run(cmd)) && ctx.
|
|
759
|
+
print_success if success?(run(cmd)) && ctx.start_with?(/(?:network|tag|save)/)
|
|
787
760
|
end
|
|
788
761
|
end
|
|
789
762
|
|
|
@@ -793,7 +766,7 @@ module Squared
|
|
|
793
766
|
bake?(val) ? 1 : 2
|
|
794
767
|
when '.yml', '.yaml'
|
|
795
768
|
if compose?(val)
|
|
796
|
-
|
|
769
|
+
path.children.any? { |file| bake?(file) } ? 1 : 3
|
|
797
770
|
else
|
|
798
771
|
4
|
|
799
772
|
end
|
|
@@ -803,7 +776,7 @@ module Squared
|
|
|
803
776
|
end
|
|
804
777
|
|
|
805
778
|
def contextdir(val = nil)
|
|
806
|
-
val && projectpath?(val) ? shell_quote(
|
|
779
|
+
val && projectpath?(val) ? shell_quote(path + val) : '.'
|
|
807
780
|
end
|
|
808
781
|
|
|
809
782
|
def tagjoin(*args, char: '/')
|
|
@@ -813,9 +786,10 @@ module Squared
|
|
|
813
786
|
|
|
814
787
|
def tagname(val)
|
|
815
788
|
val = val.split(':').map! { |s| charname(s.sub(/^\W+/, '')) }
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
789
|
+
val.join(':').yield_self do |s|
|
|
790
|
+
s = val.first if val.size > 1 && s.size > 128
|
|
791
|
+
s[0..127]
|
|
792
|
+
end
|
|
819
793
|
end
|
|
820
794
|
|
|
821
795
|
def dnsname(val)
|
|
@@ -829,6 +803,14 @@ module Squared
|
|
|
829
803
|
def tagmain
|
|
830
804
|
tag.is_a?(Array) ? tag.first : tag
|
|
831
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
|
|
832
814
|
end
|
|
833
815
|
|
|
834
816
|
Application.implement Docker
|