squared 0.4.24 → 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 -357
- 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 +17 -24
- data/lib/squared/common/prompt.rb +38 -42
- data/lib/squared/common/shell.rb +29 -29
- 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 +21 -21
- data/lib/squared/version.rb +1 -1
- data/lib/squared/workspace/application.rb +57 -93
- data/lib/squared/workspace/project/base.rb +354 -480
- data/lib/squared/workspace/project/docker.rb +175 -203
- data/lib/squared/workspace/project/git.rb +357 -498
- data/lib/squared/workspace/project/node.rb +138 -213
- data/lib/squared/workspace/project/python.rb +88 -306
- data/lib/squared/workspace/project/ruby.rb +220 -300
- data/lib/squared/workspace/project/support/class.rb +94 -288
- data/lib/squared/workspace/project.rb +0 -10
- data/lib/squared/workspace/repo.rb +53 -92
- 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 -110
- data/lib/squared/workspace/support/base.rb +0 -17
|
@@ -4,67 +4,65 @@ 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 runtime t|tty use-api-socket io-maxbandwidth=b io-maxiops=b add-host=q annotation=q
|
|
40
|
-
blkio-weight=i blkio-weight-device=i cap-add=b cap-drop=b cgroup-parent=b cgroupns=b
|
|
41
|
-
device=q device-cgroup-rule=q device-read-bps=q device-read-iops=q device-write-bps=q
|
|
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
|
|
42
39
|
device-write-iops=q disable-content-trust=b? dns=e dns-option=e dns-search=e domainname=b
|
|
43
|
-
entrypoint=q e|env=qq env-file=p expose=e gpus=q group-add=b health-cmd=q health-interval=b
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
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,
|
|
50
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,
|
|
51
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
|
|
52
52
|
cpuset-cpus=b cpuset-mems=b m|memory=b memory-reservation=b memory-swap=b pids-limit=n
|
|
53
53
|
restart=q].freeze,
|
|
54
|
-
exec: %w[d|detach i|interactive privileged t|tty detach-keys=q e|env=qq env-file=p user=e
|
|
55
|
-
w|workdir=q].freeze,
|
|
56
54
|
commit: %w[a|author=q c|change=q m|message=q pause=b?].freeze,
|
|
57
55
|
inspect: %w[s|size f|format=q].freeze,
|
|
58
56
|
start: %w[a|attach i|interactive detach-keys=q].freeze,
|
|
59
|
-
stop: %w[s|signal=b t|time=i
|
|
60
|
-
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,
|
|
61
59
|
kill: %w[s|signal=b].freeze,
|
|
62
|
-
stats: %w[
|
|
60
|
+
stats: %w[no-trunc format|q].freeze
|
|
63
61
|
}.freeze,
|
|
64
62
|
image: {
|
|
65
|
-
list: %w[a|all
|
|
63
|
+
list: %w[a|all digests no-trunc f|filter=q format=q].freeze,
|
|
66
64
|
push: %w[a|all-tags disable-content-trust=b? platform=b q|quiet].freeze,
|
|
67
|
-
rm: %w[f|force no-prune
|
|
65
|
+
rm: %w[f|force no-prune].freeze,
|
|
68
66
|
save: %w[o|output=p platform=b].freeze
|
|
69
67
|
}.freeze,
|
|
70
68
|
network: {
|
|
@@ -74,11 +72,8 @@ module Squared
|
|
|
74
72
|
}.freeze
|
|
75
73
|
VAL_DOCKER = {
|
|
76
74
|
run: {
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
volume: %w[volume-subpath volume-nocopy volume-opt].freeze,
|
|
80
|
-
tmpfs: %w[tmpfs-size tmpfs-mode].freeze,
|
|
81
|
-
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
|
|
82
77
|
}.freeze
|
|
83
78
|
}.freeze
|
|
84
79
|
private_constant :COMPOSEFILE, :BAKEFILE, :OPT_DOCKER, :VAL_DOCKER
|
|
@@ -91,14 +86,13 @@ module Squared
|
|
|
91
86
|
def config?(val)
|
|
92
87
|
return false unless (val = as_path(val))
|
|
93
88
|
|
|
94
|
-
DIR_DOCKER.any? { |file| val.join(file).exist? }
|
|
89
|
+
val.join('Dockerfile').exist? || DIR_DOCKER.any? { |file| val.join(file).exist? }
|
|
95
90
|
end
|
|
96
91
|
end
|
|
97
92
|
|
|
98
93
|
subtasks({
|
|
99
|
-
'build' => %i[tag context].freeze,
|
|
100
|
-
'compose' => %i[build run exec up
|
|
101
|
-
'bake' => %i[build check].freeze,
|
|
94
|
+
'build' => %i[tag context bake].freeze,
|
|
95
|
+
'compose' => %i[build run exec up].freeze,
|
|
102
96
|
'image' => %i[list rm push tag save].freeze,
|
|
103
97
|
'container' => %i[run create exec update commit inspect diff start stop restart pause unpause top stats kill
|
|
104
98
|
rm].freeze,
|
|
@@ -113,10 +107,11 @@ module Squared
|
|
|
113
107
|
return unless dockerfile(file).exist?
|
|
114
108
|
|
|
115
109
|
@context = context
|
|
116
|
-
|
|
110
|
+
@tag = tag || tagname("#{@project}:#{@version || 'latest'}")
|
|
117
111
|
@mounts = mounts
|
|
118
112
|
@secrets = secrets
|
|
119
113
|
@registry = tagjoin registry, kwargs[:username]
|
|
114
|
+
@file = nil
|
|
120
115
|
initialize_ref Docker.ref
|
|
121
116
|
initialize_logger(**kwargs)
|
|
122
117
|
initialize_env(**kwargs)
|
|
@@ -129,11 +124,11 @@ module Squared
|
|
|
129
124
|
|
|
130
125
|
def populate(*, **)
|
|
131
126
|
super
|
|
132
|
-
return unless ref?(Docker.ref)
|
|
127
|
+
return unless ref?(Docker.ref)
|
|
133
128
|
|
|
134
129
|
namespace name do
|
|
135
130
|
Docker.subtasks do |action, flags|
|
|
136
|
-
next if
|
|
131
|
+
next if @pass.include?(action)
|
|
137
132
|
|
|
138
133
|
namespace action do
|
|
139
134
|
flags.each do |flag|
|
|
@@ -146,39 +141,26 @@ module Squared
|
|
|
146
141
|
param = param_guard(action, flag, args: args, key: flag)
|
|
147
142
|
buildx(:build, args.extras, "#{flag}": param)
|
|
148
143
|
end
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
break unless bake?
|
|
152
|
-
|
|
153
|
-
case flag
|
|
154
|
-
when :build
|
|
155
|
-
format_desc action, flag, 'opts*,target*,context?|:'
|
|
144
|
+
when :bake
|
|
145
|
+
format_desc action, flag, ':?,opts*,target*,context?'
|
|
156
146
|
task flag do |_, args|
|
|
157
147
|
args = args.to_a
|
|
158
148
|
if args.first == ':'
|
|
159
149
|
choice_command :bake
|
|
160
150
|
else
|
|
161
|
-
buildx
|
|
151
|
+
buildx flag, args
|
|
162
152
|
end
|
|
163
153
|
end
|
|
164
|
-
when :check
|
|
165
|
-
format_desc action, flag, 'target'
|
|
166
|
-
task flag, [:target] do |_, args|
|
|
167
|
-
target = param_guard(action, flag, args: args, key: :target)
|
|
168
|
-
buildx :bake, ['allow=fs.read=*', 'call=check', target]
|
|
169
|
-
end
|
|
170
154
|
end
|
|
171
155
|
when 'compose'
|
|
172
|
-
break unless compose?
|
|
173
|
-
|
|
174
156
|
case flag
|
|
175
|
-
when :build, :up
|
|
157
|
+
when :build, :up
|
|
176
158
|
format_desc action, flag, 'opts*,service*'
|
|
177
159
|
task flag do |_, args|
|
|
178
160
|
compose! flag, args.to_a
|
|
179
161
|
end
|
|
180
162
|
when :exec, :run
|
|
181
|
-
format_desc action, flag, "service,command#{flag == :exec ? '' : '?'}
|
|
163
|
+
format_desc action, flag, "service,command#{flag == :exec ? '' : '?'},args*,opts*"
|
|
182
164
|
task flag, [:service] do |_, args|
|
|
183
165
|
service = param_guard(action, flag, args: args, key: :service)
|
|
184
166
|
compose!(flag, args.extras, service: service)
|
|
@@ -206,7 +188,7 @@ module Squared
|
|
|
206
188
|
end
|
|
207
189
|
end
|
|
208
190
|
else
|
|
209
|
-
format_desc
|
|
191
|
+
format_desc(action, flag, 'opts*,id/name', after: flag == :update ? '+' : '*')
|
|
210
192
|
task flag do |_, args|
|
|
211
193
|
container flag, args.to_a
|
|
212
194
|
end
|
|
@@ -216,15 +198,14 @@ module Squared
|
|
|
216
198
|
when :push
|
|
217
199
|
format_desc action, flag, 'tag,registry/username?,opts*'
|
|
218
200
|
task flag, [:tag] do |_, args|
|
|
219
|
-
|
|
220
|
-
image(flag, args.extras, id:
|
|
201
|
+
id = param_guard(action, flag, args: args, key: :tag)
|
|
202
|
+
image(flag, args.extras, id: id)
|
|
221
203
|
end
|
|
222
204
|
else
|
|
223
205
|
format_desc(action, flag, case flag
|
|
224
206
|
when :rm, :save then 'id*,opts*'
|
|
225
207
|
when :tag then 'version?'
|
|
226
|
-
else 'opts*,args*'
|
|
227
|
-
end)
|
|
208
|
+
else 'opts*,args*' end)
|
|
228
209
|
task flag do |_, args|
|
|
229
210
|
args = args.to_a
|
|
230
211
|
if args.empty? && flag != :list
|
|
@@ -251,11 +232,9 @@ module Squared
|
|
|
251
232
|
end
|
|
252
233
|
|
|
253
234
|
def clean(*, sync: invoked_sync?('clean'), **)
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
image(:rm, sync: sync)
|
|
258
|
-
end
|
|
235
|
+
return super unless @clean.nil?
|
|
236
|
+
|
|
237
|
+
image(:rm, sync: sync)
|
|
259
238
|
end
|
|
260
239
|
|
|
261
240
|
def compose(opts, flags = nil, script: false, args: nil, from: :run, **)
|
|
@@ -263,12 +242,13 @@ module Squared
|
|
|
263
242
|
|
|
264
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 << 'compose build'
|
|
250
|
+
when 3, 4
|
|
251
|
+
ret << 'compose' << 'build'
|
|
272
252
|
append_file n
|
|
273
253
|
from = :compose
|
|
274
254
|
else
|
|
@@ -281,15 +261,14 @@ module Squared
|
|
|
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)
|
|
@@ -375,54 +355,44 @@ module Squared
|
|
|
375
355
|
when :run, :create, :exec
|
|
376
356
|
if rc && !op.arg?('mount')
|
|
377
357
|
run = VAL_DOCKER[:run]
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
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
|
-
run.each_pair do |key, val|
|
|
395
|
-
next unless val.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,41 +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.map { |val| basepath(val) }.select(&: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.merge(opts)
|
|
592
|
+
target.merge(files)
|
|
640
593
|
else
|
|
641
|
-
target.
|
|
594
|
+
target.concat(files)
|
|
642
595
|
end
|
|
643
596
|
end
|
|
644
597
|
|
|
@@ -650,18 +603,20 @@ 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
|
|
|
@@ -671,7 +626,7 @@ module Squared
|
|
|
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
|