Module: Dockdev

Includes:
TR::CondUtils
Defined in:
lib/dockdev.rb,
lib/dockdev/image.rb,
lib/dockdev/context.rb,
lib/dockdev/version.rb,
lib/dockdev/container.rb,
lib/dockdev/user_info.rb,
lib/dockdev/workspace.rb,
lib/dockdev/user_config.rb,
lib/dockdev/dockdev_config.rb,
lib/dockdev/context/rubygems.rb,
lib/dockdev/context/docker-compose.rb

Defined Under Namespace

Modules: Context, UserInfo Classes: Config, Container, DockdevConfig, Error, Image, UserConfig, Workspace

Constant Summary collapse

VERSION =
"0.4.3"

Class Method Summary collapse

Class Method Details

.destroy(contName, opts = {}) ⇒ Object



222
223
224
225
226
227
228
229
230
231
232
233
234
235
# File 'lib/dockdev.rb', line 222

def self.destroy(contName, opts = {})

  cont = Container.new(contName)
  if cont.has_container?
    cont.stop if cont.running?
    cont.destroy
  end

  img = Image.new(contName)
  if img.has_image?
    img.destroy
  end

end

.load_config(root) ⇒ Object

detect if the additional configuration file exist



238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
# File 'lib/dockdev.rb', line 238

def self.load_config(root)
 
  ddConf = DockdevConfig.new
  DockdevConfig.load(root) do |ops, *args|
    case ops
    when :found_more
      found = args.first
      pmt = TTY::Prompt.new
      selConf = pmt.select("There are more config files found. Please select one of the files below :") do |m|
        found.each do |f|
          m.choice Pathname.new(f).relative_path_from(root),f
        end
      end
      ddConf = DockdevConfig.new(selConf)
    when :found
      ddConf = DockdevConfig.new(args.first)
    else
    logger.debug "Load config got ops : #{ops}"
    end
  end

  logger.debug "Loaded config : #{ddConf}"
  ddConf
  
end

.logger(tag = nil, &block) ⇒ Object



264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
# File 'lib/dockdev.rb', line 264

def self.logger(tag = nil, &block)
  if @_logger.nil?
    @_logger = TeLogger::Tlogger.new(STDOUT)
  end

  if block
    if not_empty?(tag)
      @_logger.with_tag(tag, &block)
    else
      @_logger.with_tag(@_logger.tag, &block)
    end
  else
    if is_empty?(tag)
      @_logger.tag = :dockdev
      @_logger
    else
      # no block but tag is given? hmm
      @_logger.tag = tag
      @_logger
    end
  end
end

.with_running_container(contName, opts = {}) ⇒ Object

main entry points to start docker



27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
# File 'lib/dockdev.rb', line 27

def self.with_running_container(contName, opts = {})

  pmt = TTY::Prompt.new
  root = opts[:root]
  cmd = opts[:command] || ""

  ddConf = load_config(root)

  user_config = opts[:user_config]

  cont = Container.new(contName)
  if cont.has_container?
    
    logger.debug "Container '#{contName}' already exist. Just run the container"
    if cont.running?
      cont.attach_and_exec(command: cmd)
    else
      cont.start_with_command(command: cmd)
    end

  else
    
    logger.debug "Container '#{contName}' does not exist. Creating the container"

    img = Image.new(contName)
    ws = opts[:workspace] || root
    wss = Workspace.new(ws)

    # root directory is mounted by default
    ddConf.add_mount(root, File.join(ddConf.workdir,File.basename(root)))

    if user_config.has_key?(:network)
      ddConf.network = user_config.network
    end

    ctx = Dockdev::Context::ContextManager.instance.get_context(root)
    logger.debug("Found context : #{ctx}")

    ctx.each do |name, cctx|

      if ddConf.is_context_should_skip?(name)
        logger.debug "Context '#{name}' is asked to be skipped"
        next
      end

      logger.debug "Appying context '#{name}' "
      # here allow context to add additional Dockerfile entries, mounts and ports
      ddConf = cctx.apply_context(ddConf)
    end

    ddConf.manual_activated_context.each do |cctx|
      mctx = Dockdev::Context::ContextManager.instance.registered_context_by_name(cctx)
      logger.debug "Executing manual activated context : #{mctx}"
      ddConf = mctx.apply_context(ddConf) if not mctx.nil?
    end

    if not img.has_image? 

      if wss.has_dockerfile?

        if wss.has_multiple_dockerfiles?

          selDockerFile = pmt.select("Please select one of the Dockerfile to proceed : ") do |m|
            wss.dockerfiles.each do |df|
              m.choice File.basename(df), df
            end
          end

        else
          selDockerFile = wss.dockerfile
        end

        # Delegated to config file to allow
        # config file to embed addtional entries (if there is any) and proceed to build it.
        # During the process it is very likey a temporary Dockerfile shall be created since 
        # docker cli works on file basis and this temporary file need to be managed after the process.
        # Hence this makes more sense to let the config handle all those inside the operation
        res = ddConf.build_image(img, selDockerFile, root: root) 
        raise Error, "Image failed to be built. Error was : #{res.err_stream}" if res.failed?
        STDOUT.puts "\n Image '#{contName}' built successfully\n\n".green
        #img.build(wss.dockerfile)

      else
        raise Error, "\n No image and no Dockerfile found to build the image. Operation aborted. \n\n".red

      end
    end

    # image already exist!
    # Since reach here means container doesn't exist yet.
    # Proceed to create container

    param = { command: cmd, mounts: ddConf.mounts, ports: ddConf.ports }
    if not_empty?(ddConf.network)
      cmd_fact = Docker::Cli::CommandFactory.new
      res = cmd_fact.create_network(ddConf.network).run
      if res.success? and not res.is_out_stream_empty?
        param[:network] = ddConf.network 
      else
        err = res.err_stream
        if err =~ /already exist/
          param[:network] = ddConf.network 
        else
          raise Error, "\n Failed to create network. Error was : #{res.err_stream}\n"
        end
      end
    end
    img.new_container(cont.name, param)

    #if img.has_image?
    #  
    #  # has image but no container
    #  ctx.each do |cctx|
    #   
    #    ddConf = cctx.apply_context(ddConf)

    #    #cctx.process_mount(dir_inside_docker: ddConf.workdir).each do |host,docker|
    #    #  logger.debug "Mount points by context '#{cctx}' : #{host} => #{docker}"
    #    #  ddConf.add_mount(host, docker)
    #    #end

    #    #cctx.process_port.each do |host, docker|
    #    #  logger.debug "Ports mapping by context '#{cctx}' : #{host} => #{docker}"
    #    #  ddConf.add_port(host, docker)
    #    #end

    #    #mnts = cctx.process_mount(dir_inside_docker: ddConf.workdir)
    #    #logger.debug "Mount points by context : #{mnts}"

    #    #mount.merge!(mnts) if not mnts.empty?

    #    #prt = cctx.process_port
    #    #port.merge!(prt) if not prt.empty?

    #    #logger.debug "Ports by context #{cctx} : #{prt}"
    #  end

    #  #param = { command: cmd, mounts: mount }
    #  #param[:ports] = port if not port.empty? 
    #  param = { command: cmd, mounts: ddConf.mounts, ports: ddConf.ports }

    #  img.new_container(cont.name, param)

    #elsif wss.has_dockerfile?

    #  logger.debug "Dockerfile '#{wss.dockerfile}' found. Proceed building the image."

    #  # Delegated to config file to allow
    #  # config file to embed addtional entries (if there is any) and proceed to build it.
    #  # During the process it is very likey a temporary Dockerfile shall be created since 
    #  # docker cli works on file basis and this temporary file need to be managed after the process.
    #  # Hence this makes more sense to let the config handle all those inside the operation
    #  ddConf.build_image(img, wss, root: root)
    #  #img.build(wss.dockerfile)
    # 
    #  ddConf.add_mount(root, File.join(ddConf.workdir,File.basename(root)))
    #  #mount = { root => File.join(ddConf.workdir,File.basename(root)) }
    #  #port = {}
    #  ctx.each do |cctx|

    #    ddConf = cctx.apply_context(ddConf)

    #    #cctx.process_mount(dir_inside_docker: ddConf.workdir).each do |host,docker|
    #    #  logger.debug "Mount points by context '#{cctx}' : #{host} => #{docker}"
    #    #  ddConf.add_mount(host, docker)
    #    #end

    #    #cctx.process_port.each do |host, docker|
    #    #  logger.debug "Ports mapping by context '#{cctx}' : #{host} => #{docker}"
    #    #  ddConf.add_port(host, docker)
    #    #end

    #    #mnt = cctx.process_mount(dir_inside_docker: ddConf.workdir)
    #    #mount.merge!(mnt) if not mnt.empty?

    #    #logger.debug "Mount points by context #{cctx} : #{mnt}"

    #    #prt = cctx.process_port
    #    #port.merge!(prt) if not prt.empty?

    #    #logger.debug "Ports by context #{cctx} : #{prt}"
    #  end

    #  #param = { command: cmd, mounts: mount }
    #  #param[:ports] = port if not port.empty? 
    #  param = { command: cmd, mounts: ddConf.mounts, ports: ddConf.ports }

    #  img.new_container(cont.name, param)

    #else
    #  raise Error, "\n No image and no Dockerfile found to build the image found. Operation aborted. \n\n".red
    #end
  end
end