dockerun 0.3.6 → 0.4.1

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