docker-template 0.8.0 → 0.10.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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"