summaryrefslogtreecommitdiff
path: root/chef
diff options
context:
space:
mode:
authorAdam Jacob <adam@hjksolutions.com>2009-04-24 17:47:24 -0700
committerAdam Jacob <adam@hjksolutions.com>2009-04-24 17:47:24 -0700
commit0e67f1b224400858edfe3fff0345d04ba9aef71f (patch)
tree2a81cfdaa5679b15977d2c098feccd91052248dd /chef
parent2abe9484b4ae546807e48ee5f030bae209eede3b (diff)
parentbd2fad29a8045fc64354d68830a0e1f0f6494ca3 (diff)
downloadchef-0e67f1b224400858edfe3fff0345d04ba9aef71f.tar.gz
Merge branch 'master' into cabeca/chef-186
Diffstat (limited to 'chef')
-rwxr-xr-xchef/bin/chef-client2
-rwxr-xr-xchef/bin/chef-solo2
-rw-r--r--chef/contrib/el/chef-client.config16
-rw-r--r--chef/contrib/el/chef-client.init74
-rw-r--r--chef/lib/chef/config.rb2
-rw-r--r--chef/lib/chef/daemon.rb4
-rw-r--r--chef/lib/chef/mixin/command.rb98
-rw-r--r--chef/lib/chef/provider/package/yum-dump-json.py67
-rw-r--r--chef/lib/chef/provider/package/yum.rb127
-rw-r--r--chef/lib/chef/provider/remote_file.rb68
-rw-r--r--chef/lib/chef/resource/remote_file.rb9
-rw-r--r--chef/lib/chef/util/file_edit.rb125
-rw-r--r--chef/spec/data/fileedit/blank0
-rw-r--r--chef/spec/data/fileedit/hosts4
-rw-r--r--chef/spec/lib/chef/provider/easy.rb28
-rw-r--r--chef/spec/lib/chef/provider/snakeoil.rb28
-rw-r--r--chef/spec/lib/chef/resource/cat.rb29
-rw-r--r--chef/spec/lib/chef/resource/zen_master.rb29
-rw-r--r--chef/spec/spec_helper.rb27
-rw-r--r--chef/spec/unit/couchdb_spec.rb4
-rw-r--r--chef/spec/unit/mixin/command_spec.rb85
-rw-r--r--chef/spec/unit/mixin/template_spec.rb3
-rw-r--r--chef/spec/unit/provider/package/yum_spec.rb116
-rw-r--r--chef/spec/unit/provider/remote_file_spec.rb55
-rw-r--r--chef/spec/unit/resource/remote_file_spec.rb13
-rw-r--r--chef/spec/unit/util/file_edit_spec.rb127
26 files changed, 779 insertions, 363 deletions
diff --git a/chef/bin/chef-client b/chef/bin/chef-client
index df06e068fd..1c1b38bd19 100755
--- a/chef/bin/chef-client
+++ b/chef/bin/chef-client
@@ -79,6 +79,8 @@ end
Chef::Config.from_file(config[:config_file])
Chef::Config.configure { |c| c.merge!(config) }
+Chef::Daemon.change_privilege
+
if Chef::Config[:daemonize]
unless Chef::Config[:log_location].is_a? IO
Chef::Log.init(Chef::Config[:log_location])
diff --git a/chef/bin/chef-solo b/chef/bin/chef-solo
index 5543faf9c3..ecc2c57f8a 100755
--- a/chef/bin/chef-solo
+++ b/chef/bin/chef-solo
@@ -34,7 +34,7 @@ config = {
Chef::Config[:solo] = true
opts = OptionParser.new do |opts|
- opts.banner = "Usage: #{$0} [-d DIR|-r FILE] (options)"
+ opts.banner = "Usage: #{$0} (options)"
opts.on("-c CONFIG", "--config CONFIG", "The Chef Config file to use") do |c|
config[:config_file] = c
end
diff --git a/chef/contrib/el/chef-client.config b/chef/contrib/el/chef-client.config
new file mode 100644
index 0000000000..5be5f35114
--- /dev/null
+++ b/chef/contrib/el/chef-client.config
@@ -0,0 +1,16 @@
+#
+# Chef Client Config File
+#
+
+log_level :info
+ssl_verify_mode :verify_none
+registration_url "http://127.0.0.1:4000"
+openid_url "http://127.0.0.1:4001"
+template_url "http://127.0.0.1:4000"
+remotefile_url "http://127.0.0.1:4000"
+search_url "http://127.0.0.1:4000"
+
+pid_file "/var/run/chef/chef-client.pid"
+
+#interval 1800
+#splay 0
diff --git a/chef/contrib/el/chef-client.init b/chef/contrib/el/chef-client.init
new file mode 100644
index 0000000000..332e9606d9
--- /dev/null
+++ b/chef/contrib/el/chef-client.init
@@ -0,0 +1,74 @@
+#!/bin/bash
+# Startup script for chef-client
+#
+# chkconfig: - 98 02
+# description: Client component of the Chef systems integration framework.
+# processname: chef-client
+#
+# config: /etc/sysconfig/chef-client
+# pidfile: /var/run/chef/chef-client.pid
+
+# Source function library
+. /etc/init.d/functions
+
+[ -f /etc/sysconfig/chef-client ] && . /etc/sysconfig/chef-client
+
+prog="chef-client"
+pidfile=${PIDFILE-/var/run/chef/chef-client.pid}
+lockfile=${LOCKFILE-/var/lock/subsys/$prog}
+config=${CONFIG-/etc/chef/client.rb}
+logfile=${LOGFILE-/var/log/chef/chef-client.log}
+OPTIONS=
+
+start() {
+ echo -n "Starting $prog:"
+ daemon chef-client -d -c "$config" -L "$logfile" "$OPTIONS" ">/dev/null"
+ RETVAL=$?
+ echo
+ [ $RETVAL -eq 0 ] && touch ${lockfile}
+ return $RETVAL
+}
+
+stop() {
+ echo -n "Stopping $prog: "
+ if [ -f $pidfile ]; then
+ killproc chef-client
+ RETVAL=$?
+ if [ $RETVAL -ne 0 ]; then
+ failure;
+ fi;
+ else
+ RETVAL=1
+ failure;
+ fi
+ rm -f $lockfile
+ echo
+ return $RETVAL
+}
+
+case "$1" in
+ start)
+ start
+ ;;
+ stop)
+ stop
+ ;;
+ restart)
+ stop
+ start
+ ;;
+ condrestart)
+ if [ -f $lockfile ]; then
+ stop
+ start
+ fi
+ ;;
+ status)
+ status chef-client
+ ;;
+ *)
+ echo "Usage: $0 {start|stop|restart|condrestart|status}"
+ exit 1
+esac
+
+exit $RETVAL
diff --git a/chef/lib/chef/config.rb b/chef/lib/chef/config.rb
index f864274b40..f9fda13cf0 100644
--- a/chef/lib/chef/config.rb
+++ b/chef/lib/chef/config.rb
@@ -41,8 +41,6 @@ class Chef
:interval => nil,
:splay => nil,
:solo => false,
- :user => nil,
- :group => nil,
:json_attribs => nil,
:cookbook_path => [ "/var/chef/site-cookbooks", "/var/chef/cookbooks" ],
:validation_token => nil,
diff --git a/chef/lib/chef/daemon.rb b/chef/lib/chef/daemon.rb
index 7ab66ab710..2b6e6db3ea 100644
--- a/chef/lib/chef/daemon.rb
+++ b/chef/lib/chef/daemon.rb
@@ -40,12 +40,12 @@ class Chef
exit if fork
Process.setsid
exit if fork
- change_privilege
Chef::Log.info("Forked, in #{Process.pid}. Priveleges: #{Process.euid} #{Process.egid}")
File.umask 0000
$stdin.reopen("/dev/null")
$stdout.reopen("/dev/null", "a")
$stdout.reopen($stdout)
+ save_pid_file
at_exit { remove_pid_file }
rescue NotImplementedError => e
Chef.fatal!("There is no fork: #{e.message}")
@@ -167,4 +167,4 @@ class Chef
end
end
end
-end \ No newline at end of file
+end
diff --git a/chef/lib/chef/mixin/command.rb b/chef/lib/chef/mixin/command.rb
index d787059548..f0c76b09e9 100644
--- a/chef/lib/chef/mixin/command.rb
+++ b/chef/lib/chef/mixin/command.rb
@@ -113,35 +113,11 @@ class Chef
end
exec_processing_block = lambda do |pid, stdin, stdout, stderr|
- stdout.sync = true
- stderr.sync = true
-
Chef::Log.debug("---- Begin output of #{args[:command]} ----")
-
- stdout_finished = false
- stderr_finished = false
-
- while !stdout_finished || !stderr_finished
- ready = IO.select([stdout, stderr], nil, nil, 1.0)
- if ready && ready.first.include?(stdout)
- line = stdout.gets
- if line
- command_output << "STDOUT: #{line.strip}\n"
- Chef::Log.debug("STDOUT: #{line.strip}")
- else
- stdout_finished = true
- end
- end
- if ready && ready.first.include?(stderr)
- line = stderr.gets
- if line
- command_output << "STDERR: #{line.strip}\n"
- Chef::Log.debug("STDERR: #{line.strip}")
- else
- stderr_finished = true
- end
- end
- end
+ Chef::Log.debug("STDOUT: #{stdout.string.chomp!}")
+ Chef::Log.debug("STDERR: #{stderr.string.chomp!}")
+ command_output << "STDOUT: #{stdout.string.chomp!}"
+ command_output << "STDERR: #{stderr.string.chomp!}"
Chef::Log.debug("---- End output of #{args[:command]} ----")
end
@@ -154,10 +130,6 @@ class Chef
status = nil
- # I don't understand what this :waitlast argument is doing, but setting it to true is causing the block in popen4
- # not to wait until the command is finished to execute, kind of the opposite of what I would guess from the name
- args[:waitlast] ||= true
-
Dir.chdir(args[:cwd]) do
if args[:timeout]
begin
@@ -200,8 +172,13 @@ class Chef
#
# Thanks Ara!
def popen4(cmd, args={}, &b)
-
+
# Waitlast - this is magic.
+ #
+ # Do we wait for the child process to die before we yield
+ # to the block, or after? That is the magic of waitlast.
+ #
+ # By default, we are waiting before we yield the block.
args[:waitlast] ||= false
args[:user] ||= nil
@@ -298,11 +275,58 @@ class Chef
# wants to do must be done - it's dead. If it isn't,
# it's because something totally skanky is happening,
# and we don't care.
+ o = StringIO.new
+ e = StringIO.new
+
pi[0].close
- pi[1].fcntl(Fcntl::F_SETFL, pi[1].fcntl(Fcntl::F_GETFL) | Fcntl::O_NONBLOCK)
- pi[2].fcntl(Fcntl::F_SETFL, pi[2].fcntl(Fcntl::F_GETFL) | Fcntl::O_NONBLOCK)
- results = Process.waitpid2(cid).last
- b[cid, *pi]
+
+ stdout = pi[1]
+ stderr = pi[2]
+
+ stdout.sync = true
+ stderr.sync = true
+
+ stdout.fcntl(Fcntl::F_SETFL, pi[1].fcntl(Fcntl::F_GETFL) | Fcntl::O_NONBLOCK)
+ stderr.fcntl(Fcntl::F_SETFL, pi[2].fcntl(Fcntl::F_GETFL) | Fcntl::O_NONBLOCK)
+
+
+ stdout_finished = false
+ stderr_finished = false
+
+ results = nil
+
+ while !stdout_finished || !stderr_finished
+ begin
+ ready = IO.select([stdout, stderr], nil, nil, 1.0)
+ rescue Errno::EAGAIN
+ results = Process.waitpid2(cid, Process::WNOHANG)
+ if results
+ stdout_finished = true
+ stderr_finished = true
+ end
+ end
+
+ if ready && ready.first.include?(stdout)
+ line = results ? stdout.gets(nil) : stdout.gets
+ if line
+ o.write(line)
+ else
+ stdout_finished = true
+ end
+ end
+ if ready && ready.first.include?(stderr)
+ line = results ? stderr.gets(nil) : stderr.gets
+ if line
+ e.write(line)
+ else
+ stderr_finished = true
+ end
+ end
+ end
+ results = Process.waitpid2(cid).last unless results
+ o.rewind
+ e.rewind
+ b[cid, pi[0], o, e]
results
end
ensure
diff --git a/chef/lib/chef/provider/package/yum-dump-json.py b/chef/lib/chef/provider/package/yum-dump-json.py
new file mode 100644
index 0000000000..115265e5aa
--- /dev/null
+++ b/chef/lib/chef/provider/package/yum-dump-json.py
@@ -0,0 +1,67 @@
+#
+# Author:: Matthew Kent (<mkent@magoazul.com>)
+# Copyright:: Copyright (c) 2009 Matthew Kent
+# 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.
+#
+
+# yum-dump-json.py
+# Inspired by yumhelper.py by David Lutterkort
+#
+# Produce a list of installed and available packages using yum and dump the
+# result as json to stdout.
+#
+# This invokes yum just as the command line would which makes it subject to
+# all the caching related configuration paramaters in yum.conf.
+#
+# Can be run as non root, but that won't update the cache.
+
+import os
+import sys
+import yum
+import json
+
+y = yum.YumBase()
+# Only want json in output
+y.doConfigSetup(debuglevel=0, errorlevel=0)
+
+# yum assumes it can update the cache directory. Disable this for non root
+# users.
+y.conf.cache = os.geteuid() != 0
+
+y.doTsSetup()
+y.doRpmDBSetup()
+
+db = y.doPackageLists('all')
+
+y.closeRpmDB()
+
+combined = {}
+
+for pkg in db.installed:
+ combined[pkg.name] = {}
+ combined[pkg.name]["installed"] = { "epoch": pkg.epoch,
+ "version": pkg.version,
+ "release": pkg.release,
+ "arch": pkg.arch }
+for pkg in db.available:
+ if not combined.has_key(pkg.name):
+ combined[pkg.name] = {}
+ combined[pkg.name]["available"] = { "epoch": pkg.epoch,
+ "version": pkg.version,
+ "release": pkg.release,
+ "arch": pkg.arch }
+print json.write( combined )
+
+sys.exit(0)
diff --git a/chef/lib/chef/provider/package/yum.rb b/chef/lib/chef/provider/package/yum.rb
index 7e4a6e96ba..5eab817f0e 100644
--- a/chef/lib/chef/provider/package/yum.rb
+++ b/chef/lib/chef/provider/package/yum.rb
@@ -19,63 +19,114 @@
require 'chef/provider/package'
require 'chef/mixin/command'
require 'chef/resource/package'
+require 'singleton'
class Chef
class Provider
class Package
class Yum < Chef::Provider::Package
+ class YumCache
+ include Chef::Mixin::Command
+ include Singleton
+
+ def initialize
+ @created_at = Time.now
+ load_data
+ end
+
+ def stale?
+ interval = Chef::Config[:interval].to_f
+
+ # run once mode
+ if interval == 0
+ return false
+ elsif (Time.now - @created_at) > interval
+ return true
+ end
+
+ false
+ end
+
+ def refresh
+ if @data.empty?
+ reload
+ elsif stale?
+ reload
+ end
+ end
+
+ def load_data
+ parsed = String.new
+ helper = ::File.join(::File.dirname(__FILE__), 'yum-dump-json.py')
+ status = popen4("python #{helper}", :waitlast => true) do |pid, stdin, stdout, stderr|
+ stdout.each do |line|
+ parsed << line
+ end
+ end
+
+ unless status.exitstatus == 0
+ raise Chef::Exceptions::Package, "yum failed - #{status.inspect}!"
+ end
+
+ @data = JSON.parse(parsed)
+ end
+ alias :reload :load_data
+
+ def version(package_name, type)
+ if (x = @data[package_name])
+ if (y = x[type])
+ return "#{y["version"]}-#{y["release"]}"
+ end
+ end
+
+ nil
+ end
+
+ def installed_version(package_name)
+ version(package_name, "installed")
+ end
+
+ def candidate_version(package_name)
+ version(package_name, "available")
+ end
+
+ def flush
+ @data.clear
+ end
+ end
+
+ def initialize(node, new_resource)
+ @yum = YumCache.instance
+ super(node, new_resource)
+ end
+
def load_current_resource
@current_resource = Chef::Resource::Package.new(@new_resource.name)
@current_resource.package_name(@new_resource.package_name)
Chef::Log.debug("Checking yum info for #{@new_resource.package_name}")
- status = popen4("yum info -q -y #{@new_resource.package_name}") do |pid, stdin, stdout, stderr|
- package_type = nil
- installed_version = nil
- candidate_version = nil
- stdout.each do |line|
- case line
- when /^Installed Packages$/
- package_type = :installed
- when /^Available Packages$/
- package_type = :available
- when /^Version\s*: (.+)$/
- if package_type == :installed
- installed_version = $1
- elsif package_type == :available
- candidate_version = $1
- end
- when /^Release: (.+)$/
- if package_type == :installed
- installed_version += "-#{$1}"
- Chef::Log.debug("Installed release is #{installed_version}")
- elsif package_type == :available
- candidate_version += "-#{$1}"
- Chef::Log.debug("Candidate version is #{candidate_version}")
- end
- end
- end
-
- @current_resource.version(installed_version)
- if candidate_version
- @candidate_version = candidate_version
- else
- @candidate_version = installed_version
- end
- end
+
+ @yum.refresh
- unless status.exitstatus == 0
- raise Chef::Exceptions::Package, "yum failed - #{status.inspect}!"
+ installed_version = @yum.installed_version(@new_resource.package_name)
+ @candidate_version = @yum.candidate_version(@new_resource.package_name)
+
+ @current_resource.version(installed_version)
+ if candidate_version
+ @candidate_version = candidate_version
+ else
+ @candidate_version = installed_version
end
@current_resource
end
-
+
def install_package(name, version)
run_command(
:command => "yum -q -y install #{name}-#{version}"
)
+ @yum.flush
end
def upgrade_package(name, version)
@@ -84,6 +135,7 @@ class Chef
run_command(
:command => "yum -q -y update #{name}-#{version}"
)
+ @yum.flush
else
install_package(name, version)
end
@@ -93,6 +145,7 @@ class Chef
run_command(
:command => "yum -q -y remove #{name}-#{version}"
)
+ @yum.flush
end
def purge_package(name, version)
diff --git a/chef/lib/chef/provider/remote_file.rb b/chef/lib/chef/provider/remote_file.rb
index df2afd4976..3c55b873e3 100644
--- a/chef/lib/chef/provider/remote_file.rb
+++ b/chef/lib/chef/provider/remote_file.rb
@@ -43,48 +43,50 @@ class Chef
end
def do_remote_file(source, path)
- # The current files checksum
- current_checksum = self.checksum(path) if ::File.exists?(path)
+ if(@new_resource.checksum && @current_resource.checksum && @current_resource.checksum =~ /^#{@new_resource.checksum}/)
+ Chef::Log.debug("File #{@new_resource} checksum matches, not updating")
+ else
+ begin
+ # The remote filehandle
+ raw_file = get_from_uri(source) ||
+ get_from_server(source, @current_resource.checksum) ||
+ get_from_local_cookbook(source)
+ rescue Net::HTTPRetriableError => e
+ if e.response.kind_of?(Net::HTTPNotModified)
+ Chef::Log.debug("File #{path} is unchanged")
+ return false
+ else
+ raise e
+ end
+ end
- begin
- # The remote filehandle
- raw_file = get_from_uri(source) ||
- get_from_server(source, current_checksum) ||
- get_from_local_cookbook(source)
- rescue Net::HTTPRetriableError => e
- if e.response.kind_of?(Net::HTTPNotModified)
- Chef::Log.debug("File #{path} is unchanged")
- return false
+ # If the file exists
+ if ::File.exists?(@new_resource.path)
+ # And it matches the checksum of the raw file
+ @new_resource.checksum(self.checksum(raw_file.path))
+ if @new_resource.checksum != @current_resource.checksum
+ # Updating target file, let's perform a backup!
+ Chef::Log.debug("#{@new_resource} changed from #{@current_resource.checksum} to #{@new_resource.checksum}")
+ Chef::Log.info("Updating #{@new_resource} at #{@new_resource.path}")
+ backup(@new_resource.path)
+ end
else
- raise e
+ # We're creating a new file
+ Chef::Log.info("Creating #{@new_resource} at #{@new_resource.path}")
end
- end
- # If the file exists
- if ::File.exists?(@new_resource.path)
- # And it matches the checksum of the raw file
- @new_resource.checksum(self.checksum(raw_file.path))
- if @new_resource.checksum != @current_resource.checksum
- # Updating target file, let's perform a backup!
- Chef::Log.debug("#{@new_resource} changed from #{@current_resource.checksum} to #{@new_resource.checksum}")
- Chef::Log.info("Updating #{@new_resource} at #{@new_resource.path}")
- backup(@new_resource.path)
- end
- else
- # We're creating a new file
- Chef::Log.info("Creating #{@new_resource} at #{@new_resource.path}")
- end
+ FileUtils.cp(raw_file.path, @new_resource.path)
+ @new_resource.updated = true
- FileUtils.cp(raw_file.path, @new_resource.path)
- @new_resource.updated = true
-
+ # We're done with the file, so make sure to close it if it was open.
+ raw_file.close
+ true
+ end
+
set_owner if @new_resource.owner
set_group if @new_resource.group
set_mode if @new_resource.mode
- # We're done with the file, so make sure to close it if it was open.
- raw_file.close
- true
end
def get_from_uri(source)
diff --git a/chef/lib/chef/resource/remote_file.rb b/chef/lib/chef/resource/remote_file.rb
index a1f276aff3..136a704c63 100644
--- a/chef/lib/chef/resource/remote_file.rb
+++ b/chef/lib/chef/resource/remote_file.rb
@@ -46,6 +46,15 @@ class Chef
)
end
+ def checksum(args=nil)
+ set_or_return(
+ :checksum,
+ args,
+ :kind_of => String
+ )
+ end
+
+
end
end
end
diff --git a/chef/lib/chef/util/file_edit.rb b/chef/lib/chef/util/file_edit.rb
new file mode 100644
index 0000000000..c09e427741
--- /dev/null
+++ b/chef/lib/chef/util/file_edit.rb
@@ -0,0 +1,125 @@
+#
+# Author:: Nuo Yan (<nuo@opscode.com>)
+# Copyright:: Copyright (c) 2009 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.
+
+require 'ftools'
+require 'fileutils'
+require 'tempfile'
+
+class Chef
+ class Util
+ class FileEdit
+
+ private
+
+ attr_accessor :original_pathname, :contents, :file_edited
+
+ public
+
+ def initialize(filepath)
+ @original_pathname = filepath
+ @file_edited = false
+
+ raise ArgumentError, "File doesn't exist" unless File.exist? @original_pathname
+ raise ArgumentError, "File is blank" unless (@contents = File.new(@original_pathname).readlines).length > 0
+ end
+
+ #search the file line by line and match each line with the given regex
+ #if matched, replace the whole line with newline.
+ def search_file_replace_line(regex, newline)
+ search_match(regex, newline, 'r', 1)
+ end
+
+ #search the file line by line and match each line with the given regex
+ #if matched, replace the match (all occurances) with the replace parameter
+ def search_file_replace(regex, replace)
+ search_match(regex, replace, 'r', 2)
+ end
+
+ #search the file line by line and match each line with the given regex
+ #if matched, delete the line
+ def search_file_delete_line(regex)
+ search_match(regex, " ", 'd', 1)
+ end
+
+ #search the file line by line and match each line with the given regex
+ #if matched, delete the match (all occurances) from the line
+ def search_file_delete(regex)
+ search_match(regex, " ", 'd', 2)
+ end
+
+ #search the file line by line and match each line with the given regex
+ #if matched, insert newline after each matching line
+ def insert_line_after_match(regex, newline)
+ search_match(regex, newline, 'i', 0)
+ end
+
+ #Make a copy of old_file and write new file out (only if file changed)
+ def write_file
+
+ # file_edited is false when there was no match in the whole file and thus no contents have changed.
+ if file_edited
+ backup_pathname = original_pathname + ".old"
+ File.copy(original_pathname, backup_pathname)
+ Tempfile.open("w") do |newfile|
+ contents.each do |line|
+ newfile.puts(line)
+ end
+ newfile.flush
+ FileUtils.mv(newfile.path, original_pathname)
+ end
+ end
+ self.file_edited = false
+
+ end
+
+ private
+
+ #helper method to do the match, replace, delete, and insert operations
+ #command is the switch of delete, replace, and insert ('d', 'r', 'i')
+ #method is to control operation on whole line or only the match (1 for line, 2 for match)
+ def search_match(regex, replace, command, method)
+
+ #convert regex to a Regexp object (if not already is one) and store it in exp.
+ exp = Regexp.new(regex)
+
+ #loop through contents and do the appropriate operation depending on 'command' and 'method'
+ new_contents = []
+
+ contents.each do |line|
+ if line.match(exp)
+ self.file_edited = true
+ case
+ when command == 'r'
+ new_contents << ((method == 1) ? replace : line.gsub!(exp, replace))
+ when command == 'd'
+ if method == 2
+ new_contents << line.gsub!(exp, "")
+ end
+ when command == 'i'
+ new_contents << line
+ new_contents << replace
+ end
+ else
+ new_contents << line
+ end
+ end
+
+ self.contents = new_contents
+ end
+ end
+ end
+end
diff --git a/chef/spec/data/fileedit/blank b/chef/spec/data/fileedit/blank
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/chef/spec/data/fileedit/blank
diff --git a/chef/spec/data/fileedit/hosts b/chef/spec/data/fileedit/hosts
new file mode 100644
index 0000000000..6fbdc0f59d
--- /dev/null
+++ b/chef/spec/data/fileedit/hosts
@@ -0,0 +1,4 @@
+127.0.0.1 localhost
+255.255.255.255 broadcasthost
+::1 localhost
+fe80::1%lo0 localhost
diff --git a/chef/spec/lib/chef/provider/easy.rb b/chef/spec/lib/chef/provider/easy.rb
index 966fbc8dc5..054b45256c 100644
--- a/chef/spec/lib/chef/provider/easy.rb
+++ b/chef/spec/lib/chef/provider/easy.rb
@@ -1,22 +1,20 @@
#
# Author:: Adam Jacob (<adam@opscode.com>)
# Copyright:: Copyright (c) 2008 Opscode, Inc.
-# License:: GNU General Public License version 2 or later
-#
-# This program and entire repository is free software; you can
-# redistribute it and/or modify it under the terms of the GNU
-# General Public License as published by the Free Software
-# Foundation; either version 2 of the License, or any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
+# 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
#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+# 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.
+#
class Chef
class Provider
@@ -34,4 +32,4 @@ class Chef
end
end
end
-end \ No newline at end of file
+end
diff --git a/chef/spec/lib/chef/provider/snakeoil.rb b/chef/spec/lib/chef/provider/snakeoil.rb
index 7985218f04..5db174bdf7 100644
--- a/chef/spec/lib/chef/provider/snakeoil.rb
+++ b/chef/spec/lib/chef/provider/snakeoil.rb
@@ -1,22 +1,20 @@
#
# Author:: Adam Jacob (<adam@opscode.com>)
# Copyright:: Copyright (c) 2008 Opscode, Inc.
-# License:: GNU General Public License version 2 or later
-#
-# This program and entire repository is free software; you can
-# redistribute it and/or modify it under the terms of the GNU
-# General Public License as published by the Free Software
-# Foundation; either version 2 of the License, or any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
+# 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
#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+# 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.
+#
class Chef
class Provider
@@ -34,4 +32,4 @@ class Chef
end
end
end
-end \ No newline at end of file
+end
diff --git a/chef/spec/lib/chef/resource/cat.rb b/chef/spec/lib/chef/resource/cat.rb
index 0602158312..71e1df1f75 100644
--- a/chef/spec/lib/chef/resource/cat.rb
+++ b/chef/spec/lib/chef/resource/cat.rb
@@ -1,21 +1,20 @@
+#
# Author:: Adam Jacob (<adam@opscode.com>)
# Copyright:: Copyright (c) 2008 Opscode, Inc.
-# License:: GNU General Public License version 2 or later
+# 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
#
-# This program and entire repository is free software; you can
-# redistribute it and/or modify it under the terms of the GNU
-# General Public License as published by the Free Software
-# Foundation; either version 2 of the License, or any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+# 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.
+#
class Chef
class Resource
@@ -39,4 +38,4 @@ class Chef
end
end
end
-end \ No newline at end of file
+end
diff --git a/chef/spec/lib/chef/resource/zen_master.rb b/chef/spec/lib/chef/resource/zen_master.rb
index 5cbb82f5b9..6a40d545c3 100644
--- a/chef/spec/lib/chef/resource/zen_master.rb
+++ b/chef/spec/lib/chef/resource/zen_master.rb
@@ -1,21 +1,20 @@
+#
# Author:: Adam Jacob (<adam@opscode.com>)
# Copyright:: Copyright (c) 2008 Opscode, Inc.
-# License:: GNU General Public License version 2 or later
+# 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
#
-# This program and entire repository is free software; you can
-# redistribute it and/or modify it under the terms of the GNU
-# General Public License as published by the Free Software
-# Foundation; either version 2 of the License, or any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+# 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.
+#
class Chef
class Resource
@@ -41,4 +40,4 @@ class Chef
end
end
end
-end \ No newline at end of file
+end
diff --git a/chef/spec/spec_helper.rb b/chef/spec/spec_helper.rb
index 35bc9d57ac..0dd5b202cb 100644
--- a/chef/spec/spec_helper.rb
+++ b/chef/spec/spec_helper.rb
@@ -1,21 +1,20 @@
+#
# Author:: Adam Jacob (<adam@opscode.com>)
# Copyright:: Copyright (c) 2008 Opscode, Inc.
-# License:: GNU General Public License version 2 or later
+# 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
#
-# This program and entire repository is free software; you can
-# redistribute it and/or modify it under the terms of the GNU
-# General Public License as published by the Free Software
-# Foundation; either version 2 of the License, or any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+# 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.
+#
$:.unshift(File.join(File.dirname(__FILE__), "..", "lib"))
diff --git a/chef/spec/unit/couchdb_spec.rb b/chef/spec/unit/couchdb_spec.rb
index c822671225..62ba85e33d 100644
--- a/chef/spec/unit/couchdb_spec.rb
+++ b/chef/spec/unit/couchdb_spec.rb
@@ -31,7 +31,7 @@ describe Chef::CouchDB, "new" do
Chef::REST.should_receive(:new).with("http://monkey")
Chef::CouchDB.new
end
-
+
it "should create a new Chef::REST object from a provided url" do
Chef::REST.should_receive(:new).with("http://monkeypants")
Chef::CouchDB.new("http://monkeypants")
@@ -292,4 +292,4 @@ describe Chef::CouchDB, "view_uri" do
@couchdb.view_uri("nodes", "all")
end
end
-end \ No newline at end of file
+end
diff --git a/chef/spec/unit/mixin/command_spec.rb b/chef/spec/unit/mixin/command_spec.rb
deleted file mode 100644
index d35712bab5..0000000000
--- a/chef/spec/unit/mixin/command_spec.rb
+++ /dev/null
@@ -1,85 +0,0 @@
-#
-# Author:: Matthew Landauer (<matthew@openaustralia.org>)
-# Copyright:: Copyright (c) 2008 Matthew Landauer
-# 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 File.expand_path(File.join(File.dirname(__FILE__), "..", "..", "spec_helper"))
-
-describe Chef::Mixin::Command do
- before :each do
- Chef::Log.init
- end
-
- # Reset the logger for other tests
- after :each do
- Chef::Log.init
- end
-
- it "should log the command's standard output at debug log level" do
- command = "ruby -e 'puts 5'"
- Chef::Log.should_receive(:debug).with("Executing #{command}").ordered
- Chef::Log.should_receive(:debug).with("---- Begin output of #{command} ----").ordered
- Chef::Log.should_receive(:debug).with("STDOUT: 5").ordered
- Chef::Log.should_receive(:debug).with("---- End output of #{command} ----").ordered
- Chef::Log.should_receive(:debug).with("Ran #{command} returned 0").ordered
- Chef::Mixin::Command.run_command(:command => command)
- end
-
- it "should log the command's standard error at debug log level" do
- command = "ruby -e 'STDERR.puts 5'"
- Chef::Log.should_receive(:debug).with("Executing #{command}").ordered
- Chef::Log.should_receive(:debug).with("---- Begin output of #{command} ----").ordered
- Chef::Log.should_receive(:debug).with("STDERR: 5").ordered
- Chef::Log.should_receive(:debug).with("---- End output of #{command} ----").ordered
- Chef::Log.should_receive(:debug).with("Ran #{command} returned 0").ordered
- Chef::Mixin::Command.run_command(:command => command)
- end
-
- it "should log the command's standard out and error at the same time" do
- command = "ruby -e 'STDERR.puts 1; puts 2; STDERR.puts 3; puts 4'"
- Chef::Log.should_receive(:debug).with("Executing #{command}").ordered
- Chef::Log.should_receive(:debug).with("---- Begin output of #{command} ----").ordered
- Chef::Log.should_receive(:debug).with("STDERR: 1").ordered
- Chef::Log.should_receive(:debug).with("STDOUT: 2").ordered
- Chef::Log.should_receive(:debug).with("STDERR: 3").ordered
- Chef::Log.should_receive(:debug).with("STDOUT: 4").ordered
- Chef::Log.should_receive(:debug).with("---- End output of #{command} ----").ordered
- Chef::Log.should_receive(:debug).with("Ran #{command} returned 0").ordered
- Chef::Mixin::Command.run_command(:command => command)
- end
-
- it "should throw an exception if the command returns a bad exit value" do
- command = "ruby -e 'puts 1; exit 1'"
- Chef::Log.level :debug
- # Stub out Chef::Log.debug to avoid messages going to console
- Chef::Log.stub!(:debug)
- lambda {Chef::Mixin::Command.run_command(:command => command)}.should raise_error(Chef::Exceptions::Exec, "#{command} returned 1, expected 0")
- end
-
- it "should include the command output in the exception if the log level is not at debug" do
- command = "ruby -e 'puts 1; exit 1'"
- Chef::Log.level :info
- lambda {Chef::Mixin::Command.run_command(:command => command)}.should raise_error(Chef::Exceptions::Exec, "#{command} returned 1, expected 0\n---- Begin output of #{command} ----\nSTDOUT: 1\n---- End output of #{command} ----\n")
- end
-
- it "should log the output as the command is executing" do
- command = "ruby -e 'STDOUT.sync = true; puts 1; sleep 2; puts 2'"
- Chef::Log.should_receive(:debug).with("Executing #{command}").ordered
- Chef::Log.should_receive(:debug).with("---- Begin output of #{command} ----").ordered
- Chef::Log.should_receive(:debug).with("STDOUT: 1").ordered
- lambda {Chef::Mixin::Command.run_command(:command => command, :timeout => 1)}.should raise_error(Timeout::Error)
- end
-end
diff --git a/chef/spec/unit/mixin/template_spec.rb b/chef/spec/unit/mixin/template_spec.rb
index 86e0b59232..05fee6820a 100644
--- a/chef/spec/unit/mixin/template_spec.rb
+++ b/chef/spec/unit/mixin/template_spec.rb
@@ -31,7 +31,8 @@ describe Chef::Mixin::Template, "render_template" do
end
it "should return a file" do
- @template.render_template("abcdef", {}).should be_kind_of(File)
+ f = @template.render_template("abcdef", {})
+ @template.render_template("abcdef", {}).should be_kind_of(Tempfile)
end
describe "when an exception is raised in the template" do
diff --git a/chef/spec/unit/provider/package/yum_spec.rb b/chef/spec/unit/provider/package/yum_spec.rb
index 6a554c812f..2e8ddb9971 100644
--- a/chef/spec/unit/provider/package/yum_spec.rb
+++ b/chef/spec/unit/provider/package/yum_spec.rb
@@ -36,55 +36,16 @@ describe Chef::Provider::Package::Yum, "load_current_resource" do
:updated => nil
)
@status = mock("Status", :exitstatus => 0)
+ @yum_cache = mock(
+ 'Chef::Provider::Yum::YumCache',
+ :refresh => true,
+ :flush => true,
+ :installed_version => "1.2.4-11.18.el5",
+ :candidate_version => "1.2.4-11.18.el5_2.3"
+ )
+ Chef::Provider::Package::Yum::YumCache.stub!(:instance).and_return(@yum_cache)
@provider = Chef::Provider::Package::Yum.new(@node, @new_resource)
Chef::Resource::Package.stub!(:new).and_return(@current_resource)
- @provider.stub!(:popen4).and_return(@status)
- @stdin = mock("STDIN", :null_object => true)
- @stdout = mock("STDOUT", :null_object => true)
- @stdout.stub!(:each).and_yield("Installed Packages").
- and_yield("Name : cups").
- and_yield("Arch : i386").
- and_yield("Epoch : 1").
- and_yield("Version: 1.2.4").
- and_yield("Release: 11.18.el5").
- and_yield("Size : 7.8 M").
- and_yield("Repo : installed").
- and_yield("Summary: Common Unix Printing System").
- and_yield("Description:").
- and_yield("The Common UNIX Printing System provides a portable printing layer for").
- and_yield("UNIX® operating systems. It has been developed by Easy Software Products").
- and_yield("to promote a standard printing solution for all UNIX vendors and users.").
- and_yield("CUPS provides the System V and Berkeley command-line interfaces.").
- and_yield("").
- and_yield("Available Packages").
- and_yield("Name : cups").
- and_yield("Arch : i386").
- and_yield("Epoch : 1").
- and_yield("Version: 1.2.4").
- and_yield("Release: 11.18.el5_2.3").
- and_yield("Size : 2.7 M").
- and_yield("Repo : updates").
- and_yield("Summary: Common Unix Printing System").
- and_yield("Description:").
- and_yield("The Common UNIX Printing System provides a portable printing layer for").
- and_yield("UNIX® operating systems. It has been developed by Easy Software Products").
- and_yield("to promote a standard printing solution for all UNIX vendors and users.").
- and_yield("CUPS provides the System V and Berkeley command-line interfaces.")
- @stdout_available = mock("STDOUT AVAILABLE", :null_object => true)
- @stdout_available.stub!(:each).and_yield("Available Packages").
- and_yield("Name : cups").
- and_yield("Arch : i386").
- and_yield("Epoch : 1").
- and_yield("Version: 1.2.4").
- and_yield("Release: 11.18.el5_2.3").
- and_yield("Size : 2.7 M").
- and_yield("Repo : updates").
- and_yield("Summary: Common Unix Printing System").
- and_yield("Description:").
- and_yield("The Common UNIX Printing System provides a portable printing layer for").
- and_yield("UNIX® operating systems. It has been developed by Easy Software Products").
- and_yield("to promote a standard printing solution for all UNIX vendors and users.").
- and_yield("CUPS provides the System V and Berkeley command-line interfaces.")
@stderr = mock("STDERR", :null_object => true)
@pid = mock("PID", :null_object => true)
end
@@ -99,45 +60,22 @@ describe Chef::Provider::Package::Yum, "load_current_resource" do
@provider.load_current_resource
end
- it "should run yum info with the package name" do
- @provider.should_receive(:popen4).with("yum info -q -y #{@new_resource.package_name}").and_return(@status)
- @provider.load_current_resource
- end
-
- it "should read stdout on yum info" do
- @provider.stub!(:popen4).and_yield(@pid, @stdin, @stdout, @stderr).and_return(@status)
- @stdout.should_receive(:each).and_return(true)
- @provider.load_current_resource
- end
-
it "should set the installed version to nil on the current resource if no installed package" do
- @provider.stub!(:popen4).and_yield(@pid, @stdin, @stdout_available, @stderr).and_return(@status)
+ @yum_cache.stub!(:installed_version).and_return(nil)
@current_resource.should_receive(:version).with(nil).and_return(true)
@provider.load_current_resource
end
- it "should set the installed version if yum info has one" do
- @provider.stub!(:popen4).and_yield(@pid, @stdin, @stdout, @stderr).and_return(@status)
+ it "should set the installed version if yum has one" do
@current_resource.should_receive(:version).with("1.2.4-11.18.el5").and_return(true)
@provider.load_current_resource
end
it "should set the candidate version if yum info has one" do
- @provider.stub!(:popen4).and_yield(@pid, @stdin, @stdout, @stderr).and_return(@status)
@provider.load_current_resource
@provider.candidate_version.should eql("1.2.4-11.18.el5_2.3")
end
- it "should raise an exception if yum info fails" do
- @status.should_receive(:exitstatus).and_return(1)
- lambda { @provider.load_current_resource }.should raise_error(Chef::Exceptions::Package)
- end
-
- it "should not raise an exception if yum info succeeds" do
- @status.should_receive(:exitstatus).and_return(0)
- lambda { @provider.load_current_resource }.should_not raise_error(Chef::Exceptions::Package)
- end
-
it "should return the current resouce" do
@provider.load_current_resource.should eql(@current_resource)
end
@@ -154,6 +92,14 @@ describe Chef::Provider::Package::Yum, "install_package" do
:package_name => "emacs",
:updated => nil
)
+ @yum_cache = mock(
+ 'Chef::Provider::Yum::YumCache',
+ :refresh => true,
+ :flush => true,
+ :installed_version => "1.2.4-11.18.el5",
+ :candidate_version => "1.2.4-11.18.el5_2.3"
+ )
+ Chef::Provider::Package::Yum::YumCache.stub!(:instance).and_return(@yum_cache)
@provider = Chef::Provider::Package::Yum.new(@node, @new_resource)
end
@@ -169,13 +115,21 @@ describe Chef::Provider::Package::Yum, "upgrade_package" do
before(:each) do
@node = mock("Chef::Node", :null_object => true)
- @new_resource = mock("Chef::Resource::Package",
+ @new_resource = mock("Chef::Resource::Package",
:null_object => true,
:name => "emacs",
:version => nil,
:package_name => "emacs",
:updated => nil
)
+ @yum_cache = mock(
+ 'Chef::Provider::Yum::YumCache',
+ :refresh => true,
+ :flush => true,
+ :installed_version => "1.2.4-11.18.el5",
+ :candidate_version => "1.2.4-11.18.el5_2.3"
+ )
+ Chef::Provider::Package::Yum::YumCache.stub!(:instance).and_return(@yum_cache)
@current_resource = mock("Chef::Resource::Package",
:null_object => true,
:name => "emacs",
@@ -214,6 +168,14 @@ describe Chef::Provider::Package::Yum, "remove_package" do
:package_name => "emacs",
:updated => nil
)
+ @yum_cache = mock(
+ 'Chef::Provider::Yum::YumCache',
+ :refresh => true,
+ :flush => true,
+ :installed_version => "1.2.4-11.18.el5",
+ :candidate_version => "1.2.4-11.18.el5_2.3"
+ )
+ Chef::Provider::Package::Yum::YumCache.stub!(:instance).and_return(@yum_cache)
@provider = Chef::Provider::Package::Yum.new(@node, @new_resource)
end
@@ -235,6 +197,14 @@ describe Chef::Provider::Package::Yum, "purge_package" do
:package_name => "emacs",
:updated => nil
)
+ @yum_cache = mock(
+ 'Chef::Provider::Yum::YumCache',
+ :refresh => true,
+ :flush => true,
+ :installed_version => "1.2.4-11.18.el5",
+ :candidate_version => "1.2.4-11.18.el5_2.3"
+ )
+ Chef::Provider::Package::Yum::YumCache.stub!(:instance).and_return(@yum_cache)
@provider = Chef::Provider::Package::Yum.new(@node, @new_resource)
end
diff --git a/chef/spec/unit/provider/remote_file_spec.rb b/chef/spec/unit/provider/remote_file_spec.rb
index 430a2e5916..e2a5fbb94d 100644
--- a/chef/spec/unit/provider/remote_file_spec.rb
+++ b/chef/spec/unit/provider/remote_file_spec.rb
@@ -65,10 +65,46 @@ describe Chef::Provider::RemoteFile, "do_remote_file" do
end
describe "when given a URI source" do
- it "should download the file from the remote URL" do
- @resource.source("http://opscode.com/seattle.txt")
- @rest.should_receive(:get_rest).with("http://opscode.com/seattle.txt", true).and_return(@tempfile)
- do_remote_file
+ describe "and given a checksum" do
+ it "should not download the file if the checksum matches" do
+ @resource.checksum("0fd012fdc96e96f8f7cf2046522a54aed0ce470224513e45da6bc1a17a4924aa")
+ @resource.source("http://opscode.com/seattle.txt")
+ @rest.should_not_receive(:get_rest).with("http://opscode.com/seattle.txt", true).and_return(@tempfile)
+ do_remote_file
+ end
+
+ it "should not download the file if the checksum is a partial match from the beginning" do
+ @resource.checksum("0fd012fd")
+ @resource.source("http://opscode.com/seattle.txt")
+ @rest.should_not_receive(:get_rest).with("http://opscode.com/seattle.txt", true).and_return(@tempfile)
+ do_remote_file
+ end
+
+
+ it "should download the file if the checksum does not match" do
+ @resource.checksum("this hash doesn't match")
+ @resource.source("http://opscode.com/seattle.txt")
+ @rest.should_receive(:get_rest).with("http://opscode.com/seattle.txt", true).and_return(@tempfile)
+ do_remote_file
+ end
+
+ it "should download the file if the checksum matches, but not from the beginning" do
+ @resource.checksum("fd012fd")
+ @resource.source("http://opscode.com/seattle.txt")
+ @rest.should_receive(:get_rest).with("http://opscode.com/seattle.txt", true).and_return(@tempfile)
+ do_remote_file
+ end
+
+
+ end
+
+ describe "and not given a checksum" do
+ it "should download the file from the remote URL" do
+ @resource.checksum(nil)
+ @resource.source("http://opscode.com/seattle.txt")
+ @rest.should_receive(:get_rest).with("http://opscode.com/seattle.txt", true).and_return(@tempfile)
+ do_remote_file
+ end
end
end
@@ -102,17 +138,6 @@ describe Chef::Provider::RemoteFile, "do_remote_file" do
end
end
- it "should set the checksum if the file exists" do
- @provider.should_receive(:checksum).with(@resource.path)
- do_remote_file
- end
-
- it "should not set the checksum if the file doesn't exist" do
- File.stub!(:exists?).with(@resource.path).and_return(false)
- @provider.should_not_receive(:checksum).with(@resource.path)
- do_remote_file
- end
-
it "should not transfer the file if it has not been changed" do
r = Net::HTTPNotModified.new("one", "two", "three")
e = Net::HTTPRetriableError.new("304", r)
diff --git a/chef/spec/unit/resource/remote_file_spec.rb b/chef/spec/unit/resource/remote_file_spec.rb
index 24ed30f4e0..cc31b543ef 100644
--- a/chef/spec/unit/resource/remote_file_spec.rb
+++ b/chef/spec/unit/resource/remote_file_spec.rb
@@ -49,5 +49,16 @@ describe Chef::Resource::RemoteFile do
@resource.cookbook.should == nil
end
end
+
+ describe "checksum" do
+ it "should accept a string for the checksum object" do
+ @resource.checksum "asdf"
+ @resource.checksum.should eql("asdf")
+ end
+
+ it "should default to nil" do
+ @resource.checksum.should == nil
+ end
+ end
-end \ No newline at end of file
+end
diff --git a/chef/spec/unit/util/file_edit_spec.rb b/chef/spec/unit/util/file_edit_spec.rb
new file mode 100644
index 0000000000..24d6503fc2
--- /dev/null
+++ b/chef/spec/unit/util/file_edit_spec.rb
@@ -0,0 +1,127 @@
+#
+# Author:: Nuo Yan (<nuo@opscode.com>)
+# Copyright:: Copyright (c) 2008 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.
+#
+
+
+require File.join(File.dirname(__FILE__), '..', '..', "spec_helper")
+
+describe Chef::Util::FileEdit, "initialiize" do
+ it "should create a new Chef::Util::FileEdit object" do
+ Chef::Util::FileEdit.new("./spec/data/fileedit/hosts").should be_kind_of(Chef::Util::FileEdit)
+ end
+
+ it "should throw an exception if the input file does not exist" do
+ lambda{Chef::Util::FileEdit.new("nonexistfile")}.should raise_error
+ end
+
+ it "should throw an exception if the input file is blank" do
+ lambda{Chef::Util::FileEdit.new("./spec/data/fileedit/blank")}.should raise_error
+ end
+
+end
+
+describe Chef::Util::FileEdit, "search_file_replace" do
+
+ it "should accept regex passed in as a string (not Regexp object) and replace the match if there is one" do
+ helper_method("./spec/data/fileedit/hosts", "localhost", true)
+ end
+
+
+ it "should accept regex passed in as a Regexp object and replace the match if there is one" do
+ helper_method("./spec/data/fileedit/hosts", /localhost/, true)
+ end
+
+
+ it "should do nothing if there isn't a match" do
+ helper_method("./spec/data/fileedit/hosts", /pattern/, false)
+ end
+
+
+ def helper_method(filename, regex, value)
+ fedit = Chef::Util::FileEdit.new(filename)
+ fedit.search_file_replace(regex, "replacement")
+ fedit.write_file
+ (File.exist? filename+".old").should be(value)
+ if value == true
+ newfile = File.new(filename).readlines
+ newfile[0].should match(/replacement/)
+ File.delete("./spec/data/fileedit/hosts")
+ File.rename("./spec/data/fileedit/hosts.old", "./spec/data/fileedit/hosts")
+ end
+ end
+
+end
+
+describe Chef::Util::FileEdit, "search_file_replace_line" do
+
+ it "should search for match and replace the whole line" do
+ fedit = Chef::Util::FileEdit.new("./spec/data/fileedit/hosts")
+ fedit.search_file_replace_line(/localhost/, "replacement line")
+ fedit.write_file
+ newfile = File.new("./spec/data/fileedit/hosts").readlines
+ newfile[0].should match(/replacement/)
+ newfile[0].should_not match(/127/)
+ File.delete("./spec/data/fileedit/hosts")
+ File.rename("./spec/data/fileedit/hosts.old", "./spec/data/fileedit/hosts")
+ end
+
+end
+
+describe Chef::Util::FileEdit, "search_file_delete" do
+ it "should search for match and delete the match" do
+ fedit = Chef::Util::FileEdit.new("./spec/data/fileedit/hosts")
+ fedit.search_file_delete(/localhost/)
+ fedit.write_file
+ newfile = File.new("./spec/data/fileedit/hosts").readlines
+ newfile[0].should_not match(/localhost/)
+ newfile[0].should match(/127/)
+ File.delete("./spec/data/fileedit/hosts")
+ File.rename("./spec/data/fileedit/hosts.old", "./spec/data/fileedit/hosts")
+ end
+end
+
+describe Chef::Util::FileEdit, "search_file_delete_line" do
+ it "should search for match and delete the matching line" do
+ fedit = Chef::Util::FileEdit.new("./spec/data/fileedit/hosts")
+ fedit.search_file_delete_line(/localhost/)
+ fedit.write_file
+ newfile = File.new("./spec/data/fileedit/hosts").readlines
+ newfile[0].should_not match(/localhost/)
+ newfile[0].should match(/broadcasthost/)
+ File.delete("./spec/data/fileedit/hosts")
+ File.rename("./spec/data/fileedit/hosts.old", "./spec/data/fileedit/hosts")
+ end
+end
+
+describe Chef::Util::FileEdit, "insert_line_after_match" do
+ it "should search for match and insert the given line after the matching line" do
+ fedit = Chef::Util::FileEdit.new("./spec/data/fileedit/hosts")
+ fedit.insert_line_after_match(/localhost/, "new line inserted")
+ fedit.write_file
+ newfile = File.new("./spec/data/fileedit/hosts").readlines
+ newfile[1].should match(/new/)
+ File.delete("./spec/data/fileedit/hosts")
+ File.rename("./spec/data/fileedit/hosts.old", "./spec/data/fileedit/hosts")
+ end
+
+end
+
+
+
+
+
+