tenderloin 0.3.0 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- data/config/default.rb +3 -0
- data/lib/tenderloin/actions/box/add.rb +1 -0
- data/lib/tenderloin/actions/box/convert.rb +42 -0
- data/lib/tenderloin/actions/vm/provision.rb +12 -0
- data/lib/tenderloin/actions/vm/shared_folders.rb +10 -2
- data/lib/tenderloin/actions/vm/up.rb +2 -0
- data/lib/tenderloin/commands.rb +1 -1
- data/lib/tenderloin/config.rb +5 -1
- data/lib/tenderloin/env.rb +6 -3
- data/lib/tenderloin/ovftool.rb +21 -0
- data/lib/tenderloin/ssh.rb +31 -10
- data/templates/Tenderfile +10 -2
- metadata +3 -1
data/config/default.rb
CHANGED
@@ -6,6 +6,8 @@ Tenderloin::Config.run do |config|
|
|
6
6
|
|
7
7
|
config.ssh.username = "tenderloin"
|
8
8
|
config.ssh.password = "tenderloin"
|
9
|
+
config.ssh.key = nil
|
10
|
+
config.ssh.port = 22
|
9
11
|
# config.ssh.host = "localhost"
|
10
12
|
config.ssh.max_tries = 10
|
11
13
|
config.ssh.timeout = 30
|
@@ -18,6 +20,7 @@ Tenderloin::Config.run do |config|
|
|
18
20
|
|
19
21
|
config.provisioning.script = nil
|
20
22
|
config.provisioning.command = nil
|
23
|
+
config.provisioning.rsync = []
|
21
24
|
|
22
25
|
config.shared_folders.enabled = true
|
23
26
|
config.shared_folders.folders = []
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module Tenderloin
|
2
|
+
module Actions
|
3
|
+
module Box
|
4
|
+
# If the box is vagrant format, it converts it to something suitible for tenderloin
|
5
|
+
class Convert < Base
|
6
|
+
|
7
|
+
def execute!
|
8
|
+
if !Dir[@runner.directory + '/Tenderfile'].empty?
|
9
|
+
# We can do nothing - pretenderized
|
10
|
+
logger.info "Tenderloin box provided"
|
11
|
+
elsif !Dir[@runner.directory + '/Vagrantfile'].empty?
|
12
|
+
# Need to import from Vagrant. Convert the ovf to vmx using OVFtool, then write a base tenderfile
|
13
|
+
logger.info "Vagrant box provided, converting"
|
14
|
+
convert_ovf
|
15
|
+
write_tenderfile
|
16
|
+
logger.info "Vagrant box converted. It has a basic Tenderfile, you may want to customize this if needed"
|
17
|
+
logger.info "This file can be found in #{@runner.directory}"
|
18
|
+
else
|
19
|
+
raise "Invalid box - No Tenderfile or Vagrantfile"
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def convert_ovf
|
24
|
+
ovf = File.join(@runner.directory, 'box.ovf')
|
25
|
+
vmx = File.join(@runner.directory, 'vmwarebox.vmx')
|
26
|
+
OVFTool.ovf2vmx(ovf, vmx, :lax => true)
|
27
|
+
FileUtils.rm_rf(@runner.directory)
|
28
|
+
FileUtils.mv(@runner.directory + ".vmwarevm", @runner.directory)
|
29
|
+
end
|
30
|
+
|
31
|
+
def write_tenderfile
|
32
|
+
tenderfile = <<EOF
|
33
|
+
Tenderloin::Config.run do |config|
|
34
|
+
config.vm.box_vmx = "vmwarebox.vmx"
|
35
|
+
end
|
36
|
+
EOF
|
37
|
+
File.open(File.join(@runner.directory, 'Tenderfile'), 'w') {|f| f.write(tenderfile) }
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -3,10 +3,22 @@ module Tenderloin
|
|
3
3
|
module VM
|
4
4
|
class Provision < Base
|
5
5
|
def execute!
|
6
|
+
run_rsync if Tenderloin.config.provisioning.rsync
|
6
7
|
setup_script if Tenderloin.config.provisioning.script
|
7
8
|
run_command if Tenderloin.config.provisioning.command
|
8
9
|
end
|
9
10
|
|
11
|
+
def run_rsync
|
12
|
+
logger.info "Running rsync..."
|
13
|
+
Tenderloin.config.provisioning.rsync.each do |rsync|
|
14
|
+
src, dst = *rsync
|
15
|
+
SSH.execute(@runner.fusion_vm.ip) do |ssh|
|
16
|
+
ssh.exec!("mkdir -p #{dst}")
|
17
|
+
end
|
18
|
+
logger.info SSH.rsync(@runner.fusion_vm.ip, File.expand_path(src), File.expand_path(dst))
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
10
22
|
def setup_script
|
11
23
|
logger.info "Uploading provisioning script..."
|
12
24
|
|
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'timeout'
|
2
|
+
|
1
3
|
module Tenderloin
|
2
4
|
module Actions
|
3
5
|
module VM
|
@@ -29,8 +31,14 @@ module Tenderloin
|
|
29
31
|
logger.info "Creating shared folders metadata..."
|
30
32
|
|
31
33
|
shared_folders.each do |name, hostpath, guestpath|
|
32
|
-
|
33
|
-
|
34
|
+
begin
|
35
|
+
status = Timeout::timeout(10) {
|
36
|
+
@runner.fusion_vm.share_folder(name, File.expand_path(hostpath))
|
37
|
+
@runner.fusion_vm.enable_shared_folders
|
38
|
+
}
|
39
|
+
rescue Timeout::Error
|
40
|
+
logger.warn "Sharing folder #{name} timed out"
|
41
|
+
end
|
34
42
|
end
|
35
43
|
|
36
44
|
logger.info "Linking shared folders..."
|
@@ -16,6 +16,7 @@ msg
|
|
16
16
|
|
17
17
|
# Up is a "meta-action" so it really just queues up a bunch
|
18
18
|
# of other actions in its place:
|
19
|
+
Tenderloin::Box.add(Tenderloin.config.vm.box, Tenderloin.config.vm.box_url) unless Tenderloin::Env.box
|
19
20
|
steps = [Import, SharedFolders, Boot]
|
20
21
|
steps << Provision if Tenderloin.config.provisioning.enabled
|
21
22
|
steps.insert(0, MoveHardDrive) if Tenderloin.config.vm.hd_location
|
@@ -46,6 +47,7 @@ msg
|
|
46
47
|
data.delete "ethernet1.generatedAddress"
|
47
48
|
data.delete "ethernet0.generatedAddressOffset"
|
48
49
|
data.delete "ethernet1.generatedAddressOffset"
|
50
|
+
data.delete 'displayname'
|
49
51
|
data['displayName'] = "tenderloin-" + @runner.vm_id
|
50
52
|
end
|
51
53
|
end
|
data/lib/tenderloin/commands.rb
CHANGED
data/lib/tenderloin/config.rb
CHANGED
@@ -59,10 +59,13 @@ module Tenderloin
|
|
59
59
|
attr_accessor :host
|
60
60
|
attr_accessor :max_tries
|
61
61
|
attr_accessor :timeout
|
62
|
+
attr_accessor :key
|
63
|
+
attr_accessor :port
|
62
64
|
end
|
63
65
|
|
64
66
|
class VMConfig < Base
|
65
67
|
attr_accessor :box
|
68
|
+
attr_accessor :box_url
|
66
69
|
attr_accessor :box_vmx
|
67
70
|
attr_accessor :project_directory
|
68
71
|
attr_accessor :hd_location
|
@@ -99,8 +102,9 @@ module Tenderloin
|
|
99
102
|
class ProvisioningConfig
|
100
103
|
attr_accessor :script
|
101
104
|
attr_accessor :command
|
105
|
+
attr_accessor :rsync
|
102
106
|
def enabled
|
103
|
-
script || command
|
107
|
+
script || command || !rsync.empty?
|
104
108
|
end
|
105
109
|
end
|
106
110
|
|
data/lib/tenderloin/env.rb
CHANGED
@@ -11,11 +11,14 @@ module Tenderloin
|
|
11
11
|
extend Tenderloin::Util
|
12
12
|
|
13
13
|
class << self
|
14
|
-
def box
|
14
|
+
def box
|
15
|
+
load_box! unless @@box
|
16
|
+
@@box
|
17
|
+
end
|
15
18
|
def persisted_vm; @@persisted_vm; end
|
16
19
|
def root_path; @@root_path; end
|
17
20
|
def dotfile_path
|
18
|
-
File.join(root_path, $ROOTFILE_NAME + ".loinstate")
|
21
|
+
File.join(root_path, "." + $ROOTFILE_NAME + ".loinstate")
|
19
22
|
end
|
20
23
|
def home_path; File.expand_path(Tenderloin.config.tenderloin.home); end
|
21
24
|
def tmp_path; File.join(home_path, "tmp"); end
|
@@ -127,7 +130,7 @@ No base box was specified! A base box is required as a staring point
|
|
127
130
|
for every tenderloin virtual machine. Please specify one in your Tenderfile
|
128
131
|
using `config.vm.box`
|
129
132
|
msg
|
130
|
-
|
133
|
+
elsif !Tenderloin.config.vm.box_url
|
131
134
|
error_and_exit(<<-msg)
|
132
135
|
Specified box `#{Tenderloin.config.vm.box}` does not exist!
|
133
136
|
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Tenderloin
|
2
|
+
class OVFTool
|
3
|
+
TOOL = "/Applications/VMware\\ Fusion.app//Contents/Library/VMware\\ OVF\\ Tool/ovftool"
|
4
|
+
|
5
|
+
def self.run(cmd, opts = '')
|
6
|
+
res = `#{TOOL} #{opts} #{cmd}`
|
7
|
+
if $? == 0
|
8
|
+
return res
|
9
|
+
else
|
10
|
+
raise "Error running ovftool command #{cmd}: " + res
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.ovf2vmx(ovf, vmx, opts = {})
|
15
|
+
cmd_opts = []
|
16
|
+
cmd_opts << '--lax' if opts[:lax]
|
17
|
+
run("#{cmd_opts.join(' ')} #{ovf} #{vmx}")
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
end
|
data/lib/tenderloin/ssh.rb
CHANGED
@@ -3,17 +3,16 @@ module Tenderloin
|
|
3
3
|
SCRIPT = File.join(File.dirname(__FILE__), '..', '..', 'script', 'tenderloin-ssh-expect.sh')
|
4
4
|
|
5
5
|
class << self
|
6
|
-
def connect(
|
7
|
-
options
|
8
|
-
|
9
|
-
|
6
|
+
def connect(ip)
|
7
|
+
if options.key
|
8
|
+
Kernel.exec "#{cmd_ssh_opts} #{options.username}@#{ip}"
|
9
|
+
else
|
10
|
+
Kernel.exec cmd_ssh_opts.strip
|
10
11
|
end
|
11
|
-
|
12
|
-
Kernel.exec "#{SCRIPT} #{options[:username]} #{options[:password]} #{options[:host]} #{port(opts)}".strip
|
13
12
|
end
|
14
13
|
|
15
14
|
def execute(ip)
|
16
|
-
Net::SSH.start(ip, Tenderloin.config[:ssh][:username],
|
15
|
+
Net::SSH.start(ip, Tenderloin.config[:ssh][:username], net_ssh_opts) do |ssh|
|
17
16
|
yield ssh
|
18
17
|
end
|
19
18
|
end
|
@@ -25,11 +24,16 @@ module Tenderloin
|
|
25
24
|
end
|
26
25
|
end
|
27
26
|
|
27
|
+
def rsync(ip,src,dst)
|
28
|
+
cmd = "rsync -avz --delete -e \"#{cmd_ssh_opts}\" #{src} #{options.username}@#{ip}:#{dst}"
|
29
|
+
`#{cmd}`
|
30
|
+
end
|
31
|
+
|
28
32
|
def up?(ip)
|
29
33
|
check_thread = Thread.new do
|
30
34
|
begin
|
31
35
|
Thread.current[:result] = false
|
32
|
-
Net::SSH.start(ip, Tenderloin.config.ssh.username,
|
36
|
+
Net::SSH.start(ip, Tenderloin.config.ssh.username, net_ssh_opts) do |ssh|
|
33
37
|
Thread.current[:result] = true
|
34
38
|
end
|
35
39
|
rescue Errno::ECONNREFUSED, Net::SSH::Disconnect
|
@@ -41,8 +45,25 @@ module Tenderloin
|
|
41
45
|
return check_thread[:result]
|
42
46
|
end
|
43
47
|
|
44
|
-
def
|
45
|
-
|
48
|
+
def options
|
49
|
+
Tenderloin.config.ssh
|
50
|
+
end
|
51
|
+
|
52
|
+
def cmd_ssh_opts
|
53
|
+
if options.key
|
54
|
+
"ssh -i #{options.key} -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -p #{options.port}"
|
55
|
+
else
|
56
|
+
"#{SCRIPT} #{options.username} #{options.password} #{options.host} #{options.port}".strip
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def net_ssh_opts
|
61
|
+
opts = {}
|
62
|
+
opts[:port] = Tenderloin.config.ssh.port
|
63
|
+
opts[:password] = Tenderloin.config.ssh.password
|
64
|
+
opts[:timeout] = Tenderloin.config.ssh.timeout
|
65
|
+
opts[:keys] = [Tenderloin.config[:ssh][:key]] if Tenderloin.config[:ssh][:key]
|
66
|
+
opts
|
46
67
|
end
|
47
68
|
end
|
48
69
|
end
|
data/templates/Tenderfile
CHANGED
@@ -5,19 +5,27 @@ Tenderloin::Config.run do |config|
|
|
5
5
|
|
6
6
|
# Every Tenderloin virtual environment requires a box to build off of.
|
7
7
|
config.vm.box = "base"
|
8
|
+
# You can optionally specify a path or URL to automatically retrieve it from
|
9
|
+
# config.vm.box_url = "http://download"
|
8
10
|
|
9
11
|
## SSH username and password defaults to 'tenderloin'. You can change this.
|
12
|
+
## If you provide a key, this will be used over the password
|
10
13
|
# config.ssh.username = 'youruser'
|
11
14
|
# config.ssh.password = 'yourpass'
|
15
|
+
# config.ssh.key = '~/.ssh/id_rsa'
|
12
16
|
|
13
|
-
## Provisioning can either provide a shell script, or a command to execute
|
17
|
+
## Provisioning can either provide a shell script, or a command to execute.
|
18
|
+
## You can also provide folders to rsync (over SSH)
|
14
19
|
# config.provisioning.script = <<EOF
|
15
20
|
# ls /usr
|
16
21
|
# EOF
|
17
22
|
# config.provisioning.command = "apt-get install -y ruby"
|
23
|
+
## This is destructive - it uses the --delete flag
|
24
|
+
# config.provisioning.rsync << ["src/", "dst"]
|
18
25
|
|
19
26
|
## Shared folders are enabled by default, and the project dir is always shared
|
20
27
|
## You can turn this off, or add additional folders
|
21
28
|
# config.shared_folders.enabled = false
|
22
|
-
# config.shared_folders.folders
|
29
|
+
# config.shared_folders.folders << ["my-files", "src", "/mnt/src"]
|
30
|
+
# config.shared_folders.folders << ["bin-files", "bin", "/mnt/bin"]
|
23
31
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: tenderloin
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -108,6 +108,7 @@ extra_rdoc_files:
|
|
108
108
|
files:
|
109
109
|
- lib/tenderloin/actions/base.rb
|
110
110
|
- lib/tenderloin/actions/box/add.rb
|
111
|
+
- lib/tenderloin/actions/box/convert.rb
|
111
112
|
- lib/tenderloin/actions/box/destroy.rb
|
112
113
|
- lib/tenderloin/actions/box/download.rb
|
113
114
|
- lib/tenderloin/actions/box/unpackage.rb
|
@@ -132,6 +133,7 @@ files:
|
|
132
133
|
- lib/tenderloin/downloaders/http.rb
|
133
134
|
- lib/tenderloin/env.rb
|
134
135
|
- lib/tenderloin/fusion_vm.rb
|
136
|
+
- lib/tenderloin/ovftool.rb
|
135
137
|
- lib/tenderloin/ssh.rb
|
136
138
|
- lib/tenderloin/util.rb
|
137
139
|
- lib/tenderloin/vm.rb
|