dockdev 0.3.8 → 0.4.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: aef435aebef51b0a8aa6535d4f75b6ea8151bd7c474e15547421cc31d7e4dfbc
4
- data.tar.gz: 727d3c78e3c9ae406e4e0dda8c399cced4e86a6c79c4f899d06f626cf365f7d3
3
+ metadata.gz: dc457c18386138fb748fcc182da23a0a53613bcdfad90288ff2e4f553fe81ab7
4
+ data.tar.gz: 6a9d639a8a4a09f76c3948cead657f50688e42c0aaada6f45222dd766b45e947
5
5
  SHA512:
6
- metadata.gz: 81a9a8152486d15d21db57fcaf83a95480bd948c500c28aef61bb3b1f321d5d2d39c5c1d07eb782905ff48b3e763a1db9bf284da78dcc3258d172b6e237684b7
7
- data.tar.gz: 1f9a94feef8e90938743c97623671dcf37ee96153723db7e3f1964c2d0ca08ef8cfbf2bdabc78946c33f37dcbb002a1106c42c6e3b3958a60463e62826876809
6
+ metadata.gz: fa1e22aafc5d128eef30ab82e3b5545d616efda9c30eccc5e85a414aa0638b260be020d3d4d376cceeca0197417f3b9f61098c7fbd607f68576e218ce00e40aa
7
+ data.tar.gz: 677f6dcc88a354185760d1abed3064f8292352ae9f6efb08c4493f1ac42f45eccdb25e70e5ea4b71708aa2cd458ce42de6d3704edcbc658b812f7d257a58e768
data/exe/dockdev CHANGED
@@ -7,13 +7,19 @@
7
7
 
8
8
  require_relative '../lib/dockdev'
9
9
 
10
- contName = ARGV.first || File.basename(Dir.getwd)
11
- cmd = ARGV[1]
10
+ #contName = ARGV.first || File.basename(Dir.getwd)
11
+ #cmd = ARGV[1]
12
+ #input = ARGV[1]
13
+
14
+ uconf = Dockdev::UserConfig.new(ARGV.first)
15
+ contName = uconf.container_name || File.basename(Dir.getwd)
12
16
 
13
17
  begin
14
- Dockdev.with_running_container(contName, command: cmd, root: Dir.getwd)
18
+ #Dockdev.with_running_container(contName, command: cmd, root: Dir.getwd)
19
+ Dockdev.with_running_container(contName, user_config: uconf, root: Dir.getwd)
15
20
  rescue StandardError => ex
16
21
  STDERR.puts ex.message
22
+ STDERR.puts ex.backtrace.join("\n")
17
23
  end
18
24
 
19
25
 
@@ -69,5 +69,6 @@ module Dockdev
69
69
  end
70
70
  end
71
71
 
72
+
72
73
  end
73
74
  end
@@ -88,14 +88,20 @@ module Dockdev
88
88
  [@mounts, @ports]
89
89
  end
90
90
 
91
- def process_mount(opts = {}, &block)
92
- mounts, _ = parse_docker_compose
93
- mounts
94
- end
91
+ def apply_context(dockdev_config)
92
+ ddConf = dockdev_config
93
+
94
+ if not ddConf.nil?
95
+ mounts, ports = parse_docker_compose
96
+ mounts.each do |host, docker|
97
+ ddConf.add_mount(host, docker)
98
+ end
99
+ ports.each do |host, docker|
100
+ ddConf.add_port(host, docker)
101
+ end
102
+ end
95
103
 
96
- def process_port(opts = {}, &block)
97
- _, ports = parse_docker_compose
98
- ports
104
+ ddConf
99
105
  end
100
106
 
101
107
  private
@@ -4,6 +4,7 @@ require 'bundler'
4
4
  module Dockdev
5
5
  module Context
6
6
  class Rubygems
7
+ include TR::CondUtils
7
8
 
8
9
  def self.init_path(path)
9
10
  Rubygems.new(path)
@@ -23,15 +24,10 @@ module Dockdev
23
24
  Dir.glob(File.join(@path,"Gemfile"))
24
25
  end
25
26
 
26
- def process_mount(opts = { dir_inside_docker: "/opt" })
27
+ def apply_context(dockdev_config)
28
+ ddConf = dockdev_config
27
29
 
28
- if @mounts.empty?
29
-
30
- dir_inside_docker = opts[:dir_inside_docker]
31
-
32
- script = ["#!/bin/bash"]
33
- #script << "alias be > /dev/null 2>&1 && echo 'alias be=bundle exec' >> ~/.bashrc"
34
- script << "echo 'alias be=\"bundle exec\"' >> ~/.bashrc"
30
+ if not_empty?(ddConf)
35
31
 
36
32
  #
37
33
  # looking at source code
@@ -39,33 +35,91 @@ module Dockdev
39
35
  # seems this is the way to set root for Bundler
40
36
  #
41
37
  ENV['BUNDLE_GEMFILE'] = find_gemfile.first
42
- Bundler.load.dependencies.each do |d|
43
- if not d.source.nil?
44
- src = d.source
45
- if src.path.to_s != "."
46
- pathInsideDocker = File.join(dir_inside_docker, d.name)
47
- @mounts[src.path.expand_path.to_s] = pathInsideDocker
48
- script << "bundle config --global local.#{d.name} #{pathInsideDocker}"
49
- #res[d.name] = src.path.expand_path.to_s
38
+ if not_empty?(ENV['BUNDLE_GEMFILE'])
39
+
40
+ cmd = ["echo 'alias be = \"bundle exec\"' >> /etc/bash.bashrc"]
41
+
42
+ Bundler.load.dependencies.each do |d|
43
+ if not d.source.nil?
44
+ src = d.source
45
+ if src.path.to_s != "."
46
+ pathInsideDocker = File.join(ddConf.workdir, d.name)
47
+ ddConf.add_mount(src.path.expand_path.to_s,pathInsideDocker)
48
+ # following line assumed 'bundle' program already installed inside the image
49
+ cmd << "bundle config --global local.#{d.name} #{pathInsideDocker}"
50
+ end
50
51
  end
51
52
  end
52
- end
53
53
 
54
- scriptOut = File.join(@path,"to-be-executed-once-inside-docker.sh")
55
- File.open(scriptOut,"w") do |f|
56
- f.write script.join("\n")
54
+ if not_empty?(cmd)
55
+
56
+ script = ["#!/bin/bash"]
57
+ script << "if ! command -v bundle &> /dev/null"
58
+ script << " echo \"Command 'bundle' is available!\""
59
+ script.concat(cmd.collect { |e| " #{e}"})
60
+ script << "then"
61
+ script << " echo \"Command 'bundle' not available\""
62
+ #script << " exit 1"
63
+ script << "fi"
64
+
65
+ File.open("rubygems_init.sh","w") do |f|
66
+ f.write script.join("\n")
67
+ end
68
+
69
+ ddConf.append_Dockerfile("COPY rubygems_init.sh /tmp/rubygems_init.sh")
70
+ ddConf.append_Dockerfile("RUN chmod +x /tmp/rubygems_init.sh && /tmp/rubygems_init.sh")
71
+ end
72
+
57
73
  end
58
- `chmod +x #{scriptOut}`
59
74
 
60
75
  end
61
76
 
62
- @mounts
63
-
77
+ ddConf
64
78
  end
65
79
 
66
- def process_port(opts = {})
67
- @ports
68
- end
80
+ #def process_mount(opts = { dir_inside_docker: "/opt" })
81
+
82
+ # if @mounts.empty?
83
+
84
+ # dir_inside_docker = opts[:dir_inside_docker]
85
+
86
+ # script = ["#!/bin/bash"]
87
+ # #script << "alias be > /dev/null 2>&1 && echo 'alias be=bundle exec' >> ~/.bashrc"
88
+ # script << "echo 'alias be=\"bundle exec\"' >> ~/.bashrc"
89
+
90
+ # #
91
+ # # looking at source code
92
+ # # https://github.com/rubygems/rubygems/blob/master/bundler/lib/bundler/shared_helpers.rb#L246
93
+ # # seems this is the way to set root for Bundler
94
+ # #
95
+ # ENV['BUNDLE_GEMFILE'] = find_gemfile.first
96
+ # Bundler.load.dependencies.each do |d|
97
+ # if not d.source.nil?
98
+ # src = d.source
99
+ # if src.path.to_s != "."
100
+ # pathInsideDocker = File.join(dir_inside_docker, d.name)
101
+ # @mounts[src.path.expand_path.to_s] = pathInsideDocker
102
+ # script << "bundle config --global local.#{d.name} #{pathInsideDocker}"
103
+ # #res[d.name] = src.path.expand_path.to_s
104
+ # end
105
+ # end
106
+ # end
107
+
108
+ # scriptOut = File.join(@path,"to-be-executed-once-inside-docker.sh")
109
+ # File.open(scriptOut,"w") do |f|
110
+ # f.write script.join("\n")
111
+ # end
112
+ # `chmod +x #{scriptOut}`
113
+
114
+ # end
115
+
116
+ # @mounts
117
+
118
+ #end
119
+
120
+ #def process_port(opts = {})
121
+ # @ports
122
+ #end
69
123
 
70
124
  end
71
125
  end
@@ -14,12 +14,26 @@ module Dockdev
14
14
  @ctx[name] = cls
15
15
  end
16
16
 
17
+ def registered_context
18
+ @ctx.keys.freeze
19
+ end
20
+
21
+ def registered_context_by_name(name, path)
22
+ ctx = @ctx[id]
23
+ if not ctx.nil?
24
+ ctx.init_path(path)
25
+ end
26
+
27
+ ctx
28
+ end
29
+
17
30
  def get_context(path)
18
- ctx = []
19
- @ctx.values.each do |v|
31
+ ctx = {}
32
+ @ctx.each do |k, v|
20
33
  vv = v.init_path(path)
21
34
  if vv.is_context?
22
- ctx << vv
35
+ #ctx << vv
36
+ ctx[k] = vv
23
37
  end
24
38
  end
25
39
  ctx
@@ -0,0 +1,311 @@
1
+
2
+ require 'toolrack'
3
+
4
+ module Dockdev
5
+
6
+
7
+ ## Support multiple Dockerfile different configurations
8
+ ## Default config is the default Dockerfile file name
9
+ #class Configs
10
+ # include TR::CondUtils
11
+
12
+ # def initialize
13
+ # @configs = { default: Config.new }
14
+ # end
15
+
16
+ # def config_names
17
+ # @configs.keys.freeze
18
+ # end
19
+
20
+ # def default_config_name
21
+ # :default
22
+ # end
23
+
24
+ # def default_config
25
+ # @configs[:default]
26
+ # end
27
+
28
+ # def config(name)
29
+ # indx = File.basename(name)
30
+ # indx = :default if indx == "Dockerfile"
31
+
32
+ # conf = @configs[indx]
33
+ # if conf.nil?
34
+ # conf = Config.new
35
+ # @configs[indx] = conf
36
+ # end
37
+ # conf
38
+ # end
39
+
40
+ # def is_config_exist?(name)
41
+ # not_empty?(config(name))
42
+ # end
43
+
44
+ # private
45
+ # def method_missing(mtd, *args, &block)
46
+ # default_config.send(mtd, *args, &block)
47
+ # end
48
+ #end # end class Configs
49
+
50
+ # Content of the config file
51
+ # which shall configure the to be run docker instance
52
+ # Hence mostly the accessors/readers are related to docker configuration items
53
+ class Config
54
+ include TR::CondUtils
55
+
56
+ # for image
57
+ attr_accessor :workdir
58
+
59
+ # for container
60
+ attr_reader :mounts, :ports
61
+ attr_accessor :network
62
+
63
+ # for image
64
+ attr_reader :dockerfile_entries
65
+
66
+ # since context activation is automated:
67
+ # 1. skip_context shall skip all found automated activated context
68
+ # 2. activate_context shall add those context which is not found by automated discovery
69
+ attr_reader :skip_context, :activate_context
70
+ def initialize(val = {})
71
+ @mounts = val[:mounts] || {}
72
+ @ports = val[:ports] || {}
73
+ @network = val[:network] || nil
74
+ @dockerfile_entries = val[:dockerfile_entries] || []
75
+ @workdir = val[:workdir] || "/opt"
76
+ @skip_context = val[:skip_context] || []
77
+ @activate_context = val[:activate_context] || []
78
+ end
79
+
80
+
81
+ # Convert internal value into hash to be written to file to get rid of the object
82
+ # encoding in the yaml file
83
+ def to_storage
84
+ { mounts: @mounts, ports: @ports, dockerfile_entries: @dockerfile_entries, workdir: @workdir, skip_context: @skip_context, activate_context: @activate_context }
85
+ end
86
+
87
+
88
+ # Add mount mapping of host => docker follows docker-cli which follows
89
+ # docker cli -v format
90
+ #
91
+ # @param on_host [String] path on host
92
+ # @param on_docker [String] path on docker
93
+ # @param opts [Hash] options for the mount spec definition. Value keys including:
94
+ # @option opts [Symbol] :duplicated_entry_policy :error (default) raise error if the on_host is duplicated/already defined
95
+ # @option opts [Symbol] :duplicated_entry_policy :warn_replace raise warning if the on_host is duplicated/already defined and new entry shall replace the old entry
96
+ # @option opts [Symbol] :duplicated_entry_policy :warn_discard raise warning if the on_host is duplicated/already defined and new entry is discarded
97
+ def add_mount(on_host, on_docker, opts = { duplicated_entry_policy: :error })
98
+ if not_empty?(on_host) and not_empty?(on_docker)
99
+ if @mounts.keys.include?(on_host)
100
+ policy = opts[:duplicated_entry_policy] || :error
101
+ case policy
102
+ when :warn_replace
103
+ logger.warn "on_host '#{on_host}' was mapped to '#{@mounts[on_host]}'. It shall be replaced with '#{on_docker}'"
104
+ @mounts[on_host] = on_docker
105
+
106
+ when :warn_discard
107
+ logger.warn "on_host '#{on_host}' already mapped to '#{@mounts[on_host]}'. New value on_docker is ignored."
108
+
109
+ else
110
+ # default policy always raise error
111
+ raise Error, "on_host '#{on_host}' already mapped to '#{@mounts[on_host]}'"
112
+ end
113
+ else
114
+ @mounts[on_host] = on_docker
115
+ end
116
+ else
117
+ logger.debug "add_mount unsuccessful = on_host : #{on_host} / on_docker : #{on_docker}"
118
+ raise Error, "on_host mount entry cannot be empty" if is_empty?(on_host)
119
+ raise Error, "on_docker mount entry cannot be empty" if is_empty?(on_docker)
120
+ end
121
+ end
122
+
123
+
124
+ # Add port mapping of host => docker follows docker-cli which follows
125
+ # docker cli -p format
126
+ #
127
+ # @param on_host [String] port on host
128
+ # @param on_docker [String] port on docker
129
+ # @param opts [Hash] options for the port spec definition. Value keys including:
130
+ # @option opts [Symbol] :duplicated_entry_policy :error (default) raise error if the on_host is duplicated/already defined
131
+ # @option opts [Symbol] :duplicated_entry_policy :warn_replace raise warning if the on_host is duplicated/already defined and new entry shall replace the old entry
132
+ # @option opts [Symbol] :duplicated_entry_policy :warn_discard raise warning if the on_host is duplicated/already defined and new entry is discarded
133
+ def add_port(on_host, on_docker, opts = { duplicated_entry_policy: :error })
134
+ if not_empty?(on_host) and not_empty?(on_docker)
135
+ if @ports.keys.include?(on_host)
136
+ policy = opts[:duplicated_entry_policy] || :error
137
+ case policy
138
+ when :warn_replace
139
+ logger.warn "on_host '#{on_host}' was mapped to '#{@mounts[on_host]}'. It shall be replaced with '#{on_docker}'"
140
+ @ports[on_host] = on_docker
141
+
142
+ when :warn_discard
143
+ logger.warn "on_host '#{on_host}' already mapped to '#{@mounts[on_host]}'. New value on_docker is ignored."
144
+
145
+ else
146
+ # default policy always raise error
147
+ raise Error, "on_host '#{on_host}' already mapped to '#{@mounts[on_host]}'"
148
+ end
149
+ else
150
+ @ports[on_host] = on_docker
151
+ end
152
+ else
153
+ logger.debug "add_port unsuccessful = on_host : #{on_host} / on_docker : #{on_docker}"
154
+ raise Error, "on_host port entry cannot be empty" if is_empty?(on_host)
155
+ raise Error, "on_docker port entry cannot be empty" if is_empty?(on_docker)
156
+ end
157
+
158
+ end
159
+
160
+ # Any instruction to be appended into Dockerfile.
161
+ # Note this did not presume the entry is RUN, COPY or anyting.
162
+ # A full valid Dockerfile entry has to be provided here
163
+ #
164
+ # @param st [String] Full valid Dockerfile line to be embed into Dockerfile
165
+ def append_Dockerfile(st)
166
+ logger.debug "Appending : #{st}"
167
+ @dockerfile_entries << st
168
+ end
169
+
170
+ def is_context_should_skip?(name)
171
+ @skip_context.include?(name)
172
+ end
173
+
174
+
175
+ def manual_activated_context
176
+ @activate_context.freeze
177
+ end
178
+
179
+
180
+ private
181
+ def logger
182
+ Dockdev.logger(:config)
183
+ end
184
+
185
+ def has_additional_entries?
186
+ not @dockerfile_entries.empty?
187
+ end
188
+ end
189
+
190
+ # Managing the config
191
+ class DockdevConfig
192
+ include TR::CondUtils
193
+
194
+ DOCDEV_CONFIG_FILE = "dockdev-config"
195
+
196
+ def self.load(root = Dir.getwd, &block)
197
+ confFile = Dir.glob(File.join(root,"#{DOCDEV_CONFIG_FILE}.*")).grep(/.yml|.yaml$/)
198
+ if confFile.length > 1
199
+ block.call(:found_more, contFile)
200
+ elsif confFile.length == 0
201
+ block.call(:not_found)
202
+ else
203
+ block.call(:found, confFile.first)
204
+ end
205
+ end
206
+
207
+ def initialize(conf = nil)
208
+ logger.debug "Given to initialize : #{conf}"
209
+ if not_empty?(conf)
210
+ @config = parse(conf)
211
+ else
212
+ @config = Config.new
213
+ end
214
+ end
215
+
216
+
217
+ def save(root = Dir.getwd)
218
+ path = File.join(root,"#{DOCDEV_CONFIG_FILE}.yml")
219
+ File.open(path,"w") do |f|
220
+ f.write YAML.dump(@config.to_storage)
221
+ end
222
+ path
223
+ end
224
+
225
+
226
+ # Build the docker image by embedding additional entries into the Dockerfile.
227
+ # This likely will need a temporary file to be created and it should be managed by
228
+ # this operation.
229
+ #
230
+ # @param [Dockdev::Image] image instance
231
+ # @param [String] path to selected Dockerfile
232
+ def build_image(image, dockerfile_path, opts = { root: Dir.getwd }, &block)
233
+
234
+ if has_additional_entries?
235
+
236
+ logger.debug "dockdev_config has additional entry for Dockerfile. Merging additional entries into Dockerfile"
237
+
238
+ root = opts[:root] || Dir.getwd
239
+ # make it static name so:
240
+ # 1. No file removal is required
241
+ # 2. Allow debug on generated Dockerfile
242
+ # 3. Replace Dockerfile on each run and only single Dockerfile is left on system
243
+ # 4. Allow this temporary to be added to .gitignore
244
+ tmpFile = File.join(root, "#{File.basename(dockerfile_path)}-dockdev")
245
+ File.open(tmpFile,"w") do |f|
246
+ found = false
247
+ File.open(dockerfile_path,"r").each_line do |line|
248
+ # detecting the CMD line if there is any
249
+ if line =~ /^CMD/
250
+ found = true
251
+ # here we append the lines
252
+ dockerfile_entries.each do |al|
253
+ f.puts al
254
+ end
255
+ f.write line
256
+
257
+ else
258
+ f.write line
259
+
260
+ end
261
+ end
262
+
263
+ if not found
264
+ @dockerfile_entries.each do |al|
265
+ f.puts al
266
+ end
267
+ end
268
+
269
+ end
270
+
271
+ image.build(tmpFile)
272
+
273
+ else
274
+ logger.debug "dockdev_config has no additional entry for Dockerfile. Proceed to build found Dockerfile"
275
+ image.build(dockerfile_path)
276
+ end
277
+
278
+ end
279
+
280
+
281
+ private
282
+ def parse(conf)
283
+ logger.debug "Given to parse : #{conf}"
284
+ cont = File.read(conf)
285
+ val = YAML.unsafe_load(cont)
286
+ Config.new(val)
287
+ end
288
+
289
+ def method_missing(mtd, *args, &block)
290
+ logger.debug "method_missing '#{mtd}' / #{args}"
291
+ @config.send(mtd, *args, &block)
292
+ end
293
+
294
+ def logger
295
+ Dockdev.logger(:dockdev_config)
296
+ end
297
+
298
+ end
299
+ end
300
+
301
+
302
+ if $0 == __FILE__
303
+
304
+ require_relative '../dockdev'
305
+
306
+ c = Dockdev::DockdevConfig.new
307
+ c.add_mount("/Users/chris/01.Workspaces/02.Code-Factory/08-Workspace/docker-cli","/opt/docker-cli")
308
+ c.save
309
+ end
310
+
311
+
data/lib/dockdev/image.rb CHANGED
@@ -53,10 +53,12 @@ module Dockdev
53
53
  dockerfile: dockerfilePath
54
54
  }
55
55
  optss.merge!(opts)
56
- @cmd_fact.build_image(@image_name, optss).run
56
+ res = @cmd_fact.build_image(@image_name, optss).run
57
57
 
58
58
  FileUtils.rm(generated_dockerfile) if File.exist?(generated_dockerfile) and not is_keep_generated_dockerfile?
59
59
 
60
+ res
61
+
60
62
  end
61
63
 
62
64
  def destroy
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Dockdev
4
- VERSION = "0.3.8"
4
+ VERSION = "0.4.1"
5
5
  end
@@ -12,11 +12,27 @@ module Dockdev
12
12
  end
13
13
 
14
14
  def has_dockerfile?
15
- Dir.glob(File.join(@root,"Dockerfile")).length > 0
15
+ found_dockerfile_count > 0
16
+ end
17
+
18
+ def found_dockerfile_count
19
+ dockerfiles.length
20
+ end
21
+
22
+ def has_multiple_dockerfiles?
23
+ found_dockerfile_count > 1
24
+ end
25
+
26
+ def dockerfiles
27
+ Dir.glob(File.join(@root,"Dockerfile*"))
16
28
  end
17
29
 
18
30
  def dockerfile
19
- Dir.glob(File.join(@root,"Dockerfile")).first
31
+ if has_dockerfile?
32
+ dockerfiles.first
33
+ else
34
+ nil
35
+ end
20
36
  end
21
37
 
22
38
  def has_docker_compose?
data/lib/dockdev.rb CHANGED
@@ -5,82 +5,217 @@ require 'toolrack'
5
5
  require 'docker/cli'
6
6
  require 'colorize'
7
7
 
8
+ require 'tty/prompt'
9
+
8
10
  require_relative "dockdev/version"
9
11
 
10
12
  require_relative 'dockdev/workspace'
11
13
  require_relative 'dockdev/image'
12
14
  require_relative 'dockdev/container'
13
15
 
16
+ require_relative 'dockdev/dockdev_config'
17
+
18
+ require_relative 'dockdev/user_config'
19
+
14
20
  module Dockdev
15
21
  include TR::CondUtils
16
22
 
17
23
  class Error < StandardError; end
18
24
  # Your code goes here...
19
25
 
26
+ # main entry points to start docker
20
27
  def self.with_running_container(contName, opts = {})
21
28
 
29
+ pmt = TTY::Prompt.new
22
30
  root = opts[:root]
23
- cmd = opts[:command]
31
+ cmd = opts[:command] || ""
24
32
 
25
- ctx = Dockdev::Context::ContextManager.instance.get_context(root)
26
- logger.debug("Found context : #{ctx}")
33
+ ddConf = load_config(root)
34
+
35
+ user_config = opts[:user_config]
27
36
 
28
37
  cont = Container.new(contName)
29
38
  if cont.has_container?
39
+
40
+ logger.debug "Container '#{contName}' already exist. Just run the container"
30
41
  if cont.running?
31
42
  cont.attach_and_exec(command: cmd)
32
43
  else
33
44
  cont.start_with_command(command: cmd)
34
45
  end
46
+
35
47
  else
48
+
49
+ logger.debug "Container '#{contName}' does not exist. Creating the container"
50
+
36
51
  img = Image.new(contName)
37
52
  ws = opts[:workspace] || root
38
53
  wss = Workspace.new(ws)
39
- if img.has_image?
40
- mount = { root => File.join("/opt",File.basename(root)) }
41
- port = {}
42
- ctx.each do |cctx|
43
- mnts = cctx.process_mount(dir_inside_docker: "/opt")
44
- logger.debug "Mount points by context : #{mnts}"
45
54
 
46
- mount.merge!(mnts) if not mnts.empty?
55
+ # root directory is mounted by default
56
+ ddConf.add_mount(root, File.join(ddConf.workdir,File.basename(root)))
47
57
 
48
- prt = cctx.process_port
49
- port.merge!(prt) if not prt.empty?
58
+ if user_config.has_key?(:network)
59
+ ddConf.network = user_config.network
60
+ end
61
+
62
+ ctx = Dockdev::Context::ContextManager.instance.get_context(root)
63
+ logger.debug("Found context : #{ctx}")
64
+
65
+ ctx.each do |name, cctx|
50
66
 
51
- logger.debug "Ports by context #{cctx} : #{prt}"
67
+ if ddConf.is_context_should_skip?(name)
68
+ logger.debug "Context '#{name}' is asked to be skipped"
69
+ next
52
70
  end
53
71
 
54
- param = { command: cmd, mounts: mount }
55
- param[:ports] = port if not port.empty?
72
+ logger.debug "Appying context '#{name}' "
73
+ # here allow context to add additional Dockerfile entries, mounts and ports
74
+ ddConf = cctx.apply_context(ddConf)
75
+ end
56
76
 
57
- img.new_container(cont.name, param)
77
+ ddConf.manual_activated_context.each do |cctx|
78
+ mctx = Dockdev::Context::ContextManager.instance.registered_context_by_name(cctx)
79
+ logger.debug "Executing manual activated context : #{mctx}"
80
+ ddConf = mctx.apply_context(ddConf) if not mctx.nil?
81
+ end
58
82
 
59
- elsif wss.has_dockerfile?
60
- img.build(wss.dockerfile)
61
-
62
- mount = { root => File.join("/opt",File.basename(root)) }
63
- port = {}
64
- ctx.each do |cctx|
65
- mnt = cctx.process_mount(dir_inside_docker: "/opt")
66
- mount.merge!(mnt) if not mnt.empty?
83
+ if not img.has_image?
67
84
 
68
- logger.debug "Mount points by context #{cctx} : #{mnt}"
85
+ if wss.has_dockerfile?
69
86
 
70
- prt = cctx.process_port
71
- port.merge!(prt) if not prt.empty?
87
+ if wss.has_multiple_dockerfiles?
72
88
 
73
- logger.debug "Ports by context #{cctx} : #{prt}"
74
- end
89
+ selDockerFile = pmt.select("Please select one of the Dockerfile to proceed : ") do |m|
90
+ wss.dockerfiles.each do |df|
91
+ m.choice File.basename(df), df
92
+ end
93
+ end
75
94
 
76
- param = { command: cmd, mounts: mount }
77
- param[:ports] = port if not port.empty?
95
+ else
96
+ selDockerFile = wss.dockerfile
97
+ end
78
98
 
79
- img.new_container(cont.name, param)
99
+ # Delegated to config file to allow
100
+ # config file to embed addtional entries (if there is any) and proceed to build it.
101
+ # During the process it is very likey a temporary Dockerfile shall be created since
102
+ # docker cli works on file basis and this temporary file need to be managed after the process.
103
+ # Hence this makes more sense to let the config handle all those inside the operation
104
+ res = ddConf.build_image(img, selDockerFile, root: root)
105
+ raise Error, "Image failed to be built. Error was : #{res.err_stream}" if res.failed?
106
+ STDOUT.puts "\n Image '#{contName}' built successfully\n\n".green
107
+ #img.build(wss.dockerfile)
80
108
 
81
- else
82
- raise Error, "\n No image and no Dockerfile found to build the image found. Operation aborted. \n\n".red
109
+ else
110
+ raise Error, "\n No image and no Dockerfile found to build the image. Operation aborted. \n\n".red
111
+
112
+ end
113
+ end
114
+
115
+ # image already exist!
116
+ # Since reach here means container doesn't exist yet.
117
+ # Proceed to create container
118
+
119
+ param = { command: cmd, mounts: ddConf.mounts, ports: ddConf.ports }
120
+ if not_empty?(ddConf.network)
121
+ cmd_fact = Docker::Cli::CommandFactory.new
122
+ res = cmd_fact.create_network(ddConf.network).run
123
+ if res.success? and not res.is_out_stream_empty?
124
+ param[:network] = ddConf.network
125
+ else
126
+ err = res.err_stream
127
+ if err =~ /already exist/
128
+ param[:network] = ddConf.network
129
+ else
130
+ raise Error, "\n Failed to create network. Error was : #{res.err_stream}\n"
131
+ end
132
+ end
83
133
  end
134
+ img.new_container(cont.name, param)
135
+
136
+ #if img.has_image?
137
+ #
138
+ # # has image but no container
139
+ # ctx.each do |cctx|
140
+ #
141
+ # ddConf = cctx.apply_context(ddConf)
142
+
143
+ # #cctx.process_mount(dir_inside_docker: ddConf.workdir).each do |host,docker|
144
+ # # logger.debug "Mount points by context '#{cctx}' : #{host} => #{docker}"
145
+ # # ddConf.add_mount(host, docker)
146
+ # #end
147
+
148
+ # #cctx.process_port.each do |host, docker|
149
+ # # logger.debug "Ports mapping by context '#{cctx}' : #{host} => #{docker}"
150
+ # # ddConf.add_port(host, docker)
151
+ # #end
152
+
153
+ # #mnts = cctx.process_mount(dir_inside_docker: ddConf.workdir)
154
+ # #logger.debug "Mount points by context : #{mnts}"
155
+
156
+ # #mount.merge!(mnts) if not mnts.empty?
157
+
158
+ # #prt = cctx.process_port
159
+ # #port.merge!(prt) if not prt.empty?
160
+
161
+ # #logger.debug "Ports by context #{cctx} : #{prt}"
162
+ # end
163
+
164
+ # #param = { command: cmd, mounts: mount }
165
+ # #param[:ports] = port if not port.empty?
166
+ # param = { command: cmd, mounts: ddConf.mounts, ports: ddConf.ports }
167
+
168
+ # img.new_container(cont.name, param)
169
+
170
+ #elsif wss.has_dockerfile?
171
+
172
+ # logger.debug "Dockerfile '#{wss.dockerfile}' found. Proceed building the image."
173
+
174
+ # # Delegated to config file to allow
175
+ # # config file to embed addtional entries (if there is any) and proceed to build it.
176
+ # # During the process it is very likey a temporary Dockerfile shall be created since
177
+ # # docker cli works on file basis and this temporary file need to be managed after the process.
178
+ # # Hence this makes more sense to let the config handle all those inside the operation
179
+ # ddConf.build_image(img, wss, root: root)
180
+ # #img.build(wss.dockerfile)
181
+ #
182
+ # ddConf.add_mount(root, File.join(ddConf.workdir,File.basename(root)))
183
+ # #mount = { root => File.join(ddConf.workdir,File.basename(root)) }
184
+ # #port = {}
185
+ # ctx.each do |cctx|
186
+
187
+ # ddConf = cctx.apply_context(ddConf)
188
+
189
+ # #cctx.process_mount(dir_inside_docker: ddConf.workdir).each do |host,docker|
190
+ # # logger.debug "Mount points by context '#{cctx}' : #{host} => #{docker}"
191
+ # # ddConf.add_mount(host, docker)
192
+ # #end
193
+
194
+ # #cctx.process_port.each do |host, docker|
195
+ # # logger.debug "Ports mapping by context '#{cctx}' : #{host} => #{docker}"
196
+ # # ddConf.add_port(host, docker)
197
+ # #end
198
+
199
+ # #mnt = cctx.process_mount(dir_inside_docker: ddConf.workdir)
200
+ # #mount.merge!(mnt) if not mnt.empty?
201
+
202
+ # #logger.debug "Mount points by context #{cctx} : #{mnt}"
203
+
204
+ # #prt = cctx.process_port
205
+ # #port.merge!(prt) if not prt.empty?
206
+
207
+ # #logger.debug "Ports by context #{cctx} : #{prt}"
208
+ # end
209
+
210
+ # #param = { command: cmd, mounts: mount }
211
+ # #param[:ports] = port if not port.empty?
212
+ # param = { command: cmd, mounts: ddConf.mounts, ports: ddConf.ports }
213
+
214
+ # img.new_container(cont.name, param)
215
+
216
+ #else
217
+ # raise Error, "\n No image and no Dockerfile found to build the image found. Operation aborted. \n\n".red
218
+ #end
84
219
  end
85
220
  end
86
221
 
@@ -99,6 +234,33 @@ module Dockdev
99
234
 
100
235
  end
101
236
 
237
+ # detect if the additional configuration file exist
238
+ def self.load_config(root)
239
+
240
+ ddConf = DockdevConfig.new
241
+ DockdevConfig.load(root) do |ops, *args|
242
+ case ops
243
+ when :found_more
244
+ found = args.first
245
+ pmt = TTY::Prompt.new
246
+ selConf = pmt.select("There are more config files found. Please select one of the files below :") do |m|
247
+ found.each do |f|
248
+ m.choice Pathname.new(f).relative_path_from(root),f
249
+ end
250
+ end
251
+ ddConf = DockdevConfig.new(selConf)
252
+ when :found
253
+ ddConf = DockdevConfig.new(args.first)
254
+ else
255
+ logger.debug "Load config got ops : #{ops}"
256
+ end
257
+ end
258
+
259
+ logger.debug "Loaded config : #{ddConf}"
260
+ ddConf
261
+
262
+ end
263
+
102
264
  def self.logger(tag = nil, &block)
103
265
  if @_logger.nil?
104
266
  @_logger = TeLogger::Tlogger.new(STDOUT)
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dockdev
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.8
4
+ version: 0.4.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Chris
8
- autorequire:
8
+ autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-01-17 00:00:00.000000000 Z
11
+ date: 2024-04-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: teLogger
@@ -128,6 +128,7 @@ files:
128
128
  - lib/dockdev/context.rb
129
129
  - lib/dockdev/context/docker-compose.rb
130
130
  - lib/dockdev/context/rubygems.rb
131
+ - lib/dockdev/dockdev_config.rb
131
132
  - lib/dockdev/image.rb
132
133
  - lib/dockdev/user_info.rb
133
134
  - lib/dockdev/version.rb
@@ -136,7 +137,7 @@ files:
136
137
  homepage: ''
137
138
  licenses: []
138
139
  metadata: {}
139
- post_install_message:
140
+ post_install_message:
140
141
  rdoc_options: []
141
142
  require_paths:
142
143
  - lib
@@ -151,8 +152,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
151
152
  - !ruby/object:Gem::Version
152
153
  version: '0'
153
154
  requirements: []
154
- rubygems_version: 3.5.3
155
- signing_key:
155
+ rubygems_version: 3.5.1
156
+ signing_key:
156
157
  specification_version: 4
157
158
  summary: ''
158
159
  test_files: []