Merge branch 'f-machine-readable'
This adds the foundation for supporting machine-readable output. This purposely doesn't add much machine-readable output, because we want to learn from the community what people want. This also isn't a full API for controlling Vagrant. Rather, it is a way to programmatically script Vagrant commands.
This commit is contained in:
commit
aa02c64b0a
|
@ -55,6 +55,12 @@ if ARGV.include?("--color")
|
||||||
opts[:ui_class] = Vagrant::UI::Colored
|
opts[:ui_class] = Vagrant::UI::Colored
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Highest precedence is if we have enabled machine-readable output
|
||||||
|
if ARGV.include?("--machine-readable")
|
||||||
|
ARGV.delete("--machine-readable")
|
||||||
|
opts[:ui_class] = Vagrant::UI::MachineReadable
|
||||||
|
end
|
||||||
|
|
||||||
# Default to colored output
|
# Default to colored output
|
||||||
opts[:ui_class] ||= Vagrant::UI::Colored
|
opts[:ui_class] ||= Vagrant::UI::Colored
|
||||||
|
|
||||||
|
|
|
@ -31,6 +31,14 @@ module Vagrant
|
||||||
define_method(method) { |*args| }
|
define_method(method) { |*args| }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# For machine-readable output.
|
||||||
|
#
|
||||||
|
# @param [String] type The type of the data
|
||||||
|
# @param [Array] data The data associated with the type
|
||||||
|
def machine(type, *data)
|
||||||
|
@logger.info("Machine: #{type} #{data.inspect}")
|
||||||
|
end
|
||||||
|
|
||||||
# Returns a new UI class that is scoped to the given resource name.
|
# Returns a new UI class that is scoped to the given resource name.
|
||||||
# Subclasses can then use this scope name to do whatever they please.
|
# Subclasses can then use this scope name to do whatever they please.
|
||||||
#
|
#
|
||||||
|
@ -51,6 +59,46 @@ module Vagrant
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
class MachineReadable < Interface
|
||||||
|
include Util::SafePuts
|
||||||
|
|
||||||
|
def initialize
|
||||||
|
super
|
||||||
|
|
||||||
|
@lock = Mutex.new
|
||||||
|
end
|
||||||
|
|
||||||
|
def ask(*args)
|
||||||
|
super
|
||||||
|
|
||||||
|
# Machine-readable can't ask for input
|
||||||
|
raise Errors::UIExpectsTTY
|
||||||
|
end
|
||||||
|
|
||||||
|
def machine(type, *data)
|
||||||
|
opts = {}
|
||||||
|
opts = data.pop if data.last.kind_of?(Hash)
|
||||||
|
|
||||||
|
target = opts[:scope] || ""
|
||||||
|
|
||||||
|
# Prepare the data by replacing characters that aren't outputted
|
||||||
|
data.each_index do |i|
|
||||||
|
data[i] = data[i].to_s
|
||||||
|
data[i].gsub!(",", "%!(VAGRANT_COMMA)")
|
||||||
|
data[i].gsub!("\n", "\\n")
|
||||||
|
data[i].gsub!("\r", "\\r")
|
||||||
|
end
|
||||||
|
|
||||||
|
@lock.synchronize do
|
||||||
|
safe_puts("#{Time.now.utc.to_i},#{target},#{type},#{data.join(",")}")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def scope(scope_name)
|
||||||
|
BasicScope.new(self, scope_name)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
# This is a UI implementation that outputs the text as is. It
|
# This is a UI implementation that outputs the text as is. It
|
||||||
# doesn't add any color.
|
# doesn't add any color.
|
||||||
class Basic < Interface
|
class Basic < Interface
|
||||||
|
@ -172,6 +220,14 @@ module Vagrant
|
||||||
# By default do nothing, these aren't logged
|
# By default do nothing, these aren't logged
|
||||||
define_method(method) { |*args| @ui.send(method, *args) }
|
define_method(method) { |*args| @ui.send(method, *args) }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def machine(type, *data)
|
||||||
|
opts = {}
|
||||||
|
opts = data.pop if data.last.is_a?(Hash)
|
||||||
|
opts[:scope] = @scope
|
||||||
|
data << opts
|
||||||
|
@ui.machine(type, *data)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# This is a UI implementation that outputs color for various types
|
# This is a UI implementation that outputs color for various types
|
||||||
|
|
|
@ -30,6 +30,9 @@ module VagrantPlugins
|
||||||
# and which don't, since we plan on doing that transparently.
|
# and which don't, since we plan on doing that transparently.
|
||||||
boxes.each do |name, provider, _v1|
|
boxes.each do |name, provider, _v1|
|
||||||
@env.ui.info("#{name.ljust(longest_box_length)} (#{provider})", :prefix => false)
|
@env.ui.info("#{name.ljust(longest_box_length)} (#{provider})", :prefix => false)
|
||||||
|
|
||||||
|
@env.ui.machine("box-name", name)
|
||||||
|
@env.ui.machine("box-provider", provider)
|
||||||
end
|
end
|
||||||
|
|
||||||
# Success, exit status 0
|
# Success, exit status 0
|
||||||
|
|
|
@ -25,7 +25,15 @@ module VagrantPlugins
|
||||||
results = []
|
results = []
|
||||||
with_target_vms(argv) do |machine|
|
with_target_vms(argv) do |machine|
|
||||||
state = machine.state if !state
|
state = machine.state if !state
|
||||||
results << "#{machine.name.to_s.ljust(max_name_length)} #{machine.state.short_description} (#{machine.provider_name})"
|
current_state = machine.state
|
||||||
|
results << "#{machine.name.to_s.ljust(max_name_length)} " +
|
||||||
|
"#{current_state.short_description} (#{machine.provider_name})"
|
||||||
|
|
||||||
|
opts = { scope: machine.name.to_s }
|
||||||
|
@env.ui.machine("provider-name", machine.provider_name, opts)
|
||||||
|
@env.ui.machine("state", current_state.id, opts)
|
||||||
|
@env.ui.machine("state-human-short", current_state.short_description, opts)
|
||||||
|
@env.ui.machine("state-human-long", current_state.long_description, opts)
|
||||||
end
|
end
|
||||||
|
|
||||||
message = nil
|
message = nil
|
||||||
|
|
|
@ -119,6 +119,7 @@
|
||||||
<li<%= sidebar_current("cli-status") %>><a href="/v2/cli/status.html">status</a></li>
|
<li<%= sidebar_current("cli-status") %>><a href="/v2/cli/status.html">status</a></li>
|
||||||
<li<%= sidebar_current("cli-suspend") %>><a href="/v2/cli/suspend.html">suspend</a></li>
|
<li<%= sidebar_current("cli-suspend") %>><a href="/v2/cli/suspend.html">suspend</a></li>
|
||||||
<li<%= sidebar_current("cli-up") %>><a href="/v2/cli/up.html">up</a></li>
|
<li<%= sidebar_current("cli-up") %>><a href="/v2/cli/up.html">up</a></li>
|
||||||
|
<li<%= sidebar_current("cli-machinereadable") %>><a href="/v2/cli/machine-readable.html">Machine Readable Output</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
|
|
|
@ -86,7 +86,7 @@ h6 {
|
||||||
line-height: @font-size;
|
line-height: @font-size;
|
||||||
}
|
}
|
||||||
|
|
||||||
p {
|
p, td {
|
||||||
letter-spacing: 1px;
|
letter-spacing: 1px;
|
||||||
line-height: 32px;
|
line-height: 32px;
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,11 @@
|
||||||
/* compontents */
|
/* compontents */
|
||||||
|
|
||||||
|
table.mr-types {
|
||||||
|
th.mr-type {
|
||||||
|
width: 200px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//search
|
//search
|
||||||
.search-bar {
|
.search-bar {
|
||||||
border-bottom: 1px solid fade(@black, 10%);
|
border-bottom: 1px solid fade(@black, 10%);
|
||||||
|
|
|
@ -0,0 +1,136 @@
|
||||||
|
---
|
||||||
|
page_title: "Machine Readable Output - Command-Line Interface"
|
||||||
|
sidebar_current: "cli-machinereadable"
|
||||||
|
---
|
||||||
|
|
||||||
|
# Machine Readable Output
|
||||||
|
|
||||||
|
Every Vagrant commands accepts a `--machine-readable` flag which enables
|
||||||
|
machine readable output mode. In this mode, the output to the terminal
|
||||||
|
is replaced with machine-friendly output.
|
||||||
|
|
||||||
|
This mode makes it easy to programmatically execute Vagrant and read data
|
||||||
|
out of it. This output format is protected by our
|
||||||
|
[backwards compatibility](/v2/installation/backwards-compatibility.html)
|
||||||
|
policy. Until Vagrant 2.0 is released, however, the machine readable output
|
||||||
|
may change as we determine more use cases for it. But the backwards
|
||||||
|
compatibility promise should make it safe to write client libraries to
|
||||||
|
parse the output format.
|
||||||
|
|
||||||
|
<div class="alert alert-block alert-warn">
|
||||||
|
<p>
|
||||||
|
<strong>Advanced topic!</strong> This is an advanced topic for use only if
|
||||||
|
you want to programmatically execute Vagrant. If you're just getting started
|
||||||
|
with Vagrant, you may safely skip this section.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
## Work-In-Progress
|
||||||
|
|
||||||
|
The machine-readable output is very new (released as part of Vagrant 1.4).
|
||||||
|
We're still gathering use cases for it and building up the output for each
|
||||||
|
of the commands. It is likely that what you may want to achieve with
|
||||||
|
the machine-readable output is not possible due to missing information.
|
||||||
|
|
||||||
|
In this case, we ask that you please
|
||||||
|
[open an issue](https://github.com/mitchellh/vagrant/issues)
|
||||||
|
requesting that certain information become available. We'll most likely add
|
||||||
|
it!
|
||||||
|
|
||||||
|
## Format
|
||||||
|
|
||||||
|
The machine readable format is a line-oriented, comma-delimeted text format.
|
||||||
|
This makes it extremely easy to parse using standard Unix tools such as awk or
|
||||||
|
grep in addition to full programming languages like Ruby or Python.
|
||||||
|
|
||||||
|
The format is:
|
||||||
|
|
||||||
|
```
|
||||||
|
timestamp,target,type,data...
|
||||||
|
```
|
||||||
|
|
||||||
|
Each component is explained below:
|
||||||
|
|
||||||
|
* **timestamp** is a Unix timestamp in UTC of when the message was printed.
|
||||||
|
|
||||||
|
* **target** is the target of the following output. This is empty if the
|
||||||
|
message is related to Vagrant globally. Otherwise, this is generally a machine
|
||||||
|
name so you can relate output to a specific machine when multi-VM is in use.
|
||||||
|
|
||||||
|
* **type** is the type of machine-readable message being outputted. There are
|
||||||
|
a set of standard types which are covered later.
|
||||||
|
|
||||||
|
* **data** is zero or more comma-seperated values associated with the prior
|
||||||
|
type. The exact amount and meaning of this data is type-dependent, so you
|
||||||
|
must read the documentation associated with the type to understand fully.
|
||||||
|
|
||||||
|
Within the format, if data contains a comma, it is replaced with
|
||||||
|
`%!(VAGRANT_COMMA)`. This was preferred over an escape character such as \'
|
||||||
|
because it is more friendly to tools like awk.
|
||||||
|
|
||||||
|
Newlines within the format are replaced with their respective standard escape
|
||||||
|
sequence. Newlines become a literal `\n` within the output. Carriage returns
|
||||||
|
become a literal `\r`.
|
||||||
|
|
||||||
|
## Types
|
||||||
|
|
||||||
|
This section documents all the available types that may be outputted
|
||||||
|
with the machine-readable output.
|
||||||
|
|
||||||
|
<table class="table table-hover table-bordered mr-types">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th class="mr-type">Type</th>
|
||||||
|
<th>Description</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td>box-name</td>
|
||||||
|
<td>
|
||||||
|
Name of a box installed into Vagrant.
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td>box-provider</td>
|
||||||
|
<td>
|
||||||
|
Provider for an installed box.
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td>provider-name</td>
|
||||||
|
<td>
|
||||||
|
The provider name of the target machine.
|
||||||
|
<span class="label">targetted</span>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td>state</td>
|
||||||
|
<td>
|
||||||
|
The state ID of the target machine.
|
||||||
|
<span class="label">targetted</span>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td>state-human-long</td>
|
||||||
|
<td>
|
||||||
|
Human-readable description of the state of the machine. This is the
|
||||||
|
long version, and may be a paragraph or longer.
|
||||||
|
<span class="label">targetted</span>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td>state-human-short</td>
|
||||||
|
<td>
|
||||||
|
Human-readable description of the state of the machine. This is the
|
||||||
|
short version, limited to at most a sentence.
|
||||||
|
<span class="label">targetted</span>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
</table>
|
Loading…
Reference in New Issue