From e735453422ba6215b81a20cfd90f514a69e2e1cb Mon Sep 17 00:00:00 2001 From: Chris Roberts Date: Fri, 21 Dec 2018 15:50:59 -0800 Subject: [PATCH] Add reboot option to shell provisioner Adds a `reboot` option which allows the guest to be rebooted after the completion of a shell provisioning task. The guest must support the `:reboot` capability. Like the `reset` option, the `reboot` option may be provided without defining `inline` or `file` options when a reboot may be required between other provisioners. Fixes #8639 --- plugins/provisioners/shell/config.rb | 5 +- plugins/provisioners/shell/provisioner.rb | 6 +- .../plugins/provisioners/shell/config_test.rb | 8 +++ .../provisioners/shell/provisioner_test.rb | 64 +++++++++++++++++-- .../source/docs/provisioning/shell.html.md | 3 + 5 files changed, 79 insertions(+), 7 deletions(-) diff --git a/plugins/provisioners/shell/config.rb b/plugins/provisioners/shell/config.rb index b336b0c5c..18a9f1ebd 100644 --- a/plugins/provisioners/shell/config.rb +++ b/plugins/provisioners/shell/config.rb @@ -17,6 +17,7 @@ module VagrantPlugins attr_accessor :sensitive attr_accessor :powershell_args attr_accessor :powershell_elevated_interactive + attr_accessor :reboot attr_accessor :reset def initialize @@ -32,6 +33,7 @@ module VagrantPlugins @keep_color = UNSET_VALUE @name = UNSET_VALUE @sensitive = UNSET_VALUE + @reboot = UNSET_VALUE @reset = UNSET_VALUE @powershell_args = UNSET_VALUE @powershell_elevated_interactive = UNSET_VALUE @@ -50,6 +52,7 @@ module VagrantPlugins @keep_color = false if @keep_color == UNSET_VALUE @name = nil if @name == UNSET_VALUE @sensitive = false if @sensitive == UNSET_VALUE + @reboot = false if @reboot == UNSET_VALUE @reset = false if @reset == UNSET_VALUE @powershell_args = "-ExecutionPolicy Bypass" if @powershell_args == UNSET_VALUE @powershell_elevated_interactive = false if @powershell_elevated_interactive == UNSET_VALUE @@ -71,7 +74,7 @@ module VagrantPlugins # Validate that the parameters are properly set if path && inline errors << I18n.t("vagrant.provisioners.shell.path_and_inline_set") - elsif !path && !inline && !reset + elsif !path && !inline && !reset && !reboot errors << I18n.t("vagrant.provisioners.shell.no_path_or_inline") end diff --git a/plugins/provisioners/shell/provisioner.rb b/plugins/provisioners/shell/provisioner.rb index a77f9185e..4b7cd0507 100644 --- a/plugins/provisioners/shell/provisioner.rb +++ b/plugins/provisioners/shell/provisioner.rb @@ -31,7 +31,11 @@ module VagrantPlugins provision_ssh(args) end ensure - @machine.communicate.reset! if config.reset + if config.reboot + @machine.guest.capability(:reboot) + else + @machine.communicate.reset! if config.reset + end end protected diff --git a/test/unit/plugins/provisioners/shell/config_test.rb b/test/unit/plugins/provisioners/shell/config_test.rb index e0d5a7c52..3a843ca20 100644 --- a/test/unit/plugins/provisioners/shell/config_test.rb +++ b/test/unit/plugins/provisioners/shell/config_test.rb @@ -134,6 +134,14 @@ describe "VagrantPlugins::Shell::Config" do result = subject.validate(machine) expect(result["shell provisioner"]).to be_empty end + + it "returns no error when inline and path are unset but reboot is true" do + subject.reboot = true + subject.finalize! + + result = subject.validate(machine) + expect(result["shell provisioner"]).to be_empty + end end describe 'finalize!' do diff --git a/test/unit/plugins/provisioners/shell/provisioner_test.rb b/test/unit/plugins/provisioners/shell/provisioner_test.rb index e71b3a3bf..0ae5e8a68 100644 --- a/test/unit/plugins/provisioners/shell/provisioner_test.rb +++ b/test/unit/plugins/provisioners/shell/provisioner_test.rb @@ -31,7 +31,8 @@ describe "Vagrant::Shell::Provisioner" do :path => path, :inline => inline, :binary => false, - :reset => true + :reset => true, + :reboot => false, ) } @@ -62,6 +63,55 @@ describe "Vagrant::Shell::Provisioner" do end end + context "when reboot is enabled" do + let(:path) { nil } + let(:inline) { "" } + let(:communicator) { double("communicator") } + let(:guest) { double("guest") } + + let(:config) { + double( + :config, + :args => "doesn't matter", + :env => {}, + :upload_path => "arbitrary", + :remote? => false, + :path => path, + :inline => inline, + :binary => false, + :reset => false, + :reboot => true + ) + } + + let(:vsp) { + VagrantPlugins::Shell::Provisioner.new(machine, config) + } + + before { + allow(machine).to receive(:communicate).and_return(communicator) + allow(machine).to receive(:guest).and_return(guest) + allow(vsp).to receive(:provision_ssh) + } + + it "should provision and then reboot the guest" do + expect(vsp).to receive(:provision_ssh) + expect(guest).to receive(:capability).with(:reboot) + vsp.provision + end + + context "when path and inline are not set" do + let(:path) { nil } + let(:inline) { nil } + + it "should reboot the guest and not provision" do + expect(vsp).not_to receive(:provision_ssh) + expect(guest).to receive(:capability).with(:reboot) + vsp.provision + end + end + end + context "with a script that contains invalid us-ascii byte sequences" do let(:config) { double( @@ -73,7 +123,8 @@ describe "Vagrant::Shell::Provisioner" do :path => nil, :inline => script_that_is_incorrectly_us_ascii_encoded, :binary => false, - :reset => false + :reset => false, + :reboot => false ) } @@ -106,7 +157,8 @@ describe "Vagrant::Shell::Provisioner" do :path => nil, :inline => script, :binary => false, - :reset => false + :reset => false, + :reboot => false ) } @@ -136,7 +188,8 @@ describe "Vagrant::Shell::Provisioner" do :binary => false, :md5 => nil, :sha1 => 'EXPECTED_VALUE', - :reset => false + :reset => false, + :reboot => false ) } @@ -167,7 +220,8 @@ describe "Vagrant::Shell::Provisioner" do :binary => false, :md5 => 'EXPECTED_VALUE', :sha1 => nil, - :reset => false + :reset => false, + :reboot => false ) } diff --git a/website/source/docs/provisioning/shell.html.md b/website/source/docs/provisioning/shell.html.md index bb5a23ea1..65235ddc6 100644 --- a/website/source/docs/provisioning/shell.html.md +++ b/website/source/docs/provisioning/shell.html.md @@ -75,6 +75,9 @@ The remainder of the available options are optional: guests use a scheduled task to run as a true administrator without the WinRM limitations. +* `reboot` (boolean) - Reboot the guest. This requires the guest to have a + reboot capability implemented. + * `reset` (boolean) - Reset the communicator to the machine after completion. This is useful when a shell may need to be reloaded.