From 8900173016e3a55f7593c3f91efc1e3b559edec7 Mon Sep 17 00:00:00 2001 From: Fabian Schlenz Date: Wed, 8 Feb 2017 16:45:53 +0100 Subject: [PATCH] Initial commit. --- dup.rb | 123 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 123 insertions(+) create mode 100755 dup.rb diff --git a/dup.rb b/dup.rb new file mode 100755 index 0000000..1829a36 --- /dev/null +++ b/dup.rb @@ -0,0 +1,123 @@ +#!/usr/bin/ruby +require 'yaml' +require 'pp' +require 'shellwords' + +def get_sample(name="container") + return <<~HEREDOC + #{name}: + image: "my/image:1.2.3" + restart: always + command: "/bin/bash" + build: "/data/dir" + + ports: + - "1234:1234" + - "8080" + - "1001:1001/udp" + + environment: + VERSION: 1.7.0 + TZ: + + volumes: + - "/etc:/etc:ro" + + links: + - "another_container" + + container_name: "Something" + mem_limit: 125M + interactive: false + detach: true + remove: false + stop_signal: SIGUSR1 + stop_grace_period: 5s + + before_build: + - "echo 'Starting build'" + after_build: + - "echo 'After build'" + before_run: + - "echo 'Starting run'" + after_run: + - "echo 'Run has finished.'" + - "docker restart container" + + devices: + - "/dev/ttyUSB0:/dev/ttyUSB0" + HEREDOC +end + +if ARGV[0]=="--sample" + puts get_sample + exit 1 +end + +def run(cmd, ignore_returnvalue=false) + puts "+ #{cmd}" + returnvalue = true + returnvalue = system(cmd) + raise "Command returned a non-zero exit value." if returnvalue!=true && !ignore_returnvalue +end + +if ARGV[0]=="--create" + filename = ARGV[1] +else + filename = ARGV[0] +end + +if filename==nil || filename=="" + raise "No name given." +end + +file = "%s/%s.yml" % [ "/data/fabian/projects/dup", filename ] + +if ARGV[0]=="--create" + raise "File #{file} already exists" if File.exists?(file) + + File.open(file, "w") {|f| f.write(get_sample(filename))} + + exec("joe #{file.shellescape}") + exit 1 # will never be reached because exec replaces this process. But just in case... ;-) +end + +raise "File #{file} not found." unless File.exists?(file) + +data = File.open(file, "r") {|f| YAML.load(f.read)} + +raise "Expected #{file} to define (at least) a container named #{filename}." unless data.has_key?(filename) + +data.each do |key, data| + if data["build"] + (data["before_build"] || []).each{|cmd| run(cmd)} + cmd = ["docker", "build", "-t", data["image"].shellescape, data["build"].shellescape] + run(cmd.join(" ")) + (data["after_build"] || []).each{|cmd| run(cmd)} + 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"] + + run("docker rm -f #{(data["container_name"] || key).shellescape}", true) + run(cmd.join(" ")) + + (data["after_run"] || []).each{|cmd| run(cmd)} +end