├── .gitignore ├── .rspec ├── Gemfile ├── LICENSE ├── README.md ├── Rakefile ├── lib ├── vagrant-list.rb └── vagrant-list │ ├── command.rb │ ├── command_error.rb │ ├── plugin.rb │ ├── version.rb │ ├── virtual_box │ └── list.rb │ └── vm_info.rb ├── spec ├── spec_helper.rb └── vagrant-list │ ├── virtual_box │ └── list_spec.rb │ └── vm_info_spec.rb └── vagrant-list.gemspec /.gitignore: -------------------------------------------------------------------------------- 1 | *.gem 2 | *.rbc 3 | .bundle 4 | .config 5 | .yardoc 6 | Gemfile.lock 7 | InstalledFiles 8 | _yardoc 9 | coverage 10 | doc/ 11 | lib/bundler/man 12 | pkg 13 | rdoc 14 | spec/reports 15 | test/tmp 16 | test/version_tmp 17 | tmp 18 | .DS_Store 19 | .rvmrc 20 | -------------------------------------------------------------------------------- /.rspec: -------------------------------------------------------------------------------- 1 | --color 2 | --format progress 3 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | # Specify your gem's dependencies in vagrant-list.gemspec 4 | gemspec 5 | 6 | # Required for running rake spec 7 | group :development, :test do 8 | gem 'vagrant', :git => 'https://github.com/mitchellh/vagrant.git' 9 | end 10 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2012 Josh McArthur 2 | 3 | MIT License 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining 6 | a copy of this software and associated documentation files (the 7 | "Software"), to deal in the Software without restriction, including 8 | without limitation the rights to use, copy, modify, merge, publish, 9 | distribute, sublicense, and/or sell copies of the Software, and to 10 | permit persons to whom the Software is furnished to do so, subject to 11 | the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be 14 | included in all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 20 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 21 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 22 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | vagrant-list 2 | ===== 3 | 4 | ### What does it do? 5 | 6 | `vagrant-list` adds a command to the Vagrant CLI to list both all VMs known to VirtualBox, as well as any that are running. It's handy for seeing what all your VMs are up to. 7 | 8 | 9 | ### How do I install it using `vagrant`? 10 | 11 | If you are using the packaged version of `vagrant` from [the Vagrant homepage](http://downloads.vagrantup.com/) then you simply install this gem as a plugin by entering the following command in your terminal: 12 | 13 | ``` bash 14 | vagrant plugin install vagrant-list 15 | ``` 16 | 17 | 18 | ### How do I install it using Rubygems? 19 | 20 | If you have vagrant installed from Rubygems, then you need to do a little more work - first, you can install the gem from [Rubygems](https://rubygems.org): 21 | 22 | ``` bash 23 | gem install vagrant-list 24 | ``` 25 | 26 | Next, you need to tell Vagrant about this plugin, by adding to your project's `Vagrantfile`: 27 | 28 | ``` ruby 29 | Vagrant.require_plugin "vagrant-list" 30 | ``` 31 | 32 | **If you are still using a gem version though, it's worth considering the package upgrade, as that seems to be the preferred way for end-users to install Vagrant nowadays and will probably be better supported than a gem install.** 33 | 34 | ##### Vagrant < 1.1.x 35 | 36 | If you are using a version of Vagrant older than 1.1.x, then you need to install an older version of this gem from Rubygems - only 0.0.5 and below will work with Vagrant 1.0.x: 37 | 38 | `gem install vagrant-list --version "0.0.5"` 39 | 40 | Please note that versions older than 0.0.5 **will not** work with Vagrant 1.1.x and above. 41 | 42 | ### How do I use it? 43 | 44 | #### From the CLI 45 | `vagrant-list` adds just one command to vagrant - `list`. 46 | For example, this following command will list the VMs: 47 | 48 | `vagrant list` will output: 49 | 50 | ``` sh 51 | [vagrant] ALL: 52 | [vagrant] 35279736-412a-47b0-aa09-b1aef373a9c7: IE7 (Windows Vista) 53 | [vagrant] ebb807dd-64d6-4a17-87f8-1d6d80a3f467: IE8 (Windows 7) 54 | [vagrant] 4db11a4d-0a97-48c4-8b23-9cb2ca4fcb93: IE9 (Windows 7) 55 | [vagrant] 508bf5cd-dcce-48f6-b19d-287fba4306d6: Windows XP (Windows XP) 56 | [vagrant] 729322cf-e11d-438c-b9dc-6b1d31e9a56d: Python Development (Windows XP) 57 | [vagrant] RUNNING: 58 | [vagrant] ebb807dd-64d6-4a17-87f8-1d6d80a3f467: IE8 (Windows 7) 59 | ``` 60 | 61 | #### On Windows 62 | 63 | The Windows installer for VirtualBox may not have added VirtualBox to the `PATH`. 64 | 65 | On a typical Windows install, the installation directory is `C:\Program Files\Oracle\VirtualBox`. 66 | 67 | Add this installation directory to your `PATH` from [`%windir%\System32\rundll32.exe sysdm.cpl,EditEnvironmentVariables`](http://superuser.com/a/284351/4888). 68 | 69 | #### From your own code 70 | 71 | If you need to acquire the same sort of list that the `vagrant list` command does, but programmatically, feel free to leverage a gem module that wraps around a couple of `VBoxManage` shell commands, like this: 72 | 73 | ``` ruby 74 | require 'vagrant-list' 75 | 76 | Vagrant::List::VirtualBox::List.all # Returns all VMs 77 | Vagrant::List::VirtualBox::List.running # Returns only running VMs 78 | ``` 79 | 80 | The two methods above return an array of UUIDs. If you want to gather further information about a VM, you may also use another class - `Vagrant::List::VMInfo`, like so: 81 | 82 | ``` ruby 83 | require 'vagrant-list` 84 | 85 | Vagrant::List::VirtualBox::List.all.map do |uuid| 86 | puts Vagrant::List::VMInfo.new(uuid).inspect 87 | end 88 | ``` 89 | 90 | ### Running Tests 91 | 92 | Tests for this type of gem are slightly problematic, since much of the core functionality involves shelling out, which is inherently difficult to test, however there are tests to ensure that methods are called as designed, and that helper classes function the way they should. 93 | 94 | To run the tests, follow the steps below: 95 | 96 | 1. Clone the project: `git clone https://github.com/joshmcarthur/vagrant-list.git` 97 | 2. Install dependencies: `bundle install` 98 | 3. Create a virtual machine named `Test` and boot it up 99 | 4. Run the tests: `rake spec` 100 | 101 | ** Remember, in order for the specs to pass, it is required that you have a VM called 'Test' running when the specs are run. It doesn't matter what this VM _is_ (XP, Ubuntu etc.), just as long as it's there** 102 | 103 | ### Contributing 104 | 105 | 1. Fork and clone the project 106 | 2. Run specs and make sure everything is passing 107 | 3. Install the plugin into your vagrant install from the local source and run `vagrant list` to test: `rake build && vagrant plugin install pkg/vagrant-list-#{version}.gem && vagrant list`. 108 | 4. Make your changes, rinse and repeat steps 2 & 3 often 109 | 5. Push your changes in a `feature` or `bugfix` branch to Github. 110 | 6. Send me a pull request! 111 | 112 | ### License 113 | 114 | This open source software is licensed under the MIT License. For more details, see `./LICENSE.txt`. 115 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env rake 2 | require "bundler/gem_tasks" 3 | require 'rspec/core/rake_task' 4 | 5 | RSpec::Core::RakeTask.new(:spec) 6 | 7 | task :default => :spec -------------------------------------------------------------------------------- /lib/vagrant-list.rb: -------------------------------------------------------------------------------- 1 | require 'i18n' 2 | require "vagrant-list/version" 3 | require "vagrant-list/plugin" 4 | require "vagrant-list/vm_info" 5 | require "vagrant-list/command_error" 6 | require "vagrant-list/virtual_box/list" 7 | 8 | -------------------------------------------------------------------------------- /lib/vagrant-list/command.rb: -------------------------------------------------------------------------------- 1 | 2 | 3 | module Vagrant 4 | module List 5 | class Command < Vagrant.plugin("2", :command) 6 | def execute 7 | @env.ui.info "ALL:" 8 | Vagrant::List::VirtualBox::List.all.each do |uuid| 9 | @env.ui.info Vagrant::List::VMInfo.new(uuid).inspect 10 | end 11 | 12 | @env.ui.info "RUNNING:" 13 | Vagrant::List::VirtualBox::List.running.each do |uuid| 14 | @env.ui.info Vagrant::List::VMInfo.new(uuid).inspect 15 | end 16 | end 17 | end 18 | end 19 | end -------------------------------------------------------------------------------- /lib/vagrant-list/command_error.rb: -------------------------------------------------------------------------------- 1 | require 'vagrant/errors' 2 | 3 | 4 | module Vagrant 5 | module List 6 | class CommandError < ::Vagrant::Errors::VagrantError 7 | error_key "command_failed" 8 | end 9 | end 10 | end -------------------------------------------------------------------------------- /lib/vagrant-list/plugin.rb: -------------------------------------------------------------------------------- 1 | begin 2 | require 'vagrant' 3 | rescue LoadError 4 | raise 'vagrant-list should be used from within vagrant.' 5 | end 6 | 7 | # Ensure that the gem is not trying to be used from within a vagrant release 8 | # that will not have the ability to load the plugin 9 | if Vagrant::VERSION < "1.1.0" 10 | raise <<-WARN 11 | The vagrant-list plugin is only compatible with Vagrant 1.1+. 12 | See https://github.com/joshmcarthur/vagrant-list/tree/1.0.x for a 1.0.x-comaptible version 13 | WARN 14 | end 15 | 16 | module Vagrant 17 | module List 18 | class Plugin < Vagrant.plugin("2") 19 | name "List" 20 | description <<-DESC 21 | This plugin makes a `list` command available to you to list all or running vms. 22 | The information is returned in a clear but easy to parse format which is handy for automated 23 | control of vagrant boxes. 24 | DESC 25 | 26 | command "list" do 27 | require_relative 'command' 28 | Command 29 | end 30 | end 31 | end 32 | end 33 | -------------------------------------------------------------------------------- /lib/vagrant-list/version.rb: -------------------------------------------------------------------------------- 1 | module Vagrant 2 | module List 3 | VERSION = "0.0.6" 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /lib/vagrant-list/virtual_box/list.rb: -------------------------------------------------------------------------------- 1 | module Vagrant 2 | module List 3 | module VirtualBox 4 | module List 5 | 6 | def self.all 7 | raw = `VBoxManage list vms`.split("\n") 8 | raise Vagrant::List::CommandError, "VBoxManage list returned non-zero status" if errored? 9 | 10 | process(raw) 11 | end 12 | 13 | def self.running 14 | raw = `VBoxManage list runningvms`.split("\n") 15 | raise Vagrant::List::CommandError, "VBoxManage list returned non-zero status" if errored? 16 | 17 | process(raw) 18 | end 19 | 20 | def self.errored? 21 | $? != 0 22 | end 23 | 24 | private 25 | 26 | def self.process(raw) 27 | raw.map! do |line| 28 | next nil if line =~ /\A""/ 29 | if vm = line[/^".+?" \{(.+?)\}$/, 1] 30 | next vm 31 | end 32 | end.compact 33 | end 34 | end 35 | end 36 | end 37 | end -------------------------------------------------------------------------------- /lib/vagrant-list/vm_info.rb: -------------------------------------------------------------------------------- 1 | require 'vagrant/util' 2 | 3 | module Vagrant 4 | module List 5 | class VMInfo 6 | include Vagrant::Util 7 | 8 | attr_accessor :raw 9 | attr_accessor :uuid 10 | attr_accessor :name 11 | attr_accessor :guest_os 12 | 13 | def initialize(uuid) 14 | self.raw = `VBoxManage showvminfo #{uuid}` 15 | process! 16 | end 17 | 18 | 19 | # Public - Override inspect to display 20 | # vm attributes 21 | def inspect 22 | "#{uuid}: #{name} (#{guest_os})" 23 | end 24 | 25 | private 26 | 27 | # Private - Accept raw output from VBoxManage showvminfo command 28 | # and manipulate string into a useful form. 29 | # 30 | # Requires raw be defined on the instance 31 | # 32 | # Returns the processed object 33 | def process! 34 | lines = self.raw.split("\n") 35 | lines.each do |line| 36 | raw_key, value = line.split(/\:\s+/) 37 | 38 | if raw_key 39 | key = raw_key.downcase.gsub(/\s+/, '_') 40 | self.send("#{key}=", value) if self.respond_to?("#{key}=") && !self.send(key) 41 | end 42 | end 43 | 44 | self 45 | end 46 | end 47 | end 48 | end 49 | -------------------------------------------------------------------------------- /spec/spec_helper.rb: -------------------------------------------------------------------------------- 1 | require 'rubygems' 2 | require 'bundler/setup' 3 | require 'vagrant-list' 4 | 5 | 6 | puts <<-WARNING 7 | WARNING: Because there is currently no support for mocking or stubbing 8 | out calls to VirtualBox, it is required that there be at least 9 | one running VM called 'Test' loaded into VirtualBox in order 10 | for these tests to pass. 11 | WARNING 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /spec/vagrant-list/virtual_box/list_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe Vagrant::List::VirtualBox::List do 4 | describe ".all" do 5 | it "should list VMs" do 6 | subject.all.should have_at_least(1).string 7 | end 8 | 9 | it "should gracefully handle command failure" do 10 | subject.stub(:errored?).and_return(true) 11 | expect { 12 | subject.all 13 | }.to raise_error Vagrant::List::CommandError 14 | end 15 | end 16 | 17 | describe ".running" do 18 | it "should list the 'Test' VM" do 19 | subject.running.should have(1).string 20 | end 21 | 22 | it "should gracefully handle command failure" do 23 | subject.stub(:errored?).and_return(true) 24 | expect { 25 | subject.running 26 | }.to raise_error Vagrant::List::CommandError 27 | end 28 | end 29 | end -------------------------------------------------------------------------------- /spec/vagrant-list/vm_info_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe Vagrant::List::VMInfo do 4 | let(:uuid) { Vagrant::List::VirtualBox::List.all.first } 5 | let(:attributes) { %w( raw uuid name guest_os ) } 6 | 7 | subject do 8 | Vagrant::List::VMInfo.new(uuid) 9 | end 10 | 11 | describe "attributes" do 12 | %w( raw uuid name guest_os ).each do |attribute| 13 | it { subject.methods.should include attribute.to_sym } 14 | it { subject.methods.should include "#{attribute}=".to_sym } 15 | end 16 | end 17 | 18 | describe "initialization" do 19 | it "should delegate to process! for deriving VM information" do 20 | subject.class.any_instance.should_receive(:process!).and_call_original 21 | subject.class.new(uuid) 22 | end 23 | 24 | %w( raw uuid name guest_os ).each do |attribute| 25 | it "should set #{attribute}" do 26 | subject.send(attribute).should be_a(String) 27 | subject.send(attribute).should_not eq "" 28 | end 29 | end 30 | end 31 | 32 | describe ".inspect" do 33 | let(:vm_info) { Vagrant::List::VMInfo.new(uuid) } 34 | subject do 35 | vm_info.inspect 36 | end 37 | 38 | it "should include the UUID" do 39 | subject.should include vm_info.uuid 40 | end 41 | 42 | it "should include the name" do 43 | subject.should include vm_info.name 44 | end 45 | 46 | it "should include the guest OS" do 47 | subject.should include vm_info.guest_os 48 | end 49 | end 50 | end -------------------------------------------------------------------------------- /vagrant-list.gemspec: -------------------------------------------------------------------------------- 1 | # -*- encoding: utf-8 -*- 2 | require File.expand_path('../lib/vagrant-list/version', __FILE__) 3 | 4 | Gem::Specification.new do |gem| 5 | gem.authors = ["Josh McArthur"] 6 | gem.email = ["joshua.mcarthur@gmail.com"] 7 | gem.description = %q{Extends Vagrant with a 'list' command to list known VirtualBox virtual machines} 8 | gem.summary = %q{Extends Vagrant with a 'list' command to list known VirtualBox virtual machines} 9 | gem.homepage = "https://github.com/joshmcarthur/vagrant-list" 10 | 11 | gem.files = `git ls-files`.split($\) 12 | gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) } 13 | gem.test_files = gem.files.grep(%r{^(test|spec|features)/}) 14 | gem.name = "vagrant-list" 15 | gem.require_paths = ["lib"] 16 | gem.version = Vagrant::List::VERSION 17 | 18 | gem.add_development_dependency "rake" 19 | gem.add_development_dependency "rspec" 20 | gem.add_dependency "i18n" 21 | end 22 | --------------------------------------------------------------------------------