From b98117efa693d5eb0e47adb5f633f3c8975cf11a Mon Sep 17 00:00:00 2001 From: danielsdeleo Date: Thu, 4 Dec 2014 15:31:58 -0800 Subject: [PATCH] Make export dir cleanliness checking more granular ExportRepo now only fails if there are files in cookbooks/ or data_bags/policyfiles/. Fixes an issue where export would not work with test kitchen when other kitchen directories were created first. --- .../policyfile_services/export_repo.rb | 31 ++++++++--- lib/kitchen/provisioner/policyfile_zero.rb | 3 +- .../policyfile_services/export_repo_spec.rb | 54 ++++++++++++++++--- 3 files changed, 72 insertions(+), 16 deletions(-) diff --git a/lib/chef-dk/policyfile_services/export_repo.rb b/lib/chef-dk/policyfile_services/export_repo.rb index aefee37ae..1ed5f6e8e 100644 --- a/lib/chef-dk/policyfile_services/export_repo.rb +++ b/lib/chef-dk/policyfile_services/export_repo.rb @@ -57,7 +57,7 @@ def policy_name def run assert_lockfile_exists! - assert_export_dir_empty! + assert_export_dir_clean! validate_lockfile write_updated_lockfile @@ -86,10 +86,12 @@ def export private def create_repo_structure - FileUtils.rm_rf(export_dir) + FileUtils.rm_rf(cookbooks_dir) + FileUtils.rm_rf(policyfiles_data_bag_dir) + FileUtils.mkdir_p(export_dir) - FileUtils.mkdir_p(File.join(export_dir, "cookbooks")) - FileUtils.mkdir_p(File.join(export_dir, "data_bags", "policyfiles")) + FileUtils.mkdir_p(cookbooks_dir) + FileUtils.mkdir_p(policyfiles_data_bag_dir) end def copy_cookbooks @@ -161,10 +163,10 @@ def assert_lockfile_exists! end end - def assert_export_dir_empty! - entries = Dir.glob(File.join(export_dir, "*")) - if !force_export? && !entries.empty? - raise ExportDirNotEmpty, "Export dir (#{export_dir}) not empty. Refusing to export." + def assert_export_dir_clean! + if !force_export? && !conflicting_fs_entries.empty? + msg = "Export dir (#{export_dir}) not clean. Refusing to export. (Conflicting files: #{conflicting_fs_entries.join(', ')})" + raise ExportDirNotEmpty, msg end end @@ -172,6 +174,19 @@ def force_export? @force_export end + def conflicting_fs_entries + Dir.glob(File.join(cookbooks_dir, "*")) + + Dir.glob(File.join(policyfiles_data_bag_dir, "*")) + end + + def cookbooks_dir + File.join(export_dir, "cookbooks") + end + + def policyfiles_data_bag_dir + File.join(export_dir, "data_bags", "policyfiles") + end + end end diff --git a/lib/kitchen/provisioner/policyfile_zero.rb b/lib/kitchen/provisioner/policyfile_zero.rb index a210af6c4..65f397595 100644 --- a/lib/kitchen/provisioner/policyfile_zero.rb +++ b/lib/kitchen/provisioner/policyfile_zero.rb @@ -119,8 +119,7 @@ def prepare_cookbooks # # @api private def policy_exporter - return @policy_exporter if @policy_exporter - @policy_exporter = ChefDK::PolicyfileServices::ExportRepo.new(export_dir: sandbox_path) + @policy_exporter ||= ChefDK::PolicyfileServices::ExportRepo.new(export_dir: sandbox_path) end # Writes a fake (but valid) validation.pem into the sandbox directory. diff --git a/spec/unit/policyfile_services/export_repo_spec.rb b/spec/unit/policyfile_services/export_repo_spec.rb index 94bc0c63f..0a1f740b8 100644 --- a/spec/unit/policyfile_services/export_repo_spec.rb +++ b/spec/unit/policyfile_services/export_repo_spec.rb @@ -235,21 +235,59 @@ end - context "When the export dir is already populated" do + context "When the export dir has non-conflicting content" do let(:file_in_export_dir) { File.join(export_dir, "some_random_cruft") } + let(:extra_data_bag_dir) { File.join(export_dir, "data_bags", "extraneous") } + + let(:extra_data_bag_item) { File.join(extra_data_bag_dir, "an_item.json") } + before do FileUtils.mkdir_p(export_dir) File.open(file_in_export_dir, "wb+") { |f| f.print "some random cruft" } + FileUtils.mkdir_p(extra_data_bag_dir) + File.open(extra_data_bag_item, "wb+") { |f| f.print "some random cruft" } + end + + it "ignores the non-conflicting content and exports" do + export_service.run + + expect(File).to exist(file_in_export_dir) + expect(File).to exist(extra_data_bag_item) + + expect(File).to be_directory(File.join(export_dir, "cookbooks")) + expect(File).to be_directory(File.join(export_dir, "data_bags")) + end + end + + context "When the export dir has conflicting content" do + + let(:non_conflicting_file_in_export_dir) { File.join(export_dir, "some_random_cruft") } + + let(:cookbooks_dir) { File.join(export_dir, "cookbooks") } + + let(:file_in_cookbooks_dir) { File.join(cookbooks_dir, "some_random_cruft") } + + let(:policyfiles_data_bag_dir) { File.join(export_dir, "data_bags", "policyfiles") } + + let(:extra_policyfile_data_item) { File.join(policyfiles_data_bag_dir, "leftover-policy.json") } + + before do + FileUtils.mkdir_p(export_dir) + FileUtils.mkdir_p(cookbooks_dir) + FileUtils.mkdir_p(policyfiles_data_bag_dir) + File.open(non_conflicting_file_in_export_dir, "wb+") { |f| f.print "some random cruft" } + File.open(file_in_cookbooks_dir, "wb+") { |f| f.print "some random cruft" } + File.open(extra_policyfile_data_item, "wb+") { |f| f.print "some random cruft" } end it "raises a PolicyfileExportRepoError" do - message = "Export dir (#{export_dir}) not empty. Refusing to export." + message = "Export dir (#{export_dir}) not clean. Refusing to export. (Conflicting files: #{file_in_cookbooks_dir}, #{extra_policyfile_data_item})" expect { export_service.run }.to raise_error(ChefDK::ExportDirNotEmpty, message) - expect(File).to be_file(file_in_export_dir) - expect(File).to_not exist(File.join(export_dir, "cookbooks")) - expect(File).to_not exist(File.join(export_dir, "data_bags")) + expect(File).to exist(non_conflicting_file_in_export_dir) + expect(File).to exist(file_in_cookbooks_dir) + expect(File).to exist(extra_policyfile_data_item) end context "and the force option is set" do @@ -259,7 +297,11 @@ it "clears the export dir and exports" do export_service.run - expect(File).to_not exist(file_in_export_dir) + expect(File).to_not exist(file_in_cookbooks_dir) + expect(File).to_not exist(extra_policyfile_data_item) + + expect(File).to exist(non_conflicting_file_in_export_dir) + expect(File).to be_directory(File.join(export_dir, "cookbooks")) expect(File).to be_directory(File.join(export_dir, "data_bags")) end