squared 0.4.30 → 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 +62 -429
- data/README.md +1279 -650
- data/README.ruby.md +722 -0
- data/lib/squared/common/base.rb +8 -9
- data/lib/squared/common/format.rb +24 -31
- data/lib/squared/common/prompt.rb +46 -47
- data/lib/squared/common/shell.rb +50 -64
- 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 +26 -25
- data/lib/squared/version.rb +1 -1
- data/lib/squared/workspace/application.rb +74 -95
- data/lib/squared/workspace/project/base.rb +408 -536
- data/lib/squared/workspace/project/docker.rb +177 -206
- data/lib/squared/workspace/project/git.rb +361 -503
- data/lib/squared/workspace/project/node.rb +188 -296
- data/lib/squared/workspace/project/python.rb +88 -306
- data/lib/squared/workspace/project/ruby.rb +232 -306
- data/lib/squared/workspace/project/support/class.rb +93 -300
- data/lib/squared/workspace/project.rb +0 -10
- data/lib/squared/workspace/repo.rb +55 -96
- data/lib/squared/workspace/series.rb +34 -32
- data/lib/squared/workspace/support/data.rb +3 -2
- data/lib/squared/workspace/support.rb +0 -1
- data/lib/squared/workspace.rb +1 -1
- data/squared.gemspec +5 -5
- metadata +7 -8
- data/lib/squared/common/class.rb +0 -175
- 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
|
-
log-driver=b log-opt=q mac-address=
|
|
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
|
|
47
44
|
memory-swappiness=n mount=qq name=b network=b network-alias=b oom-score-adj=b pid=b pids-limit=n
|
|
48
|
-
platform=b p|publish=
|
|
45
|
+
platform=b p|publish=e pull=b restart=b runtime=b security-opt=q shm-size=b stop-signal=b
|
|
49
46
|
stop-timeout=i storage-opt=q sysctl=q tmpfs=q ulimit=q u|user=b userns=b uts=b v|volume=q
|
|
50
47
|
volume-driver=b volumes-from=b w|workdir=q].freeze,
|
|
51
|
-
run: %w[d|detach detach-keys=q
|
|
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
|
|
63
|
+
list: %w[a|all digests no-trunc f|filter=q format=q].freeze,
|
|
67
64
|
push: %w[a|all-tags disable-content-trust=b? platform=b q|quiet].freeze,
|
|
68
|
-
rm: %w[f|force no-prune
|
|
65
|
+
rm: %w[f|force no-prune].freeze,
|
|
69
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,11 +232,9 @@ module Squared
|
|
|
252
232
|
end
|
|
253
233
|
|
|
254
234
|
def clean(*, sync: invoked_sync?('clean'), **)
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
image(:rm, sync: sync)
|
|
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, **)
|
|
@@ -264,12 +242,13 @@ module Squared
|
|
|
264
242
|
|
|
265
243
|
ret = docker_session
|
|
266
244
|
if from == :run
|
|
267
|
-
|
|
268
|
-
|
|
245
|
+
case (n = filetype)
|
|
246
|
+
when 1, 2
|
|
247
|
+
ret << 'buildx' << 'bake'
|
|
269
248
|
append_file n
|
|
270
249
|
from = :bake
|
|
271
|
-
|
|
272
|
-
ret << 'compose build'
|
|
250
|
+
when 3, 4
|
|
251
|
+
ret << 'compose' << 'build'
|
|
273
252
|
append_file n
|
|
274
253
|
from = :compose
|
|
275
254
|
else
|
|
@@ -282,15 +261,14 @@ module Squared
|
|
|
282
261
|
when String
|
|
283
262
|
ret << opts
|
|
284
263
|
when Hash
|
|
285
|
-
ret.merge(append_hash(opts,
|
|
264
|
+
ret.merge(append_hash(opts, build: true))
|
|
286
265
|
when Enumerable
|
|
287
266
|
ret.merge(opts.to_a)
|
|
288
267
|
end
|
|
268
|
+
|
|
289
269
|
[args, flags].each_with_index do |target, index|
|
|
290
|
-
if target
|
|
291
|
-
ret
|
|
292
|
-
elsif (target = append_any(target, target: []))
|
|
293
|
-
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) })
|
|
294
272
|
end
|
|
295
273
|
end
|
|
296
274
|
case from
|
|
@@ -300,12 +278,12 @@ module Squared
|
|
|
300
278
|
ret << quote_option('secret', @secrets, double: true)
|
|
301
279
|
when Hash
|
|
302
280
|
append = lambda do |type|
|
|
303
|
-
|
|
281
|
+
as_a(@secrets[type]).each { |arg| ret << quote_option('secret', "type=#{type},#{arg}", double: true) }
|
|
304
282
|
end
|
|
305
283
|
append.call(:file)
|
|
306
284
|
append.call(:env)
|
|
307
285
|
else
|
|
308
|
-
|
|
286
|
+
as_a(@secrets).each { |arg| ret << quote_option('secret', arg) }
|
|
309
287
|
end
|
|
310
288
|
if (val = option('tag', ignore: false))
|
|
311
289
|
append_tag val
|
|
@@ -314,8 +292,8 @@ module Squared
|
|
|
314
292
|
end
|
|
315
293
|
append_context
|
|
316
294
|
when :bake, :compose
|
|
317
|
-
|
|
318
|
-
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) })
|
|
319
297
|
end
|
|
320
298
|
end
|
|
321
299
|
ret
|
|
@@ -328,20 +306,20 @@ module Squared
|
|
|
328
306
|
op.parse(OPT_DOCKER[:buildx][flag == :bake ? :bake : :build] + OPT_DOCKER[:buildx][:shared])
|
|
329
307
|
case flag
|
|
330
308
|
when :build, :context
|
|
331
|
-
append_tag(tag || option('tag', ignore: false) ||
|
|
309
|
+
append_tag(tag || option('tag', ignore: false) || @tag)
|
|
332
310
|
append_context context
|
|
333
311
|
when :bake
|
|
334
312
|
unless op.empty?
|
|
335
313
|
args = op.dup
|
|
336
|
-
op.
|
|
314
|
+
op.extras.clear
|
|
337
315
|
if Dir.exist?(args.last)
|
|
338
316
|
if projectpath?(val = args.pop)
|
|
339
317
|
context = val
|
|
340
318
|
else
|
|
341
|
-
op.
|
|
319
|
+
op.extras << val
|
|
342
320
|
end
|
|
343
321
|
end
|
|
344
|
-
op.append(args, escape: true
|
|
322
|
+
op.append(args, escape: true)
|
|
345
323
|
contextdir context if context
|
|
346
324
|
end
|
|
347
325
|
end
|
|
@@ -354,14 +332,15 @@ module Squared
|
|
|
354
332
|
op = OptionPartition.new(opts, OPT_DOCKER[:compose][:common], cmd, project: self)
|
|
355
333
|
append_file filetype unless op.arg?('f', 'file')
|
|
356
334
|
op << flag
|
|
357
|
-
op.parse(OPT_DOCKER[:compose]
|
|
335
|
+
op.parse(OPT_DOCKER[:compose][flag])
|
|
336
|
+
from = :"compose:#{flag}"
|
|
358
337
|
case flag
|
|
359
|
-
when :build, :up
|
|
360
|
-
op.append(escape: true
|
|
338
|
+
when :build, :up
|
|
339
|
+
op.append(escape: true)
|
|
361
340
|
when :exec, :run
|
|
362
|
-
append_command
|
|
341
|
+
append_command(flag, service, op.extras, from: from)
|
|
363
342
|
end
|
|
364
|
-
run(from:
|
|
343
|
+
run(from: from)
|
|
365
344
|
end
|
|
366
345
|
|
|
367
346
|
def container(flag, opts = [], id: nil)
|
|
@@ -375,54 +354,45 @@ module Squared
|
|
|
375
354
|
case flag
|
|
376
355
|
when :run, :create, :exec
|
|
377
356
|
if rc && !op.arg?('mount')
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
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|
|
|
381
362
|
args = []
|
|
382
|
-
|
|
363
|
+
tmpfs = true
|
|
383
364
|
val.split(delim).each do |opt|
|
|
384
365
|
k, v, q = split_option opt
|
|
385
|
-
|
|
386
|
-
case v
|
|
387
|
-
when 'bind', 'volume', 'image', 'tmpfs'
|
|
388
|
-
type = v
|
|
389
|
-
else
|
|
390
|
-
raise_error("unknown type: #{v}", hint: flag)
|
|
391
|
-
end
|
|
392
|
-
elsif all.include?(k)
|
|
393
|
-
unless type
|
|
394
|
-
VAL_DOCKER[:run].each_pair do |key, a|
|
|
395
|
-
next unless a.include?(k)
|
|
366
|
+
next unless both.include?(k)
|
|
396
367
|
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
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'
|
|
412
382
|
end
|
|
383
|
+
args << "#{k}=#{q + v + q}"
|
|
413
384
|
end
|
|
414
|
-
|
|
415
|
-
cmd << "--mount type=#{type},#{args.join(',')}"
|
|
385
|
+
cmd << "--mount type=#{tmpfs ? 'tmpfs' : 'bind'},#{args.join(',')}"
|
|
416
386
|
end
|
|
417
387
|
end
|
|
418
|
-
append_command(flag, id || tagmain, op.extras)
|
|
388
|
+
append_command(flag, id || tagmain, op.extras, from: from)
|
|
419
389
|
when :update
|
|
420
|
-
raise_error('missing container', hint:
|
|
421
|
-
op.append(escape: true
|
|
390
|
+
raise_error('missing container', hint: from) if op.empty?
|
|
391
|
+
op.append(escape: true)
|
|
422
392
|
when :commit
|
|
423
393
|
latest = op.shift || tagmain
|
|
424
394
|
cmd << id << latest
|
|
425
|
-
raise_error("unknown args: #{op.join(', ')}", hint:
|
|
395
|
+
raise_error("unknown args: #{op.join(', ')}", hint: from) unless op.empty?
|
|
426
396
|
return unless confirm_command(cmd.to_s, title: from, target: id, as: latest)
|
|
427
397
|
|
|
428
398
|
registry = option('registry') || @registry
|
|
@@ -465,13 +435,13 @@ module Squared
|
|
|
465
435
|
when :rm
|
|
466
436
|
status = %w[created exited dead]
|
|
467
437
|
end
|
|
468
|
-
ps = docker_output('ps -a', *status.map { |s|
|
|
438
|
+
ps = docker_output('ps -a', *status.map { |s| "--filter=\"status=#{s}\"" })
|
|
469
439
|
list_image(flag, ps, no: no, hint: "status: #{status.join(', ')}", from: from) do |img|
|
|
470
440
|
run(cmd.temp(img), from: from)
|
|
471
441
|
end
|
|
472
442
|
return
|
|
473
443
|
else
|
|
474
|
-
op.append(escape: true
|
|
444
|
+
op.append(escape: true)
|
|
475
445
|
end
|
|
476
446
|
end
|
|
477
447
|
run(from: from)
|
|
@@ -522,17 +492,17 @@ module Squared
|
|
|
522
492
|
list_image(flag, docker_output('image ls -a'), from: from) do |val|
|
|
523
493
|
op << val
|
|
524
494
|
if flag == :tag
|
|
525
|
-
op << tagname("#{project}:#{op.first}")
|
|
495
|
+
op << tagname("#{@project}:#{op.extras.first}")
|
|
526
496
|
break
|
|
527
497
|
end
|
|
528
498
|
end
|
|
529
499
|
when :push
|
|
530
500
|
id ||= option('tag', ignore: false) || tagmain
|
|
531
501
|
registry ||= op.shift || option('registry') || @registry
|
|
532
|
-
raise_error(id ? "unknown args: #{op.join(', ')}" : 'no id/tag given', hint:
|
|
533
|
-
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
|
|
534
504
|
registry.chomp!('/')
|
|
535
|
-
uri = shell_quote
|
|
505
|
+
uri = shell_quote "#{registry}/#{id}"
|
|
536
506
|
op << uri
|
|
537
507
|
img = docker_output 'image', 'tag', id, uri
|
|
538
508
|
return unless confirm_command(img.to_s, cmd.to_s, target: id, as: registry, title: from)
|
|
@@ -548,7 +518,7 @@ module Squared
|
|
|
548
518
|
|
|
549
519
|
def network(flag, opts = [], target: nil)
|
|
550
520
|
cmd, opts = docker_session('network', flag, opts: opts)
|
|
551
|
-
op = OptionPartition.new(opts, OPT_DOCKER[:network]
|
|
521
|
+
op = OptionPartition.new(opts, OPT_DOCKER[:network][flag], cmd, project: self)
|
|
552
522
|
op.clear
|
|
553
523
|
from = :"network:#{flag}"
|
|
554
524
|
list_image(flag, docker_output('ps -a'), from: from) do |img|
|
|
@@ -564,28 +534,17 @@ module Squared
|
|
|
564
534
|
super || dockerfile.exist?
|
|
565
535
|
end
|
|
566
536
|
|
|
567
|
-
def compose?(file = dockerfile)
|
|
568
|
-
return file == 3 || file == 4 if file.is_a?(Numeric)
|
|
569
|
-
|
|
570
|
-
COMPOSEFILE.include?(File.basename(file))
|
|
571
|
-
end
|
|
572
|
-
|
|
573
|
-
def bake?(file = dockerfile)
|
|
574
|
-
return file == 1 || file == 2 if file.is_a?(Numeric)
|
|
575
|
-
|
|
576
|
-
BAKEFILE.include?(File.basename(file))
|
|
577
|
-
end
|
|
578
|
-
|
|
579
537
|
def dockerfile(val = nil)
|
|
580
|
-
if val
|
|
538
|
+
if val == 'Dockerfile'
|
|
539
|
+
@file = false
|
|
540
|
+
elsif val
|
|
581
541
|
@file = if val.is_a?(Array)
|
|
582
542
|
val = val.select { |file| basepath(file).exist? }
|
|
583
543
|
val.size > 1 ? val : val.first
|
|
584
|
-
|
|
585
|
-
DIR_DOCKER.find { |file| basepath(file).exist? }
|
|
586
|
-
elsif val != 'Dockerfile'
|
|
587
|
-
val
|
|
544
|
+
else
|
|
545
|
+
val || DIR_DOCKER.find { |file| basepath(file).exist? }
|
|
588
546
|
end
|
|
547
|
+
@file ||= false
|
|
589
548
|
end
|
|
590
549
|
basepath((@file.is_a?(Array) ? @file.first : @file) || 'Dockerfile')
|
|
591
550
|
end
|
|
@@ -604,42 +563,35 @@ module Squared
|
|
|
604
563
|
session('docker', *cmd, main: false, options: false, **kwargs)
|
|
605
564
|
end
|
|
606
565
|
|
|
607
|
-
def append_command(flag, val, list, target: @session)
|
|
608
|
-
if
|
|
609
|
-
list << readline('Enter command [args]', force: true)
|
|
610
|
-
elsif (args = env('DOCKER_ARGS'))
|
|
566
|
+
def append_command(flag, val, list, target: @session, from: nil)
|
|
567
|
+
if (args = env('DOCKER_ARGS'))
|
|
611
568
|
list << args
|
|
612
569
|
end
|
|
613
570
|
case flag
|
|
614
571
|
when :run
|
|
615
572
|
unless session_arg?('name', target: target)
|
|
616
|
-
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))
|
|
617
579
|
end
|
|
618
580
|
when :exec
|
|
619
|
-
raise_error('no command args', hint:
|
|
581
|
+
raise_error('no command args', hint: from) if list.empty?
|
|
620
582
|
end
|
|
621
583
|
target << val << list.shift
|
|
622
584
|
target << list.join(' && ') unless list.empty?
|
|
623
585
|
end
|
|
624
586
|
|
|
625
|
-
def append_file(type, target: @session
|
|
626
|
-
return
|
|
587
|
+
def append_file(type, target: @session)
|
|
588
|
+
return unless type == 2 || type == 4 || @file.is_a?(Array)
|
|
627
589
|
|
|
628
|
-
|
|
629
|
-
case type
|
|
630
|
-
when 2, 4
|
|
631
|
-
return
|
|
632
|
-
when 3
|
|
633
|
-
return unless COMPOSEFILE.select { |val| basepath(val).exist? }.size > 1
|
|
634
|
-
end
|
|
635
|
-
end
|
|
636
|
-
files = Array(@file).map { |val| quote_option('file', basepath(val)) }
|
|
590
|
+
files = as_a(@file).map { |val| quote_option('file', path + val) }
|
|
637
591
|
if target.is_a?(Set)
|
|
638
|
-
|
|
639
|
-
target.clear
|
|
640
|
-
.merge(opts)
|
|
592
|
+
target.merge(files)
|
|
641
593
|
else
|
|
642
|
-
target.
|
|
594
|
+
target.concat(files)
|
|
643
595
|
end
|
|
644
596
|
end
|
|
645
597
|
|
|
@@ -651,18 +603,20 @@ module Squared
|
|
|
651
603
|
end
|
|
652
604
|
|
|
653
605
|
def append_tag(val, target: @session)
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
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
|
|
666
620
|
end
|
|
667
621
|
end
|
|
668
622
|
|
|
@@ -672,7 +626,7 @@ module Squared
|
|
|
672
626
|
index = 0
|
|
673
627
|
all = option('all', prefix: 'docker')
|
|
674
628
|
y = from == :'image:rm' && option('y', prefix: 'docker')
|
|
675
|
-
pat =
|
|
629
|
+
pat = /^(?:#{dnsname(name)}|#{tagname(project)}|#{tagmain.split(':', 2).first})(?:[_.,:-]|$)/
|
|
676
630
|
IO.popen(session_done(cmd << '--format=json')).each do |line|
|
|
677
631
|
data = JSON.parse(line)
|
|
678
632
|
id = data['ID']
|
|
@@ -709,7 +663,7 @@ module Squared
|
|
|
709
663
|
cols.each do |key|
|
|
710
664
|
next if (key == 'Tag' && !dd) || (key == 'Size' && data[key] == '0B')
|
|
711
665
|
|
|
712
|
-
puts "#{g + f} #{key}: #{
|
|
666
|
+
puts "#{g + f} #{key}: #{as_a(data[key]).join(', ')}" unless data[key].to_s.empty?
|
|
713
667
|
end
|
|
714
668
|
w = 9 + flag.to_s.size + 4 + ee.size
|
|
715
669
|
puts g + sub_style(ARG[:BORDER][6] + (ARG[:BORDER][1] * w), styles: theme[:inline])
|
|
@@ -721,10 +675,14 @@ module Squared
|
|
|
721
675
|
end
|
|
722
676
|
yield id
|
|
723
677
|
end
|
|
724
|
-
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
|
|
725
679
|
end
|
|
726
680
|
rescue StandardError => e
|
|
727
|
-
|
|
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?
|
|
728
686
|
end
|
|
729
687
|
|
|
730
688
|
def confirm_command(*args, title: nil, target: nil, as: nil)
|
|
@@ -781,7 +739,7 @@ module Squared
|
|
|
781
739
|
cmd = docker_output ctx
|
|
782
740
|
case flag
|
|
783
741
|
when :tag
|
|
784
|
-
args = tagjoin @registry, tag
|
|
742
|
+
args = tagjoin @registry, @tag
|
|
785
743
|
when :save
|
|
786
744
|
opts = "#{opts}.tar" unless opts.end_with?('.tar')
|
|
787
745
|
cmd << quote_option('output', File.expand_path(opts))
|
|
@@ -792,9 +750,13 @@ module Squared
|
|
|
792
750
|
else
|
|
793
751
|
cmd << opts << '--'
|
|
794
752
|
end
|
|
795
|
-
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)
|
|
796
758
|
cmd << args
|
|
797
|
-
print_success if success?(run(cmd)) && ctx.
|
|
759
|
+
print_success if success?(run(cmd)) && ctx.start_with?(/(?:network|tag|save)/)
|
|
798
760
|
end
|
|
799
761
|
end
|
|
800
762
|
|
|
@@ -804,7 +766,7 @@ module Squared
|
|
|
804
766
|
bake?(val) ? 1 : 2
|
|
805
767
|
when '.yml', '.yaml'
|
|
806
768
|
if compose?(val)
|
|
807
|
-
|
|
769
|
+
path.children.any? { |file| bake?(file) } ? 1 : 3
|
|
808
770
|
else
|
|
809
771
|
4
|
|
810
772
|
end
|
|
@@ -814,7 +776,7 @@ module Squared
|
|
|
814
776
|
end
|
|
815
777
|
|
|
816
778
|
def contextdir(val = nil)
|
|
817
|
-
val && projectpath?(val) ? shell_quote(
|
|
779
|
+
val && projectpath?(val) ? shell_quote(path + val) : '.'
|
|
818
780
|
end
|
|
819
781
|
|
|
820
782
|
def tagjoin(*args, char: '/')
|
|
@@ -824,9 +786,10 @@ module Squared
|
|
|
824
786
|
|
|
825
787
|
def tagname(val)
|
|
826
788
|
val = val.split(':').map! { |s| charname(s.sub(/^\W+/, '')) }
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
789
|
+
val.join(':').yield_self do |s|
|
|
790
|
+
s = val.first if val.size > 1 && s.size > 128
|
|
791
|
+
s[0..127]
|
|
792
|
+
end
|
|
830
793
|
end
|
|
831
794
|
|
|
832
795
|
def dnsname(val)
|
|
@@ -840,6 +803,14 @@ module Squared
|
|
|
840
803
|
def tagmain
|
|
841
804
|
tag.is_a?(Array) ? tag.first : tag
|
|
842
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
|
|
843
814
|
end
|
|
844
815
|
|
|
845
816
|
Application.implement Docker
|