596 lines
19 KiB
Ruby
596 lines
19 KiB
Ruby
require File.expand_path("../../../../base", __FILE__)
|
|
require Vagrant.source_root.join("plugins/provisioners/shell/provisioner")
|
|
|
|
describe "Vagrant::Shell::Provisioner" do
|
|
include_context "unit"
|
|
|
|
let(:default_win_path) { "C:/tmp/vagrant-shell" }
|
|
let(:env){ isolated_environment }
|
|
let(:machine) {
|
|
double(:machine, env: env, id: "ID").tap { |machine|
|
|
allow(machine).to receive_message_chain(:config, :vm, :communicator).and_return(:not_winrm)
|
|
allow(machine).to receive_message_chain(:config, :vm, :guest).and_return(:linux)
|
|
allow(machine).to receive_message_chain(:communicate, :tap) {}
|
|
}
|
|
}
|
|
|
|
before do
|
|
allow(env).to receive(:tmp_path).and_return(Pathname.new("/dev/null"))
|
|
end
|
|
|
|
context "when reset is enabled" do
|
|
let(:path) { nil }
|
|
let(:inline) { "" }
|
|
let(:communicator) { double("communicator") }
|
|
|
|
let(:config) {
|
|
double(
|
|
:config,
|
|
:args => "doesn't matter",
|
|
:env => {},
|
|
:upload_path => "arbitrary",
|
|
:remote? => false,
|
|
:path => path,
|
|
:inline => inline,
|
|
:binary => false,
|
|
:reset => true,
|
|
:reboot => false,
|
|
)
|
|
}
|
|
|
|
let(:vsp) {
|
|
VagrantPlugins::Shell::Provisioner.new(machine, config)
|
|
}
|
|
|
|
before {
|
|
allow(machine).to receive(:communicate).and_return(communicator)
|
|
allow(vsp).to receive(:provision_ssh)
|
|
}
|
|
|
|
it "should provision and then reset the connection" do
|
|
expect(vsp).to receive(:provision_ssh)
|
|
expect(communicator).to receive(:reset!)
|
|
vsp.provision
|
|
end
|
|
|
|
context "when path and inline are not set" do
|
|
let(:path) { nil }
|
|
let(:inline) { nil }
|
|
|
|
it "should reset the connection and not provision" do
|
|
expect(vsp).not_to receive(:provision_ssh)
|
|
expect(communicator).to receive(:reset!)
|
|
vsp.provision
|
|
end
|
|
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(
|
|
:config,
|
|
:args => "doesn't matter",
|
|
:env => {},
|
|
:upload_path => "arbitrary",
|
|
:remote? => false,
|
|
:path => nil,
|
|
:inline => script_that_is_incorrectly_us_ascii_encoded,
|
|
:binary => false,
|
|
:reset => false,
|
|
:reboot => false
|
|
)
|
|
}
|
|
|
|
let(:script_that_is_incorrectly_us_ascii_encoded) {
|
|
[207].pack("c*").force_encoding("US-ASCII")
|
|
}
|
|
|
|
it "does not raise an exception when normalizing newlines" do
|
|
vsp = VagrantPlugins::Shell::Provisioner.new(machine, config)
|
|
|
|
expect {
|
|
vsp.provision
|
|
}.not_to raise_error
|
|
end
|
|
end
|
|
|
|
context "with a script that was set to freeze the string" do
|
|
TEST_CONSTANT_VARIABLE = <<-TEST_CONSTANT_VARIABLE.freeze
|
|
echo test
|
|
TEST_CONSTANT_VARIABLE
|
|
|
|
let(:script) { TEST_CONSTANT_VARIABLE }
|
|
let(:config) {
|
|
double(
|
|
:config,
|
|
:args => "doesn't matter",
|
|
:env => {},
|
|
:upload_path => "arbitrary",
|
|
:remote? => false,
|
|
:path => nil,
|
|
:inline => script,
|
|
:binary => false,
|
|
:reset => false,
|
|
:reboot => false
|
|
)
|
|
}
|
|
|
|
it "does not raise an exception" do
|
|
vsp = VagrantPlugins::Shell::Provisioner.new(machine, config)
|
|
|
|
RSpec::Expectations.configuration.on_potential_false_positives = :nothing
|
|
# This test should be fine, since we are specifically looking for the
|
|
# string 'freeze' when RuntimeError is raised
|
|
expect {
|
|
vsp.provision
|
|
}.not_to raise_error(RuntimeError)
|
|
end
|
|
end
|
|
|
|
context "with remote script" do
|
|
let(:filechecksum) { double("filechecksum", checksum: checksum_value) }
|
|
let(:checksum_value) { double("checksum_value") }
|
|
|
|
before do
|
|
allow(FileChecksum).to receive(:new).and_return(filechecksum)
|
|
allow_any_instance_of(Vagrant::Util::Downloader).to receive(:execute_curl).and_return(true)
|
|
end
|
|
|
|
context "that does not have matching sha1 checksum" do
|
|
let(:checksum_value) { "INVALID_VALUE" }
|
|
let(:config) {
|
|
double(
|
|
:config,
|
|
:args => "doesn't matter",
|
|
:env => {},
|
|
:upload_path => "arbitrary",
|
|
:remote? => true,
|
|
:path => "http://example.com/script.sh",
|
|
:binary => false,
|
|
:md5 => nil,
|
|
:sha1 => 'EXPECTED_VALUE',
|
|
:sha256 => nil,
|
|
:sha384 => nil,
|
|
:sha512 => nil,
|
|
:reset => false,
|
|
:reboot => false
|
|
)
|
|
}
|
|
|
|
it "should raise an exception" do
|
|
vsp = VagrantPlugins::Shell::Provisioner.new(machine, config)
|
|
|
|
expect{ vsp.provision }.to raise_error(Vagrant::Errors::DownloaderChecksumError)
|
|
end
|
|
end
|
|
|
|
context "that does not have matching sha256 checksum" do
|
|
let(:checksum_value) { "INVALID_VALUE" }
|
|
let(:config) {
|
|
double(
|
|
:config,
|
|
:args => "doesn't matter",
|
|
:env => {},
|
|
:upload_path => "arbitrary",
|
|
:remote? => true,
|
|
:path => "http://example.com/script.sh",
|
|
:binary => false,
|
|
:md5 => nil,
|
|
:sha1 => nil,
|
|
:sha256 => 'EXPECTED_VALUE',
|
|
:sha384 => nil,
|
|
:sha512 => nil,
|
|
:reset => false,
|
|
:reboot => false
|
|
)
|
|
}
|
|
|
|
it "should raise an exception" do
|
|
vsp = VagrantPlugins::Shell::Provisioner.new(machine, config)
|
|
|
|
expect{ vsp.provision }.to raise_error(Vagrant::Errors::DownloaderChecksumError)
|
|
end
|
|
end
|
|
|
|
context "that does not have matching sha384 checksum" do
|
|
let(:checksum_value) { "INVALID_VALUE" }
|
|
let(:config) {
|
|
double(
|
|
:config,
|
|
:args => "doesn't matter",
|
|
:env => {},
|
|
:upload_path => "arbitrary",
|
|
:remote? => true,
|
|
:path => "http://example.com/script.sh",
|
|
:binary => false,
|
|
:md5 => nil,
|
|
:sha1 => nil,
|
|
:sha256 => nil,
|
|
:sha384 => 'EXPECTED_VALUE',
|
|
:sha512 => nil,
|
|
:reset => false,
|
|
:reboot => false
|
|
)
|
|
}
|
|
|
|
it "should raise an exception" do
|
|
vsp = VagrantPlugins::Shell::Provisioner.new(machine, config)
|
|
|
|
expect{ vsp.provision }.to raise_error(Vagrant::Errors::DownloaderChecksumError)
|
|
end
|
|
end
|
|
|
|
context "that does not have matching sha512 checksum" do
|
|
let(:checksum_value) { "INVALID_VALUE" }
|
|
let(:config) {
|
|
double(
|
|
:config,
|
|
:args => "doesn't matter",
|
|
:env => {},
|
|
:upload_path => "arbitrary",
|
|
:remote? => true,
|
|
:path => "http://example.com/script.sh",
|
|
:binary => false,
|
|
:md5 => nil,
|
|
:sha1 => nil,
|
|
:sha256 => nil,
|
|
:sha384 => nil,
|
|
:sha512 => 'EXPECTED_VALUE',
|
|
:reset => false,
|
|
:reboot => false
|
|
)
|
|
}
|
|
|
|
it "should raise an exception" do
|
|
vsp = VagrantPlugins::Shell::Provisioner.new(machine, config)
|
|
|
|
expect{ vsp.provision }.to raise_error(Vagrant::Errors::DownloaderChecksumError)
|
|
end
|
|
end
|
|
|
|
context "that does not have matching md5 checksum" do
|
|
let(:checksum_value) { "INVALID_VALUE" }
|
|
let(:config) {
|
|
double(
|
|
:config,
|
|
:args => "doesn't matter",
|
|
:env => {},
|
|
:upload_path => "arbitrary",
|
|
:remote? => true,
|
|
:path => "http://example.com/script.sh",
|
|
:binary => false,
|
|
:md5 => 'EXPECTED_VALUE',
|
|
:sha1 => nil,
|
|
:sha256 => nil,
|
|
:sha384 => nil,
|
|
:sha512 => nil,
|
|
:reset => false,
|
|
:reboot => false
|
|
)
|
|
}
|
|
|
|
it "should raise an exception" do
|
|
vsp = VagrantPlugins::Shell::Provisioner.new(machine, config)
|
|
|
|
expect{ vsp.provision }.to raise_error(Vagrant::Errors::DownloaderChecksumError)
|
|
end
|
|
end
|
|
end
|
|
|
|
describe "#upload_path" do
|
|
context "when upload path is not set" do
|
|
let(:vsp) {
|
|
VagrantPlugins::Shell::Provisioner.new(machine, config)
|
|
}
|
|
|
|
let(:config) {
|
|
double(
|
|
:config,
|
|
:args => "doesn't matter",
|
|
:env => {},
|
|
:upload_path => nil,
|
|
:remote? => false,
|
|
:path => "doesn't matter",
|
|
:inline => "doesn't matter",
|
|
:binary => false,
|
|
:reset => true,
|
|
:reboot => false,
|
|
)
|
|
}
|
|
|
|
it "should default to /tmp/vagrant-shell" do
|
|
expect(vsp.upload_path).to eq("/tmp/vagrant-shell")
|
|
end
|
|
|
|
context "windows" do
|
|
before do
|
|
allow(machine).to receive_message_chain(:config, :vm, :guest).and_return(:windows)
|
|
end
|
|
|
|
it "should default to C:/tmp/vagrant-shell" do
|
|
expect(vsp.upload_path).to eq("C:/tmp/vagrant-shell")
|
|
end
|
|
end
|
|
end
|
|
|
|
context "when upload_path is set" do
|
|
let(:upload_path) { "arbitrary" }
|
|
|
|
let(:config) {
|
|
double(
|
|
:config,
|
|
:args => "doesn't matter",
|
|
:env => {},
|
|
:upload_path => upload_path,
|
|
:remote? => false,
|
|
:path => "doesn't matter",
|
|
:inline => "doesn't matter",
|
|
:binary => false,
|
|
:reset => true,
|
|
:reboot => false,
|
|
)
|
|
}
|
|
|
|
let(:vsp) {
|
|
VagrantPlugins::Shell::Provisioner.new(machine, config)
|
|
}
|
|
|
|
it "should use the value from from config" do
|
|
expect(vsp.upload_path).to eq("arbitrary")
|
|
end
|
|
|
|
context "windows" do
|
|
let(:upload_path) { "C:\\Windows\\Temp" }
|
|
|
|
before do
|
|
allow(machine).to receive_message_chain(:config, :vm, :guest).and_return(:windows)
|
|
end
|
|
|
|
it "should normalize the slashes" do
|
|
expect(vsp.upload_path).to eq("C:/Windows/Temp")
|
|
end
|
|
end
|
|
end
|
|
|
|
context "with cached value" do
|
|
let(:config) { double(:config) }
|
|
|
|
let(:vsp) {
|
|
VagrantPlugins::Shell::Provisioner.new(machine, config)
|
|
}
|
|
|
|
before do
|
|
vsp.instance_variable_set(:@_upload_path, "anything")
|
|
end
|
|
|
|
it "should use cached value" do
|
|
expect(vsp.upload_path).to eq("anything")
|
|
end
|
|
end
|
|
end
|
|
|
|
describe "#provision_winrm" do
|
|
let(:config) {
|
|
double(
|
|
:config,
|
|
:args => "doesn't matter",
|
|
:env => {},
|
|
:upload_path => "arbitrary",
|
|
:remote? => false,
|
|
:path => "script/info.ps1",
|
|
:binary => false,
|
|
:md5 => nil,
|
|
:sha1 => 'EXPECTED_VALUE',
|
|
:sha256 => nil,
|
|
:sha384 => nil,
|
|
:sha512 => nil,
|
|
:reset => false,
|
|
:reboot => false,
|
|
:powershell_args => "",
|
|
:name => nil,
|
|
:privileged => false,
|
|
:powershell_elevated_interactive => false
|
|
)
|
|
}
|
|
|
|
let(:vsp) {
|
|
VagrantPlugins::Shell::Provisioner.new(machine, config)
|
|
}
|
|
|
|
let(:communicator) { double("communicator") }
|
|
let(:guest) { double("guest") }
|
|
let(:ui) { double("ui") }
|
|
|
|
before {
|
|
allow(guest).to receive(:capability?).with(:wait_for_reboot).and_return(false)
|
|
allow(ui).to receive(:detail)
|
|
allow(communicator).to receive(:sudo)
|
|
allow(machine).to receive(:communicate).and_return(communicator)
|
|
allow(machine).to receive(:guest).and_return(guest)
|
|
allow(machine).to receive(:ui).and_return(ui)
|
|
}
|
|
|
|
it "ensures that files are uploaded with an extension" do
|
|
allow(vsp).to receive(:with_script_file).and_yield(config.path)
|
|
expect(communicator).to receive(:upload).with(config.path, /arbitrary.ps1$/)
|
|
vsp.send(:provision_winrm, "")
|
|
end
|
|
|
|
context "inline option set" do
|
|
let(:config) {
|
|
double(
|
|
:config,
|
|
:args => "doesn't matter",
|
|
:env => {},
|
|
:remote? => false,
|
|
:inline => "some commands",
|
|
:upload_path => nil,
|
|
:path => nil,
|
|
:binary => false,
|
|
:md5 => nil,
|
|
:sha1 => 'EXPECTED_VALUE',
|
|
:sha256 => nil,
|
|
:sha384 => nil,
|
|
:sha512 => nil,
|
|
:reset => false,
|
|
:reboot => false,
|
|
:powershell_args => "",
|
|
:name => nil,
|
|
:privileged => false,
|
|
:powershell_elevated_interactive => false
|
|
)
|
|
}
|
|
|
|
it "creates an executable with an extension" do
|
|
allow(vsp).to receive(:with_script_file).and_yield(default_win_path)
|
|
allow(communicator).to receive(:upload).with(default_win_path, /vagrant-shell/)
|
|
expect(communicator).to receive(:sudo).with(/vagrant-shell.ps1/, anything)
|
|
vsp.send(:provision_winrm, "")
|
|
end
|
|
end
|
|
end
|
|
|
|
describe "#provision_winssh" do
|
|
let(:config) {
|
|
double(
|
|
:config,
|
|
:args => "doesn't matter",
|
|
:env => {},
|
|
:upload_path => "arbitrary",
|
|
:remote? => false,
|
|
:path => nil,
|
|
:inline => "something",
|
|
:binary => false,
|
|
:md5 => nil,
|
|
:sha1 => 'EXPECTED_VALUE',
|
|
:sha256 => nil,
|
|
:sha384 => nil,
|
|
:sha512 => nil,
|
|
:reset => false,
|
|
:reboot => false,
|
|
:powershell_args => "",
|
|
:name => nil,
|
|
:privileged => false,
|
|
:powershell_elevated_interactive => false
|
|
)
|
|
}
|
|
|
|
let(:vsp) {
|
|
VagrantPlugins::Shell::Provisioner.new(machine, config)
|
|
}
|
|
|
|
let(:communicator) { double("communicator") }
|
|
let(:guest) { double("guest") }
|
|
let(:ui) { double("ui") }
|
|
|
|
before {
|
|
allow(guest).to receive(:capability?).with(:wait_for_reboot).and_return(false)
|
|
allow(ui).to receive(:detail)
|
|
allow(communicator).to receive(:sudo)
|
|
allow(communicator).to receive_message_chain(:machine_config_ssh, :shell)
|
|
allow(machine).to receive(:communicate).and_return(communicator)
|
|
allow(machine).to receive(:guest).and_return(guest)
|
|
allow(machine).to receive(:ui).and_return(ui)
|
|
allow(machine).to receive(:ssh_info).and_return(true)
|
|
}
|
|
|
|
it "ensures that files are uploaded as .bat when shell is cmd" do
|
|
allow(machine).to receive_message_chain(:config, :winssh, :shell).and_return("cmd")
|
|
allow(vsp).to receive(:with_script_file).and_yield(default_win_path)
|
|
expect(communicator).to receive(:upload).with(default_win_path, /arbitrary.bat/)
|
|
expect(communicator).to receive(:execute).with(/arbitrary.bat/, anything)
|
|
vsp.send(:provision_winssh, "")
|
|
end
|
|
|
|
it "ensures that files are uploaded as .ps1 when shell is not cmd" do
|
|
allow(machine).to receive_message_chain(:config, :winssh, :shell).and_return("ps")
|
|
allow(vsp).to receive(:with_script_file).and_yield(default_win_path)
|
|
expect(communicator).to receive(:upload).with(default_win_path, /arbitrary.ps1/)
|
|
expect(communicator).to receive(:execute).with(/arbitrary.ps1/, anything)
|
|
vsp.send(:provision_winssh, "")
|
|
end
|
|
|
|
context "ps1 file being uploaded" do
|
|
let(:config) {
|
|
double(
|
|
:config,
|
|
:args => "doesn't matter",
|
|
:env => {},
|
|
:upload_path => "arbitrary",
|
|
:remote? => false,
|
|
:path => "script/info.ps1",
|
|
:binary => false,
|
|
:md5 => nil,
|
|
:sha1 => 'EXPECTED_VALUE',
|
|
:sha256 => nil,
|
|
:sha384 => nil,
|
|
:sha512 => nil,
|
|
:reset => false,
|
|
:reboot => false,
|
|
:powershell_args => "",
|
|
:name => nil,
|
|
:privileged => false,
|
|
:powershell_elevated_interactive => false
|
|
)
|
|
}
|
|
|
|
it "ensures that files are uploaded same extension as provided path.ps1" do
|
|
allow(machine).to receive_message_chain(:config, :winssh, :shell).and_return("cmd")
|
|
allow(vsp).to receive(:with_script_file).and_yield(config.path)
|
|
expect(communicator).to receive(:upload).with(config.path, /arbitrary.ps1/)
|
|
expect(communicator).to receive(:execute).with(/arbitrary.ps1/, anything)
|
|
vsp.send(:provision_winssh, "")
|
|
end
|
|
end
|
|
end
|
|
end
|