docker_core 0.0.16 → 0.0.20

Sign up to get free protection for your applications and to get access to all the features.
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