docker-template 0.1.2 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Rakefile +39 -2
- data/bin/docker-template +3 -5
- data/lib/docker/template.rb +19 -7
- data/lib/docker/template/alias.rb +1 -1
- data/lib/docker/template/ansi.rb +27 -17
- data/lib/docker/template/auth.rb +3 -3
- data/lib/docker/template/common.rb +14 -10
- data/lib/docker/template/config.rb +14 -18
- data/lib/docker/template/interface.rb +8 -9
- data/lib/docker/template/metadata.rb +33 -29
- data/lib/docker/template/parser.rb +10 -9
- data/lib/docker/template/patches/hash.rb +11 -16
- data/lib/docker/template/patches/pathname.rb +3 -3
- data/lib/docker/template/repo.rb +22 -28
- data/lib/docker/template/scratch.rb +3 -6
- data/lib/docker/template/simple.rb +3 -5
- data/lib/docker/template/stream.rb +5 -4
- data/lib/docker/template/util.rb +23 -8
- data/lib/docker/template/util/copy.rb +8 -13
- data/lib/docker/template/util/data.rb +1 -1
- data/lib/docker/template/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a041995698dcbe6253e4c997a940e1e7eb492e4b
|
4
|
+
data.tar.gz: 39b3a79d100a7ddb4f75d7352b1dac9db157ee94
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1e2949a9cd7ce54000508599cd1c31b07dbdbf654596b3d6984977f2bfa75cc7932bb1a6cd097af97f77122fd5434f150f00b10011cf689edb35455013fd69e8
|
7
|
+
data.tar.gz: e2997be78cc2d37d48cd7ef3184b6481992fcc6befc0d595835d396d7935230e852a76128b933f55aeaa618b1fa31fbf5e16b3416fecd01d325cfbe0ec38e888
|
data/Rakefile
CHANGED
@@ -2,8 +2,11 @@
|
|
2
2
|
# Copyright: 2015 Jordon Bedwell - Apache v2.0 License
|
3
3
|
# Encoding: utf-8
|
4
4
|
|
5
|
-
|
5
|
+
$LOAD_PATH.unshift(File.expand_path("../lib", __FILE__))
|
6
|
+
require "docker/template/ansi"
|
6
7
|
require "rspec/core/rake_task"
|
8
|
+
require "open3"
|
9
|
+
|
7
10
|
task :default => [:spec]
|
8
11
|
RSpec::Core::RakeTask.new :spec
|
9
12
|
task :test => :spec
|
@@ -15,6 +18,40 @@ task :build do
|
|
15
18
|
end
|
16
19
|
|
17
20
|
task :pry do
|
18
|
-
|
21
|
+
sh "bundle", "exec", "pry", "-Ilib/", \
|
19
22
|
"-rdocker/template"
|
20
23
|
end
|
24
|
+
|
25
|
+
task :analysis do
|
26
|
+
ansi = Docker::Template::Ansi
|
27
|
+
cmd = [
|
28
|
+
"docker", "run", "--rm", "--env=CODE_PATH=#{Dir.pwd}", \
|
29
|
+
"--volume=#{Dir.pwd}:/code", "--volume=/var/run/docker.sock:/var/run/docker.sock", \
|
30
|
+
"--volume=/tmp/cc:/tmp/cc", "-i", "codeclimate/codeclimate", "analyze"
|
31
|
+
]
|
32
|
+
|
33
|
+
file = File.open(".analysis", "w+")
|
34
|
+
Open3.popen3(cmd.shelljoin) do |_, out, err, _|
|
35
|
+
while data = out.gets
|
36
|
+
file.write data
|
37
|
+
if data =~ /\A==/
|
38
|
+
$stdout.print ansi.yellow(data)
|
39
|
+
|
40
|
+
elsif data !~ %r!\A[0-9\-]+!
|
41
|
+
$stdout.puts data
|
42
|
+
|
43
|
+
else
|
44
|
+
h, d = data.split(":", 2)
|
45
|
+
$stdout.print ansi.cyan(h)
|
46
|
+
$stdout.print ":", d
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
while data = err.gets
|
51
|
+
file.write data
|
52
|
+
$stderr.print ansi.red(data)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
file.close
|
57
|
+
end
|
data/bin/docker-template
CHANGED
@@ -3,9 +3,7 @@
|
|
3
3
|
# Copyright: 2015 Jordon Bedwell - Apache v2.0 License
|
4
4
|
# Encoding: utf-8
|
5
5
|
|
6
|
-
|
7
|
-
"../lib", __dir__
|
8
|
-
))
|
6
|
+
$LOAD_PATH.unshift(File.expand_path("../lib", __dir__))
|
9
7
|
|
10
8
|
trap :SIGINT do
|
11
9
|
$stderr.puts "\nApparently that's all for now."
|
@@ -20,5 +18,5 @@ rescue LoadError
|
|
20
18
|
require "docker/template"
|
21
19
|
end
|
22
20
|
|
23
|
-
Docker::Template::Interface
|
24
|
-
start($
|
21
|
+
Docker::Template::Interface \
|
22
|
+
.start($PROGRAM_NAME)
|
data/lib/docker/template.rb
CHANGED
@@ -12,7 +12,9 @@ require "erb"
|
|
12
12
|
require "set"
|
13
13
|
|
14
14
|
module Docker
|
15
|
-
module Template
|
15
|
+
module Template
|
16
|
+
module_function
|
17
|
+
|
16
18
|
autoload :Util, "docker/template/util"
|
17
19
|
autoload :Config, "docker/template/config"
|
18
20
|
autoload :Ansi, "docker/template/ansi"
|
@@ -31,8 +33,12 @@ module Docker
|
|
31
33
|
autoload :Alias, "docker/template/alias"
|
32
34
|
autoload :Auth, "docker/template/auth"
|
33
35
|
|
36
|
+
def repo_is_root?
|
37
|
+
root.join("copy").exist? && !root.join("../..", config["repos_dir"]).exist?
|
38
|
+
end
|
39
|
+
|
34
40
|
def config
|
35
|
-
|
41
|
+
@config ||= begin
|
36
42
|
Config.new
|
37
43
|
end
|
38
44
|
end
|
@@ -40,7 +46,7 @@ module Docker
|
|
40
46
|
#
|
41
47
|
|
42
48
|
def root
|
43
|
-
|
49
|
+
@root ||= begin
|
44
50
|
Pathname.new(Dir.pwd)
|
45
51
|
end
|
46
52
|
end
|
@@ -51,17 +57,23 @@ module Docker
|
|
51
57
|
# guarantees that an absolute path will work.
|
52
58
|
|
53
59
|
def repos_root
|
54
|
-
|
60
|
+
@repos_root ||= begin
|
55
61
|
root.join(config["repos_dir"])
|
56
62
|
end
|
57
63
|
end
|
58
64
|
|
65
|
+
#
|
66
|
+
|
67
|
+
def repo_root_for(name)
|
68
|
+
repo_is_root?? root : repos_root.join(name)
|
69
|
+
end
|
70
|
+
|
59
71
|
# Provides the root to Docker template, wherever it is installed so that
|
60
|
-
# we can do things, mostly ignore files for the profiler.
|
72
|
+
# we can do things, mostly ignore files for the profiler. Otherwise it's
|
61
73
|
# not really used, it's just an encapsulator.
|
62
74
|
|
63
75
|
def gem_root
|
64
|
-
|
76
|
+
@gem_root ||= begin
|
65
77
|
path = File.expand_path("../../", __dir__)
|
66
78
|
Pathname.new(path)
|
67
79
|
end
|
@@ -71,7 +83,7 @@ module Docker
|
|
71
83
|
# from our templates and use it if you wish to.
|
72
84
|
|
73
85
|
def template_root
|
74
|
-
|
86
|
+
@template_root ||= begin
|
75
87
|
gem_root.join("lib/docker/template/templates")
|
76
88
|
end
|
77
89
|
end
|
data/lib/docker/template/ansi.rb
CHANGED
@@ -4,18 +4,28 @@
|
|
4
4
|
|
5
5
|
module Docker
|
6
6
|
module Template
|
7
|
-
module Ansi
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
7
|
+
module Ansi
|
8
|
+
module_function
|
9
|
+
|
10
|
+
ESCAPE = format("%c", 27)
|
11
|
+
MATCH = /#{ESCAPE}\[(?:\d+)(?:;\d+)*(j|k|m|s|u|A|B|G)|\e\(B\e\[m/ix.freeze
|
12
|
+
COLORS = {
|
13
|
+
:red => 31,
|
14
|
+
:green => 32,
|
15
|
+
:black => 30,
|
16
|
+
:magenta => 35,
|
17
|
+
:yellow => 33,
|
18
|
+
:white => 37,
|
19
|
+
:blue => 34,
|
20
|
+
:cyan => 36
|
21
|
+
}
|
12
22
|
|
13
23
|
# Strip ANSI from the current string. It also strips cursor stuff,
|
14
24
|
# well some of it, and it also strips some other stuff that a lot of
|
15
25
|
# the other ANSI strippers don't.
|
16
26
|
|
17
27
|
def strip(str)
|
18
|
-
str.gsub
|
28
|
+
str.gsub MATCH, ""
|
19
29
|
end
|
20
30
|
|
21
31
|
# Reset the vterm view if it's supported. Depending on how badly
|
@@ -23,24 +33,24 @@ module Docker
|
|
23
33
|
# with a few empty lines added on the top.
|
24
34
|
|
25
35
|
def clear
|
26
|
-
$stdout.print("%c[H%c[2J"
|
36
|
+
$stdout.print(format("%c[H%c[2J", 27, 27))
|
27
37
|
end
|
28
38
|
|
29
39
|
#
|
30
40
|
|
31
41
|
def has?(str)
|
32
|
-
!!(str =~
|
42
|
+
!!(str =~ MATCH)
|
33
43
|
end
|
34
44
|
|
35
45
|
# Jump the cursor up and then back down or just up and down. This is
|
36
46
|
# useful when streaming async downloads from something like Docker. It
|
37
47
|
# also works better than using `tput`
|
38
48
|
|
39
|
-
def jump(str = "", up: nil, down: nil, both: nil
|
40
|
-
str = clear_line(str)
|
49
|
+
def jump(str = "", up: nil, down: nil, both: nil)
|
50
|
+
str = clear_line(str)
|
41
51
|
|
42
|
-
return "%c[%dA%s%c[%dB"
|
43
|
-
up ? "%c[%dA%s"
|
52
|
+
return format("%c[%dA%s%c[%dB", 27, up || both, str, 27, down || both) if (up && down) || both
|
53
|
+
up ? format("%c[%dA%s", 27, up, str) : format("%s%c[%dB", str, 27, down)
|
44
54
|
end
|
45
55
|
|
46
56
|
# Reset the color back to the default color so that you do not leak any
|
@@ -48,26 +58,26 @@ module Docker
|
|
48
58
|
# used as part of a wrapper so that we don't leak colors.
|
49
59
|
|
50
60
|
def reset(str = "")
|
51
|
-
@ansi_reset ||= "%c[0m"
|
61
|
+
@ansi_reset ||= format("%c[0m", 27)
|
52
62
|
"#{@ansi_reset}#{str}"
|
53
63
|
end
|
54
64
|
|
55
65
|
#
|
56
66
|
|
57
67
|
def clear_line(str = "")
|
58
|
-
@ansi_clear_line ||= "%c[2K\r"
|
68
|
+
@ansi_clear_line ||= format("%c[2K\r", 27)
|
59
69
|
"#{@ansi_clear_line}#{str}\r"
|
60
70
|
end
|
61
71
|
|
62
|
-
# SEE: `self::
|
72
|
+
# SEE: `self::COLORS` for a list of methods. They are mostly
|
63
73
|
# standard base colors supported by pretty much any xterm-color, we do
|
64
74
|
# not need more than the base colors so we do not include them.
|
65
75
|
# Actually... if I'm honest we don't even need most of the
|
66
76
|
# base colors.
|
67
77
|
|
68
|
-
|
78
|
+
COLORS.each do |color, num|
|
69
79
|
define_method color do |str|
|
70
|
-
"#{"%c"
|
80
|
+
"#{format("%c", 27)}[#{num}m#{str}#{reset}"
|
71
81
|
end; module_function color
|
72
82
|
end
|
73
83
|
end
|
data/lib/docker/template/auth.rb
CHANGED
@@ -4,7 +4,7 @@ module Docker
|
|
4
4
|
module_function
|
5
5
|
|
6
6
|
def auth!
|
7
|
-
return unless login =
|
7
|
+
return unless login = credentials
|
8
8
|
login["auths"].each do |server, auth|
|
9
9
|
username, password = Base64.decode64(auth["auth"]).split(":", 2)
|
10
10
|
Docker.authenticate!({
|
@@ -16,9 +16,9 @@ module Docker
|
|
16
16
|
end
|
17
17
|
end
|
18
18
|
|
19
|
-
def
|
19
|
+
def credentials
|
20
20
|
path = Pathname.new("~/.docker/config.json").expand_path
|
21
|
-
|
21
|
+
JSON.parse(path.read) if path.exist?
|
22
22
|
end
|
23
23
|
end
|
24
24
|
end
|
@@ -35,9 +35,9 @@ module Docker
|
|
35
35
|
|
36
36
|
def parent_repo
|
37
37
|
return false unless aliased?
|
38
|
-
@parent_repo ||=
|
39
|
-
"tag" => @repo.aliased
|
40
|
-
|
38
|
+
@parent_repo ||= begin
|
39
|
+
Repo.new(@repo.to_h.merge("tag" => @repo.aliased))
|
40
|
+
end
|
41
41
|
end
|
42
42
|
|
43
43
|
#
|
@@ -58,14 +58,8 @@ module Docker
|
|
58
58
|
|
59
59
|
Ansi.clear
|
60
60
|
Util.notify_build(@repo, rootfs: rootfs?)
|
61
|
-
logger = Stream.new.method(:log)
|
62
61
|
copy_build_and_verify
|
63
|
-
|
64
|
-
Dir.chdir(@context) do
|
65
|
-
@img = Docker::Image.build_from_dir(".", &logger)
|
66
|
-
@img.tag rootfs?? @repo.to_rootfs_h : @repo.to_tag_h
|
67
|
-
push
|
68
|
-
end
|
62
|
+
chdir_build
|
69
63
|
rescue SystemExit => exit_
|
70
64
|
unlink img: true
|
71
65
|
raise exit_
|
@@ -77,6 +71,16 @@ module Docker
|
|
77
71
|
|
78
72
|
#
|
79
73
|
|
74
|
+
def chdir_build
|
75
|
+
Dir.chdir(@context) do
|
76
|
+
@img = Docker::Image.build_from_dir(".", &Stream.new.method(:log))
|
77
|
+
@img.tag rootfs?? @repo.to_rootfs_h : @repo.to_tag_h
|
78
|
+
push
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
#
|
83
|
+
|
80
84
|
private
|
81
85
|
def copy_build_and_verify
|
82
86
|
unless respond_to?(:setup_context, true)
|
@@ -18,11 +18,13 @@ module Docker
|
|
18
18
|
def_delegator :@config, :keys
|
19
19
|
def_delegator :@config, :to_h
|
20
20
|
def_delegator :@config, :to_enum
|
21
|
+
def_delegator :@config, :key?, :has_default?
|
21
22
|
def_delegator :@config, :has_key?
|
23
|
+
def_delegator :@config, :key?
|
22
24
|
def_delegator :@config, :each
|
23
25
|
def_delegator :@config, :[]
|
24
26
|
|
25
|
-
|
27
|
+
DEFAULTS = {
|
26
28
|
"type" => "simple",
|
27
29
|
"user" => "envygeeks",
|
28
30
|
"local_prefix" => "local",
|
@@ -33,24 +35,24 @@ module Docker
|
|
33
35
|
"copy_dir" => "copy",
|
34
36
|
"tag" => "latest",
|
35
37
|
|
36
|
-
"
|
37
|
-
|
38
|
-
"entries"
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
38
|
+
"env" => { "tag" => {}, "type" => {}, "all" => nil },
|
39
|
+
"pkgs" => { "tag" => {}, "type" => {}, "all" => nil },
|
40
|
+
"entries" => { "tag" => {}, "type" => {}, "all" => nil },
|
41
|
+
"releases" => { "tag" => {}, "type" => {}, "all" => nil },
|
42
|
+
"versions" => { "tag" => {}, "type" => {}, "all" => nil },
|
43
|
+
"aliases" => {},
|
44
|
+
"tags" => {}
|
43
45
|
}.freeze
|
44
46
|
|
45
|
-
|
47
|
+
EMPTY_DEFAULTS = {
|
46
48
|
"tags" => { "latest" => "normal" }
|
47
49
|
}
|
48
50
|
|
49
51
|
#
|
50
52
|
|
51
53
|
def initialize
|
52
|
-
@config =
|
53
|
-
@config = @config.merge(
|
54
|
+
@config = DEFAULTS.deep_merge(read_config_from)
|
55
|
+
@config = @config.merge(EMPTY_DEFAULTS) do |_, oval, nval|
|
54
56
|
oval.nil? || oval.empty?? nval : oval
|
55
57
|
end
|
56
58
|
|
@@ -70,14 +72,8 @@ module Docker
|
|
70
72
|
|
71
73
|
#
|
72
74
|
|
73
|
-
def has_default?(key)
|
74
|
-
return @config.has_key?(key)
|
75
|
-
end
|
76
|
-
|
77
|
-
#
|
78
|
-
|
79
75
|
def build_types
|
80
|
-
|
76
|
+
@build_types ||= %W(simple scratch).freeze
|
81
77
|
end
|
82
78
|
end
|
83
79
|
end
|
@@ -32,12 +32,11 @@ module Docker
|
|
32
32
|
|
33
33
|
private
|
34
34
|
def sync
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
end
|
35
|
+
return unless wants_sync?
|
36
|
+
Parser.new.parse.each do |repo|
|
37
|
+
next unless repo.syncable?
|
38
|
+
repo.builder.tap(&:sync) \
|
39
|
+
.unlink(sync: false)
|
41
40
|
end
|
42
41
|
end
|
43
42
|
|
@@ -45,7 +44,7 @@ module Docker
|
|
45
44
|
|
46
45
|
private
|
47
46
|
def argv_without_flags
|
48
|
-
|
47
|
+
@argv.select do |val|
|
49
48
|
!["--sync", "--push"].include?(val)
|
50
49
|
end
|
51
50
|
end
|
@@ -81,9 +80,9 @@ module Docker
|
|
81
80
|
|
82
81
|
private
|
83
82
|
def self.discover
|
84
|
-
rtn = bins.
|
83
|
+
rtn = bins.find do |path|
|
85
84
|
path.basename.fnmatch?("docker") && path.executable_real?
|
86
|
-
end
|
85
|
+
end
|
87
86
|
|
88
87
|
if rtn
|
89
88
|
rtn.to_s
|
@@ -10,12 +10,12 @@ module Docker
|
|
10
10
|
# Provides aliases for the root element so you can do something like:
|
11
11
|
# * data["release"].fallback
|
12
12
|
|
13
|
-
|
14
|
-
|
13
|
+
ALIASES = {
|
14
|
+
"entry" => "entries",
|
15
15
|
"release" => "releases",
|
16
16
|
"version" => "versions",
|
17
|
-
|
18
|
-
|
17
|
+
"script" => "scripts",
|
18
|
+
"image" => "images"
|
19
19
|
}
|
20
20
|
|
21
21
|
def_delegator :@metadata, :keys
|
@@ -26,6 +26,7 @@ module Docker
|
|
26
26
|
def_delegator :@metadata, :delete
|
27
27
|
def_delegator :@metadata, :each
|
28
28
|
def_delegator :@metadata, :to_h
|
29
|
+
def_delegator :@metadata, :key?
|
29
30
|
route_to_ivar :is_root, :@is_root, bool: true
|
30
31
|
route_to_hash :for_all, :self, :all
|
31
32
|
|
@@ -34,22 +35,24 @@ module Docker
|
|
34
35
|
@root_metadata = root_metadata || {}
|
35
36
|
@metadata = metadata || {}
|
36
37
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
38
|
+
return unless is_root?
|
39
|
+
@root_metadata = @metadata
|
40
|
+
@base = Template.config
|
41
|
+
end
|
42
|
+
|
43
|
+
#
|
44
|
+
|
45
|
+
def as_gem_version
|
46
|
+
"#{self["repo"]}@#{self["version"].fallback}"
|
41
47
|
end
|
42
48
|
|
43
49
|
#
|
44
50
|
|
45
51
|
def aliased
|
46
|
-
aliases = from_root("aliases")
|
47
52
|
tag = from_root("tag")
|
48
|
-
|
49
|
-
if aliases.
|
50
|
-
|
51
|
-
end
|
52
|
-
tag
|
53
|
+
aliases = from_root("aliases")
|
54
|
+
return aliases[tag] if aliases.key?(tag)
|
55
|
+
tag
|
53
56
|
end
|
54
57
|
|
55
58
|
# Queries providing a default value if on the root repo hash otherwise
|
@@ -72,8 +75,8 @@ module Docker
|
|
72
75
|
|
73
76
|
#
|
74
77
|
|
75
|
-
def merge(
|
76
|
-
@metadata.merge!(
|
78
|
+
def merge(new_)
|
79
|
+
@metadata.merge!(new_)
|
77
80
|
self
|
78
81
|
end
|
79
82
|
|
@@ -86,18 +89,19 @@ module Docker
|
|
86
89
|
#
|
87
90
|
|
88
91
|
def as_hash
|
89
|
-
{}
|
90
|
-
|
91
|
-
|
92
|
+
{} \
|
93
|
+
.merge(for_all.to_h) \
|
94
|
+
.merge(by_type.to_h) \
|
95
|
+
.merge(by_tag. to_h)
|
92
96
|
end
|
93
97
|
|
94
98
|
#
|
95
99
|
|
96
100
|
def as_set
|
97
|
-
Set.new
|
98
|
-
merge(for_all.to_a)
|
99
|
-
merge(by_type.to_a)
|
100
|
-
merge(by_tag .to_a)
|
101
|
+
Set.new \
|
102
|
+
.merge(for_all.to_a) \
|
103
|
+
.merge(by_type.to_a) \
|
104
|
+
.merge(by_tag .to_a)
|
101
105
|
end
|
102
106
|
|
103
107
|
#
|
@@ -118,7 +122,7 @@ module Docker
|
|
118
122
|
|
119
123
|
def by_tag
|
120
124
|
return unless tag = aliased
|
121
|
-
return unless
|
125
|
+
return unless key?("tag")
|
122
126
|
hash = self["tag"]
|
123
127
|
hash[tag]
|
124
128
|
end
|
@@ -129,8 +133,8 @@ module Docker
|
|
129
133
|
|
130
134
|
def by_type
|
131
135
|
return unless tag = aliased
|
132
|
-
type =
|
133
|
-
return unless
|
136
|
+
type = from_root("tags")[tag]
|
137
|
+
return unless key?("type")
|
134
138
|
return unless type
|
135
139
|
|
136
140
|
hash = self["type"]
|
@@ -141,10 +145,10 @@ module Docker
|
|
141
145
|
|
142
146
|
private
|
143
147
|
def determine_key(key)
|
144
|
-
if is_root? && !
|
145
|
-
key =
|
148
|
+
if is_root? && !key?(key) && ALIASES.key?(key)
|
149
|
+
key = ALIASES[key]
|
146
150
|
end
|
147
|
-
|
151
|
+
key
|
148
152
|
end
|
149
153
|
|
150
154
|
#
|
@@ -5,9 +5,9 @@
|
|
5
5
|
module Docker
|
6
6
|
module Template
|
7
7
|
class Parser
|
8
|
-
|
9
|
-
|
10
|
-
|
8
|
+
SLASH_REGEXP = /\//.freeze
|
9
|
+
SPLIT_REGEXP = /:|\//.freeze
|
10
|
+
COLON_REGEXP = /:/.freeze
|
11
11
|
|
12
12
|
def initialize(argv = [].freeze)
|
13
13
|
@argv = argv.freeze
|
@@ -19,7 +19,7 @@ module Docker
|
|
19
19
|
|
20
20
|
def all
|
21
21
|
return @argv unless @argv.empty?
|
22
|
-
|
22
|
+
Template.repos_root.children.map do |path|
|
23
23
|
path.basename.to_s
|
24
24
|
end
|
25
25
|
rescue Errno::ENOENT
|
@@ -34,22 +34,24 @@ module Docker
|
|
34
34
|
raise Docker::Template::Error::BadRepoName, val if hash.empty?
|
35
35
|
out += as == :repos ? Repo.new(hash).to_repos : [hash]
|
36
36
|
end
|
37
|
-
|
37
|
+
out
|
38
38
|
end
|
39
39
|
|
40
40
|
#
|
41
41
|
|
42
42
|
private
|
43
43
|
def build_repo_hash(val)
|
44
|
-
data
|
44
|
+
data = val.split(SPLIT_REGEXP)
|
45
|
+
hsh = {}
|
46
|
+
|
45
47
|
if data.size == 1
|
46
48
|
hsh["repo"] = data[0]
|
47
49
|
|
48
|
-
elsif val =~
|
50
|
+
elsif val =~ COLON_REGEXP && data.size == 2
|
49
51
|
hsh["repo"] = data[0]
|
50
52
|
hsh[ "tag"] = data[1]
|
51
53
|
|
52
|
-
elsif val =~
|
54
|
+
elsif val =~ SLASH_REGEXP && data.size == 2
|
53
55
|
hsh["user"] = data[0]
|
54
56
|
hsh["repo"] = data[1]
|
55
57
|
|
@@ -58,7 +60,6 @@ module Docker
|
|
58
60
|
hsh["repo"] = data[1]
|
59
61
|
hsh[ "tag"] = data[2]
|
60
62
|
end
|
61
|
-
|
62
63
|
hsh
|
63
64
|
end
|
64
65
|
end
|
@@ -4,18 +4,17 @@
|
|
4
4
|
|
5
5
|
class Hash
|
6
6
|
def to_env
|
7
|
-
|
7
|
+
each_with_object({}) do |(key, val), hsh|
|
8
8
|
val = val.is_a?(Array) ? val.join(" ") : val.to_s
|
9
9
|
key = key.to_s.upcase
|
10
10
|
hsh[key] = val
|
11
|
-
hsh
|
12
11
|
end
|
13
12
|
end
|
14
13
|
|
15
14
|
#
|
16
15
|
|
17
16
|
def any_keys?(*keys)
|
18
|
-
keys.map(&method(:
|
17
|
+
keys.map(&method(:key?)).any? do |val|
|
19
18
|
val == true
|
20
19
|
end
|
21
20
|
end
|
@@ -23,32 +22,31 @@ class Hash
|
|
23
22
|
#
|
24
23
|
|
25
24
|
def leftover_keys?(*keys)
|
26
|
-
|
25
|
+
(self.keys - keys).any?
|
27
26
|
end
|
28
27
|
|
29
28
|
#
|
30
29
|
|
31
|
-
def
|
30
|
+
def keys?(*keys)
|
32
31
|
return false unless rtn = true && any?
|
33
32
|
while rtn && key = keys.shift
|
34
|
-
rtn =
|
33
|
+
rtn = key?(key) || false
|
35
34
|
end
|
36
|
-
|
37
|
-
rtn
|
35
|
+
rtn
|
38
36
|
end
|
39
37
|
|
40
38
|
#
|
41
39
|
|
42
40
|
def to_env_ary
|
43
|
-
|
44
|
-
|
41
|
+
each_with_object([]) do |(key, val), ary|
|
42
|
+
ary << "#{key}=#{val}"
|
45
43
|
end
|
46
44
|
end
|
47
45
|
|
48
46
|
#
|
49
47
|
|
50
48
|
def deep_merge(newh)
|
51
|
-
merge(newh) do |
|
49
|
+
merge(newh) do |_, oval, nval|
|
52
50
|
if oval.is_a?(self.class) && nval.is_a?(self.class)
|
53
51
|
then oval.deep_merge(nval) else nval
|
54
52
|
end
|
@@ -58,19 +56,16 @@ class Hash
|
|
58
56
|
#
|
59
57
|
|
60
58
|
def stringify
|
61
|
-
|
59
|
+
each_with_object({}) do |(key, val), hsh|
|
62
60
|
hsh[key.to_s] = val.is_a?(Array) || val.is_a?(Hash) ? val.stringify : val.to_s
|
63
|
-
hsh
|
64
61
|
end
|
65
62
|
end
|
66
63
|
|
67
64
|
#
|
68
65
|
|
69
66
|
def stringify_keys
|
70
|
-
|
67
|
+
each_with_object({}) do |(key, val), hsh|
|
71
68
|
hsh[key.to_s] = val
|
72
|
-
|
73
|
-
hsh
|
74
69
|
end
|
75
70
|
end
|
76
71
|
end
|
@@ -11,7 +11,7 @@ class Pathname
|
|
11
11
|
#
|
12
12
|
|
13
13
|
def write(data)
|
14
|
-
File.write(
|
14
|
+
File.write(to_s, data)
|
15
15
|
end
|
16
16
|
|
17
17
|
#
|
@@ -25,7 +25,7 @@ class Pathname
|
|
25
25
|
#
|
26
26
|
|
27
27
|
def expanded_realpath
|
28
|
-
|
28
|
+
@expanded_real_path ||= begin
|
29
29
|
expanded_path.realpath
|
30
30
|
end
|
31
31
|
end
|
@@ -39,7 +39,7 @@ class Pathname
|
|
39
39
|
#
|
40
40
|
|
41
41
|
def glob(*args)
|
42
|
-
Dir.glob(
|
42
|
+
Dir.glob(join(*args)).map do |path|
|
43
43
|
self.class.new(path)
|
44
44
|
end
|
45
45
|
end
|
data/lib/docker/template/repo.rb
CHANGED
@@ -12,6 +12,7 @@ module Docker
|
|
12
12
|
class Repo
|
13
13
|
extend Forwardable, Routable
|
14
14
|
|
15
|
+
def_delegator :builder, :build
|
15
16
|
route_to_hash :name, :@base_metadata, :repo
|
16
17
|
route_to_hash [:tag, :type, :user], :metadata
|
17
18
|
def_delegator :@base_metadata, :to_h
|
@@ -19,12 +20,12 @@ module Docker
|
|
19
20
|
def_delegator :metadata, :tags
|
20
21
|
|
21
22
|
def initialize(base_metadata)
|
22
|
-
raise ArgumentError, "Metadata not a hash"
|
23
|
-
|
23
|
+
raise ArgumentError, "Metadata not a hash" unless base_metadata.is_a?(Hash)
|
24
|
+
|
24
25
|
@base_metadata = base_metadata.freeze
|
25
26
|
@sync_allowed = type == "simple" ? true : false
|
26
|
-
raise Error::InvalidRepoType, type
|
27
|
-
raise Error::RepoNotFound, name
|
27
|
+
raise Error::InvalidRepoType, type unless Template.config.build_types.include?(type)
|
28
|
+
raise Error::RepoNotFound, name unless root.exist?
|
28
29
|
end
|
29
30
|
|
30
31
|
def builder
|
@@ -32,14 +33,6 @@ module Docker
|
|
32
33
|
const.new(self)
|
33
34
|
end
|
34
35
|
|
35
|
-
# Simply initializes the the builder and passes itself onto
|
36
|
-
# it so that it the builder can take over and do it's job cleanly
|
37
|
-
# without us needing to care about what's going on.
|
38
|
-
|
39
|
-
def build
|
40
|
-
return builder.build
|
41
|
-
end
|
42
|
-
|
43
36
|
#
|
44
37
|
|
45
38
|
def disable_sync!
|
@@ -68,7 +61,7 @@ module Docker
|
|
68
61
|
#
|
69
62
|
|
70
63
|
def building_all?
|
71
|
-
|
64
|
+
!@base_metadata.key?("tag")
|
72
65
|
end
|
73
66
|
|
74
67
|
#
|
@@ -81,8 +74,8 @@ module Docker
|
|
81
74
|
#
|
82
75
|
|
83
76
|
def root
|
84
|
-
|
85
|
-
Template.
|
77
|
+
@root ||= begin
|
78
|
+
Template.repo_root_for(name)
|
86
79
|
end
|
87
80
|
end
|
88
81
|
|
@@ -90,9 +83,9 @@ module Docker
|
|
90
83
|
|
91
84
|
def to_tag_h
|
92
85
|
{
|
93
|
-
"
|
94
|
-
|
95
|
-
|
86
|
+
"tag" => tag,
|
87
|
+
"repo" => "#{user}/#{name}",
|
88
|
+
"force" => true
|
96
89
|
}
|
97
90
|
end
|
98
91
|
|
@@ -102,9 +95,9 @@ module Docker
|
|
102
95
|
prefix = metadata["local_prefix"]
|
103
96
|
|
104
97
|
{
|
105
|
-
"
|
106
|
-
|
107
|
-
|
98
|
+
"tag" => name,
|
99
|
+
"repo" => "#{prefix}/rootfs",
|
100
|
+
"force" => true
|
108
101
|
}
|
109
102
|
end
|
110
103
|
|
@@ -133,11 +126,12 @@ module Docker
|
|
133
126
|
|
134
127
|
def to_repos
|
135
128
|
if building_all?
|
136
|
-
|
129
|
+
set = Set.new
|
130
|
+
base = to_h
|
131
|
+
|
137
132
|
tags.each do |tag|
|
138
|
-
|
139
|
-
|
140
|
-
})))
|
133
|
+
base = base.merge("tag" => tag)
|
134
|
+
set << self.class.new(base)
|
141
135
|
end
|
142
136
|
|
143
137
|
set
|
@@ -151,8 +145,8 @@ module Docker
|
|
151
145
|
#
|
152
146
|
|
153
147
|
def metadata
|
154
|
-
|
155
|
-
metadata = Template.
|
148
|
+
@metadata ||= begin
|
149
|
+
metadata = Template.repo_root_for(name)
|
156
150
|
metadata = Template.config.read_config_from(metadata)
|
157
151
|
Metadata.new(metadata).merge(@base_metadata)
|
158
152
|
end
|
@@ -172,7 +166,7 @@ module Docker
|
|
172
166
|
"BUILD_TYPE" => type,
|
173
167
|
"COPY" => copy_dir,
|
174
168
|
"TAR" => tar_gz,
|
175
|
-
"TAG" => tag
|
169
|
+
"TAG" => tag
|
176
170
|
}).to_env
|
177
171
|
end
|
178
172
|
end
|
@@ -77,7 +77,7 @@ module Docker
|
|
77
77
|
# and stream the logs after it's exited if we have given no output,
|
78
78
|
# we want you to always get the output that was given.
|
79
79
|
|
80
|
-
|
80
|
+
unless output_given
|
81
81
|
img.streaming_logs "stdout" => true, "stderr" => true do |type, str|
|
82
82
|
type == :stdout ? $stdout.print(str) : $stderr.print(Ansi.red(str))
|
83
83
|
end
|
@@ -87,10 +87,7 @@ module Docker
|
|
87
87
|
raise Error::BadExitStatus, status
|
88
88
|
end
|
89
89
|
ensure
|
90
|
-
if img
|
91
|
-
img.stop rescue nil
|
92
|
-
img.delete
|
93
|
-
end
|
90
|
+
img.tap(&:stop).delete("force" => true) if img
|
94
91
|
end
|
95
92
|
|
96
93
|
#
|
@@ -130,7 +127,7 @@ module Docker
|
|
130
127
|
def start_args
|
131
128
|
{
|
132
129
|
"Binds" => [
|
133
|
-
"#{@copy
|
130
|
+
"#{@copy}:#{@copy}:ro", "#{@tar_gz}:#{@tar_gz}"
|
134
131
|
]
|
135
132
|
}
|
136
133
|
end
|
@@ -14,17 +14,15 @@ module Docker
|
|
14
14
|
|
15
15
|
def sync
|
16
16
|
copy_build_and_verify unless @context
|
17
|
-
Util.create_dockerhub_context(
|
18
|
-
self, @context)
|
17
|
+
Util.create_dockerhub_context(self, @context)
|
19
18
|
end
|
20
19
|
|
21
20
|
#
|
22
21
|
|
23
22
|
def unlink(img: false, sync: true)
|
24
|
-
self.sync if sync && @repo.syncable?
|
25
23
|
@img.delete "force" => true if @img && img
|
26
|
-
@context.rmtree if @context &&
|
27
|
-
|
24
|
+
@context.rmtree if @context && @context.directory?
|
25
|
+
self.sync if sync && @repo.syncable?
|
28
26
|
end
|
29
27
|
|
30
28
|
#
|
@@ -6,7 +6,7 @@ module Docker
|
|
6
6
|
module Template
|
7
7
|
class Stream
|
8
8
|
def initialize
|
9
|
-
@lines
|
9
|
+
@lines = {}
|
10
10
|
end
|
11
11
|
|
12
12
|
#
|
@@ -38,9 +38,9 @@ module Docker
|
|
38
38
|
end
|
39
39
|
|
40
40
|
before, diff = progress_diff(id)
|
41
|
-
$stdout.print
|
41
|
+
$stdout.print before if before
|
42
42
|
str = stream["progress"] || stream["status"]
|
43
|
-
str = "
|
43
|
+
str = "#{id}: #{str}\r"
|
44
44
|
|
45
45
|
$stdout.print(Ansi.jump(str, both: diff))
|
46
46
|
end
|
@@ -49,12 +49,13 @@ module Docker
|
|
49
49
|
|
50
50
|
private
|
51
51
|
def progress_diff(id)
|
52
|
-
if @lines.
|
52
|
+
if @lines.key?(id)
|
53
53
|
return nil, @lines.size - @lines[id]
|
54
54
|
end
|
55
55
|
|
56
56
|
@lines[id] = @lines.size
|
57
57
|
before = "\n" unless @lines.size == 1
|
58
|
+
# rubocop:disable RedundantReturn
|
58
59
|
return before, 0
|
59
60
|
end
|
60
61
|
end
|
data/lib/docker/template/util.rb
CHANGED
@@ -4,7 +4,9 @@
|
|
4
4
|
|
5
5
|
module Docker
|
6
6
|
module Template
|
7
|
-
module Util
|
7
|
+
module Util
|
8
|
+
module_function
|
9
|
+
|
8
10
|
autoload :Copy, "docker/template/util/copy"
|
9
11
|
autoload :Data, "docker/template/util/data"
|
10
12
|
|
@@ -24,15 +26,28 @@ module Docker
|
|
24
26
|
#
|
25
27
|
|
26
28
|
def create_dockerhub_context(builder, context)
|
27
|
-
|
28
|
-
|
29
|
-
context = tags.join(builder.repo.aliased) if builder.aliased?
|
30
|
-
dir = tags.join(builder.repo.tag)
|
31
|
-
|
29
|
+
dir = builder.repo.root.join("tags", builder.repo.tag)
|
30
|
+
context = get_context(builder, context)
|
32
31
|
FileUtils.mkdir_p dir
|
33
|
-
|
32
|
+
|
33
|
+
$stdout.puts Ansi.yellow("Copying context for #{builder.repo}")
|
34
|
+
Util::Copy.file(readme_file(builder), dir)
|
34
35
|
Util::Copy.directory(context, dir)
|
35
|
-
|
36
|
+
end
|
37
|
+
|
38
|
+
#
|
39
|
+
|
40
|
+
def get_context(builder, context)
|
41
|
+
return context unless builder.aliased?
|
42
|
+
builder.repo.root.join("tags", builder.repo.aliased)
|
43
|
+
end
|
44
|
+
|
45
|
+
#
|
46
|
+
|
47
|
+
def readme_file(builder)
|
48
|
+
builder.repo.root.children.find do |val|
|
49
|
+
val.to_s =~ /readme/i
|
50
|
+
end
|
36
51
|
end
|
37
52
|
end
|
38
53
|
end
|
@@ -8,7 +8,7 @@ module Docker
|
|
8
8
|
class Copy
|
9
9
|
def initialize(from, to)
|
10
10
|
@root = Template.root.realpath
|
11
|
-
@repos_root = Template.repos_root.realpath
|
11
|
+
@repos_root = Template.repo_is_root?? Template.root.realpath : Template.repos_root.realpath
|
12
12
|
@from = from.to_pathname
|
13
13
|
@to = to.to_pathname
|
14
14
|
end
|
@@ -30,18 +30,15 @@ module Docker
|
|
30
30
|
def directory
|
31
31
|
FileUtils.cp_r(@from.children, @to, :dereference_root => false)
|
32
32
|
@from.all_children.select(&:symlink?).each do |path|
|
33
|
+
path = @to.join(path.relative_path_from(@from))
|
33
34
|
resolved = path.realpath
|
34
|
-
pth = path.relative_path_from(@from)
|
35
|
-
pth = @to.join(path)
|
36
35
|
|
37
36
|
unless in_path?(resolved)
|
38
|
-
raise Errno::EPERM, "#{
|
37
|
+
raise Errno::EPERM, "#{path} not in #{@root}"
|
39
38
|
end
|
40
39
|
|
41
|
-
FileUtils.rm_r(
|
42
|
-
FileUtils.cp_r(resolved,
|
43
|
-
:dereference_root => false
|
44
|
-
})
|
40
|
+
FileUtils.rm_r(path)
|
41
|
+
FileUtils.cp_r(resolved, path, :dereference_root => false)
|
45
42
|
end
|
46
43
|
end
|
47
44
|
|
@@ -56,9 +53,7 @@ module Docker
|
|
56
53
|
#
|
57
54
|
|
58
55
|
def file
|
59
|
-
|
60
|
-
return FileUtils.cp(@from, @to)
|
61
|
-
end
|
56
|
+
return FileUtils.cp(@from, @to) unless @from.symlink?
|
62
57
|
|
63
58
|
resolved = @from.realpath
|
64
59
|
allowed = resolved.in_path?(@root)
|
@@ -73,8 +68,8 @@ module Docker
|
|
73
68
|
private
|
74
69
|
def in_path?(resolved)
|
75
70
|
resolved.in_path?(@repos_root) || \
|
76
|
-
|
77
|
-
|
71
|
+
resolved.in_path?(@from.realpath) || \
|
72
|
+
resolved.in_path?(@root)
|
78
73
|
end
|
79
74
|
end
|
80
75
|
end
|