Skip to content

Commit

Permalink
Merge pull request chef#8925 from MsysTechnologiesllc/VSingh/MSYS-110…
Browse files Browse the repository at this point in the history
…9_chefignore_for_respective_cookbook_dir

Fix multiple chefignore file issues
  • Loading branch information
tas50 authored Nov 1, 2019
2 parents 09a210c + dd682d9 commit a421bf3
Show file tree
Hide file tree
Showing 18 changed files with 94 additions and 40 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ def upload_cookbook(other, options)
file_class.symlink other.file_path, proxy_cookbook_path

# Instantiate a proxy loader using the temporary symlink
proxy_loader = Chef::Cookbook::CookbookVersionLoader.new(proxy_cookbook_path, other.parent.chefignore)
proxy_loader = Chef::Cookbook::CookbookVersionLoader.new(proxy_cookbook_path, other.chefignore)
proxy_loader.load_cookbooks

cookbook_to_upload = proxy_loader.cookbook_version
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ def upload_cookbook(other, options)
file_class.symlink other.file_path, proxy_cookbook_path

# Instantiate a proxy loader using the temporary symlink
proxy_loader = Chef::Cookbook::CookbookVersionLoader.new(proxy_cookbook_path, other.parent.chefignore)
proxy_loader = Chef::Cookbook::CookbookVersionLoader.new(proxy_cookbook_path, other.chefignore)
proxy_loader.load_cookbooks

cookbook_to_upload = proxy_loader.cookbook_version
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ module Repository
class ChefRepositoryFileSystemCookbookArtifactDir < ChefRepositoryFileSystemCookbookDir
# Override from parent
def cookbook_version
loader = Chef::Cookbook::CookbookVersionLoader.new(file_path, parent.chefignore)
loader = Chef::Cookbook::CookbookVersionLoader.new(file_path, chefignore)
cookbook_name, _dash, identifier = name.rpartition("-")
# KLUDGE: We shouldn't have to use instance_variable_set
loader.instance_variable_set(:@cookbook_name, cookbook_name)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
require_relative "../chef_server/versioned_cookbook_dir"
require_relative "../exceptions"
require_relative "../../../cookbook/cookbook_version_loader"
require_relative "../../../cookbook/chefignore"

class Chef
module ChefFS
Expand All @@ -31,6 +32,11 @@ module Repository
class ChefRepositoryFileSystemCookbookDir < ChefRepositoryFileSystemCookbookEntry

# API Required by Respository::Directory
def chefignore
@chefignore ||= Chef::Cookbook::Chefignore.new(file_path)
rescue Errno::EISDIR, Errno::EACCES
# Work around a bug in Chefignore when chefignore is a directory
end

def fs_entry_valid?
return false unless File.directory?(file_path) && name_valid?
Expand Down Expand Up @@ -136,7 +142,7 @@ def make_child_entry(child_name)
end

def cookbook_version
loader = Chef::Cookbook::CookbookVersionLoader.new(file_path, parent.chefignore)
loader = Chef::Cookbook::CookbookVersionLoader.new(file_path, chefignore)
loader.load_cookbooks
loader.cookbook_version
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,13 +68,14 @@ def can_have_child?(name, is_dir)
end

# Check chefignore
ignorer = parent
ignorer = self

loop do
if ignorer.is_a?(CookbooksDir)
if ignorer.is_a?(ChefRepositoryFileSystemCookbookDir)
# Grab the path from entry to child
path_to_child = name
child = self
while child.parent != ignorer
while child != ignorer
path_to_child = PathUtils.join(child.name, path_to_child)
child = child.parent
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ module Repository
class ChefRepositoryFileSystemVersionedCookbookDir < ChefRepositoryFileSystemCookbookDir
# Override from parent
def cookbook_version
loader = Chef::Cookbook::CookbookVersionLoader.new(file_path, parent.chefignore)
loader = Chef::Cookbook::CookbookVersionLoader.new(file_path, chefignore)
# We need the canonical cookbook name if we are using versioned cookbooks, but we don't
# want to spend a lot of time adding code to the main Chef libraries
canonical_name = canonical_cookbook_name(File.basename(file_path))
Expand Down
27 changes: 16 additions & 11 deletions lib/chef/cookbook/chefignore.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,9 @@ class Chefignore
attr_reader :ignores

def initialize(ignore_file_or_repo)
# Check the 'ignore_file_or_repo' path first and then look in the parent directory
# Check the 'ignore_file_or_repo' path first and then look in the parent directories till root
# to handle both the chef repo cookbook layout and a standalone cookbook
@ignore_file = find_ignore_file(ignore_file_or_repo)
@ignore_file = find_ignore_file(File.dirname(ignore_file_or_repo)) unless readable_file_or_symlink?(@ignore_file)

@ignores = parse_ignore_file
end

Expand All @@ -50,27 +48,34 @@ def ignored?(file_name)

def parse_ignore_file
ignore_globs = []
if readable_file_or_symlink?(@ignore_file)
if @ignore_file && readable_file_or_symlink?(@ignore_file)
File.foreach(@ignore_file) do |line|
ignore_globs << line.strip unless line =~ COMMENTS_AND_WHITESPACE
end
else
Chef::Log.trace("No chefignore file found at #{@ignore_file} no files will be ignored")
Chef::Log.debug("No chefignore file found. No files will be ignored!")
end
ignore_globs
end

# Lookup of chefignore file till the root dir of the provided path.
# If file refer then lookup the parent dir till the root.
# eg. path: /var/.chef/cookbook_name
# Lookup at '/var/.chef/cookbook_name/chefignore', '/var/.chef/chefignore' '/var/chefignore' and '/chefignore' until exist
def find_ignore_file(path)
if File.basename(path) =~ /chefignore/
path
else
File.join(path, "chefignore")
Pathname.new(path).ascend do |dir|
next unless dir.directory?

file = dir.join("chefignore")
return file.expand_path.to_s if file.exist?
end

nil
end

def readable_file_or_symlink?(path)
File.exist?(@ignore_file) && File.readable?(@ignore_file) &&
(File.file?(@ignore_file) || File.symlink?(@ignore_file))
File.exist?(path) && File.readable?(path) &&
(File.file?(path) || File.symlink?(path))
end
end
end
Expand Down
2 changes: 1 addition & 1 deletion lib/chef/cookbook/cookbook_version_loader.rb
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ def empty?
end

def chefignore
@chefignore ||= Chefignore.new(File.basename(cookbook_path))
@chefignore ||= Chefignore.new(cookbook_path)
end

# Enumerate all the files in a cookbook and assign the resulting list to
Expand Down
8 changes: 5 additions & 3 deletions lib/chef/cookbook/syntax_check.rb
Original file line number Diff line number Diff line change
Expand Up @@ -84,11 +84,13 @@ def ensure_cache_path_created
# If no +cookbook_path+ is given, +Chef::Config.cookbook_path+ is used.
def self.for_cookbook(cookbook_name, cookbook_path = nil)
cookbook_path ||= Chef::Config.cookbook_path
unless cookbook_path
raise ArgumentError, "Cannot find cookbook #{cookbook_name} unless Chef::Config.cookbook_path is set or an explicit cookbook path is given"

Array(cookbook_path).each do |entry|
path = File.expand_path(File.join(entry, cookbook_name.to_s))
return new(path) if Dir.exist?(path)
end

new(File.join(cookbook_path, cookbook_name.to_s))
raise ArgumentError, "Cannot find cookbook #{cookbook_name} unless Chef::Config.cookbook_path is set or an explicit cookbook path is given"
end

# Create a new SyntaxCheck object
Expand Down
6 changes: 3 additions & 3 deletions lib/chef/cookbook_loader.rb
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,8 @@ class CookbookLoader

# @param repo_paths [Array<String>] the array of repo paths containing cookbook dirs
def initialize(*repo_paths)
@repo_paths = repo_paths.flatten.map { |p| File.expand_path(p) }
raise ArgumentError, "You must specify at least one cookbook repo path" if repo_paths.empty?
@repo_paths = repo_paths.flatten.compact.map { |p| File.expand_path(p) }
raise ArgumentError, "You must specify at least one cookbook repo path" if @repo_paths.empty?
end

# The primary function of this class is to build this Mash mapping cookbook names as a string to
Expand Down Expand Up @@ -171,7 +171,7 @@ def cookbook_version_loaders
begin
mash = Mash.new
all_directories_in_repo_paths.each do |cookbook_path|
loader = Cookbook::CookbookVersionLoader.new(cookbook_path, chefignore(File.dirname(cookbook_path)))
loader = Cookbook::CookbookVersionLoader.new(cookbook_path, chefignore(cookbook_path))
cookbook_name = loader.cookbook_name
if mash.key?(cookbook_name)
raise Chef::Exceptions::CookbookMergingError, "Cookbook merging is no longer supported, the cookbook named #{cookbook_name} can only appear once in the cookbook_path"
Expand Down
2 changes: 1 addition & 1 deletion lib/chef/cookbook_uploader.rb
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ def uploader_function_for(file, checksum, url, checksums_to_upload)

def validate_cookbooks
cookbooks.each do |cb|
syntax_checker = Chef::Cookbook::SyntaxCheck.for_cookbook(cb.name)
syntax_checker = Chef::Cookbook::SyntaxCheck.new(cb.root_dir)
Chef::Log.info("Validating ruby files")
exit(1) unless syntax_checker.validate_ruby_files
Chef::Log.info("Validating templates")
Expand Down
8 changes: 8 additions & 0 deletions spec/data/cookbooks/starter/chefignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#
# The ignore file allows you to skip files in cookbooks with the same name that appear
# later in the search path.
#

recipes/default.rb
# comments can be indented
ignored
1 change: 1 addition & 0 deletions spec/data/cookbooks/starter/files/sample.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
This is a Chef cookbook file. It is used to copy content verbatim on to a server.
2 changes: 2 additions & 0 deletions spec/data/cookbooks/starter/metadata.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
name "starter"
version "1.0.0"
4 changes: 4 additions & 0 deletions spec/data/cookbooks/starter/recipes/default.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# This is a Chef recipe file. It can be used to specify resources which will
# apply configuration to a server.

# For more information, see the documentation: https://docs.chef.io/essentials_cookbook_recipes.html
42 changes: 31 additions & 11 deletions spec/unit/cookbook/chefignore_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,32 +18,52 @@
require "spec_helper"

describe Chef::Cookbook::Chefignore do
before do
@chefignore = Chef::Cookbook::Chefignore.new(File.join(CHEF_SPEC_DATA, "cookbooks"))
end
let(:chefignore) { described_class.new(File.join(CHEF_SPEC_DATA, "cookbooks")) }

it "loads the globs in the chefignore file" do
expect(@chefignore.ignores).to match_array(%w{recipes/ignoreme.rb ignored})
expect(chefignore.ignores).to match_array(%w{recipes/ignoreme.rb ignored})
end

it "removes items from an array that match the ignores" do
file_list = %w{ recipes/ignoreme.rb recipes/dontignoreme.rb }
expect(@chefignore.remove_ignores_from(file_list)).to eq(%w{recipes/dontignoreme.rb})
expect(chefignore.remove_ignores_from(file_list)).to eq(%w{recipes/dontignoreme.rb})
end

it "determines if a file is ignored" do
expect(@chefignore.ignored?("ignored")).to be_truthy
expect(@chefignore.ignored?("recipes/ignoreme.rb")).to be_truthy
expect(@chefignore.ignored?("recipes/dontignoreme.rb")).to be_falsey
expect(chefignore.ignored?("ignored")).to be_truthy
expect(chefignore.ignored?("recipes/ignoreme.rb")).to be_truthy
expect(chefignore.ignored?("recipes/dontignoreme.rb")).to be_falsey
end

context "when using the single cookbook pattern" do
before do
@chefignore = Chef::Cookbook::Chefignore.new(File.join(CHEF_SPEC_DATA, "standalone_cookbook"))
let(:chefignore) { described_class.new(File.join(CHEF_SPEC_DATA, "cookbooks/starter")) }

it "loads the globs in the chefignore file" do
expect(chefignore.ignores).to match_array(%w{recipes/default.rb ignored})
end
end

context "when cookbook has it's own chefignore" do
let(:chefignore) { described_class.new(File.join(CHEF_SPEC_DATA, "cookbooks/starter")) }

it "loads the globs in the chefignore file" do
expect(chefignore.ignores).to match_array(%w{recipes/default.rb ignored})
end
end

context "when cookbook don't have own chefignore" do
let(:chefignore) { described_class.new(File.join(CHEF_SPEC_DATA, "cookbooks/apache2")) }

it "loads the globs in the chefignore file of cookbooks dir" do
expect(chefignore.ignores).to match_array(%w{recipes/ignoreme.rb ignored})
end
end

context "when using the single cookbook pattern" do
let(:chefignore) { described_class.new(File.join(CHEF_SPEC_DATA, "standalone_cookbook")) }

it "loads the globs in the chefignore file" do
expect(@chefignore.ignores).to match_array(%w{recipes/ignoreme.rb ignored vendor/bundle/*})
expect(chefignore.ignores).to match_array(%w{recipes/ignoreme.rb ignored vendor/bundle/*})
end
end
end
2 changes: 1 addition & 1 deletion spec/unit/cookbook_loader_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ def full_paths_for_part(cb, part)
cookbook_loader.each_key do |cookbook_name|
seen << cookbook_name
end
expect(seen).to eq %w{angrybash apache2 borken ignorken irssi java name-mismatch openldap preseed supports-platform-constraints wget}
expect(seen).to eq %w{angrybash apache2 borken ignorken irssi java name-mismatch openldap preseed starter supports-platform-constraints wget}
end
end

Expand Down
7 changes: 6 additions & 1 deletion spec/unit/cookbook_uploader_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,10 @@
describe Chef::CookbookUploader do

let(:http_client) { double("Chef::ServerAPI") }
let(:cookbook_path) { File.join(CHEF_SPEC_DATA, "cookbooks") }

let(:cookbook_loader) do
loader = Chef::CookbookLoader.new(File.join(CHEF_SPEC_DATA, "cookbooks"))
loader = Chef::CookbookLoader.new(cookbook_path)
loader.load_cookbooks
loader.cookbooks_by_name["apache2"].identifier = apache2_identifier
loader.cookbooks_by_name["java"].identifier = java_identifier
Expand Down Expand Up @@ -55,6 +56,10 @@

let(:uploader) { described_class.new(cookbooks_to_upload, rest: http_client, policy_mode: policy_mode) }

before do
allow(Chef::Config).to receive(:cookbook_path) { cookbook_path }
end

it "defaults to not enabling policy mode" do
expect(described_class.new(cookbooks_to_upload, rest: http_client).policy_mode?).to be(false)
end
Expand Down

0 comments on commit a421bf3

Please sign in to comment.