lib/chef-cli/policyfile/chef_repo_cookbook_source.rb
# # Copyright:: Copyright (c) 2014-2018 Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # require_relative "../exceptions" require "chef/cookbook_loader" require "chef/cookbook/file_system_file_vendor" require_relative "../ui" module ChefCLI module Policyfile class ChefRepoCookbookSource # path to a chef-repo or the cookbook path under it attr_reader :path # UI object for output attr_accessor :ui attr_reader :preferred_cookbooks # Constructor # # @param path [String] path to a chef-repo or the cookbook path under it def initialize(path) self.path = path @ui = UI.new @preferred_cookbooks = [] yield self if block_given? end def default_source_args [:chef_repo, path] end def preferred_for(*cookbook_names) preferred_cookbooks.concat(cookbook_names) end def preferred_source_for?(cookbook_name) preferred_cookbooks.include?(cookbook_name) end def ==(other) other.is_a?(self.class) && other.path == path && other.preferred_cookbooks == preferred_cookbooks end # Calls the slurp_metadata! helper once to calculate the @universe_graph # and @cookbook_version_paths metadata. Returns the @universe_graph. # # @return [Hash] universe_graph def universe_graph slurp_metadata! if @universe_graph.nil? @universe_graph end # Returns the metadata (path and version) for an individual cookbook # # @return [Hash] metadata for a single cookbook version def source_options_for(cookbook_name, cookbook_version) { path: cookbook_version_paths[cookbook_name][cookbook_version], version: cookbook_version } end def null? false end def desc "chef_repo(#{path})" end private # Setter for setting the path. It may either be a full chef-repo with # a cookbooks directory in it, or only a path to the cookbooks directory, # and it autodetects which it is passed. # # @param path [String] path to a chef-repo or the cookbook path under it def path=(path) cookbooks_path = "#{path}/cookbooks" if Dir.exist?(cookbooks_path) @path = cookbooks_path else @path = path end end # Calls the slurp_metadata! helper once to calculate the @universe_graph # and @cookbook_version_paths metadata. Returns the @cookbook_version_paths. # # @return [Hash] cookbook_version_paths def cookbook_version_paths slurp_metadata! if @cookbook_version_paths.nil? @cookbook_version_paths end # Helper to compute the @universe_graph and @cookbook_version_paths once # from the Chef::CookbookLoader on-disk cookbook repo. def slurp_metadata! @universe_graph = {} @cookbook_version_paths = {} cookbook_repo.load_cookbooks cookbook_repo.each do |cookbook_name, cookbook_version| metadata = cookbook_version.metadata if metadata.name.nil? ui.err("WARN: #{cookbook_name} cookbook missing metadata or no name field, skipping") next end @universe_graph[metadata.name] ||= {} @universe_graph[metadata.name][metadata.version] = metadata.dependencies.to_a @cookbook_version_paths[metadata.name] ||= {} @cookbook_version_paths[metadata.name][metadata.version] = cookbook_version.root_dir end end # @return [Chef::CookbookLoader] cookbook loader using on disk FileVendor def cookbook_repo @cookbook_repo ||= begin Chef::Cookbook::FileVendor.fetch_from_disk(path) Chef::CookbookLoader.new(path) end end end end end