lib/dockdev.rb in dockdev-0.3.8 vs lib/dockdev.rb in dockdev-0.4.0

- old
+ new

@@ -3,86 +3,199 @@ require 'teLogger' require 'toolrack' require 'docker/cli' require 'colorize' +require 'tty/prompt' + require_relative "dockdev/version" require_relative 'dockdev/workspace' require_relative 'dockdev/image' require_relative 'dockdev/container' +require_relative 'dockdev/dockdev_config' + module Dockdev include TR::CondUtils class Error < StandardError; end # Your code goes here... + # main entry points to start docker def self.with_running_container(contName, opts = {}) + pmt = TTY::Prompt.new root = opts[:root] cmd = opts[:command] - ctx = Dockdev::Context::ContextManager.instance.get_context(root) - logger.debug("Found context : #{ctx}") + ddConf = load_config(root) 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) - if img.has_image? - mount = { root => File.join("/opt",File.basename(root)) } - port = {} - ctx.each do |cctx| - mnts = cctx.process_mount(dir_inside_docker: "/opt") - logger.debug "Mount points by context : #{mnts}" - mount.merge!(mnts) if not mnts.empty? + # root directory is mounted by default + ddConf.add_mount(root, File.join(ddConf.workdir,File.basename(root))) - prt = cctx.process_port - port.merge!(prt) if not prt.empty? + ctx = Dockdev::Context::ContextManager.instance.get_context(root) + logger.debug("Found context : #{ctx}") - logger.debug "Ports by context #{cctx} : #{prt}" + ctx.each do |name, cctx| + + if ddConf.is_context_should_skip?(name) + logger.debug "Context '#{name}' is asked to be skipped" + next end - param = { command: cmd, mounts: mount } - param[:ports] = port if not port.empty? + logger.debug "Appying context '#{name}' " + # here allow context to add additional Dockerfile entries, mounts and ports + ddConf = cctx.apply_context(ddConf) + end - img.new_container(cont.name, param) + 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 - elsif wss.has_dockerfile? - img.build(wss.dockerfile) - - mount = { root => File.join("/opt",File.basename(root)) } - port = {} - ctx.each do |cctx| - mnt = cctx.process_mount(dir_inside_docker: "/opt") - mount.merge!(mnt) if not mnt.empty? + if not img.has_image? - logger.debug "Mount points by context #{cctx} : #{mnt}" + if wss.has_dockerfile? - prt = cctx.process_port - port.merge!(prt) if not prt.empty? + if wss.has_multiple_dockerfiles? - logger.debug "Ports by context #{cctx} : #{prt}" - end + 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 - param = { command: cmd, mounts: mount } - param[:ports] = port if not port.empty? + else + selDockerFile = wss.dockerfile + end - img.new_container(cont.name, param) + # 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 found. Operation aborted. \n\n".red + 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 } + 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 def self.destroy(contName, opts = {}) @@ -95,9 +208,36 @@ img = Image.new(contName) if img.has_image? img.destroy end + end + + # detect if the additional configuration file exist + 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 def self.logger(tag = nil, &block) if @_logger.nil? @_logger = TeLogger::Tlogger.new(STDOUT)