Skip to content

Commit

Permalink
added check for existing git cookbook tag in local store. Should spee…
Browse files Browse the repository at this point in the history
…d up minimart mirror significantly.

using lazy evaluation for getting cookbook metadata.

create a versioned metadata file.
Update base requirement metadata file to include requirement name, metadata_version
add logic to do stricter  matching_sources? for all requirements
created has_key? implementation for DownloadMetadata.
  • Loading branch information
Jason Kulatunga authored and berniedurfee-ge committed Mar 24, 2016
1 parent 8dcea21 commit fa330d9
Show file tree
Hide file tree
Showing 8 changed files with 103 additions and 7 deletions.
12 changes: 10 additions & 2 deletions lib/minimart/inventory_requirement/base_requirement.rb
Original file line number Diff line number Diff line change
Expand Up @@ -60,15 +60,23 @@ def version_requirement?
# Convert the requirement to a Hash.
# @return [Hash]
def to_hash
{}
{
:metadata_version => '2.0', #metadata document version.
:name => @name
}
end

# Determine if a cookbook in the inventory has metadata matching this requirement
# @param [Minimart::Mirror::DownloadMetadata] metadata The download metadata for a cookbook
# in the inventory.
# @return [Boolean] Defaults to true
def matching_source?(metadata)
return true
if metadata.has_key?('metadata_version') && metadata['metadata_version'] == '2.0'
metadata['name'] == @name &&
metadata['version'] == @version_requirement
else
true
end
end

private
Expand Down
13 changes: 10 additions & 3 deletions lib/minimart/inventory_requirement/git_requirement.rb
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,16 @@ def to_hash
# in the inventory.
# @return [Boolean] Defaults to true
def matching_source?(metadata)
metadata['source_type'] == 'git' &&
metadata['commitish_type'] == commitish_type.to_s &&
(metadata['commitish_type'] == 'ref' ? true : metadata['commitish'] == commitish.to_s)
if metadata.has_key?('metadata_version') && metadata['metadata_version'] == '2.0'
metadata['source_type'] == 'git' &&
metadata['location'] == @location &&
metadata['commitish_type'] == commitish_type.to_s &&
(metadata['commitish_type'] == 'ref' ? true : metadata['commitish'] == commitish.to_s)
else
metadata['source_type'] == 'git' &&
metadata['commitish_type'] == commitish_type.to_s &&
(metadata['commitish_type'] == 'ref' ? true : metadata['commitish'] == commitish.to_s)
end
end

private
Expand Down
8 changes: 7 additions & 1 deletion lib/minimart/inventory_requirement/local_path_requirement.rb
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,18 @@ def explicit_location?
# @return [Hash]
def to_hash
result = super
result[:path] = @path
result[:source_type] = :local_path
result
end

def matching_source?(metadata)
metadata['source_type'] == 'local_path'
if metadata.has_key?('metadata_version') && metadata['metadata_version'] == '2.0'
metadata['source_type'] == 'local_path' &&
metadata['path'] == @path
else
metadata['source_type'] == 'local_path'
end
end

private
Expand Down
4 changes: 4 additions & 0 deletions lib/minimart/mirror/download_metadata.rb
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@ def [](key)
metadata[key] if metadata
end

def has_key?(key)
(metadata ? metadata.has_key?(key) : false)
end

private

def parse_file
Expand Down
7 changes: 6 additions & 1 deletion lib/minimart/mirror/inventory_builder.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
require 'ridley'
module Minimart
module Mirror

Expand Down Expand Up @@ -35,6 +34,12 @@ def build!
def install_cookbooks_with_explicit_location
inventory_requirements.each_with_explicit_location do |requirement|
begin
requirement_cookbook = local_store.cookbook_for_requirement(requirement)
if requirement_cookbook
Configuration.output.puts_yellow("cookbook already installed: #{requirement_cookbook}.")
next
end

requirement.fetch_cookbook do |cookbook|
validate_cookbook_against_local_store(cookbook, requirement)
add_artifact_to_graph(cookbook)
Expand Down
28 changes: 28 additions & 0 deletions lib/minimart/mirror/local_store.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,19 @@ class LocalStore
def initialize(directory_path)
@directory_path = directory_path
@cookbooks = {}
@metadata = {}

load_local_inventory

end

# :nodoc:
def add_cookbook_to_store(name, version)
cookbooks[name] ||= []
cookbooks[name] << version

metadata[name] ||= {}
metadata[name][version] = local_path_for("#{name}-#{version}")
end

# Copy a given cookbook to the local store, and record any metadata
Expand All @@ -45,6 +50,28 @@ def installed?(cookbook_name, cookbook_version)
cookbooks[cookbook_name].include?(cookbook_version))
end

def cookbook_for_requirement(requirement)
#we dont handle caching for anything other than git requirements in this function.
return nil unless requirement.is_a?(InventoryRequirement::GitRequirement)
# if this is a branch, we can't assume that the commit is the same (remote could have changed)
return nil if requirement.branch

@metadata.each{ |cookbook, versions|

versions.each{ |version, lazy_metadata|
#lazy populate the metadata
if(lazy_metadata.is_a?(String))
lazy_metadata = Minimart::Mirror::DownloadMetadata.new(lazy_metadata)
end

if requirement.matching_source?(lazy_metadata)
return "#{cookbook}-#{version}"
end
}
}
return nil
end

# Validate that a new resolved requirement is not in the local store
# with different requirements. If we download two different branches
# of the same cookbook and they both resolve to the same version, then we
Expand All @@ -64,6 +91,7 @@ def validate_resolved_requirement(new_cookbook, requirement)
private

attr_reader :cookbooks
attr_reader :metadata

def copy_cookbook(source, destination)
FileUtils.rm_rf(destination) if Dir.exists?(destination)
Expand Down
3 changes: 3 additions & 0 deletions lib/minimart/mirror/source_cookbook.rb
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,9 @@ def fetch(&block)
# @return [Hash]
def to_hash
{
metadata_version: '2.0',
name: @name,
version: @version,
source_type: location_type,
location: location_path
}
Expand Down
35 changes: 35 additions & 0 deletions spec/lib/minimart/mirror/local_store_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -61,4 +61,39 @@
end
end

describe '#cookbook_for_requirement' do
let(:sample_cookbook_path) { 'spec/fixtures/sample_cookbook' }
it 'should return cookbook name when requirement matches existing cookbook' do
subject.add_cookbook_from_path(sample_cookbook_path, {
'source_type' => 'git',
'location' => 'spec/fixtures/sample_cookbook',
'commitish_type' => 'tag',
'commitish' => 'v1.2.3'})

requirement = Minimart::InventoryRequirement::GitRequirement.new('sample_cookbook', {
:tag => 'v1.2.3',
:location => 'spec/fixtures/sample_cookbook',
:version_requirement => '1.2.3'
})

expect(subject.cookbook_for_requirement(requirement)).to eq 'sample_cookbook-1.2.3'
end

it 'should return nil when requirement does not match any existing cookbook' do
subject.add_cookbook_from_path(sample_cookbook_path, {
'source_type' => 'git',
'location' => 'spec/fixtures/sample_cookbook',
'commitish_type' => 'tag',
'commitish' => 'v1.2.3'})

requirement = Minimart::InventoryRequirement::GitRequirement.new('sample_cookbook', {
:branch => 'feature_branch',
:location => 'spec/fixtures/sample_cookbook',
:version_requirement => '1.2.3'
})

expect(subject.cookbook_for_requirement(requirement)).to eq nil
end
end

end

0 comments on commit fa330d9

Please sign in to comment.