docker-template 0.8.0 → 0.10.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.
@@ -0,0 +1,58 @@
1
+ # Frozen-string-literal: true
2
+ # Copyright: 2015 - 2016 Jordon Bedwell - Apache v2.0 License
3
+ # Encoding: utf-8
4
+
5
+ module Docker
6
+ module Template
7
+ class Builder
8
+ class Normal < Builder
9
+ projects_allowed!
10
+
11
+ def teardown(img: false)
12
+ @img.delete "force" => true if @img && img
13
+ @context.rmtree if @context && \
14
+ @context.directory?
15
+ end
16
+
17
+ # --
18
+
19
+ def setup_context
20
+ @context = @repo.tmpdir
21
+ @copy = @context.join("copy")
22
+ copy_dockerfile
23
+ @copy.mkdir
24
+ end
25
+
26
+ # --
27
+
28
+ private
29
+ def copy_dockerfile
30
+ dockerfile = Template.project?? Template.root : @repo.root
31
+ dockerfile = dockerfile.join("Dockerfile").read
32
+
33
+ data = ERB::Context.new(:meta => @repo.meta)
34
+ data = ERB.new(dockerfile).result(data._binding)
35
+ context = @context.join("Dockerfile")
36
+ context.write(data)
37
+ end
38
+
39
+ # --
40
+
41
+ private
42
+ def cache_context
43
+ return unless @repo.cacheable?
44
+ return Cache.aliased_context(self) if alias?
45
+ Cache.context(self, @context)
46
+ end
47
+
48
+ class << self
49
+ def files
50
+ %w(
51
+ Dockerfile
52
+ )
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,111 @@
1
+ # Frozen-string-literal: true
2
+ # Copyright: 2015 - 2016 Jordon Bedwell - Apache v2.0 License
3
+ # Encoding: utf-8
4
+
5
+ module Docker
6
+ module Template
7
+ class Builder
8
+ class Rootfs < Builder
9
+ extend Forwardable::Extended
10
+
11
+ # --
12
+
13
+ def data
14
+ Template.get(:rootfs, {
15
+ :rootfs_base_img => @repo.meta["rootfs_base_img"]
16
+ })
17
+ end
18
+
19
+ # --
20
+
21
+ def discover
22
+ self.class.files.map do |file|
23
+ file = @repo.root.join(
24
+ file
25
+ )
26
+
27
+ if file.file?
28
+ then return file
29
+ end
30
+ end
31
+
32
+ "rootfs/#{
33
+ @repo.meta.rootfs_template
34
+ }"
35
+ end
36
+
37
+ # --
38
+
39
+ def builder_data
40
+ Template.get(discover, {
41
+ :meta => @repo.meta
42
+ })
43
+ end
44
+
45
+ # --
46
+ # During a simple copy you store all the data (including rootfs) data
47
+ # as a project unit, this helps us clean up data that is known to be for
48
+ # just the rootfs image and remove it so it doesn't impact.
49
+ # --
50
+ def simple_cleanup(dir)
51
+ file = dir.join("usr/local/bin/mkimg")
52
+
53
+ if file.exist?
54
+ then file.delete
55
+ end
56
+ end
57
+
58
+ # --
59
+
60
+ def teardown(img: true)
61
+ @context.rmtree if @context && @context.directory?
62
+ @img.delete "force" => true if @img && img \
63
+ rescue nil
64
+ end
65
+
66
+ # --
67
+
68
+ private
69
+ def setup_context
70
+ @context = @repo.tmpdir("rootfs")
71
+ @copy = @context.join(@repo.meta["copy_dir"])
72
+ @context.join("Dockerfile").write(data)
73
+
74
+ @copy.join("usr/local/bin").mkdir_p
75
+ @copy.join("usr/local/bin/mkimg").write(builder_data)
76
+ @copy.join("usr/local/bin/mkimg").chmod(0755)
77
+ copy_rootfs
78
+ end
79
+
80
+ # --
81
+
82
+ private
83
+ def copy_rootfs
84
+ dir = @repo.copy_dir(
85
+ "rootfs"
86
+ )
87
+
88
+ if dir.exist?
89
+ @repo.copy_dir("rootfs").safe_copy(@copy, {
90
+ :root => Template.root
91
+ })
92
+ end
93
+ end
94
+
95
+ class << self
96
+ def sub?
97
+ return true
98
+ end
99
+
100
+ # --
101
+
102
+ def files
103
+ %w(
104
+ Rootfs.erb Rootfs rootfs.erb rootfs
105
+ )
106
+ end
107
+ end
108
+ end
109
+ end
110
+ end
111
+ end
@@ -0,0 +1,165 @@
1
+ # Frozen-string-literal: true
2
+ # Copyright: 2015 - 2016 Jordon Bedwell - Apache v2.0 License
3
+ # Encoding: utf-8
4
+
5
+ module Docker
6
+ module Template
7
+ class Builder
8
+ class Scratch < Builder
9
+ attr_reader :rootfs
10
+
11
+ # --
12
+
13
+ def initialize(*args)
14
+ super; @rootfs = Rootfs.new(
15
+ repo
16
+ )
17
+ end
18
+
19
+ # --
20
+
21
+ def data
22
+ Template.get(:scratch, {
23
+ :entrypoint => @repo.meta.entry,
24
+ :maintainer => @repo.meta.maintainer,
25
+ :tar_gz => @tar_gz.basename
26
+ })
27
+ end
28
+
29
+ # --
30
+
31
+ def teardown(img: false)
32
+ @copy.rm_rf if @copy
33
+ @context.rm_rf if @context
34
+ @tar_gz.rm_rf if @tar_gz
35
+
36
+ if @img && img
37
+ then @img.delete({
38
+ "force" => true
39
+ })
40
+ end
41
+ rescue Docker::Error::NotFoundError
42
+ nil
43
+ end
44
+
45
+ # --
46
+
47
+ private
48
+ def setup_context
49
+ @context = @repo.tmpdir
50
+ @tar_gz = @repo.tmpfile "archive", ".tar.gz", root: @context
51
+ @copy = @repo.tmpdir "copy"
52
+ copy_dockerfile
53
+ end
54
+
55
+ # --
56
+
57
+ private
58
+ def copy_dockerfile
59
+ data = self.data % @tar_gz.basename
60
+ dockerfile = @context.join("Dockerfile")
61
+ dockerfile.write(data)
62
+ end
63
+
64
+ # --
65
+
66
+ def copy_cleanup
67
+ @rootfs.simple_cleanup(
68
+ @copy
69
+ )
70
+ end
71
+
72
+ # --
73
+
74
+ def verify_context
75
+ if @repo.buildable? && @tar_gz.zero?
76
+ raise Error::InvalidTargzFile, @tar_gz
77
+ end
78
+ end
79
+
80
+ # --
81
+
82
+ private
83
+ def build_context
84
+ return unless @repo.buildable?
85
+ @rootfs.build
86
+
87
+ logger = Logger.new
88
+ img = Container.create(create_args)
89
+ img.start.attach(logger_opts, &logger.method(logger_type))
90
+ status = img.json["State"]["ExitCode"]
91
+
92
+ if status != 0
93
+ logger.simple(:stderr, img.logs(:stderr => true)) unless logger.output?
94
+ logger.simple(:stdout, img.logs(:stdout => true)) unless logger.output?
95
+ raise Error::BadExitStatus, status
96
+ end
97
+ ensure
98
+ if img
99
+ then img.tap(&:stop).delete({
100
+ "force" => true
101
+ })
102
+ end
103
+
104
+ @rootfs.teardown
105
+ end
106
+
107
+ # --
108
+
109
+ private
110
+ def logger_type
111
+ @repo.meta["tty"] ? :tty : :simple
112
+ end
113
+
114
+ # --
115
+
116
+ private
117
+ def logger_opts
118
+ return {
119
+ :tty => @repo.meta["tty"], :stdout => true, :stderr => true
120
+ }
121
+ end
122
+
123
+ # --
124
+
125
+ private
126
+ def create_args
127
+ name = ["rootfs", @repo.name, @repo.tag, "image"].join("-")
128
+ env = @repo.to_env(:tar_gz => @tar_gz, :copy_dir => @copy)
129
+
130
+ return {
131
+ "Env" => env.to_a,
132
+ "Tty" => @repo.meta["tty"],
133
+ "Image" => @rootfs.img.id,
134
+ "Name" => name,
135
+
136
+ "HostConfig" => {
137
+ "Binds" => [
138
+ "#{@copy}:#{@copy}", "#{@tar_gz}:#{@tar_gz}"
139
+ ]
140
+ },
141
+
142
+ "Volumes" => {
143
+ @copy.to_s => {
144
+ "source" => @copy.to_s,
145
+ "destination" => @copy.to_s
146
+ },
147
+
148
+ @tar_gz.to_s => {
149
+ "source" => @tar_gz.to_s,
150
+ "destination" => @tar_gz.to_s
151
+ }
152
+ }
153
+ }
154
+ end
155
+
156
+ class << self
157
+ def files
158
+ return Rootfs \
159
+ .files
160
+ end
161
+ end
162
+ end
163
+ end
164
+ end
165
+ end
@@ -1,17 +1,15 @@
1
- # ----------------------------------------------------------------------------
2
1
  # Frozen-string-literal: true
3
2
  # Copyright: 2015 - 2016 Jordon Bedwell - Apache v2.0 License
4
3
  # Encoding: utf-8
5
- # ----------------------------------------------------------------------------
6
4
 
7
5
  module Docker
8
6
  module Template
9
7
  module Cache
10
8
  module_function
11
9
 
12
- # ----------------------------------------------------------------------
10
+ # --
13
11
  # Cache the context into the cache directory.
14
- # ----------------------------------------------------------------------
12
+ # --
15
13
 
16
14
  def context(builder, context)
17
15
  builder.repo.cache_dir.rm_rf
@@ -19,15 +17,16 @@ module Docker
19
17
  cache_dir = builder.repo.cache_dir
20
18
  cache_dir.parent.mkdir_p
21
19
 
22
- readme(builder)
23
20
  context.cp_r(cache_dir.tap(
24
21
  &:rm_rf
25
22
  ))
23
+
24
+ readme(builder)
26
25
  end
27
26
 
28
- # ----------------------------------------------------------------------
27
+ # --
29
28
  # rubocop:disable Metrics/LineLength
30
- # ----------------------------------------------------------------------
29
+ # --
31
30
 
32
31
  def aliased_context(builder)
33
32
  if builder.aliased_repo.cache_dir.exist?
@@ -38,18 +37,18 @@ module Docker
38
37
  end
39
38
  end
40
39
 
41
- # ----------------------------------------------------------------------
40
+ # --
42
41
  # Cleanup the context caches, removing the caches we no longer need.
43
- # ----------------------------------------------------------------------
44
42
  # rubocop:enable Metrics/LineLength
45
- # ----------------------------------------------------------------------
43
+ # --
46
44
 
47
45
  def cleanup(repo)
46
+ return unless repo.clean_cache?
48
47
  cache_dir = repo.cache_dir.parent
49
48
 
50
- if repo.cacheable? && cache_dir.exist?
51
- then cache_dir.children.each do |file|
52
- next unless repo.metadata.tags.include?(file.basename)
49
+ if cache_dir.exist?
50
+ cache_dir.children.each do |file|
51
+ next unless repo.meta.tags.include?(file.basename)
53
52
  $stdout.puts Simple::Ansi.yellow(format("Removing %s.",
54
53
  file.relative_path_from(Template.root)
55
54
  ))
@@ -59,17 +58,13 @@ module Docker
59
58
  end
60
59
  end
61
60
 
62
- # ----------------------------------------------------------------------
61
+ # --
63
62
  # Note: We normally expect but do not require you to have a README.
64
63
  # Search for and copy the readme if available.
65
- # ----------------------------------------------------------------------
64
+ # --
66
65
 
67
66
  def readme(builder)
68
- file = builder.repo.root.children.find do |val|
69
- val =~ /readme/i
70
- end
71
-
72
- return unless file
67
+ return unless file = builder.repo.root.children.find { |val| val =~ /readme/i }
73
68
  file.safe_copy(builder.repo.cache_dir, {
74
69
  :root => file.parent
75
70
  })
@@ -1,46 +1,98 @@
1
- # ----------------------------------------------------------------------------
2
1
  # Frozen-string-literal: true
3
2
  # Copyright: 2015 - 2016 Jordon Bedwell - Apache v2.0 License
4
3
  # Encoding: utf-8
5
- # ----------------------------------------------------------------------------
6
4
 
5
+ require "docker/template"
7
6
  require "thor"
8
7
 
9
8
  module Docker
10
9
  module Template
11
10
  class CLI < Thor
12
- autoload :Build, "docker/template/cli/build"
13
- autoload :List, "docker/template/cli/list"
14
11
 
15
- # ----------------------------------------------------------------------
12
+ # --
13
+
14
+ option :force, :type => :boolean, :desc => "Force caching."
15
+ desc "cache [REPOS [OPTS]]", "Cache all (or some) of your repositories."
16
+ option :clean, :type => :boolean, :desc => "Cleanup your caches."
17
+ option :help, :type => :boolean, :desc => "Output this."
18
+
19
+ # --
20
+
21
+ def cache(*args)
22
+ return help(__method__) if options.help?
23
+ self.options = options.merge(:cache => true) if options.force?
24
+ self.options = options.merge(:cache_only => true)
25
+ return build(
26
+ *args
27
+ )
28
+ end
29
+
30
+ # --
31
+
32
+ option :force, :type => :boolean, :desc => "Force cleaning."
33
+ desc "clean [REPOS [OPTS]]", "Clean all (or some) of your repositories caches."
34
+ option :help, :type => :boolean, :desc => "Output this."
35
+
36
+ # --
37
+
38
+ def clean(*args)
39
+ return help(__method__) if options.help?
40
+ self.options = options.merge(:clean => true) if options.force?
41
+ self.options = options.merge(:clean_only => true)
42
+ return build(
43
+ *args
44
+ )
45
+ end
46
+
47
+ # --
48
+
49
+ option :force, :type => :boolean, :desc => "Force cleaning."
50
+ desc "push [REPOS [OPTS]]", "Push all (or some) of your repositories."
51
+ option :help, :type => :boolean, :desc => "Output this."
52
+
53
+ # --
54
+
55
+ def push(*args)
56
+ return help(__method__) if options.help?
57
+ self.options = options.merge(:push => true) if options.force?
58
+ self.options = options.merge(:push_only => true)
59
+ return build(
60
+ *args
61
+ )
62
+ end
63
+
64
+ # --
16
65
  # docker-template build [repos [opts]]
17
- # ----------------------------------------------------------------------
66
+ # --
18
67
 
19
- desc "build [REPOS [OPTS]]", "Build all (or some) of your repositories"
20
- option :diff, :type => :boolean, :desc => "Build only modified repositories."
21
- option :cache_only, :type => :boolean, :desc => "Only cache your repositories, don't build."
22
- option :clean_only, :type => :boolean, :desc => "Only clean your repositories, don't build."
23
- option :push_only, :type => :boolean, :desc => "Only push your repositories, don't build."
68
+ desc "build [REPOS [OPTS]]", "Build all (or some) of your repositories."
24
69
  option :profile, :type => :boolean, :desc => "Profile Memory."
25
70
  option :tty, :type => :boolean, :desc => "Enable TTY Output."
26
- option :push, :type => :boolean, :desc => "Push Repo After Building."
27
71
  option :cache, :type => :boolean, :desc => "Cache your repositories to cache."
28
- option :mocking, :type => :boolean, :desc => "Disable Certain Actions."
72
+ option :exclude, :type => :array, :desc => "Build everything except for these images."
73
+ option :debug, :type => :boolean, :desc => "Send the DEBUG=true env var to your instance."
74
+ option :diff, :type => :boolean, :desc => "Build only modified repositories."
75
+ option :push, :type => :boolean, :desc => "Push Repo After Building."
29
76
  option :clean, :type => :boolean, :desc => "Cleanup your caches."
77
+ option :force, :type => :boolean, :desc => "Force your build."
78
+ option :squash, :type => :boolean, :desc => "Squash the build."
79
+ option :help, :type => :boolean, :desc => "Output this."
30
80
 
31
- # ----------------------------------------------------------------------
81
+ # --
32
82
  # rubocop:disable Lint/RescueException
33
- # ----------------------------------------------------------------------
83
+ # --
34
84
 
35
85
  def build(*args)
36
- Build.new(args, options).start
86
+ return help(__method__) if options.help?
87
+ Build.new(args, options)
88
+ .start
37
89
 
38
90
  rescue Docker::Template::Error::StandardError => e
39
91
  $stderr.puts Simple::Ansi.red(e.message)
40
92
  exit e.respond_to?(:status) ? \
41
93
  e.status : 1
42
94
 
43
- rescue Exception
95
+ rescue Exception => _e
44
96
  raise unless $ERROR_POSITION
45
97
  $ERROR_POSITION.delete_if do |source|
46
98
  source =~ %r!#{Regexp.escape(
@@ -49,16 +101,18 @@ module Docker
49
101
  end
50
102
  end
51
103
 
52
- # ----------------------------------------------------------------------
104
+ # --
53
105
  # rubocop:enable Lint/RescueException
54
106
  # docker-template list [options]
55
- # ----------------------------------------------------------------------
107
+ # --
56
108
 
109
+ option :help, :type => :boolean, :desc => "Output this."
57
110
  desc "list [OPTS]", "List all possible builds."
58
111
 
59
- # ----------------------------------------------------------------------
112
+ # --
60
113
 
61
114
  def list
115
+ return help(__method__) if options.help?
62
116
  return $stdout.puts(
63
117
  List.build
64
118
  )
@@ -66,3 +120,6 @@ module Docker
66
120
  end
67
121
  end
68
122
  end
123
+
124
+ require "docker/template/cli/build"
125
+ require "docker/template/cli/list"