dockerun 0.3.6 → 0.4.1

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 (50) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +7 -11
  3. data/Rakefile +0 -2
  4. data/Rakefile.bak +8 -0
  5. data/dockerspec.sample +107 -0
  6. data/{dockerun.gemspec → dockerun.gemspec.bak} +20 -22
  7. data/exe/dockerun +15 -115
  8. data/lib/dockerun/cli/command.rb +140 -0
  9. data/lib/dockerun/cli/command_factory.rb +316 -0
  10. data/lib/dockerun/cli/command_result.rb +67 -0
  11. data/lib/dockerun/cli/delete_container.rb +59 -0
  12. data/lib/dockerun/cli/delete_image.rb +103 -0
  13. data/lib/dockerun/cli/run.rb +40 -0
  14. data/lib/dockerun/cli/user_info.rb +39 -0
  15. data/lib/dockerun/cli_engine.rb +122 -0
  16. data/lib/dockerun/config.rb +50 -85
  17. data/lib/dockerun/context/rubygems.rb +142 -0
  18. data/lib/dockerun/dfile.rb +204 -0
  19. data/lib/dockerun/docker_cli.rb +124 -0
  20. data/lib/dockerun/dsl.rb +342 -0
  21. data/lib/dockerun/version.rb +1 -1
  22. data/lib/dockerun.rb +32 -24
  23. data/sig/dockerun.rbs +4 -0
  24. metadata +62 -73
  25. data/.release_history.yml +0 -56
  26. data/Dockerfile.dockerun +0 -38
  27. data/Gemfile +0 -15
  28. data/Gemfile.lock +0 -94
  29. data/bin/console +0 -15
  30. data/bin/setup +0 -8
  31. data/lib/dockerun/bundler_helper.rb +0 -25
  32. data/lib/dockerun/cli_prompt.rb +0 -18
  33. data/lib/dockerun/command/dockerun.rb +0 -30
  34. data/lib/dockerun/command/init.rb +0 -79
  35. data/lib/dockerun/command/remove_container.rb +0 -99
  36. data/lib/dockerun/command/reset_image.rb +0 -107
  37. data/lib/dockerun/command/run.rb +0 -226
  38. data/lib/dockerun/command/run_new_container.rb +0 -94
  39. data/lib/dockerun/command/run_new_image.rb +0 -89
  40. data/lib/dockerun/command/stop_container.rb +0 -90
  41. data/lib/dockerun/docker_command_factory_helper.rb +0 -19
  42. data/lib/dockerun/docker_container_helper.rb +0 -213
  43. data/lib/dockerun/docker_image_helper.rb +0 -381
  44. data/lib/dockerun/template/general_template_writer.rb +0 -14
  45. data/lib/dockerun/template/jruby_template_writer.rb +0 -24
  46. data/lib/dockerun/template/template_engine.rb +0 -27
  47. data/lib/dockerun/template/template_writer.rb +0 -102
  48. data/lib/dockerun/user_info.rb +0 -37
  49. data/template/Dockerfile_general.erb +0 -41
  50. data/template/setup_ruby_devenv.rb.erb +0 -22
@@ -0,0 +1,316 @@
1
+
2
+ require 'erb'
3
+
4
+ require_relative 'command'
5
+ require_relative 'user_info'
6
+
7
+ module Dockerun
8
+ module Cli
9
+ class CommandFactory
10
+ include TR::CondUtils
11
+
12
+ def build_image(name = "", opts = { }, &block)
13
+
14
+ opts = { } if opts.nil?
15
+ cmd = []
16
+ cmd << "cd #{opts[:working_dir]} && " if not_empty?(opts[:working_dir])
17
+ cmd << DockerCli.docker_exe
18
+ cmd << "build"
19
+ if not_empty?(name)
20
+ cmd << "-t #{name}"
21
+ end
22
+
23
+ if not_empty?(opts[:dockerfile])
24
+ cmd << "-f #{opts[:dockerfile]}"
25
+ end
26
+
27
+ root = opts[:context_root]
28
+ root = "." if is_empty?(root)
29
+ cmd << root
30
+
31
+ logger.debug "Build Image : #{cmd.join(" ")}"
32
+ Command.new(cmd)
33
+
34
+ end # build_image
35
+
36
+
37
+ def find_image(name, tag = "", opts = { })
38
+ name = "" if name.nil?
39
+ cmd = []
40
+ cmd << DockerCli.docker_exe
41
+ cmd << "images"
42
+ cmd << "-q"
43
+ if not_empty?(tag)
44
+ cmd << "#{name}:#{tag}"
45
+ else
46
+ cmd << name
47
+ end
48
+
49
+ logger.debug "Find image: #{cmd.join(" ")}"
50
+
51
+ Command.new(cmd)
52
+ end # find_image
53
+
54
+ def delete_image(name, tag = "", opts = { })
55
+
56
+ if not_empty?(name)
57
+
58
+ cmd = []
59
+ cmd << DockerCli.docker_exe
60
+ cmd << "rmi"
61
+ if not_empty?(tag)
62
+ cmd << "#{name}:#{tag}"
63
+ else
64
+ cmd << name
65
+ end
66
+
67
+ logger.debug "Delete image: #{cmd.join(" ")}"
68
+ Command.new(cmd)
69
+
70
+ else
71
+ raise Error, "Name is required for delete operation"
72
+ end
73
+
74
+ end # delete_image
75
+
76
+
77
+ def find_running_container(name, opts = { })
78
+
79
+ raise Error, "Name is mandatory" if is_empty?(name)
80
+
81
+ cmd = []
82
+ cmd << DockerCli.docker_exe
83
+ cmd << "ps"
84
+ cmd << "-q"
85
+ cmd << "-f"
86
+ cmd << "name=\"#{name}\""
87
+
88
+ logger.debug "Find container: #{cmd.join(" ")}"
89
+
90
+ Command.new(cmd)
91
+
92
+ end
93
+
94
+ # Find from container even if it is already stopped
95
+ def find_from_all_container(name, opts = { })
96
+ raise Error, "Name is required" if is_empty?(name)
97
+ cmd = []
98
+ cmd << DockerCli.docker_exe
99
+ cmd << "ps"
100
+ # return all info instead of only the container ID
101
+ #cmd << "-a"
102
+ cmd << "-aq"
103
+ cmd << "-f"
104
+ # From little testing seems the command by default already support regex formatting
105
+ # So can use the regex marker to get exact match
106
+ # e.g. if want exact match, pass in ^#{name}\z
107
+ cmd << "name=\"#{name}\""
108
+
109
+ logger.debug "Find from all container: #{cmd.join(" ")}"
110
+ Command.new(cmd)
111
+ end
112
+
113
+
114
+ def find_container_names_by_image_name(image_name, opts = { })
115
+
116
+ raise Error, "Image name is mandatory" if is_empty?(image_name)
117
+
118
+ cmd = []
119
+ cmd << DockerCli.docker_exe
120
+ cmd << "ps"
121
+ cmd << "-a" if opts[:all_containers] == true
122
+ cmd << "-f"
123
+ cmd << "ancestor=\"#{image_name}\""
124
+ cmd << "--format \"{{.Names}}\""
125
+
126
+ logger.debug "Find container by image name: #{cmd.join(" ")}"
127
+
128
+ Command.new(cmd)
129
+
130
+ end
131
+
132
+
133
+ #
134
+ # Create container from image directly
135
+ # e.g. > docker run -it <image> "/bin/bash"
136
+ #
137
+ def create_container_from_image(image, opts = { })
138
+ opts = {} if opts.nil?
139
+ cmd = []
140
+ cmd << DockerCli.docker_exe
141
+ cmd << "run"
142
+ cmd << "-i" if opts[:interactive] == true
143
+ cmd << "-t" if opts[:tty] == true
144
+ cmd << "-d" if opts[:detached] == true
145
+ cmd << "--rm" if opts[:del] == true
146
+ if not (opts[:container_name].nil? or opts[:container_name].empty?)
147
+ cmd << "--name \"#{opts[:container_name]}\""
148
+ end
149
+
150
+ cmd << process_mount(opts)
151
+ cmd << process_port(opts)
152
+
153
+ if opts[:match_user] == true
154
+ ui = UserInfo.user_info
155
+ gi = UserInfo.group_info
156
+ cmd << "-u #{ui[:uid]}:#{gi[:gid]}"
157
+ end
158
+
159
+ cmd << image
160
+
161
+ if not_empty?(opts[:command])
162
+ cmd << "\"#{opts[:command]}\""
163
+ end
164
+
165
+ interactive = false
166
+ interactive = true if opts[:interactive] or opts[:tty]
167
+
168
+ logger.debug "Run Container from Image : #{cmd.join(" ")}"
169
+ Command.new(cmd, (interactive ? true : false))
170
+ end # run_container_from_image
171
+
172
+
173
+ def start_container(container, opts = { })
174
+
175
+ opts = {} if opts.nil?
176
+ cmd = []
177
+ cmd << DockerCli.docker_exe
178
+ cmd << "container"
179
+ cmd << "start"
180
+ cmd << container
181
+
182
+ logger.debug "Start Container : #{cmd.join(" ")}"
183
+ Command.new(cmd)
184
+ end
185
+
186
+
187
+ def attach_container(container, opts = { })
188
+
189
+ opts = {} if opts.nil?
190
+ cmd = []
191
+ cmd << DockerCli.docker_exe
192
+ cmd << "container"
193
+ cmd << "attach"
194
+ cmd << container
195
+
196
+ logger.debug "Attach Container : #{cmd.join(" ")}"
197
+ # this is a bit difficult to juggle
198
+ # it depending on the previous docker configuration
199
+ # but to be save, just open up a new terminal
200
+ Command.new(cmd, true)
201
+ end
202
+
203
+
204
+ def stop_container(container, opts = { })
205
+
206
+ cmd = []
207
+ cmd << DockerCli.docker_exe
208
+ cmd << "container"
209
+ cmd << "stop"
210
+ cmd << container
211
+
212
+ logger.debug "Stop Container : #{cmd.join(" ")}"
213
+ Command.new(cmd)
214
+ end
215
+
216
+
217
+ def delete_container(container, opts = { })
218
+
219
+ cmd = []
220
+ cmd << DockerCli.docker_exe
221
+ cmd << "container"
222
+ cmd << "rm"
223
+ cmd << container
224
+
225
+ logger.debug "Delete Container : #{cmd.join(" ")}"
226
+ Command.new(cmd)
227
+ end
228
+
229
+
230
+ def run_command_in_running_container(container, command, opts = { })
231
+ cmd = []
232
+ cmd << DockerCli.docker_exe
233
+ cmd << "container"
234
+ cmd << "exec"
235
+
236
+ isTty = false
237
+ isInteractive = false
238
+ if not_empty?(opts[:tty]) and opts[:tty] == true
239
+ cmd << "-t"
240
+ isTty = true
241
+ end
242
+ if not_empty?(opts[:interactive]) and opts[:interactive] == true
243
+ cmd << "-i"
244
+ isInteractive = true
245
+ end
246
+
247
+ cmd << container
248
+
249
+ if is_empty?(command)
250
+ cmd << "/bin/bash --login"
251
+ else
252
+ cmd << command
253
+ end
254
+
255
+ logger.debug "Run command in running container : #{cmd.join(" ")}"
256
+ Command.new(cmd, ((isTty or isInteractive) ? true : false))
257
+ end # container_prompt
258
+
259
+
260
+ private
261
+ # expecting :mounts => { "/dir/local" => "/dir/inside/docker" }
262
+ def process_mount(opts)
263
+ if not_empty?(opts[:mounts]) #not (opts[:mounts].nil? or opts[:mounts].empty?)
264
+ m = opts[:mounts]
265
+ if m.is_a?(Hash)
266
+ res = []
267
+ m.each do |local, docker|
268
+ res << "-v #{local}:#{docker}"
269
+ end
270
+ res.join(" ")
271
+ end
272
+ else
273
+ ""
274
+ end
275
+
276
+ end # process_mount
277
+
278
+ def process_port(opts)
279
+ if not_empty?(opts[:ports]) #not (opts[:ports].nil? or opts[:ports].empty?)
280
+ po = opts[:ports]
281
+ res = []
282
+ if po.is_a?(Hash)
283
+ po.each do |host, docker|
284
+ res << "-p #{host}:#{docker}"
285
+ end
286
+ end
287
+ #po = [po] if not po.is_a?(Array)
288
+ #po.each do |e|
289
+ # # 1st is port on host
290
+ # # 2nd is port inside container
291
+ # res << "-p #{e.keys.first}:#{e.values.first}"
292
+ #end
293
+ res.join(" ")
294
+ else
295
+ ""
296
+ end
297
+
298
+ end
299
+
300
+ def logger
301
+ Dockerun.logger(:cmdFact)
302
+ end
303
+
304
+ def build_add_user_script
305
+ path = File.join(File.dirname(__FILE__),"..","..","..","scripts","create_user.sh.erb")
306
+ if File.exist?(path)
307
+ ui = UserInfo.user_info
308
+ gi = UserInfo.group_info
309
+
310
+ ERB.new(File.read(path)).result_with_hash({ user_group_id: gi[:gid], user_group_name: gi[:group_name], user_id: ui[:uid], user_login: ui[:login] })
311
+ end
312
+ end
313
+
314
+ end
315
+ end
316
+ end
@@ -0,0 +1,67 @@
1
+
2
+ require 'toolrack'
3
+
4
+ module Dockerun
5
+
6
+ module Cli
7
+
8
+ class CommandResult
9
+ include TR::CondUtils
10
+
11
+ attr_reader :out, :err, :result
12
+ def initialize(result, out, err)
13
+ @result = result
14
+ @out = out
15
+ @err = err
16
+ end
17
+
18
+ def is_out_stream_empty?
19
+ is_empty?(@out)
20
+ end
21
+
22
+ def is_err_stream_empty?
23
+ is_empty?(@err)
24
+ end
25
+
26
+ def out_stream
27
+ @out.join("\n")
28
+ end
29
+
30
+ def err_stream
31
+ @err.join("\n")
32
+ end
33
+
34
+ def failed?
35
+ if @result.nil?
36
+ true
37
+ else
38
+ @result.failed?
39
+ end
40
+ end
41
+
42
+ def success?
43
+ not failed?
44
+ end
45
+ alias_method :successful?, :success?
46
+
47
+ def each_output_line(&block)
48
+ out_stream.each_line(&block)
49
+ end
50
+
51
+ def each_err_lines(&block)
52
+ err_stream.each_line(&block)
53
+ end
54
+
55
+ def output_lines
56
+ out_stream.lines
57
+ end
58
+
59
+ def err_lines
60
+ err_stream.lines
61
+ end
62
+
63
+ end
64
+
65
+ end
66
+
67
+ end
@@ -0,0 +1,59 @@
1
+
2
+ require_relative 'command_factory'
3
+
4
+ module Dockerun
5
+ module Cli
6
+ class DSLProxy
7
+ include DSL
8
+ end
9
+
10
+ class DeleteContainer
11
+
12
+ def initialize
13
+ @proxy = DSLProxy.new
14
+ end
15
+
16
+ def start(root)
17
+ @proxy.set_exec_root(root)
18
+ begin
19
+ pmt.puts " Dockerun version #{Dockerun::VERSION}".yellow
20
+ pmt.puts " Operational : Delete Container"
21
+ delete_container
22
+ rescue TTY::Reader::InputInterrupt
23
+ end
24
+ end
25
+
26
+ def delete_container
27
+ selSpec = CliEngine.select_spec(@proxy.exec_root)
28
+ cont = File.read(selSpec)
29
+ @proxy.set_dry_run_mode
30
+ @proxy.instance_eval(cont)
31
+
32
+ skip = pmt.no?(" Delete container named '#{@proxy.container_name}'?")
33
+ if not skip
34
+ cf.stop_container(@proxy.container_name).run
35
+ res = cf.delete_container(@proxy.container_name).run
36
+ if res.success?
37
+ pmt.puts " Container '#{@proxy.container_name}' deleted".green
38
+ else
39
+ pmt.puts " Container '#{@proxy.container_name}' deletion failed. Error was : #{res.err_lines.join("\n")}".red
40
+ end
41
+ else
42
+ pmt.puts " Container deletion of name '#{@proxy.container_name}' aborted.".yellow
43
+ end
44
+ end
45
+
46
+ def pmt
47
+ CliEngine.pmt
48
+ end
49
+
50
+ def cf
51
+ if @_cf.nil?
52
+ @_cf = CommandFactory.new
53
+ end
54
+ @_cf
55
+ end
56
+
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,103 @@
1
+
2
+ require_relative 'command_factory'
3
+
4
+ module Dockerun
5
+ module Cli
6
+ class DSLProxy
7
+ include DSL
8
+ end
9
+
10
+ class DeleteImage
11
+ include TR::CondUtils
12
+
13
+ def initialize
14
+ @proxy = DSLProxy.new
15
+ end
16
+
17
+ def start(root)
18
+ @proxy.set_exec_root(root)
19
+ begin
20
+ pmt.puts " Dockerun version #{Dockerun::VERSION}".yellow
21
+ pmt.puts " Operational : Delete Image"
22
+ delete_image
23
+ rescue TTY::Reader::InputInterrupt
24
+ end
25
+ end
26
+
27
+ def delete_image
28
+ selSpec = CliEngine.select_spec(@proxy.exec_root)
29
+ cont = File.read(selSpec)
30
+ @proxy.set_dry_run_mode
31
+ @proxy.instance_eval(cont)
32
+
33
+ res = cf.find_image(@proxy.image_name).run
34
+ if res.success?
35
+ if not_empty?(res.output_lines)
36
+
37
+ skip = pmt.no?(" Delete image named '#{@proxy.image_name}'?")
38
+ if not skip
39
+ res = cf.find_container_names_by_image_name(@proxy.image_name, all_containers: true).run
40
+ raise Error, "Failed to extract container name by image name '#{@proxy.image_name}'" if not res.success?
41
+
42
+ if not_empty?(res.output_lines)
43
+ cont = []
44
+ cnt = 0
45
+ res.output_lines.each do |l|
46
+ cont << " #{cnt += 1}. #{l}"
47
+ end
48
+ skip = pmt.no?(" All the containers shall be deleted prior to image '#{@proxy.image_name}' deletion. Proceed?\n#{cont.join("\n")}")
49
+ if not skip
50
+ res.output_lines.each do |ci|
51
+ cf.stop_container(ci).run
52
+ cf.delete_container(ci).run
53
+ end
54
+
55
+ res = cf.delete_image(@proxy.image_name).run
56
+ if res.success?
57
+ pmt.puts " Image '#{@proxy.image_name}' deleted".green
58
+ else
59
+ raise Error, " Image '#{@proxy.image_name}' deletion failed. Error was : #{res.err_lines.join("\n")}"
60
+ end
61
+
62
+ else
63
+ pmt.puts " Delete of image '#{@proxy.image_name}' aborted".yellow
64
+ end
65
+
66
+ else
67
+ res = cf.delete_image(@proxy.image_name).run
68
+ if res.success?
69
+ pmt.puts " Image '#{@proxy.image_name}' deleted".green
70
+ else
71
+ raise Error, " Image '#{@proxy.image_name}' deletion failed. Error was : #{res.err_lines.join("\n")}"
72
+ end
73
+
74
+ end
75
+
76
+ else
77
+ pmt.puts " Delete of image '#{@proxy.image_name}' aborted".yellow
78
+
79
+ end
80
+
81
+ else
82
+ pmt.puts " Image '#{@proxy.image_name}' does not exist".green
83
+ end
84
+
85
+ else
86
+ pmt.puts " Failed to find image '#{@proxy.image_name}'. Error was : #{res.err_lines.join("\n")}"
87
+ end
88
+ end
89
+
90
+ def pmt
91
+ CliEngine.pmt
92
+ end
93
+
94
+ def cf
95
+ if @_cf.nil?
96
+ @_cf = CommandFactory.new
97
+ end
98
+ @_cf
99
+ end
100
+
101
+ end
102
+ end
103
+ end
@@ -0,0 +1,40 @@
1
+
2
+ require 'tty/prompt'
3
+ require 'colorize'
4
+
5
+ module Dockerun
6
+ module Cli
7
+ class Run
8
+ #include TR::ArgUtils
9
+ include DSL
10
+
11
+ def start(root)
12
+ set_exec_root(root)
13
+ begin
14
+ pmt.puts " Dockerun version #{Dockerun::VERSION}".yellow
15
+ pmt.puts " Operational : Run Spec"
16
+ load_spec
17
+ rescue TTY::Reader::InputInterrupt
18
+ end
19
+ end
20
+
21
+
22
+ private
23
+ def load_spec
24
+ selSpec = CliEngine.select_spec(exec_root)
25
+ pmt.puts " Loading spec '#{selSpec}"
26
+ cont = File.read(selSpec)
27
+ self.instance_eval(cont)
28
+ go if not is_go_done?
29
+ end
30
+
31
+ def pmt
32
+ if @_pmt.nil?
33
+ @_pmt = TTY::Prompt.new
34
+ end
35
+ @_pmt
36
+ end
37
+
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,39 @@
1
+
2
+ require 'etc'
3
+
4
+ module Dockerun
5
+ module Cli
6
+
7
+ module UserInfo
8
+ include TR::CondUtils
9
+
10
+ def self.user_info(login = nil)
11
+ login = Etc.getlogin if is_empty?(login)
12
+ res = { login: login }
13
+ begin
14
+ res[:uid] = Etc.getpwnam(login).uid
15
+ rescue Exception => ex
16
+ res[:uid] = nil
17
+ end
18
+ res
19
+ end
20
+
21
+ def self.group_info(login = nil)
22
+ login = Etc.getlogin if is_empty?(login)
23
+ res = { }
24
+ begin
25
+ gnm = Etc.getgrnam(login)
26
+ res[:group_name] = gnm.name
27
+ res[:gid] = gnm.gid
28
+ rescue Exception => ex
29
+ p ex
30
+ res[:group_name] = ""
31
+ res[:gid] = nil
32
+ end
33
+ res
34
+ end
35
+
36
+ end
37
+ end
38
+
39
+ end