1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
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
|
#!/usr/bin/env ruby
require 'optparse'
require 'ostruct'
require 'tempfile'
OPTIONS = OpenStruct.new({
noop: false,
drumkit: ".drumkit"
})
class Drumkit
def self.parse_file(filename)
Drumkit.parse(File.read(filename))
end
def self.parse(input)
input = input.lines if input.is_a?(String)
input = input.map(&:strip).reject(&:empty?)
drumkit = Drumkit.new(input)
end
def initialize(lines = [])
@bassdrum = nil
@kickdrum = nil
@snaredrum = nil
lines.each do |line|
case line
when /^BASSDRUM/
@bassdrum = line[9..-1]
when /^KICKDRUM/
@kickdrum = line[9..-1]
when /^SNAREDRUM/
@snaredrum = line[10..-1]
end
end
end
attr_accessor :bassdrum, :kickdrum, :snaredrum, :drumsticks
def add_stick(stick)
@drumsticks.push(stick)
end
def to_s
"This file will be modified automatically. Only make changes if you know what you are doing. Otherwise, use drum.\n\n" +
(@bassdrum ? "BASSDRUM #{@bassdrum}\n" : "") +
(@kickdrum ? "KICKDRUM #{@kickdrum}\n" : "") +
(@snaredrum ? "SNAREDRUM #{@snaredrum}\n" : "")
end
end
def help(parser)
puts parser.banner
puts parser.summarize
end
def info(str)
puts "INFO: #{str}"
end
def error(str, rc = nil)
$stderr.puts "ERROR: #{str}"
exit rc unless rc.nil?
end
def entrypoint
"./#{File.basename(Dir.pwd)}.rb"
end
parser = OptionParser.new do |opt|
opt.banner = "DRuM: The Docker Ruby Manager\n\nUsage: drum [flags] COMMAND"
opt.on("-n", "--noop", "--dry-run", "Dry run, don't actually *do* anything") do
OPTIONS.noop = true
end
opt.on("-d", "--drumkit", :REQUIRED, "Specify drumkit file (default: .drumkit)") do |dk|
OPTIONS.drumkit = dk
end
opt.on("-h", "--help", "Print usage") do
help opt
exit 0
end
end
parser.parse!
COMMAND = ARGV.shift&.downcase
if File.exists?(OPTIONS.drumkit)
DRUMKIT = Drumkit.parse_file(OPTIONS.drumkit)
else
DRUMKIT = Drumkit.new
end
case COMMAND
when nil
error "Error: No command given\n\n"
help parser
exit 1
when "bass"
if !ARGV[0].nil?
bd = ARGV[0].strip
case bd
when /\A[^:]+\Z/
bassdrum = "ruby:#{bd}"
when /:\Z/
bassdrum = bd[0..-2]
when /\w:\w/
bassdrum = bd
else
error("Invalid Bass Drum specification: #{bd}", 1)
end
else
if DRUMKIT.bassdrum.nil?
bassdrum = "ruby:alpine"
else
bassdrum = DRUMKIT.bassdrum
end
end
info "Fetching Bass Drum: #{bassdrum}" if OPTIONS.noop
system "docker pull #{bassdrum}" unless OPTIONS.noop
DRUMKIT.bassdrum = bassdrum unless OPTIONS.noop
when "kick"
error("No Bass Drum specified.", 1) if DRUMKIT.bassdrum.nil?
if DRUMKIT.kickdrum.nil?
kickdrum = "drum-bass-#{DRUMKIT.bassdrum.gsub(/:/,"_")}-kick-#{File.basename(Dir.pwd)}"
else
kickdrum = DRUMKIT.kickdrum
end
puts "Building Kick Drum: #{kickdrum}" if OPTIONS.noop
Tempfile.open("drum-tmp-dockerfile", Dir.pwd) do |f|
f.puts "FROM #{DRUMKIT.bassdrum}"
f.puts "COPY Gemfile* ./"
f.puts "RUN bundle install"
f.flush
system "docker build -t #{kickdrum} -f #{File.basename(f)} ."
system "docker run #{kickdrum} cat Gemfile.lock > Gemfile.lock"
end unless OPTIONS.noop
DRUMKIT.kickdrum = kickdrum unless OPTIONS.noop
when "snare"
error("No Kick Drum specified.", 1) if DRUMKIT.kickdrum.nil?
if DRUMKIT.snaredrum.nil?
snaredrum = "#{DRUMKIT.kickdrum}-snare-#{entrypoint.gsub(/[\/.]/, "_")}"
else
snaredrum = DRUMKIT.snaredrum
end
puts "Creating Snare Drum: #{snaredrum}" if OPTIONS.noop
Tempfile.open("drum-tmp-dockerfile", Dir.pwd) do |f|
f.puts "FROM #{DRUMKIT.kickdrum}"
f.puts "COPY . ."
f.puts "ENTRYPOINT [\"#{entrypoint}\"]"
f.flush
system "docker build -t #{snaredrum} -f #{File.basename(f)} ."
end unless OPTIONS.noop
DRUMKIT.snaredrum = snaredrum unless OPTIONS.noop
when "roll"
error("No Snare Drum specified.", 1) if DRUMKIT.snaredrum.nil?
system "docker run #{ARGV.join(" ")} #{DRUMKIT.snaredrum}"
end
File.open(OPTIONS.drumkit, "w").puts(DRUMKIT.to_s)
|