fission 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,4 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --colour
data/.rvmrc ADDED
@@ -0,0 +1 @@
1
+ rvm use 1.9.2@fission --create
@@ -0,0 +1,6 @@
1
+ # changes
2
+
3
+ ## head
4
+
5
+ ## 0.1.0 (05/17/2011)
6
+ Initial release
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in fission.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License
2
+
3
+ Copyright (c) 2011 Thomas Bishop, bishop.thomas@gmail.com
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
@@ -0,0 +1,51 @@
1
+ # Fission
2
+
3
+ ## Intro
4
+ Fission is a simple command line tool for cloning of VMware Fusion VMs.
5
+
6
+
7
+ ## Config
8
+ By default, fission will use the default VMware Fusion VM directory
9
+ (~/Documents/Virtual Machines.localized/) when cloning. If you want to use a
10
+ different directory, you can set this in a config file.
11
+
12
+ The config file needs to be in yaml format and live at '~/.fissionrc'
13
+
14
+ $cat ~/.fissionrc
15
+ ---
16
+ vm_dir: "/vm"
17
+
18
+
19
+ ## Install
20
+ gem install fission
21
+
22
+
23
+ ## Usage
24
+ ### Clone
25
+ fission clone existing_vm new_vm
26
+
27
+ ### Help
28
+ fission -h
29
+
30
+ or just
31
+
32
+ fission
33
+
34
+
35
+ ## Other Notable Info
36
+ As of now, VMware Fusion doesn't provide an easy, out of
37
+ the box, way to modify the personality (hostname, ip, etc.) of a VM. Because of
38
+ this, a clone created by fission is an _exact_ copy of the original (including
39
+ hostname, ip address, etc.). Most likely, this isn't what you want.
40
+
41
+ One approach is to create a VM which will act as a template. Create the VM with
42
+ the desired install method (ideally with easy install) and settings, but do not
43
+ power on the VM. You can create clones from this VM and when you power it on,
44
+ it will start the OS install process (and assign a new ip, etc.)
45
+
46
+
47
+ ## Contribute
48
+ * Fork the project
49
+ * Make your feature addition or bug fix (with tests) in a topic branch
50
+ * Bonus points for not mucking with the gemspec or version
51
+ * Send a pull request and I'll get it integrated
@@ -0,0 +1,11 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
3
+
4
+ require 'rspec/core/rake_task'
5
+
6
+ task :default => [:spec]
7
+
8
+ desc 'Run specs'
9
+ RSpec::Core::RakeTask.new do |t|
10
+ t.rspec_opts = %w(-fs --color)
11
+ end
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $:.unshift File.join(File.dirname(__FILE__), *%w[.. lib])
4
+
5
+ require 'fission'
6
+
7
+ Fission::CLI.execute
@@ -0,0 +1,23 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "fission/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "fission"
7
+ s.version = Fission::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ['Tommy Bishop']
10
+ s.email = ['bishop.thomas@gmail.com']
11
+ s.homepage = "https://github.com/thbishop/fission"
12
+ s.summary = %q{Tool to clone VMware fusion VMs}
13
+ s.description = %q{A simple utility to create VMware Fusion VM clones}
14
+
15
+ s.rubyforge_project = "fission"
16
+
17
+ s.files = `git ls-files`.split("\n")
18
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
19
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
20
+ s.require_paths = ["lib"]
21
+ s.add_development_dependency 'rspec', '~> 2.6.0'
22
+ s.add_development_dependency 'fakefs', '~> 0.3.2'
23
+ end
@@ -0,0 +1,28 @@
1
+ require 'fileutils'
2
+ require 'optparse'
3
+ require 'ostruct'
4
+ require 'yaml'
5
+
6
+ $:.unshift File.join(File.dirname(__FILE__), *%w[.. lib])
7
+
8
+ require 'fission/cli'
9
+ require 'fission/command'
10
+ require 'fission/command/clone'
11
+ require 'fission/config'
12
+ require 'fission/core_ext/class'
13
+ require 'fission/core_ext/object'
14
+ require 'fission/ui'
15
+ require 'fission/vm'
16
+ require 'fission/version'
17
+
18
+ module Fission
19
+ extend self
20
+
21
+ def config
22
+ @config ||= Fission::Config.new
23
+ end
24
+
25
+ def ui
26
+ @ui ||= Fission::UI.new
27
+ end
28
+ end
@@ -0,0 +1,59 @@
1
+ module Fission
2
+ class CLI
3
+ def self.execute(args=ARGV)
4
+ optparse = OptionParser.new do |opts|
5
+ opts.banner = "\nUsage: fission [options] COMMAND [arguments]"
6
+
7
+ opts.on_head('-v', '--version', 'Output the version of fission') do
8
+ Fission.ui.output Fission::VERSION
9
+ exit(0)
10
+ end
11
+
12
+ opts.on_head('-h', '--help', 'Displays this message') do
13
+ show_all_help(optparse)
14
+ exit(0)
15
+ end
16
+
17
+ opts.define_tail do
18
+ commands_banner
19
+ end
20
+
21
+ end
22
+
23
+ begin
24
+ optparse.order! args
25
+ rescue OptionParser::InvalidOption => e
26
+ Fission.ui.output e
27
+ show_all_help(optparse)
28
+ exit(1)
29
+ end
30
+
31
+ case args.first
32
+ when 'clone'
33
+ @command = Fission::Command::Clone.new args.drop 1
34
+ @command.execute
35
+ else
36
+ show_all_help(optparse)
37
+ exit(0)
38
+ end
39
+
40
+ end
41
+
42
+ private
43
+ def self.commands_banner
44
+ text = "\nCommands:\n"
45
+ Fission::Command.descendants.each do |command_klass|
46
+ text << (command_klass.send :help)
47
+ text << "\n\n"
48
+ end
49
+
50
+ text
51
+ end
52
+
53
+ def self.show_all_help(options)
54
+ Fission.ui.output options
55
+ Fission.ui.output commands_banner
56
+ end
57
+
58
+ end
59
+ end
@@ -0,0 +1,15 @@
1
+ module Fission
2
+ class Command
3
+ attr_reader :options, :args
4
+
5
+ def initialize(args=[])
6
+ @options = OpenStruct.new
7
+ @args = args
8
+ end
9
+
10
+ def self.help
11
+ self.new.option_parser.to_s
12
+ end
13
+
14
+ end
15
+ end
@@ -0,0 +1,57 @@
1
+ module Fission
2
+ class Command
3
+ class Clone < Command
4
+
5
+ def initialize(args=[])
6
+ super
7
+ @options.start = false
8
+ end
9
+
10
+ def execute
11
+ unless args.count > 1
12
+ Fission.ui.output self.class.help
13
+ Fission.ui.output ""
14
+ Fission.ui.output_and_exit "Incorrect arguments for clone command", 1
15
+ end
16
+
17
+ source_vm = @args.first
18
+ target_vm = @args[1]
19
+
20
+ unless Fission::VM.exists? source_vm
21
+ Fission.ui.output_and_exit "Unable to find the source vm #{source_vm} (#{Fission::VM.path(source_vm)})", 1
22
+ end
23
+
24
+ if Fission::VM.exists? target_vm
25
+ Fission::ui.output_and_exit "The target vm #{target_vm} already exists", 1
26
+ end
27
+
28
+ clone_options = option_parser
29
+ clone_options.parse! @args
30
+
31
+ Fission::VM.clone source_vm, target_vm
32
+
33
+ Fission.ui.output ''
34
+ Fission.ui.output 'Clone complete!'
35
+
36
+ if @options.start
37
+ Fission.ui.output "Starting '#{target_vm}'"
38
+ @vm = Fission::VM.new target_vm
39
+ @vm.start
40
+ end
41
+ end
42
+
43
+ def option_parser
44
+ optparse = OptionParser.new do |opts|
45
+ opts.banner = "\nclone usage: fission clone source_vm target_vm [options]"
46
+
47
+ opts.on '--start', 'Start the VM after cloning' do
48
+ @options.start = true
49
+ end
50
+ end
51
+
52
+ optparse
53
+ end
54
+
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,26 @@
1
+ module Fission
2
+ class Config
3
+ attr_accessor :attributes
4
+
5
+ CONF_FILE = File.expand_path '~/.fissionrc'
6
+
7
+ def initialize
8
+ @attributes = {}
9
+ load_from_file
10
+
11
+ if @attributes['vm_dir'].blank?
12
+ @attributes['vm_dir'] = File.expand_path('~/Documents/Virtual Machines.localized/')
13
+ end
14
+
15
+ @attributes['vmrun_bin'] = '/Library/Application Support/VMware Fusion/vmrun'
16
+ end
17
+
18
+ private
19
+ def load_from_file
20
+ if File.file?(CONF_FILE)
21
+ @attributes.merge!(YAML.load_file(CONF_FILE))
22
+ end
23
+ end
24
+
25
+ end
26
+ end
@@ -0,0 +1,5 @@
1
+ class Class
2
+ def descendants
3
+ ObjectSpace.each_object(Class).select { |klass| klass < self }
4
+ end
5
+ end
@@ -0,0 +1,112 @@
1
+ # this is from active_support
2
+ # github.com/rails/rails/activesupport
3
+ #
4
+ class Object
5
+ # An object is blank if it's false, empty, or a whitespace string.
6
+ # For example, "", " ", +nil+, [], and {} are blank.
7
+ #
8
+ # This simplifies:
9
+ #
10
+ # if !address.nil? && !address.empty?
11
+ #
12
+ # ...to:
13
+ #
14
+ # if !address.blank?
15
+ def blank?
16
+ respond_to?(:empty?) ? empty? : !self
17
+ end
18
+
19
+ # An object is present if it's not <tt>blank?</tt>.
20
+ def present?
21
+ !blank?
22
+ end
23
+
24
+ # Returns object if it's <tt>present?</tt> otherwise returns +nil+.
25
+ # <tt>object.presence</tt> is equivalent to <tt>object.present? ? object : nil</tt>.
26
+ #
27
+ # This is handy for any representation of objects where blank is the same
28
+ # as not present at all. For example, this simplifies a common check for
29
+ # HTTP POST/query parameters:
30
+ #
31
+ # state = params[:state] if params[:state].present?
32
+ # country = params[:country] if params[:country].present?
33
+ # region = state || country || 'US'
34
+ #
35
+ # ...becomes:
36
+ #
37
+ # region = params[:state].presence || params[:country].presence || 'US'
38
+ def presence
39
+ self if present?
40
+ end
41
+ end
42
+
43
+ class NilClass
44
+ # +nil+ is blank:
45
+ #
46
+ # nil.blank? # => true
47
+ #
48
+ def blank?
49
+ true
50
+ end
51
+ end
52
+
53
+ class FalseClass
54
+ # +false+ is blank:
55
+ #
56
+ # false.blank? # => true
57
+ #
58
+ def blank?
59
+ true
60
+ end
61
+ end
62
+
63
+ class TrueClass
64
+ # +true+ is not blank:
65
+ #
66
+ # true.blank? # => false
67
+ #
68
+ def blank?
69
+ false
70
+ end
71
+ end
72
+
73
+ class Array
74
+ # An array is blank if it's empty:
75
+ #
76
+ # [].blank? # => true
77
+ # [1,2,3].blank? # => false
78
+ #
79
+ alias_method :blank?, :empty?
80
+ end
81
+
82
+ class Hash
83
+ # A hash is blank if it's empty:
84
+ #
85
+ # {}.blank? # => true
86
+ # {:key => 'value'}.blank? # => false
87
+ #
88
+ alias_method :blank?, :empty?
89
+ end
90
+
91
+ class String
92
+ # A string is blank if it's empty or contains whitespaces only:
93
+ #
94
+ # "".blank? # => true
95
+ # " ".blank? # => true
96
+ # " something here ".blank? # => false
97
+ #
98
+ def blank?
99
+ self !~ /\S/
100
+ end
101
+ end
102
+
103
+ class Numeric #:nodoc:
104
+ # No number is blank:
105
+ #
106
+ # 1.blank? # => false
107
+ # 0.blank? # => false
108
+ #
109
+ def blank?
110
+ false
111
+ end
112
+ end
@@ -0,0 +1,18 @@
1
+ module Fission
2
+ class UI
3
+ attr_reader :stdout
4
+
5
+ def initialize(stdout=$stdout)
6
+ @stdout = stdout
7
+ end
8
+
9
+ def output(s)
10
+ @stdout.puts s
11
+ end
12
+
13
+ def output_and_exit(s, exit_code)
14
+ output s
15
+ exit exit_code
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,3 @@
1
+ module Fission
2
+ VERSION = "0.1.0"
3
+ end
@@ -0,0 +1,62 @@
1
+ module Fission
2
+ class VM
3
+ attr_reader :name
4
+
5
+ def initialize(name)
6
+ @name = name
7
+ end
8
+
9
+ def start
10
+ command = "#{Fission.config.attributes['vmrun_bin'].gsub(' ', '\ ' )} -T fusion start #{conf_file.gsub ' ', '\ '} gui 2>&1"
11
+ output = `#{command}`
12
+
13
+ if $?.exitstatus == 0
14
+ Fission.ui.output "VM started"
15
+ else
16
+ Fission.ui.output "There was a problem starting the VM. The error was:\n#{output}"
17
+ end
18
+ end
19
+
20
+ def conf_file
21
+ File.join self.class.path(@name), "#{@name}.vmx"
22
+ end
23
+
24
+ def self.exists?(vm_name)
25
+ File.directory? path(vm_name)
26
+ end
27
+
28
+ def self.path(vm_name)
29
+ File.join Fission.config.attributes['vm_dir'], "#{vm_name}.vmwarevm"
30
+ end
31
+
32
+ def self.clone(source_vm, target_vm)
33
+ Fission.ui.output "Cloning #{source_vm} to #{target_vm}"
34
+ FileUtils.cp_r path(source_vm), path(target_vm)
35
+
36
+ Fission.ui.output "Configuring #{target_vm}"
37
+ rename_vm_files source_vm, target_vm
38
+ update_config source_vm, target_vm
39
+ end
40
+
41
+ private
42
+ def self.rename_vm_files(from, to)
43
+ files_to_rename(from, to).each do |file|
44
+ FileUtils.mv File.join(path(to), file), File.join(path(to), file.gsub(from, to))
45
+ end
46
+ end
47
+
48
+ def self.files_to_rename(from, to)
49
+ Dir.entries(path(to)).select { |f| f.include?(from) }
50
+ end
51
+
52
+ def self.update_config(from, to)
53
+ ['.vmdk', '.vmx', '.vmxf'].each do |ext|
54
+ file = File.join path(to), "#{to}#{ext}"
55
+ text = File.read file
56
+ text.gsub! from, to
57
+ File.open(file, 'w'){ |f| f.print text }
58
+ end
59
+ end
60
+
61
+ end
62
+ end
@@ -0,0 +1,63 @@
1
+ require File.expand_path('../../spec_helper.rb', __FILE__)
2
+
3
+ describe Fission::CLI do
4
+ before :each do
5
+ @string_io = StringIO.new
6
+ Fission.stub!(:ui).and_return(Fission::UI.new(@string_io))
7
+ end
8
+
9
+ describe 'execute' do
10
+
11
+ describe 'with no arguments' do
12
+ it 'should output the usage info' do
13
+ lambda {
14
+ Fission::CLI.execute []
15
+ }.should raise_error SystemExit
16
+
17
+ @string_io.string.should match /Usage/
18
+ end
19
+ end
20
+
21
+ describe '-v or --version' do
22
+ ['-v', '--version'].each do |arg|
23
+ it "should output the version with #{arg}" do
24
+ lambda {
25
+ Fission::CLI.execute [arg]
26
+ }.should raise_error SystemExit
27
+
28
+ @string_io.string.should match /#{Fission::VERSION}/
29
+
30
+ end
31
+ end
32
+
33
+ end
34
+
35
+ describe '-h or --help' do
36
+ ['-h', '--help'].each do |arg|
37
+ it "should output the usage info with #{arg}" do
38
+ lambda {
39
+ Fission::CLI.execute [arg]
40
+ }.should raise_error SystemExit
41
+
42
+ @string_io.string.should match /Usage/
43
+ end
44
+ end
45
+
46
+ end
47
+
48
+ describe 'clone' do
49
+ before :each do
50
+ @clone_mock = mock('clone_mock')
51
+ Fission::Command::Clone.stub!(:help).and_return('')
52
+ end
53
+
54
+ it "should try to clone the vm" do
55
+ @clone_mock.should_receive(:execute)
56
+ Fission::Command::Clone.should_receive(:new).with(['foo', 'bar']).and_return(@clone_mock)
57
+
58
+ Fission::CLI.execute ['clone', 'foo', 'bar']
59
+ end
60
+ end
61
+
62
+ end
63
+ end
@@ -0,0 +1,90 @@
1
+ require File.expand_path('../../../spec_helper.rb', __FILE__)
2
+
3
+ describe Fission::Command::Clone do
4
+ before :all do
5
+ @vm_info = ['foo', 'bar']
6
+ end
7
+
8
+ before :each do
9
+ @string_io = StringIO.new
10
+ Fission.stub!(:ui).and_return(Fission::UI.new(@string_io))
11
+ end
12
+
13
+ describe 'execute' do
14
+ [ [], ['foo'] ].each do |args|
15
+ it "should output an error and the help when #{args.count} arguments are passed in" do
16
+ Fission::Command::Clone.should_receive(:help)
17
+
18
+ lambda {
19
+ command = Fission::Command::Clone.new args
20
+ command.execute
21
+ }.should raise_error SystemExit
22
+
23
+ @string_io.string.should match /Incorrect arguments for clone command/
24
+ end
25
+ end
26
+
27
+ it "should output an error and exit if it can't find the source vm" do
28
+ Fission::VM.should_receive(:exists?).with(@vm_info.first).and_return(false)
29
+ Fission::VM.should_not_receive(:exists?).with(@vm_info[1])
30
+
31
+ lambda {
32
+ command = Fission::Command::Clone.new @vm_info
33
+ command.execute
34
+ }.should raise_error SystemExit
35
+
36
+ @string_io.string.should match /Unable to find the source vm #{@vm_info.first}/
37
+ end
38
+
39
+
40
+ it "should output an error and exit if the target vm already exists" do
41
+ @vm_info.each do |vm|
42
+ Fission::VM.should_receive(:exists?).with(vm).and_return(true)
43
+ end
44
+
45
+ lambda {
46
+ command = Fission::Command::Clone.new @vm_info
47
+ command.execute
48
+ }.should raise_error SystemExit
49
+
50
+ @string_io.string.should match /The target vm #{@vm_info[1]} already exists/
51
+ end
52
+
53
+ it 'should try to clone the vm if the source vm exists and the target vm does not' do
54
+ Fission::VM.should_receive(:exists?).with(@vm_info.first).and_return(true)
55
+ Fission::VM.should_receive(:exists?).with(@vm_info[1]).and_return(false)
56
+ Fission::VM.should_receive(:clone).with(@vm_info.first, @vm_info[1])
57
+ command = Fission::Command::Clone.new @vm_info
58
+ command.execute
59
+
60
+ @string_io.string.should match /Clone complete/
61
+ end
62
+
63
+ describe 'with --start' do
64
+ it 'should try to clone the vm and start it' do
65
+ @vm_mock = mock('vm_mock')
66
+ Fission::VM.should_receive(:exists?).with(@vm_info.first).and_return(true)
67
+ Fission::VM.should_receive(:exists?).with(@vm_info[1]).and_return(false)
68
+ Fission::VM.should_receive(:clone).with(@vm_info.first, @vm_info[1])
69
+
70
+ @vm_mock.should_receive(:start)
71
+ Fission::VM.should_receive(:new).with(@vm_info[1]).and_return(@vm_mock)
72
+
73
+ command = Fission::Command::Clone.new @vm_info << '--start'
74
+ command.execute
75
+
76
+ @string_io.string.should match /Clone complete/
77
+ @string_io.string.should match /Starting '#{@vm_info[1]}'/
78
+ end
79
+ end
80
+
81
+ end
82
+
83
+ describe 'help' do
84
+ it 'should output info for this command' do
85
+ output = Fission::Command::Clone.help
86
+
87
+ output.should match /clone source_vm target_vm/
88
+ end
89
+ end
90
+ end
@@ -0,0 +1,26 @@
1
+ require File.expand_path('../../spec_helper.rb', __FILE__)
2
+
3
+ describe Fission::Command do
4
+
5
+ describe 'new' do
6
+ it 'should set options variable as an open struct' do
7
+ @command = Fission::Command.new
8
+ @command.options.should be_kind_of OpenStruct
9
+ end
10
+
11
+ it 'should set the args variable' do
12
+ @command = Fission::Command.new ['foo', 'bar']
13
+ @command.args.should == ['foo', 'bar']
14
+ end
15
+ end
16
+
17
+ describe 'help' do
18
+ it 'should call option_parser on a new instance' do
19
+ @new_instance_mock = mock('new_instance')
20
+ @new_instance_mock.should_receive(:option_parser).and_return('foo')
21
+ Fission::Command.should_receive(:new).and_return(@new_instance_mock)
22
+ Fission::Command.help.should == 'foo'
23
+ end
24
+ end
25
+
26
+ end
@@ -0,0 +1,30 @@
1
+ require File.expand_path('../../spec_helper.rb', __FILE__)
2
+
3
+ describe Fission::Config do
4
+ describe "init" do
5
+ it "should use the fusion default dir for vm_dir" do
6
+ FakeFS do
7
+ @config = Fission::Config.new
8
+ @config.attributes['vm_dir'].should == File.expand_path('~/Documents/Virtual Machines.localized/')
9
+ end
10
+ end
11
+
12
+ it 'should use the fusion default for vmrun_bin' do
13
+ FakeFS do
14
+ @config = Fission::Config.new
15
+ @config.attributes['vmrun_bin'].should == '/Library/Application Support/VMware Fusion/vmrun'
16
+ end
17
+ end
18
+
19
+ it "should use the user specified dir in ~/.fissionrc" do
20
+ FakeFS do
21
+ File.open('~/.fissionrc', 'w') { |f| f.puts YAML.dump({ 'vm_dir' => '/var/tmp/foo' })}
22
+
23
+ @config = Fission::Config.new
24
+ @config.attributes['vm_dir'].should == '/var/tmp/foo'
25
+ end
26
+ end
27
+
28
+ end
29
+
30
+ end
@@ -0,0 +1,26 @@
1
+ require File.expand_path('../../spec_helper.rb', __FILE__)
2
+
3
+ describe Fission::UI do
4
+ describe 'output' do
5
+ it 'should show the desired text' do
6
+ output = capturing_output do
7
+ Fission::UI.new.output "foo bar\nbaz blah"
8
+ end
9
+
10
+ output.should == "foo bar\nbaz blah\n"
11
+ end
12
+ end
13
+
14
+ describe 'output_and_exit' do
15
+ it 'should show the desired text and exit with the desired exit code' do
16
+ Fission::UI.any_instance.should_receive(:exit).and_return(1)
17
+
18
+ output = capturing_output do
19
+ Fission::UI.new.output_and_exit "foo bar\nbaz blah", 1
20
+ end
21
+
22
+ output.should == "foo bar\nbaz blah\n"
23
+ end
24
+
25
+ end
26
+ end
@@ -0,0 +1,107 @@
1
+ require File.expand_path('../../spec_helper.rb', __FILE__)
2
+
3
+ describe Fission::VM do
4
+ before :each do
5
+ @string_io = StringIO.new
6
+ end
7
+
8
+ describe 'new' do
9
+ it 'should set the vm name' do
10
+ Fission::VM.new('foo').name.should == 'foo'
11
+ end
12
+ end
13
+
14
+ describe 'start' do
15
+ it 'should output that it was successful' do
16
+ Fission.stub!(:ui).and_return(Fission::UI.new(@string_io))
17
+ @vm = Fission::VM.new('foo')
18
+ @vm.should_receive(:`).with("#{Fission.config.attributes['vmrun_bin'].gsub ' ', '\ '} -T fusion start #{(File.join(Fission::VM.path('foo'), 'foo.vmx')).gsub ' ', '\ '} gui 2>&1").and_return("it's all good")
19
+ @vm.start
20
+
21
+ @string_io.string.should match /VM started/
22
+ end
23
+
24
+ it 'it should output that it was unsuccessful' do
25
+ $?.should_receive(:exitstatus).and_return(1)
26
+ Fission.stub!(:ui).and_return(Fission::UI.new(@string_io))
27
+ @vm = Fission::VM.new('foo')
28
+ @vm.should_receive(:`).with("#{Fission.config.attributes['vmrun_bin'].gsub ' ', '\ '} -T fusion start #{(File.join(Fission::VM.path('foo'), 'foo.vmx')).gsub ' ', '\ '} gui 2>&1").and_return("it blew up")
29
+ @vm.start
30
+
31
+ @string_io.string.should match /There was a problem starting the VM.+it blew up.+/m
32
+ end
33
+ end
34
+
35
+ describe 'conf_file' do
36
+ it 'should return the path to the conf file' do
37
+ Fission::VM.new('foo').conf_file.should == File.join(Fission.config.attributes['vm_dir'], 'foo.vmwarevm', 'foo.vmx')
38
+ end
39
+ end
40
+
41
+ describe "self.path" do
42
+ it "should return the path of the vm" do
43
+ vm_path = File.join(Fission.config.attributes['vm_dir'], 'foo.vmwarevm').gsub '\\', ''
44
+ Fission::VM.path('foo').should == vm_path
45
+ end
46
+ end
47
+
48
+ describe "self.exists?" do
49
+ it "should return true if the vm exists" do
50
+ FakeFS do
51
+ FileUtils.mkdir_p(Fission::VM.path('foo'))
52
+ Fission::VM.exists?('foo').should == true
53
+ end
54
+ end
55
+
56
+ it 'should return false if the vm does not exist' do
57
+ FakeFS do
58
+ FileUtils.rm_r(Fission::VM.path('foo'))
59
+ Fission::VM.exists?('foo').should == false
60
+ end
61
+ end
62
+ end
63
+
64
+
65
+ describe "self.clone" do
66
+ before :each do
67
+ Fission.stub!(:ui).and_return(Fission::UI.new(@string_io))
68
+ end
69
+
70
+ it 'should clone the vm to the target' do
71
+ source_vm = 'foo'
72
+ target_vm = 'bar'
73
+ vm_files = [ '.vmx',
74
+ '.vmxf',
75
+ '.vmdk',
76
+ '-s001.vmdk',
77
+ '-s002.vmdk',
78
+ '.vmsd' ]
79
+
80
+ FakeFS do
81
+ FileUtils.mkdir_p Fission::VM.path('foo')
82
+
83
+ vm_files.each do |file|
84
+ FileUtils.touch File.join(Fission::VM.path('foo'), "#{source_vm}#{file}")
85
+ end
86
+
87
+ File.open(File.join(Fission::VM.path('foo'), 'foo.vmx'), 'w') { |f| f.write 'foo.vmdk'}
88
+
89
+ Fission::VM.clone source_vm, target_vm
90
+
91
+ File.directory?(Fission::VM.path('bar')).should == true
92
+
93
+ vm_files.each do |file|
94
+ File.file?(File.join(Fission::VM.path('bar'), "#{target_vm}#{file}")).should == true
95
+ end
96
+
97
+ conf_file = File.read File.join(Fission::VM.path('bar'), 'bar.vmx')
98
+ conf_file.should == 'bar.vmdk'
99
+ end
100
+
101
+ @string_io.string.should match /Cloning #{source_vm} to #{target_vm}/
102
+ @string_io.string.should match /Configuring #{target_vm}/
103
+ end
104
+
105
+ end
106
+
107
+ end
@@ -0,0 +1,15 @@
1
+ require 'spec_helper'
2
+
3
+ describe Fission do
4
+ describe "config" do
5
+ it "should load a config object" do
6
+ Fission.config.should be_a Fission::Config
7
+ end
8
+ end
9
+
10
+ describe "ui" do
11
+ it "should load a ui object" do
12
+ Fission.ui.should be_a Fission::UI
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,20 @@
1
+ require 'rspec'
2
+ require 'fission'
3
+ require 'fakefs/safe'
4
+
5
+ # Helper to capture our stdout
6
+ # Example
7
+ # output = capturing_output do
8
+ # lambda {
9
+ # Erector.new(["--version"])
10
+ # }.should raise_error(SystemExit)
11
+ # end
12
+ # output.should == Erector::VERSION + "\n"
13
+ def capturing_output
14
+ output = StringIO.new
15
+ $stdout = output
16
+ yield
17
+ output.string
18
+ ensure
19
+ $stdout = STDOUT
20
+ end
metadata ADDED
@@ -0,0 +1,110 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: fission
3
+ version: !ruby/object:Gem::Version
4
+ prerelease:
5
+ version: 0.1.0
6
+ platform: ruby
7
+ authors:
8
+ - Tommy Bishop
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+
13
+ date: 2011-05-18 00:00:00 Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: rspec
17
+ prerelease: false
18
+ requirement: &id001 !ruby/object:Gem::Requirement
19
+ none: false
20
+ requirements:
21
+ - - ~>
22
+ - !ruby/object:Gem::Version
23
+ version: 2.6.0
24
+ type: :development
25
+ version_requirements: *id001
26
+ - !ruby/object:Gem::Dependency
27
+ name: fakefs
28
+ prerelease: false
29
+ requirement: &id002 !ruby/object:Gem::Requirement
30
+ none: false
31
+ requirements:
32
+ - - ~>
33
+ - !ruby/object:Gem::Version
34
+ version: 0.3.2
35
+ type: :development
36
+ version_requirements: *id002
37
+ description: A simple utility to create VMware Fusion VM clones
38
+ email:
39
+ - bishop.thomas@gmail.com
40
+ executables:
41
+ - fission
42
+ extensions: []
43
+
44
+ extra_rdoc_files: []
45
+
46
+ files:
47
+ - .gitignore
48
+ - .rspec
49
+ - .rvmrc
50
+ - CHANGELOG.md
51
+ - Gemfile
52
+ - LICENSE
53
+ - README.md
54
+ - Rakefile
55
+ - bin/fission
56
+ - fission.gemspec
57
+ - lib/fission.rb
58
+ - lib/fission/cli.rb
59
+ - lib/fission/command.rb
60
+ - lib/fission/command/clone.rb
61
+ - lib/fission/config.rb
62
+ - lib/fission/core_ext/class.rb
63
+ - lib/fission/core_ext/object.rb
64
+ - lib/fission/ui.rb
65
+ - lib/fission/version.rb
66
+ - lib/fission/vm.rb
67
+ - spec/fission/cli_spec.rb
68
+ - spec/fission/command/clone_spec.rb
69
+ - spec/fission/command_spec.rb
70
+ - spec/fission/config_spec.rb
71
+ - spec/fission/ui_spec.rb
72
+ - spec/fission/vm_spec.rb
73
+ - spec/fission_spec.rb
74
+ - spec/spec_helper.rb
75
+ homepage: https://github.com/thbishop/fission
76
+ licenses: []
77
+
78
+ post_install_message:
79
+ rdoc_options: []
80
+
81
+ require_paths:
82
+ - lib
83
+ required_ruby_version: !ruby/object:Gem::Requirement
84
+ none: false
85
+ requirements:
86
+ - - ">="
87
+ - !ruby/object:Gem::Version
88
+ version: "0"
89
+ required_rubygems_version: !ruby/object:Gem::Requirement
90
+ none: false
91
+ requirements:
92
+ - - ">="
93
+ - !ruby/object:Gem::Version
94
+ version: "0"
95
+ requirements: []
96
+
97
+ rubyforge_project: fission
98
+ rubygems_version: 1.8.2
99
+ signing_key:
100
+ specification_version: 3
101
+ summary: Tool to clone VMware fusion VMs
102
+ test_files:
103
+ - spec/fission/cli_spec.rb
104
+ - spec/fission/command/clone_spec.rb
105
+ - spec/fission/command_spec.rb
106
+ - spec/fission/config_spec.rb
107
+ - spec/fission/ui_spec.rb
108
+ - spec/fission/vm_spec.rb
109
+ - spec/fission_spec.rb
110
+ - spec/spec_helper.rb