Merge branch '0.24.x'
Conflicts: lib/puppet/indirector/facts/facter.rb lib/puppet/provider/augeas/augeas.rb lib/puppet/util/filetype.rb spec/unit/indirector/facts/facter.rb spec/unit/provider/augeas/augeas.rb test/util/filetype.rb
This commit is contained in:
Коммит
3fbec12076
16
CHANGELOG
16
CHANGELOG
|
@ -14,6 +14,22 @@
|
|||
Fixed #1840 - Bug fixes and improvements for Emacs puppet-mode.el
|
||||
|
||||
0.24.8
|
||||
Fixed #1831 - Added sprintf function
|
||||
|
||||
Fixed #1830 - Added regsubst function
|
||||
|
||||
Updated up2date and service confines to add support for Oracle EL and VM
|
||||
|
||||
Fixing #1948 and #1953 - augeas ins bug: wrong number of arguments (1 for 3)
|
||||
|
||||
Fixing #944 - changing error message from warning to info - connection recycled
|
||||
|
||||
Fixed #961 - puppetd creating too many/not closing TCP connections
|
||||
|
||||
Fixed #1959 - Added column protection for environment schema migration
|
||||
|
||||
Fixing #1869 - autoloaded files should never leak exceptions
|
||||
|
||||
Fixing #1543 - Nagios parse errors no longer kill Puppet
|
||||
|
||||
Fixed #1420 - nagios_serviceescalation not allowing host_name more than one type
|
||||
|
|
|
@ -16,7 +16,7 @@ elseif exists("b:current_syntax")
|
|||
finish
|
||||
endif
|
||||
|
||||
syn region puppetDefine start="^\s*\(class\|define\|site\|node\)" end="{" contains=puppetDefType,puppetDefName,puppetDefArguments
|
||||
syn region puppetDefine start="^\s*\(class\|define\|node\)" end="{" contains=puppetDefType,puppetDefName,puppetDefArguments
|
||||
syn keyword puppetDefType class define site node inherits contained
|
||||
syn keyword puppetInherits inherits contained
|
||||
syn region puppetDefArguments start="(" end=")" contains=puppetArgument
|
||||
|
|
|
@ -416,18 +416,20 @@ class Nagios::Base
|
|||
:dependent_service_description, :host_name, :hostgroup_name,
|
||||
:service_description, :inherits_parent, :execution_failure_criteria,
|
||||
:notification_failure_criteria, :dependency_period,
|
||||
:register, :use
|
||||
:register, :use,
|
||||
:_naginator_name
|
||||
|
||||
setnamevar :service_description
|
||||
setnamevar :_naginator_name
|
||||
end
|
||||
|
||||
newtype :serviceescalation do
|
||||
setparameters :host_name, :hostgroup_name, :service_description, :contacts,
|
||||
:contact_groups, :first_notification, :last_notification,
|
||||
:notification_interval, :escalation_period, :escalation_options,
|
||||
:register, :use
|
||||
:register, :use,
|
||||
:_naginator_name
|
||||
|
||||
setnamevar :service_description
|
||||
setnamevar :_naginator_name
|
||||
end
|
||||
|
||||
newtype :hostdependency do
|
||||
|
@ -435,18 +437,20 @@ class Nagios::Base
|
|||
setparameters :dependent_host_name, :dependent_hostgroup_name, :host_name,
|
||||
:hostgroup_name, :inherits_parent, :execution_failure_criteria,
|
||||
:notification_failure_criteria, :dependency_period,
|
||||
:register, :use
|
||||
:register, :use,
|
||||
:_naginator_name
|
||||
|
||||
setnamevar :host_name
|
||||
setnamevar :_naginator_name
|
||||
end
|
||||
|
||||
newtype :hostescalation do
|
||||
setparameters :host_name, :hostgroup_name, :contacts, :contact_groups,
|
||||
:first_notification, :last_notification, :notification_interval,
|
||||
:escalation_period, :escalation_options,
|
||||
:register, :use
|
||||
:register, :use,
|
||||
:_naginator_name
|
||||
|
||||
setnamevar :host_name
|
||||
setnamevar :_naginator_name
|
||||
end
|
||||
|
||||
newtype :hostextinfo do
|
||||
|
@ -463,9 +467,10 @@ class Nagios::Base
|
|||
|
||||
setparameters :host_name, :service_description, :notes, :notes_url,
|
||||
:action_url, :icon_image, :icon_image_alt,
|
||||
:register, :use
|
||||
:register, :use,
|
||||
:_naginator_name
|
||||
|
||||
setnamevar :service_description
|
||||
setnamevar :_naginator_name
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -8,8 +8,12 @@ class Puppet::Node::Facts::Facter < Puppet::Indirector::Code
|
|||
|
||||
|
||||
def self.load_fact_plugins
|
||||
# LAK:NOTE See http://snurl.com/21zf8 [groups_google_com]
|
||||
x = Puppet[:factpath].split(":").each do |dir|
|
||||
# Add any per-module fact directories to the factpath
|
||||
module_fact_dirs = Puppet[:modulepath].split(":").collect do |d|
|
||||
Dir.glob("%s/*/plugins/facter" % d)
|
||||
end.flatten
|
||||
dirs = module_fact_dirs + Puppet[:factpath].split(":")
|
||||
x = dirs.each do |dir|
|
||||
load_facts_in_dir(dir)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -36,57 +36,7 @@ module Puppet::Network
|
|||
interface.methods.each { |ary|
|
||||
method = ary[0]
|
||||
newclient.send(:define_method,method) { |*args|
|
||||
Puppet.debug "Calling %s.%s" % [namespace, method]
|
||||
begin
|
||||
call("%s.%s" % [namespace, method.to_s],*args)
|
||||
rescue OpenSSL::SSL::SSLError => detail
|
||||
if detail.message =~ /bad write retry/
|
||||
Puppet.warning "Transient SSL write error; restarting connection and retrying"
|
||||
self.recycle_connection
|
||||
retry
|
||||
end
|
||||
["certificate verify failed", "hostname was not match", "hostname not match"].each do |str|
|
||||
if detail.message.include?(str)
|
||||
Puppet.warning "Certificate validation failed; consider using the certname configuration option"
|
||||
end
|
||||
end
|
||||
raise XMLRPCClientError,
|
||||
"Certificates were not trusted: %s" % detail
|
||||
rescue ::XMLRPC::FaultException => detail
|
||||
raise XMLRPCClientError, detail.faultString
|
||||
rescue Errno::ECONNREFUSED => detail
|
||||
msg = "Could not connect to %s on port %s" %
|
||||
[@host, @port]
|
||||
raise XMLRPCClientError, msg
|
||||
rescue SocketError => detail
|
||||
Puppet.err "Could not find server %s: %s" %
|
||||
[@host, detail.to_s]
|
||||
error = XMLRPCClientError.new(
|
||||
"Could not find server %s" % @host
|
||||
)
|
||||
error.set_backtrace detail.backtrace
|
||||
raise error
|
||||
rescue Errno::EPIPE, EOFError
|
||||
Puppet.warning "Other end went away; restarting connection and retrying"
|
||||
self.recycle_connection
|
||||
retry
|
||||
rescue Timeout::Error => detail
|
||||
Puppet.err "Connection timeout calling %s.%s: %s" %
|
||||
[namespace, method, detail.to_s]
|
||||
error = XMLRPCClientError.new("Connection Timeout")
|
||||
error.set_backtrace(detail.backtrace)
|
||||
raise error
|
||||
rescue => detail
|
||||
if detail.message =~ /^Wrong size\. Was \d+, should be \d+$/
|
||||
Puppet.warning "XMLRPC returned wrong size. Retrying."
|
||||
retry
|
||||
end
|
||||
Puppet.err "Could not call %s.%s: %s" %
|
||||
[namespace, method, detail.inspect]
|
||||
error = XMLRPCClientError.new(detail.to_s)
|
||||
error.set_backtrace detail.backtrace
|
||||
raise error
|
||||
end
|
||||
make_rpc_call(namespace, method, *args)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -97,13 +47,119 @@ module Puppet::Network
|
|||
@clients[handler] || self.mkclient(handler)
|
||||
end
|
||||
|
||||
class ErrorHandler
|
||||
def initialize(&block)
|
||||
metaclass.define_method(:execute, &block)
|
||||
end
|
||||
end
|
||||
|
||||
# Use a class variable so all subclasses have access to it.
|
||||
@@error_handlers = {}
|
||||
|
||||
def self.error_handler(exception)
|
||||
if handler = @@error_handlers[exception.class]
|
||||
return handler
|
||||
else
|
||||
return @@error_handlers[:default]
|
||||
end
|
||||
end
|
||||
|
||||
def self.handle_error(*exceptions, &block)
|
||||
handler = ErrorHandler.new(&block)
|
||||
|
||||
exceptions.each do |exception|
|
||||
@@error_handlers[exception] = handler
|
||||
end
|
||||
end
|
||||
|
||||
handle_error(OpenSSL::SSL::SSLError) do |client, detail, namespace, method|
|
||||
if detail.message =~ /bad write retry/
|
||||
Puppet.warning "Transient SSL write error; restarting connection and retrying"
|
||||
client.recycle_connection
|
||||
return :retry
|
||||
end
|
||||
["certificate verify failed", "hostname was not match", "hostname not match"].each do |str|
|
||||
if detail.message.include?(str)
|
||||
Puppet.warning "Certificate validation failed; consider using the certname configuration option"
|
||||
end
|
||||
end
|
||||
raise XMLRPCClientError, "Certificates were not trusted: %s" % detail
|
||||
end
|
||||
|
||||
handle_error(:default) do |client, detail, namespace, method|
|
||||
if detail.message.to_s =~ /^Wrong size\. Was \d+, should be \d+$/
|
||||
Puppet.warning "XMLRPC returned wrong size. Retrying."
|
||||
return :retry
|
||||
end
|
||||
Puppet.err "Could not call %s.%s: %s" % [namespace, method, detail.inspect]
|
||||
error = XMLRPCClientError.new(detail.to_s)
|
||||
error.set_backtrace detail.backtrace
|
||||
raise error
|
||||
end
|
||||
|
||||
handle_error(OpenSSL::SSL::SSLError) do |client, detail, namespace, method|
|
||||
if detail.message =~ /bad write retry/
|
||||
Puppet.warning "Transient SSL write error; restarting connection and retrying"
|
||||
client.recycle_connection
|
||||
return :retry
|
||||
end
|
||||
["certificate verify failed", "hostname was not match", "hostname not match"].each do |str|
|
||||
if detail.message.include?(str)
|
||||
Puppet.warning "Certificate validation failed; consider using the certname configuration option"
|
||||
end
|
||||
end
|
||||
raise XMLRPCClientError, "Certificates were not trusted: %s" % detail
|
||||
end
|
||||
|
||||
handle_error(::XMLRPC::FaultException) do |client, detail, namespace, method|
|
||||
raise XMLRPCClientError, detail.faultString
|
||||
end
|
||||
|
||||
handle_error(Errno::ECONNREFUSED) do |client, detail, namespace, method|
|
||||
msg = "Could not connect to %s on port %s" % [client.host, client.port]
|
||||
raise XMLRPCClientError, msg
|
||||
end
|
||||
|
||||
handle_error(SocketError) do |client, detail, namespace, method|
|
||||
Puppet.err "Could not find server %s: %s" % [@host, detail.to_s]
|
||||
error = XMLRPCClientError.new("Could not find server %s" % client.host)
|
||||
error.set_backtrace detail.backtrace
|
||||
raise error
|
||||
end
|
||||
|
||||
handle_error(Errno::EPIPE, EOFError) do |client, detail, namespace, method|
|
||||
Puppet.info "Other end went away; restarting connection and retrying"
|
||||
client.recycle_connection
|
||||
return :retry
|
||||
end
|
||||
|
||||
handle_error(Timeout::Error) do |client, detail, namespace, method|
|
||||
Puppet.err "Connection timeout calling %s.%s: %s" % [namespace, method, detail.to_s]
|
||||
error = XMLRPCClientError.new("Connection Timeout")
|
||||
error.set_backtrace(detail.backtrace)
|
||||
raise error
|
||||
end
|
||||
|
||||
def make_rpc_call(namespace, method, *args)
|
||||
Puppet.debug "Calling %s.%s" % [namespace, method]
|
||||
begin
|
||||
call("%s.%s" % [namespace, method.to_s],*args)
|
||||
rescue Exception => detail
|
||||
retry if self.class.error_handler(detail).execute(self, detail, namespace, method) == :retry
|
||||
end
|
||||
ensure
|
||||
http.finish if http.started?
|
||||
end
|
||||
|
||||
def http
|
||||
unless @http
|
||||
@http = Puppet::Network::HttpPool.http_instance(@host, @port, true)
|
||||
@http = Puppet::Network::HttpPool.http_instance(host, port, true)
|
||||
end
|
||||
@http
|
||||
end
|
||||
|
||||
attr_reader :host, :port
|
||||
|
||||
def initialize(hash = {})
|
||||
hash[:Path] ||= "/RPC2"
|
||||
hash[:Server] ||= Puppet[:server]
|
||||
|
@ -135,7 +191,11 @@ module Puppet::Network
|
|||
# or we've just downloaded certs and we need to create new http instances
|
||||
# with the certs added.
|
||||
def recycle_connection
|
||||
@http = Puppet::Network::HttpPool.http_instance(@host, @port, true) # reset the instance
|
||||
if http.started?
|
||||
http.finish
|
||||
end
|
||||
@http = nil
|
||||
self.http # force a new one
|
||||
end
|
||||
|
||||
def start
|
||||
|
|
|
@ -0,0 +1,93 @@
|
|||
module Puppet::Parser::Functions
|
||||
newfunction(:regsubst, :type => :rvalue,
|
||||
:doc => "\
|
||||
Perform regexp replacement on a string.
|
||||
|
||||
Parameters (in order):
|
||||
|
||||
:str:
|
||||
The string to operate on.
|
||||
|
||||
:regexp:
|
||||
The regular expression matching the string. If you want it
|
||||
anchored at the start and/or end of the string, you must do
|
||||
that with ^ and $ yourself.
|
||||
|
||||
:replacement:
|
||||
Replacement string. Can contain back references to what was
|
||||
matched using \\0, \\1, and so on.
|
||||
|
||||
:flags:
|
||||
Optional. String of single letter flags for how the regexp
|
||||
is interpreted:
|
||||
|
||||
- **E**
|
||||
Extended regexps
|
||||
- **I**
|
||||
Ignore case in regexps
|
||||
- **M**
|
||||
Multiline regexps
|
||||
- **G**
|
||||
Global replacement; all occurances of the regexp in
|
||||
the string will be replaced. Without this, only the
|
||||
first occurance will be replaced.
|
||||
|
||||
:lang:
|
||||
Optional. How to handle multibyte characters. A
|
||||
single-character string with the following values:
|
||||
|
||||
- **N**
|
||||
None
|
||||
- **E**
|
||||
EUC
|
||||
- **S**
|
||||
SJIS
|
||||
- **U**
|
||||
UTF-8
|
||||
|
||||
**Examples**
|
||||
|
||||
Get the third octet from the node's IP address: ::
|
||||
|
||||
$i3 = regsubst($ipaddress,
|
||||
'^([0-9]+)[.]([0-9]+)[.]([0-9]+)[.]([0-9]+)$',
|
||||
'\\\\3')
|
||||
|
||||
Put angle brackets around each octet in the node's IP address: ::
|
||||
|
||||
$x = regsubst($ipaddress, '([0-9]+)', '<\\\\1>', 'G')
|
||||
") \
|
||||
do |args|
|
||||
flag_mapping = {
|
||||
"E" => Regexp::EXTENDED,
|
||||
"I" => Regexp::IGNORECASE,
|
||||
"M" => Regexp::MULTILINE,
|
||||
}
|
||||
if args.length < 3 or args.length > 5
|
||||
raise Puppet::ParseError, ("regsub(): wrong number of arguments" +
|
||||
" (#{args.length}; min 3, max 5)")
|
||||
end
|
||||
str, regexp, replacement, flags, lang = args
|
||||
reflags = 0
|
||||
global = false
|
||||
(flags or "").each_byte do |f|
|
||||
f = f.chr
|
||||
if f == "G"
|
||||
global = true
|
||||
else
|
||||
fvalue = flag_mapping[f]
|
||||
if !fvalue
|
||||
raise Puppet::ParseError, "regsub(): bad flag `#{f}'"
|
||||
end
|
||||
reflags |= fvalue
|
||||
end
|
||||
end
|
||||
re = Regexp.compile(regexp, reflags, lang)
|
||||
if global
|
||||
result = str.gsub(re, replacement)
|
||||
else
|
||||
result = str.sub(re, replacement)
|
||||
end
|
||||
return result
|
||||
end
|
||||
end
|
|
@ -0,0 +1,17 @@
|
|||
module Puppet::Parser::Functions
|
||||
newfunction(:sprintf, :type => :rvalue,
|
||||
:doc => "\
|
||||
Perform printf-style formatting of text.
|
||||
|
||||
The first parameter is format string describing how the rest of the
|
||||
parameters should be formatted. See the documentation for the
|
||||
``Kernel::sprintf()`` function in Ruby for all the details.
|
||||
") \
|
||||
do |args|
|
||||
if args.length < 1
|
||||
raise Puppet::ParseError, 'sprintf() needs at least one argument'
|
||||
end
|
||||
fmt = args.shift()
|
||||
return sprintf(fmt, *args)
|
||||
end
|
||||
end
|
|
@ -69,7 +69,6 @@ Puppet::Type.type(:augeas).provide(:augeas) do
|
|||
commands.concat(parse_commands(datum))
|
||||
end
|
||||
end
|
||||
|
||||
return commands
|
||||
end
|
||||
|
||||
|
@ -181,15 +180,36 @@ Puppet::Type.type(:augeas).provide(:augeas) do
|
|||
fail("invalid command #{cmd_array.join[" "]}") if cmd_array.length < 2
|
||||
command = cmd_array[0]
|
||||
cmd_array.shift()
|
||||
loc = cmd_array[0]
|
||||
cmd_array[0]=File.join(context, loc)
|
||||
debug("sending command '#{command}' with params #{cmd_array.inspect}")
|
||||
begin
|
||||
case command
|
||||
when "set": aug.set(cmd_array[0], cmd_array[1])
|
||||
when "rm", "remove": aug.rm(cmd_array[0])
|
||||
when "clear": aug.clear(cmd_array[0])
|
||||
when "insert", "ins": aug.insert(cmd_array[0])
|
||||
when "set":
|
||||
cmd_array[0]=File.join(context, cmd_array[0])
|
||||
debug("sending command '#{command}' with params #{cmd_array.inspect}")
|
||||
aug.set(cmd_array[0], cmd_array[1])
|
||||
when "rm", "remove":
|
||||
cmd_array[0]=File.join(context, cmd_array[0])
|
||||
debug("sending command '#{command}' with params #{cmd_array.inspect}")
|
||||
aug.rm(cmd_array[0])
|
||||
when "clear":
|
||||
cmd_array[0]=File.join(context, cmd_array[0])
|
||||
debug("sending command '#{command}' with params #{cmd_array.inspect}")
|
||||
aug.clear(cmd_array[0])
|
||||
when "insert", "ins"
|
||||
|
||||
ext_array = cmd_array[1].split(" ") ;
|
||||
if cmd_array.size < 2 or ext_array.size < 2
|
||||
fail("ins requires 3 parameters")
|
||||
end
|
||||
label = cmd_array[0]
|
||||
where = ext_array[0]
|
||||
path = File.join(context, ext_array[1])
|
||||
case where
|
||||
when "before": before = true
|
||||
when "after": before = false
|
||||
else fail("Invalid value '#{where}' for where param")
|
||||
end
|
||||
debug("sending command '#{command}' with params #{[label, where, path].inspect()}")
|
||||
aug.insert(path, label, before)
|
||||
else fail("Command '#{command}' is not supported")
|
||||
end
|
||||
rescue Exception => e
|
||||
|
|
|
@ -7,6 +7,7 @@ require 'puppet/external/nagios'
|
|||
|
||||
# The base class for all Naginator providers.
|
||||
class Puppet::Provider::Naginator < Puppet::Provider::ParsedFile
|
||||
NAME_STRING = "## --PUPPET_NAME-- (called '_naginator_name' in the manifest)"
|
||||
# Retrieve the associated class from Nagios::Base.
|
||||
def self.nagios_type
|
||||
unless defined?(@nagios_type) and @nagios_type
|
||||
|
@ -24,14 +25,14 @@ class Puppet::Provider::Naginator < Puppet::Provider::ParsedFile
|
|||
|
||||
def self.parse(text)
|
||||
begin
|
||||
Nagios::Parser.new.parse(text)
|
||||
Nagios::Parser.new.parse(text.gsub(NAME_STRING, "_naginator_name"))
|
||||
rescue => detail
|
||||
raise Puppet::Error, "Could not parse configuration for %s: %s" % [resource_type.name, detail]
|
||||
end
|
||||
end
|
||||
|
||||
def self.to_file(records)
|
||||
header + records.collect { |record| record.to_s }.join("\n")
|
||||
header + records.collect { |record| record.to_s }.join("\n").gsub("_naginator_name", NAME_STRING)
|
||||
end
|
||||
|
||||
def self.skip_record?(record)
|
||||
|
|
|
@ -3,9 +3,11 @@ Puppet::Type.type(:package).provide :up2date, :parent => :rpm, :source => :rpm d
|
|||
mechanism."
|
||||
|
||||
commands :up2date => "/usr/sbin/up2date-nox"
|
||||
defaultfor :operatingsystem => :redhat,
|
||||
|
||||
defaultfor :operatingsystem => [:redhat, :oel, :ovm]
|
||||
:lsbdistrelease => ["2.1", "3", "4"]
|
||||
confine :operatingsystem => :redhat
|
||||
|
||||
confine :operatingsystem => [:redhat, :oel, :ovm]
|
||||
|
||||
# Install a package using 'up2date'.
|
||||
def install
|
||||
|
|
|
@ -78,8 +78,22 @@ class Puppet::Provider::ParsedFile < Puppet::Provider
|
|||
@modified.reject! { |t| flushed.include?(t) }
|
||||
end
|
||||
|
||||
# Make sure our file is backed up, but only back it up once per transaction.
|
||||
# We cheat and rely on the fact that @records is created on each prefetch.
|
||||
def self.backup_target(target)
|
||||
unless defined?(@backup_stats)
|
||||
@backup_stats = {}
|
||||
end
|
||||
return nil if @backup_stats[target] == @records.object_id
|
||||
|
||||
target_object(target).backup
|
||||
@backup_stats[target] = @records.object_id
|
||||
end
|
||||
|
||||
# Flush all of the records relating to a specific target.
|
||||
def self.flush_target(target)
|
||||
backup_target(target)
|
||||
|
||||
records = target_records(target).reject { |r|
|
||||
r[:ensure] == :absent
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@ Puppet::Type.type(:service).provide :redhat, :parent => :init do
|
|||
|
||||
commands :chkconfig => "/sbin/chkconfig", :service => "/sbin/service"
|
||||
|
||||
defaultfor :operatingsystem => [:redhat, :fedora, :suse, :centos, :sles]
|
||||
defaultfor :operatingsystem => [:redhat, :fedora, :suse, :centos, :sles, :oel, :ovm]
|
||||
|
||||
def self.defpath
|
||||
superclass.defpath
|
||||
|
|
|
@ -1,9 +1,13 @@
|
|||
class AddEnvironmentToHost < ActiveRecord::Migration
|
||||
def self.up
|
||||
add_column :hosts, :environment, :string
|
||||
unless ActiveRecord::Base.connection.columns(:hosts).collect {|c| c.name}.include?("environment")
|
||||
add_column :hosts, :environment, :string
|
||||
end
|
||||
end
|
||||
|
||||
def self.down
|
||||
remove_column :hosts, :environment
|
||||
if ActiveRecord::Base.connection.columns(:hosts).collect {|c| c.name}.include?("environment")
|
||||
remove_column :hosts, :environment
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -92,10 +92,12 @@ Puppet::Type.newtype(:augeas) do
|
|||
rm [PATH] Removes the node at location PATH
|
||||
remove [PATH] Synonym for rm
|
||||
clear [PATH] Keeps the node at PATH, but removes the value.
|
||||
ins [PATH] Inserts an empty node at PATH.
|
||||
insert [PATH] Synonym for ins
|
||||
ins [LABEL] [WHERE] [PATH]
|
||||
Inserts an empty node LABEL either [WHERE={before|after}] PATH.
|
||||
insert [LABEL] [WHERE] [PATH]
|
||||
Synonym for ins
|
||||
|
||||
If the parameter 'context' is set that that value is prepended to PATH"
|
||||
If the parameter 'context' is set that value is prepended to PATH"
|
||||
|
||||
munge do |value|
|
||||
provider.parse_commands(value)
|
||||
|
|
|
@ -78,7 +78,7 @@ class Puppet::Util::Autoload
|
|||
name = symbolize(name)
|
||||
loaded name, file
|
||||
return true
|
||||
rescue LoadError => detail
|
||||
rescue Exception => detail
|
||||
# I have no idea what's going on here, but different versions
|
||||
# of ruby are raising different errors on missing files.
|
||||
unless detail.to_s =~ /^no such file/i
|
||||
|
@ -115,7 +115,7 @@ class Puppet::Util::Autoload
|
|||
begin
|
||||
Kernel.require file
|
||||
loaded(name, file)
|
||||
rescue => detail
|
||||
rescue Exception => detail
|
||||
if Puppet[:trace]
|
||||
puts detail.backtrace
|
||||
end
|
||||
|
|
|
@ -74,7 +74,7 @@ class Puppet::Util::FileType
|
|||
|
||||
# Back the file up before replacing it.
|
||||
def backup
|
||||
bucket.backup(@path) if FileTest.exists?(@path)
|
||||
bucket.backup(@path) if File.exists?(@path)
|
||||
end
|
||||
|
||||
# Pick or create a filebucket to use.
|
||||
|
@ -94,7 +94,7 @@ class Puppet::Util::FileType
|
|||
newfiletype(:flat) do
|
||||
# Read the file.
|
||||
def read
|
||||
if File.exists?(@path)
|
||||
if File.exist?(@path)
|
||||
File.read(@path)
|
||||
else
|
||||
return nil
|
||||
|
@ -103,17 +103,13 @@ class Puppet::Util::FileType
|
|||
|
||||
# Remove the file.
|
||||
def remove
|
||||
if File.exists?(@path)
|
||||
if File.exist?(@path)
|
||||
File.unlink(@path)
|
||||
end
|
||||
end
|
||||
|
||||
# Overwrite the file.
|
||||
def write(text)
|
||||
backup()
|
||||
|
||||
raise("Cannot create file %s in absent directory" % @path) unless FileTest.exist?(File.dirname(@path))
|
||||
|
||||
require "tempfile"
|
||||
tf = Tempfile.new("puppet")
|
||||
tf.print text; tf.flush
|
||||
|
@ -255,92 +251,4 @@ class Puppet::Util::FileType
|
|||
output_file.delete
|
||||
end
|
||||
end
|
||||
|
||||
# Treat netinfo tables as a single file, just for simplicity of certain
|
||||
# types
|
||||
newfiletype(:netinfo) do
|
||||
class << self
|
||||
attr_accessor :format
|
||||
end
|
||||
def read
|
||||
%x{nidump -r /#{@path} /}
|
||||
end
|
||||
|
||||
# This really only makes sense for cron tabs.
|
||||
def remove
|
||||
%x{nireport / /#{@path} name}.split("\n").each do |name|
|
||||
newname = name.gsub(/\//, '\/').sub(/\s+$/, '')
|
||||
output = %x{niutil -destroy / '/#{@path}/#{newname}'}
|
||||
|
||||
unless $? == 0
|
||||
raise Puppet::Error, "Could not remove %s from %s" %
|
||||
[name, @path]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Convert our table to an array of hashes. This only works for
|
||||
# handling one table at a time.
|
||||
def to_array(text = nil)
|
||||
unless text
|
||||
text = read
|
||||
end
|
||||
|
||||
hash = nil
|
||||
|
||||
# Initialize it with the first record
|
||||
records = []
|
||||
text.split("\n").each do |line|
|
||||
next if line =~ /^[{}]$/ # Skip the wrapping lines
|
||||
next if line =~ /"name" = \( "#{@path}" \)/ # Skip the table name
|
||||
next if line =~ /CHILDREN = \(/ # Skip this header
|
||||
next if line =~ /^ \)/ # and its closer
|
||||
|
||||
# Now we should have nothing but records, wrapped in braces
|
||||
|
||||
case line
|
||||
when /^\s+\{/: hash = {}
|
||||
when /^\s+\}/: records << hash
|
||||
when /\s+"(\w+)" = \( (.+) \)/
|
||||
field = $1
|
||||
values = $2
|
||||
|
||||
# Always use an array
|
||||
hash[field] = []
|
||||
|
||||
values.split(/, /).each do |value|
|
||||
if value =~ /^"(.*)"$/
|
||||
hash[field] << $1
|
||||
else
|
||||
raise ArgumentError, "Could not match value %s" % value
|
||||
end
|
||||
end
|
||||
else
|
||||
raise ArgumentError, "Could not match line %s" % line
|
||||
end
|
||||
end
|
||||
|
||||
records
|
||||
end
|
||||
|
||||
def write(text)
|
||||
text.gsub!(/^#.*\n/,'')
|
||||
text.gsub!(/^$/,'')
|
||||
if text == "" or text == "\n"
|
||||
self.remove
|
||||
return
|
||||
end
|
||||
unless format = self.class.format
|
||||
raise Puppe::DevError, "You must define the NetInfo format to inport"
|
||||
end
|
||||
IO.popen("niload -d #{format} . 1>/dev/null 2>/dev/null", "w") { |p|
|
||||
p.print text
|
||||
}
|
||||
|
||||
unless $? == 0
|
||||
raise ArgumentError, "Failed to write %s" % @path
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -93,15 +93,6 @@ describe Puppet::Node::Facts::Facter do
|
|||
end
|
||||
end
|
||||
|
||||
it "should load each directory in the Fact path when loading fact plugins" do
|
||||
Puppet.settings.expects(:value).with(:factpath).returns("one%stwo" % File::PATH_SEPARATOR)
|
||||
|
||||
Puppet::Node::Facts::Facter.expects(:load_facts_in_dir).with("one")
|
||||
Puppet::Node::Facts::Facter.expects(:load_facts_in_dir).with("two")
|
||||
|
||||
Puppet::Node::Facts::Facter.load_fact_plugins
|
||||
end
|
||||
|
||||
it "should skip files when asked to load a directory" do
|
||||
FileTest.expects(:directory?).with("myfile").returns false
|
||||
|
||||
|
@ -119,4 +110,33 @@ describe Puppet::Node::Facts::Facter do
|
|||
|
||||
Puppet::Node::Facts::Facter.load_facts_in_dir("mydir")
|
||||
end
|
||||
|
||||
describe Puppet::Node::Facts::Facter, "when loading fact plugins from disk" do
|
||||
it "should load each directory in the Fact path" do
|
||||
Puppet.settings.stubs(:value).returns "foo"
|
||||
Puppet.settings.expects(:value).with(:factpath).returns("one%stwo" % File::PATH_SEPARATOR)
|
||||
|
||||
Puppet::Node::Facts::Facter.expects(:load_facts_in_dir).with("one")
|
||||
Puppet::Node::Facts::Facter.expects(:load_facts_in_dir).with("two")
|
||||
|
||||
Puppet::Node::Facts::Facter.load_fact_plugins
|
||||
end
|
||||
|
||||
it "should load all facts from the modules" do
|
||||
Puppet.settings.stubs(:value).returns "foo"
|
||||
Puppet::Node::Facts::Facter.stubs(:load_facts_in_dir)
|
||||
|
||||
Puppet.settings.expects(:value).with(:modulepath).returns("one%stwo" % File::PATH_SEPARATOR)
|
||||
|
||||
Dir.expects(:glob).with("one/*/plugins/facter").returns %w{oneA oneB}
|
||||
Dir.expects(:glob).with("two/*/plugins/facter").returns %w{twoA twoB}
|
||||
|
||||
Puppet::Node::Facts::Facter.expects(:load_facts_in_dir).with("oneA")
|
||||
Puppet::Node::Facts::Facter.expects(:load_facts_in_dir).with("oneB")
|
||||
Puppet::Node::Facts::Facter.expects(:load_facts_in_dir).with("twoA")
|
||||
Puppet::Node::Facts::Facter.expects(:load_facts_in_dir).with("twoB")
|
||||
|
||||
Puppet::Node::Facts::Facter.load_fact_plugins
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -2,12 +2,170 @@
|
|||
|
||||
Dir.chdir(File.dirname(__FILE__)) { (s = lambda { |f| File.exist?(f) ? require(f) : Dir.chdir("..") { s.call(f) } }).call("spec/spec_helper.rb") }
|
||||
|
||||
describe Puppet::Network do
|
||||
it "should raise an XMLRPCClientError if a generated class raises a Timeout::Error" do
|
||||
http = mock 'http'
|
||||
Puppet::Network::HttpPool.stubs(:http_instance).returns http
|
||||
file = Puppet::Network::Client.file.new({:Server => "foo.com"})
|
||||
http.stubs(:post2).raises Timeout::Error
|
||||
lambda { file.retrieve }.should raise_error(Puppet::Network::XMLRPCClientError)
|
||||
describe Puppet::Network::XMLRPCClient do
|
||||
describe "when performing the rpc call" do
|
||||
before do
|
||||
@client = Puppet::Network::Client.report.xmlrpc_client.new
|
||||
@client.stubs(:call).returns "foo"
|
||||
|
||||
end
|
||||
|
||||
it "should call the specified namespace and method, with the specified arguments" do
|
||||
@client.expects(:call).with("puppetreports.report", "eh").returns "foo"
|
||||
@client.report("eh")
|
||||
end
|
||||
|
||||
it "should return the results from the call" do
|
||||
@client.expects(:call).returns "foo"
|
||||
@client.report("eh").should == "foo"
|
||||
end
|
||||
|
||||
it "should always close the http connection if it is still open after the call" do
|
||||
http = mock 'http'
|
||||
@client.stubs(:http).returns http
|
||||
|
||||
http.expects(:started?).returns true
|
||||
http.expects(:finish)
|
||||
|
||||
@client.report("eh").should == "foo"
|
||||
end
|
||||
|
||||
it "should always close the http connection if it is still open after a call that raises an exception" do
|
||||
http = mock 'http'
|
||||
@client.stubs(:http).returns http
|
||||
|
||||
@client.expects(:call).raises RuntimeError
|
||||
|
||||
http.expects(:started?).returns true
|
||||
http.expects(:finish)
|
||||
|
||||
lambda { @client.report("eh") }.should raise_error
|
||||
end
|
||||
|
||||
describe "when returning the http instance" do
|
||||
it "should use the http pool to create the instance" do
|
||||
@client.instance_variable_set("@http", nil)
|
||||
@client.expects(:host).returns "myhost"
|
||||
@client.expects(:port).returns "myport"
|
||||
Puppet::Network::HttpPool.expects(:http_instance).with("myhost", "myport", true).returns "http"
|
||||
|
||||
@client.http.should == "http"
|
||||
end
|
||||
|
||||
it "should reuse existing instances" do
|
||||
@client.http.should equal(@client.http)
|
||||
end
|
||||
end
|
||||
|
||||
describe "when recycling the connection" do
|
||||
it "should close the existing instance if it's open" do
|
||||
http = mock 'http'
|
||||
@client.stubs(:http).returns http
|
||||
|
||||
http.expects(:started?).returns true
|
||||
http.expects(:finish)
|
||||
|
||||
@client.recycle_connection
|
||||
end
|
||||
|
||||
it "should force creation of a new instance" do
|
||||
Puppet::Network::HttpPool.expects(:http_instance).returns "second_http"
|
||||
|
||||
@client.recycle_connection
|
||||
|
||||
@client.http.should == "second_http"
|
||||
end
|
||||
end
|
||||
|
||||
describe "and an exception is raised" do
|
||||
it "should raise XMLRPCClientError if XMLRPC::FaultException is raised" do
|
||||
error = XMLRPC::FaultException.new("foo", "bar")
|
||||
|
||||
@client.expects(:call).raises(error)
|
||||
|
||||
lambda { @client.report("eh") }.should raise_error(Puppet::Network::XMLRPCClientError)
|
||||
end
|
||||
|
||||
it "should raise XMLRPCClientError if Errno::ECONNREFUSED is raised" do
|
||||
@client.expects(:call).raises(Errno::ECONNREFUSED)
|
||||
|
||||
lambda { @client.report("eh") }.should raise_error(Puppet::Network::XMLRPCClientError)
|
||||
end
|
||||
|
||||
it "should log and raise XMLRPCClientError if Timeout::Error is raised" do
|
||||
Puppet.expects(:err)
|
||||
@client.expects(:call).raises(Timeout::Error)
|
||||
|
||||
lambda { @client.report("eh") }.should raise_error(Puppet::Network::XMLRPCClientError)
|
||||
end
|
||||
|
||||
it "should log and raise XMLRPCClientError if SocketError is raised" do
|
||||
Puppet.expects(:err)
|
||||
@client.expects(:call).raises(SocketError)
|
||||
|
||||
lambda { @client.report("eh") }.should raise_error(Puppet::Network::XMLRPCClientError)
|
||||
end
|
||||
|
||||
it "should log, recycle the connection, and retry if Errno::EPIPE is raised" do
|
||||
@client.expects(:call).times(2).raises(Errno::EPIPE).then.returns "eh"
|
||||
|
||||
Puppet.expects(:warning)
|
||||
@client.expects(:recycle_connection)
|
||||
|
||||
@client.report("eh")
|
||||
end
|
||||
|
||||
it "should log, recycle the connection, and retry if EOFError is raised" do
|
||||
@client.expects(:call).times(2).raises(EOFError).then.returns "eh"
|
||||
|
||||
Puppet.expects(:warning)
|
||||
@client.expects(:recycle_connection)
|
||||
|
||||
@client.report("eh")
|
||||
end
|
||||
|
||||
it "should log and retry if an exception containing 'Wrong size' is raised" do
|
||||
error = RuntimeError.new("Wrong size. Was 15, should be 30")
|
||||
@client.expects(:call).times(2).raises(error).then.returns "eh"
|
||||
|
||||
Puppet.expects(:warning)
|
||||
|
||||
@client.report("eh")
|
||||
end
|
||||
|
||||
it "should raise XMLRPCClientError if OpenSSL::SSL::SSLError is raised" do
|
||||
@client.expects(:call).raises(OpenSSL::SSL::SSLError)
|
||||
|
||||
lambda { @client.report("eh") }.should raise_error(Puppet::Network::XMLRPCClientError)
|
||||
end
|
||||
|
||||
it "should log and raise XMLRPCClientError if OpenSSL::SSL::SSLError is raised with certificate issues" do
|
||||
error = OpenSSL::SSL::SSLError.new("hostname was not match")
|
||||
@client.expects(:call).raises(error)
|
||||
|
||||
Puppet.expects(:warning)
|
||||
|
||||
lambda { @client.report("eh") }.should raise_error(Puppet::Network::XMLRPCClientError)
|
||||
end
|
||||
|
||||
it "should log, recycle the connection, and retry if OpenSSL::SSL::SSLError is raised containing 'bad write retry'" do
|
||||
error = OpenSSL::SSL::SSLError.new("bad write retry")
|
||||
@client.expects(:call).times(2).raises(error).then.returns "eh"
|
||||
|
||||
@client.expects(:recycle_connection)
|
||||
|
||||
Puppet.expects(:warning)
|
||||
|
||||
@client.report("eh")
|
||||
end
|
||||
|
||||
it "should log and raise XMLRPCClientError if any other exception is raised" do
|
||||
@client.expects(:call).raises(RuntimeError)
|
||||
|
||||
Puppet.expects(:err)
|
||||
|
||||
lambda { @client.report("eh") }.should raise_error(Puppet::Network::XMLRPCClientError)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -0,0 +1,88 @@
|
|||
#! /usr/bin/env ruby
|
||||
|
||||
require File.dirname(__FILE__) + '/../../../spec_helper'
|
||||
|
||||
describe "the regsubst function" do
|
||||
|
||||
before :each do
|
||||
@scope = Puppet::Parser::Scope.new()
|
||||
end
|
||||
|
||||
it "should exist" do
|
||||
Puppet::Parser::Functions.function("regsubst").should == "function_regsubst"
|
||||
end
|
||||
|
||||
it "should raise a ParseError if there is less than 3 arguments" do
|
||||
lambda { @scope.function_regsubst(["foo", "bar"]) }.should(
|
||||
raise_error(Puppet::ParseError))
|
||||
end
|
||||
|
||||
it "should raise a ParseError if there is more than 5 arguments" do
|
||||
lambda { @scope.function_regsubst(["foo", "bar", "gazonk", "del", "x", "y"]) }.should(
|
||||
raise_error(Puppet::ParseError))
|
||||
end
|
||||
|
||||
|
||||
it "should raise a ParseError when given a bad flag" do
|
||||
lambda { @scope.function_regsubst(["foo", "bar", "gazonk", "X"]) }.should(
|
||||
raise_error(Puppet::ParseError))
|
||||
end
|
||||
|
||||
it "should handle groups" do
|
||||
result = @scope.function_regsubst(
|
||||
[ '130.236.254.10',
|
||||
'^([0-9]+)[.]([0-9]+)[.]([0-9]+)[.]([0-9]+)$',
|
||||
'\4-\3-\2-\1'
|
||||
])
|
||||
result.should(eql("10-254-236-130"))
|
||||
end
|
||||
|
||||
it "should handle simple regexps" do
|
||||
result = @scope.function_regsubst(
|
||||
[ "the monkey breaks banana trees",
|
||||
"b[an]*a",
|
||||
"coconut"
|
||||
])
|
||||
result.should(eql("the monkey breaks coconut trees"))
|
||||
end
|
||||
|
||||
it "should handle case-sensitive regexps" do
|
||||
result = @scope.function_regsubst(
|
||||
[ "the monkey breaks baNAna trees",
|
||||
"b[an]+a",
|
||||
"coconut"
|
||||
])
|
||||
result.should(eql("the monkey breaks baNAna trees"))
|
||||
end
|
||||
|
||||
it "should handle case-insensitive regexps" do
|
||||
result = @scope.function_regsubst(
|
||||
[ "the monkey breaks baNAna trees",
|
||||
"b[an]+a",
|
||||
"coconut",
|
||||
"I"
|
||||
])
|
||||
result.should(eql("the monkey breaks coconut trees"))
|
||||
end
|
||||
|
||||
it "should handle global substitutions" do
|
||||
result = @scope.function_regsubst(
|
||||
[ "the monkey breaks\tbanana trees",
|
||||
"[ \t]",
|
||||
"--",
|
||||
"G"
|
||||
])
|
||||
result.should(eql("the--monkey--breaks--banana--trees"))
|
||||
end
|
||||
|
||||
it "should handle global substitutions with groups" do
|
||||
result = @scope.function_regsubst(
|
||||
[ '130.236.254.10',
|
||||
'([0-9]+)',
|
||||
'<\1>',
|
||||
'G'
|
||||
])
|
||||
result.should(eql('<130>.<236>.<254>.<10>'))
|
||||
end
|
||||
|
||||
end
|
|
@ -0,0 +1,42 @@
|
|||
#! /usr/bin/env ruby
|
||||
|
||||
require File.dirname(__FILE__) + '/../../../spec_helper'
|
||||
|
||||
describe "the sprintf function" do
|
||||
|
||||
before :each do
|
||||
@scope = Puppet::Parser::Scope.new()
|
||||
end
|
||||
|
||||
it "should exist" do
|
||||
Puppet::Parser::Functions.function("sprintf").should == "function_sprintf"
|
||||
end
|
||||
|
||||
it "should raise a ParseError if there is less than 1 argument" do
|
||||
lambda { @scope.function_sprintf([]) }.should(
|
||||
raise_error(Puppet::ParseError))
|
||||
end
|
||||
|
||||
it "should format integers" do
|
||||
result = @scope.function_sprintf(["%+05d", "23"])
|
||||
result.should(eql("+0023"))
|
||||
end
|
||||
|
||||
it "should format floats" do
|
||||
result = @scope.function_sprintf(["%+.2f", "2.7182818284590451"])
|
||||
result.should(eql("+2.72"))
|
||||
end
|
||||
|
||||
it "should format large floats" do
|
||||
result = @scope.function_sprintf(["%+.2e", "27182818284590451"])
|
||||
result.should(eql("+2.72e+16"))
|
||||
end
|
||||
|
||||
it "should perform more complex formatting" do
|
||||
result = @scope.function_sprintf(
|
||||
[ "<%.8s:%#5o %#8X (%-8s)>",
|
||||
"overlongstring", "23", "48879", "foo" ])
|
||||
result.should(eql("<overlong: 027 0XBEEF (foo )>"))
|
||||
end
|
||||
|
||||
end
|
|
@ -285,32 +285,42 @@ describe provider_class do
|
|||
@augeas.expects(:clear).with("/foo/Jar/Jar")
|
||||
@augeas.expects(:save).returns(true)
|
||||
@provider.execute_changes.should == :executed
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
it "should handle insert commands" do
|
||||
command = [["insert", "/Jar/Jar"]]
|
||||
it "should handle ins commands with before" do
|
||||
command = [["ins", "Binks", "before /Jar/Jar"]]
|
||||
context = "/foo"
|
||||
@resource.expects(:[]).times(2).returns(command).then.returns(context)
|
||||
@augeas.expects(:insert).with("/foo/Jar/Jar")
|
||||
@augeas.expects(:insert).with("/foo/Jar/Jar", "Binks", true)
|
||||
@augeas.expects(:save).returns(true)
|
||||
@provider.execute_changes.should == :executed
|
||||
end
|
||||
|
||||
it "should handle ins commands" do
|
||||
command = [["ins", "/Jar/Jar"]]
|
||||
it "should handle ins commands with before" do
|
||||
command = [["ins", "Binks", "after /Jar/Jar"]]
|
||||
context = "/foo"
|
||||
@resource.expects(:[]).times(2).returns(command).then.returns(context)
|
||||
@augeas.expects(:insert).with("/foo/Jar/Jar")
|
||||
@augeas.expects(:insert).with("/foo/Jar/Jar", "Binks", false)
|
||||
@augeas.expects(:save).returns(true)
|
||||
@provider.execute_changes.should == :executed
|
||||
end
|
||||
|
||||
it "should handle ins with no context" do
|
||||
command = [["ins", "Binks", "after /Jar/Jar"]]
|
||||
context = "" # this is the default
|
||||
@resource.expects(:[]).times(2).returns(command).then.returns(context)
|
||||
@augeas.expects(:insert).with("/Jar/Jar", "Binks", false)
|
||||
@augeas.expects(:save).returns(true)
|
||||
@provider.execute_changes.should == :executed
|
||||
end
|
||||
|
||||
it "should handle multiple commands" do
|
||||
command = [["ins", "/Jar/Jar"], ["clear", "/Jar/Jar"]]
|
||||
command = [["ins", "Binks", "after /Jar/Jar"], ["clear", "/Jar/Jar"]]
|
||||
context = "/foo"
|
||||
@resource.expects(:[]).times(2).returns(command).then.returns(context)
|
||||
@augeas.expects(:insert).with("/foo/Jar/Jar")
|
||||
@augeas.expects(:clear).with("/foo/Jar/Jar")
|
||||
@augeas.expects(:insert).with("/foo/Jar/Jar", "Binks", false)
|
||||
@augeas.expects(:clear).with("/foo/Jar/Jar")
|
||||
@augeas.expects(:save).returns(true)
|
||||
@provider.execute_changes.should == :executed
|
||||
end
|
||||
|
|
|
@ -47,4 +47,40 @@ describe Puppet::Provider::ParsedFile do
|
|||
@class.instances
|
||||
end
|
||||
end
|
||||
|
||||
describe "when flushing a file's records to disk" do
|
||||
before do
|
||||
# This way we start with some @records, like we would in real life.
|
||||
@class.stubs(:retrieve).returns []
|
||||
@class.default_target = "/foo/bar"
|
||||
@class.initvars
|
||||
@class.prefetch
|
||||
|
||||
@filetype = mock 'filetype'
|
||||
Puppet::Util::FileType.filetype(:flat).expects(:new).with("/my/file").returns @filetype
|
||||
|
||||
@filetype.stubs(:write)
|
||||
end
|
||||
|
||||
it "should back up the file being written" do
|
||||
@filetype.expects(:backup)
|
||||
|
||||
@class.flush_target("/my/file")
|
||||
end
|
||||
|
||||
it "should not back up the file more than once between calls to 'prefetch'" do
|
||||
@filetype.expects(:backup).once
|
||||
|
||||
@class.flush_target("/my/file")
|
||||
@class.flush_target("/my/file")
|
||||
end
|
||||
|
||||
it "should back the file up again once the file has been reread" do
|
||||
@filetype.expects(:backup).times(2)
|
||||
|
||||
@class.flush_target("/my/file")
|
||||
@class.prefetch
|
||||
@class.flush_target("/my/file")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
#!/usr/bin/env ruby
|
||||
|
||||
Dir.chdir(File.dirname(__FILE__)) { (s = lambda { |f| File.exist?(f) ? require(f) : Dir.chdir("..") { s.call(f) } }).call("spec/spec_helper.rb") }
|
||||
|
||||
require 'puppet/util/autoload'
|
||||
|
||||
describe Puppet::Util::Autoload do
|
||||
before do
|
||||
@autoload = Puppet::Util::Autoload.new("foo", "tmp")
|
||||
|
||||
@autoload.stubs(:eachdir).yields "/my/dir"
|
||||
end
|
||||
|
||||
describe "when loading a file" do
|
||||
[RuntimeError, LoadError, SyntaxError].each do |error|
|
||||
it "should not die an if a #{error.to_s} exception is thrown" do
|
||||
FileTest.stubs(:exists?).returns true
|
||||
|
||||
Kernel.expects(:load).raises error
|
||||
|
||||
lambda { @autoload.load("foo") }.should_not raise_error
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "when loading all files" do
|
||||
before do
|
||||
Dir.stubs(:glob).returns "file.rb"
|
||||
end
|
||||
|
||||
[RuntimeError, LoadError, SyntaxError].each do |error|
|
||||
it "should not die an if a #{error.to_s} exception is thrown" do
|
||||
Kernel.expects(:require).raises error
|
||||
|
||||
lambda { @autoload.loadall }.should_not raise_error
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,110 @@
|
|||
#!/usr/bin/env ruby
|
||||
|
||||
Dir.chdir(File.dirname(__FILE__)) { (s = lambda { |f| File.exist?(f) ? require(f) : Dir.chdir("..") { s.call(f) } }).call("spec/spec_helper.rb") }
|
||||
|
||||
require 'puppet/util/filetype'
|
||||
|
||||
# XXX Import all of the tests into this file.
|
||||
describe Puppet::Util::FileType do
|
||||
describe "when backing up a file" do
|
||||
before do
|
||||
@file = Puppet::Util::FileType.filetype(:flat).new("/my/file")
|
||||
end
|
||||
|
||||
it "should do nothing if the file does not exist" do
|
||||
File.expects(:exists?).with("/my/file").returns false
|
||||
@file.expects(:bucket).never
|
||||
@file.backup
|
||||
end
|
||||
|
||||
it "should use its filebucket to backup the file if it exists" do
|
||||
File.expects(:exists?).with("/my/file").returns true
|
||||
|
||||
bucket = mock 'bucket'
|
||||
bucket.expects(:backup).with("/my/file")
|
||||
|
||||
@file.expects(:bucket).returns bucket
|
||||
@file.backup
|
||||
end
|
||||
|
||||
it "should use the filebucket named 'puppet' if it finds one" do
|
||||
bucket = mock 'bucket'
|
||||
bucket.expects(:bucket).returns "mybucket"
|
||||
|
||||
Puppet::Type.type(:filebucket).expects(:[]).with("puppet").returns bucket
|
||||
|
||||
@file.bucket.should == "mybucket"
|
||||
end
|
||||
|
||||
it "should use the default filebucket if none named 'puppet' is found" do
|
||||
bucket = mock 'bucket'
|
||||
bucket.expects(:bucket).returns "mybucket"
|
||||
|
||||
Puppet::Type.type(:filebucket).expects(:[]).with("puppet").returns nil
|
||||
Puppet::Type.type(:filebucket).expects(:mkdefaultbucket).returns bucket
|
||||
|
||||
@file.bucket.should == "mybucket"
|
||||
end
|
||||
end
|
||||
|
||||
describe "the flat filetype" do
|
||||
before do
|
||||
@type = Puppet::Util::FileType.filetype(:flat)
|
||||
end
|
||||
it "should exist" do
|
||||
@type.should_not be_nil
|
||||
end
|
||||
|
||||
describe "when the file already exists" do
|
||||
it "should return the file's contents when asked to read it" do
|
||||
file = @type.new("/my/file")
|
||||
File.expects(:exist?).with("/my/file").returns true
|
||||
File.expects(:read).with("/my/file").returns "my text"
|
||||
|
||||
file.read.should == "my text"
|
||||
end
|
||||
|
||||
it "should unlink the file when asked to remove it" do
|
||||
file = @type.new("/my/file")
|
||||
File.expects(:exist?).with("/my/file").returns true
|
||||
File.expects(:unlink).with("/my/file")
|
||||
|
||||
file.remove
|
||||
end
|
||||
end
|
||||
|
||||
describe "when the file does not exist" do
|
||||
it "should return an empty string when asked to read the file" do
|
||||
file = @type.new("/my/file")
|
||||
File.expects(:exist?).with("/my/file").returns false
|
||||
|
||||
file.read.should == ""
|
||||
end
|
||||
end
|
||||
|
||||
describe "when writing the file" do
|
||||
before do
|
||||
@file = @type.new("/my/file")
|
||||
FileUtils.stubs(:cp)
|
||||
|
||||
@tempfile = stub 'tempfile', :print => nil, :close => nil, :flush => nil, :path => "/other/file"
|
||||
Tempfile.stubs(:new).returns @tempfile
|
||||
end
|
||||
|
||||
it "should first create a temp file and copy its contents over to the file location" do
|
||||
Tempfile.expects(:new).with("puppet").returns @tempfile
|
||||
@tempfile.expects(:print).with("my text")
|
||||
@tempfile.expects(:flush)
|
||||
@tempfile.expects(:close)
|
||||
FileUtils.expects(:cp).with(@tempfile.path, "/my/file")
|
||||
|
||||
@file.write "my text"
|
||||
end
|
||||
|
||||
it "should set the selinux default context on the file" do
|
||||
@file.expects(:set_selinux_default_context).with("/my/file")
|
||||
@file.write "eh"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,137 +0,0 @@
|
|||
#!/usr/bin/env ruby
|
||||
|
||||
require File.dirname(__FILE__) + '/../lib/puppettest'
|
||||
|
||||
require 'puppettest'
|
||||
require 'puppet/util/filetype'
|
||||
require 'mocha'
|
||||
|
||||
class TestFileType < Test::Unit::TestCase
|
||||
include PuppetTest
|
||||
|
||||
def test_flat
|
||||
obj = nil
|
||||
path = tempfile()
|
||||
type = nil
|
||||
|
||||
assert_nothing_raised {
|
||||
type = Puppet::Util::FileType.filetype(:flat)
|
||||
}
|
||||
|
||||
assert(type, "Could not retrieve flat filetype")
|
||||
|
||||
assert_nothing_raised {
|
||||
obj = type.new(path)
|
||||
}
|
||||
|
||||
text = "This is some text\n"
|
||||
|
||||
newtext = nil
|
||||
assert_nothing_raised {
|
||||
newtext = obj.read
|
||||
}
|
||||
|
||||
# The base class doesn't allow a return of nil
|
||||
assert_equal("", newtext, "Somehow got some text")
|
||||
|
||||
assert_nothing_raised {
|
||||
obj.write(text)
|
||||
}
|
||||
assert_nothing_raised {
|
||||
newtext = obj.read
|
||||
}
|
||||
|
||||
assert_equal(text, newtext, "Text was changed somehow")
|
||||
|
||||
File.open(path, "w") { |f| f.puts "someyayness" }
|
||||
|
||||
text = File.read(path)
|
||||
assert_nothing_raised {
|
||||
newtext = obj.read
|
||||
}
|
||||
|
||||
assert_equal(text, newtext, "Text was changed somehow")
|
||||
end
|
||||
|
||||
# Make sure that modified files are backed up before they're changed.
|
||||
def test_backup_is_called
|
||||
path = tempfile
|
||||
File.open(path, "w") { |f| f.print 'yay' }
|
||||
|
||||
obj = Puppet::Util::FileType.filetype(:flat).new(path)
|
||||
|
||||
obj.expects(:backup)
|
||||
|
||||
obj.write("something")
|
||||
|
||||
assert_equal("something", File.read(path), "File did not get changed")
|
||||
end
|
||||
|
||||
def test_backup
|
||||
path = tempfile
|
||||
type = Puppet::Type.type(:filebucket)
|
||||
|
||||
obj = Puppet::Util::FileType.filetype(:flat).new(path)
|
||||
|
||||
# First try it when the file does not yet exist.
|
||||
assert_nothing_raised("Could not call backup when file does not exist") do
|
||||
obj.backup
|
||||
end
|
||||
|
||||
# Then create the file
|
||||
File.open(path, "w") { |f| f.print 'one' }
|
||||
|
||||
# Then try it with no filebucket objects
|
||||
assert_nothing_raised("Could not call backup with no buckets") do
|
||||
obj.backup
|
||||
end
|
||||
puppet = type.mkdefaultbucket
|
||||
assert(puppet, "Did not create default filebucket")
|
||||
|
||||
assert_equal("one", puppet.bucket.getfile(Digest::MD5.hexdigest(File.read(path))), "Could not get file from backup")
|
||||
|
||||
# Try it again when the default already exists
|
||||
File.open(path, "w") { |f| f.print 'two' }
|
||||
assert_nothing_raised("Could not call backup with no buckets") do
|
||||
obj.backup
|
||||
end
|
||||
|
||||
assert_equal("two", puppet.bucket.getfile(Digest::MD5.hexdigest(File.read(path))), "Could not get file from backup")
|
||||
end
|
||||
|
||||
if Facter["operatingsystem"].value == "Darwin" and Facter["operatingsystemrelease"] != "9.1.0"
|
||||
def test_ninfotoarray
|
||||
obj = nil
|
||||
type = nil
|
||||
|
||||
assert_nothing_raised {
|
||||
type = Puppet::Util::FileType.filetype(:netinfo)
|
||||
}
|
||||
|
||||
assert(type, "Could not retrieve netinfo filetype")
|
||||
%w{users groups aliases}.each do |map|
|
||||
assert_nothing_raised {
|
||||
obj = type.new(map)
|
||||
}
|
||||
|
||||
assert_nothing_raised("could not read map %s" % map) {
|
||||
obj.read
|
||||
}
|
||||
|
||||
array = nil
|
||||
|
||||
assert_nothing_raised("Failed to parse %s map" % map) {
|
||||
array = obj.to_array
|
||||
}
|
||||
|
||||
assert_instance_of(Array, array)
|
||||
|
||||
array.each do |record|
|
||||
assert_instance_of(Hash, record)
|
||||
assert(record.length != 0)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
Загрузка…
Ссылка в новой задаче