docker_core 0.0.16 → 0.0.20

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.
Files changed (3) hide show
  1. checksums.yaml +4 -4
  2. data/lib/docker_core.rb +317 -198
  3. metadata +16 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: cbaa902624f73c386b5a294fdcc0a7dffff512dae884b08c8ee0dd6facc6de57
4
- data.tar.gz: 1a91928b1a48399cb184fb0dbd69ab9a8df936c30db2edb010c908f8aba29e60
3
+ metadata.gz: a39a514720435a65fbc3f039eee7c86503e501ab70b821656510b3ba8e8fe941
4
+ data.tar.gz: 7c95deb803d9b5a095a8cc2a5758e926000065e22aaac2a2420a896ef2be2c81
5
5
  SHA512:
6
- metadata.gz: f611c33f83c264638550cfd7e6ea965081b280bdf581e96bd195acf3cffec03d3dc7fd95ae1d10caaa6d435a65160e47af62c71dbd4e532ecca066c7e04932a2
7
- data.tar.gz: d4f35905d557fa37b672b732cd4e6d7fd76fb7208f22feb4a7fdf1a260cbb55fb77067558735eff67c5c07421b078f0f1ea1a1da2043566a0824a8d6d16e1f95
6
+ metadata.gz: e0929e952d6d9c3bca9f1d0e5ca3a5f5fa9f193c545bbd0e286361ef7811f54c624db153354664f32e74eef2d20ce36632380a84c343273a05c5e71c435bf968
7
+ data.tar.gz: 4e8ede2a599f2d820649d667f8b64e14d33227cd25abba7838b16202b1002633f4b363a91c7cf9dd709b99c036ff59210fb4deb76c8818946292a3a853c537fc
data/lib/docker_core.rb CHANGED
@@ -1,268 +1,387 @@
1
+ require('etc')
1
2
  require('fileutils')
2
3
  require('json')
3
4
  require('net/http')
4
5
  require('rubygems/package')
6
+ require('thor')
5
7
  require('zlib')
6
8
 
7
9
  module DockerCore
8
- COLOR_CODE = { error: 31, info: 32, warn: 33 }
9
- ARCH_SUFFIX = { x86: '386', x86_64: 'amd64', armhf: 'armv6', aarch64: 'arm64' }
10
-
11
- # @param [String] text
12
- # @param [Integer] code
13
- def self.color(text, code)
14
- escape = "\033"
15
- prefix = "#{escape}[#{code}m"
16
- suffix = "#{escape}[0m"
17
- return "#{prefix}#{text}#{suffix}"
18
- end
10
+ USER = 'core'
11
+ GROUP = 'core'
12
+
13
+ class Color < Thor::Shell::Color
14
+ # @param [String] text
15
+ # @param [Array<String>] colors
16
+ def self.echo(text, *colors)
17
+ if 0 == colors.size
18
+ return puts(text)
19
+ end
19
20
 
20
- # @param [String] text
21
- # @param [Integer] code
22
- def self.echo(text, code: self::COLOR_CODE[:info])
23
- puts(self.color(text, code))
24
- end
21
+ color = colors.map do |color|
22
+ if color.is_a?(Symbol)
23
+ next self.const_get(color.to_s.upcase)
24
+ end
25
25
 
26
- # @param [String] title
27
- # @param [Method] run
28
- # @param [Array] argumets
29
- def self.execute(title, run, *argumets)
30
- code = self::COLOR_CODE[:warn]
31
- self.echo("> #{title}", code: code)
32
- run.call(*argumets)
33
- self.echo("< #{title}", code: code)
34
- end
26
+ next "#{color}"
27
+ end.join
35
28
 
36
- # @param [String] command
37
- # @param [Boolean] force
38
- def self.run(command, force: false)
39
- begin
40
- self.echo("+ #{command}")
41
- print(`#{command}`)
42
- rescue
43
- raise unless force
29
+ return puts("#{color}#{text}#{self::CLEAR}")
44
30
  end
45
31
  end
46
32
 
47
- # @param [String] command
48
- # @param [Boolean] force
49
- def self.suexec(command, force: false)
50
- command = "su-exec core #{command}"
51
- self.run(command, force: force)
33
+ class Runner < Thor
52
34
  end
53
35
 
54
- # @param [Integer] uid
55
- # @param [Integer] gid
56
- def self.update_user(uid: 500, gid: 500)
57
- uid = ENV.fetch('DOCKER_CORE_UID', uid)
58
- gid = ENV.fetch('DOCKER_CORE_GID', gid)
59
- self.run('deluser core', force: true)
60
- self.run('delgroup core', force: true)
61
- self.run("addgroup --system --gid=#{gid} core")
62
- self.run("adduser --system --disabled-password --no-create-home --ingroup=core --gecos=core --shell=/bin/bash --uid=#{uid} core")
36
+ module Image
63
37
  end
64
38
 
65
- # @param [Array<String>] arguments
66
- def self.glob(*arguments)
67
- return Dir.glob(arguments.flatten, File::FNM_DOTMATCH).map do |item|
68
- File.path(item)
69
- end.filter do |item|
70
- false == %w[. ..].include?(File.basename(item))
71
- end.uniq
39
+ module Command
72
40
  end
73
41
 
74
- # @param [Array<String>] arguments
75
- def self.chown(*arguments)
76
- self.glob(*arguments).each do |path|
77
- FileUtils.chown_R('core', 'core', path, force: true)
42
+ module Paser
43
+ # @param [String] text
44
+ def self.boolean(text)
45
+ return %w[true yes on].include?("#{text}".strip.downcase)
78
46
  end
79
- end
80
47
 
81
- # @param [Array<String>] arguments
82
- def self.chmod(mode, *arguments)
83
- self.glob(*arguments).each do |path|
84
- FileUtils.chmod_R(mode, path, force: true)
48
+ # @param [String] text
49
+ def self.kebab(text)
50
+ return "#{text}".gsub(/_/, '-')
85
51
  end
86
- end
87
52
 
88
- # @param [Array<String>] arguments
89
- def self.mkdir(*arguments, mode: nil)
90
- stack = []
91
- paths = arguments.map { |path| File.path(path) }.uniq
53
+ # @param [Hash] hash
54
+ def self.options(hash)
55
+ items = []
56
+
57
+ if hash.is_a?(Hash)
58
+ hash.each do |key, value|
59
+ name = '--' + self.kebab(key)
60
+
61
+ if true == value
62
+ items << name
63
+ next
64
+ end
92
65
 
93
- paths.each do |path|
94
- until path == stack.last
95
- stack << path
96
- path = File.dirname(path)
66
+ value = "#{value}".gsub(/\\/, '\&\&').gsub('"', '\"')
67
+ items << %(#{name}="#{value}")
68
+ next
69
+ end
97
70
  end
71
+
72
+ return items
98
73
  end
99
74
 
100
- stack.uniq.each do |path|
101
- if File.exist?(path) && false == File.directory?(path)
102
- File.delete(path)
75
+ # @param [Array] items
76
+ def self.arguments(*items)
77
+ list = []
78
+
79
+ items.each do |item|
80
+ if item.is_a?(Array)
81
+ list.concat(item.map { |value| "#{value}" })
82
+ next
83
+ end
84
+
85
+ if item.is_a?(Hash)
86
+ list.concat(self.options(item))
87
+ next
88
+ end
89
+
90
+ list << "#{item}"
91
+ next
103
92
  end
104
- end
105
93
 
106
- FileUtils.mkdir_p(paths, mode: mode)
94
+ return list
95
+ end
107
96
  end
108
97
 
109
- # @param [Array<String>] arguments
110
- def self.rm(*arguments)
111
- self.glob(*arguments).each do |path|
112
- FileUtils.rm_rf(path)
98
+ module Process
99
+ # @param [Array] arguments
100
+ # @param [Boolean] substitute
101
+ def self.command(*arguments, substitute: false)
102
+ if substitute
103
+ arguments.unshift('su-exec', USER)
104
+ end
105
+
106
+ return Paser.arguments(*arguments).join(' ')
113
107
  end
114
- end
115
108
 
116
- # @param [String, Array<String>] source
117
- # @param [String] target
118
- def self.mv(source, target)
119
- source = [source].flatten
120
- FileUtils.mv(self.glob(*source), target)
121
- end
109
+ # @param [Array] arguments
110
+ # @param [Boolean] strip
111
+ # @param [Boolean] verbose
112
+ # @param [Boolean] substitute
113
+ def self.capture(*arguments, strip: true, verbose: false, substitute: false)
114
+ command = self.command(*arguments, substitute: substitute)
122
115
 
123
- # @param [String] value
124
- def self.to_boolean(value)
125
- return %w[true yes on].include?("#{value}".strip.downcase)
126
- end
116
+ if verbose
117
+ Color.echo("+ #{command}", Color::GREEN)
118
+ end
127
119
 
128
- # @param [String] stdout
129
- # @param [String] stderr
130
- def self.link_log(stdout: '', stderr: '')
131
- if '' != stdout
132
- File.symlink('/dev/stdout', File.path(stdout))
120
+ data = `#{command}`
121
+ return strip ? "#{data}".strip : data
133
122
  end
134
123
 
135
- if '' != stderr
136
- File.symlink('/dev/stderr', File.path(stderr))
124
+ # @param [Array] arguments
125
+ # @param [Boolean] force
126
+ # @param [Boolean] substitute
127
+ def self.run(*arguments, force: false, substitute: false)
128
+ begin
129
+ data = self.capture(*arguments, strip: false, verbose: true, substitute: substitute)
130
+ print(data)
131
+ rescue
132
+ raise unless force
133
+ end
137
134
  end
138
- end
139
135
 
140
- # @param [Array<String>] arguments
141
- def self.clear_path(*arguments, mode: nil)
142
- self.rm(*arguments)
143
- self.mkdir(*arguments, mode: mode)
144
- end
136
+ # @param [Array] arguments
137
+ # @param [Boolean] substitute
138
+ def self.execute(*arguments, substitute: false)
139
+ command = self.command(*arguments, substitute: substitute)
140
+ Color.echo("= #{command}", Color::CYAN)
141
+ exec(command)
142
+ end
145
143
 
146
- def self.arch_suffix
147
- arch = "#{`apk --print-arch`}".strip
148
- return ARCH_SUFFIX.fetch(arch.to_sym, arch)
149
- end
144
+ # @param [String] title
145
+ # @param [Method] delegate
146
+ # @param [Array] arguments
147
+ def self.invoke(title, delegate, *arguments)
148
+ color = Color::YELLOW
149
+ Color.echo("> #{title}", color)
150
+ delegate.call(*arguments)
151
+ Color.echo("< #{title}", color)
152
+ end
150
153
 
151
- # @param [String] repository
152
- def self.github_latest_version(repository)
153
- uri = URI("https://api.github.com/repos/#{repository}/releases/latest")
154
- return JSON.parse(Net::HTTP.get(uri))['tag_name']
155
154
  end
156
155
 
157
- # @param [String] uri
158
- # @param [Integer] max_redirect
159
- def self.uri_resolve(uri, max_redirect = 10)
160
- response = Net::HTTP.get_response(URI.parse(uri))
161
-
162
- if false == response.is_a?(Net::HTTPRedirection)
163
- return uri
156
+ module Shell
157
+ def self.architecture
158
+ hash = { x86: '386', x86_64: 'amd64', armhf: 'armv6', armv7l: 'armv7', aarch64: 'arm64' }
159
+ machine = "#{Etc.uname[:machine]}"
160
+ return hash.fetch(machine.to_sym, machine)
164
161
  end
165
162
 
166
- max_redirect = max_redirect - 1
167
-
168
- if 0 == max_redirect
169
- raise('maximum redirect reached')
163
+ # @param [Array<String>] arguments
164
+ # @return [Array<String>]
165
+ def self.find_paths(*arguments)
166
+ return Dir.glob(arguments.flatten, File::FNM_DOTMATCH).map do |item|
167
+ next File.path(item)
168
+ end.filter do |item|
169
+ next false == %w[. ..].include?(File.basename(item))
170
+ end.uniq
170
171
  end
171
172
 
172
- return self.uri_resolve(response['location'], max_redirect)
173
- end
173
+ # @param [Array<String>] arguments
174
+ # @param [String] user
175
+ # @param [String] group
176
+ def self.change_owner(*arguments, user: USER, group: GROUP)
177
+ self.find_paths(*arguments).each do |path|
178
+ FileUtils.chown_R(user, group, path, force: true)
179
+ end
180
+ end
174
181
 
175
- # @param [String] uri
176
- # @param [String] file
177
- def self.download_file(uri, file)
178
- uri = self.uri_resolve(uri)
179
- content = Net::HTTP.get(URI(uri))
180
- return File.binwrite(file, content)
181
- end
182
+ # @param [Array<String>] arguments
183
+ # @param [String, Integer] mode
184
+ def self.change_mode(mode, *arguments)
185
+ self.find_paths(*arguments).each do |path|
186
+ FileUtils.chmod_R(mode, path, force: true)
187
+ end
188
+ end
182
189
 
183
- # @param [String] path
184
- # @param [Boolean] verbose
185
- def self.untar(io, path, verbose: false)
186
- # @type [Gem::Package::TarReader] reader
187
- Gem::Package::TarReader.new(io) do |reader|
188
- reader.rewind
189
- reader.each do |entry|
190
- # @type [Gem::Package::TarHeader] header
191
- header = entry.header
192
- mode = header.mode
193
- file = File.join(path, entry.full_name)
194
-
195
- if verbose
196
- self.echo(": #{file}")
190
+ # @param [Array<String>] arguments
191
+ # @param [Integer, nil] mode
192
+ def self.make_folders(*arguments, mode: nil)
193
+ stack = []
194
+ paths = arguments.map do |path|
195
+ next File.path(path)
196
+ end.uniq
197
+
198
+ paths.each do |path|
199
+ until path == stack.last
200
+ stack << path
201
+ path = File.dirname(path)
197
202
  end
203
+ end
198
204
 
199
- if entry.directory?
200
- self.mkdir(file, mode: mode)
201
- next
205
+ stack.uniq.each do |path|
206
+ if File.exist?(path) && false == File.directory?(path)
207
+ File.delete(path)
202
208
  end
209
+ end
203
210
 
204
- if entry.file?
205
- self.mkdir(File.dirname(file))
206
- File.binwrite(file, entry.read)
207
- self.chmod(mode, file)
208
- next
209
- end
211
+ FileUtils.mkdir_p(paths, mode: mode)
212
+ end
213
+
214
+ # @param [Array<String>] arguments
215
+ def self.remove_paths(*arguments)
216
+ self.find_paths(*arguments).each do |path|
217
+ FileUtils.rm_rf(path)
210
218
  end
211
219
  end
212
- end
213
220
 
214
- # @param [String] file
215
- # @param [String] path
216
- # @param [Boolean] verbose
217
- def self.ungzip(file, path, verbose: false)
218
- # @type [Zlib::GzipReader] reader
219
- Zlib::GzipReader.open(file) do |reader|
220
- self.untar(reader, path, verbose: verbose)
221
+ # @param [String, Array<String>] source
222
+ # @param [String] target
223
+ def self.move_paths(source, target)
224
+ paths = [source].flatten
225
+ FileUtils.mv(self.find_paths(*paths), target)
221
226
  end
222
- end
223
227
 
224
- # @param [String] path
225
- # @param [Boolean] verbose
226
- def self.tar(path, verbose: false)
227
- io = StringIO.new('')
228
- offset = path.size + 1
229
-
230
- # @type [Gem::Package::TarWriter] writer
231
- Gem::Package::TarWriter.new(io) do |writer|
232
- # @type [String] file
233
- self.glob(File.join(path, '**/*')).each do |name|
234
- mode = File.stat(name).mode
235
- file = name.slice(offset ..)
236
-
237
- if verbose
238
- self.echo(": #{file}")
239
- end
228
+ # @param [String] uri
229
+ # @param [Integer] max_redirect
230
+ def self.resolve_link(uri, max_redirect = 10)
231
+ response = Net::HTTP.get_response(URI.parse(uri))
240
232
 
241
- if File.directory?(name)
242
- writer.mkdir(file, mode)
243
- next
233
+ if false == response.is_a?(Net::HTTPRedirection)
234
+ return uri
235
+ end
236
+
237
+ max_redirect = max_redirect - 1
238
+
239
+ if 0 == max_redirect
240
+ raise('maximum redirect reached')
241
+ end
242
+
243
+ return self.resolve_link(response['location'], max_redirect)
244
+ end
245
+
246
+ # @param [String] uri
247
+ # @param [String] file
248
+ def self.download_file(uri, file)
249
+ uri = self.resolve_link(uri)
250
+ content = Net::HTTP.get(URI(uri))
251
+ return File.binwrite(file, content)
252
+ end
253
+
254
+ # @param [Object] io
255
+ # @param [String] path
256
+ # @param [Boolean] verbose
257
+ def self.unpack_archive(io, path, verbose: false)
258
+ Gem::Package::TarReader.new(io) do
259
+
260
+ # @type [Gem::Package::TarReader] reader
261
+ |reader|
262
+ reader.rewind
263
+ reader.each do |entry|
264
+ # @type [Gem::Package::TarHeader] header
265
+ header = entry.header
266
+ mode = header.mode
267
+ file = File.join(path, entry.full_name)
268
+
269
+ if verbose
270
+ Color.echo(": #{file}", Color::GREEN)
271
+ end
272
+
273
+ if entry.directory?
274
+ self.make_folders(file, mode: mode)
275
+ next
276
+ end
277
+
278
+ if entry.file?
279
+ self.make_folders(File.dirname(file))
280
+ File.binwrite(file, entry.read)
281
+ self.change_mode(mode, file)
282
+ next
283
+ end
244
284
  end
285
+ end
286
+ end
287
+
288
+ # @param [String] file
289
+ # @param [String] path
290
+ # @param [Boolean] verbose
291
+ def self.inflate_file(file, path, verbose: false)
292
+ Zlib::GzipReader.open(file) do
293
+
294
+ # @type [Zlib::GzipReader] reader
295
+ |reader|
296
+ self.unpack_archive(reader, path, verbose: verbose)
297
+ end
298
+ end
299
+
300
+ # @param [String] path
301
+ # @param [Boolean] verbose
302
+ def self.tape_archive(path, verbose: false)
303
+ io = StringIO.new('')
304
+ offset = path.size + 1
305
+
306
+ Gem::Package::TarWriter.new(io) do
245
307
 
246
- if File.file?(name)
247
- writer.add_file(file, mode) do |stream|
248
- stream.write(File.binread(name))
308
+ # @type [Gem::Package::TarWriter] writer
309
+ |writer|
310
+ self.find_paths(File.join(path, '**/*')).each do |name|
311
+ mode = File.stat(name).mode
312
+ file = name.slice(offset ..)
313
+
314
+ if verbose
315
+ Color.echo(": #{file}", Color::GREEN)
316
+ end
317
+
318
+ if File.directory?(name)
319
+ writer.mkdir(file, mode)
320
+ next
321
+ end
322
+
323
+ if File.file?(name)
324
+ writer.add_file(file, mode) do |stream|
325
+ stream.write(File.binread(name))
326
+ end
327
+ next
249
328
  end
250
- next
251
329
  end
252
330
  end
331
+
332
+ io.rewind
333
+ return io.string
253
334
  end
254
335
 
255
- io.rewind
256
- return io.string
257
- end
336
+ # @param [String] file
337
+ # @param [String] path
338
+ # @param [Boolean] verbose
339
+ def self.deflate_file(file, path, verbose: false)
340
+ Zlib::GzipWriter.open(file, Zlib::BEST_COMPRESSION) do
341
+
342
+ # @type [Zlib::GzipWriter] writer
343
+ |writer|
344
+ writer.write(self.tape_archive(path, verbose: verbose))
345
+ end
346
+ end
347
+
348
+ # @param [Integer] uid
349
+ # @param [Integer] gid
350
+ def self.update_user(uid: 500, gid: 500)
351
+ uid = ENV.fetch('DOCKER_CORE_UID', uid)
352
+ gid = ENV.fetch('DOCKER_CORE_GID', gid)
353
+ Process.run('deluser', USER, force: true)
354
+ Process.run('delgroup', GROUP, force: true)
355
+ Process.run('addgroup', { system: true, gid: gid }, GROUP)
356
+ Process.run('adduser', { system: true, 'disabled-password': true, 'no-create-home': true, ingroup: GROUP, gecos: USER, shell: '/bin/bash', uid: uid }, USER)
357
+ end
358
+
359
+ # @param [String] stdout
360
+ # @param [String] stderr
361
+ def self.link_logs(stdout: '', stderr: '')
362
+ if '' != stdout
363
+ File.symlink('/dev/stdout', File.path(stdout))
364
+ end
365
+
366
+ if '' != stderr
367
+ File.symlink('/dev/stderr', File.path(stderr))
368
+ end
369
+
370
+ return
371
+ end
372
+
373
+ # @param [Array<String>] arguments
374
+ # @param [Integer ,nil] mode
375
+ def self.clear_folders(*arguments, mode: nil)
376
+ self.remove_paths(*arguments)
377
+ self.make_folders(*arguments, mode: mode)
378
+ end
258
379
 
259
- # @param [String] file
260
- # @param [String] path
261
- # @param [Boolean] verbose
262
- def self.gzip(file, path, verbose: false)
263
- # @type [Zlib::GzipWriter] writer
264
- Zlib::GzipWriter.open(file, Zlib::BEST_COMPRESSION) do |writer|
265
- writer.write(self.tar(path, verbose: verbose))
380
+ # @param [String] repository
381
+ def self.github_latest_version(repository)
382
+ uri = URI("https://api.github.com/repos/#{repository}/releases/latest")
383
+ data = JSON.parse(Net::HTTP.get(uri))['tag_name']
384
+ return "#{data}"
266
385
  end
267
386
  end
268
387
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: docker_core
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.16
4
+ version: 0.0.20
5
5
  platform: ruby
6
6
  authors:
7
7
  - agrozyme
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-07-13 00:00:00.000000000 Z
11
+ date: 2021-08-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: fileutils
@@ -38,6 +38,20 @@ dependencies:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
40
  version: '2'
41
+ - !ruby/object:Gem::Dependency
42
+ name: thor
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '1'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '1'
41
55
  - !ruby/object:Gem::Dependency
42
56
  name: zlib
43
57
  requirement: !ruby/object:Gem::Requirement