1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181
|
# author: Dominik Richter
# author: Christoph Hartmann
require "helper"
require "train/transports/mock"
require "train/extras"
require "base64" unless defined?(Base64)
describe "linux command" do
let(:cls) { Train::Extras::LinuxCommand }
let(:cmd) { rand.to_s }
let(:backend) do
backend = Train::Transports::Mock.new.connection
backend.mock_os({ family: "linux" })
backend
end
describe "sudo wrapping" do
it "wraps commands in sudo" do
lc = cls.new(backend, { sudo: true })
_(lc.run(cmd)).must_equal "sudo #{cmd}"
end
it "doesn't wrap commands in sudo if user == root" do
lc = cls.new(backend, { sudo: true, user: "root" })
_(lc.run(cmd)).must_equal cmd
end
it "wraps commands in sudo with all options" do
opts = rand.to_s
lc = cls.new(backend, { sudo: true, sudo_options: opts })
_(lc.run(cmd)).must_equal "sudo #{opts} #{cmd}"
end
it "runs commands in sudo with password" do
pw = rand.to_s
lc = cls.new(backend, { sudo: true, sudo_password: pw })
bpw = Base64.strict_encode64(pw + "\n")
_(lc.run(cmd)).must_equal "echo #{bpw} | base64 --decode | sudo -S #{cmd}"
end
it "wraps commands in sudo_command instead of sudo" do
sudo_command = rand.to_s
lc = cls.new(backend, { sudo: true, sudo_command: sudo_command })
_(lc.run(cmd)).must_equal "#{sudo_command} #{cmd}"
end
it "wraps commands in sudo_command with all options" do
opts = rand.to_s
sudo_command = rand.to_s
lc = cls.new(backend, { sudo: true, sudo_command: sudo_command, sudo_options: opts })
_(lc.run(cmd)).must_equal "#{sudo_command} #{opts} #{cmd}"
end
it "runs commands in sudo_command with password" do
pw = rand.to_s
sudo_command = rand.to_s
lc = cls.new(backend, { sudo: true, sudo_command: sudo_command, sudo_password: pw })
bpw = Base64.strict_encode64(pw + "\n")
_(lc.run(cmd)).must_equal "echo #{bpw} | base64 --decode | #{sudo_command} -S #{cmd}"
end
end
describe "shell wrapping" do
it "wraps commands in a default shell with login" do
lc = cls.new(backend, { shell: true, shell_options: "--login" })
bcmd = Base64.strict_encode64(cmd)
_(lc.run(cmd)).must_equal "echo #{bcmd} | base64 --decode | $SHELL --login"
end
it "wraps sudo commands in a default shell with login" do
lc = cls.new(backend, { sudo: true, shell: true, shell_options: "--login" })
bcmd = Base64.strict_encode64("sudo #{cmd}")
_(lc.run(cmd)).must_equal "echo #{bcmd} | base64 --decode | $SHELL --login"
end
it "wraps sudo commands and sudo passwords in a default shell with login" do
pw = rand.to_s
lc = cls.new(backend, { sudo: true, sudo_password: pw, shell: true, shell_options: "--login" })
bpw = Base64.strict_encode64(pw + "\n")
bcmd = Base64.strict_encode64("echo #{bpw} | base64 --decode | sudo -S #{cmd}")
_(lc.run(cmd)).must_equal "echo #{bcmd} | base64 --decode | $SHELL --login"
end
it "wraps commands in a default shell when shell is true" do
lc = cls.new(backend, { shell: true })
bcmd = Base64.strict_encode64(cmd)
_(lc.run(cmd)).must_equal "echo #{bcmd} | base64 --decode | $SHELL"
end
it "doesnt wrap commands in a shell when shell is false" do
lc = cls.new(backend, { shell: false })
_(lc.run(cmd)).must_equal cmd
end
it "wraps commands in a `shell` instead of default shell" do
lc = cls.new(backend, { shell: true, shell_command: "/bin/bash" })
bcmd = Base64.strict_encode64(cmd)
_(lc.run(cmd)).must_equal "echo #{bcmd} | base64 --decode | /bin/bash"
end
it "wraps commands in a default shell with login" do
lc = cls.new(backend, { shell: true, shell_command: "/bin/bash", shell_options: "--login" })
bcmd = Base64.strict_encode64(cmd)
_(lc.run(cmd)).must_equal "echo #{bcmd} | base64 --decode | /bin/bash --login"
end
end
describe "#verify" do
def mock_connect_result(stderr, exit_status)
OpenStruct.new(stdout: "", stderr: stderr, exit_status: exit_status)
end
it "returns nil on success" do
backend.stubs(:run_command).returns(mock_connect_result(nil, 0))
lc = cls.new(backend, { sudo: true })
_(lc.verify).must_be_nil
end
it "error message for bad sudo password" do
backend.stubs(:run_command).returns(mock_connect_result("Sorry, try again", 1))
lc = cls.new(backend, { sudo: true })
err = _ { lc.verify! }.must_raise Train::UserError
_(err.reason.to_s).must_match("bad_sudo_password")
end
it "error message for sudo password required" do
backend.stubs(:run_command).returns(mock_connect_result("sudo: no tty present and no program specified", 1))
lc = cls.new(backend, { sudo: true })
err = _ { lc.verify! }.must_raise Train::UserError
_(err.message).must_match(/Sudo failed: sudo: no tty present and no program specified/)
end
it "error message for sudo: command not found" do
backend.stubs(:run_command).returns(mock_connect_result("sudo: command not found", 1))
lc = cls.new(backend, { sudo: true })
err = _ { lc.verify! }.must_raise Train::UserError
_(err.reason.to_s).must_match("sudo_command_not_found")
end
it "error message for requires tty" do
backend.stubs(:run_command).returns(mock_connect_result("sudo: sorry, you must have a tty to run sudo", 1))
lc = cls.new(backend, { sudo: true })
err = _ { lc.verify! }.must_raise Train::UserError
_(err.reason.to_s).must_match("sudo_no_tty")
end
it "error message for other sudo related errors" do
backend.stubs(:run_command).returns(mock_connect_result("Other sudo related error", 1))
lc = cls.new(backend, { sudo: true })
err = _ { lc.verify! }.must_raise Train::UserError
_(err.message).must_match(/Other sudo related error/)
end
it "error message for not enough sudo privileges for OS operations" do
backend.stubs(:run_command).returns(mock_connect_result("sudo: a terminal is required to read the password; either use the -S option to read from standard input or configure an askpass helper", 1))
lc = cls.new(backend, { sudo: true })
err = _ { lc.verify! }.must_raise Train::UserError
_(err.reason.to_s).must_match("sudo_missing_terminal")
end
end
end
describe "windows command" do
let(:cls) { Train::Extras::WindowsCommand }
let(:cmd) { rand.to_s }
let(:backend) do
backend = Train::Transports::Mock.new.connection
backend.mock_os({ family: "windows" })
backend
end
describe "shell wrapping" do
it "wraps commands in a default powershell" do
lc = cls.new(backend, { shell: true })
wcmd = "$ProgressPreference='SilentlyContinue';" + cmd
bcmd = Base64.strict_encode64(wcmd.encode("UTF-16LE", "UTF-8"))
_(lc.run(cmd)).must_equal "powershell -NoProfile -EncodedCommand #{bcmd}"
end
end
end
|