0
votes

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.

1
Try checking the output: its(:stdout) { should eq '' } and similar to stderr. That will display them from the rspec output. - coderanger
@coderanger I just realized (haven't added to OP yet) that when serverspec runs the command the $PATH variable is different. I changed the command to /home/ec2-user/.rbenv/rbenv versions and the test passed. Any idea what I need to do to make the paths work correctly here? - sixty4bit
ok so I've finally figured out serverspec is running the tests as root user...so the changes I made to ec2-user's $PATH aren't accessible... - sixty4bit
That is correct, kitchen expects to run everything as root to keep things standardized. - coderanger
thanks @coderanger. do you know of another solution besides runuser that I've added to the end of the OP, or is that the best? - sixty4bit

1 Answers

1
votes

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'