vagrant-triggers 0.4.4 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 82d8d42ba2873b8ff1d16d07b4415c7b408c0cfa
4
- data.tar.gz: 393eaa0899b5e070d5e8bcec79da77f1f19bd92b
3
+ metadata.gz: feda77ab141c553c1886766fd74d69ddfb0b2153
4
+ data.tar.gz: 0b73b4f744e7f5c0aec0a769eaa90629076c2c98
5
5
  SHA512:
6
- metadata.gz: 56647d8624db454ebb33e9c46a1e0199e7c38e9e818f7d88ce371aaf83e295e6a70a26b5ecb5e4d9cd224679ede171b7f7206d6cf781f39a3ea7382b3900ca49
7
- data.tar.gz: 2e4fea84758569ce2a2e114e0555922678223ae2bb8832768aef71bf8fd01e24bdb6c442fee84f0371a3dc6e610d970b76a77b457adde560f56dbe3d917d1f31
6
+ metadata.gz: 5ec60cd4c036eaedf2f64d9f5e63559d00dfc39d7a29eab6cd7e38b4de3a1d9d5acb4d0dc65d8ad02c2e5767d5c69c9ce22bacb610cf609084466edcad85a491
7
+ data.tar.gz: 8d05d7c3abf88ccabc6a93b2542183a36bfdfe9d7aea0abdba3e41c2fbfc047e8a3fbab2eafc61af1fc06165cdb2fc35a37978fcdaab5307bc9a2b0e7f80f370
data/.gitignore CHANGED
@@ -3,6 +3,8 @@
3
3
  .bundle
4
4
  pkg/*
5
5
  Gemfile.lock
6
+ Gemfile.dev
7
+ Gemfile.dev.lock
6
8
 
7
9
  coverage
8
10
 
data/.travis.yml CHANGED
@@ -7,11 +7,13 @@ before_install:
7
7
  - gem uninstall -ax bundler
8
8
  - gem install bundler -v 1.5.3
9
9
  env:
10
- - VAGRANT_VERSION=v1.6.5
10
+ - VAGRANT_VERSION=v1.7.1
11
11
  matrix:
12
12
  include:
13
13
  - env: VAGRANT_VERSION=master
14
14
  rvm: 2.0.0
15
+ - env: VAGRANT_VERSION=v1.6.5
16
+ rvm: 2.0.0
15
17
  - env: VAGRANT_VERSION=v1.5.4
16
18
  rvm: 2.0.0
17
19
  - env: VAGRANT_VERSION=v1.4.3
@@ -23,3 +25,4 @@ matrix:
23
25
  allow_failures:
24
26
  - env: VAGRANT_VERSION=master
25
27
  rvm: 2.0.0
28
+ sudo: false
data/CHANGELOG.md CHANGED
@@ -1,3 +1,24 @@
1
+ ## 0.5.0 (December 29, 2014)
2
+
3
+ **BEHAVIOURAL CHANGES:**
4
+
5
+ - The ```:stdout``` option now defaults to true.
6
+
7
+ NEW FEATURES:
8
+
9
+ - New option ```:stderr``` for displaying standard error from scripts.
10
+ - The special action ```:ALL``` can be used when a trigger should always run [(#23)](https://github.com/emyl/vagrant-triggers/issues/23)
11
+ - Actions can be blacklisted using ```config.trigger.blacklist```.
12
+ - Triggers can be run as a provisioner [(#21)](https://github.com/emyl/vagrant-triggers/issues/21)
13
+
14
+ IMPROVEMENTS:
15
+
16
+ - Do not buffer command output and better integrate in core UI [(#18)](https://github.com/emyl/vagrant-triggers/issues/18)
17
+
18
+ BUG FIXES:
19
+
20
+ - Handle MS-DOS commands better [(#27)](https://github.com/emyl/vagrant-triggers/issues/27)
21
+
1
22
  ## 0.4.4 (December 12, 2014)
2
23
 
3
24
  BUG FIXES:
data/README.md CHANGED
@@ -43,11 +43,27 @@ The ```instead_of``` trigger could also be aliased as ```reject```.
43
43
 
44
44
  The first argument is the command in which the trigger will be tied. It could be an array (e.g. ```[:up, :resume]```) in case of multiple commands.
45
45
 
46
+ Starting from version 0.5.0, triggers can also be run as a provisioner:
47
+
48
+ ```ruby
49
+ Vagrant.configure("2") do |config|
50
+ # Your existing Vagrant configuration
51
+ ...
52
+
53
+ config.vm.provision "trigger", :option => "value" do |trigger|
54
+ trigger.fire do
55
+ run "script"
56
+ end
57
+ end
58
+ end
59
+ ```
60
+
46
61
  ### Options
47
62
 
48
63
  * ```:append_to_path => ["dir", "dir"]```: additional places where looking for scripts. See [this wiki page](https://github.com/emyl/vagrant-triggers/wiki/The-:append_to_path-option) for details.
49
- * ```:force => true```: continue even if one of the scripts fails (exits with non-zero code)
50
- * ```:stdout => true```: display script output
64
+ * ```:force => true|false```: continue even if one of the scripts fails (exits with non-zero code). Defaults to false.
65
+ * ```:stderr => true|false```: display standard error from scripts. Defaults to true.
66
+ * ```:stdout => true|false```: display standard output from scripts. Defaults to true.
51
67
  * ```:vm => ["vm1", /vm[2-3]/]```: fire only for matching virtual machines. Value can be a string, a regexp or an array of strings and/or regexps.
52
68
 
53
69
  ### Trigger block DSL
@@ -109,6 +125,3 @@ To run the plugin's tests:
109
125
  $ bundle exec rake
110
126
 
111
127
  You can now fork this repository, make your changes and send a pull request.
112
-
113
-
114
- [![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/emyl/vagrant-triggers/trend.png)](https://bitdeli.com/free "Bitdeli Badge")
@@ -4,10 +4,11 @@ require "vagrant-triggers/plugin"
4
4
  module VagrantPlugins
5
5
  module Triggers
6
6
  lib_path = Pathname.new(File.expand_path("../vagrant-triggers", __FILE__))
7
- autoload :Action, lib_path.join("action")
8
- autoload :DSL, lib_path.join("dsl")
9
- autoload :Config, lib_path.join("config")
10
- autoload :Errors, lib_path.join("errors")
7
+ autoload :Action, lib_path.join("action")
8
+ autoload :DSL, lib_path.join("dsl")
9
+ autoload :Config, lib_path.join("config")
10
+ autoload :Errors, lib_path.join("errors")
11
+ autoload :Provisioner, lib_path.join("provisioner")
11
12
 
12
13
  # This returns the path to the source of this plugin.
13
14
  #
@@ -31,18 +31,13 @@ module VagrantPlugins
31
31
  trigger_env.each { |k, v| @logger.debug("-- #{k}: #{v}")}
32
32
 
33
33
  # Loop through all defined triggers checking for matches.
34
+ triggers_config = @env[:machine].config.trigger
34
35
  triggers_to_fire = [].tap do |triggers|
35
- @env[:machine].config.trigger.triggers.each do |trigger|
36
- next if trigger[:action] != trigger_env[:action]
36
+ triggers_config.triggers.each do |trigger|
37
+ next if trigger[:action] != :ALL && trigger[:action] != trigger_env[:action]
37
38
  next if trigger[:condition] != trigger_env[:condition]
38
39
 
39
- if trigger[:options][:vm]
40
- match = false
41
- Array(trigger[:options][:vm]).each do |pattern|
42
- match = true if trigger_env[:vm].match(Regexp.new(pattern))
43
- end
44
- next unless match
45
- end
40
+ next if triggers_config.blacklist.include?(trigger_env[:action])
46
41
 
47
42
  triggers << trigger
48
43
  end
@@ -55,8 +50,11 @@ module VagrantPlugins
55
50
 
56
51
  triggers_to_fire.each do |trigger|
57
52
  if trigger[:proc]
58
- dsl = DSL.new(@env[:ui], @env[:machine], trigger[:options])
59
- dsl.instance_eval &trigger[:proc]
53
+ begin
54
+ dsl = DSL.new(@env[:machine], trigger[:options])
55
+ dsl.instance_eval &trigger[:proc]
56
+ rescue Errors::NotMatchingMachine
57
+ end
60
58
  else
61
59
  @logger.debug("Trigger command not found.")
62
60
  end
@@ -1,48 +1,10 @@
1
1
  module VagrantPlugins
2
2
  module Triggers
3
- class Config < Vagrant.plugin("2", :config)
4
- attr_reader :triggers
5
-
6
- def initialize
7
- @triggers = []
8
- end
9
-
10
- def after(actions, options = {}, &block)
11
- add_trigger(actions, :after, options, block)
12
- end
13
-
14
- def before(actions, options = {}, &block)
15
- add_trigger(actions, :before, options, block)
16
- end
17
-
18
- def instead_of(actions, options = {}, &block)
19
- add_trigger(actions, :instead_of, options, block)
20
- end
21
- alias_method :reject, :instead_of
22
-
23
- def merge(other)
24
- super.tap do |result|
25
- result.instance_variable_set(:@triggers, @triggers + other.triggers)
26
- end
27
- end
28
-
29
- def validate(machine)
30
- errors = []
31
-
32
- if @__invalid_methods && !@__invalid_methods.empty?
33
- errors << I18n.t("vagrant.config.common.bad_field", :fields => @__invalid_methods.to_a.sort.join(", "))
34
- end
35
-
36
- { "triggers" => errors }
37
- end
38
-
39
- private
40
-
41
- def add_trigger(actions, condition, options, proc)
42
- Array(actions).each do |action|
43
- @triggers << { :action => action, :condition => condition, :options => options, :proc => proc }
44
- end
45
- end
3
+ module Config
4
+ # Autoload farm
5
+ config_root = Pathname.new(File.expand_path("../config", __FILE__))
6
+ autoload :Provisioner, config_root.join("provisioner")
7
+ autoload :Trigger, config_root.join("trigger")
46
8
  end
47
9
  end
48
10
  end
@@ -0,0 +1,22 @@
1
+ module VagrantPlugins
2
+ module Triggers
3
+ module Config
4
+ class Provisioner < Vagrant.plugin("2", :config)
5
+ attr_reader :options
6
+ attr_reader :trigger_body
7
+
8
+ def initialize
9
+ @options = {}
10
+ end
11
+
12
+ def fire(&block)
13
+ @trigger_body = block
14
+ end
15
+
16
+ def set_options(options)
17
+ @options = options
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,61 @@
1
+ module VagrantPlugins
2
+ module Triggers
3
+ module Config
4
+ class Trigger < Vagrant.plugin("2", :config)
5
+ attr_reader :triggers
6
+
7
+ def initialize
8
+ @blacklist = []
9
+ @options = { :stdout => true, :stderr => true }
10
+ @triggers = []
11
+ end
12
+
13
+ def after(actions, options = {}, &block)
14
+ add_trigger(actions, :after, options, block)
15
+ end
16
+
17
+ def before(actions, options = {}, &block)
18
+ add_trigger(actions, :before, options, block)
19
+ end
20
+
21
+ def blacklist(actions = nil)
22
+ if actions
23
+ Array(actions).each { |action| @blacklist << action.to_s }
24
+ @blacklist.uniq!
25
+ end
26
+ @blacklist
27
+ end
28
+
29
+ def instead_of(actions, options = {}, &block)
30
+ add_trigger(actions, :instead_of, options, block)
31
+ end
32
+ alias_method :reject, :instead_of
33
+
34
+ def merge(other)
35
+ super.tap do |result|
36
+ result.instance_variable_set(:@blacklist, @blacklist + other.blacklist)
37
+ result.instance_variable_set(:@triggers, @triggers + other.triggers)
38
+ end
39
+ end
40
+
41
+ def validate(machine)
42
+ errors = []
43
+
44
+ if @__invalid_methods && !@__invalid_methods.empty?
45
+ errors << I18n.t("vagrant.config.common.bad_field", :fields => @__invalid_methods.to_a.sort.join(", "))
46
+ end
47
+
48
+ { "triggers" => errors }
49
+ end
50
+
51
+ private
52
+
53
+ def add_trigger(actions, condition, options, proc)
54
+ Array(actions).each do |action|
55
+ @triggers << { :action => action, :condition => condition, :options => @options.merge(options), :proc => proc }
56
+ end
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end
@@ -1,16 +1,30 @@
1
1
  require "bundler"
2
2
  require "log4r"
3
- require "shellwords"
4
3
  require "vagrant/util/subprocess"
5
4
 
6
5
  module VagrantPlugins
7
6
  module Triggers
8
7
  class DSL
9
- def initialize(ui, machine, options = {})
8
+ def initialize(machine, options = {})
9
+ if options[:vm]
10
+ match = false
11
+ Array(options[:vm]).each do |pattern|
12
+ match = true if machine.name.match(Regexp.new(pattern))
13
+ end
14
+ raise Errors::NotMatchingMachine unless match
15
+ end
16
+
17
+ @buffer = Hash.new("")
10
18
  @logger = Log4r::Logger.new("vagrant::plugins::triggers::dsl")
11
19
  @machine = machine
12
20
  @options = options
13
- @ui = ui
21
+ @ui = machine.ui
22
+
23
+ @command_output = lambda do |channel, data, options|
24
+ ui_method = (channel == :stdout) ? :info : :error
25
+ @buffer[channel] += data
26
+ @ui.send(ui_method, data) if options[channel]
27
+ end
14
28
  end
15
29
 
16
30
  def error(message, *opts)
@@ -18,36 +32,38 @@ module VagrantPlugins
18
32
  end
19
33
 
20
34
  def run(raw_command, options = {})
21
- info I18n.t("vagrant_triggers.action.trigger.executing_command", :command => raw_command)
22
- command = Shellwords.shellsplit(raw_command)
35
+ command = shellsplit(raw_command)
36
+ options.merge!(@options) { |key, old, new| old }
37
+ info I18n.t("vagrant_triggers.action.trigger.executing_command", :command => command.join(" "))
23
38
  env_backup = ENV.to_hash
24
39
  begin
25
40
  result = nil
26
41
  Bundler.with_clean_env do
27
42
  build_environment
28
- result = Vagrant::Util::Subprocess.execute(command[0], *command[1..-1])
43
+ @buffer.clear
44
+ result = Vagrant::Util::Subprocess.execute(command[0], *command[1..-1], :notify => [:stdout, :stderr]) do |channel, data|
45
+ @command_output.call(channel, data, options)
46
+ end
29
47
  end
48
+ info I18n.t("vagrant_triggers.action.trigger.command_finished")
30
49
  rescue Vagrant::Errors::CommandUnavailable, Vagrant::Errors::CommandUnavailableWindows
31
50
  raise Errors::CommandUnavailable, :command => command[0]
32
51
  ensure
33
52
  ENV.replace(env_backup)
34
53
  end
35
- process_result(raw_command, result, @options.merge(options))
54
+ process_result(raw_command, result, options)
36
55
  end
37
56
  alias_method :execute, :run
38
57
 
39
58
  def run_remote(raw_command, options = {})
59
+ options.merge!(@options) { |key, old, new| old }
40
60
  info I18n.t("vagrant_triggers.action.trigger.executing_remote_command", :command => raw_command)
41
- stderr = ""
42
- stdout = ""
43
- exit_code = @machine.communicate.sudo(raw_command, :elevated => true, :good_exit => (0..255).to_a) do |type, data|
44
- if type == :stderr
45
- stderr += data
46
- elsif type == :stdout
47
- stdout += data
48
- end
61
+ @buffer.clear
62
+ exit_code = @machine.communicate.sudo(raw_command, :elevated => true, :good_exit => (0..255).to_a) do |channel, data|
63
+ @command_output.call(channel, data, options)
49
64
  end
50
- process_result(raw_command, Vagrant::Util::Subprocess::Result.new(exit_code, stdout, stderr), @options.merge(options))
65
+ info I18n.t("vagrant_triggers.action.trigger.remote_command_finished")
66
+ process_result(raw_command, Vagrant::Util::Subprocess::Result.new(exit_code, @buffer[:stdout], @buffer[:stderr]), options)
51
67
  end
52
68
  alias_method :execute_remote, :run_remote
53
69
 
@@ -84,11 +100,27 @@ module VagrantPlugins
84
100
  if result.exit_code != 0 && !options[:force]
85
101
  raise Errors::CommandFailed, :command => command, :stderr => result.stderr
86
102
  end
87
- if options[:stdout]
88
- info I18n.t("vagrant_triggers.action.trigger.command_output", :output => result.stdout)
89
- end
90
103
  result.stdout
91
104
  end
105
+
106
+ # This is a custom version of Shellwords.shellsplit adapted for handling MS-DOS commands.
107
+ #
108
+ # Basically escape sequences are left intact if the platform is Windows.
109
+ def shellsplit(line)
110
+ words = []
111
+ field = ''
112
+ line.scan(/\G\s*(?>([^\s\\\'\"]+)|'([^\']*)'|"((?:[^\"\\]|\\.)*)"|(\\.?)|(\S))(\s|\z)?/) do |word, sq, dq, esc, garbage, sep|
113
+ raise ArgumentError, "Unmatched double quote: #{line.inspect}" if garbage
114
+ token = (word || sq || (dq || esc))
115
+ token.gsub!(/\\(.)/, '\1') unless Vagrant::Util::Platform.windows?
116
+ field << token
117
+ if sep
118
+ words << field
119
+ field = ''
120
+ end
121
+ end
122
+ words
123
+ end
92
124
  end
93
125
  end
94
126
  end
@@ -16,6 +16,9 @@ module VagrantPlugins
16
16
  class DSLError < VagrantTriggerError
17
17
  error_key(:dsl_error)
18
18
  end
19
+
20
+ class NotMatchingMachine < VagrantTriggerError
21
+ end
19
22
  end
20
23
  end
21
24
  end
@@ -34,12 +34,22 @@ module VagrantPlugins
34
34
  end
35
35
 
36
36
  config(:trigger) do
37
- require_relative "config"
38
- Config
37
+ require_relative "config/trigger"
38
+ Config::Trigger
39
+ end
40
+
41
+ config(:trigger, :provisioner) do
42
+ require_relative "config/provisioner"
43
+ Config::Provisioner
44
+ end
45
+
46
+ provisioner(:trigger) do
47
+ require_relative "provisioner"
48
+ Provisioner
39
49
  end
40
50
 
41
51
  # This initializes the I18n load path so that the plugin specific
42
- # transations work.
52
+ # translations work.
43
53
  def self.init_i18n
44
54
  I18n.load_path << File.expand_path("locales/en.yml", Triggers.source_root)
45
55
  I18n.reload!
@@ -0,0 +1,26 @@
1
+ module VagrantPlugins
2
+ module Triggers
3
+ class Provisioner < Vagrant.plugin("2", :provisioner)
4
+ def initialize(machine, config)
5
+ @config = config
6
+ begin
7
+ @dsl = DSL.new(machine, @config.options)
8
+ rescue Errors::NotMatchingMachine
9
+ ENV["VAGRANT_NO_TRIGGERS"] = "1"
10
+ end
11
+ end
12
+
13
+ def configure(root_config)
14
+ end
15
+
16
+ def provision
17
+ unless ENV["VAGRANT_NO_TRIGGERS"]
18
+ @dsl.instance_eval &@config.trigger_body
19
+ end
20
+ end
21
+
22
+ def cleanup
23
+ end
24
+ end
25
+ end
26
+ end
@@ -1,5 +1,5 @@
1
1
  module VagrantPlugins
2
2
  module Triggers
3
- VERSION = "0.4.4"
3
+ VERSION = "0.5.0"
4
4
  end
5
5
  end
data/locales/en.yml CHANGED
@@ -2,15 +2,14 @@ en:
2
2
  vagrant_triggers:
3
3
  action:
4
4
  trigger:
5
- command_output: |-
6
- Command output:
7
- ---------------
8
- %{output}
9
- ---------------
5
+ command_finished: |-
6
+ Command execution finished.
10
7
  executing_command: |-
11
8
  Executing command "%{command}"...
12
9
  executing_remote_command: |-
13
10
  Executing remote command "%{command}"...
11
+ remote_command_finished: |-
12
+ Remote command execution finished.
14
13
  running_triggers: |-
15
14
  Running triggers %{condition} %{action}...
16
15
  errors:
data/spec/spec_helper.rb CHANGED
@@ -5,3 +5,9 @@ require "vagrant"
5
5
  require_relative "../lib/vagrant-triggers"
6
6
 
7
7
  VagrantPlugins::Triggers::Plugin.init_i18n
8
+
9
+ RSpec.configure do |config|
10
+ config.mock_with :rspec do |mocks|
11
+ mocks.syntax = :should
12
+ end
13
+ end
@@ -5,16 +5,17 @@ describe VagrantPlugins::Triggers::Action::Trigger do
5
5
  let(:env) { { :action_name => action_name, :machine => machine, :machine_action => machine_action, :ui => ui } }
6
6
  let(:condition) { double("condition") }
7
7
  let(:action_name) { double("action_name") }
8
- let(:machine) { double("machine") }
8
+ let(:machine) { double("machine", :ui => ui) }
9
9
  let(:machine_action) { double("machine_action") }
10
10
 
11
11
  let(:ui) { double("ui", :info => info) }
12
12
  let(:info) { double("info") }
13
13
 
14
- before do
14
+ before :each do
15
15
  trigger_block = Proc.new { nil }
16
16
  @triggers = [ { :action => machine_action, :condition => condition, :options => { }, :proc => trigger_block } ]
17
17
  machine.stub(:name)
18
+ machine.stub_chain(:config, :trigger, :blacklist).and_return([])
18
19
  machine.stub_chain(:config, :trigger, :triggers).and_return(@triggers)
19
20
  end
20
21
 
@@ -35,7 +36,15 @@ describe VagrantPlugins::Triggers::Action::Trigger do
35
36
 
36
37
  it "should fire trigger when all conditions are satisfied" do
37
38
  dsl = double("dsl")
38
- VagrantPlugins::Triggers::DSL.stub(:new).with(ui, machine, @triggers.first[:options]).and_return(dsl)
39
+ VagrantPlugins::Triggers::DSL.stub(:new).with(machine, @triggers.first[:options]).and_return(dsl)
40
+ dsl.should_receive(:instance_eval).and_yield
41
+ described_class.new(app, env, condition).call(env)
42
+ end
43
+
44
+ it "should fire trigger when condition matches and action is :ALL" do
45
+ @triggers[0][:action] = :ALL
46
+ dsl = double("dsl")
47
+ VagrantPlugins::Triggers::DSL.stub(:new).with(machine, @triggers.first[:options]).and_return(dsl)
39
48
  dsl.should_receive(:instance_eval).and_yield
40
49
  described_class.new(app, env, condition).call(env)
41
50
  end
@@ -52,14 +61,20 @@ describe VagrantPlugins::Triggers::Action::Trigger do
52
61
  described_class.new(app, env, condition).call(env)
53
62
  end
54
63
 
64
+ it "shouldn't fire trigger when the action is blacklisted" do
65
+ machine.stub_chain(:config, :trigger, :blacklist).and_return([machine_action])
66
+ VagrantPlugins::Triggers::DSL.should_not_receive(:new)
67
+ described_class.new(app, env, condition).call(env)
68
+ end
69
+
55
70
  it "shouldn't fire trigger when condition doesn't match" do
56
- @triggers[0][:condition] = "blah"
71
+ @triggers[0][:condition] = :blah
57
72
  VagrantPlugins::Triggers::DSL.should_not_receive(:new)
58
73
  described_class.new(app, env, condition).call(env)
59
74
  end
60
75
 
61
76
  it "shouldn't fire trigger when action doesn't match" do
62
- @triggers[0][:action] = "blah"
77
+ @triggers[0][:action] = :blah
63
78
  VagrantPlugins::Triggers::DSL.should_not_receive(:new)
64
79
  described_class.new(app, env, condition).call(env)
65
80
  end
@@ -70,45 +85,8 @@ describe VagrantPlugins::Triggers::Action::Trigger do
70
85
  described_class.new(app, env, :instead_of).call(env)
71
86
  end
72
87
 
73
- context ":vm option" do
74
- before do
75
- machine.stub(:name).and_return(:vm1)
76
- end
77
-
78
- it "should fire trigger when :vm option match" do
79
- @triggers[0][:options][:vm] = "vm1"
80
- VagrantPlugins::Triggers::DSL.should_receive(:new)
81
- described_class.new(app, env, condition).call(env)
82
- end
83
-
84
- it "shouldn't fire trigger when :vm option doesn't match" do
85
- @triggers[0][:options][:vm] = "vm2"
86
- VagrantPlugins::Triggers::DSL.should_not_receive(:new)
87
- described_class.new(app, env, condition).call(env)
88
- end
89
-
90
- it "should fire trigger when :vm option is an array and one of the elements match" do
91
- @triggers[0][:options][:vm] = ["vm1", "vm2"]
92
- VagrantPlugins::Triggers::DSL.should_receive(:new)
93
- described_class.new(app, env, condition).call(env)
94
- end
95
-
96
- it "shouldn't fire trigger when :vm option is an array and no element match" do
97
- @triggers[0][:options][:vm] = ["vm2", "vm3"]
98
- VagrantPlugins::Triggers::DSL.should_not_receive(:new)
99
- described_class.new(app, env, condition).call(env)
100
- end
101
-
102
- it "should fire trigger when :vm option is a regex and the pattern match" do
103
- @triggers[0][:options][:vm] = /^vm/
104
- VagrantPlugins::Triggers::DSL.should_receive(:new)
105
- described_class.new(app, env, condition).call(env)
106
- end
107
-
108
- it "shouldn't fire trigger when :vm option is a regex and the pattern doesn't match" do
109
- @triggers[0][:options][:vm] = /staging/
110
- VagrantPlugins::Triggers::DSL.should_not_receive(:new)
111
- described_class.new(app, env, condition).call(env)
112
- end
88
+ it "should handle gracefully a not matching :vm option" do
89
+ VagrantPlugins::Triggers::DSL.stub(:new).and_raise(VagrantPlugins::Triggers::Errors::NotMatchingMachine)
90
+ expect { described_class.new(app, env, condition).call(env) }.not_to raise_exception()
113
91
  end
114
92
  end
@@ -0,0 +1,21 @@
1
+ require "spec_helper"
2
+
3
+ describe VagrantPlugins::Triggers::Config::Provisioner do
4
+ let(:config) { described_class.new }
5
+
6
+ describe "fire" do
7
+ it "should record trigger code" do
8
+ code = Proc.new { "foo" }
9
+ config.fire(&code)
10
+ expect(config.trigger_body).to eq(code)
11
+ end
12
+ end
13
+
14
+ describe "set_options" do
15
+ it "should set options" do
16
+ options = { :foo => "bar", :baz => "bat" }
17
+ config.set_options(options)
18
+ expect(config.options).to eq(options)
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,95 @@
1
+ require "spec_helper"
2
+
3
+ describe VagrantPlugins::Triggers::Config::Trigger do
4
+ let(:config) { described_class.new }
5
+ let(:machine) { double("machine") }
6
+
7
+ describe "defaults" do
8
+ subject do
9
+ config.tap do |o|
10
+ o.finalize!
11
+ end
12
+ expect(config.triggers).to eq([])
13
+ end
14
+
15
+ it "should default :stdout option to true" do
16
+ config.before(:up) { run "ls" }
17
+ expect(config.triggers.first[:options][:stdout]).to eq(true)
18
+ end
19
+
20
+ it "should default :stderr option to true" do
21
+ config.before(:up) { run "ls" }
22
+ expect(config.triggers.first[:options][:stderr]).to eq(true)
23
+ end
24
+
25
+ it "should override options" do
26
+ config.before(:up, :stdout => false) { run "ls" }
27
+ expect(config.triggers.first[:options][:stdout]).to eq(false)
28
+ end
29
+ end
30
+
31
+ describe "add triggers" do
32
+ it "should add before triggers" do
33
+ config.before(:up) { run "ls" }
34
+ expect(config.triggers.size).to eq(1)
35
+ end
36
+
37
+ it "should add instead_of triggers" do
38
+ config.instead_of(:up) { run "ls" }
39
+ expect(config.triggers.size).to eq(1)
40
+ end
41
+
42
+ it "should add after triggers" do
43
+ config.after(:up) { run "ls" }
44
+ expect(config.triggers.size).to eq(1)
45
+ end
46
+ end
47
+
48
+ describe "blacklist" do
49
+ it "should blacklist an action" do
50
+ config.blacklist(:up)
51
+ expect(config.blacklist.size).to eq(1)
52
+ end
53
+
54
+ it "should blacklist multiple actions" do
55
+ config.blacklist([:up, :destroy])
56
+ expect(config.blacklist.size).to eq(2)
57
+ end
58
+
59
+ it "should convert symbols to strings" do
60
+ config.blacklist(:up)
61
+ expect(config.blacklist).to eq(["up"])
62
+ end
63
+
64
+ it "should blacklist an action only once" do
65
+ config.blacklist(["up", "destroy"])
66
+ config.blacklist(:up)
67
+ expect(config.blacklist).to eq(["up", "destroy"])
68
+ end
69
+ end
70
+
71
+ describe "accept multiple entries" do
72
+ it "should record multiple entries" do
73
+ config.before(:up) { run "ls" }
74
+ config.after(:up) { run "ls" }
75
+ expect(config.triggers.size).to eq(2)
76
+ end
77
+
78
+ it "should record multiple entries if the action is an array" do
79
+ config.before([:up, :halt]) { run "ls" }
80
+ expect(config.triggers.size).to eq(2)
81
+ end
82
+ end
83
+
84
+ describe "validation" do
85
+ it "should validate" do
86
+ config.finalize!
87
+ expect(config.validate(machine)["triggers"].size).to eq(0)
88
+ end
89
+
90
+ it "shouldn't accept invalid methods" do
91
+ config.foo "bar"
92
+ expect(config.validate(machine)["triggers"].size).to eq(1)
93
+ end
94
+ end
95
+ end
@@ -5,17 +5,53 @@ describe VagrantPlugins::Triggers::DSL do
5
5
  let(:result) { double("result", :exit_code => 0, :stderr => stderr) }
6
6
  let(:stderr) { double("stderr") }
7
7
 
8
- let(:machine) { double("machine") }
8
+ let(:machine) { double("machine", :ui => ui) }
9
9
  let(:ui) { double("ui", :info => info) }
10
10
  let(:info) { double("info") }
11
11
 
12
12
  before do
13
13
  @command = "foo"
14
- @dsl = described_class.new(ui, machine, {})
14
+ @dsl = described_class.new(machine, {})
15
15
 
16
16
  result.stub(:stdout => "Some output")
17
17
  end
18
18
 
19
+ context ":vm option" do
20
+ before do
21
+ machine.stub(:name => :vm1)
22
+ end
23
+
24
+ it "should raise no exception when :vm option match" do
25
+ options = { :vm => "vm1" }
26
+ expect { described_class.new(machine, options) }.not_to raise_error()
27
+ end
28
+
29
+ it "should raise NotMatchingMachine when :vm option doesn't match" do
30
+ options = { :vm => "vm2" }
31
+ expect { described_class.new(machine, options) }.to raise_error(VagrantPlugins::Triggers::Errors::NotMatchingMachine)
32
+ end
33
+
34
+ it "should raise no exception when :vm option is an array and one of the elements match" do
35
+ options = { :vm => ["vm1", "vm2"] }
36
+ expect { described_class.new(machine, options) }.not_to raise_error()
37
+ end
38
+
39
+ it "should raise NotMatchingMachine when :vm option is an array and no element match" do
40
+ options = { :vm => ["vm2", "vm3"] }
41
+ expect { described_class.new(machine, options) }.to raise_error(VagrantPlugins::Triggers::Errors::NotMatchingMachine)
42
+ end
43
+
44
+ it "should raise no exception when :vm option is a regex and the pattern match" do
45
+ options = { :vm => /^vm/ }
46
+ expect { described_class.new(machine, options) }.not_to raise_error()
47
+ end
48
+
49
+ it "should raise NotMatchingMachine when :vm option is a regex and the pattern doesn't match" do
50
+ options = { :vm => /staging/ }
51
+ expect { described_class.new(machine, options) }.to raise_error(VagrantPlugins::Triggers::Errors::NotMatchingMachine)
52
+ end
53
+ end
54
+
19
55
  context "error" do
20
56
  it "should raise a DSL error on UI error" do
21
57
  ui.should_receive(:error).with("Error message")
@@ -33,6 +69,7 @@ describe VagrantPlugins::Triggers::DSL do
33
69
  context "run a regular command" do
34
70
  before do
35
71
  Vagrant::Util::Subprocess.stub(:execute => result)
72
+ @options = { :notify => [:stdout, :stderr] }
36
73
  end
37
74
 
38
75
  it "should raise an error if executed command exits with non-zero code" do
@@ -41,15 +78,14 @@ describe VagrantPlugins::Triggers::DSL do
41
78
  end
42
79
 
43
80
  it "shouldn't raise an error if executed command exits with non-zero code but :force option was specified" do
44
- dsl = described_class.new(ui, machine, :force => true)
81
+ dsl = described_class.new(machine, :force => true)
45
82
  result.stub(:exit_code => 1)
46
83
  expect { dsl.run(@command) }.not_to raise_error()
47
84
  end
48
85
 
49
- it "should display output if :stdout option was specified" do
50
- dsl = described_class.new(ui, machine, :stdout => true)
51
- ui.should_receive(:info).with(/Some output/)
52
- dsl.run(@command)
86
+ it "should return standard output" do
87
+ dsl = described_class.new(machine)
88
+ expect(dsl.run(@command)).to eq("Some output")
53
89
  end
54
90
 
55
91
  it "should pass VAGRANT_NO_TRIGGERS environment variable to the command" do
@@ -59,6 +95,19 @@ describe VagrantPlugins::Triggers::DSL do
59
95
  end
60
96
  @dsl.run(@command)
61
97
  end
98
+
99
+ it "should remove escape sequences on UNIX Bourne Shell" do
100
+ command = "echo foo\\ bar"
101
+ Vagrant::Util::Subprocess.should_receive(:execute).with("echo", "foo bar", @options)
102
+ @dsl.run(command)
103
+ end
104
+
105
+ it "should not remove escape sequences on MS-DOS Shell" do
106
+ Vagrant::Util::Platform.stub(:windows? => true)
107
+ command = "echo foo\\ bar"
108
+ Vagrant::Util::Subprocess.should_receive(:execute).with("echo", "foo\\ bar", @options)
109
+ @dsl.run(command)
110
+ end
62
111
  end
63
112
 
64
113
  context "run a command not in the PATH" do
@@ -83,14 +132,14 @@ describe VagrantPlugins::Triggers::DSL do
83
132
  end
84
133
 
85
134
  it "should honor the :append_to_path option and restore original path after execution" do
86
- dsl = described_class.new(ui, machine, :append_to_path => @tmp_dir)
135
+ dsl = described_class.new(machine, :append_to_path => @tmp_dir)
87
136
  original_path = ENV["PATH"]
88
137
  dsl.run(@command)
89
138
  expect(ENV["PATH"]).to eq(original_path)
90
139
  end
91
140
 
92
141
  it "should accept an array for the :append_to_path option" do
93
- dsl = described_class.new(ui, machine, :append_to_path => [@tmp_dir, @tmp_dir])
142
+ dsl = described_class.new(machine, :append_to_path => [@tmp_dir, @tmp_dir])
94
143
  expect { dsl.run(@command) }.not_to raise_error()
95
144
  end
96
145
  end
@@ -162,15 +211,14 @@ describe VagrantPlugins::Triggers::DSL do
162
211
  end
163
212
 
164
213
  it "shouldn't raise an error if executed command exits with non-zero code but :force option was specified" do
165
- dsl = described_class.new(ui, machine, :force => true)
214
+ dsl = described_class.new(machine, :force => true)
166
215
  result.stub(:exit_code => 1)
167
216
  expect { dsl.run_remote(@command) }.not_to raise_error()
168
217
  end
169
218
 
170
- it "should display output if :stdout option was specified" do
171
- dsl = described_class.new(ui, machine, :stdout => true)
172
- ui.should_receive(:info).with(/Some output/)
173
- dsl.run_remote(@command)
219
+ it "should return standard output" do
220
+ dsl = described_class.new(machine)
221
+ expect(dsl.run_remote(@command)).to eq("Some output")
174
222
  end
175
223
  end
176
224
  end
@@ -0,0 +1,41 @@
1
+ require "spec_helper"
2
+
3
+ describe VagrantPlugins::Triggers::Provisioner do
4
+ let(:config) { double("config", :options => options, :trigger_body => Proc.new { "foo" }) }
5
+ let(:machine) { double("machine") }
6
+ let(:options) { double("options") }
7
+
8
+ before :each do
9
+ ENV["VAGRANT_NO_TRIGGERS"] = nil
10
+ end
11
+
12
+ describe "constructor" do
13
+ it "should create a DSL object" do
14
+ VagrantPlugins::Triggers::DSL.should_receive(:new).with(machine, options)
15
+ described_class.new(machine, config)
16
+ end
17
+
18
+ it "should handle gracefully a not matching :vm option" do
19
+ VagrantPlugins::Triggers::DSL.stub(:new).and_raise(VagrantPlugins::Triggers::Errors::NotMatchingMachine)
20
+ expect { described_class.new(machine, config) }.not_to raise_exception()
21
+ end
22
+ end
23
+
24
+ describe "provision" do
25
+ before :each do
26
+ @dsl = double("dsl")
27
+ VagrantPlugins::Triggers::DSL.stub(:new).with(machine, options).and_return(@dsl)
28
+ end
29
+
30
+ it "should run code against DSL object" do
31
+ @dsl.should_receive(:instance_eval).and_yield
32
+ described_class.new(machine, config).provision
33
+ end
34
+
35
+ it "should not run code if VAGRANT_NO_TRIGGERS is set" do
36
+ ENV["VAGRANT_NO_TRIGGERS"] = "1"
37
+ @dsl.should_not_receive(:instance_eval)
38
+ described_class.new(machine, config).provision
39
+ end
40
+ end
41
+ end
@@ -51,5 +51,5 @@ Gem::Specification.new do |spec|
51
51
  spec.add_dependency "bundler", "~> 1.3"
52
52
 
53
53
  spec.add_development_dependency "rake"
54
- spec.add_development_dependency "rspec", "< 3"
54
+ spec.add_development_dependency "rspec"
55
55
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: vagrant-triggers
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.4
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Emiliano Ticci
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-12-12 00:00:00.000000000 Z
11
+ date: 2014-12-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -42,16 +42,16 @@ dependencies:
42
42
  name: rspec
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - <
45
+ - - '>='
46
46
  - !ruby/object:Gem::Version
47
- version: '3'
47
+ version: '0'
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
- - - <
52
+ - - '>='
53
53
  - !ruby/object:Gem::Version
54
- version: '3'
54
+ version: '0'
55
55
  description: This plugin allow the definition of arbitrary scripts that will run on
56
56
  the host before and/or after Vagrant commands.
57
57
  email: emiticci@gmail.com
@@ -63,10 +63,13 @@ files:
63
63
  - Gemfile
64
64
  - lib/vagrant-triggers/action/trigger.rb
65
65
  - lib/vagrant-triggers/action.rb
66
+ - lib/vagrant-triggers/config/provisioner.rb
67
+ - lib/vagrant-triggers/config/trigger.rb
66
68
  - lib/vagrant-triggers/config.rb
67
69
  - lib/vagrant-triggers/dsl.rb
68
70
  - lib/vagrant-triggers/errors.rb
69
71
  - lib/vagrant-triggers/plugin.rb
72
+ - lib/vagrant-triggers/provisioner.rb
70
73
  - lib/vagrant-triggers/version.rb
71
74
  - lib/vagrant-triggers.rb
72
75
  - LICENSE.txt
@@ -75,8 +78,10 @@ files:
75
78
  - README.md
76
79
  - spec/spec_helper.rb
77
80
  - spec/vagrant-triggers/action/trigger_spec.rb
78
- - spec/vagrant-triggers/config_spec.rb
81
+ - spec/vagrant-triggers/config/provisioner_spec.rb
82
+ - spec/vagrant-triggers/config/trigger_spec.rb
79
83
  - spec/vagrant-triggers/dsl_spec.rb
84
+ - spec/vagrant-triggers/provisioner_spec.rb
80
85
  - spec/vagrant-triggers/vagrant_spec.rb
81
86
  - vagrant-triggers.gemspec
82
87
  - .gitignore
@@ -108,6 +113,8 @@ summary: Triggers for Vagrant commands.
108
113
  test_files:
109
114
  - spec/spec_helper.rb
110
115
  - spec/vagrant-triggers/action/trigger_spec.rb
111
- - spec/vagrant-triggers/config_spec.rb
116
+ - spec/vagrant-triggers/config/provisioner_spec.rb
117
+ - spec/vagrant-triggers/config/trigger_spec.rb
112
118
  - spec/vagrant-triggers/dsl_spec.rb
119
+ - spec/vagrant-triggers/provisioner_spec.rb
113
120
  - spec/vagrant-triggers/vagrant_spec.rb
@@ -1,58 +0,0 @@
1
- require "spec_helper"
2
-
3
- describe VagrantPlugins::Triggers::Config do
4
- let(:config) { described_class.new }
5
- let(:machine) { double("machine") }
6
-
7
- describe "defaults" do
8
- subject do
9
- config.tap do |o|
10
- o.finalize!
11
- end
12
- end
13
-
14
- its("triggers") { should eq [] }
15
- end
16
-
17
- describe "add triggers" do
18
- it "should add before triggers" do
19
- config.before(:up) { run "ls" }
20
- expect(config.triggers).to have(1).item
21
- end
22
-
23
- it "should add instead_of triggers" do
24
- config.instead_of(:up) { run "ls" }
25
- expect(config.triggers).to have(1).item
26
- end
27
-
28
- it "should add after triggers" do
29
- config.after(:up) { run "ls" }
30
- expect(config.triggers).to have(1).item
31
- end
32
- end
33
-
34
- describe "accept multiple entries" do
35
- it "should record multiple entries" do
36
- config.before(:up) { run "ls" }
37
- config.after(:up) { run "ls" }
38
- expect(config.triggers).to have(2).items
39
- end
40
-
41
- it "should record multiple entries if the action is an array" do
42
- config.before([:up, :halt]) { run "ls" }
43
- expect(config.triggers).to have(2).items
44
- end
45
- end
46
-
47
- describe "validation" do
48
- it "should validate" do
49
- config.finalize!
50
- expect(config.validate(machine)["triggers"]).to have(:no).items
51
- end
52
-
53
- it "shouldn't accept invalid methods" do
54
- config.foo "bar"
55
- expect(config.validate(machine)["triggers"]).to have(1).item
56
- end
57
- end
58
- end