docker-template 0.1.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 +7 -0
- data/Gemfile +13 -0
- data/LICENSE +13 -0
- data/README.md +20 -0
- data/Rakefile +20 -0
- data/lib/docker/template.rb +86 -0
- data/lib/docker/template/alias.rb +28 -0
- data/lib/docker/template/ansi.rb +75 -0
- data/lib/docker/template/auth.rb +25 -0
- data/lib/docker/template/common.rb +126 -0
- data/lib/docker/template/config.rb +84 -0
- data/lib/docker/template/error.rb +20 -0
- data/lib/docker/template/error/bad_exit_status.rb +17 -0
- data/lib/docker/template/error/bad_repo_name.rb +15 -0
- data/lib/docker/template/error/invalid_repo_type.rb +16 -0
- data/lib/docker/template/error/invalid_targz_file.rb +15 -0
- data/lib/docker/template/error/no_rootfs_copy_dir.rb +15 -0
- data/lib/docker/template/error/no_rootfs_mkimg.rb +15 -0
- data/lib/docker/template/error/no_setup_context_found.rb +15 -0
- data/lib/docker/template/error/not_implemented.rb +15 -0
- data/lib/docker/template/error/repo_not_found.rb +16 -0
- data/lib/docker/template/interface.rb +119 -0
- data/lib/docker/template/metadata.rb +160 -0
- data/lib/docker/template/parser.rb +66 -0
- data/lib/docker/template/patches.rb +9 -0
- data/lib/docker/template/patches/array.rb +11 -0
- data/lib/docker/template/patches/hash.rb +76 -0
- data/lib/docker/template/patches/object.rb +9 -0
- data/lib/docker/template/patches/pathname.rb +46 -0
- data/lib/docker/template/patches/string.rb +9 -0
- data/lib/docker/template/repo.rb +180 -0
- data/lib/docker/template/rootfs.rb +75 -0
- data/lib/docker/template/routable.rb +28 -0
- data/lib/docker/template/scratch.rb +139 -0
- data/lib/docker/template/simple.rb +51 -0
- data/lib/docker/template/stream.rb +62 -0
- data/lib/docker/template/templates/rootfs.erb +8 -0
- data/lib/docker/template/templates/scratch.erb +7 -0
- data/lib/docker/template/util.rb +39 -0
- data/lib/docker/template/util/copy.rb +82 -0
- data/lib/docker/template/util/data.rb +26 -0
- data/lib/docker/template/version.rb +9 -0
- metadata +155 -0
@@ -0,0 +1,66 @@
|
|
1
|
+
# Frozen-string-literal: true
|
2
|
+
# Copyright: 2015 Jordon Bedwell - Apache v2.0 License
|
3
|
+
# Encoding: utf-8
|
4
|
+
|
5
|
+
module Docker
|
6
|
+
module Template
|
7
|
+
class Parser
|
8
|
+
SlashRegexp = /\//.freeze
|
9
|
+
SplitRegexp = /:|\//.freeze
|
10
|
+
ColonRegexp = /:/.freeze
|
11
|
+
|
12
|
+
def initialize(argv = [].freeze)
|
13
|
+
@argv = argv.freeze
|
14
|
+
end
|
15
|
+
|
16
|
+
# Return ARGV if you send us a list of repos you wish to build,
|
17
|
+
# otherwise we get the children of the repo folder and ship that off
|
18
|
+
# so you can build *every* repo, I don't know if you want that.
|
19
|
+
|
20
|
+
def all
|
21
|
+
return @argv unless @argv.empty?
|
22
|
+
Docker::Template.repos_root.children.map do |path|
|
23
|
+
path.basename.to_s
|
24
|
+
end
|
25
|
+
rescue Errno::ENOENT
|
26
|
+
raise Error::RepoNotFound
|
27
|
+
end
|
28
|
+
|
29
|
+
#
|
30
|
+
|
31
|
+
def parse(as: :repos, out: Set.new)
|
32
|
+
all.each do |val|
|
33
|
+
hash = build_repo_hash(val)
|
34
|
+
raise Docker::Template::Error::BadRepoName, val if hash.empty?
|
35
|
+
out += as == :repos ? Repo.new(hash).to_repos : [hash]
|
36
|
+
end
|
37
|
+
out
|
38
|
+
end
|
39
|
+
|
40
|
+
#
|
41
|
+
|
42
|
+
private
|
43
|
+
def build_repo_hash(val)
|
44
|
+
data, hsh = val.split(SplitRegexp), {}
|
45
|
+
if data.size == 1
|
46
|
+
hsh["repo"] = data[0]
|
47
|
+
|
48
|
+
elsif val =~ ColonRegexp && data.size == 2
|
49
|
+
hsh["repo"] = data[0]
|
50
|
+
hsh[ "tag"] = data[1]
|
51
|
+
|
52
|
+
elsif val =~ SlashRegexp && data.size == 2
|
53
|
+
hsh["user"] = data[0]
|
54
|
+
hsh["repo"] = data[1]
|
55
|
+
|
56
|
+
elsif data.size == 3
|
57
|
+
hsh["user"] = data[0]
|
58
|
+
hsh["repo"] = data[1]
|
59
|
+
hsh[ "tag"] = data[2]
|
60
|
+
end
|
61
|
+
|
62
|
+
hsh
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
# Frozen-string-literal: true
|
2
|
+
# Copyright: 2015 Jordon Bedwell - Apache v2.0 License
|
3
|
+
# Encoding: utf-8
|
4
|
+
|
5
|
+
require "docker/template/patches/object"
|
6
|
+
require "docker/template/patches/array"
|
7
|
+
require "docker/template/patches/pathname"
|
8
|
+
require "docker/template/patches/string"
|
9
|
+
require "docker/template/patches/hash"
|
@@ -0,0 +1,76 @@
|
|
1
|
+
# Frozen-string-literal: true
|
2
|
+
# Copyright: 2015 Jordon Bedwell - Apache v2.0 License
|
3
|
+
# Encoding: utf-8
|
4
|
+
|
5
|
+
class Hash
|
6
|
+
def to_env
|
7
|
+
inject({}) do |hsh, (key, val)|
|
8
|
+
val = val.is_a?(Array) ? val.join(" ") : val.to_s
|
9
|
+
key = key.to_s.upcase
|
10
|
+
hsh[key] = val
|
11
|
+
hsh
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
#
|
16
|
+
|
17
|
+
def any_keys?(*keys)
|
18
|
+
keys.map(&method(:has_key?)).any? do |val|
|
19
|
+
val == true
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
#
|
24
|
+
|
25
|
+
def leftover_keys?(*keys)
|
26
|
+
return (self.keys - keys).any?
|
27
|
+
end
|
28
|
+
|
29
|
+
#
|
30
|
+
|
31
|
+
def has_keys?(*keys)
|
32
|
+
return false unless rtn = true && any?
|
33
|
+
while rtn && key = keys.shift
|
34
|
+
rtn = has_key?(key) || false
|
35
|
+
end
|
36
|
+
|
37
|
+
rtn
|
38
|
+
end
|
39
|
+
|
40
|
+
#
|
41
|
+
|
42
|
+
def to_env_ary
|
43
|
+
inject([]) do |array, (key, val)|
|
44
|
+
array.push("#{key}=#{val}")
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
#
|
49
|
+
|
50
|
+
def deep_merge(newh)
|
51
|
+
merge(newh) do |key, oval, nval|
|
52
|
+
if oval.is_a?(self.class) && nval.is_a?(self.class)
|
53
|
+
then oval.deep_merge(nval) else nval
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
#
|
59
|
+
|
60
|
+
def stringify
|
61
|
+
inject({}) do |hsh, (key, val)|
|
62
|
+
hsh[key.to_s] = val.is_a?(Array) || val.is_a?(Hash) ? val.stringify : val.to_s
|
63
|
+
hsh
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
#
|
68
|
+
|
69
|
+
def stringify_keys
|
70
|
+
inject({}) do |hsh, (key, val)|
|
71
|
+
hsh[key.to_s] = val
|
72
|
+
|
73
|
+
hsh
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# Frozen-string-literal: true
|
2
|
+
# Copyright: 2015 Jordon Bedwell - Apache v2.0 License
|
3
|
+
# Encoding: utf-8
|
4
|
+
|
5
|
+
class Pathname
|
6
|
+
def in_path?(path)
|
7
|
+
path_str = path.is_a?(self.class) ? path.expanded_realpath.to_s : path.to_s
|
8
|
+
expanded_realpath.to_s.start_with?(path_str)
|
9
|
+
end
|
10
|
+
|
11
|
+
#
|
12
|
+
|
13
|
+
def write(data)
|
14
|
+
File.write(self.to_s, data)
|
15
|
+
end
|
16
|
+
|
17
|
+
#
|
18
|
+
|
19
|
+
def expanded_path
|
20
|
+
@expanded_path ||= begin
|
21
|
+
expand_path Dir.pwd
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
#
|
26
|
+
|
27
|
+
def expanded_realpath
|
28
|
+
return @expanded_real_path ||= begin
|
29
|
+
expanded_path.realpath
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
#
|
34
|
+
|
35
|
+
def all_children
|
36
|
+
glob "**/*"
|
37
|
+
end
|
38
|
+
|
39
|
+
#
|
40
|
+
|
41
|
+
def glob(*args)
|
42
|
+
Dir.glob(self.join(*args)).map do |path|
|
43
|
+
self.class.new(path)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,180 @@
|
|
1
|
+
# Frozen-string-literal: true
|
2
|
+
# Copyright: 2015 Jordon Bedwell - Apache v2.0 License
|
3
|
+
# Encoding: utf-8
|
4
|
+
|
5
|
+
module Docker
|
6
|
+
module Template
|
7
|
+
|
8
|
+
# * A repo is not an image but a parent name w/ a tag.
|
9
|
+
# * An image is the final result of a build on a repo, and is associated.
|
10
|
+
# * Think of an image as the binary of the source in the repo.
|
11
|
+
|
12
|
+
class Repo
|
13
|
+
extend Forwardable, Routable
|
14
|
+
|
15
|
+
route_to_hash :name, :@base_metadata, :repo
|
16
|
+
route_to_hash [:tag, :type, :user], :metadata
|
17
|
+
def_delegator :@base_metadata, :to_h
|
18
|
+
def_delegator :metadata, :aliased
|
19
|
+
def_delegator :metadata, :tags
|
20
|
+
|
21
|
+
def initialize(base_metadata)
|
22
|
+
raise ArgumentError, "Metadata not a hash" if !base_metadata.is_a?(Hash)
|
23
|
+
|
24
|
+
@base_metadata = base_metadata.freeze
|
25
|
+
@sync_allowed = type == "simple" ? true : false
|
26
|
+
raise Error::InvalidRepoType, type if !Template.config.build_types.include?(type)
|
27
|
+
raise Error::RepoNotFound, name if !root.exist?
|
28
|
+
end
|
29
|
+
|
30
|
+
def builder
|
31
|
+
const = Template.const_get(type.capitalize)
|
32
|
+
const.new(self)
|
33
|
+
end
|
34
|
+
|
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
|
+
#
|
44
|
+
|
45
|
+
def disable_sync!
|
46
|
+
@sync_allowed = false
|
47
|
+
end
|
48
|
+
|
49
|
+
#
|
50
|
+
|
51
|
+
def syncable?
|
52
|
+
metadata["dockerhub_copy"] && @sync_allowed
|
53
|
+
end
|
54
|
+
|
55
|
+
#
|
56
|
+
|
57
|
+
def to_s
|
58
|
+
"#{user}/#{name}:#{tag}"
|
59
|
+
end
|
60
|
+
|
61
|
+
#
|
62
|
+
|
63
|
+
def copy_dir(*path)
|
64
|
+
dir = metadata["copy_dir"]
|
65
|
+
root.join(dir, *path)
|
66
|
+
end
|
67
|
+
|
68
|
+
#
|
69
|
+
|
70
|
+
def building_all?
|
71
|
+
!@base_metadata.has_key?("tag")
|
72
|
+
end
|
73
|
+
|
74
|
+
#
|
75
|
+
|
76
|
+
def to_rootfs_s
|
77
|
+
prefix = metadata["local_prefix"]
|
78
|
+
"#{prefix}/rootfs:#{name}"
|
79
|
+
end
|
80
|
+
|
81
|
+
#
|
82
|
+
|
83
|
+
def root
|
84
|
+
return @root ||= begin
|
85
|
+
Template.repos_root.join(name)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
#
|
90
|
+
|
91
|
+
def to_tag_h
|
92
|
+
{
|
93
|
+
"force" => true,
|
94
|
+
"repo" => "#{user}/#{name}",
|
95
|
+
"tag" => tag,
|
96
|
+
}
|
97
|
+
end
|
98
|
+
|
99
|
+
#
|
100
|
+
|
101
|
+
def to_rootfs_h
|
102
|
+
prefix = metadata["local_prefix"]
|
103
|
+
|
104
|
+
{
|
105
|
+
"force" => true,
|
106
|
+
"repo" => "#{prefix}/rootfs",
|
107
|
+
"tag" => name
|
108
|
+
}
|
109
|
+
end
|
110
|
+
|
111
|
+
#
|
112
|
+
|
113
|
+
def tmpdir(*prefixes, root: nil)
|
114
|
+
prefixes = [user, name, tag] + prefixes
|
115
|
+
args = ["#{prefixes.join("-")}-", root].delete_if(&:nil?)
|
116
|
+
Pathname.new(Dir.mktmpdir(*args))
|
117
|
+
end
|
118
|
+
|
119
|
+
#
|
120
|
+
|
121
|
+
def tmpfile(*prefixes, root: nil)
|
122
|
+
prefixes = [user, name, tag] + prefixes
|
123
|
+
ext = prefixes.pop if prefixes.last =~ /\A\./
|
124
|
+
prefixes = ["#{prefixes.join("-")}-"]
|
125
|
+
prefixes = ext ? prefixes.push(ext) : prefixes.first
|
126
|
+
args = [prefixes, root].delete_if(&:nil?)
|
127
|
+
Pathname.new(Tempfile.new(*args))
|
128
|
+
end
|
129
|
+
|
130
|
+
# If a tag was given then it returns [self] and if a tag was not
|
131
|
+
# sent it then goes on to detect the type and split itself accordingly
|
132
|
+
# returning multiple AKA all repos to be built.
|
133
|
+
|
134
|
+
def to_repos
|
135
|
+
if building_all?
|
136
|
+
base, set = to_h, Set.new
|
137
|
+
tags.each do |tag|
|
138
|
+
set.add(self.class.new(base.merge({
|
139
|
+
"tag" => tag
|
140
|
+
})))
|
141
|
+
end
|
142
|
+
|
143
|
+
set
|
144
|
+
else
|
145
|
+
Set.new([
|
146
|
+
self
|
147
|
+
])
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
#
|
152
|
+
|
153
|
+
def metadata
|
154
|
+
return @metadata ||= begin
|
155
|
+
metadata = Template.repos_root.join(name)
|
156
|
+
metadata = Template.config.read_config_from(metadata)
|
157
|
+
Metadata.new(metadata).merge(@base_metadata)
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
#
|
162
|
+
|
163
|
+
def to_env_hash(tar_gz: nil, copy_dir: nil)
|
164
|
+
metadata["env"].as_hash.merge({
|
165
|
+
"REPO" => name,
|
166
|
+
"NAME" => name,
|
167
|
+
"TAR_GZ" => tar_gz,
|
168
|
+
"TYPE" => metadata["tags"][tag],
|
169
|
+
"VERSION" => metadata["version"].fallback,
|
170
|
+
"PKGS" => metadata["pkgs"].as_string_set,
|
171
|
+
"RELEASE" => metadata["release"].fallback,
|
172
|
+
"BUILD_TYPE" => type,
|
173
|
+
"COPY" => copy_dir,
|
174
|
+
"TAR" => tar_gz,
|
175
|
+
"TAG" => tag,
|
176
|
+
}).to_env
|
177
|
+
end
|
178
|
+
end
|
179
|
+
end
|
180
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
# Frozen-string-literal: true
|
2
|
+
# Copyright: 2015 Jordon Bedwell - Apache v2.0 License
|
3
|
+
# Encoding: utf-8
|
4
|
+
|
5
|
+
module Docker
|
6
|
+
module Template
|
7
|
+
class Rootfs < Common
|
8
|
+
attr_reader :img
|
9
|
+
def initialize(repo)
|
10
|
+
@repo = repo
|
11
|
+
end
|
12
|
+
|
13
|
+
#
|
14
|
+
|
15
|
+
def rootfs?
|
16
|
+
true
|
17
|
+
end
|
18
|
+
|
19
|
+
#
|
20
|
+
|
21
|
+
def data
|
22
|
+
Template.get(:rootfs, {
|
23
|
+
:rootfs_base_img => @repo.metadata["rootfs_base_img"]
|
24
|
+
})
|
25
|
+
end
|
26
|
+
|
27
|
+
# In a typical situation we do not remove the rootfs img and don't
|
28
|
+
# recommend removing it as it's better cached by Docker, if you wish
|
29
|
+
# to delete it we will. Now, here we only remove it if we get told
|
30
|
+
# to exit, since we will be in the middle of a build and probably
|
31
|
+
# not have tagged yet, unless we are downstream, we will remove
|
32
|
+
# it so you have no broken images on your system.
|
33
|
+
|
34
|
+
def unlink(img: true)
|
35
|
+
keep = @repo.metadata["keep_rootfs"]
|
36
|
+
@img.delete "force" => true if img && @img && !keep
|
37
|
+
@context.rmtree if @context && @context.directory?
|
38
|
+
rescue Docker::Error::NotFoundError
|
39
|
+
nil
|
40
|
+
end
|
41
|
+
|
42
|
+
#
|
43
|
+
|
44
|
+
private
|
45
|
+
def setup_context
|
46
|
+
@context = @repo.tmpdir("rootfs")
|
47
|
+
@context.join("Dockerfile").write(data)
|
48
|
+
@copy = @context.join(@repo.metadata["copy_dir"])
|
49
|
+
@copy.mkdir
|
50
|
+
copy_rootfs
|
51
|
+
end
|
52
|
+
|
53
|
+
#
|
54
|
+
|
55
|
+
private
|
56
|
+
def copy_rootfs
|
57
|
+
dir = @repo.copy_dir("rootfs")
|
58
|
+
Util::Copy.new(dir, @copy).directory
|
59
|
+
rescue Errno::ENOENT => error_
|
60
|
+
if error_.message !~ /\/(copy|rootfs)\Z/
|
61
|
+
raise error_ else raise Error::NoRootfsCopyDir
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
#
|
66
|
+
|
67
|
+
private
|
68
|
+
def verify_context
|
69
|
+
unless @copy.join("usr/local/bin/mkimg").file?
|
70
|
+
raise Error::NoRootfsMkimg
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|