inspec/test/unit/bundles/inspect-habitat/profile_test.rb
Adam Leff 8269d0da9e Support vendored profiles in Habitat-packaged profiles
This change adds support in Habitat-packaged profiles for
profiles that depend on other profiles. When `inspec habitat
profile create` or `inspec habitat profile upload` is run,
it will see if the profile's dependencies have been vendored
yet, and if not, it will vendor them before creating the
habitat artifact.

For the git and URL fetchers, more explicit creation of the
target directories for the vendored profiles is done. This
is implicitly done via normal CLI interactions a user may
go through, but in our case, we want to ensure those directories
are there before the fetchers try to write out content.

By adding this support, we also fix a bug experienced in Habitat
where a profile that was packaged before an `inspec exec` was run
for the profile would cause a failure in Habitat. This is caused
by `inspec exec` doing a vendor of the dependencies if necessary
and generating the inspec.lock file. In Habitat, the package dir
is not writable by the hab user and InSpec would fail to run due
to an inability to write out an inspec.lock.

Signed-off-by: Adam Leff <adam@leff.co>
2017-03-29 10:22:20 +02:00

185 lines
5.9 KiB
Ruby

require 'helper'
require 'mixlib/log'
require 'ostruct'
describe Habitat::Profile do
let(:profile) do
OpenStruct.new(
name: 'my_profile',
version: '1.2.3',
files: %w(file1 file2)
)
end
let(:subject) { Habitat::Profile.new('/path/to/profile', { 'log_level' => 'fatal' }) }
before do
Habitat::Log.level(:fatal)
end
describe '#verify_profile' do
it 'exits if the profile is not valid' do
profile = mock
profile.stubs(:check).returns(summary: { valid: false })
subject.expects(:profile).returns(profile)
proc { subject.send(:verify_profile) }.must_raise SystemExit
end
it 'does not exist if the profile is valid' do
profile = mock
profile.stubs(:check).returns(summary: { valid: true })
subject.expects(:profile).returns(profile)
subject.send(:verify_profile)
end
end
describe '#vendor_profile_dependencies' do
let(:cache) { '/path/to/cache' }
let(:lockfile) { '/path/to/lock' }
let(:profile) do
profile = mock
profile.stubs(:generate_lockfile).returns(foo: 'bar')
profile
end
before do
subject.expects(:cache_path).at_least_once.returns(cache)
subject.expects(:inspec_lockfile).at_least_once.returns(lockfile)
end
describe 'when lockfile exists and cache dir exists' do
it 'does not generate the lockfile' do
File.expects(:exist?).with(lockfile).returns(true)
Dir.expects(:exist?).with(cache).returns(true)
subject.expects(:profile).returns(profile).never
profile.expects(:generate_lockfile).never
subject.send(:vendor_profile_dependencies)
end
end
describe 'when the lockfile exists but the cache dir does not' do
it 'deletes the lockfile, generates the lockfile, and refreshes the profile object' do
File.expects(:exist?).with(lockfile).returns(true).at_least_once
Dir.expects(:exist?).with(cache).returns(false).at_least_once
FileUtils.expects(:rm_rf).with(cache)
File.expects(:delete).with(lockfile)
subject.expects(:profile).returns(profile)
File.expects(:write).with(lockfile, "---\n:foo: bar\n")
subject.expects(:create_profile_object)
subject.send(:vendor_profile_dependencies)
end
end
describe 'when the lockfile does not exist' do
it 'generates the lockfile, and refreshes the profile object' do
File.expects(:exist?).with(lockfile).returns(false).at_least_once
FileUtils.expects(:rm_rf).with(cache)
subject.expects(:profile).returns(profile)
File.expects(:write).with(lockfile, "---\n:foo: bar\n")
subject.expects(:create_profile_object)
subject.send(:vendor_profile_dependencies)
end
end
end
describe '#validate_habitat_installed' do
it 'exits if hab --version fails' do
cmd = mock
cmd.stubs(:error?).returns(true)
cmd.stubs(:run_command)
cmd.stubs(:stdout)
cmd.stubs(:stderr)
Mixlib::ShellOut.expects(:new).with('hab --version').returns(cmd)
proc { subject.send(:validate_habitat_installed) }.must_raise SystemExit
end
end
describe '#validate_habitat_origin' do
it 'does not exit if the origin key exists' do
subject.expects(:habitat_origin).returns('12345')
subject.send(:validate_habitat_origin)
end
it 'exits if no origin key exists' do
subject.expects(:habitat_origin).returns(nil)
proc { subject.send(:validate_habitat_origin) }.must_raise SystemExit
end
end
describe '#validate_habitat_auth_token' do
it 'does not exit if the auth_token exists' do
subject.expects(:habitat_auth_token).returns('12345')
subject.send(:validate_habitat_auth_token)
end
it 'exits if no auth_token exists' do
subject.expects(:habitat_auth_token).returns(nil)
proc { subject.send(:validate_habitat_auth_token) }.must_raise SystemExit
end
end
describe '#build_hart' do
before do
subject.expects(:work_dir).at_least_once.returns(Dir.tmpdir)
end
it 'exits if the build fails' do
subject.expects(:system).returns(false)
proc { subject.send(:build_hart) }.must_raise SystemExit
end
it 'exits if more than one hart is created' do
subject.expects(:system).returns(true)
Dir.expects(:glob).returns(%w(hart1 hart2))
proc { subject.send(:build_hart) }.must_raise SystemExit
end
it 'exits if more than no hart is created' do
subject.expects(:system).returns(true)
Dir.expects(:glob).returns([])
proc { subject.send(:build_hart) }.must_raise SystemExit
end
it 'returns the hart filename' do
subject.expects(:system).returns(true)
Dir.expects(:glob).returns(%w(hart1))
subject.send(:build_hart).must_equal('hart1')
end
end
describe '#upload_hart' do
it 'exits if the upload failed' do
env = {
'TERM' => 'vt100',
'HAB_AUTH_TOKEN' => 'my_token',
'HAB_NONINTERACTIVE' => 'true',
}
cmd = mock
cmd.stubs(:run_command)
cmd.stubs(:error?).returns(true)
cmd.stubs(:stdout)
cmd.stubs(:stderr)
subject.expects(:habitat_auth_token).returns('my_token')
Mixlib::ShellOut.expects(:new).with("hab pkg upload my_hart", env: env).returns(cmd)
proc { subject.send(:upload_hart, 'my_hart') }.must_raise SystemExit
end
end
describe '#habitat_cli_config' do
it 'returns an empty hash if the CLI config does not exist' do
File.expects(:exist?).with(File.join(ENV['HOME'], '.hab', 'etc', 'cli.toml')).returns(false)
subject.send(:habitat_cli_config).must_equal({})
end
it 'returns parsed TOML from the hab config file' do
config_file = File.join(ENV['HOME'], '.hab', 'etc', 'cli.toml')
File.expects(:exist?).with(config_file).returns(true)
TOML.expects(:load_file).with(config_file).returns(foo: 1)
subject.send(:habitat_cli_config).must_equal(foo: 1)
end
end
end