Merge pull request #9504 from zachflower/feature/vagrant-aliases
Vagrant aliases
This commit is contained in:
commit
f3c5e86f28
|
@ -84,6 +84,7 @@ require "vagrant/registry"
|
||||||
|
|
||||||
module Vagrant
|
module Vagrant
|
||||||
autoload :Action, 'vagrant/action'
|
autoload :Action, 'vagrant/action'
|
||||||
|
autoload :Alias, 'vagrant/alias'
|
||||||
autoload :BatchAction, 'vagrant/batch_action'
|
autoload :BatchAction, 'vagrant/batch_action'
|
||||||
autoload :Box, 'vagrant/box'
|
autoload :Box, 'vagrant/box'
|
||||||
autoload :BoxCollection, 'vagrant/box_collection'
|
autoload :BoxCollection, 'vagrant/box_collection'
|
||||||
|
|
|
@ -0,0 +1,56 @@
|
||||||
|
require "vagrant/registry"
|
||||||
|
|
||||||
|
module Vagrant
|
||||||
|
# This class imports and processes CLI aliases stored in ~/.vagrant.d/aliases
|
||||||
|
class Alias
|
||||||
|
def initialize(env)
|
||||||
|
@aliases = Registry.new
|
||||||
|
@env = env
|
||||||
|
|
||||||
|
if env.aliases_path.file?
|
||||||
|
env.aliases_path.readlines.each do |line|
|
||||||
|
# separate keyword-command pairs
|
||||||
|
keyword, command = interpret(line)
|
||||||
|
|
||||||
|
if keyword && command
|
||||||
|
register(keyword, command)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# This returns all the registered alias commands.
|
||||||
|
def commands
|
||||||
|
@aliases
|
||||||
|
end
|
||||||
|
|
||||||
|
# This interprets a raw line from the aliases file.
|
||||||
|
def interpret(line)
|
||||||
|
# is it a comment?
|
||||||
|
return nil if line.strip.start_with?("#")
|
||||||
|
|
||||||
|
keyword, command = line.split("=", 2).collect(&:strip)
|
||||||
|
|
||||||
|
# validate the keyword
|
||||||
|
if keyword.match(/\s/i)
|
||||||
|
raise Errors::AliasInvalidError, alias: line, message: "Alias keywords must not contain any whitespace."
|
||||||
|
end
|
||||||
|
|
||||||
|
[keyword, command]
|
||||||
|
end
|
||||||
|
|
||||||
|
# This registers an alias.
|
||||||
|
def register(keyword, command)
|
||||||
|
@aliases.register(keyword.to_sym) do
|
||||||
|
lambda do |args|
|
||||||
|
# directly execute shell commands
|
||||||
|
if command.start_with?("!")
|
||||||
|
return Util::SafeExec.exec "#{command[1..-1]} #{args.join(" ")}".strip
|
||||||
|
end
|
||||||
|
|
||||||
|
return CLI.new(command.split.concat(args), @env).execute
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -28,6 +28,14 @@ module Vagrant
|
||||||
command_plugin = nil
|
command_plugin = nil
|
||||||
if @sub_command
|
if @sub_command
|
||||||
command_plugin = Vagrant.plugin("2").manager.commands[@sub_command.to_sym]
|
command_plugin = Vagrant.plugin("2").manager.commands[@sub_command.to_sym]
|
||||||
|
|
||||||
|
if !command_plugin
|
||||||
|
alias_command = Alias.new(@env).commands[@sub_command.to_sym]
|
||||||
|
|
||||||
|
if alias_command
|
||||||
|
return alias_command.call(@sub_args)
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if !command_plugin || !@sub_command
|
if !command_plugin || !@sub_command
|
||||||
|
|
|
@ -56,6 +56,9 @@ module Vagrant
|
||||||
# The directory where temporary files for Vagrant go.
|
# The directory where temporary files for Vagrant go.
|
||||||
attr_reader :tmp_path
|
attr_reader :tmp_path
|
||||||
|
|
||||||
|
# File where command line aliases go.
|
||||||
|
attr_reader :aliases_path
|
||||||
|
|
||||||
# The directory where boxes are stored.
|
# The directory where boxes are stored.
|
||||||
attr_reader :boxes_path
|
attr_reader :boxes_path
|
||||||
|
|
||||||
|
@ -124,6 +127,9 @@ module Vagrant
|
||||||
@tmp_path = @home_path.join("tmp")
|
@tmp_path = @home_path.join("tmp")
|
||||||
@machine_index_dir = @data_dir.join("machine-index")
|
@machine_index_dir = @data_dir.join("machine-index")
|
||||||
|
|
||||||
|
@aliases_path = Pathname.new(ENV["VAGRANT_ALIAS_FILE"]).expand_path if ENV.key?("VAGRANT_ALIAS_FILE")
|
||||||
|
@aliases_path ||= @home_path.join("aliases")
|
||||||
|
|
||||||
# Prepare the directories
|
# Prepare the directories
|
||||||
setup_home_path
|
setup_home_path
|
||||||
|
|
||||||
|
|
|
@ -108,6 +108,10 @@ module Vagrant
|
||||||
error_key(:active_machine_with_different_provider)
|
error_key(:active_machine_with_different_provider)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
class AliasInvalidError < VagrantError
|
||||||
|
error_key(:alias_invalid_error)
|
||||||
|
end
|
||||||
|
|
||||||
class BatchMultiError < VagrantError
|
class BatchMultiError < VagrantError
|
||||||
error_key(:batch_multi_error)
|
error_key(:batch_multi_error)
|
||||||
end
|
end
|
||||||
|
|
|
@ -402,6 +402,12 @@ en:
|
||||||
Machine name: %{name}
|
Machine name: %{name}
|
||||||
Active provider: %{active_provider}
|
Active provider: %{active_provider}
|
||||||
Requested provider: %{requested_provider}
|
Requested provider: %{requested_provider}
|
||||||
|
alias_invalid_error: |-
|
||||||
|
The defined alias is not valid. Please review the information below
|
||||||
|
to help resolve the issue:
|
||||||
|
|
||||||
|
Alias: %{alias}
|
||||||
|
Message: %{message}
|
||||||
batch_multi_error: |-
|
batch_multi_error: |-
|
||||||
An error occurred while executing multiple actions in parallel.
|
An error occurred while executing multiple actions in parallel.
|
||||||
Any errors that occurred are shown below.
|
Any errors that occurred are shown below.
|
||||||
|
|
|
@ -0,0 +1,68 @@
|
||||||
|
require_relative "../base"
|
||||||
|
|
||||||
|
require "vagrant/alias"
|
||||||
|
|
||||||
|
describe Vagrant::Alias do
|
||||||
|
include_context "unit"
|
||||||
|
include_context "command plugin helpers"
|
||||||
|
|
||||||
|
let(:iso_env) { isolated_environment }
|
||||||
|
let(:env) { iso_env.create_vagrant_env }
|
||||||
|
|
||||||
|
describe "#interpret" do
|
||||||
|
let(:interpreter) { described_class.new(env) }
|
||||||
|
|
||||||
|
it "returns nil for comments" do
|
||||||
|
comments = [
|
||||||
|
"# this is a comment",
|
||||||
|
"# so is this ",
|
||||||
|
" # and this",
|
||||||
|
" # this too "
|
||||||
|
]
|
||||||
|
|
||||||
|
comments.each do |comment|
|
||||||
|
expect(interpreter.interpret(comment)).to be_nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
it "raises an error on invalid keywords" do
|
||||||
|
keywords = [
|
||||||
|
"keyword with a space = command",
|
||||||
|
"keyword\twith a tab = command",
|
||||||
|
"keyword\nwith a newline = command",
|
||||||
|
]
|
||||||
|
|
||||||
|
keywords.each do |keyword|
|
||||||
|
expect { interpreter.interpret(keyword) }.to raise_error(Vagrant::Errors::AliasInvalidError)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
it "properly interprets a simple alias" do
|
||||||
|
keyword, command = interpreter.interpret("keyword=command")
|
||||||
|
|
||||||
|
expect(keyword).to eq("keyword")
|
||||||
|
expect(command).to eq("command")
|
||||||
|
end
|
||||||
|
|
||||||
|
it "properly interprets an alias with excess whitespace" do
|
||||||
|
keyword, command = interpreter.interpret(" keyword = command ")
|
||||||
|
|
||||||
|
expect(keyword).to eq("keyword")
|
||||||
|
expect(command).to eq("command")
|
||||||
|
end
|
||||||
|
|
||||||
|
it "properly interprets an alias with an equals sign in the command" do
|
||||||
|
keyword, command = interpreter.interpret(" keyword = command = command ")
|
||||||
|
|
||||||
|
expect(keyword).to eq("keyword")
|
||||||
|
expect(command).to eq("command = command")
|
||||||
|
end
|
||||||
|
|
||||||
|
it "allows keywords with non-alpha-numeric characters" do
|
||||||
|
keyword, command = interpreter.interpret("keyword! = command")
|
||||||
|
|
||||||
|
expect(keyword).to eq("keyword!")
|
||||||
|
expect(command).to eq("command")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,74 @@
|
||||||
|
---
|
||||||
|
layout: "docs"
|
||||||
|
page_title: "Aliases - Command-Line Interface"
|
||||||
|
sidebar_current: "cli-aliases"
|
||||||
|
description: |-
|
||||||
|
Custom Vagrant commands can be defined using aliases, allowing for a simpler,
|
||||||
|
easier, and more familiar command line interface.
|
||||||
|
---
|
||||||
|
|
||||||
|
# Aliases
|
||||||
|
|
||||||
|
Inspired in part by Git's own
|
||||||
|
[alias functionality](https://git-scm.com/book/en/v2/Git-Basics-Git-Aliases),
|
||||||
|
aliases make your Vagrant experience simpler, easier, and more familiar by
|
||||||
|
allowing you to create your own custom Vagrant commands.
|
||||||
|
|
||||||
|
Aliases can be defined within `VAGRANT_HOME/aliases` file, or in a custom file
|
||||||
|
defined using the `VAGRANT_ALIAS_FILE` environment variable, in the following
|
||||||
|
format:
|
||||||
|
|
||||||
|
```
|
||||||
|
# basic command-level aliases
|
||||||
|
start = up
|
||||||
|
stop = halt
|
||||||
|
|
||||||
|
# advanced command-line aliases
|
||||||
|
eradicate = !vagrant destroy && rm -rf .vagrant
|
||||||
|
```
|
||||||
|
|
||||||
|
In a nutshell, aliases are defined using a standard `key = value` format, where
|
||||||
|
the `key` is the new Vagrant command, and the `value` is the aliased command.
|
||||||
|
Using this format, there are two types of aliases that can be defined: internal
|
||||||
|
and external aliases.
|
||||||
|
|
||||||
|
## Internal Aliases
|
||||||
|
|
||||||
|
Internal command aliases call the CLI class directly, allowing you to alias
|
||||||
|
one Vagrant command to another Vagrant command. This technique can be very
|
||||||
|
useful for creating commands that you think _should_ exist. For example,
|
||||||
|
if `vagrant stop` feels more intuitive than `vagrant halt`, the following alias
|
||||||
|
definitions would make that change possible:
|
||||||
|
|
||||||
|
```
|
||||||
|
stop = halt
|
||||||
|
```
|
||||||
|
|
||||||
|
This makes the following commands equivalent:
|
||||||
|
|
||||||
|
```
|
||||||
|
vagrant stop
|
||||||
|
vagrant halt
|
||||||
|
```
|
||||||
|
|
||||||
|
## External Aliases
|
||||||
|
|
||||||
|
While internal aliases can be used to define more intuitive Vagrant commands,
|
||||||
|
external command aliases are used to define Vagrant commands with brand new
|
||||||
|
functionality. These aliases are prefixed with the `!` character, which
|
||||||
|
indicates to the interpreter that the alias should be executed as a shell
|
||||||
|
command. For example, let's say that you want to be able to view the processor
|
||||||
|
and memory utilization of the active project's virtual machine. To do this, you
|
||||||
|
could define a `vagrant metrics` command that returns the required information
|
||||||
|
in an easy-to-read format, like so:
|
||||||
|
|
||||||
|
```
|
||||||
|
metrics = !ps aux | grep "[V]BoxHeadless" | grep $(cat .vagrant/machines/default/virtualbox/id) | awk '{ printf("CPU: %.02f%%, Memory: %.02f%%", $3, $4) }'
|
||||||
|
```
|
||||||
|
|
||||||
|
The above alias, from within the context of an active Vagrant project, would
|
||||||
|
print the CPU and memory utilization directly to the console:
|
||||||
|
|
||||||
|
```
|
||||||
|
CPU: 4.20%, Memory: 11.00%
|
||||||
|
```
|
|
@ -14,6 +14,11 @@ Vagrant has a set of environmental variables that can be used to
|
||||||
configure and control it in a global way. This page lists those environmental
|
configure and control it in a global way. This page lists those environmental
|
||||||
variables.
|
variables.
|
||||||
|
|
||||||
|
## `VAGRANT_ALIAS_FILE`
|
||||||
|
|
||||||
|
`VAGRANT_ALIAS_FILE` can be set to change the file where Vagrant aliases are
|
||||||
|
defined. By default, this is set to `~/.vagrant.d/aliases`.
|
||||||
|
|
||||||
## `VAGRANT_DEBUG_LAUNCHER`
|
## `VAGRANT_DEBUG_LAUNCHER`
|
||||||
|
|
||||||
For performance reasons, especially for Windows users, Vagrant uses a static
|
For performance reasons, especially for Windows users, Vagrant uses a static
|
||||||
|
|
|
@ -44,6 +44,7 @@
|
||||||
<li<%= sidebar_current("cli-validate") %>><a href="/docs/cli/validate.html">validate</a></li>
|
<li<%= sidebar_current("cli-validate") %>><a href="/docs/cli/validate.html">validate</a></li>
|
||||||
<li<%= sidebar_current("cli-version") %>><a href="/docs/cli/version.html">version</a></li>
|
<li<%= sidebar_current("cli-version") %>><a href="/docs/cli/version.html">version</a></li>
|
||||||
<li<%= sidebar_current("cli-nonprimary") %>><a href="/docs/cli/non-primary.html">More Commands</a></li>
|
<li<%= sidebar_current("cli-nonprimary") %>><a href="/docs/cli/non-primary.html">More Commands</a></li>
|
||||||
|
<li<%= sidebar_current("cli-aliases") %>><a href="/docs/cli/aliases.html">Aliases</a></li>
|
||||||
<li<%= sidebar_current("cli-machinereadable") %>><a href="/docs/cli/machine-readable.html">Machine Readable Output</a></li>
|
<li<%= sidebar_current("cli-machinereadable") %>><a href="/docs/cli/machine-readable.html">Machine Readable Output</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
|
|
Loading…
Reference in New Issue