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.
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