Merge pull request #10267 from briancain/ruby-trigger-option

Fixes #9840: Introduce `ruby` option for trigger
This commit is contained in:
Brian Cain 2018-10-08 09:02:17 -07:00 committed by GitHub
commit 5daa25db80
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 126 additions and 3 deletions

View File

@ -135,6 +135,10 @@ module Vagrant
if trigger.run_remote
run_remote(trigger.run_remote, trigger.on_error, trigger.exit_codes)
end
if trigger.ruby_block
execute_ruby(trigger.ruby_block)
end
end
end
@ -253,6 +257,13 @@ module Vagrant
@machine.ui.warn(I18n.t("vagrant.trigger.abort"))
exit(exit_code)
end
# Calls the given ruby block for execution
#
# @param [Proc] ruby_block
def execute_ruby(ruby_block)
ruby_block.call(@env, @machine)
end
end
end
end

View File

@ -78,6 +78,17 @@ module VagrantPlugins
# @return [Integer]
attr_accessor :abort
# Internal reader for the internal variable ruby_block
#
# @return [Proc]
attr_reader :ruby_block
# Variable used to store ruby proc when defining a ruby trigger
# with the "hash" syntax
#
# @return [Proc]
attr_accessor :ruby
def initialize(command)
@logger = Log4r::Logger.new("vagrant::config::vm::trigger::config")
@ -91,14 +102,26 @@ module VagrantPlugins
@run_remote = UNSET_VALUE
@exit_codes = UNSET_VALUE
@abort = UNSET_VALUE
@ruby = UNSET_VALUE
# Internal options
@id = SecureRandom.uuid
@command = command.to_sym
@ruby_block = UNSET_VALUE
@logger.debug("Trigger defined for command: #{command}")
end
# Config option `ruby` for a trigger which reads in a ruby block and sets
# it to be evaluated when the configured trigger fires. This method is only
# invoked when the regular "block" syntax is used. Otherwise the proc is
# set through the attr_accessor if the hash syntax is used.
#
# @param [Proc] block
def ruby(&block)
@ruby_block = block
end
def finalize!
# Ensure all config options are set to nil or default value if untouched
# by user
@ -113,7 +136,11 @@ module VagrantPlugins
@exit_codes = DEFAULT_EXIT_CODE if @exit_codes == UNSET_VALUE
@abort = nil if @abort == UNSET_VALUE
# these values are expected to always be an Array internally,
@ruby_block = nil if @ruby_block == UNSET_VALUE
@ruby = nil if @ruby == UNSET_VALUE
@ruby_block = @ruby if @ruby
# These values are expected to always be an Array internally,
# but can be set as a single String or Symbol
#
# Guests are stored internally as strings
@ -225,6 +252,10 @@ module VagrantPlugins
machine.ui.warn(I18n.t("vagrant.config.triggers.abort_false_type"))
end
if @ruby_block && !ruby_block.is_a?(Proc)
errors << I18n.t("vagrant.config.triggers.ruby_bad_type", cmd: @command)
end
errors
end

View File

@ -1781,6 +1781,9 @@ en:
only be a single integer or an array of integers.
only_on_bad_type: |-
Invalid type found for `only_on`. All values must be a `String` or `Regexp`.
ruby_bad_type: |-
Invalid type for `ruby` option on trigger for command '%{cmd}'. Only `proc`
types are allowed.
privileged_ignored: |-
The `privileged` setting for option `run` for trigger command '%{command}' will be ignored and set to false.
powershell_args_ignored: |-

View File

@ -37,6 +37,10 @@ describe VagrantPlugins::Kernel_V2::VagrantConfigTrigger do
subject.warn = "Warning!!"
subject.ignore = :up
subject.only_on = "guest"
subject.ruby do |env,machine|
var = 'test'
math = 1+1
end
subject.run = {inline: "apt-get update"}
subject.run_remote = {inline: "apt-get update", env: {"VAR"=>"VAL"}}
end
@ -67,6 +71,9 @@ describe VagrantPlugins::Kernel_V2::VagrantConfigTrigger do
cfg.only_on = :guest
cfg.ignore = "up"
cfg.abort = true
cfg.ruby do
var = 1+1
end
arr_cfg.only_on = ["guest", /other/]
arr_cfg.ignore = ["up", "destroy"]
end
@ -95,6 +102,11 @@ describe VagrantPlugins::Kernel_V2::VagrantConfigTrigger do
end
end
it "ensures ruby is a proc" do
cfg.finalize!
expect(cfg.ruby_block).to be_a(Proc)
end
it "converts aborts true to exit code 0" do
cfg.finalize!
@ -113,6 +125,7 @@ describe VagrantPlugins::Kernel_V2::VagrantConfigTrigger do
cfg.ignore = :up
cfg.abort = 3
cfg.only_on = "guest"
cfg.ruby = proc{ var = 1+1 }
cfg.run = {inline: "apt-get update"}
cfg.run_remote = {inline: "apt-get update", env: {"VAR"=>"VAL"}}
end
@ -127,7 +140,7 @@ describe VagrantPlugins::Kernel_V2::VagrantConfigTrigger do
expect(cfg.run).to be_a(VagrantPlugins::Shell::Config)
expect(cfg.run_remote).to be_a(VagrantPlugins::Shell::Config)
expect(cfg.abort).to eq(3)
expect(cfg.ruby_block).to be_a(Proc)
end
end
end

View File

@ -375,7 +375,6 @@ describe Vagrant::Plugin::V2::Trigger do
end
context "#trigger_abort" do
it "system exits when called" do
output = ""
allow(machine.ui).to receive(:warn) do |data|
@ -385,4 +384,20 @@ describe Vagrant::Plugin::V2::Trigger do
expect { subject.send(:trigger_abort, 3) }.to raise_error(SystemExit)
end
end
context "#ruby" do
let(:trigger_run) { VagrantPlugins::Kernel_V2::TriggerConfig.new }
let(:block) { proc{var = 1+1} }
let(:ruby_trigger) { {info: "hi", ruby: block} }
before do
trigger_run.after(:up, ruby_trigger)
trigger_run.finalize!
end
it "executes a ruby block" do
expect(block).to receive(:call)
subject.send(:execute_ruby, block)
end
end
end

View File

@ -34,6 +34,18 @@ The trigger class takes various options.
* `only_on` (string, regex, array) - Limit the trigger to these guests. Values can be a string or regex that matches a guest name.
* `ruby` (block) - A block of Ruby code to be executed. Can only be a `Proc` type. Two optional arguments may be passed into the given block: `env` and `machine`. These options correspond to the environment used, and the machine that the trigger is firing on. If no options are provided to the block, then they will not be available to be used with your Ruby code.
```ruby
ubuntu.trigger.after :up do |trigger|
trigger.info = "More information"
trigger.ruby do |env,machine|
greetings = "hello there #{machine.id}!"
puts greetings
end
end
```
* `run_remote` (hash) - A collection of settings to run a inline or remote script with on the guest. These settings correspond to the [shell provisioner](/docs/provisioning/shell.html).
* `run` (hash) - A collection of settings to run a inline or remote script on the host. These settings correspond to the [shell provisioner](/docs/provisioning/shell.html). However, at the moment the only settings `run` takes advantage of are:

View File

@ -93,3 +93,41 @@ end
Running `vagrant up` would fire the before trigger to start tinyproxy, where as
running either `vagrant destroy` or `vagrant halt` would stop tinyproxy.
### Ruby Option
Triggers can also be defined to run Ruby, rather than bash or powershell. An
example of this might be using a Ruby option to get more information from the `VBoxManage`
tool. In this case, we are printing the `ostype` defined for thte guest after
it has been brought up.
```ruby
Vagrant.configure("2") do |config|
config.vm.define "ubuntu" do |ubuntu|
ubuntu.vm.box = "ubuntu"
ubuntu.trigger.after :up do |trigger|
trigger.info = "More information with ruby magic"
trigger.ruby do |env,machine|
puts `VBoxManage showvminfo #{machine.id} --machinereadable | grep ostype`
end
end
end
end
```
If you are defining your triggers using the hash syntax, you must use the `Proc`
type for defining a ruby trigger.
```ruby
Vagrant.configure("2") do |config|
config.vm.define "ubuntu" do |ubuntu|
ubuntu.vm.box = "ubuntu"
ubuntu.trigger.after :up,
info: "More information with ruby magic",
ruby: proc{|env,machine| puts `VBoxManage showvminfo #{machine.id} --machinereadable | grep ostype`}
end
end
```