summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordanielsdeleo <dan@opscode.com>2012-12-20 16:12:34 -0800
committerdanielsdeleo <dan@opscode.com>2012-12-21 12:15:18 -0800
commit2c460c191bcdb1acfe6978a6e7e7ff8e0273f973 (patch)
tree4a4a2d5e30377c6eb2e2f59e42674b789f2c07f6
parent6bdcab78353213c189c4feb9097949633b8e8e7b (diff)
downloadchef-2c460c191bcdb1acfe6978a6e7e7ff8e0273f973.tar.gz
[CHEF-3715] remove caching of sha256 cksums
This also eliminates the dependency on moneta.
-rw-r--r--chef.gemspec3
-rw-r--r--lib/chef/checksum_cache.rb131
-rw-r--r--lib/chef/config.rb4
-rw-r--r--lib/chef/monkey_patches/moneta.rb50
-rw-r--r--spec/unit/checksum_cache_spec.rb161
-rw-r--r--spec/unit/cookbook/syntax_check_spec.rb5
-rw-r--r--spec/unit/provider/file_spec.rb13
-rw-r--r--spec/unit/provider/template_spec.rb1
8 files changed, 18 insertions, 350 deletions
diff --git a/chef.gemspec b/chef.gemspec
index fcf5d2b8ec..9de2822270 100644
--- a/chef.gemspec
+++ b/chef.gemspec
@@ -26,9 +26,8 @@ Gem::Specification.new do |s|
s.add_dependency "net-ssh-multi", "~> 1.1.0"
# CHEF-3027: The knife-cloud plugins require newer features from highline, core chef should not.
s.add_dependency "highline", ">= 1.6.9"
- %w{erubis moneta}.each { |gem| s.add_dependency gem }
+ s.add_dependency "erubis"
- # development_dependency thin: eventmachine 0.12.10 doesn't support Ruby 1.9 on Windows
%w(rdoc sdoc ronn rake rack rspec_junit_formatter).each { |gem| s.add_development_dependency gem }
%w(rspec-core rspec-expectations rspec-mocks).each { |gem| s.add_development_dependency gem, "~> 2.8.0" }
diff --git a/lib/chef/checksum_cache.rb b/lib/chef/checksum_cache.rb
index 6db7115a56..23ac195892 100644
--- a/lib/chef/checksum_cache.rb
+++ b/lib/chef/checksum_cache.rb
@@ -18,84 +18,13 @@
# limitations under the License.
#
-require 'set'
-require 'fileutils'
-require 'chef/log'
-require 'chef/config'
-require 'chef/client'
-require 'chef/mixin/convert_to_class_name'
-require 'singleton'
-require 'moneta'
+require 'digest'
class Chef
class ChecksumCache
- include Chef::Mixin::ConvertToClassName
- include ::Singleton
- attr_reader :moneta
-
- def initialize(*args)
- self.reset!(*args)
- end
-
- def reset!(backend=nil, options=nil)
- backend ||= Chef::Config[:cache_type]
- options ||= Chef::Config[:cache_options]
-
- begin
- require "moneta/#{convert_to_snake_case(backend, 'Moneta')}"
- require 'chef/monkey_patches/moneta'
- rescue LoadError => e
- Chef::Log.fatal("Could not load Moneta back end #{backend.inspect}")
- raise e
- end
-
- @moneta = Moneta.const_get(backend).new(options)
- end
-
- def self.reset_cache_validity
- @valid_cached_checksums = nil
- end
-
- Chef::Client.when_run_starts do |run_status|
- reset_cache_validity
- end
-
- def self.valid_cached_checksums
- @valid_cached_checksums ||= Set.new
- end
-
- def self.validate_checksum(checksum_key)
- valid_cached_checksums << checksum_key
- end
-
- def self.all_cached_checksums
- all_checksums_with_filenames = {}
-
- Dir[File.join(Chef::Config[:cache_options][:path], '*')].each do |cksum_file|
- all_checksums_with_filenames[File.basename(cksum_file)] = cksum_file
- end
- all_checksums_with_filenames
- end
-
- def self.cleanup_checksum_cache
- Chef::Log.debug("Cleaning the checksum cache")
- if (Chef::Config[:cache_type].to_s == "BasicFile")
- all_cached_checksums.each do |cache_key, cksum_cache_file|
- unless valid_cached_checksums.include?(cache_key)
- remove_unused_checksum(cksum_cache_file)
- end
- end
- end
- end
-
- Chef::Client.when_run_completes_successfully do |run_status|
- cleanup_checksum_cache
- end
-
- def self.remove_unused_checksum(checksum_file)
- Chef::Log.debug("Removing unused checksum cache file #{checksum_file}")
- FileUtils.rm(checksum_file)
+ def self.instance
+ @instance ||= new
end
def self.checksum_for_file(*args)
@@ -106,31 +35,12 @@ class Chef
self.class.validate_checksum(*args)
end
- def checksum_for_file(file, key=nil)
- key ||= generate_key(file)
- fstat = File.stat(file)
- lookup_checksum(key, fstat) || generate_checksum(key, file, fstat)
- end
-
- def lookup_checksum(key, fstat)
- cached = fetch(key)
- if cached && file_unchanged?(cached, fstat)
- validate_checksum(key)
- cached["checksum"]
- else
- nil
- end
- end
-
- def generate_checksum(key, file, fstat)
- checksum = checksum_file(file, Digest::SHA256.new)
- moneta.store(key, {"mtime" => fstat.mtime.to_f, "checksum" => checksum})
- validate_checksum(key)
- checksum
+ def checksum_for_file(file)
+ generate_checksum(file)
end
- def generate_key(file, group="chef")
- "#{group}-file-#{file.gsub(/(#{File::SEPARATOR}|\.)/, '-')}"
+ def generate_checksum(file)
+ checksum_file(file, Digest::SHA256.new)
end
def self.generate_md5_checksum_for_file(*args)
@@ -147,26 +57,6 @@ class Chef
private
- def fetch(key)
- @moneta.fetch(key)
- rescue ArgumentError => e
- Log.warn "Error loading cached checksum for key #{key.inspect}"
- Log.warn(e)
- repair_checksum_cache
- nil
- end
-
- def repair_checksum_cache
- Chef::Log.info("Removing invalid checksum cache files")
- Dir["#{Chef::Config[:cache_options][:path]}/*"].each do |file_path|
- File.unlink(file_path) unless File.size?(file_path)
- end
- end
-
- def file_unchanged?(cached, fstat)
- cached["mtime"].to_f == fstat.mtime.to_f
- end
-
def checksum_file(file, digest)
File.open(file, 'rb') { |f| checksum_io(f, digest) }
end
@@ -181,10 +71,3 @@ class Chef
end
end
-module Moneta
- module Defaults
- def default
- nil
- end
- end
-end
diff --git a/lib/chef/config.rb b/lib/chef/config.rb
index 85dce44474..74b10a4250 100644
--- a/lib/chef/config.rb
+++ b/lib/chef/config.rb
@@ -310,9 +310,7 @@ class Chef
start_handlers []
# Checksum Cache
- # Uses Moneta on the back-end
- cache_type "BasicFile"
- cache_options({ :path => platform_specific_path("/var/chef/cache/checksums"), :skip_expires => true })
+ cache_options({ :path => platform_specific_path("/var/chef/cache/checksums") })
# Set to false to silence Chef 11 deprecation warnings:
chef11_deprecation_warnings true
diff --git a/lib/chef/monkey_patches/moneta.rb b/lib/chef/monkey_patches/moneta.rb
deleted file mode 100644
index 1c2895db56..0000000000
--- a/lib/chef/monkey_patches/moneta.rb
+++ /dev/null
@@ -1,50 +0,0 @@
-#
-# Author:: Seth Chisamore (<schisamo@opscode.com>)
-# Copyright:: Copyright (c) 2011 Opscode, 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.
-#
-
-# ensure data is written and read in binary mode
-# stops "dump format error for symbol(0x75)" errors
-module Moneta
- class BasicFile
-
- def store(key, value, options = {})
- ensure_directory_created(::File.dirname(path(key)))
- ::File.open(path(key), "wb") do |file|
- if @expires
- data = {:value => value}
- if options[:expires_in]
- data[:expires_at] = Time.now + options[:expires_in]
- end
- contents = Marshal.dump(data)
- else
- contents = Marshal.dump(value)
- end
- file.puts(contents)
- end
- end
-
- def raw_get(key)
- if ::File.respond_to?(:binread)
- data = ::File.binread(path(key))
- else
- data = ::File.open(path(key),"rb") { |f| f.read }
- end
- Marshal.load(data)
- end
-
- end
-end
diff --git a/spec/unit/checksum_cache_spec.rb b/spec/unit/checksum_cache_spec.rb
index 78e76b6dfb..9746e096e2 100644
--- a/spec/unit/checksum_cache_spec.rb
+++ b/spec/unit/checksum_cache_spec.rb
@@ -22,96 +22,22 @@ require 'spec_helper'
describe Chef::ChecksumCache do
before(:each) do
- Chef::Config[:cache_type] = "Memory"
- Chef::Config[:cache_options] = { }
@cache = Chef::ChecksumCache.instance
- @cache.reset!
end
- describe "loading the moneta backend" do
- it "should build a Chef::ChecksumCache object" do
- @cache.should be_a_kind_of(Chef::ChecksumCache)
- end
-
- it "should set up a Moneta Cache adaptor" do
- @cache.moneta.should be_a_kind_of(Moneta::Memory)
- end
-
- it "should raise an exception if it cannot load the moneta adaptor" do
- Chef::Log.should_receive(:fatal).with(/^Could not load Moneta back end/)
- lambda {
- c = Chef::ChecksumCache.instance.reset!('WTF')
- }.should raise_error(LoadError)
- end
- end
-
- describe "when caching checksums of cookbook files and templates" do
-
- before do
- @cache.reset!("Memory", {})
- end
+ describe "when computing checksums of cookbook files and templates" do
it "proxies the class method checksum_for_file to the instance" do
@cache.should_receive(:checksum_for_file).with("a_file_or_a_fail")
Chef::ChecksumCache.checksum_for_file("a_file_or_a_fail")
end
- it "returns a cached checksum value" do
- @cache.moneta["chef-file-riseofthemachines"] = {"mtime" => "12345", "checksum" => "123abc"}
- fstat = mock("File.stat('riseofthemachines')", :mtime => Time.at(12345))
- File.should_receive(:stat).with("riseofthemachines").and_return(fstat)
- @cache.checksum_for_file("riseofthemachines").should == "123abc"
- end
-
- it "gives nil for a cache miss" do
- @cache.moneta["chef-file-riseofthemachines"] = {"mtime" => "12345", "checksum" => "123abc"}
- fstat = mock("File.stat('riseofthemachines')", :mtime => Time.at(555555))
- @cache.lookup_checksum("chef-file-riseofthemachines", fstat).should be_nil
- end
-
- it "treats a non-matching mtime as a cache miss" do
- @cache.moneta["chef-file-riseofthemachines"] = {"mtime" => "12345", "checksum" => "123abc"}
- fstat = mock("File.stat('riseofthemachines')", :mtime => Time.at(555555))
- @cache.lookup_checksum("chef-file-riseofthemachines", fstat).should be_nil
- end
-
it "computes a checksum of a file" do
fixture_file = CHEF_SPEC_DATA + "/checksum/random.txt"
expected = "09ee9c8cc70501763563bcf9c218d71b2fbf4186bf8e1e0da07f0f42c80a3394"
- @cache.send(:checksum_file, fixture_file, Digest::SHA256.new).should == expected
- end
-
- it "computes a checksum and stores it in the cache" do
- fstat = mock("File.stat('riseofthemachines')", :mtime => Time.at(555555))
- @cache.should_receive(:checksum_file).with("riseofthemachines", an_instance_of(Digest::SHA256)).and_return("ohai2uChefz")
- @cache.generate_checksum("chef-file-riseofthemachines", "riseofthemachines", fstat).should == "ohai2uChefz"
- @cache.lookup_checksum("chef-file-riseofthemachines", fstat).should == "ohai2uChefz"
- end
-
- it "returns a generated checksum if there is no cached value" do
- fixture_file = CHEF_SPEC_DATA + "/checksum/random.txt"
- expected = "09ee9c8cc70501763563bcf9c218d71b2fbf4186bf8e1e0da07f0f42c80a3394"
@cache.checksum_for_file(fixture_file).should == expected
end
- it "generates a key from a file name" do
- file = "/this/is/a/test/random.rb"
- @cache.generate_key(file).should == "chef-file--this-is-a-test-random-rb"
- end
-
- it "generates a key from a file name and group" do
- file = "/this/is/a/test/random.rb"
- @cache.generate_key(file, "spec").should == "spec-file--this-is-a-test-random-rb"
- end
-
- it "returns a cached checksum value using a user defined key" do
- key = @cache.generate_key("riseofthemachines", "specs")
- @cache.moneta[key] = {"mtime" => "12345", "checksum" => "123abc"}
- fstat = mock("File.stat('riseofthemachines')", :mtime => Time.at(12345))
- File.should_receive(:stat).with("riseofthemachines").and_return(fstat)
- @cache.checksum_for_file("riseofthemachines", key).should == "123abc"
- end
-
it "generates a checksum from a non-file IO object" do
io = StringIO.new("riseofthemachines\nriseofthechefs\n")
expected_md5 = '0e157ac1e2dd73191b76067fb6b4bceb'
@@ -120,90 +46,5 @@ describe Chef::ChecksumCache do
end
- describe "when cleaning up after outdated checksums" do
-
- before do
- Chef::ChecksumCache.reset_cache_validity
- end
-
- it "initially has no valid cached checksums" do
- Chef::ChecksumCache.valid_cached_checksums.should be_empty
- end
-
- it "adds a checksum to the list of valid cached checksums when it's created" do
- @cache.checksum_for_file(File.join(CHEF_SPEC_DATA, 'checksum', 'random.txt'))
- Chef::ChecksumCache.valid_cached_checksums.should have(1).valid_checksum
- end
-
- it "adds a checksum to the list of valid cached checksums when it's read" do
- @cache.checksum_for_file(File.join(CHEF_SPEC_DATA, 'checksum', 'random.txt'))
- Chef::ChecksumCache.reset_cache_validity
- @cache.checksum_for_file(File.join(CHEF_SPEC_DATA, 'checksum', 'random.txt'))
- Chef::ChecksumCache.valid_cached_checksums.should have(1).valid_checksum
- end
-
- context "with an existing set of cached checksums" do
- before do
- Chef::Config[:cache_type] = "BasicFile"
- Chef::Config[:cache_options] = {:path => File.join(CHEF_SPEC_DATA, "checksum_cache")}
-
- @expected_cached_checksums = ["chef-file--tmp-chef-rendered-template20100929-10863-600hhz-0",
- "chef-file--tmp-chef-rendered-template20100929-10863-6m8zdk-0",
- "chef-file--tmp-chef-rendered-template20100929-10863-ahd2gq-0",
- "chef-file--tmp-chef-rendered-template20100929-10863-api8ux-0",
- "chef-file--tmp-chef-rendered-template20100929-10863-b0r1m1-0",
- "chef-file--tmp-chef-rendered-template20100929-10863-bfygsi-0",
- "chef-file--tmp-chef-rendered-template20100929-10863-el14l6-0",
- "chef-file--tmp-chef-rendered-template20100929-10863-ivrl3y-0",
- "chef-file--tmp-chef-rendered-template20100929-10863-kkbs85-0",
- "chef-file--tmp-chef-rendered-template20100929-10863-ory1ux-0",
- "chef-file--tmp-chef-rendered-template20100929-10863-pgsq76-0",
- "chef-file--tmp-chef-rendered-template20100929-10863-ra8uim-0",
- "chef-file--tmp-chef-rendered-template20100929-10863-t7k1g-0",
- "chef-file--tmp-chef-rendered-template20100929-10863-t8g0sv-0",
- "chef-file--tmp-chef-rendered-template20100929-10863-ufy6g3-0",
- "chef-file--tmp-chef-rendered-template20100929-10863-x2d6j9-0",
- "chef-file--tmp-chef-rendered-template20100929-10863-xi0l6h-0"]
- @expected_cached_checksums.sort!
- end
-
- after do
- Chef::Config[:cache_type] = "Memory"
- Chef::Config[:cache_options] = { }
- @cache = Chef::ChecksumCache.instance
- @cache.reset!
- end
-
- it "lists all of the cached checksums in the cache directory" do
- Chef::ChecksumCache.all_cached_checksums.keys.sort.should == @expected_cached_checksums
- end
-
- it "clears all of the checksums not marked valid from the checksums directory" do
- valid_cksum_key = "chef-file--tmp-chef-rendered-template20100929-10863-ivrl3y-0"
- valid_cksum_file = File.join(CHEF_SPEC_DATA, "checksum_cache", valid_cksum_key)
- @expected_cached_checksums.delete(valid_cksum_key)
-
- Chef::ChecksumCache.valid_cached_checksums << valid_cksum_key
-
- Chef::ChecksumCache.should_not_receive(:remove_unused_checksum).with(valid_cksum_file)
- @expected_cached_checksums.each do |cksum_key|
- full_path_to_cksum = File.join(CHEF_SPEC_DATA, "checksum_cache", cksum_key)
- Chef::ChecksumCache.should_receive(:remove_unused_checksum).with(full_path_to_cksum)
- end
-
- Chef::ChecksumCache.cleanup_checksum_cache
- end
-
- it "cleans all 0byte checksum files when it encounters a Marshal error" do
- @cache.moneta.stub!(:fetch).and_raise(ArgumentError)
- # This cache file is 0 bytes, raises an argument error when
- # attempting to Marshal.load
- File.should_receive(:unlink).with(File.join(CHEF_SPEC_DATA, "checksum_cache", "chef-file--tmp-chef-rendered-template20100929-10863-6m8zdk-0"))
- @cache.lookup_checksum("chef-file--tmp-chef-rendered-template20100929-10863-6m8zdk-0", "foo")
- end
- end
-
- end
-
end
diff --git a/spec/unit/cookbook/syntax_check_spec.rb b/spec/unit/cookbook/syntax_check_spec.rb
index e7eaba07bc..b9cea935b5 100644
--- a/spec/unit/cookbook/syntax_check_spec.rb
+++ b/spec/unit/cookbook/syntax_check_spec.rb
@@ -126,11 +126,6 @@ describe Chef::Cookbook::SyntaxCheck do
before do
Chef::Config[:cache_options] = {:path => cache_path }
- Chef::Config[:cache_type] = 'Memory'
- @checksum_cache_klass = Class.new(Chef::ChecksumCache)
- @checksum_cache = @checksum_cache_klass.instance
- @checksum_cache.reset!('Memory')
- syntax_check.stub!(:cache).and_return(@checksum_cache)
end
after do
diff --git a/spec/unit/provider/file_spec.rb b/spec/unit/provider/file_spec.rb
index b298aaca34..8c575e815e 100644
--- a/spec/unit/provider/file_spec.rb
+++ b/spec/unit/provider/file_spec.rb
@@ -57,7 +57,7 @@ describe Chef::Provider::File do
it "should collect the current state of the file on the filesystem and populate current_resource" do
# test setup
stat_struct = mock("::File.stat", :mode => 0600, :uid => 0, :gid => 0, :mtime => 10000)
- ::File.should_receive(:stat).exactly(3).with(@resource.path).and_return(stat_struct)
+ ::File.should_receive(:stat).exactly(2).times.with(@resource.path).and_return(stat_struct)
# test execution
@provider.load_current_resource
@@ -71,7 +71,7 @@ describe Chef::Provider::File do
it "should NOT update the new_resource state with the current_resourse state if new_resource state is already specified" do
# test setup
stat_struct = mock("::File.stat", :mode => 0600, :uid => 0, :gid => 0, :mtime => 10000)
- ::File.should_receive(:stat).exactly(3).with(@resource.path).and_return(stat_struct)
+ ::File.should_receive(:stat).exactly(2).times.with(@resource.path).and_return(stat_struct)
@provider.new_resource.group(1)
@provider.new_resource.owner(1)
@@ -89,7 +89,7 @@ describe Chef::Provider::File do
it "should update the new_resource state with the current_resource state if the new_resource state is not specified." do
# test setup
stat_struct = mock("::File.stat", :mode => 0600, :uid => 0, :gid => 0, :mtime => 10000)
- ::File.should_receive(:stat).exactly(3).with(@resource.path).and_return(stat_struct)
+ ::File.should_receive(:stat).exactly(2).times.with(@resource.path).and_return(stat_struct)
@provider.new_resource.group(nil)
@provider.new_resource.owner(nil)
@@ -108,7 +108,7 @@ describe Chef::Provider::File do
# test setup
stat_struct = mock("::File.stat", :mode => 0600, :uid => 0, :gid => 0, :mtime => 10000)
# called once in update_new_file_state and once in checksum
- ::File.should_receive(:stat).twice.with(@provider.new_resource.path).and_return(stat_struct)
+ ::File.should_receive(:stat).with(@provider.new_resource.path).and_return(stat_struct)
::File.should_receive(:directory?).once.with(@provider.new_resource.path).and_return(false)
@provider.new_resource.group(nil)
@@ -174,6 +174,8 @@ describe Chef::Provider::File do
@provider.new_resource.content "foobar"
@provider.should_receive(:diff_current_from_content).and_return("")
@provider.should_receive(:backup)
+ # checksum check
+ File.should_receive(:open).with(@provider.new_resource.path, "rb").and_yield(io)
File.should_receive(:open).with(@provider.new_resource.path, "w").and_yield(io)
@provider.set_content
io.string.should == "foobar"
@@ -182,7 +184,8 @@ describe Chef::Provider::File do
it "should not set the content of the file if it already matches the requested content" do
@provider.load_current_resource
@provider.new_resource.content IO.read(@resource.path)
- File.stub!(:open).and_return(1)
+ # Checksum check:
+ File.should_receive(:open).with(@resource.path, "rb").and_yield(StringIO.new(@resource.content))
File.should_not_receive(:open).with(@provider.new_resource.path, "w")
lambda { @provider.set_content }.should_not raise_error
@resource.should_not be_updated_by_last_action
diff --git a/spec/unit/provider/template_spec.rb b/spec/unit/provider/template_spec.rb
index 6747876d61..f5d30f0219 100644
--- a/spec/unit/provider/template_spec.rb
+++ b/spec/unit/provider/template_spec.rb
@@ -156,7 +156,6 @@ describe Chef::Provider::Template do
describe "when the target has the correct content" do
before do
- Chef::ChecksumCache.instance.reset!
File.open(@rendered_file_location, "w") { |f| f.print "slappiness is a warm gun" }
@current_resource.checksum('4ff94a87794ed9aefe88e734df5a66fc8727a179e9496cbd88e3b5ec762a5ee9')
@access_controls = mock("access controls")