docker-template 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (43) hide show
  1. checksums.yaml +7 -0
  2. data/Gemfile +13 -0
  3. data/LICENSE +13 -0
  4. data/README.md +20 -0
  5. data/Rakefile +20 -0
  6. data/lib/docker/template.rb +86 -0
  7. data/lib/docker/template/alias.rb +28 -0
  8. data/lib/docker/template/ansi.rb +75 -0
  9. data/lib/docker/template/auth.rb +25 -0
  10. data/lib/docker/template/common.rb +126 -0
  11. data/lib/docker/template/config.rb +84 -0
  12. data/lib/docker/template/error.rb +20 -0
  13. data/lib/docker/template/error/bad_exit_status.rb +17 -0
  14. data/lib/docker/template/error/bad_repo_name.rb +15 -0
  15. data/lib/docker/template/error/invalid_repo_type.rb +16 -0
  16. data/lib/docker/template/error/invalid_targz_file.rb +15 -0
  17. data/lib/docker/template/error/no_rootfs_copy_dir.rb +15 -0
  18. data/lib/docker/template/error/no_rootfs_mkimg.rb +15 -0
  19. data/lib/docker/template/error/no_setup_context_found.rb +15 -0
  20. data/lib/docker/template/error/not_implemented.rb +15 -0
  21. data/lib/docker/template/error/repo_not_found.rb +16 -0
  22. data/lib/docker/template/interface.rb +119 -0
  23. data/lib/docker/template/metadata.rb +160 -0
  24. data/lib/docker/template/parser.rb +66 -0
  25. data/lib/docker/template/patches.rb +9 -0
  26. data/lib/docker/template/patches/array.rb +11 -0
  27. data/lib/docker/template/patches/hash.rb +76 -0
  28. data/lib/docker/template/patches/object.rb +9 -0
  29. data/lib/docker/template/patches/pathname.rb +46 -0
  30. data/lib/docker/template/patches/string.rb +9 -0
  31. data/lib/docker/template/repo.rb +180 -0
  32. data/lib/docker/template/rootfs.rb +75 -0
  33. data/lib/docker/template/routable.rb +28 -0
  34. data/lib/docker/template/scratch.rb +139 -0
  35. data/lib/docker/template/simple.rb +51 -0
  36. data/lib/docker/template/stream.rb +62 -0
  37. data/lib/docker/template/templates/rootfs.erb +8 -0
  38. data/lib/docker/template/templates/scratch.erb +7 -0
  39. data/lib/docker/template/util.rb +39 -0
  40. data/lib/docker/template/util/copy.rb +82 -0
  41. data/lib/docker/template/util/data.rb +26 -0
  42. data/lib/docker/template/version.rb +9 -0
  43. metadata +155 -0
@@ -0,0 +1,20 @@
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
+ module Error
8
+ const_set :StandardError, Class.new(StandardError)
9
+ autoload :BadRepoName, "docker/template/error/bad_repo_name"
10
+ autoload :BadExitStatus, "docker/template/error/bad_exit_status"
11
+ autoload :InvalidTargzFile, "docker/template/error/invalid_targz_file"
12
+ autoload :NoSetupContextFound, "docker/template/error/no_setup_context_found"
13
+ autoload :NoRootfsCopyDir, "docker/template/error/no_rootfs_copy_dir"
14
+ autoload :InvalidRepoType, "docker/template/error/invalid_repo_type"
15
+ autoload :NoRootfsMkimg, "docker/template/error/no_rootfs_mkimg"
16
+ autoload :NotImplemented, "docker/template/error/not_implemented"
17
+ autoload :RepoNotFound, "docker/template/error/repo_not_found"
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,17 @@
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
+ module Error
8
+ class BadExitStatus < StandardError
9
+ attr_reader :status
10
+
11
+ def initialize(status)
12
+ super "Got bad exit status #{@status = status}"
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,15 @@
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
+ module Error
8
+ class BadRepoName < StandardError
9
+ def initialize(name)
10
+ super "Only a-z0-9_- are allowed. Invalid repo name: #{name}"
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,16 @@
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
+ module Error
8
+ class InvalidRepoType < StandardError
9
+ def initialize(type)
10
+ build_types = Template.config.build_types.join(", ")
11
+ super "Uknown repo type given '#{type}' not in '#{build_types}'"
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,15 @@
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
+ module Error
8
+ class InvalidTargzFile < StandardError
9
+ def initialize(tar_gz)
10
+ super "No data was given to the tar.gz file '#{tar_gz.basename}'"
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,15 @@
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
+ module Error
8
+ class NoRootfsCopyDir < StandardError
9
+ def initialize
10
+ super "Unable to find your rootfs copy folder."
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,15 @@
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
+ module Error
8
+ class NoRootfsMkimg < StandardError
9
+ def initialize
10
+ super "Unable to find a mkimg in your rootfs folder."
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,15 @@
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
+ module Error
8
+ class NoSetupContextFound < StandardError
9
+ def initialize
10
+ super "No #setup_context found."
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,15 @@
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
+ module Error
8
+ class NotImplemented < StandardError
9
+ def initialize
10
+ super "The feature is not implemented yet, sorry about that."
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,16 @@
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
+ module Error
8
+ class RepoNotFound < StandardError
9
+ def initialize(repo = nil)
10
+ ending = repo ? "the repo '#{repo}'" : "your repo folder"
11
+ super "Unable to find #{ending}"
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,119 @@
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 Interface
8
+ def initialize(argv = [])
9
+ @argv = argv
10
+ end
11
+
12
+ #
13
+
14
+ def self.push?
15
+ ARGV.include?("--push")
16
+ end
17
+
18
+ #
19
+
20
+ def run
21
+ unless only_sync?
22
+ Parser.new(argv_without_flags).parse.map do |repo|
23
+ repo.disable_sync! if wants_sync?
24
+ repo.build
25
+ end
26
+ end
27
+
28
+ sync
29
+ end
30
+
31
+ #
32
+
33
+ private
34
+ def sync
35
+ if wants_sync?
36
+ Parser.new.parse.each do |repo|
37
+ next unless repo.syncable?
38
+ repo.builder.tap(&:sync). \
39
+ unlink(sync: false)
40
+ end
41
+ end
42
+ end
43
+
44
+ #
45
+
46
+ private
47
+ def argv_without_flags
48
+ return @argv.select do |val|
49
+ !["--sync", "--push"].include?(val)
50
+ end
51
+ end
52
+
53
+ #
54
+
55
+ private
56
+ def only_sync?
57
+ @argv == [
58
+ "--sync"
59
+ ]
60
+ end
61
+
62
+ #
63
+
64
+ private
65
+ def wants_sync?
66
+ @argv.include?("--sync")
67
+ end
68
+
69
+ # Determine whether we are the Docker bin so that we can transform
70
+ # based on that... for example we will pass on commands to `docker` if
71
+ # we are running as the `docker` binary in place of `docker`.
72
+
73
+ private
74
+ def self.bin?(bin)
75
+ !bin ? false : File.basename(bin.to_s) == "docker"
76
+ end
77
+
78
+ # Discover the Docker bin using Ruby. This is a highly unoptimized
79
+ # method and needs to be reworked because it's pretty trashy shit and
80
+ # it's just flat out ugly to look at, make it better than it is.
81
+
82
+ private
83
+ def self.discover
84
+ rtn = bins.select do |path|
85
+ path.basename.fnmatch?("docker") && path.executable_real?
86
+ end.first
87
+
88
+ if rtn
89
+ rtn.to_s
90
+ end
91
+ end
92
+
93
+ #
94
+
95
+ private
96
+ def self.start(zero)
97
+ return new(ARGV[1..-1]).run if ARGV[0] == "template" && bin?(zero)
98
+ return new(ARGV).run unless bin?(zero)
99
+
100
+ exe = discover
101
+ exec exe.to_s, *ARGV if exe
102
+ abort "No Docker."
103
+ rescue Error::StandardError => error_
104
+ $stderr.puts Ansi.red(error_.message)
105
+ $stderr.puts Ansi.red("Aborting your build. Bye and good luck.")
106
+ exit error_.respond_to?(:status) ? error_.status.to_i : 1
107
+ end
108
+
109
+ #
110
+
111
+ private
112
+ def self.bins
113
+ ENV["PATH"].split(":").each_with_object(Set.new) do |val, array|
114
+ array.merge(Pathname.new(val).children) rescue next
115
+ end
116
+ end
117
+ end
118
+ end
119
+ end
@@ -0,0 +1,160 @@
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 Metadata
8
+ extend Forwardable, Routable
9
+
10
+ # Provides aliases for the root element so you can do something like:
11
+ # * data["release"].fallback
12
+
13
+ Aliases = {
14
+ "entry" => "entries",
15
+ "release" => "releases",
16
+ "version" => "versions",
17
+ "script" => "scripts",
18
+ "image" => "images"
19
+ }
20
+
21
+ def_delegator :@metadata, :keys
22
+ def_delegator :@metadata, :size
23
+ def_delegator :@metadata, :to_enum
24
+ def_delegator :@metadata, :has_key?
25
+ def_delegator :@metadata, :inspect
26
+ def_delegator :@metadata, :delete
27
+ def_delegator :@metadata, :each
28
+ def_delegator :@metadata, :to_h
29
+ route_to_ivar :is_root, :@is_root, bool: true
30
+ route_to_hash :for_all, :self, :all
31
+
32
+ def initialize(metadata, root_metadata = metadata)
33
+ @is_root = metadata == root_metadata
34
+ @root_metadata = root_metadata || {}
35
+ @metadata = metadata || {}
36
+
37
+ if is_root?
38
+ @base = Template.config
39
+ @root_metadata = @metadata
40
+ end
41
+ end
42
+
43
+ #
44
+
45
+ def aliased
46
+ aliases = from_root("aliases")
47
+ tag = from_root("tag")
48
+
49
+ if aliases.has_key?(tag)
50
+ return aliases[tag]
51
+ end
52
+ tag
53
+ end
54
+
55
+ # Queries providing a default value if on the root repo hash otherwise
56
+ # returning the returned value, as a `self.class` if it's a Hash.
57
+
58
+ def [](key)
59
+ key = determine_key(key)
60
+ val = @metadata[key]
61
+
62
+ return try_default(key) if !val && is_root?
63
+ return self.class.new(val, @root_metadata) if val.is_a?(Hash)
64
+ val
65
+ end
66
+
67
+ #
68
+
69
+ def tags
70
+ self["tags"].keys + self["aliases"].keys
71
+ end
72
+
73
+ #
74
+
75
+ def merge(_new)
76
+ @metadata.merge!(_new)
77
+ self
78
+ end
79
+
80
+ #
81
+
82
+ def as_string_set
83
+ as_set.to_a.join(" ")
84
+ end
85
+
86
+ #
87
+
88
+ def as_hash
89
+ {}.merge(for_all.to_h). \
90
+ merge(by_type.to_h). \
91
+ merge(by_tag. to_h)
92
+ end
93
+
94
+ #
95
+
96
+ 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
+ end
102
+
103
+ #
104
+
105
+ def from_root(key)
106
+ root = self.class.new(@root_metadata)
107
+ root[key]
108
+ end
109
+
110
+ #
111
+
112
+ def fallback
113
+ by_tag || by_type || for_all
114
+ end
115
+
116
+ # Pulls data based on the given tag through anything that provides a
117
+ # "tag" key with the given tags. ("tags" is a `Hash`)
118
+
119
+ def by_tag
120
+ return unless tag = aliased
121
+ return unless has_key?("tag")
122
+ hash = self["tag"]
123
+ hash[tag]
124
+ end
125
+
126
+ # Pull data based on the type given in { "tags" => { tag => type }}
127
+ # through anything that provides a "type" key with the type as a
128
+ # sub-key and the values.
129
+
130
+ def by_type
131
+ return unless tag = aliased
132
+ type = @root_metadata["tags"][tag]
133
+ return unless has_key?("type")
134
+ return unless type
135
+
136
+ hash = self["type"]
137
+ hash[type]
138
+ end
139
+
140
+ #
141
+
142
+ private
143
+ def determine_key(key)
144
+ if is_root? && !has_key?(key) && Aliases.has_key?(key)
145
+ key = Aliases[key]
146
+ end
147
+ key
148
+ end
149
+
150
+ #
151
+
152
+ private
153
+ def try_default(key)
154
+ val = @base[key]
155
+ return self.class.new(val, @root_metadata) if val.is_a?(Hash)
156
+ val
157
+ end
158
+ end
159
+ end
160
+ end