derelict 0.0.1 → 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.
- checksums.yaml +5 -13
- data/.cane +2 -0
- data/.coveralls.yml +1 -0
- data/.travis.yml +13 -0
- data/README.md +55 -9
- data/Rakefile +21 -0
- data/derelict.gemspec +25 -1
- data/lib/derelict/connection/invalid.rb +14 -0
- data/lib/derelict/connection/not_found.rb +13 -0
- data/lib/derelict/connection.rb +84 -0
- data/lib/derelict/exception/optional_reason.rb +32 -0
- data/lib/derelict/exception.rb +3 -2
- data/lib/derelict/instance/command_failed.rb +28 -0
- data/lib/derelict/instance/invalid.rb +11 -11
- data/lib/derelict/instance/missing_binary.rb +13 -0
- data/lib/derelict/instance/non_directory.rb +10 -8
- data/lib/derelict/instance/not_found.rb +10 -8
- data/lib/derelict/instance.rb +105 -33
- data/lib/derelict/parser/status/invalid_format.rb +16 -0
- data/lib/derelict/parser/status.rb +89 -0
- data/lib/derelict/parser/version/invalid_format.rb +16 -0
- data/lib/derelict/parser/version.rb +28 -0
- data/lib/derelict/parser.rb +25 -0
- data/lib/derelict/utils/logger/array_outputter.rb +43 -0
- data/lib/derelict/utils/logger/invalid_type.rb +15 -0
- data/lib/derelict/utils/logger/raw_formatter.rb +12 -0
- data/lib/derelict/utils/logger.rb +51 -0
- data/lib/derelict/utils.rb +11 -0
- data/lib/derelict/version.rb +2 -2
- data/lib/derelict/virtual_machine/invalid.rb +14 -0
- data/lib/derelict/virtual_machine/not_found.rb +18 -0
- data/lib/derelict/virtual_machine.rb +154 -0
- data/lib/derelict.rb +61 -14
- data/spec/coverage_helper.rb +16 -0
- data/spec/derelict/connection/invalid_spec.rb +16 -0
- data/spec/derelict/connection/not_found_spec.rb +13 -0
- data/spec/derelict/connection_spec.rb +107 -0
- data/spec/derelict/exception/optional_reason_spec.rb +41 -0
- data/spec/derelict/exception_spec.rb +11 -0
- data/spec/derelict/instance/command_failed_spec.rb +40 -0
- data/spec/derelict/instance/invalid_spec.rb +16 -0
- data/spec/derelict/instance/missing_binary_spec.rb +13 -0
- data/spec/derelict/instance/non_directory_spec.rb +13 -0
- data/spec/derelict/instance/not_found_spec.rb +13 -0
- data/spec/derelict/instance_spec.rb +226 -0
- data/spec/derelict/parser/status/invalid_format_spec.rb +16 -0
- data/spec/derelict/parser/status_spec.rb +214 -0
- data/spec/derelict/parser/version/invalid_format_spec.rb +16 -0
- data/spec/derelict/parser/version_spec.rb +31 -0
- data/spec/derelict/parser_spec.rb +24 -0
- data/spec/derelict/utils/logger/array_outputter_spec.rb +40 -0
- data/spec/derelict/utils/logger/invalid_type_spec.rb +13 -0
- data/spec/derelict/utils/logger/raw_formatter_spec.rb +17 -0
- data/spec/derelict/utils/logger_spec.rb +35 -0
- data/spec/derelict/virtual_machine/invalid_spec.rb +16 -0
- data/spec/derelict/virtual_machine/not_found_spec.rb +34 -0
- data/spec/derelict/virtual_machine_spec.rb +295 -0
- data/spec/derelict_spec.rb +50 -0
- data/spec/spec_helper.rb +28 -3
- data/spec/support/log_context.rb +36 -0
- metadata +175 -22
- data/lib/derelict/instance/already_active.rb +0 -9
- data/spec/system_spec.spec +0 -10
checksums.yaml
CHANGED
@@ -1,15 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
|
5
|
-
data.tar.gz: !binary |-
|
6
|
-
N2RmNTAwOTcwM2VkYTFmNGZmZDQ4NzI2NDhlYTgxNTZlODVjNzU3Mw==
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 4fa06a401e855d7793e04db862ea95dab0af609b
|
4
|
+
data.tar.gz: b0f47b9b5f6a5c4613cea9e73f422c62c68b3b50
|
7
5
|
SHA512:
|
8
|
-
metadata.gz:
|
9
|
-
|
10
|
-
NzAxMmQ0ZGQxNzMyZjljZTc2MWU3MGVkOGU0OTcwMzdhMjBhMmZlZGEzZWQy
|
11
|
-
ZGU2NjAwNDhiNTNlNGFhNTVjMWExNjEyYjAyYjdhMjJiNTQ5MGE=
|
12
|
-
data.tar.gz: !binary |-
|
13
|
-
MmFkMmJkMjk1ZWRlNTY2N2IxYTc5ZTU5NWFhZjMxZTQ4MDI4YjQ1MDRlMzg3
|
14
|
-
N2Q5ZDhjZmQxOTYyZDEzNmFiYzE1ZDY5MDhmYzg4N2I0NTY2MzIxYWM1NjEw
|
15
|
-
MDMxNmUwNjRhYTgzM2QyODRkNDljNmM5ZDY2NDA5Mjk5YTMzZGU=
|
6
|
+
metadata.gz: 022c6640fd37eaf97cfa45a1d8d5ff8fed190487d032614ba138beace12b52dd94419018b006444153289fe440740a24c17f070b1ccb6a89e4bf87aa889b8228
|
7
|
+
data.tar.gz: a0e5c3a9c89be92bedb6310299634e4bf9d8cf3bd00396ff7a6b457adcc3647497400821190e3e103c8e000dc258b0c14abc675404e9a9a71b43aed783d048de
|
data/.cane
ADDED
data/.coveralls.yml
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
service_name: travis-ci
|
data/.travis.yml
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
language: ruby
|
2
|
+
rvm:
|
3
|
+
- 1.8.7
|
4
|
+
- 1.9.3
|
5
|
+
- 2.0.0
|
6
|
+
deploy:
|
7
|
+
provider: rubygems
|
8
|
+
api_key:
|
9
|
+
secure: lm8VbzXJIylbk3bHC5KBU7x0zI5zDHgOaYUkrc4z8R2gjdW9RLAoX8dwJ0N2FEX24zMf3s1fPT4dg70YD2S7FnVy3zan25BP2C2FKGkQ5kqRzV+gJCSD0Hwk8Yj5Breh1RF3xutV12asLq/+rltei7Fu6BnE2pQDk9/gGSCxILs=
|
10
|
+
gem: derelict
|
11
|
+
on:
|
12
|
+
repo: bradfeehan/derelict
|
13
|
+
ruby: 2.0.0
|
data/README.md
CHANGED
@@ -1,5 +1,11 @@
|
|
1
1
|
# Derelict
|
2
2
|
|
3
|
+
[](http://badge.fury.io/rb/derelict)
|
4
|
+
[](https://travis-ci.org/bradfeehan/derelict)
|
5
|
+
[](https://coveralls.io/r/bradfeehan/derelict)
|
6
|
+
[](https://codeclimate.com/github/bradfeehan/derelict)
|
7
|
+
[](https://gemnasium.com/bradfeehan/derelict)
|
8
|
+
|
3
9
|
Provides a Ruby API to control [Vagrant][1] where Vagrant is installed
|
4
10
|
via the Installer package on Mac OS X.
|
5
11
|
|
@@ -13,15 +19,9 @@ Currently a work-in-progress.
|
|
13
19
|
Vagrant was historically available as a [gem][2], naturally providing a
|
14
20
|
Ruby API to control Vagrant in other Ruby libraries and applications.
|
15
21
|
However, [since version 1.1.0][3], [Vagrant is distributed exclusively
|
16
|
-
using an Installer package][4].
|
17
|
-
|
18
|
-
|
19
|
-
parsing its output using string manipulation.
|
20
|
-
|
21
|
-
Derelict is a Ruby gem that can control an instance of Vagrant that's
|
22
|
-
installed with the Installer package, which avoids calling the Vagrant
|
23
|
-
binary by interfacing directly with the Ruby source files in the
|
24
|
-
Vagrant installation.
|
22
|
+
using an Installer package][4]. Derelict is a Ruby library that wraps
|
23
|
+
the Vagrant binary, shelling out and parsing the results of each
|
24
|
+
command.
|
25
25
|
|
26
26
|
[2]: <https://rubygems.org>
|
27
27
|
[3]: <https://groups.google.com/forum/#!msg/vagrant-up/kX_wvn7wcds/luwNur4kgDEJ>
|
@@ -43,6 +43,52 @@ Or install it yourself as:
|
|
43
43
|
$ gem install derelict
|
44
44
|
|
45
45
|
|
46
|
+
## Usage
|
47
|
+
|
48
|
+
Some examples of common operations using Derelict:
|
49
|
+
|
50
|
+
```ruby
|
51
|
+
require "derelict"
|
52
|
+
|
53
|
+
# Determine if there's a "default" VM defined in /path/to/project
|
54
|
+
Derelict.instance.connect("/path/to/project").vm(:default).exists?
|
55
|
+
```
|
56
|
+
|
57
|
+
### Advanced
|
58
|
+
|
59
|
+
```ruby
|
60
|
+
require "derelict"
|
61
|
+
|
62
|
+
# Create an instance (represents a Vagrant installation)
|
63
|
+
instance = Derelict.instance("/path/to/vagrant")
|
64
|
+
instance = Derelict.instance # Defaults to /Applications/Vagrant
|
65
|
+
|
66
|
+
# Issue commands to the instance directly (not usually necessary)
|
67
|
+
result = instance.execute('--version') # Shell::Executer object
|
68
|
+
print "success" if result.success? # if Vagrant's exit status was 0
|
69
|
+
print result.stdout # "Vagrant 1.3.3\n"
|
70
|
+
|
71
|
+
# Connect to a Vagrant project (containing a Vagrantfile)
|
72
|
+
connection = instance.connect("/path/to/project")
|
73
|
+
|
74
|
+
# Issue commands to the connection directly (runs from the project dir)
|
75
|
+
result = connection.execute(:up) # runs "vagrant up" in project dir
|
76
|
+
result.success? # it's a Shell::Executer object again
|
77
|
+
|
78
|
+
# Retrieve a particular VM from a connection (multi-machine support)
|
79
|
+
vm = connection.vm(:web) # "vm" is a Derelict::VirtualMachine
|
80
|
+
vm.exists? # does the connection define a "web" VM?
|
81
|
+
vm.state # current VM state (:running, :not_created...)
|
82
|
+
vm.running? # whether the VM is currently running or not
|
83
|
+
vm.up! # runs "vagrant up" for this VM only
|
84
|
+
vm.halt! # runs "vagrant halt" for this VM only
|
85
|
+
vm.destroy! # runs "vagrant destroy --force" for this VM
|
86
|
+
vm.reload! # runs "vagrant reload" for this VM only
|
87
|
+
vm.suspend! # runs "vagrant suspend" for this VM only
|
88
|
+
vm.resume! # runs "vagrant resume" for this VM only
|
89
|
+
```
|
90
|
+
|
91
|
+
|
46
92
|
## Contributing
|
47
93
|
|
48
94
|
1. Fork it
|
data/Rakefile
CHANGED
@@ -1 +1,22 @@
|
|
1
1
|
require "bundler/gem_tasks"
|
2
|
+
require "rspec/core/rake_task"
|
3
|
+
|
4
|
+
# Define "spec" task using RSpec's built-in Rake task
|
5
|
+
RSpec::Core::RakeTask.new :spec do |spec|
|
6
|
+
spec.verbose = false
|
7
|
+
end
|
8
|
+
|
9
|
+
version_major = RbConfig::CONFIG["MAJOR"].to_i
|
10
|
+
version_minor = RbConfig::CONFIG["MINOR"].to_i
|
11
|
+
if version_major >= 1 and version_minor >= 9
|
12
|
+
require "cane/rake_task"
|
13
|
+
|
14
|
+
# Define "quality" task using Cane's built-in Rake task
|
15
|
+
Cane::RakeTask.new :quality do |quality|
|
16
|
+
quality.canefile = File.join File.dirname(__FILE__), ".cane"
|
17
|
+
end
|
18
|
+
|
19
|
+
task :default => [:spec, :quality]
|
20
|
+
else
|
21
|
+
task :default => :spec
|
22
|
+
end
|
data/derelict.gemspec
CHANGED
@@ -20,7 +20,7 @@ Gem::Specification.new do |spec|
|
|
20
20
|
"applications typically need to invoke the Vagrant binary, which ",
|
21
21
|
"requires forking a new process and parsing its output using ",
|
22
22
|
"string manipulation.",
|
23
|
-
].join
|
23
|
+
].join,
|
24
24
|
spec.summary =
|
25
25
|
"Ruby API for Vagrant installed via Installer package on Mac OS X."
|
26
26
|
spec.homepage = "https://github.com/bradfeehan/derelict"
|
@@ -31,7 +31,31 @@ Gem::Specification.new do |spec|
|
|
31
31
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
32
32
|
spec.require_paths = ["lib"]
|
33
33
|
|
34
|
+
spec.add_runtime_dependency "log4r"
|
35
|
+
spec.add_runtime_dependency "memoist"
|
36
|
+
spec.add_runtime_dependency "shell-executer"
|
37
|
+
|
38
|
+
|
39
|
+
version_major = RbConfig::CONFIG["MAJOR"].to_i
|
40
|
+
version_minor = RbConfig::CONFIG["MINOR"].to_i
|
41
|
+
cane_supported = (version_major >= 1 and version_minor >= 9)
|
42
|
+
|
34
43
|
spec.add_development_dependency "bundler", "~> 1.3"
|
44
|
+
spec.add_development_dependency "cane" if cane_supported
|
45
|
+
spec.add_development_dependency "coveralls"
|
35
46
|
spec.add_development_dependency "rake"
|
36
47
|
spec.add_development_dependency "rspec"
|
48
|
+
spec.add_development_dependency "simplecov"
|
49
|
+
spec.add_development_dependency "its"
|
50
|
+
|
51
|
+
# When running on Travis CI, any passing builds will be deployed
|
52
|
+
# (i.e. pushed to RubyGems). This changes the version number so that
|
53
|
+
# these deployments are marked as pre-release versions (which will
|
54
|
+
# occur if the version number has a letter in it, so we add
|
55
|
+
# "travis" followed by the job number to the version string).
|
56
|
+
# So version 1.2.3 will be marked as (e.g.) "1.2.4.travis.567".
|
57
|
+
if ENV["TRAVIS"]
|
58
|
+
build = ENV["TRAVIS_JOB_NUMBER"].split(".").first
|
59
|
+
spec.version = "#{spec.version.to_s.succ}.travis.#{build}"
|
60
|
+
end
|
37
61
|
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module Derelict
|
2
|
+
class Connection
|
3
|
+
# Represents an invalid connection, which Derelict can't use
|
4
|
+
class Invalid < Derelict::Exception
|
5
|
+
include Derelict::Exception::OptionalReason
|
6
|
+
|
7
|
+
private
|
8
|
+
# Retrieves the default error message
|
9
|
+
def default_message
|
10
|
+
"Invalid Derelict connection"
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module Derelict
|
2
|
+
class Connection
|
3
|
+
# The Vagrantfile for the connection was not found
|
4
|
+
class NotFound < Invalid
|
5
|
+
# Initializes a new instance of this exception for a given path
|
6
|
+
#
|
7
|
+
# * path: The requested path of the instance
|
8
|
+
def initialize(path)
|
9
|
+
super "Vagrantfile not found for #{path}"
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
module Derelict
|
2
|
+
# Connects a Derelict::Instance to its use in a particular directory
|
3
|
+
class Connection
|
4
|
+
autoload :Invalid, "derelict/connection/invalid"
|
5
|
+
autoload :NotFound, "derelict/connection/not_found"
|
6
|
+
|
7
|
+
# Include "logger" method to get a logger for this class
|
8
|
+
include Utils::Logger
|
9
|
+
|
10
|
+
attr_reader :instance
|
11
|
+
attr_reader :path
|
12
|
+
|
13
|
+
# Initializes a Connection for use in a particular directory
|
14
|
+
#
|
15
|
+
# * instance: The Derelict::Instance to use to control Vagrant
|
16
|
+
# * path: The project path, which contains the Vagrantfile
|
17
|
+
def initialize(instance, path)
|
18
|
+
@instance = instance
|
19
|
+
@path = path
|
20
|
+
logger.debug "Successfully initialized #{description}"
|
21
|
+
end
|
22
|
+
|
23
|
+
# Validates the data used for this connection
|
24
|
+
#
|
25
|
+
# Raises exceptions on failure:
|
26
|
+
#
|
27
|
+
# * +Derelict::Connection::NotFound+ if the path is not found
|
28
|
+
def validate!
|
29
|
+
logger.debug "Starting validation for #{description}"
|
30
|
+
raise NotFound.new path unless File.exists? path
|
31
|
+
logger.info "Successfully validated #{description}"
|
32
|
+
self
|
33
|
+
end
|
34
|
+
|
35
|
+
# Executes a Vagrant subcommand using this connection
|
36
|
+
#
|
37
|
+
# * subcommand: Vagrant subcommand to run (:up, :status, etc.)
|
38
|
+
# * arguments: Arguments to pass to the subcommand (optional)
|
39
|
+
# * block: Passed through to @instance#execute
|
40
|
+
def execute(subcommand, *arguments, &block)
|
41
|
+
log_execute subcommand, *arguments
|
42
|
+
Dir.chdir path do
|
43
|
+
instance.execute subcommand.to_sym, *arguments, &block
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
# Executes a Vagrant subcommand, raising an exception on failure
|
48
|
+
#
|
49
|
+
# * subcommand: Vagrant subcommand to run (:up, :status, etc.)
|
50
|
+
# * arguments: Arguments to pass to the subcommand (optional)
|
51
|
+
# * block: Passed through to Shell.execute (shell-executer)
|
52
|
+
#
|
53
|
+
# Raises +Derelict::Instance::CommandFailed+ if the command fails.
|
54
|
+
def execute!(subcommand, *arguments, &block)
|
55
|
+
log_execute subcommand, *arguments
|
56
|
+
Dir.chdir path do
|
57
|
+
instance.execute! subcommand.to_sym, *arguments, &block
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
# Retrieves a Derelict::VirtualMachine for a particular VM
|
62
|
+
#
|
63
|
+
# * name: The name of the virtual machine to retrieve
|
64
|
+
def vm(name)
|
65
|
+
logger.debug "Retrieving VM '#{name}' from #{description}"
|
66
|
+
Derelict::VirtualMachine.new(self, name).validate!
|
67
|
+
end
|
68
|
+
|
69
|
+
# Provides a description of this Connection
|
70
|
+
#
|
71
|
+
# Mainly used for log messages.
|
72
|
+
def description
|
73
|
+
"Derelict::Connection at '#{path}' using #{instance.description}"
|
74
|
+
end
|
75
|
+
|
76
|
+
private
|
77
|
+
# Handles the logging that should occur for a call to #execute(!)
|
78
|
+
def log_execute(subcommand, *arguments)
|
79
|
+
logger.debug do
|
80
|
+
"Executing #{subcommand} #{arguments.inspect} on #{description}"
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module Derelict
|
2
|
+
class Exception
|
3
|
+
# An exception that has a message and optional additional reason
|
4
|
+
#
|
5
|
+
# The reason can be passed to the constructor (if desired). When a
|
6
|
+
# reason is passed, it's appended to the default message. If no
|
7
|
+
# reason is passed, the default message is used.
|
8
|
+
module OptionalReason
|
9
|
+
# Initializes a new instance of this exception, with a reason
|
10
|
+
#
|
11
|
+
# * reason: Optional reason to add to the default error message
|
12
|
+
# (optional, the default message will be used if no
|
13
|
+
# reason is provided)
|
14
|
+
def initialize(reason = nil)
|
15
|
+
if reason.nil?
|
16
|
+
super default_message
|
17
|
+
else
|
18
|
+
super "#{default_message}: #{reason}"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
# Retrieves the default error message
|
24
|
+
#
|
25
|
+
# This needs to be overridden in child classes in order to
|
26
|
+
# customize the default error message.
|
27
|
+
def default_message
|
28
|
+
raise NotImplementedError.new "#default_message not defined"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
data/lib/derelict/exception.rb
CHANGED
@@ -0,0 +1,28 @@
|
|
1
|
+
module Derelict
|
2
|
+
class Instance
|
3
|
+
# Represents an invalid instance, which can't be used with Derelict
|
4
|
+
class CommandFailed < Derelict::Exception
|
5
|
+
# Initializes a new instance of this exception, with a reason
|
6
|
+
#
|
7
|
+
# * reason: The result (Shell::Executer) for the command that
|
8
|
+
# failed (optional, provides extra detail in the
|
9
|
+
# message)
|
10
|
+
def initialize(command = nil, result = nil)
|
11
|
+
super [default_message, describe(command, result)].join
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
# Retrieves the default error message
|
16
|
+
def default_message
|
17
|
+
"Error executing Vagrant command"
|
18
|
+
end
|
19
|
+
|
20
|
+
def describe(command = nil, result = nil)
|
21
|
+
[
|
22
|
+
command.nil? ? "" : " '#{command}'",
|
23
|
+
result.nil? ? "" : ", STDERR output:\n#{result.stderr}",
|
24
|
+
].join
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -1,14 +1,14 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
1
|
+
module Derelict
|
2
|
+
class Instance
|
3
|
+
# Represents an invalid instance, which can't be used with Derelict
|
4
|
+
class Invalid < Derelict::Exception
|
5
|
+
include Derelict::Exception::OptionalReason
|
6
|
+
|
7
|
+
private
|
8
|
+
# Retrieves the default error message
|
9
|
+
def default_message
|
10
|
+
"Invalid Derelict instance"
|
11
|
+
end
|
12
12
|
end
|
13
13
|
end
|
14
14
|
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module Derelict
|
2
|
+
class Instance
|
3
|
+
# The "vagrant" binary was missing from the instance
|
4
|
+
class MissingBinary < Invalid
|
5
|
+
# Initializes a new instance of this exception for a given file
|
6
|
+
#
|
7
|
+
# * file: The expected location of the binary
|
8
|
+
def initialize(file)
|
9
|
+
super "'vagrant' binary not found at #{file}"
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -1,11 +1,13 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
1
|
+
module Derelict
|
2
|
+
class Instance
|
3
|
+
# The path used for the instance was a file, not a directory
|
4
|
+
class NonDirectory < Invalid
|
5
|
+
# Initializes a new instance of this exception for a given path
|
6
|
+
#
|
7
|
+
# * path: The requested path of the instance
|
8
|
+
def initialize(path)
|
9
|
+
super "expected directory, found file: #{path}"
|
10
|
+
end
|
9
11
|
end
|
10
12
|
end
|
11
13
|
end
|
@@ -1,11 +1,13 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
1
|
+
module Derelict
|
2
|
+
class Instance
|
3
|
+
# The path used for the instance was not found
|
4
|
+
class NotFound < Invalid
|
5
|
+
# Initializes a new instance of this exception for a given path
|
6
|
+
#
|
7
|
+
# * path: The requested path of the instance
|
8
|
+
def initialize(path)
|
9
|
+
super "directory doesn't exist: #{path}"
|
10
|
+
end
|
9
11
|
end
|
10
12
|
end
|
11
13
|
end
|
data/lib/derelict/instance.rb
CHANGED
@@ -1,53 +1,125 @@
|
|
1
|
-
|
2
|
-
# Represents a
|
1
|
+
module Derelict
|
2
|
+
# Represents a Vagrant instance installed via the Installer package
|
3
3
|
class Instance
|
4
|
-
autoload :
|
4
|
+
autoload :CommandFailed, "derelict/instance/command_failed"
|
5
|
+
autoload :Invalid, "derelict/instance/invalid"
|
6
|
+
autoload :MissingBinary, "derelict/instance/missing_binary"
|
5
7
|
autoload :NonDirectory, "derelict/instance/non_directory"
|
6
8
|
autoload :NotFound, "derelict/instance/not_found"
|
7
9
|
|
8
|
-
|
10
|
+
# Include "memoize" class method to memoize methods
|
11
|
+
extend Memoist
|
9
12
|
|
10
|
-
#
|
13
|
+
# Include "logger" method to get a logger for this class
|
14
|
+
include Utils::Logger
|
15
|
+
|
16
|
+
# The default path to the Vagrant installation folder
|
17
|
+
DEFAULT_PATH = "/Applications/Vagrant"
|
18
|
+
|
19
|
+
attr_reader :path
|
20
|
+
|
21
|
+
# Initialize an instance for a particular directory
|
11
22
|
#
|
12
|
-
# path: The path to the
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
23
|
+
# * path: The path to the Vagrant installation folder (optional,
|
24
|
+
# defaults to DEFAULT_PATH)
|
25
|
+
def initialize(path = DEFAULT_PATH)
|
26
|
+
@path = path
|
27
|
+
logger.debug "Successfully initialized #{description}"
|
17
28
|
end
|
18
29
|
|
19
|
-
#
|
20
|
-
|
21
|
-
|
30
|
+
# Validates the data used for this instance
|
31
|
+
#
|
32
|
+
# Raises exceptions on failure:
|
33
|
+
#
|
34
|
+
# * +Derelict::Instance::NotFound+ if the instance is not found
|
35
|
+
# * +Derelict::Instance::NonDirectory+ if the path is a file,
|
36
|
+
# instead of a directory as expected
|
37
|
+
# * +Derelict::Instance::MissingBinary+ if the "vagrant" binary
|
38
|
+
# isn't in the expected location or is not executable
|
39
|
+
def validate!
|
40
|
+
logger.debug "Starting validation for #{description}"
|
41
|
+
raise NotFound.new path unless File.exists? path
|
42
|
+
raise NonDirectory.new path unless File.directory? path
|
43
|
+
raise MissingBinary.new vagrant unless File.exists? vagrant
|
44
|
+
raise MissingBinary.new vagrant unless File.executable? vagrant
|
45
|
+
logger.info "Successfully validated #{description}"
|
46
|
+
self
|
47
|
+
end
|
22
48
|
|
23
|
-
|
24
|
-
|
25
|
-
}
|
49
|
+
# Determines the version of this Vagrant instance
|
50
|
+
def version
|
51
|
+
logger.info "Determining Vagrant version for #{description}"
|
52
|
+
output = execute!("--version").stdout
|
53
|
+
Derelict::Parser::Version.new(output).version
|
54
|
+
end
|
55
|
+
memoize :version
|
26
56
|
|
27
|
-
|
57
|
+
# Executes a Vagrant subcommand using this instance
|
58
|
+
#
|
59
|
+
# * subcommand: Vagrant subcommand to run (:up, :status, etc.)
|
60
|
+
# * arguments: Arguments to pass to the subcommand (optional)
|
61
|
+
# * block: Passed through to Shell.execute (shell-executer)
|
62
|
+
def execute(subcommand, *arguments, &block)
|
63
|
+
command = command(subcommand, *arguments)
|
64
|
+
logger.debug "Executing #{command} using #{description}"
|
65
|
+
Shell.execute command, &block
|
28
66
|
end
|
29
67
|
|
30
|
-
#
|
31
|
-
#
|
32
|
-
#
|
33
|
-
#
|
68
|
+
# Executes a Vagrant subcommand, raising an exception on failure
|
69
|
+
#
|
70
|
+
# * subcommand: Vagrant subcommand to run (:up, :status, etc.)
|
71
|
+
# * arguments: Arguments to pass to the subcommand (optional)
|
72
|
+
# * block: Passed through to Shell.execute (shell-executer)
|
73
|
+
#
|
74
|
+
# Raises +Derelict::Instance::CommandFailed+ if the command fails.
|
75
|
+
def execute!(subcommand, *arguments, &block)
|
76
|
+
execute(subcommand, *arguments, &block).tap do |result|
|
77
|
+
unless result.success?
|
78
|
+
command = command(subcommand, *arguments)
|
79
|
+
exception = CommandFailed.new command
|
80
|
+
logger.warn "Command #{command} failed: #{exception.message}"
|
81
|
+
raise exception, result
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
# Initializes a Connection for use in a particular directory
|
87
|
+
#
|
88
|
+
# * instance: The Derelict::Instance to use to control Vagrant
|
89
|
+
# * path: The project path, which contains the Vagrantfile
|
90
|
+
def connect(path)
|
91
|
+
logger.info "Creating connection for '#{path}' by #{description}"
|
92
|
+
Derelict::Connection.new(self, path).validate!
|
93
|
+
end
|
94
|
+
|
95
|
+
# Provides a description of this Instance
|
96
|
+
#
|
97
|
+
# Mainly used for log messages.
|
98
|
+
def description
|
99
|
+
"Derelict::Instance at '#{path}'"
|
100
|
+
end
|
34
101
|
|
35
102
|
private
|
36
|
-
# Retrieves the path to the
|
37
|
-
def
|
38
|
-
File.join
|
103
|
+
# Retrieves the path to the vagrant binary for this instance
|
104
|
+
def vagrant
|
105
|
+
File.join(@path, "bin", "vagrant").tap do |vagrant|
|
106
|
+
logger.debug "Vagrant binary for #{description} is '#{vagrant}'"
|
107
|
+
end
|
39
108
|
end
|
109
|
+
memoize :vagrant
|
40
110
|
|
41
|
-
# Creates a pattern to match all embedded gemspec files
|
42
|
-
def gemspec_files
|
43
|
-
pattern = File.join gems_path, "specifications", "*.gemspec"
|
44
|
-
Dir.glob(pattern).sort
|
45
|
-
end
|
46
111
|
|
47
|
-
#
|
48
|
-
|
49
|
-
|
50
|
-
|
112
|
+
# Constructs the command to execute a Vagrant subcommand
|
113
|
+
#
|
114
|
+
# * subcommand: Vagrant subcommand to run (:up, :status, etc.)
|
115
|
+
# * arguments: Arguments to pass to the subcommand (optional)
|
116
|
+
def command(subcommand, *arguments)
|
117
|
+
args = [vagrant, subcommand.to_s, arguments].flatten
|
118
|
+
args.map {|a| Shellwords.escape a }.join(' ').tap do |command|
|
119
|
+
logger.debug "Generated command '#{command}' from " +
|
120
|
+
"subcommand '#{subcommand.to_s}' with arguments " +
|
121
|
+
arguments.inspect
|
122
|
+
end
|
51
123
|
end
|
52
124
|
end
|
53
125
|
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Derelict
|
2
|
+
class Parser
|
3
|
+
class Status
|
4
|
+
# The status wasn't in the expected format and couldn't be parsed
|
5
|
+
class InvalidFormat < Derelict::Exception
|
6
|
+
include Derelict::Exception::OptionalReason
|
7
|
+
|
8
|
+
private
|
9
|
+
# Retrieves the default error message
|
10
|
+
def default_message
|
11
|
+
"Output from 'vagrant status' was in an unexpected format"
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|