require_relative 'template' require_relative 'command_builder' require_relative 'command_runner' module Hitcher module Docker class Mount attr_accessor :host, :docker def initialize(host = "",docker = "") @host = host @docker = docker end def hashify { host: @host, docker: @docker } end def self.parse(blc) res = [] if not (blc.nil? or blc.empty?) blc.each do |e| if e =~ /mount/ l = e.split(" ") if l.length == 2 else end elsif e =~ /,/ # handle host: /home/xxx/dev, docker: /opt/dev m = Mount.new e.split(",").each do |ee| s = ee.split(":") case s[0].strip when "host" m.host = translate(s[1].strip) when "docker" m.docker = s[1].strip else raise Hitcher::Error, "Unknown mount point key '#{s[0]}'" end end res << m elsif e =~ /:/ # handle host:docker ==> /home/xxx/dev:/opt/dev ee = e.split(":") m = Mount.new m.host = translate(ee[0]) m.docker = ee[1] res << m end end end res end # parse def self.translate(key) case key.upcase when "$PWD","." Dir.getwd else if key =~ /../ File.expand_path(key) else key end end end end # class Mount class Port attr_accessor :host, :docker def initialize(host = nil, docker = nil) @host = host @docker = docker end def hashify { host: @host, docker: @docker } end end # class Port # # class Dockerfile # class Dockerfile attr_reader :cont def parse(blc) @cont = [] if not (blc.nil? or blc.empty?) blc.each do |e| if e =~ /dockerfile/ l = e.split(" ") if l.length == 2 # no parameters else # todo extract parameters end elsif e.strip != "end" @cont << e end end end end def is_empty? @cont.nil? or @cont.empty? end end # class Dockerfile ## ## Module Dsl ## module Dsl attr_reader :image, :cName, :df, :mounts, :exposes, :interactive_mode, :tty_mode def image_name(name) @image = name end def container_name(name) @cName = name end def block_kw?(kw) ["dockerfile","mount"].include?(kw.to_s) end def handle_block(kw,blc) send(kw,blc) end def dockerfile(blc) @df = Dockerfile.new @df.parse(blc) end def mount(blc) @mounts = Mount.parse(blc) end def interactive(val) @interactive_mode = val end def tty(val) @tty_mode = val end def expose(port) if not port.nil? @exposes = [] if @exposes.nil? po = Port.new if port.to_s =~ /:/ ppo = port.to_s.split(":") po.host = ppo[0] po.docker = ppo[1] else # only single value is given po.docker = port po.host = port end @exposes << po end end # expose ## ## End of DSL ## def command if @builder.nil? @builder = DockerCommandBuilder.new end @builder end def command_executor if @exec.nil? @exec = DockerCommandExecutor.new(self) end @exec end # # Operation # def gen @logger.debug "Generate output files!" te = Hitcher::Docker::TemplateEngine.new if not @dockerfile.nil? te.build_template(:dockerfile, { image: @image, dockerfile: @df.cont }) @logger.debug "Dockerfile generated" end te.build_template(:build_container, { image_name: @image }) # run script mm = @mounts.collect { |m| m.hashify } pp = @exposes.collect { |po| po.hashify } te.build_template(:run_container, { mounts: mm, ports: pp, container_name: @cName, interactive: true, image: @image }) @logger.debug "run_container generated" te.build_template(:start_container, { container_name: @cName, drop_to_prompt: true }) te.build_template(:container_prompt, { container_name: @cName }) end # generate output files end # module Dsl # initialize dynamically by # DSL method container() class DockerDsl include Hitcher::Docker::Dsl def initialize(opts = { logger: Hitcher::Global.instance.glog }) @logger = opts[:logger] || Hitcher::Global.instance.glog end end # class DockerDsl end end