I am learning Chef and the testing process using Kitchen with the ec2 driver and have the following serverspec file:
require "serverspec"
set :backend, :exec
describe "rbenv" do
describe file("/home/ec2-user/.rbenv") do
it { should be_directory }
end
describe command("rbenv versions") do
its(:exit_status) { should eq 0 }
end
end
When I run kitchen verify amazon-linux
the first test passes but the second one fails and causes an error:
rbenv
File "/home/ec2-user/.rbenv"
should be directory
Command "rbenv versions"
exit_status
should eq 0 (FAILED - 1)
Failures:
1) rbenv Command "rbenv versions" exit_status should eq 0
Failure/Error: its(:exit_status) { should eq 0 }
expected: 0
got: 127
(compared using ==)
/bin/sh -c rbenv\ versions
# /tmp/verifier/suites/serverspec/rbenv_spec.rb:11:in `block (3 levels) in <top (required)>'
Finished in 0.05481 seconds (files took 0.30304 seconds to load)
2 examples, 1 failure
Failed examples:
rspec /tmp/verifier/suites/serverspec/rbenv_spec.rb:11 # rbenv Command "rbenv versions" exit_status should eq 0
/opt/chef/embedded/bin/ruby -I/tmp/verifier/suites/serverspec -I/tmp/verifier/gems/gems/rspec-support-3.4.1/lib:/tmp/ver
ifier/gems/gems/rspec-core-3.4.4/lib /opt/chef/embedded/bin/rspec --pattern /tmp/verifier/suites/serverspec/\*\*/\*_spec.rb --c
olor --format documentation --default-path /tmp/verifier/suites/serverspec failed
!!!!!! Ruby Script [/tmp/verifier/gems/gems/busser-serverspec-0.5.9/lib/busser/runner_plugin/../serverspec/runner.rb /tm
p/verifier/suites/serverspec] exit code was 1
>>>>>> Verify failed on instance <default-amazon-linux>.
>>>>>> Please see .kitchen/logs/default-amazon-linux.log for more details
>>>>>> ------Exception-------
>>>>>> Class: Kitchen::ActionFailed
>>>>>> Message: SSH exited (1) for command: [sh -c '
BUSSER_ROOT="/tmp/verifier"; export BUSSER_ROOT
GEM_HOME="/tmp/verifier/gems"; export GEM_HOME
GEM_PATH="/tmp/verifier/gems"; export GEM_PATH
GEM_CACHE="/tmp/verifier/gems/cache"; export GEM_CACHE
sudo -E /tmp/verifier/bin/busser test
']
>>>>>> ----------------------
I logged into the server manually and ran the same command /bin/sh -c rbenv\ versions
and it worked fine.
Can anyone tell if there's something I'm doing wrong here?
EDIT 1
I just discovered that when serverspec runs the command the $PATH
variable is different from what it is when I log in manually. I added puts ENV['PATH']
to the test and the output was this:
/sbin:/bin:/usr/sbin:/usr/bin
However, when I login manually I get this:
/home/ec2-user/.rbenv/shims:/home/ec2-user/.rbenv/bin:/home/ec2-user/.rbenv/shims:/usr/local/bin:/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/sbin:/opt/aws/bin:/home/ec2-user/.local/bin:/home/ec2-user/bin
I changed the command in the test to /home/ec2-user/.rbenv/rbenv versions
and it passed. Any idea what I need to do to make the paths work correctly here?
EDIT 2
So I've discovered that serverspec is running the commands as root
, which means that the changes to ec2-user
's path that took place during kitchen converge
are unavailable.
I don't know if there's a more idiomatic way to do this with serverspec, but I changed my command to this and the test now passes:
runuser -l ec2-user -c 'rbenv versions'
This allows root
to run a command as another user. Unless someone knows of a better way to do this kind of test I'll add this as the answer to the question.
serverspec runs its commands as root, so changes made to any other user's path during convergence are irrelevant.
Using the Linux runuser
command will allow root
to run a command as another user, thereby gaining access to that user's $PATH
:
runuser -l ec2-user -c 'rbenv versions'