docker-cli 0.3.0 → 0.5.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.
@@ -1,12 +1,15 @@
1
1
 
2
+ require 'erb'
3
+
2
4
  require_relative 'command'
5
+ require_relative 'user_info'
3
6
 
4
7
  module Docker
5
8
  module Cli
6
9
  class CommandFactory
7
10
  include TR::CondUtils
8
11
 
9
- def build_image(name = "", opts = { })
12
+ def build_image(name = "", opts = { }, &block)
10
13
 
11
14
  opts = { } if opts.nil?
12
15
  cmd = []
@@ -37,9 +40,9 @@ module Docker
37
40
  cmd << "images"
38
41
  cmd << "-q"
39
42
  if not_empty?(tag)
40
- cmd << "#{name}:#{tag}"
43
+ cmd << "\"#{name}:#{tag}\""
41
44
  else
42
- cmd << name
45
+ cmd << "\"#{name}\""
43
46
  end
44
47
 
45
48
  logger.debug "Find image: #{cmd.join(" ")}"
@@ -79,7 +82,7 @@ module Docker
79
82
  cmd << "ps"
80
83
  cmd << "-q"
81
84
  cmd << "-f"
82
- cmd << "name=#{name}"
85
+ cmd << "name=\"#{name}\""
83
86
 
84
87
  logger.debug "Find container: #{cmd.join(" ")}"
85
88
 
@@ -106,6 +109,10 @@ module Docker
106
109
  Command.new(cmd)
107
110
  end
108
111
 
112
+ #
113
+ # Create container from image directly
114
+ # e.g. > docker run -it <image> "/bin/bash"
115
+ #
109
116
  def create_container_from_image(image, opts = { })
110
117
  opts = {} if opts.nil?
111
118
  cmd = []
@@ -113,13 +120,21 @@ module Docker
113
120
  cmd << "run"
114
121
  cmd << "-i" if opts[:interactive] == true
115
122
  cmd << "-t" if opts[:tty] == true
123
+ cmd << "-d" if opts[:detached] == true
124
+ cmd << "--rm" if opts[:del] == true
116
125
  if not (opts[:container_name].nil? or opts[:container_name].empty?)
117
- cmd << "--name #{opts[:container_name]}"
126
+ cmd << "--name \"#{opts[:container_name]}\""
118
127
  end
119
128
 
120
129
  cmd << process_mount(opts)
121
130
  cmd << process_port(opts)
122
131
 
132
+ if opts[:match_user] == true
133
+ ui = UserInfo.user_info
134
+ gi = UserInfo.group_info
135
+ cmd << "-u #{ui[:uid]}:#{gi[:gid]}"
136
+ end
137
+
123
138
  cmd << image
124
139
 
125
140
  if not_empty?(opts[:command])
@@ -128,7 +143,7 @@ module Docker
128
143
 
129
144
  interactive = false
130
145
  interactive = true if opts[:interactive] or opts[:tty]
131
-
146
+
132
147
  logger.debug "Run Container from Image : #{cmd.join(" ")}"
133
148
  Command.new(cmd, (interactive ? true : false))
134
149
  end # run_container_from_image
@@ -220,17 +235,17 @@ module Docker
220
235
 
221
236
 
222
237
  private
223
- # expecting :mounts => [{ "/dir/local" => "/dir/inside/docker" }]
238
+ # expecting :mounts => { "/dir/local" => "/dir/inside/docker" }
224
239
  def process_mount(opts)
225
- if not (opts[:mount].nil? or opts[:mount].empty?)
226
- m = opts[:mount]
227
- m = [m] if not m.is_a?(Array)
228
- res = []
229
- m.each do |mm|
230
- host = mm.keys.first
231
- res << "-v #{host}:#{mm[host]}"
240
+ if not_empty?(opts[:mounts]) #not (opts[:mounts].nil? or opts[:mounts].empty?)
241
+ m = opts[:mounts]
242
+ if m.is_a?(Hash)
243
+ res = []
244
+ m.each do |local, docker|
245
+ res << "-v #{local}:#{docker}"
246
+ end
247
+ res.join(" ")
232
248
  end
233
- res.join(" ")
234
249
  else
235
250
  ""
236
251
  end
@@ -238,13 +253,20 @@ module Docker
238
253
  end # process_mount
239
254
 
240
255
  def process_port(opts)
241
- if not (opts[:ports].nil? or opts[:ports].empty?)
256
+ if not_empty?(opts[:ports]) #not (opts[:ports].nil? or opts[:ports].empty?)
242
257
  po = opts[:ports]
243
- po = [po] if not po.is_a?(Array)
244
258
  res = []
245
- po.each do |host,docker|
246
- res << "-p #{host}:#{docker}"
259
+ if po.is_a?(Hash)
260
+ po.each do |host, docker|
261
+ res << "-p #{host}:#{docker}"
262
+ end
247
263
  end
264
+ #po = [po] if not po.is_a?(Array)
265
+ #po.each do |e|
266
+ # # 1st is port on host
267
+ # # 2nd is port inside container
268
+ # res << "-p #{e.keys.first}:#{e.values.first}"
269
+ #end
248
270
  res.join(" ")
249
271
  else
250
272
  ""
@@ -253,15 +275,17 @@ module Docker
253
275
  end
254
276
 
255
277
  def logger
256
- if @logger.nil?
257
- @logger = TeLogger::Tlogger.new
258
- @logger.tag = :docker_cmd
259
- end
260
- @logger
278
+ Cli.logger(:cmdFact)
261
279
  end
262
280
 
263
- def parse_container_list(out, &block)
264
-
281
+ def build_add_user_script
282
+ path = File.join(File.dirname(__FILE__),"..","..","..","scripts","create_user.sh.erb")
283
+ if File.exist?(path)
284
+ ui = UserInfo.user_info
285
+ gi = UserInfo.group_info
286
+
287
+ 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] })
288
+ end
265
289
  end
266
290
 
267
291
  end
@@ -19,6 +19,10 @@ module Docker
19
19
  is_empty?(@out)
20
20
  end
21
21
 
22
+ def is_err_stream_empty?
23
+ is_empty?(@err)
24
+ end
25
+
22
26
  def out_stream
23
27
  @out.join("\n")
24
28
  end
@@ -35,6 +39,18 @@ module Docker
35
39
  end
36
40
  end
37
41
 
42
+ def success?
43
+ not failed?
44
+ end
45
+ alias_method :successful?, :success?
46
+
47
+ def each_line(&block)
48
+ out_stream.each_line(&block)
49
+ end
50
+
51
+ def lines
52
+ out_stream.lines
53
+ end
38
54
  end
39
55
 
40
56
  end
@@ -0,0 +1,113 @@
1
+
2
+ require 'yaml'
3
+
4
+ require_relative 'user_info'
5
+
6
+ module Docker
7
+ module Cli
8
+ class DockerComposer
9
+ include TR::CondUtils
10
+ include TR::ArgUtils
11
+
12
+ arg_spec do
13
+
14
+ callback :pre_processing do |a|
15
+ parse_input(a)
16
+ end
17
+
18
+ end
19
+
20
+ def parse_input(argv, &block)
21
+ @dcPath = argv.first
22
+ @dcPath = "./docker-compose.yml" if is_empty?(@dcPath)
23
+ @dcPath = "./docker-compose.yaml" if not File.exist?(@dcPath)
24
+ raise RuntimeException, "docker-compose.[yml,yaml] not found. Please provide the docker-compose.yml file to load" if not File.exist?(@dcPath)
25
+
26
+ @outPath = argv[1]
27
+ @outPath = "#{@dcPath}-gen.yml" if is_empty?(@outPath)
28
+
29
+ process_dc
30
+
31
+ [true, []]
32
+ end
33
+
34
+ def process_dc
35
+ if File.exist?(@dcPath)
36
+
37
+ cont = YAML.safe_load(File.read(@dcPath))
38
+
39
+ if not_empty?(cont["services"])
40
+
41
+ cont["services"].each do |servName, conf|
42
+
43
+ # if user key is empty, match with current uid and gid
44
+ if conf.keys.include?("user") and is_empty?(conf["user"])
45
+ conf["user"] = "#{user_info[:uid]}:#{user_group_info[:gid]}"
46
+ end
47
+
48
+ # add to volumes if there is development gems found
49
+ if not_empty?(conf["volumes"])
50
+ vol = conf["volumes"]
51
+
52
+ if vol.include?("devgems")
53
+
54
+ vol.delete("devgems")
55
+ logger.debug "Volume after delete : #{vol.inspect}"
56
+
57
+ devGems = Cli.find_dev_gems
58
+ logger.debug " Found #{devGems.length} devgems"
59
+ if devGems.length > 0
60
+ if @parse_argv_block
61
+ @mount_root = @parse_argv_block.call(:prompt_docker_mount_root)
62
+ else
63
+ raise RuntimeException, "Please provide a block to prompt for missing parameters"
64
+ end
65
+
66
+ devGems.each do |name,path|
67
+ vol << "#{path}:#{File.join(@mount_root, name)}"
68
+ end
69
+ end
70
+
71
+ end
72
+
73
+ end
74
+ end
75
+
76
+ end
77
+
78
+ reCont = cont.to_yaml
79
+ reCont = reCont.gsub("---","")
80
+ File.open(@outPath, "w") do |f|
81
+ f.write reCont
82
+ end
83
+
84
+ else
85
+ raise RuntimeException, "Given docker compose file '#{@dcPath}' does not exist"
86
+ end
87
+ end
88
+
89
+ private
90
+ def user_info
91
+ if @_user_info.nil?
92
+ @_user_info = UserInfo.user_info
93
+ end
94
+ @_user_info
95
+ end
96
+
97
+ def user_group_info
98
+ if @_userg_info.nil?
99
+ @_userg_info = UserInfo.group_info
100
+ end
101
+ @_userg_info
102
+ end
103
+
104
+ def logger
105
+ if @_logger.nil?
106
+ @_logger = Cli.logger(:docomp)
107
+ end
108
+ @_logger
109
+ end
110
+
111
+ end
112
+ end
113
+ end
@@ -0,0 +1,216 @@
1
+
2
+ require_relative 'command_factory'
3
+
4
+ module Docker
5
+ module Cli
6
+
7
+ # only use during creation of new container
8
+ class ContainerProfile
9
+ include TR::CondUtils
10
+
11
+ attr_accessor :run_command, :image_name
12
+ def initialize
13
+ @interactive = true
14
+ @run_detached = false
15
+ @remove_after_run = false
16
+ @match_user = false
17
+ @run_command = "/bin/bash"
18
+ @mounts = {}
19
+ @ports = {}
20
+ end
21
+
22
+ def mount_points
23
+ @mounts.freeze
24
+ end
25
+ def add_mount_point(host, inside_docker)
26
+ if not_empty?(host) and not_empty?(inside_docker)
27
+ @mounts[host] = inside_docker
28
+ end
29
+ end
30
+
31
+ def ports
32
+ @ports.freeze
33
+ end
34
+ def add_port_mapping(host, docker)
35
+ if not_empty?(host) and not_empty?(docker)
36
+ @ports[host] = docker
37
+ end
38
+ end
39
+
40
+ def is_interactive?
41
+ @interactive
42
+ end
43
+ def interactive=(val)
44
+ @interactive = val
45
+ end
46
+
47
+ def is_run_detached?
48
+ @run_detached
49
+ end
50
+ def run_detached=(val)
51
+ @run_detached = val
52
+ end
53
+
54
+ def remove_after_run?
55
+ @remove_after_run
56
+ end
57
+ def remove_after_run=(val)
58
+ @remove_after_run = val
59
+ end
60
+
61
+ def is_match_user?
62
+ @match_user
63
+ end
64
+ def match_user=(val)
65
+ @match_user = val
66
+ end
67
+
68
+ def to_hash
69
+ # this returns a hash that match expectation of input in CommandFactory.create_container_from_image
70
+ { interactive: @interactive, tty: @interactive, detached: @run_detached, del: @remove_after_run, mounts: @mounts, ports: @ports, match_user: @match_user, command: @run_command }
71
+ end
72
+
73
+ end # class NewContainerProfile
74
+
75
+ class DockerContainer
76
+ include TR::CondUtils
77
+
78
+ #def self.is_exists?(name)
79
+ # res = command.find_from_all_container(name, opts).run
80
+ # raise CommandFailed, "Command to check if container exist failed. Error was : #{res.err_stream}" if not res.successful?
81
+ # not res.is_out_stream_empty?
82
+ #end
83
+
84
+ #def self.create(image, opts = {}, &block)
85
+ # command.create_container_from_image(image, opts).run
86
+ #end
87
+
88
+ #def self.prep_container(image, opts = {})
89
+ # # render the create_user script
90
+ # res = build_add_user_script
91
+ # # system always mount current dir inside docker
92
+ # dest = File.join(opts[:mount_local],"create_user.sh")
93
+ # File.open(dest,"w") do |f|
94
+ # f.write res
95
+ # end
96
+ # `chmod +x #{dest}`
97
+
98
+ # # create non interactive session to create the user & group first
99
+ # opts[:command] = "#{File.join(opts[:mount_docker],"create_user.sh")}"
100
+ # opts[:detached] = true
101
+ # command.create_container_from_image(image, opts).run
102
+ #end
103
+
104
+ def self.containers_of_image_from_history(img, opts = { })
105
+ cont = DockerRunLog.instance.containers(img)
106
+ res = {}
107
+ if cont.length == 1
108
+ c = cont.first
109
+ res[c[:container]] = c
110
+ else
111
+ cont.each do |c|
112
+ res[c[:container]] = "#{c[:container]} [Last Access : #{Time.at(c[:last_run])}] - Config : #{c[:argv]}"
113
+ end
114
+ res
115
+ end
116
+ end
117
+
118
+ #def self.containers(image = nil)
119
+ #
120
+ #end
121
+
122
+ #def self.container(name)
123
+ #
124
+ #end
125
+
126
+ attr_reader :name
127
+
128
+ def initialize(name, history = nil)
129
+ @name = name
130
+ @history = history
131
+ end
132
+
133
+ def is_exist?
134
+ res = command.find_from_all_container(@name).run
135
+ raise CommandFailed, "Command to check if container exist failed. Error was : #{res.err_stream}" if not res.successful?
136
+ not res.is_out_stream_empty?
137
+ end
138
+
139
+ def create(container_profile)
140
+ raise CommandFailed, " Image name is not given to create the container '#{@name}'" if is_empty?(container_profile.image_name)
141
+ opts = container_profile.to_hash
142
+ opts[:container_name] = @name
143
+ command.create_container_from_image(container_profile.image_name, opts).run
144
+ end
145
+
146
+ def name_for_display
147
+ if @history.nil?
148
+ @name
149
+ else
150
+ "#{@history[:container]} [Last Access : #{Time.at(@history[:last_run])}] - Config : #{@history[:argv]}"
151
+ end
152
+ end
153
+
154
+ def run_before?
155
+ not @history.nil?
156
+ end
157
+
158
+ def history
159
+ if not @history.nil?
160
+ @history.freeze
161
+ else
162
+ @history = {}
163
+ end
164
+ end
165
+
166
+ def is_running?
167
+ res = command.find_running_container(@name).run
168
+ raise CommandFailed, "Command to find running container failed. Error was : #{res.err_stream}" if not res.successful?
169
+ not res.is_out_stream_empty?
170
+ end
171
+
172
+ def start(&block)
173
+ command.start_container(@name).run
174
+ end
175
+
176
+ def stop(&block)
177
+ command.stop_container(@name).run
178
+ end
179
+
180
+ def attach(&block)
181
+ command.attach_container(@name).run
182
+ end
183
+
184
+ def delete!(&block)
185
+ command.delete_container(@name).run
186
+ end
187
+
188
+ def run(cmd, opts = {}, &block)
189
+ command.run_command_in_running_container(@name, cmd, opts).run
190
+ end
191
+
192
+ private
193
+ def self.command
194
+ if @_cmd.nil?
195
+ @_cmd = CommandFactory.new
196
+ end
197
+ @_cmd
198
+ end
199
+
200
+ def command
201
+ self.class.command
202
+ end
203
+
204
+ def self.build_add_user_script
205
+ path = File.join(File.dirname(__FILE__),"..","..","..","scripts","create_user.sh.erb")
206
+ if File.exist?(path)
207
+ ui = UserInfo.user_info
208
+ gi = UserInfo.group_info
209
+
210
+ 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] })
211
+ end
212
+ end
213
+
214
+ end
215
+ end
216
+ end