squared 0.4.29 → 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 -416
- 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 +22 -29
- data/lib/squared/common/prompt.rb +46 -47
- data/lib/squared/common/shell.rb +50 -63
- 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 +74 -95
- data/lib/squared/workspace/project/base.rb +408 -536
- data/lib/squared/workspace/project/docker.rb +176 -206
- data/lib/squared/workspace/project/git.rb +357 -498
- data/lib/squared/workspace/project/node.rb +180 -286
- data/lib/squared/workspace/project/python.rb +88 -306
- data/lib/squared/workspace/project/ruby.rb +221 -301
- data/lib/squared/workspace/project/support/class.rb +93 -300
- data/lib/squared/workspace/project.rb +0 -10
- data/lib/squared/workspace/repo.rb +54 -93
- 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 -171
- 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)
|
|
@@ -376,54 +355,44 @@ module Squared
|
|
|
376
355
|
when :run, :create, :exec
|
|
377
356
|
if rc && !op.arg?('mount')
|
|
378
357
|
run = VAL_DOCKER[:run]
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
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|
|
|
382
362
|
args = []
|
|
383
|
-
|
|
363
|
+
tmpfs = true
|
|
384
364
|
val.split(delim).each do |opt|
|
|
385
365
|
k, v, q = split_option opt
|
|
386
|
-
|
|
387
|
-
case v
|
|
388
|
-
when 'bind', 'volume', 'image', 'tmpfs'
|
|
389
|
-
type = v
|
|
390
|
-
else
|
|
391
|
-
raise_error("unknown type: #{v}", hint: flag)
|
|
392
|
-
end
|
|
393
|
-
elsif all.include?(k)
|
|
394
|
-
unless type
|
|
395
|
-
run.each_pair do |key, val|
|
|
396
|
-
next unless val.include?(k)
|
|
366
|
+
next unless both.include?(k)
|
|
397
367
|
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
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'
|
|
413
382
|
end
|
|
383
|
+
args << "#{k}=#{q + v + q}"
|
|
414
384
|
end
|
|
415
|
-
|
|
416
|
-
cmd << "--mount type=#{type},#{args.join(',')}"
|
|
385
|
+
cmd << "--mount type=#{tmpfs ? 'tmpfs' : 'bind'},#{args.join(',')}"
|
|
417
386
|
end
|
|
418
387
|
end
|
|
419
|
-
append_command(flag, id || tagmain, op.extras)
|
|
388
|
+
append_command(flag, id || tagmain, op.extras, from: from)
|
|
420
389
|
when :update
|
|
421
|
-
raise_error('missing container', hint:
|
|
422
|
-
op.append(escape: true
|
|
390
|
+
raise_error('missing container', hint: from) if op.empty?
|
|
391
|
+
op.append(escape: true)
|
|
423
392
|
when :commit
|
|
424
393
|
latest = op.shift || tagmain
|
|
425
394
|
cmd << id << latest
|
|
426
|
-
raise_error("unknown args: #{op.join(', ')}", hint:
|
|
395
|
+
raise_error("unknown args: #{op.join(', ')}", hint: from) unless op.empty?
|
|
427
396
|
return unless confirm_command(cmd.to_s, title: from, target: id, as: latest)
|
|
428
397
|
|
|
429
398
|
registry = option('registry') || @registry
|
|
@@ -466,13 +435,13 @@ module Squared
|
|
|
466
435
|
when :rm
|
|
467
436
|
status = %w[created exited dead]
|
|
468
437
|
end
|
|
469
|
-
ps = docker_output('ps -a', *status.map { |s|
|
|
438
|
+
ps = docker_output('ps -a', *status.map { |s| "--filter=\"status=#{s}\"" })
|
|
470
439
|
list_image(flag, ps, no: no, hint: "status: #{status.join(', ')}", from: from) do |img|
|
|
471
440
|
run(cmd.temp(img), from: from)
|
|
472
441
|
end
|
|
473
442
|
return
|
|
474
443
|
else
|
|
475
|
-
op.append(escape: true
|
|
444
|
+
op.append(escape: true)
|
|
476
445
|
end
|
|
477
446
|
end
|
|
478
447
|
run(from: from)
|
|
@@ -523,17 +492,17 @@ module Squared
|
|
|
523
492
|
list_image(flag, docker_output('image ls -a'), from: from) do |val|
|
|
524
493
|
op << val
|
|
525
494
|
if flag == :tag
|
|
526
|
-
op << tagname("#{project}:#{op.first}")
|
|
495
|
+
op << tagname("#{@project}:#{op.extras.first}")
|
|
527
496
|
break
|
|
528
497
|
end
|
|
529
498
|
end
|
|
530
499
|
when :push
|
|
531
500
|
id ||= option('tag', ignore: false) || tagmain
|
|
532
501
|
registry ||= op.shift || option('registry') || @registry
|
|
533
|
-
raise_error(id ? "unknown args: #{op.join(', ')}" : 'no id/tag given', hint:
|
|
534
|
-
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
|
|
535
504
|
registry.chomp!('/')
|
|
536
|
-
uri = shell_quote
|
|
505
|
+
uri = shell_quote "#{registry}/#{id}"
|
|
537
506
|
op << uri
|
|
538
507
|
img = docker_output 'image', 'tag', id, uri
|
|
539
508
|
return unless confirm_command(img.to_s, cmd.to_s, target: id, as: registry, title: from)
|
|
@@ -549,7 +518,7 @@ module Squared
|
|
|
549
518
|
|
|
550
519
|
def network(flag, opts = [], target: nil)
|
|
551
520
|
cmd, opts = docker_session('network', flag, opts: opts)
|
|
552
|
-
op = OptionPartition.new(opts, OPT_DOCKER[:network]
|
|
521
|
+
op = OptionPartition.new(opts, OPT_DOCKER[:network][flag], cmd, project: self)
|
|
553
522
|
op.clear
|
|
554
523
|
from = :"network:#{flag}"
|
|
555
524
|
list_image(flag, docker_output('ps -a'), from: from) do |img|
|
|
@@ -565,28 +534,17 @@ module Squared
|
|
|
565
534
|
super || dockerfile.exist?
|
|
566
535
|
end
|
|
567
536
|
|
|
568
|
-
def compose?(file = dockerfile)
|
|
569
|
-
return file == 3 || file == 4 if file.is_a?(Numeric)
|
|
570
|
-
|
|
571
|
-
COMPOSEFILE.include?(File.basename(file))
|
|
572
|
-
end
|
|
573
|
-
|
|
574
|
-
def bake?(file = dockerfile)
|
|
575
|
-
return file == 1 || file == 2 if file.is_a?(Numeric)
|
|
576
|
-
|
|
577
|
-
BAKEFILE.include?(File.basename(file))
|
|
578
|
-
end
|
|
579
|
-
|
|
580
537
|
def dockerfile(val = nil)
|
|
581
|
-
if val
|
|
538
|
+
if val == 'Dockerfile'
|
|
539
|
+
@file = false
|
|
540
|
+
elsif val
|
|
582
541
|
@file = if val.is_a?(Array)
|
|
583
542
|
val = val.select { |file| basepath(file).exist? }
|
|
584
543
|
val.size > 1 ? val : val.first
|
|
585
|
-
|
|
586
|
-
DIR_DOCKER.find { |file| basepath(file).exist? }
|
|
587
|
-
elsif val != 'Dockerfile'
|
|
588
|
-
val
|
|
544
|
+
else
|
|
545
|
+
val || DIR_DOCKER.find { |file| basepath(file).exist? }
|
|
589
546
|
end
|
|
547
|
+
@file ||= false
|
|
590
548
|
end
|
|
591
549
|
basepath((@file.is_a?(Array) ? @file.first : @file) || 'Dockerfile')
|
|
592
550
|
end
|
|
@@ -605,42 +563,35 @@ module Squared
|
|
|
605
563
|
session('docker', *cmd, main: false, options: false, **kwargs)
|
|
606
564
|
end
|
|
607
565
|
|
|
608
|
-
def append_command(flag, val, list, target: @session)
|
|
609
|
-
if
|
|
610
|
-
list << readline('Enter command [args]', force: true)
|
|
611
|
-
elsif (args = env('DOCKER_ARGS'))
|
|
566
|
+
def append_command(flag, val, list, target: @session, from: nil)
|
|
567
|
+
if (args = env('DOCKER_ARGS'))
|
|
612
568
|
list << args
|
|
613
569
|
end
|
|
614
570
|
case flag
|
|
615
571
|
when :run
|
|
616
572
|
unless session_arg?('name', target: target)
|
|
617
|
-
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))
|
|
618
579
|
end
|
|
619
580
|
when :exec
|
|
620
|
-
raise_error('no command args', hint:
|
|
581
|
+
raise_error('no command args', hint: from) if list.empty?
|
|
621
582
|
end
|
|
622
583
|
target << val << list.shift
|
|
623
584
|
target << list.join(' && ') unless list.empty?
|
|
624
585
|
end
|
|
625
586
|
|
|
626
|
-
def append_file(type, target: @session
|
|
627
|
-
return
|
|
587
|
+
def append_file(type, target: @session)
|
|
588
|
+
return unless type == 2 || type == 4 || @file.is_a?(Array)
|
|
628
589
|
|
|
629
|
-
|
|
630
|
-
case type
|
|
631
|
-
when 2, 4
|
|
632
|
-
return
|
|
633
|
-
when 3
|
|
634
|
-
return unless COMPOSEFILE.select { |val| basepath(val).exist? }.size > 1
|
|
635
|
-
end
|
|
636
|
-
end
|
|
637
|
-
files = Array(@file).map { |val| quote_option('file', basepath(val)) }
|
|
590
|
+
files = as_a(@file).map { |val| quote_option('file', path + val) }
|
|
638
591
|
if target.is_a?(Set)
|
|
639
|
-
|
|
640
|
-
target.clear
|
|
641
|
-
.merge(opts)
|
|
592
|
+
target.merge(files)
|
|
642
593
|
else
|
|
643
|
-
target.
|
|
594
|
+
target.concat(files)
|
|
644
595
|
end
|
|
645
596
|
end
|
|
646
597
|
|
|
@@ -652,18 +603,20 @@ module Squared
|
|
|
652
603
|
end
|
|
653
604
|
|
|
654
605
|
def append_tag(val, target: @session)
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
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
|
|
667
620
|
end
|
|
668
621
|
end
|
|
669
622
|
|
|
@@ -673,7 +626,7 @@ module Squared
|
|
|
673
626
|
index = 0
|
|
674
627
|
all = option('all', prefix: 'docker')
|
|
675
628
|
y = from == :'image:rm' && option('y', prefix: 'docker')
|
|
676
|
-
pat =
|
|
629
|
+
pat = /^(?:#{dnsname(name)}|#{tagname(project)}|#{tagmain.split(':', 2).first})(?:[_.,:-]|$)/
|
|
677
630
|
IO.popen(session_done(cmd << '--format=json')).each do |line|
|
|
678
631
|
data = JSON.parse(line)
|
|
679
632
|
id = data['ID']
|
|
@@ -710,7 +663,7 @@ module Squared
|
|
|
710
663
|
cols.each do |key|
|
|
711
664
|
next if (key == 'Tag' && !dd) || (key == 'Size' && data[key] == '0B')
|
|
712
665
|
|
|
713
|
-
puts "#{g + f} #{key}: #{
|
|
666
|
+
puts "#{g + f} #{key}: #{as_a(data[key]).join(', ')}" unless data[key].to_s.empty?
|
|
714
667
|
end
|
|
715
668
|
w = 9 + flag.to_s.size + 4 + ee.size
|
|
716
669
|
puts g + sub_style(ARG[:BORDER][6] + (ARG[:BORDER][1] * w), styles: theme[:inline])
|
|
@@ -722,10 +675,14 @@ module Squared
|
|
|
722
675
|
end
|
|
723
676
|
yield id
|
|
724
677
|
end
|
|
725
|
-
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
|
|
726
679
|
end
|
|
727
680
|
rescue StandardError => e
|
|
728
|
-
|
|
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?
|
|
729
686
|
end
|
|
730
687
|
|
|
731
688
|
def confirm_command(*args, title: nil, target: nil, as: nil)
|
|
@@ -782,7 +739,7 @@ module Squared
|
|
|
782
739
|
cmd = docker_output ctx
|
|
783
740
|
case flag
|
|
784
741
|
when :tag
|
|
785
|
-
args = tagjoin @registry, tag
|
|
742
|
+
args = tagjoin @registry, @tag
|
|
786
743
|
when :save
|
|
787
744
|
opts = "#{opts}.tar" unless opts.end_with?('.tar')
|
|
788
745
|
cmd << quote_option('output', File.expand_path(opts))
|
|
@@ -793,9 +750,13 @@ module Squared
|
|
|
793
750
|
else
|
|
794
751
|
cmd << opts << '--'
|
|
795
752
|
end
|
|
796
|
-
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)
|
|
797
758
|
cmd << args
|
|
798
|
-
print_success if success?(run(cmd)) && ctx.
|
|
759
|
+
print_success if success?(run(cmd)) && ctx.start_with?(/(?:network|tag|save)/)
|
|
799
760
|
end
|
|
800
761
|
end
|
|
801
762
|
|
|
@@ -805,7 +766,7 @@ module Squared
|
|
|
805
766
|
bake?(val) ? 1 : 2
|
|
806
767
|
when '.yml', '.yaml'
|
|
807
768
|
if compose?(val)
|
|
808
|
-
|
|
769
|
+
path.children.any? { |file| bake?(file) } ? 1 : 3
|
|
809
770
|
else
|
|
810
771
|
4
|
|
811
772
|
end
|
|
@@ -815,7 +776,7 @@ module Squared
|
|
|
815
776
|
end
|
|
816
777
|
|
|
817
778
|
def contextdir(val = nil)
|
|
818
|
-
val && projectpath?(val) ? shell_quote(
|
|
779
|
+
val && projectpath?(val) ? shell_quote(path + val) : '.'
|
|
819
780
|
end
|
|
820
781
|
|
|
821
782
|
def tagjoin(*args, char: '/')
|
|
@@ -825,9 +786,10 @@ module Squared
|
|
|
825
786
|
|
|
826
787
|
def tagname(val)
|
|
827
788
|
val = val.split(':').map! { |s| charname(s.sub(/^\W+/, '')) }
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
789
|
+
val.join(':').yield_self do |s|
|
|
790
|
+
s = val.first if val.size > 1 && s.size > 128
|
|
791
|
+
s[0..127]
|
|
792
|
+
end
|
|
831
793
|
end
|
|
832
794
|
|
|
833
795
|
def dnsname(val)
|
|
@@ -841,6 +803,14 @@ module Squared
|
|
|
841
803
|
def tagmain
|
|
842
804
|
tag.is_a?(Array) ? tag.first : tag
|
|
843
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
|
|
844
814
|
end
|
|
845
815
|
|
|
846
816
|
Application.implement Docker
|