tenderloin 0.4.2 → 0.4.3

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -5,7 +5,7 @@ Tenderloin is a tool for building and distributing virtualized development envir
5
5
  It is based on [Vagrant](http://vagrantup.com), specifically the 0.1.4 release. This was
6
6
  the simplest, and provided a good starting point
7
7
 
8
- It is designed to use VMWare Fusion as the underlying provider. You will need Fusion 5.
8
+ It is designed to use VMWare Fusion as the underlying provider. It has only been tested with Version 5. In theory this should be adaptable easily to VMWare workstation on other platforms, by updating the path to vmrun/the DHCP config.
9
9
 
10
10
  Features:
11
11
 
@@ -21,14 +21,35 @@ Features:
21
21
  To build your first virtual environment:
22
22
 
23
23
  loin init
24
- loin box add base http://s3.lstoll.net/<todo>.box
24
+ # Warning! I'm 2gb's and un-optimized
25
+ loin box add base http://s3.lstoll.net/tenderloin/precise64.box
25
26
  loin up
26
27
 
27
28
  The file describing your VM is called 'Tenderfile', but you can optionally change this with
28
- the -f flag, to allow multiple VM descriptions in the same place.
29
+ the -f flag, to allow multiple VM descriptions in the same place, e.g `loin up -f esxi.loin`
30
+
31
+ ## Using Vagrant Boxes.
32
+
33
+ You can reference vagrant boxes directly, and the importer will convert them to native VMWare. The imported VM won't have additions installed, so you won't be able to use shared folders.
34
+
35
+ ## Provisioning
36
+
37
+ Provisioning is either via a shell script, or by launching a command directly. Chef and Puppet provisioning isn't natively supported - if you wish to use these you will need to write your own launcher script.
38
+
39
+ You can also set up paths to rsync using the provisioner, these wil be synced with --delete before the proisioning script/command runs. This is useful for machines that don't have the additions installed, and avoids using shared folders
40
+
41
+ ## Tenderfile
42
+
43
+ You can [view the template](tenderloin/tree/master/templates/Tenderfile) to see all available options.
44
+
45
+ ## Project status
46
+
47
+ This project is currently still in a pretty raw state. It is a quick hack to see how it would work, and to directly achieve a goal. The tests are broken, and the code might still be rough. I am currently using it on a daily basis though, so it's definitely usable.
29
48
 
30
49
  ## Building base boxes
31
50
 
51
+ *Note:* [Veewee](https://github.com/jedi4ever/veewee) supports building bases boxes with VMWare. The VMDK from this can be used in a Tenderloin box. More automation around this coming soon!
52
+
32
53
  Currently base boxes are built manually. The process:
33
54
 
34
55
  * Create image in Fusion
@@ -61,5 +61,17 @@ module Tenderloin
61
61
  Tenderloin::Commands.ssh
62
62
  end
63
63
 
64
+ desc "ip [--file <tenderfile>]", "Shows the IP to access the VM"
65
+ def ip()
66
+ setup
67
+ Tenderloin::Commands.show_ip
68
+ end
69
+
70
+ desc "jsondump [--file <tenderfile>]", "Dumps a JSON representation of the VM"
71
+ def jsondump
72
+ setup
73
+ Tenderloin::Commands.json_dump
74
+ end
75
+
64
76
  end
65
77
  end
@@ -150,6 +150,26 @@ error
150
150
  Env.persisted_vm.execute!(Actions::VM::Provision)
151
151
  end
152
152
 
153
+ # Gets the IP
154
+ def show_ip
155
+ Env.load!
156
+ Env.require_persisted_vm
157
+ puts Env.persisted_vm.fusion_vm.ip
158
+ end
159
+
160
+ def json_dump
161
+ # Bump log level, don't want other output
162
+ Tenderloin::Logger.set_level Logger::ERROR
163
+ Env.load!
164
+ ret = {:config => Tenderloin.config.to_hash}
165
+ if Env.persisted_vm
166
+ ret[:vm] = Env.persisted_vm.fusion_vm.to_hash
167
+ else
168
+ ret[:vm] = {:running => false}
169
+ end
170
+ puts ret.to_json
171
+ end
172
+
153
173
  private
154
174
 
155
175
  def act_on_vm(&block)
@@ -60,6 +60,12 @@ module Tenderloin
60
60
  attr_accessor :max_tries
61
61
  attr_accessor :timeout
62
62
  attr_accessor :key
63
+ def keys=(keys)
64
+ @keys=keys
65
+ end
66
+ def keys
67
+ @keys || (key ? [key] : nil)
68
+ end
63
69
  attr_accessor :port
64
70
  end
65
71
 
@@ -99,7 +105,7 @@ module Tenderloin
99
105
  end
100
106
  end
101
107
 
102
- class ProvisioningConfig
108
+ class ProvisioningConfig < Base
103
109
  attr_accessor :script
104
110
  attr_accessor :command
105
111
  attr_accessor :rsync
@@ -108,7 +114,7 @@ module Tenderloin
108
114
  end
109
115
  end
110
116
 
111
- class SharedFoldersConfig
117
+ class SharedFoldersConfig < Base
112
118
  attr_accessor :enabled
113
119
  attr_accessor :folders
114
120
  end
@@ -139,6 +145,20 @@ module Tenderloin
139
145
  def loaded!
140
146
  @loaded = true
141
147
  end
148
+
149
+ def to_hash
150
+ hsh = Tenderloin.config.instance_variables_hash
151
+ hsh.delete(:tenderloin)
152
+ hsh = hsh.inject({}) do |h, (k, iv)|
153
+ if iv.class.to_s =~ /Tenderloin::Config/
154
+ h[k] = iv.instance_variables_hash
155
+ else
156
+ h[k] = iv
157
+ end
158
+ h
159
+ end
160
+ hsh
161
+ end
142
162
  end
143
163
  end
144
164
  end
@@ -9,7 +9,7 @@ module Tenderloin
9
9
  # For now we read the contents of one into a buffer
10
10
  # and copy it into the other. In the future, we should do
11
11
  # a system-level file copy (FileUtils.cp).
12
- open(source_url) do |f|
12
+ open(::File.expand_path(source_url)) do |f|
13
13
  loop do
14
14
  break if f.eof?
15
15
  destination_file.write(f.read(BUFFERSIZE))
@@ -18,4 +18,4 @@ module Tenderloin
18
18
  end
19
19
  end
20
20
  end
21
- end
21
+ end
@@ -7,16 +7,19 @@ module Tenderloin
7
7
  end
8
8
 
9
9
  def run(cmd, opts='')
10
+ runcmd = "#{VMRUN} #{cmd} #{@vmx} #{opts}"
10
11
  retrycount = 0
11
12
  while true
12
- res = `#{VMRUN} #{cmd} #{@vmx} #{opts}`
13
+ res = `#{runcmd}`
13
14
  if $? == 0
14
15
  return res
16
+ elsif res =~ /The virtual machine is not powered on/
17
+ return
15
18
  else
16
19
  if res =~ /VMware Tools are not running/
17
20
  sleep 1; next unless retrycount > 10
18
21
  end
19
- raise "Error running vmrun command #{cmd}: " + res
22
+ raise "Error running vmrun command:\n#{runcmd}\nResponse: " + res
20
23
  end
21
24
  end
22
25
  end
@@ -50,8 +53,10 @@ module Tenderloin
50
53
  end
51
54
 
52
55
  def ip
53
- ip = get_guest_var('ip').strip
54
- unless ip =~ /^(?:[0-9]{1,3}\.){3}[0-9]{1,3}$/
56
+ ip = get_guest_var('ip')
57
+ if ip && ip.strip =~ /^(?:[0-9]{1,3}\.){3}[0-9]{1,3}$/
58
+ ip = ip.strip
59
+ else
55
60
  mac_address = VMXFile.load(@vmx)["ethernet0.generatedAddress"]
56
61
  ip = dhcp_leases[mac_address]
57
62
  end
@@ -86,5 +91,9 @@ module Tenderloin
86
91
  end
87
92
  mac_ip
88
93
  end
94
+
95
+ def to_hash
96
+ {:ip => ip, :running => running?}
97
+ end
89
98
  end
90
99
  end
@@ -4,7 +4,7 @@ module Tenderloin
4
4
 
5
5
  class << self
6
6
  def connect(ip)
7
- if options.key
7
+ if options.keys
8
8
  Kernel.exec "#{cmd_ssh_opts} #{options.username}@#{ip}"
9
9
  else
10
10
  Kernel.exec cmd_ssh_opts(ip).strip
@@ -50,8 +50,9 @@ module Tenderloin
50
50
  end
51
51
 
52
52
  def cmd_ssh_opts(ip=nil)
53
- if options.key
54
- "ssh -i #{options.key} -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -p #{options.port}"
53
+ if options.keys
54
+ keyopts = options.keys.map {|k| "-i #{File.expand_path(k)}"}.join(' ')
55
+ "ssh #{keyopts} -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -p #{options.port}"
55
56
  else
56
57
  "#{SCRIPT} #{options.username} #{options.password} #{options.host || ip} #{options.port}".strip
57
58
  end
@@ -62,7 +63,7 @@ module Tenderloin
62
63
  opts[:port] = Tenderloin.config.ssh.port
63
64
  opts[:password] = Tenderloin.config.ssh.password
64
65
  opts[:timeout] = Tenderloin.config.ssh.timeout
65
- opts[:keys] = [Tenderloin.config[:ssh][:key]] if Tenderloin.config[:ssh][:key]
66
+ opts[:keys] = Tenderloin.config[:ssh][:keys] if Tenderloin.config[:ssh][:keys]
66
67
  opts
67
68
  end
68
69
  end
@@ -27,15 +27,23 @@ error
27
27
 
28
28
  class Logger < ::Logger
29
29
  @@singleton_logger = nil
30
+ @@level = Logger::INFO
30
31
 
31
32
  class << self
33
+ def set_level(level)
34
+ @@singleton_logger.level = level if @@singleton_logger
35
+ @@level = level
36
+ end
37
+
32
38
  def singleton_logger
33
39
  # TODO: Buffer messages until config is loaded, then output them?
34
- if Tenderloin.config.loaded?
35
- @@singleton_logger ||= Tenderloin::Logger.new(Tenderloin.config.tenderloin.log_output)
36
- else
37
- Tenderloin::Logger.new(nil)
38
- end
40
+ logger = if Tenderloin.config.loaded?
41
+ @@singleton_logger ||= Tenderloin::Logger.new(Tenderloin.config.tenderloin.log_output)
42
+ else
43
+ Tenderloin::Logger.new(nil)
44
+ end
45
+ logger.level = @@level
46
+ logger
39
47
  end
40
48
 
41
49
  def reset_logger!
@@ -48,4 +56,3 @@ error
48
56
  end
49
57
  end
50
58
  end
51
-
@@ -13,6 +13,8 @@ Tenderloin::Config.run do |config|
13
13
  # config.ssh.username = 'youruser'
14
14
  # config.ssh.password = 'yourpass'
15
15
  # config.ssh.key = '~/.ssh/id_rsa'
16
+ ## SSH key can also be an array of keys
17
+ # config.ssh.keys = ['~/.ssh/id_rsa', '~/.ssh/id_rsa_other']
16
18
 
17
19
  ## Provisioning can either provide a shell script, or a command to execute.
18
20
  ## You can also provide folders to rsync (over SSH)
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.2
4
+ version: 0.4.3
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors: