Why do I have to source /etc/profile before command is found


#1

I am fairly new to InSpec and just started testing a cookbook that installs a ruby using rvm. I first try to simply do:

describe command('ruby -v') do
  it { should exist }
  its('stdout') { should include ruby['ruby_version']}
end

This however failed. After some tinkering I discovered that I need to run the following for the test to succeed:

describe command('source /etc/profile && ruby -v') do
  it { should exist }
  its('stdout') { should include ruby['ruby_version']}
end

I wonder why this is needed? If this is indeed needed and not a erroneous assumption on my side: Is there any way to move that into a helper or even better run it once and have it persist?

EDIT:

This also seems to only work in the InSpec shell, but not when run using kitchen test. When run this way it throws:

sudo: source: command not found\n

in stderr.

Thanks,
stiller-leser


#2

InSpec is using a non-interactive shell. I am not 100% sure how you installed ruby and why it is not part of the default path. From my perspective you have two options:

  • you can circumvent the issue by using the absolute path of the ruby binary
  • use the bash InSpec resource. source is part of bash and requires you to have a bash shell available.

I hope that was helpful?


#3

Thank you very much that did the trick.

The test is now succeeding if I use:

describe bash('source /etc/profile && ruby -v') do
  its('stdout') { should include node['ruby_version'] }
end

Ruby has been installed using rvm install ruby-#{node['ruby_version']} after rvm had been installed.


#4

This is specifically needed because of how RVM works - it relies on profiles to load it’s special magic into the shell. This isn’t unique solely to RVM either but is fairly common with programming language version managers.

Cheers,