class Berkshelf::Installer
Attributes
berksfile[R]
downloader[R]
lockfile[R]
pool[R]
worker[R]
Public Class Methods
new(berksfile)
click to toggle source
@param [Berkshelf::Berksfile] berksfile
# File lib/berkshelf/installer.rb, line 12 def initialize(berksfile) @berksfile = berksfile @lockfile = berksfile.lockfile @pool = Concurrent::FixedThreadPool.new([Concurrent.processor_count - 1, 2].max) @worker = Worker.new(berksfile) end
Public Instance Methods
build_universe()
click to toggle source
# File lib/berkshelf/installer.rb, line 19 def build_universe berksfile.sources.collect do |source| Thread.new do Berkshelf.formatter.msg("Fetching cookbook index from #{source}...") source.build_universe rescue Berkshelf::APIClientError => ex Berkshelf.formatter.warn "Error retrieving universe from source: #{source}" Berkshelf.formatter.warn " * [#{ex.class}] #{ex}" end end.map(&:join) end
run()
click to toggle source
@return [Array<Berkshelf::CachedCookbook>]
# File lib/berkshelf/installer.rb, line 34 def run lockfile.reduce! Berkshelf.formatter.msg("Resolving cookbook dependencies...") dependencies, cookbooks = if lockfile.trusted? install_from_lockfile else install_from_universe end Berkshelf.log.debug " Finished resolving, calculating locks" to_lock = dependencies.select do |dependency| berksfile.has_dependency?(dependency) end Berkshelf.log.debug " New locks" to_lock.each do |lock| Berkshelf.log.debug " #{lock}" end lockfile.graph.update(cookbooks) lockfile.update(to_lock) lockfile.save cookbooks end
Private Instance Methods
download_locations(dependencies)
click to toggle source
# File lib/berkshelf/installer.rb, line 189 def download_locations(dependencies) dependencies.select(&:location).each do |dependency| unless dependency.location.installed? Berkshelf.formatter.fetch(dependency) dependency.location.install end end end
install_from_lockfile()
click to toggle source
Install all the dependencies from the lockfile graph.
@return [Array<Array<Dependency> Array<CachedCookbook>>]
the list of installed dependencies and cookbooks
# File lib/berkshelf/installer.rb, line 119 def install_from_lockfile Berkshelf.log.info "Installing from lockfile" dependencies = lockfile.graph.locks.values Berkshelf.log.debug " Dependencies" dependencies.map do |dependency| Berkshelf.log.debug " #{dependency}" end download_locations(dependencies) # Only construct the universe if we are going to install things unless dependencies.all?(&:installed?) Berkshelf.log.debug " Not all dependencies are installed" build_universe end futures = dependencies.sort.map { |dependency| Concurrent::Future.execute(executor: pool) { worker.install(dependency) } } cookbooks = futures.map(&:value) rejects = futures.select(&:rejected?) raise rejects.first.reason unless rejects.empty? [dependencies, cookbooks] end
install_from_universe()
click to toggle source
Resolve and install the dependencies from the “universe”, updating the lockfile appropiately.
@return [Array<Array<Dependency> Array<CachedCookbook>>]
the list of installed dependencies and cookbooks
# File lib/berkshelf/installer.rb, line 150 def install_from_universe Berkshelf.log.info "Installing from universe" dependencies = lockfile.graph.locks.values + berksfile.dependencies dependencies = dependencies.inject({}) do |hash, dependency| # Fancy way of ensuring no duplicate dependencies are used... hash[dependency.name] ||= dependency hash end.values download_locations(dependencies) Berkshelf.log.debug " Creating a resolver" resolver = Resolver.new(berksfile, dependencies) # Unlike when installing from the lockfile, we _always_ need to build # the universe when installing from the universe... duh build_universe # Add any explicit dependencies for already-downloaded cookbooks (like # path locations) dependencies.each do |dependency| if dependency.location cookbook = dependency.cached_cookbook Berkshelf.log.debug " Adding explicit dependency on #{cookbook}" resolver.add_explicit_dependencies(cookbook) end end Berkshelf.log.debug " Starting resolution..." futures = resolver.resolve.sort.map { |dependency| Concurrent::Future.execute(executor: pool) { worker.install(dependency) } } cookbooks = futures.map(&:value) rejects = futures.select(&:rejected?) raise rejects.first.reason unless rejects.empty? [dependencies, cookbooks] end