squared 0.4.41 → 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 -602
- data/README.md +1283 -663
- data/README.ruby.md +722 -0
- data/lib/squared/common/base.rb +8 -17
- data/lib/squared/common/format.rb +26 -39
- data/lib/squared/common/prompt.rb +48 -53
- data/lib/squared/common/shell.rb +51 -78
- data/lib/squared/common/system.rb +34 -38
- data/lib/squared/common/utils.rb +4 -37
- 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 -132
- data/lib/squared/workspace/project/base.rb +437 -601
- data/lib/squared/workspace/project/docker.rb +200 -233
- data/lib/squared/workspace/project/git.rb +389 -539
- 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 +94 -337
- data/lib/squared/workspace/project.rb +0 -10
- data/lib/squared/workspace/repo.rb +59 -100
- data/lib/squared/workspace/series.rb +42 -49
- 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,83 +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
|
|
24
|
-
project-directory=p p|project-name=
|
|
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
|
|
22
|
+
common: %w[all-resources compatibility dry-run ansi|b env-file=p f|file=p parallel=b profile=b progress=b
|
|
23
|
+
project-directory=p p|project-name=e].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
|
|
40
|
-
blkio-weight-device=i cap-add=b cap-drop=b cgroup-parent=b cgroupns=b
|
|
41
|
-
device-cgroup-rule=q device-read-bps=q device-read-iops=q device-write-bps=q
|
|
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=b
|
|
56
|
-
w|workdir=q].freeze,
|
|
57
|
-
rm: %w[f|force l|link v|volumes].freeze,
|
|
58
54
|
commit: %w[a|author=q c|change=q m|message=q pause=b?].freeze,
|
|
59
|
-
inspect: %w[s|size f|format=q
|
|
55
|
+
inspect: %w[s|size f|format=q].freeze,
|
|
60
56
|
start: %w[a|attach i|interactive detach-keys=q].freeze,
|
|
61
|
-
stop: %w[s|signal=b t|time=i
|
|
62
|
-
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,
|
|
63
59
|
kill: %w[s|signal=b].freeze,
|
|
64
|
-
stats: %w[
|
|
60
|
+
stats: %w[no-trunc format|q].freeze
|
|
65
61
|
}.freeze,
|
|
66
62
|
image: {
|
|
67
|
-
list: %w[a|all
|
|
68
|
-
push: %w[a|all-tags disable-content-trust=b? platform=
|
|
69
|
-
rm: %w[f|force no-prune
|
|
70
|
-
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
|
|
71
67
|
}.freeze,
|
|
72
68
|
network: {
|
|
73
|
-
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,
|
|
74
70
|
disconnect: %w[f|force].freeze
|
|
75
71
|
}.freeze
|
|
76
72
|
}.freeze
|
|
77
73
|
VAL_DOCKER = {
|
|
78
74
|
run: {
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
volume: %w[volume-subpath volume-nocopy volume-opt].freeze,
|
|
82
|
-
tmpfs: %w[tmpfs-size tmpfs-mode].freeze,
|
|
83
|
-
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
|
|
84
77
|
}.freeze
|
|
85
78
|
}.freeze
|
|
86
79
|
private_constant :COMPOSEFILE, :BAKEFILE, :OPT_DOCKER, :VAL_DOCKER
|
|
@@ -93,14 +86,13 @@ module Squared
|
|
|
93
86
|
def config?(val)
|
|
94
87
|
return false unless (val = as_path(val))
|
|
95
88
|
|
|
96
|
-
DIR_DOCKER.any? { |file| val.join(file).exist? }
|
|
89
|
+
val.join('Dockerfile').exist? || DIR_DOCKER.any? { |file| val.join(file).exist? }
|
|
97
90
|
end
|
|
98
91
|
end
|
|
99
92
|
|
|
100
93
|
subtasks({
|
|
101
|
-
'build' => %i[tag context].freeze,
|
|
102
|
-
'compose' => %i[build run exec up
|
|
103
|
-
'bake' => %i[build check].freeze,
|
|
94
|
+
'build' => %i[tag context bake].freeze,
|
|
95
|
+
'compose' => %i[build run exec up].freeze,
|
|
104
96
|
'image' => %i[list rm push tag save].freeze,
|
|
105
97
|
'container' => %i[run create exec update commit inspect diff start stop restart pause unpause top stats kill
|
|
106
98
|
rm].freeze,
|
|
@@ -115,10 +107,11 @@ module Squared
|
|
|
115
107
|
return unless dockerfile(file).exist?
|
|
116
108
|
|
|
117
109
|
@context = context
|
|
118
|
-
|
|
110
|
+
@tag = tag || tagname("#{@project}:#{@version || 'latest'}")
|
|
119
111
|
@mounts = mounts
|
|
120
112
|
@secrets = secrets
|
|
121
113
|
@registry = tagjoin registry, kwargs[:username]
|
|
114
|
+
@file = nil
|
|
122
115
|
initialize_ref Docker.ref
|
|
123
116
|
initialize_logger(**kwargs)
|
|
124
117
|
initialize_env(**kwargs)
|
|
@@ -131,11 +124,11 @@ module Squared
|
|
|
131
124
|
|
|
132
125
|
def populate(*, **)
|
|
133
126
|
super
|
|
134
|
-
return unless ref?(Docker.ref)
|
|
127
|
+
return unless ref?(Docker.ref)
|
|
135
128
|
|
|
136
129
|
namespace name do
|
|
137
130
|
Docker.subtasks do |action, flags|
|
|
138
|
-
next if
|
|
131
|
+
next if @pass.include?(action)
|
|
139
132
|
|
|
140
133
|
namespace action do
|
|
141
134
|
flags.each do |flag|
|
|
@@ -148,39 +141,26 @@ module Squared
|
|
|
148
141
|
param = param_guard(action, flag, args: args, key: flag)
|
|
149
142
|
buildx(:build, args.extras, "#{flag}": param)
|
|
150
143
|
end
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
break unless bake?
|
|
154
|
-
|
|
155
|
-
case flag
|
|
156
|
-
when :build
|
|
157
|
-
format_desc action, flag, 'opts*,target*,context?|:'
|
|
144
|
+
when :bake
|
|
145
|
+
format_desc action, flag, ':?,opts*,target*,context?'
|
|
158
146
|
task flag do |_, args|
|
|
159
147
|
args = args.to_a
|
|
160
148
|
if args.first == ':'
|
|
161
149
|
choice_command :bake
|
|
162
150
|
else
|
|
163
|
-
buildx
|
|
151
|
+
buildx flag, args
|
|
164
152
|
end
|
|
165
153
|
end
|
|
166
|
-
when :check
|
|
167
|
-
format_desc action, flag, 'target'
|
|
168
|
-
task flag, [:target] do |_, args|
|
|
169
|
-
target = param_guard(action, flag, args: args, key: :target)
|
|
170
|
-
buildx :bake, ['allow=fs.read=*', 'call=check', target]
|
|
171
|
-
end
|
|
172
154
|
end
|
|
173
155
|
when 'compose'
|
|
174
|
-
break unless compose?
|
|
175
|
-
|
|
176
156
|
case flag
|
|
177
|
-
when :build, :up
|
|
157
|
+
when :build, :up
|
|
178
158
|
format_desc action, flag, 'opts*,service*'
|
|
179
159
|
task flag do |_, args|
|
|
180
160
|
compose! flag, args.to_a
|
|
181
161
|
end
|
|
182
162
|
when :exec, :run
|
|
183
|
-
format_desc action, flag, "service,command#{flag == :exec ? '' : '?'}
|
|
163
|
+
format_desc action, flag, "service,command#{flag == :exec ? '' : '?'},args*,opts*"
|
|
184
164
|
task flag, [:service] do |_, args|
|
|
185
165
|
service = param_guard(action, flag, args: args, key: :service)
|
|
186
166
|
compose!(flag, args.extras, service: service)
|
|
@@ -208,7 +188,7 @@ module Squared
|
|
|
208
188
|
end
|
|
209
189
|
end
|
|
210
190
|
else
|
|
211
|
-
format_desc
|
|
191
|
+
format_desc(action, flag, 'opts*,id/name', after: flag == :update ? '+' : '*')
|
|
212
192
|
task flag do |_, args|
|
|
213
193
|
container flag, args.to_a
|
|
214
194
|
end
|
|
@@ -218,15 +198,14 @@ module Squared
|
|
|
218
198
|
when :push
|
|
219
199
|
format_desc action, flag, 'tag,registry/username?,opts*'
|
|
220
200
|
task flag, [:tag] do |_, args|
|
|
221
|
-
|
|
222
|
-
image(flag, args.extras, id:
|
|
201
|
+
id = param_guard(action, flag, args: args, key: :tag)
|
|
202
|
+
image(flag, args.extras, id: id)
|
|
223
203
|
end
|
|
224
204
|
else
|
|
225
205
|
format_desc(action, flag, case flag
|
|
226
206
|
when :rm, :save then 'id*,opts*'
|
|
227
207
|
when :tag then 'version?'
|
|
228
|
-
else 'opts*,args*'
|
|
229
|
-
end)
|
|
208
|
+
else 'opts*,args*' end)
|
|
230
209
|
task flag do |_, args|
|
|
231
210
|
args = args.to_a
|
|
232
211
|
if args.empty? && flag != :list
|
|
@@ -253,44 +232,43 @@ module Squared
|
|
|
253
232
|
end
|
|
254
233
|
|
|
255
234
|
def clean(*, sync: invoked_sync?('clean'), **)
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
image :rm
|
|
260
|
-
end
|
|
235
|
+
return super unless @clean.nil?
|
|
236
|
+
|
|
237
|
+
image(:rm, sync: sync)
|
|
261
238
|
end
|
|
262
239
|
|
|
263
240
|
def compose(opts, flags = nil, script: false, args: nil, from: :run, **)
|
|
264
241
|
return opts if script == false
|
|
265
242
|
|
|
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
|
|
250
|
+
when 3, 4
|
|
251
|
+
ret << 'compose' << 'build'
|
|
273
252
|
append_file n
|
|
274
253
|
from = :compose
|
|
275
254
|
else
|
|
276
|
-
ret
|
|
255
|
+
ret << 'build'
|
|
277
256
|
end
|
|
278
257
|
else
|
|
279
|
-
ret
|
|
258
|
+
ret << from
|
|
280
259
|
end
|
|
281
260
|
case opts
|
|
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,11 +306,22 @@ 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
|
-
op.
|
|
335
|
-
|
|
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
|
|
336
325
|
end
|
|
337
326
|
op.clear(pass: false)
|
|
338
327
|
run(from: :"buildx:#{flag}")
|
|
@@ -343,16 +332,16 @@ module Squared
|
|
|
343
332
|
op = OptionPartition.new(opts, OPT_DOCKER[:compose][:common], cmd, project: self)
|
|
344
333
|
append_file filetype unless op.arg?('f', 'file')
|
|
345
334
|
op << flag
|
|
346
|
-
op.parse(OPT_DOCKER[:compose]
|
|
335
|
+
op.parse(OPT_DOCKER[:compose][flag])
|
|
336
|
+
from = :"compose:#{flag}"
|
|
347
337
|
case flag
|
|
348
|
-
when :build, :up
|
|
349
|
-
op.append(escape: true
|
|
338
|
+
when :build, :up
|
|
339
|
+
op.append(escape: true)
|
|
350
340
|
when :exec, :run
|
|
351
|
-
append_command
|
|
341
|
+
append_command(flag, service, op.extras, from: from)
|
|
352
342
|
end
|
|
353
|
-
run(from:
|
|
343
|
+
run(from: from)
|
|
354
344
|
end
|
|
355
|
-
alias compose_ compose!
|
|
356
345
|
|
|
357
346
|
def container(flag, opts = [], id: nil)
|
|
358
347
|
cmd, opts = docker_session('container', flag, opts: opts)
|
|
@@ -365,54 +354,45 @@ module Squared
|
|
|
365
354
|
case flag
|
|
366
355
|
when :run, :create, :exec
|
|
367
356
|
if rc && !op.arg?('mount')
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
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|
|
|
371
362
|
args = []
|
|
372
|
-
|
|
363
|
+
tmpfs = true
|
|
373
364
|
val.split(delim).each do |opt|
|
|
374
365
|
k, v, q = split_option opt
|
|
375
|
-
|
|
376
|
-
case v
|
|
377
|
-
when 'bind', 'volume', 'image', 'tmpfs'
|
|
378
|
-
type = v
|
|
379
|
-
else
|
|
380
|
-
raise_error("unknown type: #{v}", hint: flag)
|
|
381
|
-
end
|
|
382
|
-
elsif all.include?(k)
|
|
383
|
-
unless type
|
|
384
|
-
VAL_DOCKER[:run].each_pair do |key, a|
|
|
385
|
-
next unless a.include?(k)
|
|
366
|
+
next unless both.include?(k)
|
|
386
367
|
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
when 'readonly', 'ro'
|
|
393
|
-
args << k
|
|
394
|
-
next
|
|
395
|
-
when 'source', 'src', 'destination', 'dst', 'target', 'volume-subpath', 'image-path'
|
|
396
|
-
v = basepath v
|
|
397
|
-
v = shell_quote(v, option: false, force: false) if q == ''
|
|
398
|
-
end
|
|
399
|
-
args << "#{k}=#{q + v + q}"
|
|
400
|
-
elsif verbose
|
|
401
|
-
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
|
|
402
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}"
|
|
403
384
|
end
|
|
404
|
-
|
|
405
|
-
cmd << "--mount type=#{type},#{args.join(',')}"
|
|
385
|
+
cmd << "--mount type=#{tmpfs ? 'tmpfs' : 'bind'},#{args.join(',')}"
|
|
406
386
|
end
|
|
407
387
|
end
|
|
408
|
-
append_command(flag, id || tagmain, op.extras)
|
|
409
|
-
when :update
|
|
410
|
-
raise_error('missing container', hint:
|
|
411
|
-
op.append(escape: true
|
|
388
|
+
append_command(flag, id || tagmain, op.extras, from: from)
|
|
389
|
+
when :update
|
|
390
|
+
raise_error('missing container', hint: from) if op.empty?
|
|
391
|
+
op.append(escape: true)
|
|
412
392
|
when :commit
|
|
413
393
|
latest = op.shift || tagmain
|
|
414
394
|
cmd << id << latest
|
|
415
|
-
raise_error("unknown args: #{op.join(', ')}", hint:
|
|
395
|
+
raise_error("unknown args: #{op.join(', ')}", hint: from) unless op.empty?
|
|
416
396
|
return unless confirm_command(cmd.to_s, title: from, target: id, as: latest)
|
|
417
397
|
|
|
418
398
|
registry = option('registry') || @registry
|
|
@@ -455,13 +435,13 @@ module Squared
|
|
|
455
435
|
when :rm
|
|
456
436
|
status = %w[created exited dead]
|
|
457
437
|
end
|
|
458
|
-
ps = docker_output('ps -a', *status.map { |s|
|
|
438
|
+
ps = docker_output('ps -a', *status.map { |s| "--filter=\"status=#{s}\"" })
|
|
459
439
|
list_image(flag, ps, no: no, hint: "status: #{status.join(', ')}", from: from) do |img|
|
|
460
440
|
run(cmd.temp(img), from: from)
|
|
461
441
|
end
|
|
462
442
|
return
|
|
463
443
|
else
|
|
464
|
-
op.append(escape: true
|
|
444
|
+
op.append(escape: true)
|
|
465
445
|
end
|
|
466
446
|
end
|
|
467
447
|
run(from: from)
|
|
@@ -512,17 +492,17 @@ module Squared
|
|
|
512
492
|
list_image(flag, docker_output('image ls -a'), from: from) do |val|
|
|
513
493
|
op << val
|
|
514
494
|
if flag == :tag
|
|
515
|
-
op << tagname("#{project}:#{op.first}")
|
|
495
|
+
op << tagname("#{@project}:#{op.extras.first}")
|
|
516
496
|
break
|
|
517
497
|
end
|
|
518
498
|
end
|
|
519
499
|
when :push
|
|
520
500
|
id ||= option('tag', ignore: false) || tagmain
|
|
521
501
|
registry ||= op.shift || option('registry') || @registry
|
|
522
|
-
raise_error(id ? "unknown args: #{op.join(', ')}" : 'no id/tag given', hint:
|
|
523
|
-
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
|
|
524
504
|
registry.chomp!('/')
|
|
525
|
-
uri = shell_quote
|
|
505
|
+
uri = shell_quote "#{registry}/#{id}"
|
|
526
506
|
op << uri
|
|
527
507
|
img = docker_output 'image', 'tag', id, uri
|
|
528
508
|
return unless confirm_command(img.to_s, cmd.to_s, target: id, as: registry, title: from)
|
|
@@ -538,7 +518,7 @@ module Squared
|
|
|
538
518
|
|
|
539
519
|
def network(flag, opts = [], target: nil)
|
|
540
520
|
cmd, opts = docker_session('network', flag, opts: opts)
|
|
541
|
-
op = OptionPartition.new(opts, OPT_DOCKER[:network]
|
|
521
|
+
op = OptionPartition.new(opts, OPT_DOCKER[:network][flag], cmd, project: self)
|
|
542
522
|
op.clear
|
|
543
523
|
from = :"network:#{flag}"
|
|
544
524
|
list_image(flag, docker_output('ps -a'), from: from) do |img|
|
|
@@ -554,28 +534,17 @@ module Squared
|
|
|
554
534
|
super || dockerfile.exist?
|
|
555
535
|
end
|
|
556
536
|
|
|
557
|
-
def compose?(file = dockerfile)
|
|
558
|
-
return file == 3 || file == 4 if file.is_a?(Numeric)
|
|
559
|
-
|
|
560
|
-
COMPOSEFILE.include?(File.basename(file))
|
|
561
|
-
end
|
|
562
|
-
|
|
563
|
-
def bake?(file = dockerfile)
|
|
564
|
-
return file == 1 || file == 2 if file.is_a?(Numeric)
|
|
565
|
-
|
|
566
|
-
BAKEFILE.include?(File.basename(file))
|
|
567
|
-
end
|
|
568
|
-
|
|
569
537
|
def dockerfile(val = nil)
|
|
570
|
-
if val
|
|
538
|
+
if val == 'Dockerfile'
|
|
539
|
+
@file = false
|
|
540
|
+
elsif val
|
|
571
541
|
@file = if val.is_a?(Array)
|
|
572
542
|
val = val.select { |file| basepath(file).exist? }
|
|
573
543
|
val.size > 1 ? val : val.first
|
|
574
|
-
|
|
575
|
-
DIR_DOCKER.find { |file| basepath(file).exist? }
|
|
576
|
-
elsif val != 'Dockerfile'
|
|
577
|
-
val
|
|
544
|
+
else
|
|
545
|
+
val || DIR_DOCKER.find { |file| basepath(file).exist? }
|
|
578
546
|
end
|
|
547
|
+
@file ||= false
|
|
579
548
|
end
|
|
580
549
|
basepath((@file.is_a?(Array) ? @file.first : @file) || 'Dockerfile')
|
|
581
550
|
end
|
|
@@ -594,56 +563,35 @@ module Squared
|
|
|
594
563
|
session('docker', *cmd, main: false, options: false, **kwargs)
|
|
595
564
|
end
|
|
596
565
|
|
|
597
|
-
def append_command(flag, val, list, target: @session)
|
|
598
|
-
if
|
|
599
|
-
list << readline('Enter command [args]', force: true)
|
|
600
|
-
elsif (args = env('DOCKER_ARGS'))
|
|
566
|
+
def append_command(flag, val, list, target: @session, from: nil)
|
|
567
|
+
if (args = env('DOCKER_ARGS'))
|
|
601
568
|
list << args
|
|
602
569
|
end
|
|
603
570
|
case flag
|
|
604
571
|
when :run
|
|
605
572
|
unless session_arg?('name', target: target)
|
|
606
|
-
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))
|
|
607
579
|
end
|
|
608
580
|
when :exec
|
|
609
|
-
raise_error('no command args', hint:
|
|
610
|
-
end
|
|
611
|
-
target << val
|
|
612
|
-
case list.first
|
|
613
|
-
when '--'
|
|
614
|
-
target.merge(list.drop(1))
|
|
615
|
-
when /\A(--|&&)(\s|\z)/
|
|
616
|
-
target.merge(list)
|
|
617
|
-
else
|
|
618
|
-
target << list.shift
|
|
619
|
-
unless list.empty?
|
|
620
|
-
if list.first.start_with?('-')
|
|
621
|
-
target.merge(list)
|
|
622
|
-
else
|
|
623
|
-
target << list.join(' && ')
|
|
624
|
-
end
|
|
625
|
-
end
|
|
581
|
+
raise_error('no command args', hint: from) if list.empty?
|
|
626
582
|
end
|
|
583
|
+
target << val << list.shift
|
|
584
|
+
target << list.join(' && ') unless list.empty?
|
|
627
585
|
end
|
|
628
586
|
|
|
629
|
-
def append_file(type, target: @session
|
|
630
|
-
return
|
|
587
|
+
def append_file(type, target: @session)
|
|
588
|
+
return unless type == 2 || type == 4 || @file.is_a?(Array)
|
|
631
589
|
|
|
632
|
-
|
|
633
|
-
case type
|
|
634
|
-
when 2, 4
|
|
635
|
-
return
|
|
636
|
-
when 3
|
|
637
|
-
return unless COMPOSEFILE.select { |val| basepath(val).exist? }.size > 1
|
|
638
|
-
end
|
|
639
|
-
end
|
|
640
|
-
files = Array(@file).map { |val| quote_option('file', basepath(val)) }
|
|
590
|
+
files = as_a(@file).map { |val| quote_option('file', path + val) }
|
|
641
591
|
if target.is_a?(Set)
|
|
642
|
-
|
|
643
|
-
target.clear
|
|
644
|
-
.merge(opts)
|
|
592
|
+
target.merge(files)
|
|
645
593
|
else
|
|
646
|
-
target.
|
|
594
|
+
target.concat(files)
|
|
647
595
|
end
|
|
648
596
|
end
|
|
649
597
|
|
|
@@ -655,28 +603,30 @@ module Squared
|
|
|
655
603
|
end
|
|
656
604
|
|
|
657
605
|
def append_tag(val, target: @session)
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
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
|
|
670
620
|
end
|
|
671
621
|
end
|
|
672
622
|
|
|
673
|
-
def list_image(flag, cmd, hint: nil,
|
|
674
|
-
pwd_set
|
|
623
|
+
def list_image(flag, cmd, hint: nil, from: nil, no: true)
|
|
624
|
+
pwd_set do
|
|
675
625
|
found = false
|
|
676
626
|
index = 0
|
|
677
627
|
all = option('all', prefix: 'docker')
|
|
678
628
|
y = from == :'image:rm' && option('y', prefix: 'docker')
|
|
679
|
-
pat =
|
|
629
|
+
pat = /^(?:#{dnsname(name)}|#{tagname(project)}|#{tagmain.split(':', 2).first})(?:[_.,:-]|$)/
|
|
680
630
|
IO.popen(session_done(cmd << '--format=json')).each do |line|
|
|
681
631
|
data = JSON.parse(line)
|
|
682
632
|
id = data['ID']
|
|
@@ -713,7 +663,7 @@ module Squared
|
|
|
713
663
|
cols.each do |key|
|
|
714
664
|
next if (key == 'Tag' && !dd) || (key == 'Size' && data[key] == '0B')
|
|
715
665
|
|
|
716
|
-
puts "#{g + f} #{key}: #{
|
|
666
|
+
puts "#{g + f} #{key}: #{as_a(data[key]).join(', ')}" unless data[key].to_s.empty?
|
|
717
667
|
end
|
|
718
668
|
w = 9 + flag.to_s.size + 4 + ee.size
|
|
719
669
|
puts g + sub_style(ARG[:BORDER][6] + (ARG[:BORDER][1] * w), styles: theme[:inline])
|
|
@@ -725,10 +675,14 @@ module Squared
|
|
|
725
675
|
end
|
|
726
676
|
yield id
|
|
727
677
|
end
|
|
728
|
-
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
|
|
729
679
|
end
|
|
730
680
|
rescue StandardError => e
|
|
731
|
-
|
|
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?
|
|
732
686
|
end
|
|
733
687
|
|
|
734
688
|
def confirm_command(*args, title: nil, target: nil, as: nil)
|
|
@@ -785,7 +739,7 @@ module Squared
|
|
|
785
739
|
cmd = docker_output ctx
|
|
786
740
|
case flag
|
|
787
741
|
when :tag
|
|
788
|
-
args = tagjoin @registry, tag
|
|
742
|
+
args = tagjoin @registry, @tag
|
|
789
743
|
when :save
|
|
790
744
|
opts = "#{opts}.tar" unless opts.end_with?('.tar')
|
|
791
745
|
cmd << quote_option('output', File.expand_path(opts))
|
|
@@ -796,9 +750,13 @@ module Squared
|
|
|
796
750
|
else
|
|
797
751
|
cmd << opts << '--'
|
|
798
752
|
end
|
|
799
|
-
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)
|
|
800
758
|
cmd << args
|
|
801
|
-
print_success if success?(run(cmd
|
|
759
|
+
print_success if success?(run(cmd)) && ctx.start_with?(/(?:network|tag|save)/)
|
|
802
760
|
end
|
|
803
761
|
end
|
|
804
762
|
|
|
@@ -808,7 +766,7 @@ module Squared
|
|
|
808
766
|
bake?(val) ? 1 : 2
|
|
809
767
|
when '.yml', '.yaml'
|
|
810
768
|
if compose?(val)
|
|
811
|
-
|
|
769
|
+
path.children.any? { |file| bake?(file) } ? 1 : 3
|
|
812
770
|
else
|
|
813
771
|
4
|
|
814
772
|
end
|
|
@@ -818,7 +776,7 @@ module Squared
|
|
|
818
776
|
end
|
|
819
777
|
|
|
820
778
|
def contextdir(val = nil)
|
|
821
|
-
val && projectpath?(val) ? shell_quote(
|
|
779
|
+
val && projectpath?(val) ? shell_quote(path + val) : '.'
|
|
822
780
|
end
|
|
823
781
|
|
|
824
782
|
def tagjoin(*args, char: '/')
|
|
@@ -828,9 +786,10 @@ module Squared
|
|
|
828
786
|
|
|
829
787
|
def tagname(val)
|
|
830
788
|
val = val.split(':').map! { |s| charname(s.sub(/^\W+/, '')) }
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
789
|
+
val.join(':').yield_self do |s|
|
|
790
|
+
s = val.first if val.size > 1 && s.size > 128
|
|
791
|
+
s[0..127]
|
|
792
|
+
end
|
|
834
793
|
end
|
|
835
794
|
|
|
836
795
|
def dnsname(val)
|
|
@@ -844,6 +803,14 @@ module Squared
|
|
|
844
803
|
def tagmain
|
|
845
804
|
tag.is_a?(Array) ? tag.first : tag
|
|
846
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
|
|
847
814
|
end
|
|
848
815
|
|
|
849
816
|
Application.implement Docker
|