diff --git a/dup.rb b/dup.rb index 3f9f666..723ed04 100755 --- a/dup.rb +++ b/dup.rb @@ -4,6 +4,25 @@ require 'pp' require 'shellwords' require 'getoptlong' +MAPPINGS = [ + ['stdin_open', '--interactive', {:type=>:switch}], + ['tty', '--tty', {:type=>:switch}], + ['detach', '--detach', {:type=>:switch}], + ['remove', '--rm', {:type=>:switch}], + ['container_name', '--name', {:type=>:name}], + ['ports', '--publish'], + ['restart', '--restart'], + ['environment', '--env'], + ['volumes', '--volume'], + ['mem_limit', '--memory'], + ['links', '--link'], + ['stop_signal', '--stop-signal'], + ['stop_grace_period', '--stop-timeout'], + ['devices', '--device'], + ['image', nil], + ['command', nil, {:escape=>false}] +] + def get_sample(name="container") return <<~HEREDOC @@ -70,6 +89,11 @@ def run(cmd, ignore_returnvalue=false) raise "Command returned a non-zero exit value." if returnvalue!=true && !ignore_returnvalue end +def esc(obj, escape=true) + return obj unless escape + return obj.to_s.shellescape +end + def action_create(container, file) raise "File #{file} already exists" if File.exists?(file) @@ -95,27 +119,35 @@ def action_run(container, file) end (data["before_run"] || []).each{|cmd| run(cmd)} + cmd = ["docker", "run"] - data["interactive"] && cmd << "--tty" << "--interactive" - data["detach"]===false || cmd << "--detach" - data["remove"] && cmd << "--rm" - cmd << "--name=#{(data["container_name"] || key).shellescape}" - (data["ports"] || []).each {|p| cmd << "--publish" << p.to_s.shellescape} - data["restart"] && cmd << "--restart=#{data["restart"].shellescape}" - (data["environment"] || []).each {|key, val| cmd << "--env" << (val ? "#{key}=#{val.to_s.shellescape}" : key)} - (data["volumes"] || []).each {|vol| cmd << "--volume" << vol.shellescape} - data["mem_limit"] && cmd << "--memory=#{data["mem_limit"].shellescape}" - (data["links"] || []).each {|link| cmd << "--link" << link.shellescape} - data["stop_signal"] && cmd << "--stop-signal=#{data["stop_signal"].shellescape}" - data["stop_grace_period"] && cmd << "--stop-timeout=#{data["stop_grace_period"].shellescape}" - (data["devices"] || []).each {|dev| cmd << "--device" << dev.shellescape} - - cmd << data["image"].shellescape - - data["command"] && cmd << data["command"] + + MAPPINGS.each do |mapping| + yml_name, cmd_name, inspect_name, options = *mapping + options ||= {} + if !data[yml_name] + if options[:type]==:name + cmd << cmd_name << esc(key) + end + next + end + + if options[:type]==:switch + cmd << cmd_name + next + end + + if data[yml_name].is_a?(Array) + data[yml_name].each {|val| cmd << cmd_name << esc(val, options[:escape])} + elsif data[yml_name].is_a?(Hash) + data[yml_name].each {|key, val| cmd << cmd_name << "#{esc(key, options[:escape])}=#{esc(val, options[:escape])}"} + else + cmd << cmd_name << esc(data[yml_name], options[:escape]) + end + end run("docker rm -f #{(data["container_name"] || key).shellescape}", true) - run(cmd.join(" ")) + run(cmd.compact.join(" ")) (data["after_run"] || []).each{|cmd| run(cmd)} end