require 'spec_helper' describe Minimart::Mirror::InventoryBuilder do subject do Minimart::Mirror::InventoryBuilder.new(test_directory, inventory_config) end describe '#build' do describe 'when a git cookbook is present' do let(:inventory_config) do Minimart::Mirror::InventoryConfiguration.new('spec/fixtures/simple_git_inventory.yml') end before(:each) do # stub out actually cloning the repo allow_any_instance_of(Minimart::Download::GitRepository).to receive(:fetch).and_yield 'spec/fixtures/sample_cookbook' end around(:each) do |e| VCR.use_cassette('location_specific_cookbooks') { e.call } end it 'should add the cookbook to the graph' do subject.build! expect(subject.graph.source_cookbook_added?('sample_cookbook', '1.2.3')).to eq true end it 'should add the cookbook to the local store' do subject.build! expect(subject.local_store.installed?('sample_cookbook', '1.2.3')).to eq true end it 'should add any dependencies of the cookbook to the local store' do subject.build! expect(subject.local_store.installed?('yum', '3.5.1')).to eq true end it 'should clear the git cache' do expect_any_instance_of(Minimart::Download::GitCache).to receive :clear subject.build! end it 'should store metadata about downloading the cookbook' do subject.build! metadata = JSON.parse(File.open(File.join(test_directory, 'sample_cookbook-1.2.3', '.minimart.json')).read) expect(metadata).to include( 'source_type' => 'git', 'location' => 'spec/fixtures/sample_cookbook', 'commitish_type' => 'tag', 'commitish' => 'v1.2.3') end context 'when the same cookbook is present in the local store with a different source' do before(:each) do subject.build! allow_any_instance_of(Minimart::Cookbook).to receive(:download_metadata).and_return( 'source_type' => 'git', 'location' => 'spec/fixtures/sample_cookbook', 'commitish_type' => 'ref', 'commitish' => 'SHA') end it 'should raise an error' do expect { subject.build! }.to raise_error Minimart::Error::BrokenDependency end end end describe 'when a cookbook with a local path is present' do let(:inventory_config) do Minimart::Mirror::InventoryConfiguration.new('spec/fixtures/simple_local_path_inventory.yml') end around(:each) do |e| VCR.use_cassette('local_path_cookbooks') { e.call } end it 'should add the cookbook to the graph' do subject.build! expect(subject.graph.source_cookbook_added?('sample_cookbook', '1.2.3')).to eq true end it 'should add the cookbook to the local store' do subject.build! expect(subject.local_store.installed?('sample_cookbook', '1.2.3')).to eq true end it 'should add any dependencies of the cookbook to the local store' do subject.build! expect(subject.local_store.installed?('yum', '3.5.1')).to eq true end it 'should store metadata about downloading the cookbook' do subject.build! metadata = JSON.parse(File.open(File.join(test_directory, 'sample_cookbook-1.2.3', '.minimart.json')).read) expect(metadata).to include('source_type' => 'local_path') end end describe 'fetching cookbooks from a supermarket' do let(:inventory_config) do Minimart::Mirror::InventoryConfiguration.new('spec/fixtures/simple_inventory.yml') end describe 'building the dependency graph' do before(:each) do stub_request(:get, "https://supermarket.getchef.com/universe"). to_return(status: 200, body: File.open('spec/fixtures/universe.json').read) end around(:each) do |e| VCR.use_cassette('supermarket_cookbooks_graph') { e.call } end let(:expected_universe) do [['mysql', '5.6.1'], ['mysql', '5.5.4'], ['yum', '3.4.1', '3.3.1']] end it 'should populate the dependency graph with anything returned by the universe' do subject.build! expected_universe.each do |name, version| expect(subject.graph.source_cookbook_added?(name, version)).to eq true end end end describe 'installing cookbooks' do around(:each) do |e| VCR.use_cassette('supermarket_cookbooks_installing_cookbooks') { e.call } end it 'should add the resolved version of the cookbook to the local store' do subject.build! expect(subject.local_store.installed?('mysql', '5.5.4')).to eq true end it 'should add the cookbook to the local inventory' do subject.build! expect(Dir.exists?(File.join(test_directory, 'mysql-5.5.4'))).to eq true end it 'should add any resolved dependencies to the local store' do subject.build! expect(subject.local_store.installed?('yum', '3.5.1')).to eq true expect(subject.local_store.installed?('yum-mysql-community', '0.1.10')).to eq true end it 'should actually add the dependent cookbooks to the local inventory' do subject.build! expect(Dir.exists?(File.join(test_directory, 'yum-3.5.1'))).to eq true expect(Dir.exists?(File.join(test_directory, 'yum-mysql-community-0.1.10'))).to eq true end it 'should store metadata about downloading the cookbook' do subject.build! metadata = JSON.parse(File.open(File.join(test_directory, 'mysql-5.5.4', '.minimart.json')).read) expect(metadata).to include( 'source_type' => 'opscode', 'location' => 'https://supermarket.chef.io/api/v1') end context 'when a cookbook has already been installed' do before(:each) do allow(subject.local_store).to receive(:installed?).and_return true end it 'should not download the cookbooks a second time' do expect(Minimart::Download::Cookbook).to_not receive(:download) subject.build! end end context 'when a coookbook depends on a non explicit version of a required cookbook' do let(:bad_requirements) do [%w[mysql 5.4], %w[mysql 0.0.1]] end before(:each) do allow_any_instance_of(Minimart::Mirror::DependencyGraph).to receive(:resolved_requirements).and_return(bad_requirements) end it 'should raise an error' do expect { subject.build! }.to raise_error Minimart::Error::BrokenDependency end end end end end end