pauper 0.0.4
Sign up to get free protection for your applications and to get access to all the features.
- data/README +12 -0
- data/bin/pauper +55 -0
- data/lib/client.rb.erb +7 -0
- data/lib/dhcpd.rb +84 -0
- data/lib/hosts.rb +61 -0
- data/lib/pauper.rb +385 -0
- data/lib/vmx.rb +24 -0
- metadata +116 -0
data/README
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
To make a new base VM:
|
2
|
+
|
3
|
+
1) Install your OS (only tested with Ubuntu 10.04 64-bit)
|
4
|
+
2) Setup a user with a password that you don't mind hardcoding in your Pauperfile
|
5
|
+
3) Make sure that user has no-password sudo access
|
6
|
+
4) sudo apt-get install ruby1.8 ruby1.8-dev libopenssl-ruby rubygems ssh
|
7
|
+
5) sudo gem install chef
|
8
|
+
6) Delete /etc/udev/rules.d/70-persistent-net.whatever
|
9
|
+
7) Shut down VM
|
10
|
+
8) Remove all *.lck files from inside the VM's vmwarevm folder
|
11
|
+
|
12
|
+
DONE!
|
data/bin/pauper
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'thor'
|
5
|
+
require 'pauper'
|
6
|
+
|
7
|
+
class CLI < Thor
|
8
|
+
desc "destroy [NODENAME]", "Completely destroy a VM"
|
9
|
+
def destroy(node_name=nil)
|
10
|
+
pauper = Pauper.new
|
11
|
+
if node_name
|
12
|
+
pauper.destroy(node_name)
|
13
|
+
else
|
14
|
+
pauper.destroy_all
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
desc "start [NODENAME]", "Start a VM"
|
19
|
+
def start(node_name=nil)
|
20
|
+
pauper = Pauper.new
|
21
|
+
if node_name
|
22
|
+
pauper.start(node_name)
|
23
|
+
else
|
24
|
+
pauper.start_all
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
desc "stop [NODENAME]", "Stop a VM"
|
29
|
+
def stop(node_name=nil)
|
30
|
+
pauper = Pauper.new
|
31
|
+
if node_name
|
32
|
+
pauper.stop(node_name)
|
33
|
+
else
|
34
|
+
pauper.stop_all
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
desc "setup [NODENAME]", "Refresh configs and run Chef on a VM"
|
39
|
+
def setup(node_name=nil)
|
40
|
+
pauper = Pauper.new
|
41
|
+
if node_name
|
42
|
+
pauper.setup(node_name)
|
43
|
+
else
|
44
|
+
pauper.setup_all
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
desc 'write_hosts', 'Write out a new /etc/hosts file'
|
49
|
+
def write_hosts
|
50
|
+
pauper = Pauper.new
|
51
|
+
pauper.write_hosts
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
CLI.start
|
data/lib/client.rb.erb
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
# Managed by Pauper
|
2
|
+
|
3
|
+
node_name "<%= node_config.name %>"
|
4
|
+
chef_server_url "<%= config[:chef_server_url] %>"
|
5
|
+
validation_client_name "<%= config[:validation_client_name] %>"
|
6
|
+
environment "<%= config[:chef_environment] %>"
|
7
|
+
json_attribs "/etc/chef/client-config.json"
|
data/lib/dhcpd.rb
ADDED
@@ -0,0 +1,84 @@
|
|
1
|
+
class DHCPD
|
2
|
+
attr_reader :config
|
3
|
+
|
4
|
+
def initialize(conf_path)
|
5
|
+
@conf_path = conf_path
|
6
|
+
@preamble = ''
|
7
|
+
@postamble = ''
|
8
|
+
@config = {}
|
9
|
+
|
10
|
+
parse
|
11
|
+
end
|
12
|
+
|
13
|
+
def save
|
14
|
+
tmp_path = '.tmp.dhcpd.conf'
|
15
|
+
File.open(tmp_path, 'w') do |f|
|
16
|
+
f.write @preamble
|
17
|
+
f.puts BEGIN_BUM
|
18
|
+
|
19
|
+
@config.each do |host, host_config|
|
20
|
+
f.puts "host #{host} {"
|
21
|
+
host_config.each do |key, value|
|
22
|
+
f.puts "\t#{key} #{value};"
|
23
|
+
end
|
24
|
+
f.puts "}"
|
25
|
+
end
|
26
|
+
|
27
|
+
f.puts END_BUM
|
28
|
+
f.write @postamble
|
29
|
+
end
|
30
|
+
|
31
|
+
system 'sudo', 'mv', tmp_path, @conf_path
|
32
|
+
end
|
33
|
+
|
34
|
+
def restart
|
35
|
+
system 'sudo "/Library/Application Support/VMware Fusion/boot.sh" --restart >>vmware.log 2>&1'
|
36
|
+
end
|
37
|
+
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
BEGIN_BUM = "#### BEGIN BUM ####"
|
42
|
+
END_BUM = "#### END BUM ####"
|
43
|
+
|
44
|
+
def parse
|
45
|
+
state = :preamble
|
46
|
+
host = nil
|
47
|
+
|
48
|
+
File.open(@conf_path).each_line do |rawline|
|
49
|
+
line = rawline.strip
|
50
|
+
|
51
|
+
case state
|
52
|
+
when :preamble
|
53
|
+
if line == BEGIN_BUM
|
54
|
+
state = :outside_host
|
55
|
+
else
|
56
|
+
@preamble << rawline
|
57
|
+
end
|
58
|
+
|
59
|
+
when :outside_host
|
60
|
+
next unless line =~ /^host .* \{$/
|
61
|
+
words = line.split(' ').map { |x| x.strip }
|
62
|
+
host = words[1]
|
63
|
+
@config[host] = {}
|
64
|
+
state = :inside_host
|
65
|
+
|
66
|
+
when :inside_host
|
67
|
+
next if line.size == 0 || line.strip =~ /^#/
|
68
|
+
if line == '}'
|
69
|
+
state = :outside_host
|
70
|
+
host = nil
|
71
|
+
elsif line == END_BUM
|
72
|
+
state = :postamble
|
73
|
+
else
|
74
|
+
parts = line.chomp(';').split(' ')
|
75
|
+
@config[host][parts[0..-2].join(' ')] = parts[-1]
|
76
|
+
end
|
77
|
+
|
78
|
+
when :postamble
|
79
|
+
@postamble << rawline
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
end
|
84
|
+
end
|
data/lib/hosts.rb
ADDED
@@ -0,0 +1,61 @@
|
|
1
|
+
# Class for parsing and writing /etc/hosts file
|
2
|
+
|
3
|
+
class Hosts
|
4
|
+
def initialize
|
5
|
+
@preamble = ""
|
6
|
+
@postamble = ""
|
7
|
+
@config = {}
|
8
|
+
|
9
|
+
parse
|
10
|
+
end
|
11
|
+
|
12
|
+
attr_reader :config
|
13
|
+
|
14
|
+
def save
|
15
|
+
File.open('.tmp.hosts','w') do |f|
|
16
|
+
f.write @preamble
|
17
|
+
f.puts BEGIN_LINE
|
18
|
+
|
19
|
+
@config.each do |ip, host|
|
20
|
+
f.puts "#{ip}\t#{host}"
|
21
|
+
end
|
22
|
+
|
23
|
+
f.puts END_LINE
|
24
|
+
f.write @postamble
|
25
|
+
end
|
26
|
+
system "sudo mv .tmp.hosts /etc/hosts"
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
BEGIN_LINE = "#### BEGIN PAUPER ####"
|
32
|
+
END_LINE = "#### END PAUPER ####"
|
33
|
+
|
34
|
+
def parse
|
35
|
+
state = :preamble
|
36
|
+
|
37
|
+
File.open('/etc/hosts').each_line do |line|
|
38
|
+
case state
|
39
|
+
when :preamble
|
40
|
+
if line.include? BEGIN_LINE
|
41
|
+
state = :pauper
|
42
|
+
else
|
43
|
+
@preamble << line
|
44
|
+
end
|
45
|
+
when :pauper
|
46
|
+
if line.include? END_LINE
|
47
|
+
state = :postamble
|
48
|
+
else
|
49
|
+
if line.strip =~ /^#/
|
50
|
+
# skip
|
51
|
+
else
|
52
|
+
ip, host = line.split(/\s+/)
|
53
|
+
@config[ip] = host
|
54
|
+
end
|
55
|
+
end
|
56
|
+
when :postamble
|
57
|
+
@postamble << line
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
data/lib/pauper.rb
ADDED
@@ -0,0 +1,385 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'net/ssh'
|
3
|
+
require 'net/scp'
|
4
|
+
require 'json'
|
5
|
+
|
6
|
+
require 'fileutils'
|
7
|
+
require 'erb'
|
8
|
+
require 'ostruct'
|
9
|
+
|
10
|
+
require 'vmx'
|
11
|
+
require 'dhcpd'
|
12
|
+
require 'hosts'
|
13
|
+
|
14
|
+
class Pauper
|
15
|
+
DEFAULT_PAUPERFILE = './Pauperfile'
|
16
|
+
DEFAULT_VM_PATH = File.expand_path('~/Documents/Virtual Machines.localized/')
|
17
|
+
|
18
|
+
VMWARE_PATH = '/Library/Application Support/VMware Fusion'
|
19
|
+
DHCPD_CONF_PATH = "#{VMWARE_PATH}/vmnet8/dhcpd.conf"
|
20
|
+
|
21
|
+
def initialize(pauperfile=DEFAULT_PAUPERFILE)
|
22
|
+
@pauper_config = Pauper::Config.new(DEFAULT_PAUPERFILE)
|
23
|
+
end
|
24
|
+
|
25
|
+
def bootstrap
|
26
|
+
vmx = template_vmx
|
27
|
+
vmx.data['sharedFolder0.hostPath'] = File.expand_path('~')
|
28
|
+
vmx.data['sharedFolder0.guestName'] = 'host_home'
|
29
|
+
vmx.save
|
30
|
+
end
|
31
|
+
|
32
|
+
def create(node_name)
|
33
|
+
node_config = get_node_config(node_name)
|
34
|
+
|
35
|
+
raise "VM already exists!" if vm_exists?(node_name)
|
36
|
+
|
37
|
+
puts "Cloning template..."
|
38
|
+
clone_template node_name
|
39
|
+
|
40
|
+
puts "Updating machine configuration..."
|
41
|
+
mac = generate_mac
|
42
|
+
uuid = generate_uuid
|
43
|
+
|
44
|
+
vmx = node_vmx(node_name)
|
45
|
+
vmx.data['displayName'] = node_name
|
46
|
+
vmx.data['memsize'] = node_config.config[:ram] || @pauper_config.config[:default_ram] || 512
|
47
|
+
vmx.data['numvcpus'] = node_config.config[:cpus] || @pauper_config.config[:default_cpus] || 1
|
48
|
+
vmx.data['ethernet0.address'] = mac
|
49
|
+
vmx.data['uuid.bios'] = uuid
|
50
|
+
vmx.data['uuid.location'] = uuid
|
51
|
+
vmx.save
|
52
|
+
|
53
|
+
dhcpd = DHCPD.new(DHCPD_CONF_PATH)
|
54
|
+
dhcpd.config[node_name] = {
|
55
|
+
'hardware ethernet' => mac,
|
56
|
+
'fixed-address' => node_config.config[:ip]
|
57
|
+
}
|
58
|
+
dhcpd.save
|
59
|
+
|
60
|
+
puts "Restarting dhcpd..."
|
61
|
+
dhcpd.restart
|
62
|
+
|
63
|
+
puts "Starting..."
|
64
|
+
start_node(node_name)
|
65
|
+
|
66
|
+
setup(node_name)
|
67
|
+
end
|
68
|
+
|
69
|
+
def setup(node_name)
|
70
|
+
node_config = get_node_config(node_name)
|
71
|
+
|
72
|
+
puts "Setting up #{node_name}..."
|
73
|
+
|
74
|
+
client_erb = ERB.new(File.read(File.join(File.dirname(__FILE__), 'client.rb.erb')))
|
75
|
+
client_rb_data = client_erb.result(OpenStruct.new(:config => @pauper_config.config, :node_config => node_config).send(:binding))
|
76
|
+
tmp_client_rb_path = ".tmp.#{node_name}.client.rb"
|
77
|
+
File.open(tmp_client_rb_path,'w') do |f|
|
78
|
+
f.puts client_rb_data
|
79
|
+
end
|
80
|
+
|
81
|
+
chef_attribs = {
|
82
|
+
:run_list => @pauper_config.config[:default_run_list] + node_config.config[:run_list],
|
83
|
+
:ip => {
|
84
|
+
:private => node_config.config[:ip],
|
85
|
+
:private_netmask => '255.255.255.0'
|
86
|
+
}
|
87
|
+
}.merge(@pauper_config.config[:chef_options]).merge(node_config.config[:chef_options])
|
88
|
+
|
89
|
+
puts "Uploading Chef files..."
|
90
|
+
Net::SCP.start node_config.config[:ip], @pauper_config.config[:ssh_user], :password => @pauper_config.config[:ssh_password] do |scp|
|
91
|
+
scp.upload! tmp_client_rb_path, "client.rb"
|
92
|
+
scp.upload! @pauper_config.config[:validation_key_path], "validation.pem"
|
93
|
+
scp.upload! StringIO.new(chef_attribs.to_json), "client-config.json"
|
94
|
+
end
|
95
|
+
|
96
|
+
FileUtils.rm(tmp_client_rb_path)
|
97
|
+
|
98
|
+
enable_shared_folders node_name
|
99
|
+
@pauper_config.config[:shares].each do |share_name, guest_path, host_path, options|
|
100
|
+
cmd "mkdir -p #{host_path}"
|
101
|
+
share_folder node_name, share_name, host_path
|
102
|
+
end
|
103
|
+
|
104
|
+
puts "Connecting over SSH..."
|
105
|
+
Net::SSH.start node_config.config[:ip], @pauper_config.config[:ssh_user], :password => @pauper_config.config[:ssh_password] do |ssh|
|
106
|
+
ssh_exec ssh, "sudo hostname #{node_name}"
|
107
|
+
ssh_exec ssh, "sudo mkdir /etc/chef"
|
108
|
+
|
109
|
+
@pauper_config.config[:shares].each do |share_name, guest_path, host_path, options|
|
110
|
+
ssh_exec ssh, "sudo mkdir -p #{File.dirname(guest_path)} && sudo ln -sf /mnt/hgfs/#{share_name} #{guest_path}"
|
111
|
+
end
|
112
|
+
|
113
|
+
ssh_exec ssh, "sudo mv client.rb /etc/chef/"
|
114
|
+
ssh_exec ssh, "sudo mv validation.pem /etc/chef/"
|
115
|
+
ssh_exec ssh, "sudo mv client-config.json /etc/chef/"
|
116
|
+
|
117
|
+
ssh.exec! "sudo /var/lib/gems/1.8/bin/chef-client" do |channel, stream, data|
|
118
|
+
print data
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
def destroy(node_name)
|
124
|
+
node_config = get_node_config(node_name)
|
125
|
+
|
126
|
+
if vm_exists?(node_name)
|
127
|
+
stop_node(node_name)
|
128
|
+
|
129
|
+
puts "Removing #{node_name} from Chef..."
|
130
|
+
`knife node delete #{node_name} -y`
|
131
|
+
`knife client delete #{node_name} -y`
|
132
|
+
|
133
|
+
puts "Destroying #{node_name}..."
|
134
|
+
FileUtils.rm_rf(node_name_to_vm_path(node_name))
|
135
|
+
else
|
136
|
+
puts "#{node_name} hasn't even been created yet, thusly you can't destroy it!"
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
def stop(node_name)
|
141
|
+
node_config = get_node_config(node_name)
|
142
|
+
|
143
|
+
if vm_running?(node_name)
|
144
|
+
puts "Stopping #{node_name}..."
|
145
|
+
stop_node(node_name)
|
146
|
+
else
|
147
|
+
puts "wtf, #{node_name} is not running."
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
def start(node_name)
|
152
|
+
node_config = get_node_config(node_name)
|
153
|
+
|
154
|
+
if vm_running?(node_name)
|
155
|
+
puts "Dude, #{node_name} is already running!"
|
156
|
+
elsif vm_exists?(node_name)
|
157
|
+
puts "Starting #{node_name}..."
|
158
|
+
start_node node_name
|
159
|
+
else
|
160
|
+
puts "Generating, then starting #{node_name}..."
|
161
|
+
create node_name
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
def write_hosts
|
166
|
+
puts "Writing /etc/hosts file..."
|
167
|
+
hosts = Hosts.new
|
168
|
+
@pauper_config.config[:nodes].each do |node|
|
169
|
+
hosts.config[node.config[:ip]] = node.name
|
170
|
+
end
|
171
|
+
hosts.save
|
172
|
+
end
|
173
|
+
|
174
|
+
|
175
|
+
def start_all
|
176
|
+
puts "Starting all nodes..."
|
177
|
+
@pauper_config.config[:nodes].each { |n| start(n.name) }
|
178
|
+
end
|
179
|
+
|
180
|
+
def stop_all
|
181
|
+
puts "Stopping all nodes..."
|
182
|
+
@pauper_config.config[:nodes].each { |n| stop(n.name) }
|
183
|
+
end
|
184
|
+
|
185
|
+
def destroy_all
|
186
|
+
puts "Destroying all nodes..."
|
187
|
+
@pauper_config.config[:nodes].each { |n| destroy(n.name) }
|
188
|
+
end
|
189
|
+
|
190
|
+
def setup_all
|
191
|
+
puts "Setting up all nodes..."
|
192
|
+
@pauper_config.config[:nodes].each { |n| setup(n.name) }
|
193
|
+
end
|
194
|
+
|
195
|
+
private
|
196
|
+
|
197
|
+
def cmd(*args)
|
198
|
+
puts ["local>", *args].join(" ")
|
199
|
+
system *args
|
200
|
+
end
|
201
|
+
|
202
|
+
def ssh_exec(ssh, cmd)
|
203
|
+
puts "ssh> #{cmd}"
|
204
|
+
print ssh.exec!(cmd)
|
205
|
+
end
|
206
|
+
|
207
|
+
def enable_shared_folders(node_name)
|
208
|
+
cmd "'#{VMWARE_PATH}/vmrun' enableSharedFolders '#{node_name_to_vmx(node_name)}'"
|
209
|
+
end
|
210
|
+
|
211
|
+
def share_folder(node_name, share_name, path)
|
212
|
+
cmd "'#{VMWARE_PATH}/vmrun' addSharedFolder '#{node_name_to_vmx(node_name)}' '#{share_name}' '#{path}'"
|
213
|
+
end
|
214
|
+
|
215
|
+
def get_node_config(node_name)
|
216
|
+
node_config = @pauper_config.get_node(node_name)
|
217
|
+
raise "Alas, I don't know about a node named #{node_name.inspect}..." unless node_config
|
218
|
+
node_config
|
219
|
+
end
|
220
|
+
|
221
|
+
def vm_exists?(node_name)
|
222
|
+
File.exists? node_name_to_vm_path(node_name)
|
223
|
+
end
|
224
|
+
|
225
|
+
def vm_running?(node_name)
|
226
|
+
`'#{VMWARE_PATH}/vmrun' list`.include?("#{node_name}.vmwarevm")
|
227
|
+
end
|
228
|
+
|
229
|
+
def clone_template(node_name)
|
230
|
+
FileUtils.cp_r(template_vm_path, node_name_to_vm_path(node_name))
|
231
|
+
end
|
232
|
+
|
233
|
+
def template_vmx
|
234
|
+
@template_vmx ||= VMX.new(@pauper_config.config[:vmx])
|
235
|
+
end
|
236
|
+
|
237
|
+
def node_vmx(node_name)
|
238
|
+
VMX.new(node_name_to_vmx(node_name))
|
239
|
+
end
|
240
|
+
|
241
|
+
def start_node(node_name)
|
242
|
+
cmd "'#{VMWARE_PATH}/vmrun' start '#{node_name_to_vmx(node_name)}' nogui >>vmware.log 2>&1"
|
243
|
+
end
|
244
|
+
|
245
|
+
def stop_node(node_name)
|
246
|
+
cmd "'#{VMWARE_PATH}/vmrun' stop '#{node_name_to_vmx(node_name)}' >>vmware.log 2>&1"
|
247
|
+
end
|
248
|
+
|
249
|
+
def generate_mac
|
250
|
+
"00:50:56:" + 3.times.map { ("%2s" % rand(256).to_s(16)).gsub(' ','0') }.join(':').upcase
|
251
|
+
end
|
252
|
+
|
253
|
+
# not actually universal - doesn't fucking matter
|
254
|
+
def generate_uuid
|
255
|
+
2.times.map {
|
256
|
+
8.times.map {
|
257
|
+
("%2s" % rand(256).to_s(16)).gsub(' ','0')
|
258
|
+
}.join(' ')
|
259
|
+
}.join('-')
|
260
|
+
end
|
261
|
+
|
262
|
+
def node_name_to_vmx(node_name)
|
263
|
+
Dir[File.join(node_name_to_vm_path(node_name), '*.vmx')][0]
|
264
|
+
end
|
265
|
+
|
266
|
+
def node_name_to_vm_path(node_name)
|
267
|
+
File.join(DEFAULT_VM_PATH, "#{node_name}.vmwarevm")
|
268
|
+
end
|
269
|
+
|
270
|
+
def template_vm_path
|
271
|
+
File.dirname(@pauper_config.config[:vmx])
|
272
|
+
end
|
273
|
+
|
274
|
+
class Config
|
275
|
+
attr_reader :config
|
276
|
+
|
277
|
+
def initialize(pauperfile)
|
278
|
+
@config = {
|
279
|
+
:nodes => [],
|
280
|
+
:ssh_user => 'dev',
|
281
|
+
:ssh_password => 'password',
|
282
|
+
:run_list => [],
|
283
|
+
:shares => [],
|
284
|
+
:suffix => '',
|
285
|
+
:chef_options => {}
|
286
|
+
}
|
287
|
+
instance_eval File.read(pauperfile)
|
288
|
+
end
|
289
|
+
|
290
|
+
def get_node(node_name)
|
291
|
+
@config[:nodes].detect { |n| n.name == node_name }
|
292
|
+
end
|
293
|
+
|
294
|
+
|
295
|
+
def ssh_user(user)
|
296
|
+
@config[:ssh_user] = user
|
297
|
+
end
|
298
|
+
|
299
|
+
def ssh_password(pass)
|
300
|
+
@config[:ssh_password] = pass
|
301
|
+
end
|
302
|
+
|
303
|
+
def vmx(vmx_file)
|
304
|
+
@config[:vmx] = File.expand_path(vmx_file)
|
305
|
+
end
|
306
|
+
|
307
|
+
def node(name, &block)
|
308
|
+
@config[:nodes] << Node.new(name + @config[:suffix], name, &block)
|
309
|
+
end
|
310
|
+
|
311
|
+
def ram(megabytes)
|
312
|
+
@config[:default_ram] = megabytes
|
313
|
+
end
|
314
|
+
|
315
|
+
def cpus(count)
|
316
|
+
@config[:default_cpus] = count
|
317
|
+
end
|
318
|
+
|
319
|
+
def chef_server_url(url)
|
320
|
+
@config[:chef_server_url] = url
|
321
|
+
end
|
322
|
+
|
323
|
+
def validation_key_path(path)
|
324
|
+
@config[:validation_key_path] = File.expand_path(path)
|
325
|
+
end
|
326
|
+
|
327
|
+
def validation_client_name(name)
|
328
|
+
@config[:validation_client_name] = name
|
329
|
+
end
|
330
|
+
|
331
|
+
def chef_environment(env)
|
332
|
+
@config[:chef_environment] = env
|
333
|
+
end
|
334
|
+
|
335
|
+
def chef_options(opts)
|
336
|
+
@config[:chef_options] = opts
|
337
|
+
end
|
338
|
+
|
339
|
+
def default_run_list(list)
|
340
|
+
@config[:default_run_list] = list
|
341
|
+
end
|
342
|
+
|
343
|
+
def share(share_name, guest_path, host_path, options={})
|
344
|
+
@config[:shares] << [share_name, guest_path, File.expand_path(host_path), options]
|
345
|
+
end
|
346
|
+
|
347
|
+
def node_suffix(suffix)
|
348
|
+
@config[:suffix] = suffix
|
349
|
+
end
|
350
|
+
|
351
|
+
class Node
|
352
|
+
attr_reader :name, :pretty_name, :config
|
353
|
+
|
354
|
+
def initialize(name, pretty_name, &block)
|
355
|
+
@name = name
|
356
|
+
@pretty_name = pretty_name
|
357
|
+
@config = {
|
358
|
+
:run_list => [],
|
359
|
+
:chef_options => {}
|
360
|
+
}
|
361
|
+
instance_eval &block
|
362
|
+
end
|
363
|
+
|
364
|
+
def run_list(*recipes)
|
365
|
+
@config[:run_list] = recipes
|
366
|
+
end
|
367
|
+
|
368
|
+
def ip(addr)
|
369
|
+
@config[:ip] = addr
|
370
|
+
end
|
371
|
+
|
372
|
+
def chef_options(options)
|
373
|
+
@config[:chef_options] = options
|
374
|
+
end
|
375
|
+
|
376
|
+
def ram(megabytes)
|
377
|
+
@config[:ram] = megabytes
|
378
|
+
end
|
379
|
+
|
380
|
+
def cpus(count)
|
381
|
+
@config[:cpus] = count
|
382
|
+
end
|
383
|
+
end
|
384
|
+
end
|
385
|
+
end
|
data/lib/vmx.rb
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
|
3
|
+
class VMX
|
4
|
+
attr_reader :data
|
5
|
+
|
6
|
+
def initialize(filename)
|
7
|
+
@filename = filename
|
8
|
+
@data = {}
|
9
|
+
|
10
|
+
File.open(filename).each_line do |line|
|
11
|
+
key, value = line.split('=', 2)
|
12
|
+
@data[key.strip] = eval(value)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def save(filename=@filename)
|
17
|
+
FileUtils.cp(filename, filename + '.bak')
|
18
|
+
File.open(filename, 'w') do |f|
|
19
|
+
@data.sort_by { |(k,v)| k }.each do |(k,v)|
|
20
|
+
f.puts "#{k} = #{v.to_s.inspect}"
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
metadata
ADDED
@@ -0,0 +1,116 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: pauper
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 0
|
8
|
+
- 4
|
9
|
+
version: 0.0.4
|
10
|
+
platform: ruby
|
11
|
+
authors:
|
12
|
+
- Tyler McMullen
|
13
|
+
autorequire:
|
14
|
+
bindir: bin
|
15
|
+
cert_chain: []
|
16
|
+
|
17
|
+
date: 2011-08-17 00:00:00 -07:00
|
18
|
+
default_executable:
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
21
|
+
name: thor
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
25
|
+
- - ">="
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
segments:
|
28
|
+
- 0
|
29
|
+
version: "0"
|
30
|
+
type: :runtime
|
31
|
+
version_requirements: *id001
|
32
|
+
- !ruby/object:Gem::Dependency
|
33
|
+
name: net-ssh
|
34
|
+
prerelease: false
|
35
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - ">="
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
segments:
|
40
|
+
- 0
|
41
|
+
version: "0"
|
42
|
+
type: :runtime
|
43
|
+
version_requirements: *id002
|
44
|
+
- !ruby/object:Gem::Dependency
|
45
|
+
name: net-scp
|
46
|
+
prerelease: false
|
47
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
48
|
+
requirements:
|
49
|
+
- - ">="
|
50
|
+
- !ruby/object:Gem::Version
|
51
|
+
segments:
|
52
|
+
- 0
|
53
|
+
version: "0"
|
54
|
+
type: :runtime
|
55
|
+
version_requirements: *id003
|
56
|
+
- !ruby/object:Gem::Dependency
|
57
|
+
name: json
|
58
|
+
prerelease: false
|
59
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
60
|
+
requirements:
|
61
|
+
- - ">="
|
62
|
+
- !ruby/object:Gem::Version
|
63
|
+
segments:
|
64
|
+
- 0
|
65
|
+
version: "0"
|
66
|
+
type: :runtime
|
67
|
+
version_requirements: *id004
|
68
|
+
description: Inspired by Vagrant but much much simpler. Also uses VMware, instead of Virtualbox.
|
69
|
+
email:
|
70
|
+
- tyler@fastly.com
|
71
|
+
executables:
|
72
|
+
- pauper
|
73
|
+
extensions: []
|
74
|
+
|
75
|
+
extra_rdoc_files: []
|
76
|
+
|
77
|
+
files:
|
78
|
+
- bin/pauper
|
79
|
+
- lib/client.rb.erb
|
80
|
+
- lib/dhcpd.rb
|
81
|
+
- lib/hosts.rb
|
82
|
+
- lib/pauper.rb
|
83
|
+
- lib/vmx.rb
|
84
|
+
- README
|
85
|
+
has_rdoc: true
|
86
|
+
homepage: http://github.com/fastly/Pauper
|
87
|
+
licenses: []
|
88
|
+
|
89
|
+
post_install_message:
|
90
|
+
rdoc_options: []
|
91
|
+
|
92
|
+
require_paths:
|
93
|
+
- lib
|
94
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
95
|
+
requirements:
|
96
|
+
- - ">="
|
97
|
+
- !ruby/object:Gem::Version
|
98
|
+
segments:
|
99
|
+
- 0
|
100
|
+
version: "0"
|
101
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
102
|
+
requirements:
|
103
|
+
- - ">="
|
104
|
+
- !ruby/object:Gem::Version
|
105
|
+
segments:
|
106
|
+
- 0
|
107
|
+
version: "0"
|
108
|
+
requirements: []
|
109
|
+
|
110
|
+
rubyforge_project:
|
111
|
+
rubygems_version: 1.3.6
|
112
|
+
signing_key:
|
113
|
+
specification_version: 3
|
114
|
+
summary: A semi-sane way to manage a multi-vm dev environment
|
115
|
+
test_files: []
|
116
|
+
|