This commit is contained in:
Luke Kanies 2008-04-11 13:01:42 -05:00
Родитель b49fb68f76 b49fd49562
Коммит fb05ef3c96
105 изменённых файлов: 2173 добавлений и 2055 удалений

Просмотреть файл

@ -1,3 +1,38 @@
Resources now return the 'should' value for properties from
the [] accessor method (they previously threw an exception when
this method was used with properties). This shouldn't have any
affect functionally; it just makes the method equivalent to 'should'
for properties, but it works for all attribute types now.
Modified the 'master' handler to use the Catalog class to
compile node configurations, rather than using the Configuration
handler, which was never used directly. I removed the Configuration
handler as a result.
Modified the 'master' handler (responsible for sending configurations
to clients) to always return Time.now as its compile date, so
configurations will always get recompiled.
Fixed #1184 -- definitions now autoload correctly all of the time.
Removed the code from the client that tries to avoid recompiling
the catalog. The client will now always recompile, assuming it
can reach the server. It will still use the cached config if
there's a failure.
Fixing #1173 -- classes and definitions can now have the same
name as a directory with no failures.
Saving new facts now expires any cached node information.
Switching how caching is handled, so that objects now all
have an expiration date associated with them. This makes it
much easier to know whether a given cached object should be used
or if it should be regenerated.
Changing the default environment to production.
0.24.4
Pass source to pkg_add via the PKG_PATH environment variable if
it ends in a '/' indicating it is a directory. Allows pkg_add
to resolve dependancies, and make it possible to specify packages

2
bin/pi
Просмотреть файл

@ -1,4 +1,4 @@
#!/usr/bin/ruby
#!/usr/bin/env ruby
#
# = Synopsis

Просмотреть файл

@ -206,7 +206,7 @@ end
begin
# Compile our catalog
catalog = Puppet::Node::Catalog.find(node)
catalog = Puppet::Node::Catalog.find(node.name, :node => node)
# Translate it to a RAL catalog
catalog = catalog.to_ral

Просмотреть файл

@ -1,4 +1,4 @@
#!/usr/bin/ruby
#!/usr/bin/env ruby
# vim: softtabstop=4 shiftwidth=4 expandtab
#
# = Synopsis

Просмотреть файл

@ -15,7 +15,7 @@ export PATH
[ -f /etc/sysconfig/puppet ] && . /etc/sysconfig/puppet
lockfile=${LOCKFILE-/var/lock/subsys/puppet}
pidfile=${PIDFILE-/var/run/puppet/puppet.pid}
pidfile=${PIDFILE-/var/run/puppet/puppetd.pid}
puppetd=${PUPPETD-/usr/sbin/puppetd}
RETVAL=0

Просмотреть файл

@ -1,4 +1,4 @@
#!/usr/bin/ruby -w
#!/usr/bin/env ruby -w
###
# sleep indefinitely as a debug

Просмотреть файл

@ -5,57 +5,49 @@
;;; Description: A simple mode for editing puppet manifests
;;;
(defconst puppet-mode-version "0.0.1")
(defconst puppet-mode-version "0.1")
(defvar puppet-mode-abbrev-table nil
"Abbrev table in use in puppet-mode buffers.")
(define-abbrev-table 'puppet-mode-abbrev-table ())
(defvar puppet-mode-map nil "Keymap used in puppet mode.")
(defcustom puppet-indent-level 2
"*Indentation of Puppet statements."
:type 'integer :group 'puppet)
(if puppet-mode-map
nil
(setq puppet-mode-map (make-sparse-keymap))
;; (define-key puppet-mode-map "{" 'puppet-electric-brace)
;; (define-key puppet-mode-map "}" 'puppet-electric-brace)
;; (define-key puppet-mode-map "\e\C-a" 'puppet-beginning-of-defun)
;; (define-key puppet-mode-map "\e\C-e" 'puppet-end-of-defun)
;; (define-key puppet-mode-map "\e\C-b" 'puppet-backward-sexp)
;; (define-key puppet-mode-map "\e\C-f" 'puppet-forward-sexp)
;; (define-key puppet-mode-map "\e\C-p" 'puppet-beginning-of-block)
;; (define-key puppet-mode-map "\e\C-n" 'puppet-end-of-block)
;; (define-key puppet-mode-map "\e\C-h" 'puppet-mark-defun)
;; (define-key puppet-mode-map "\e\C-q" 'puppet-indent-exp)
;; (define-key puppet-mode-map "\t" 'puppet-indent-command)
;; (define-key puppet-mode-map "\C-c\C-e" 'puppet-insert-end)
;; (define-key puppet-mode-map "\C-j" 'puppet-reindent-then-newline-and-indent)
(define-key puppet-mode-map "\C-m" 'newline))
(defcustom puppet-include-indent 2
"*Indentation of continued Puppet include statements."
:type 'integer :group 'puppet)
(defvar puppet-mode-syntax-table nil
(defvar puppet-mode-map
(let ((map (make-sparse-keymap)))
(define-key map "\C-j" 'newline-and-indent)
(define-key map "\C-m" 'newline-and-indent)
map)
"Key map used in puppet-mode buffers.")
(defvar puppet-mode-syntax-table
(let ((table (make-syntax-table)))
(modify-syntax-entry ?\' "\"" table)
(modify-syntax-entry ?\" "\"" table)
(modify-syntax-entry ?# "<" table)
(modify-syntax-entry ?\n ">" table)
(modify-syntax-entry ?\\ "\\" table)
(modify-syntax-entry ?$ "." table)
(modify-syntax-entry ?- "_" table)
(modify-syntax-entry ?> "." table)
(modify-syntax-entry ?= "." table)
(modify-syntax-entry ?\; "." table)
(modify-syntax-entry ?\( "()" table)
(modify-syntax-entry ?\) ")(" table)
(modify-syntax-entry ?\{ "(}" table)
(modify-syntax-entry ?\} "){" table)
(modify-syntax-entry ?\[ "(]" table)
(modify-syntax-entry ?\] ")[" table)
table)
"Syntax table in use in puppet-mode buffers.")
(if puppet-mode-syntax-table
()
(setq puppet-mode-syntax-table (make-syntax-table))
(modify-syntax-entry ?\' "\"" puppet-mode-syntax-table)
(modify-syntax-entry ?\" "\"" puppet-mode-syntax-table)
(modify-syntax-entry ?# "<" puppet-mode-syntax-table)
(modify-syntax-entry ?\n ">" puppet-mode-syntax-table)
(modify-syntax-entry ?\\ "\\" puppet-mode-syntax-table)
(modify-syntax-entry ?$ "." puppet-mode-syntax-table)
(modify-syntax-entry ?- "_" puppet-mode-syntax-table)
(modify-syntax-entry ?> "." puppet-mode-syntax-table)
(modify-syntax-entry ?= "." puppet-mode-syntax-table)
(modify-syntax-entry ?\; "." puppet-mode-syntax-table)
(modify-syntax-entry ?\( "()" puppet-mode-syntax-table)
(modify-syntax-entry ?\) ")(" puppet-mode-syntax-table)
(modify-syntax-entry ?\{ "(}" puppet-mode-syntax-table)
(modify-syntax-entry ?\} "){" puppet-mode-syntax-table)
(modify-syntax-entry ?\[ "(]" puppet-mode-syntax-table)
(modify-syntax-entry ?\] ")[" puppet-mode-syntax-table)
)
(defcustom puppet-indent-tabs-mode nil
"*Indentation can insert tabs in puppet mode if this is non-nil."
:type 'boolean :group 'puppet)
@ -64,31 +56,6 @@
"*Indentation column of comments."
:type 'integer :group 'puppet)
(defun puppet-mode-variables ()
(set-syntax-table puppet-mode-syntax-table)
(setq local-abbrev-table puppet-mode-abbrev-table)
;(make-local-variable 'indent-line-function)
;(setq indent-line-function 'ruby-indent-line)
(make-local-variable 'require-final-newline)
(setq require-final-newline t)
(make-variable-buffer-local 'comment-start)
(setq comment-start "# ")
(make-variable-buffer-local 'comment-end)
(setq comment-end "")
(make-variable-buffer-local 'comment-column)
(setq comment-column puppet-comment-column)
(make-variable-buffer-local 'comment-start-skip)
(setq comment-start-skip "#+ *")
(setq indent-tabs-mode puppet-indent-tabs-mode)
(make-local-variable 'parse-sexp-ignore-comments)
(setq parse-sexp-ignore-comments t)
(make-local-variable 'paragraph-start)
(setq paragraph-start (concat "$\\|" page-delimiter))
(make-local-variable 'paragraph-separate)
(setq paragraph-separate paragraph-start)
(make-local-variable 'paragraph-ignore-fill-prefix)
(setq paragraph-ignore-fill-prefix t))
(defun puppet-comment-line-p ()
"Return non-nil iff this line is a comment."
(save-excursion
@ -113,6 +80,27 @@ that array, else return nil."
(if (= (count-matches "\\]" apoint opoint) 0)
apoint))))))
(defun puppet-in-include ()
"If point is in a continued list of include statements, return the position
of the initial include plus puppet-include-indent."
(save-excursion
(save-match-data
(let ((include-column nil)
(not-found t))
(while not-found
(forward-line -1)
(cond
((puppet-comment-line-p)
(if (bobp)
(setq not-found nil)))
((looking-at "^\\s-*include\\s-+.*,\\s-*$")
(setq include-column
(+ (current-indentation) puppet-include-indent))
(setq not-found nil))
((not (looking-at ".*,\\s-*$"))
(setq not-found nil))))
include-column))))
(defun puppet-indent-line ()
"Indent current line as puppet code."
(interactive)
@ -121,6 +109,7 @@ that array, else return nil."
(indent-line-to 0) ; First line is always non-indented
(let ((not-indented t)
(array-start (puppet-in-array))
(include-start (puppet-in-include))
cur-indent)
(cond
(array-start
@ -155,6 +144,8 @@ that array, else return nil."
(re-search-forward "\\S-")
(forward-char -1)
(setq cur-indent (current-column))))
(include-start
(setq cur-indent include-start))
((looking-at "^[^{\n]*}")
;; This line contains the end of a block, but the block does
;; not also begin on this line, so decrease the indentation.
@ -162,9 +153,9 @@ that array, else return nil."
(forward-line -1)
(if (looking-at "^.*}")
(progn
(setq cur-indent (- (current-indentation) 2))
(setq cur-indent (- (current-indentation) puppet-indent-level))
(setq not-indented nil))
(setq cur-indent (- (current-indentation) 2))))
(setq cur-indent (- (current-indentation) puppet-indent-level))))
(if (< cur-indent 0) ; We can't indent past the left margin
(setq cur-indent 0)))
(t
@ -183,7 +174,13 @@ that array, else return nil."
(setq cur-indent (current-indentation))
(setq not-indented nil))
((looking-at "^.*{") ; indent an extra level
(setq cur-indent (+ (current-indentation) 2))
(setq cur-indent (+ (current-indentation) puppet-indent-level))
(setq not-indented nil))
((looking-at "^.*;\\s-*$") ; Semicolon ends a nested resource
(setq cur-indent (- (current-indentation) puppet-indent-level))
(setq not-indented nil))
((looking-at "^.*:\\s-*$") ; indent an extra level after :
(setq cur-indent (+ (current-indentation) puppet-indent-level))
(setq not-indented nil))
((bobp)
(setq not-indented nil))
@ -204,13 +201,20 @@ The variable puppet-indent-level controls the amount of indentation.
(use-local-map puppet-mode-map)
(setq mode-name "Puppet")
(setq major-mode 'puppet-mode)
(puppet-mode-variables)
;; Register our indentation function
(set (make-local-variable 'indent-line-function) 'puppet-indent-line)
(set-syntax-table puppet-mode-syntax-table)
(set (make-local-variable 'local-abbrev-table) puppet-mode-abbrev-table)
(set (make-local-variable 'comment-start) "# ")
(set (make-local-variable 'comment-start-skip) "#+ *")
(set (make-local-variable 'comment-end) "")
(set (make-local-variable 'comment-column) puppet-comment-column)
(set (make-local-variable 'indent-line-function) 'puppet-indent-line)
(set (make-local-variable 'indent-tabs-mode) puppet-indent-tabs-mode)
(set (make-local-variable 'require-final-newline) t)
(set (make-local-variable 'paragraph-ignore-fill-prefix) t)
(set (make-local-variable 'paragraph-start) "\f\\|[ ]*$")
(set (make-local-variable 'paragraph-separate) "[ \f]*$")
(run-hooks 'puppet-mode-hook))
(cond
((featurep 'font-lock)
(or (boundp 'font-lock-variable-name-face)
@ -253,8 +257,13 @@ The variable puppet-indent-level controls the amount of indentation.
;; defines
'("^\\s *\\(define\\|node\\|class\\)\\s +\\([^( \t\n]+\\)"
2 font-lock-function-name-face)
'("\\s +inherits\\s +\\([^( \t\n]+\\)"
1 font-lock-function-name-face)
;; include
'("^\\s *include\\s +\\([^( \t\n]+\\)"
'("^\\s *include\\s +\\([^( \t\n,]+\\)"
1 font-lock-reference-face)
;; hack to catch continued includes
'("^\\s *\\([a-zA-Z0-9:_-]+\\),?\\s *$"
1 font-lock-reference-face)
;; keywords
(cons (concat
@ -270,6 +279,7 @@ The variable puppet-indent-level controls the amount of indentation.
"include"
"inherits"
"node"
"realize"
"true"
)
"\\|")
@ -284,7 +294,10 @@ The variable puppet-indent-level controls the amount of indentation.
'("\\(\\$\\|@\\|@@\\)\\(\\w\\|_\\)+"
0 font-lock-variable-name-face)
;; usage of types
'("^\\s +\\([a-zA-Z-]+\\)\\s +{"
'("^\\s +\\([a-zA-Z_-]+\\)\\s +{"
1 font-lock-type-face)
;; overrides
'("^\\s +\\([a-zA-Z_-]+\\)\\["
1 font-lock-type-face)
;; general delimited string
'("\\(^\\|[[ \t\n<+(,=]\\)\\(%[xrqQwW]?\\([^<[{(a-zA-Z0-9 \n]\\)[^\n\\\\]*\\(\\\\.[^\n\\\\]*\\)*\\(\\3\\)\\)"

Просмотреть файл

@ -12,7 +12,7 @@ attributetype ( 1.1.3.9 NAME 'parentnode'
EQUALITY caseIgnoreIA5Match
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
attributetype ( 1.1.3.9 NAME 'environment'
attributetype ( 1.1.3.11 NAME 'environment'
DESC 'Puppet Node Environment'
EQUALITY caseIgnoreIA5Match
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )

Просмотреть файл

@ -179,7 +179,7 @@ node.classes = classes
begin
# Compile our configuration
catalog = Puppet::Node::Catalog.find(node)
catalog = Puppet::Node::Catalog.find(node.name, :node => node)
rescue => detail
if Puppet[:trace]
puts detail.backtrace

117
ext/nagios/check_puppet.rb Executable file
Просмотреть файл

@ -0,0 +1,117 @@
#!/usr/bin/env ruby
require 'optparse'
require 'sys/proctable'
include Sys
class CheckPuppet
VERSION = '0.1'
script_name = File.basename($0)
# default options
OPTIONS = {
:statefile => "/var/puppet/state/state.yaml",
:process => "puppetd",
:interval => 30,
}
o = OptionParser.new do |o|
o.set_summary_indent(' ')
o.banner = "Usage: #{script_name} [OPTIONS]"
o.define_head "The check_puppet Nagios plug-in checks that specified " +
"Puppet process is running and the state file is no " +
"older than specified interval."
o.separator ""
o.separator "Mandatory arguments to long options are mandatory for " +
"short options too."
o.on("-s", "--statefile=statefile", String, "The state file",
"Default: #{OPTIONS[:statefile]}") { |OPTIONS[:statefile]| }
o.on("-p", "--process=processname", String, "The process to check",
"Default: #{OPTIONS[:process]}") { |OPTIONS[:process]| }
o.on("-i", "--interval=value", Integer,
"Default: #{OPTIONS[:interval]} minutes") { |OPTIONS[:interval]| }
o.separator ""
o.on_tail("-h", "--help", "Show this help message.") do
puts o
exit
end
o.parse!(ARGV)
end
def check_proc
unless ProcTable.ps.find { |p| p.name == OPTIONS[:process]}
@proc = 2
else
@proc = 0
end
end
def check_state
# Set variables
curt = Time.now
intv = OPTIONS[:interval] * 60
# Check file time
begin
@modt = File.mtime("#{OPTIONS[:statefile]}")
rescue
@file = 3
end
diff = (curt - @modt).to_i
if diff > intv
@file = 2
else
@file = 0
end
end
def output_status
case @file
when 0
state = "state file status okay updated on " + @modt.strftime("%m/%d/%Y at %H:%M:%S")
when 2
state = "state fille is not up to date and is older than #{OPTIONS[:interval]} minutes"
when 3
state = "state file status unknown"
end
case @proc
when 0
process = "process #{OPTIONS[:process]} is running"
when 2
process = "process #{OPTIONS[:process]} is not running"
end
case @proc or @file
when 0
status = "OK"
exitcode = 0
when 2
status = "CRITICAL"
exitcode = 2
when 3
status = "UNKNOWN"
exitcide = 3
end
puts "PUPPET " + status + ": " + process + ", " + state
exit(exitcode)
end
end
cp = CheckPuppet.new
cp.check_proc
cp.check_state
cp.output_status

Просмотреть файл

@ -128,7 +128,7 @@ module Puppet
This is more useful as a server-side setting than client, but any
environment chosen must be in this list. Values should be
separated by a comma."],
:environment => {:default => "development", :desc => "The environment Puppet is running in. For clients
:environment => {:default => "production", :desc => "The environment Puppet is running in. For clients
(e.g., ``puppetd``) this determines the environment itself, which
is used to find modules and much more. For servers (i.e.,
``puppetmasterd``) this provides the default environment for nodes

Просмотреть файл

@ -1,7 +1,7 @@
# Just quick mess-around to see what a DSL would look like.
#
# This is what the executable could look like:
##!/usr/bin/ruby
##!/usr/bin/env ruby
#
#require 'puppet'
#require 'puppet/dsl'
@ -23,7 +23,7 @@
# And here's what an example config could look like:
#
##!/usr/bin/ruby
##!/usr/bin/env ruby
#
#
# require 'puppet'

2
lib/puppet/external/nagios.rb поставляемый
Просмотреть файл

@ -1,4 +1,4 @@
#!/usr/local/bin/ruby -w
#!/usr/bin/env ruby -w
#--------------------
# A script to retrieve hosts from ldap and create an importable

116
lib/puppet/external/nagios/base.rb поставляемый
Просмотреть файл

@ -228,7 +228,9 @@ class Nagios::Base
# This is probably a bad idea.
def name=(value)
send(self.class.namevar.to_s + "=", value)
unless self.class.namevar.to_s == "name"
send(self.class.namevar.to_s + "=", value)
end
end
def namevar
@ -318,59 +320,64 @@ class Nagios::Base
self.class.name
end
# object types
newtype :command do
setparameters :command_name, :command_line
end
# object types
newtype :command do
setparameters :command_name, :command_line
end
newtype :contact do
newtype :contact do
setparameters :contact_name, :alias, :host_notification_period,
:host_notification_commands, :service_notification_period,
:service_notification_commands,
:email, :pager, :service_notification_options, :host_notification_options
:host_notification_commands, :service_notification_period,
:service_notification_commands, :register, :email, :pager,
:service_notification_options, :host_notification_options
setsuperior "person"
end
end
newtype :contactgroup do
setparameters :contactgroup_name, :alias, :members
end
newtype :contactgroup do
setparameters :contactgroup_name, :alias, :members
end
newtype :host do
newtype :host do
setparameters :host_name, :notifications_enabled, :event_handler_enabled,
:flap_detection_enabled, :process_perf_data, :retain_status_information,
:retain_nonstatus_information, :register, :use, :alias,
:address, :check_command, :max_check_attempts, :notification_interval,
:notification_period, :notification_options, :checks_enabled,
:failure_prediction_enabled, :parents
:flap_detection_enabled, :process_perf_data, :retain_status_information,
:retain_nonstatus_information, :register, :use, :alias,
:address, :check_command, :max_check_attempts, :notification_interval,
:notification_period, :notification_options, :checks_enabled,
:failure_prediction_enabled, :parents, :contact_groups
setsuperior "person"
map :address => "ipHostNumber"
end
newtype :hostextinfo do
auxiliary = true
end
newtype :hostextinfo do
auxiliary = true
setparameters :host_name, :notes_url, :icon_image, :icon_image_alt, :vrml_image,
"2d_coords".intern, "3d_coords".intern
"2d_coords".intern, "3d_coords".intern
setnamevar :host_name
end
end
newtype :hostgroup do
newtype :hostgroup do
setparameters :hostgroup_name, :alias, :contact_groups, :members
end
end
newtype :hostgroupescalation do
auxiliary = true
newtype :hostescalation do
setparameters :name, :first_notification, :last_notification,
:notification_interval, :contact_groups,
:escalation_options, :register, :hostgroup_name
setnamevar :name
end
newtype :hostgroupescalation do
auxiliary = true
setparameters :hostgroup_name, :first_notification, :last_notification,
:contact_groups, :notification_interval
:contact_groups, :notification_interval
setnamevar :hostgroup_name
end
end
newtype :service do
newtype :service do
attach :host => :host_name
setparameters :name, :active_checks_enabled, :passive_checks_enabled,
:parallelize_check, :obsess_over_service, :check_freshness,
@ -381,41 +388,48 @@ class Nagios::Base
:normal_check_interval, :retry_check_interval, :contact_groups,
:notification_interval, :notification_period, :notification_options,
:service_description, :host_name, :freshness_threshold,
:check_command
:check_command, :hostgroup_name, :event_handler, :servicegroups, :host
suppress :host_name
setnamevar :service_description
end
end
newtype :servicedependency do
newtype :servicedependency do
auxiliary = true
setparameters :host_name, :service_description, :dependent_host_name,
:dependent_service_description, :execution_failure_criteria,
:notification_failure_criteria
setnamevar :host_name
end
newtype :serviceescalation do
setparameters :host_name, :service_description, :first_notification,
:last_notification, :contact_groups, :notification_interval
:dependent_service_description, :execution_failure_criteria,
:notification_failure_criteria, :hostgroup_name,
:dependent_hostgroup_name
setnamevar :host_name
end
newtype :serviceextinfo do
newtype :serviceescalation do
setparameters :host_name, :service_description, :first_notification,
:last_notification, :contact_groups, :notification_interval, :hostgroup_name
setnamevar :host_name
end
newtype :servicegroup do
setparameters :servicegroup_name, :alias
setnamevar :servicegroup_name
end
newtype :serviceextinfo do
auxiliary = true
setparameters :host_name, :service_description, :icon_image, :icon_image_alt
setnamevar :host_name
end
end
newtype :timeperiod do
setparameters :timeperiod_name, :alias, :sunday, :monday, :tuesday, :wednesday,
:thursday, :friday, :saturday
end
newtype :timeperiod do
setparameters :timeperiod_name, :alias, :sunday, :monday, :tuesday,
:wednesday, :thursday, :friday, :saturday
end
end
# $Id$

Просмотреть файл

@ -12,7 +12,8 @@ module Puppet::FileServing::IndirectionHooks
PROTOCOL_MAP = {"puppet" => :rest, "file" => :file, "puppetmounts" => :file_server}
# Pick an appropriate terminus based on the protocol.
def select_terminus(full_uri, options = {})
def select_terminus(request)
full_uri = request.key
# Short-circuit to :file if it's a fully-qualified path.
return PROTOCOL_MAP["file"] if full_uri =~ /^#{::File::SEPARATOR}/
begin
@ -29,11 +30,12 @@ module Puppet::FileServing::IndirectionHooks
terminus = :file_server
end
# This is the backward-compatible module terminus.
if terminus == :file_server and uri.path =~ %r{^/([^/]+)\b}
modname = $1
if modname == "modules"
terminus = :modules
elsif terminus(:modules).find_module(modname, options[:node])
elsif terminus(:modules).find_module(modname, request.options[:node])
Puppet.warning "DEPRECATION NOTICE: Found file '%s' in module without using the 'modules' mount; please prefix path with '/modules'" % uri.path
terminus = :modules
end

Просмотреть файл

@ -11,15 +11,6 @@ require 'puppet/file_serving/indirection_hooks'
# A class that handles retrieving file metadata.
class Puppet::FileServing::Metadata < Puppet::FileServing::FileBase
module MetadataHelper
include Puppet::FileServing::IndirectionHooks
def post_find(instance)
end
def post_search(key, options = {})
end
end
include Puppet::Util::Checksums

Просмотреть файл

@ -9,6 +9,7 @@ module Puppet::Indirector
require 'puppet/indirector/indirection'
require 'puppet/indirector/terminus'
require 'puppet/indirector/envelope'
# Declare that the including class indirects its methods to
# this terminus. The terminus name must be the name of a Puppet
@ -20,6 +21,7 @@ module Puppet::Indirector
# populate this class with the various new methods
extend ClassMethods
include InstanceMethods
include Puppet::Indirector::Envelope
# instantiate the actual Terminus for that type and this name (:ldap, w/ args :node)
# & hook the instantiated Terminus into this class (Node: @indirection = terminus)
@ -28,41 +30,37 @@ module Puppet::Indirector
end
module ClassMethods
attr_reader :indirection
attr_reader :indirection
def cache_class=(klass)
indirection.cache_class = klass
end
def cache_class=(klass)
indirection.cache_class = klass
end
def terminus_class=(klass)
indirection.terminus_class = klass
end
def terminus_class=(klass)
indirection.terminus_class = klass
end
def find(*args)
indirection.find(*args)
end
# Expire any cached instance.
def expire(*args)
indirection.expire *args
end
def find(*args)
indirection.find *args
end
def destroy(*args)
indirection.destroy(*args)
end
def destroy(*args)
indirection.destroy *args
end
def search(*args)
indirection.search(*args)
end
def version(*args)
indirection.version(*args)
end
def search(*args)
indirection.search *args
end
end
module InstanceMethods
# Make it easy for the model to set versions,
# which are used for caching and such.
attr_accessor :version
# these become instance methods
def save(*args)
self.class.indirection.save(self, *args)
end
def save(*args)
self.class.indirection.save self, *args
end
end
end

Просмотреть файл

@ -13,15 +13,13 @@ class Puppet::Node::Catalog::Compiler < Puppet::Indirector::Code
attr_accessor :code
# Compile a node's catalog.
def find(key, client = nil, clientip = nil)
if key.is_a?(Puppet::Node)
node = key
else
node = find_node(key)
def find(request)
unless node = request.options[:node] || find_node(request.key)
raise ArgumentError, "Could not find node '%s'; cannot compile" % request.key
end
if catalog = compile(node)
return catalog.to_transportable
return catalog
else
# This shouldn't actually happen; we should either return
# a config or raise an exception.
@ -46,22 +44,6 @@ class Puppet::Node::Catalog::Compiler < Puppet::Indirector::Code
$0 =~ /puppetmasterd/
end
# Return the catalog version. Here we're returning the
# latest of the node, fact, or parse date. These are the
# three things that go into compiling a client catalog,
# so changes in any of them result in changes.
# LAK:FIXME Note that this only works when all three sources
# use timestamps; once one of them moves to using real versions,
# the comparison stops working.
def version(key)
if node = Puppet::Node.find_by_any_name(key)
return [Puppet::Node.version(key).to_f, Puppet::Node::Facts.version(key).to_f, interpreter.catalog_version(node).to_f].sort[-1]
else
# This is the standard for "got nothing for ya".
0
end
end
private
# Add any extra data necessary to the node.
@ -102,16 +84,12 @@ class Puppet::Node::Catalog::Compiler < Puppet::Indirector::Code
def find_node(key)
# If we want to use the cert name as our key
# LAK:FIXME This needs to be figured out somehow, but it requires the routing.
# This should be able to use the request, yay.
#if Puppet[:node_name] == 'cert' and client
# key = client
#end
# Note that this is reasonable, because either their node source should actually
# know about the node, or they should be using the ``null`` node source, which
# will always return data.
unless node = Puppet::Node.find_by_any_name(key)
raise Puppet::Error, "Could not find node '%s'" % key
end
return nil unless node = Puppet::Node.find_by_any_name(key)
# Add any external data to the node.
add_node_data(node)

Просмотреть файл

@ -18,8 +18,8 @@ class Puppet::Checksum::File < Puppet::Indirector::File
path.join(File::SEPARATOR)
end
def save(file)
path = File.dirname(path(file.name))
def save(request)
path = File.dirname(path(request.key))
# Make the directories if necessary.
unless FileTest.directory?(path)

Просмотреть файл

@ -11,17 +11,17 @@ class Puppet::Indirector::DirectFileServer < Puppet::Indirector::Terminus
include Puppet::Util::URIHelper
include Puppet::FileServing::TerminusHelper
def find(key, options = {})
uri = key2uri(key)
def find(request)
uri = key2uri(request.key)
return nil unless FileTest.exists?(uri.path)
instance = model.new(key, :path => uri.path)
instance.links = options[:links] if options[:links]
instance = model.new(request.key, :path => uri.path)
instance.links = request.options[:links] if request.options[:links]
return instance
end
def search(key, options = {})
uri = key2uri(key)
def search(request)
uri = key2uri(request.key)
return nil unless FileTest.exists?(uri.path)
path2instances(key, uri.path, options)
path2instances(request.key, uri.path, request.options)
end
end

Просмотреть файл

@ -0,0 +1,13 @@
require 'puppet/indirector'
# Provide any attributes or functionality needed for indirected
# instances.
module Puppet::Indirector::Envelope
attr_accessor :expiration
def expired?
return false unless expiration
return false if expiration >= Time.now
return true
end
end

Просмотреть файл

@ -3,9 +3,9 @@ require 'puppet/util'
class Puppet::Indirector::Exec < Puppet::Indirector::Terminus
# Look for external node definitions.
def find(name)
def find(request)
# Run the command.
unless output = query(name)
unless output = query(request.key)
return nil
end

Просмотреть файл

@ -56,8 +56,8 @@ class Puppet::Node::Facts::Facter < Puppet::Indirector::Code
end
# Look a host's facts up in Facter.
def find(key)
Puppet::Node::Facts.new(key, Facter.to_hash)
def find(request)
Puppet::Node::Facts.new(request.key, Facter.to_hash)
end
def save(facts)

Просмотреть файл

@ -2,26 +2,28 @@ require 'puppet/indirector/terminus'
# An empty terminus type, meant to just return empty objects.
class Puppet::Indirector::File < Puppet::Indirector::Terminus
def destroy(file)
# Remove files on disk.
def destroy(request)
if respond_to?(:path)
path = path(file.name)
path = path(request.key)
else
path = file.path
path = request.key
end
raise Puppet::Error.new("File %s does not exist; cannot destroy" % [file]) unless File.exist?(path)
raise Puppet::Error.new("File %s does not exist; cannot destroy" % [request.key]) unless File.exist?(path)
begin
File.unlink(path)
rescue => detail
raise Puppet::Error, "Could not remove %s: %s" % [file, detail]
raise Puppet::Error, "Could not remove %s: %s" % [request.key, detail]
end
end
def find(name)
# Return a model instance for a given file on disk.
def find(request)
if respond_to?(:path)
path = path(name)
path = path(request.key)
else
path = name
path = request.key
end
return nil unless File.exist?(path)
@ -35,20 +37,21 @@ class Puppet::Indirector::File < Puppet::Indirector::Terminus
return model.new(content)
end
def save(file)
# Save a new file to disk.
def save(request)
if respond_to?(:path)
path = path(file.name)
path = path(request.key)
else
path = file.path
path = request.key
end
dir = File.dirname(path)
raise Puppet::Error.new("Cannot save %s; parent directory %s does not exist" % [file, dir]) unless File.directory?(dir)
raise Puppet::Error.new("Cannot save %s; parent directory %s does not exist" % [request.key, dir]) unless File.directory?(dir)
begin
File.open(path, "w") { |f| f.print file.content }
File.open(path, "w") { |f| f.print request.instance.content }
rescue => detail
raise Puppet::Error, "Could not write %s: %s" % [file, detail]
raise Puppet::Error, "Could not write %s: %s" % [request.key, detail]
end
end
end

Просмотреть файл

@ -9,14 +9,14 @@ require 'puppet/indirector/direct_file_server'
class Puppet::Indirector::FileMetadata::File < Puppet::Indirector::DirectFileServer
desc "Retrieve file metadata directly from the local filesystem."
def find(key, options = {})
def find(request)
return unless data = super
data.collect_attributes
return data
end
def search(key, options = {})
def search(request)
return unless result = super
result.each { |instance| instance.collect_attributes }

Просмотреть файл

@ -1,4 +1,6 @@
require 'puppet/util/docs'
require 'puppet/indirector/envelope'
require 'puppet/indirector/request'
# The class that connects functional classes with their different collection
# back-ends. Each indirection has a set of associated terminus classes,
@ -28,8 +30,7 @@ class Puppet::Indirector::Indirection
# Find an indirected model by name. This is provided so that Terminus classes
# can specifically hook up with the indirections they are associated with.
def self.model(name)
match = @@indirections.find { |i| i.name == name }
return nil unless match
return nil unless match = @@indirections.find { |i| i.name == name }
match.model
end
@ -65,6 +66,25 @@ class Puppet::Indirector::Indirection
@@indirections.delete(self) if @@indirections.include?(self)
end
# Set the time-to-live for instances created through this indirection.
def ttl=(value)
raise ArgumentError, "Indirection TTL must be an integer" unless value.is_a?(Fixnum)
@ttl = value
end
# Default to the runinterval for the ttl.
def ttl
unless defined?(@ttl)
@ttl = Puppet[:runinterval].to_i
end
@ttl
end
# Calculate the expiration date for a returned instance.
def expiration
Time.now + ttl
end
# Generate the full doc string.
def doc
text = ""
@ -106,6 +126,11 @@ class Puppet::Indirector::Indirection
end
end
# Set up our request object.
def request(method, key, arguments = nil)
Puppet::Indirector::Request.new(self.name, method, key, arguments)
end
# Return the singleton terminus for this indirection.
def terminus(terminus_name = nil)
# Get the name of the terminus.
@ -147,85 +172,126 @@ class Puppet::Indirector::Indirection
end
end
def find(key, *args)
# Select the appropriate terminus if there's a hook
# for doing so. This allows the caller to pass in some kind
# of URI that the indirection can use for routing to the appropriate
# terminus.
if respond_to?(:select_terminus)
terminus_name = select_terminus(key, *args)
else
terminus_name = terminus_class
end
# Expire a cached object, if one is cached. Note that we don't actually
# remove it, we expire it and write it back out to disk. This way people
# can still use the expired object if they want.
def expire(key, *args)
request = request(:expire, key, *args)
check_authorization(:find, terminus_name, ([key] + args))
return nil unless cache?
return nil unless instance = cache.find(request(:find, key, *args))
Puppet.info "Expiring the %s cache of %s" % [self.name, instance.name]
# Set an expiration date in the past
instance.expiration = Time.now - 60
cache.save(request(:save, instance, *args))
end
# Search for an instance in the appropriate terminus, caching the
# results if caching is configured..
def find(key, *args)
request = request(:find, key, *args)
terminus = prepare(request)
# See if our instance is in the cache and up to date.
if cache? and cache.has_most_recent?(key, terminus(terminus_name).version(key))
Puppet.debug "Using cached %s %s" % [self.name, key]
return cache.find(key, *args)
if cache? and cached = cache.find(request)
if cached.expired?
Puppet.info "Not using expired %s for %s from cache; expired at %s" % [self.name, request.key, cached.expiration]
else
Puppet.debug "Using cached %s for %s" % [self.name, request.key]
return cached
end
end
# Otherwise, return the result from the terminus, caching if appropriate.
if result = terminus(terminus_name).find(key, *args)
result.version ||= Time.now.utc
if result = terminus.find(request)
result.expiration ||= self.expiration
if cache?
Puppet.info "Caching %s %s" % [self.name, key]
cache.save(result, *args)
Puppet.info "Caching %s for %s" % [self.name, request.key]
cache.save request(:save, result, *args)
end
terminus(terminus_name).post_find(result) if terminus(terminus_name).respond_to?(:post_find)
return result
end
return nil
end
# Remove something via the terminus.
def destroy(key, *args)
request = request(:destroy, key, *args)
terminus = prepare(request)
terminus.destroy(request)
if cache? and cached = cache.find(request(:find, key, *args))
# Reuse the existing request, since it's equivalent.
cache.destroy(request)
end
nil
end
# Search for more than one instance. Should always return an array.
def search(key, *args)
request = request(:search, key, *args)
terminus = prepare(request)
if result = terminus.search(request)
raise Puppet::DevError, "Search results from terminus %s are not an array" % terminus.name unless result.is_a?(Array)
result.each do |instance|
instance.expiration ||= self.expiration
end
return result
end
end
def destroy(*args)
check_authorization(:destroy, terminus_class, args)
terminus.destroy(*args)
end
def search(*args)
check_authorization(:search, terminus_class, args)
result = terminus.search(*args)
terminus().post_search(result) if terminus().respond_to?(:post_search)
result
end
# these become instance methods
# Save the instance in the appropriate terminus. This method is
# normally an instance method on the indirected class.
def save(instance, *args)
check_authorization(:save, terminus_class, ([instance] + args))
request = request(:save, instance, *args)
terminus = prepare(request)
instance.version ||= Time.now.utc
dest = cache? ? cache : terminus
return if dest.has_most_recent?(instance.name, instance.version)
Puppet.info "Caching %s %s" % [self.name, instance.name] if cache?
cache.save(instance, *args) if cache?
terminus.save(instance, *args)
end
def version(*args)
terminus.version(*args)
# If caching is enabled, save our document there
cache.save(request) if cache?
terminus.save(request)
end
private
# Check authorization if there's a hook available; fail if there is one
# and it returns false.
def check_authorization(method, terminus_name, arguments)
# Don't check authorization if there's no node.
# LAK:FIXME This is a hack and is quite possibly not the design we want.
return unless arguments[-1].is_a?(Hash) and arguments[-1][:node]
def check_authorization(request, terminus)
# At this point, we're assuming authorization makes no sense without
# client information.
return unless request.options[:node]
if terminus(terminus_name).respond_to?(:authorized?) and ! terminus(terminus_name).authorized?(method, *arguments)
raise ArgumentError, "Not authorized to call %s with %s" % [method, arguments[0]]
# This is only to authorize via a terminus-specific authorization hook.
return unless terminus.respond_to?(:authorized?)
unless terminus.authorized?(request)
raise ArgumentError, "Not authorized to call %s on %s with %s" % [request.method, request.key, request.options.inspect]
end
end
# Setup a request, pick the appropriate terminus, check the request's authorization, and return it.
def prepare(request)
# Pick our terminus.
if respond_to?(:select_terminus)
terminus_name = select_terminus(request)
else
terminus_name = terminus_class
end
check_authorization(request, terminus(terminus_name))
return terminus(terminus_name)
end
# Create a new terminus instance.
def make_terminus(terminus_class)
# Load our terminus class.

Просмотреть файл

@ -2,10 +2,10 @@ require 'puppet/indirector/terminus'
class Puppet::Indirector::Ldap < Puppet::Indirector::Terminus
# Perform our ldap search and process the result.
def find(name)
def find(request)
# We have to use 'yield' here because the LDAP::Entry objects
# get destroyed outside the scope of the search, strangely.
ldapsearch(name) { |entry| return process(name, entry) }
ldapsearch(request.key) { |entry| return process(request.key, entry) }
# Return nil if we haven't found something.
return nil

Просмотреть файл

@ -6,16 +6,16 @@ class Puppet::Indirector::Memory < Puppet::Indirector::Terminus
@instances = {}
end
def destroy(instance)
raise ArgumentError.new("Could not find %s to destroy" % instance) unless @instances.include?(instance.name)
@instances.delete(instance.name)
def destroy(request)
raise ArgumentError.new("Could not find %s to destroy" % request.key) unless @instances.include?(request.key)
@instances.delete(request.key)
end
def find(name)
@instances[name]
def find(request)
@instances[request.key]
end
def save(instance)
@instances[instance.name] = instance
def save(request)
@instances[request.key] = request.instance
end
end

Просмотреть файл

@ -15,20 +15,13 @@ class Puppet::Node::Exec < Puppet::Indirector::Exec
end
# Look for external node definitions.
def find(name)
def find(request)
output = super or return nil
# Translate the output to ruby.
result = translate(name, output)
result = translate(request.key, output)
return create_node(name, result)
end
# Use the version of the facts, since we assume that's the main thing
# that changes. If someone wants their own way of defining version,
# they can easily provide their own, um, version of this class.
def version(name)
Puppet::Node::Facts.version(name)
return create_node(request.key, result)
end
private

Просмотреть файл

@ -12,8 +12,11 @@ class Puppet::Node::Ldap < Puppet::Indirector::Ldap
end
# Look for our node in ldap.
def find(name)
def find(request)
return nil unless information = super
name = request.key
node = Puppet::Node.new(name)
parent_info = nil
@ -123,8 +126,4 @@ class Puppet::Node::Ldap < Puppet::Indirector::Ldap
end
filter
end
def version(name)
Puppet::Node::Facts.version(name)
end
end

Просмотреть файл

@ -11,16 +11,9 @@ class Puppet::Node::Plain < Puppet::Indirector::Plain
node instance before it is returned."
# Just return an empty node.
def find(name)
def find(request)
node = super
node.fact_merge
node
end
# Use the version of the facts, since we assume that's the main thing
# that changes. If someone wants their own way of defining version,
# they can easily provide their own, um, version of this class.
def version(name)
Puppet::Node::Facts.version(name)
end
end

Просмотреть файл

@ -3,7 +3,7 @@ require 'puppet/indirector/terminus'
# An empty terminus type, meant to just return empty objects.
class Puppet::Indirector::Plain < Puppet::Indirector::Terminus
# Just return nothing.
def find(name)
indirection.model.new(name)
def find(request)
indirection.model.new(request.key)
end
end

Просмотреть файл

@ -10,8 +10,8 @@ class Puppet::Transaction::Report::Processor < Puppet::Indirector::Code
Puppet.settings.use(:main, :reporting, :metrics)
end
def save(report)
process(report)
def save(request)
process(request.instance)
end
private

Просмотреть файл

@ -0,0 +1,25 @@
require 'puppet/indirector'
# Provide any attributes or functionality needed for indirected
# instances.
class Puppet::Indirector::Request
attr_accessor :indirection_name, :key, :method, :options, :instance
def initialize(indirection_name, method, key, options = {})
@indirection_name, @method, @options = indirection_name, method, (options || {})
if key.is_a?(String) or key.is_a?(Symbol)
@key = key
else
@instance = key
@key = @instance.name
end
raise ArgumentError, "Request options must be a hash, not %s" % @options.class unless @options.is_a?(Hash)
end
# Look up the indirection based on the name provided.
def indirection
Puppet::Indirector::Indirection.instance(@indirection_name)
end
end

Просмотреть файл

@ -128,20 +128,6 @@ class Puppet::Indirector::Terminus
end
end
# Do we have an update for this object? This compares the provided version
# to our version, and returns true if our version is at least as high
# as the asked-about version.
def has_most_recent?(key, vers)
raise Puppet::DevError.new("Cannot check update status when no 'version' method is defined") unless respond_to?(:version)
if existing_version = version(key)
#puts "%s fresh: %s (%s vs %s)" % [self.name, (existing_version.to_f >= vers.to_f).inspect, existing_version.to_f, vers.to_f]
existing_version.to_f >= vers.to_f
else
false
end
end
def indirection
self.class.indirection
end
@ -163,17 +149,4 @@ class Puppet::Indirector::Terminus
def terminus_type
self.class.terminus_type
end
# Provide a default method for retrieving an instance's version.
# By default, just find the resource and get its version. Individual
# terminus types can override this method to provide custom definitions of
# 'versions'.
def version(name)
raise Puppet::DevError.new("Cannot retrieve an instance's version without a :find method") unless respond_to?(:find)
if instance = find(name)
instance.version
else
nil
end
end
end

Просмотреть файл

@ -3,23 +3,22 @@ require 'puppet/indirector/terminus'
# The base class for YAML indirection termini.
class Puppet::Indirector::Yaml < Puppet::Indirector::Terminus
# Read a given name's file in and convert it from YAML.
def find(name)
raise ArgumentError.new("You must specify the name of the object to retrieve") unless name
file = path(name)
def find(request)
file = path(request.key)
return nil unless FileTest.exist?(file)
begin
return from_yaml(File.read(file))
rescue => detail
raise Puppet::Error, "Could not read YAML data for %s %s: %s" % [indirection.name, name, detail]
raise Puppet::Error, "Could not read YAML data for %s %s: %s" % [indirection.name, request.key, detail]
end
end
# Convert our object to YAML and store it to the disk.
def save(object)
raise ArgumentError.new("You can only save objects that respond to :name") unless object.respond_to?(:name)
def save(request)
raise ArgumentError.new("You can only save objects that respond to :name") unless request.instance.respond_to?(:name)
file = path(object.name)
file = path(request.key)
basedir = File.dirname(file)
@ -29,15 +28,15 @@ class Puppet::Indirector::Yaml < Puppet::Indirector::Terminus
end
begin
File.open(file, "w", 0660) { |f| f.print to_yaml(object) }
File.open(file, "w", 0660) { |f| f.print to_yaml(request.instance) }
rescue TypeError => detail
Puppet.err "Could not save %s %s: %s" % [self.name, object.name, detail]
Puppet.err "Could not save %s %s: %s" % [self.name, request.key, detail]
end
end
def version(name)
return nil unless FileTest.exist?(path(name))
return File.stat(path(name)).mtime
# Return the path to a given node's file.
def path(name)
File.join(Puppet[:yamldir], self.class.indirection_name.to_s, name.to_s + ".yaml")
end
private
@ -49,9 +48,4 @@ class Puppet::Indirector::Yaml < Puppet::Indirector::Terminus
def to_yaml(object)
YAML.dump(object)
end
# Return the path to a given node's file.
def path(name)
File.join(Puppet[:yamldir], self.class.indirection_name.to_s, name.to_s + ".yaml")
end
end

Просмотреть файл

@ -477,13 +477,9 @@ class Puppet::Type
end
if obj = @parameters[name]
# We throw a failure here, because this method is too
# ambiguous when used with properties.
if obj.is_a?(Puppet::Property)
fail "[] called on a property"
else
return obj.value
end
# Note that if this is a property, then the value is the "should" value,
# not the current value.
obj.value
else
return nil
end

Просмотреть файл

@ -132,7 +132,7 @@ class Puppet::Module
def manifests(rest)
rest ||= "init.pp"
p = File::join(path, MANIFESTS, rest)
files = Dir.glob(p)
files = Dir.glob(p).reject { |f| FileTest.directory?(f) }
if files.size == 0
files = Dir.glob(p + ".pp")
end

Просмотреть файл

@ -49,6 +49,8 @@ class Puppet::Network::Client::Master < Puppet::Network::Client
end
# Return the list of dynamic facts as an array of symbols
# NOTE:LAK(2008/04/10): This code is currently unused, since we now always
# recompile.
def self.dynamic_facts
# LAK:NOTE See http://snurl.com/21zf8 [groups_google_com]
x = Puppet.settings[:dynamicfacts].split(/\s*,\s*/).collect { |fact| fact.downcase }
@ -96,31 +98,6 @@ class Puppet::Network::Client::Master < Puppet::Network::Client
end
end
# Check whether our catalog is up to date
def fresh?(facts)
if Puppet[:ignorecache]
Puppet.notice "Ignoring cache"
return false
end
unless self.compile_time
Puppet.debug "No cached compile time"
return false
end
if facts_changed?(facts)
Puppet.info "Facts have changed; recompiling" unless local?
return false
end
newcompile = @driver.freshness
# We're willing to give a 2 second drift
if newcompile - @compile_time.to_i < 1
return true
else
Puppet.debug "Server compile time is %s vs %s" % [newcompile, @compile_time.to_i]
return false
end
end
# Let the daemon run again, freely in the filesystem. Frolick, little
# daemon!
def enable
@ -147,11 +124,6 @@ class Puppet::Network::Client::Master < Puppet::Network::Client
# Retrieve the plugins.
getplugins() if Puppet[:pluginsync]
if (self.catalog or FileTest.exist?(self.cachefile)) and self.fresh?(facts)
Puppet.info "Configuration is up to date"
return if use_cached_config
end
Puppet.debug("Retrieving catalog")
# If we can't retrieve the catalog, just return, which will either
@ -450,32 +422,6 @@ class Puppet::Network::Client::Master < Puppet::Network::Client
loadfacts()
# Have the facts changed since we last compiled?
def facts_changed?(facts)
oldfacts = (Puppet::Util::Storage.cache(:configuration)[:facts] || {}).dup
newfacts = facts.dup
self.class.dynamic_facts.each do |fact|
[oldfacts, newfacts].each do |facthash|
facthash.delete(fact) if facthash.include?(fact)
end
end
if oldfacts == newfacts
return false
else
# unless oldfacts
# puts "no old facts"
# return true
# end
# newfacts.keys.each do |k|
# unless newfacts[k] == oldfacts[k]
# puts "%s: %s vs %s" % [k, newfacts[k], oldfacts[k]]
# end
# end
return true
end
end
# Actually retrieve the catalog, either from the server or from a
# local master.
def get_actual_config(facts)

Просмотреть файл

@ -1,184 +0,0 @@
require 'openssl'
require 'puppet'
require 'puppet/parser/interpreter'
require 'puppet/sslcertificates'
require 'xmlrpc/server'
require 'yaml'
class Puppet::Network::Handler
class Configuration < Handler
desc "Puppet's configuration compilation interface. Passed a node name
or other key, retrieves information about the node (using the ``node_source``)
and returns a compiled configuration."
include Puppet::Util
attr_accessor :local, :classes
@interface = XMLRPC::Service::Interface.new("configuration") { |iface|
iface.add_method("string configuration(string)")
iface.add_method("string version()")
}
# Compile a node's configuration.
def configuration(key, client = nil, clientip = nil)
# If we want to use the cert name as our key
if Puppet[:node_name] == 'cert' and client
key = client
end
# Note that this is reasonable, because either their node source should actually
# know about the node, or they should be using the ``none`` node source, which
# will always return data.
unless node = Puppet::Node.find_by_any_name(key)
raise Puppet::Error, "Could not find node '%s'" % key
end
# Add any external data to the node.
add_node_data(node)
configuration = compile(node)
return translate(configuration)
end
def initialize(options = {})
options.each do |param, value|
case param
when :Classes: @classes = value
when :Local: self.local = value
else
raise ArgumentError, "Configuration handler does not accept %s" % param
end
end
set_server_facts
end
# Are we running locally, or are our clients networked?
def local?
self.local
end
# Return the configuration version.
def version(client = nil, clientip = nil)
if client and node = Puppet::Node.find_by_any_name(client)
update_node_check(node)
return interpreter.configuration_version(node)
else
# Just return something that will always result in a recompile, because
# this is local.
return (Time.now + 1000).to_i
end
end
private
# Add any extra data necessary to the node.
def add_node_data(node)
# Merge in our server-side facts, so they can be used during compilation.
node.merge(@server_facts)
# Add any specified classes to the node's class list.
if @classes
@classes.each do |klass|
node.classes << klass
end
end
end
# Compile the actual configuration.
def compile(node)
# Pick the benchmark level.
if local?
level = :none
else
level = :notice
end
# Ask the interpreter to compile the configuration.
str = "Compiled configuration for %s" % node.name
if node.environment
str += " in environment %s" % node.environment
end
config = nil
benchmark(level, "Compiled configuration for %s" % node.name) do
begin
config = interpreter.compile(node)
rescue => detail
# If we're local, then we leave it to the local system
# to handle error reporting, but otherwise we do it here
# so the interpreter doesn't need to know if the parser
# is local or not.
Puppet.err(detail.to_s) unless local?
raise
end
end
return config
end
# Create our interpreter object.
def create_interpreter
return Puppet::Parser::Interpreter.new
end
# Create/return our interpreter.
def interpreter
unless defined?(@interpreter) and @interpreter
@interpreter = create_interpreter
end
@interpreter
end
# Initialize our server fact hash; we add these to each client, and they
# won't change while we're running, so it's safe to cache the values.
def set_server_facts
@server_facts = {}
# Add our server version to the fact list
@server_facts["serverversion"] = Puppet.version.to_s
# And then add the server name and IP
{"servername" => "fqdn",
"serverip" => "ipaddress"
}.each do |var, fact|
if value = Facter.value(fact)
@server_facts[var] = value
else
Puppet.warning "Could not retrieve fact %s" % fact
end
end
if @server_facts["servername"].nil?
host = Facter.value(:hostname)
if domain = Facter.value(:domain)
@server_facts["servername"] = [host, domain].join(".")
else
@server_facts["servername"] = host
end
end
end
# Translate our configuration appropriately for sending back to a client.
def translate(config)
if local?
config
else
CGI.escape(config.to_yaml(:UseBlock => true))
end
end
# Mark that the node has checked in. FIXME this needs to be moved into
# the Node class, or somewhere that's got abstract backends.
def update_node_check(node)
if Puppet.features.rails? and Puppet[:storeconfigs]
Puppet::Rails.connect
host = Puppet::Rails::Host.find_or_create_by_name(node.name)
host.last_freshcheck = Time.now
host.save
end
end
end
end

Просмотреть файл

@ -23,8 +23,8 @@ class Puppet::Network::Handler
# Tell a client whether there's a fresh config for it
def freshness(client = nil, clientip = nil)
client ||= Facter.value("hostname")
config_handler.version(client, clientip)
# Always force a recompile. Newer clients shouldn't do this (as of April 2008).
Time.now
end
def initialize(hash = {})
@ -51,8 +51,6 @@ class Puppet::Network::Handler
if hash.include?(:Classes)
args[:Classes] = hash[:Classes]
end
@config_handler = Puppet::Network::Handler.handler(:configuration).new(args)
end
# Call our various handlers; this handler is getting deprecated.
@ -63,13 +61,9 @@ class Puppet::Network::Handler
# Pass the facts to the fact handler
Puppet::Node::Facts.new(client, facts).save unless local?
# And get the configuration from the config handler
config = nil
benchmark(:notice, "Compiled configuration for %s" % client) do
config = config_handler.configuration(client)
end
catalog = Puppet::Node::Catalog.find(client)
return translate(config.extract)
return translate(catalog.extract)
end
private
@ -93,13 +87,6 @@ class Puppet::Network::Handler
return client, clientip
end
def config_handler
unless defined? @config_handler
@config_handler = Puppet::Network::Handler.handler(:config).new :local => local?
end
@config_handler
end
#
def decode_facts(facts)
if @local

Просмотреть файл

@ -49,6 +49,11 @@ module Puppet::Network
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; considering using the certname configuration option"
end
end
raise XMLRPCClientError,
"Certificates were not trusted: %s" % detail
rescue ::XMLRPC::FaultException => detail

Просмотреть файл

@ -8,8 +8,16 @@ class Puppet::Node::Facts
# the node sources.
extend Puppet::Indirector
# We want to expire any cached nodes if the facts are saved.
module NodeExpirer
def save(instance, *args)
Puppet::Node.expire(instance.name)
super
end
end
# Use the node source as the indirection terminus.
indirects :facts, :terminus_class => :facter
indirects :facts, :terminus_class => :facter, :extend => NodeExpirer
attr_accessor :name, :values

Просмотреть файл

@ -237,7 +237,9 @@ class Puppet::Parser::Parser
end
end
return true if classes.include?(classname)
# We don't know whether we're looking for a class or definition, so we have
# to test for both.
return true if classes.include?(classname) || definitions.include?(classname)
unless @loaded.include?(filename)
@loaded << filename
@ -249,7 +251,9 @@ class Puppet::Parser::Parser
# We couldn't load the file
end
end
return classes.include?(classname)
# We don't know whether we're looking for a class or definition, so we have
# to test for both.
return classes.include?(classname) || definitions.include?(classname)
end
# Split an fq name into a namespace and name

Просмотреть файл

@ -303,6 +303,12 @@ class Puppet::Parser::Resource
return bucket
end
# Convert this resource to a RAL resource. We hackishly go via the
# transportable stuff.
def to_type
to_trans.to_type
end
def to_transobject
# Now convert to a transobject
obj = Puppet::TransObject.new(@ref.title, @ref.type)

Просмотреть файл

@ -22,7 +22,7 @@ Puppet::Type.type(:service).provide :debian, :parent => :init do
# If it's enabled, then it will print output showing removal of
# links.
if output =~ /etc\/rc[\dS].d|not installed/
if output =~ /etc\/rc[\dS].d\/S|not installed/
return :true
else
return :false

Просмотреть файл

@ -0,0 +1,23 @@
require 'puppet/reports'
report = Puppet::Util::Reference.newreference :report, :doc => "All available transaction reports" do
Puppet::Reports.reportdocs
end
report.header = "
Puppet clients can report back to the server after each transaction. This
transaction report is sent as a YAML dump of the
``Puppet::Transaction::Report`` class and includes every log message that was
generated during the transaction along with as many metrics as Puppet knows how
to collect. See `ReportsAndReporting Reports and Reporting`:trac:
for more information on how to use reports.
Currently, clients default to not sending in reports; you can enable reporting
by setting the ``report`` parameter to true.
To use a report, set the ``reports`` parameter on the server; multiple
reports must be comma-separated. You can also specify ``none`` to disable
reports entirely.
Puppet provides multiple report handlers that will process client reports:
"

Просмотреть файл

@ -1,8 +1,10 @@
Puppet::Reports.register_report(:rrdgraph) do
desc "Graph all available data about hosts using the RRD library. You
must have the Ruby RRDtool library installed to use this report, which
you can get from `the RubyRRDTool RubyForge page`_. This package requires
the binary rrdtool2 package to be installed.
you can get from `the RubyRRDTool RubyForge page`_. This package may also
be available as ``ruby-rrd`` or ``rrdtool-ruby`` in your distribution's package
management system. The library and/or package will both require the binary
``rrdtool`` package from your distribution to be installed.
.. _the RubyRRDTool RubyForge page: http://rubyforge.org/projects/rubyrrdtool/

Просмотреть файл

@ -34,6 +34,10 @@ class Puppet::Transaction::Report
end
end
def name
host
end
# Create a new metric.
def newmetric(name, hash)
metric = Puppet::Util::Metric.new(name)

Просмотреть файл

@ -11,12 +11,8 @@ module Puppet
end
def id2name(id)
if id > 70000
return nil
end
if id.is_a?(Symbol)
return id.to_s
end
return id.to_s if id.is_a?(Symbol)
return nil if id > Puppet[:maximum_uid].to_i
begin
group = Etc.getgrgid(id)
rescue ArgumentError
@ -73,7 +69,17 @@ module Puppet
@method = :chown
end
return stat.gid
currentvalue = stat.gid
# On OS X, files that are owned by -2 get returned as really
# large GIDs instead of negative ones. This isn't a Ruby bug,
# it's an OS X bug, since it shows up in perl, too.
if currentvalue > Puppet[:maximum_uid].to_i
self.warning "Apparently using negative GID (%s) on a platform that does not consistently handle them" % currentvalue
currentvalue = :silly
end
return currentvalue
end
# Determine if the group is valid, and if so, return the GID

Просмотреть файл

@ -95,7 +95,7 @@ module Puppet
# Solaris specifies two devices, not just one.
newproperty(:blockdevice) do
desc "The the device to fsck. This is property is only valid
desc "The device to fsck. This is property is only valid
on Solaris, and in most cases will default to the correct
value."

Просмотреть файл

@ -0,0 +1,3 @@
require 'puppet/util/nagios_maker'
Puppet::Util::NagiosMaker.create_nagios_type :hostescalation

Просмотреть файл

@ -0,0 +1,3 @@
require 'puppet/util/nagios_maker'
Puppet::Util::NagiosMaker.create_nagios_type :servicegroup

Просмотреть файл

@ -220,6 +220,9 @@ module Puppet
if value =~ /^\d+$/
raise ArgumentError, "Group names must be provided, not numbers"
end
if value.include?(",")
raise ArgumentError, "Group names must be provided as an array, not a comma-separated list"
end
end
end

Просмотреть файл

@ -13,7 +13,7 @@ module Puppet::Util::POSIX
end
prefix = "get" + space.to_s
if id.is_a?(Integer)
if id > 1000000
if id > Puppet[:maximum_uid].to_i
Puppet.err "Tried to get %s field for silly id %s" % [field, id]
return nil
end
@ -40,7 +40,7 @@ module Puppet::Util::POSIX
end
if id.is_a?(Integer)
integer = true
if id > 1000000
if id > Puppet[:maximum_uid].to_i
Puppet.err "Tried to get %s field for silly id %s" % [field, id]
return nil
end

Просмотреть файл

@ -38,7 +38,7 @@ describe Puppet::Checksum, " when using the file terminus" do
File.stubs(:exist?).returns(true)
File.expects(:unlink).with(@file)
Puppet::Checksum.destroy(@sum)
Puppet::Checksum.destroy(@sum.name)
end
after do

Просмотреть файл

@ -19,7 +19,7 @@ describe Puppet::Indirector::DirectFileServer, " when interacting with the files
it "should return an instance of the model" do
FileTest.expects(:exists?).with(@filepath).returns(true)
@terminus.find("file://host#{@filepath}").should be_instance_of(Puppet::FileServing::Content)
@terminus.find(@terminus.indirection.request(:find, "file://host#{@filepath}")).should be_instance_of(Puppet::FileServing::Content)
end
it "should return an instance capable of returning its content" do
@ -27,7 +27,7 @@ describe Puppet::Indirector::DirectFileServer, " when interacting with the files
File.stubs(:lstat).with(@filepath).returns(stub("stat", :ftype => "file"))
File.expects(:read).with(@filepath).returns("my content")
instance = @terminus.find("file://host#{@filepath}")
instance = @terminus.find(@terminus.indirection.request(:find, "file://host#{@filepath}"))
instance.content.should == "my content"
end
@ -50,10 +50,12 @@ describe Puppet::Indirector::DirectFileServer, " when interacting with FileServi
end
Dir.expects(:entries).with(@filepath).returns @subfiles
@request = @terminus.indirection.request(:search, "file:///my/file", :recurse => true)
end
it "should return an instance for every file in the fileset" do
result = @terminus.search("file:///my/file", :recurse => true)
result = @terminus.search(@request)
result.should be_instance_of(Array)
result.length.should == 3
result.each { |r| r.should be_instance_of(Puppet::FileServing::Content) }
@ -65,7 +67,7 @@ describe Puppet::Indirector::DirectFileServer, " when interacting with FileServi
File.expects(:read).with(File.join(@filepath, name)).returns("#{name} content")
end
@terminus.search("file:///my/file", :recurse => true).each do |instance|
@terminus.search(@request).each do |instance|
case instance.key
when /one/: instance.content.should == "one content"
when /two/: instance.content.should == "two content"

Просмотреть файл

@ -7,38 +7,86 @@ require File.dirname(__FILE__) + '/../spec_helper'
require 'puppet/node'
describe Puppet::Node, " when using the memory terminus" do
before do
@name = "me"
@old_terminus = Puppet::Node.indirection.terminus_class
@terminus = Puppet::Node.indirection.terminus(:memory)
Puppet::Node.indirection.stubs(:terminus).returns @terminus
@node = Puppet::Node.new(@name)
end
describe Puppet::Node do
describe "when delegating indirection calls" do
before do
@name = "me"
@node = Puppet::Node.new(@name)
end
it "should find no nodes by default" do
Puppet::Node.find(@name).should be_nil
end
it "should be able to use the exec terminus" do
Puppet::Node.indirection.stubs(:terminus_class).returns :exec
it "should be able to find nodes that were previously saved" do
@node.save
Puppet::Node.find(@name).should equal(@node)
end
# Load now so we can stub
terminus = Puppet::Node.indirection.terminus(:exec)
it "should replace existing saved nodes when a new node with the same name is saved" do
@node.save
two = Puppet::Node.new(@name)
two.save
Puppet::Node.find(@name).should equal(two)
end
terminus.expects(:query).with(@name).returns "myresults"
terminus.expects(:translate).with(@name, "myresults").returns "translated_results"
terminus.expects(:create_node).with(@name, "translated_results").returns @node
it "should be able to remove previously saved nodes" do
@node.save
Puppet::Node.destroy(@node)
Puppet::Node.find(@name).should be_nil
end
Puppet::Node.find(@name).should equal(@node)
end
it "should fail when asked to destroy a node that does not exist" do
proc { Puppet::Node.destroy(@node) }.should raise_error(ArgumentError)
it "should be able to use the yaml terminus" do
Puppet::Node.indirection.stubs(:terminus_class).returns :yaml
# Load now, before we stub the exists? method.
Puppet::Node.indirection.terminus(:yaml)
file = File.join(Puppet[:yamldir], "node", "me.yaml")
FileTest.expects(:exist?).with(file).returns false
Puppet::Node.find(@name).should be_nil
end
it "should have an ldap terminus" do
Puppet::Node.indirection.terminus(:ldap).should_not be_nil
end
it "should be able to use the plain terminus" do
Puppet::Node.indirection.stubs(:terminus_class).returns :plain
# Load now, before we stub the exists? method.
Puppet::Node.indirection.terminus(:plain)
Puppet::Node.expects(:new).with(@name).returns @node
Puppet::Node.find(@name).should equal(@node)
end
describe "and using the memory terminus" do
before do
@name = "me"
@old_terminus = Puppet::Node.indirection.terminus_class
@terminus = Puppet::Node.indirection.terminus(:memory)
Puppet::Node.indirection.stubs(:terminus).returns @terminus
@node = Puppet::Node.new(@name)
end
it "should find no nodes by default" do
Puppet::Node.find(@name).should be_nil
end
it "should be able to find nodes that were previously saved" do
@node.save
Puppet::Node.find(@name).should equal(@node)
end
it "should replace existing saved nodes when a new node with the same name is saved" do
@node.save
two = Puppet::Node.new(@name)
two.save
Puppet::Node.find(@name).should equal(two)
end
it "should be able to remove previously saved nodes" do
@node.save
Puppet::Node.destroy(@node.name)
Puppet::Node.find(@name).should be_nil
end
it "should fail when asked to destroy a node that does not exist" do
proc { Puppet::Node.destroy(@node) }.should raise_error(ArgumentError)
end
end
end
end

Просмотреть файл

@ -0,0 +1,38 @@
#!/usr/bin/env ruby
#
# Created by Luke Kanies on 2007-4-8.
# Copyright (c) 2008. All rights reserved.
require File.dirname(__FILE__) + '/../../spec_helper'
describe Puppet::Node::Catalog do
describe "when using the indirector" do
after { Puppet::Node::Catalog.indirection.clear_cache }
it "should be able to delegate to the :yaml terminus" do
Puppet::Node::Catalog.indirection.stubs(:terminus_class).returns :yaml
# Load now, before we stub the exists? method.
Puppet::Node::Catalog.indirection.terminus(:yaml)
file = File.join(Puppet[:yamldir], "catalog", "me.yaml")
FileTest.expects(:exist?).with(file).returns false
Puppet::Node::Catalog.find("me").should be_nil
end
it "should be able to delegate to the :compiler terminus" do
Puppet::Node::Catalog.indirection.stubs(:terminus_class).returns :compiler
# Load now, before we stub the exists? method.
compiler = Puppet::Node::Catalog.indirection.terminus(:compiler)
node = mock 'node'
node.stub_everything
Puppet::Node.expects(:find).returns(node)
compiler.expects(:compile).with(node).returns nil
Puppet::Node::Catalog.find("me").should be_nil
end
end
end

45
spec/integration/node/facts.rb Executable file
Просмотреть файл

@ -0,0 +1,45 @@
#!/usr/bin/env ruby
#
# Created by Luke Kanies on 2008-4-8.
# Copyright (c) 2008. All rights reserved.
require File.dirname(__FILE__) + '/../../spec_helper'
describe Puppet::Node::Facts do
describe "when using the indirector" do
after { Puppet::Node::Facts.indirection.clear_cache }
it "should expire any cached node instances when it is saved" do
Puppet::Node::Facts.indirection.stubs(:terminus_class).returns :yaml
terminus = Puppet::Node::Facts.indirection.terminus(:yaml)
terminus.expects(:save)
Puppet::Node.expects(:expire).with("me")
facts = Puppet::Node::Facts.new("me")
facts.save
end
it "should be able to delegate to the :yaml terminus" do
Puppet::Node::Facts.indirection.stubs(:terminus_class).returns :yaml
# Load now, before we stub the exists? method.
Puppet::Node::Facts.indirection.terminus(:yaml)
file = File.join(Puppet[:yamldir], "facts", "me.yaml")
FileTest.expects(:exist?).with(file).returns false
Puppet::Node::Facts.find("me").should be_nil
end
it "should be able to delegate to the :facter terminus" do
Puppet::Node::Facts.indirection.stubs(:terminus_class).returns :facter
Facter.expects(:to_hash).returns "facter_hash"
facts = Puppet::Node::Facts.new("me")
Puppet::Node::Facts.expects(:new).with("me", "facter_hash").returns facts
Puppet::Node::Facts.find("me").should equal(facts)
end
end
end

Просмотреть файл

@ -0,0 +1,26 @@
#!/usr/bin/env ruby
#
# Created by Luke Kanies on 2008-4-8.
# Copyright (c) 2008. All rights reserved.
require File.dirname(__FILE__) + '/../../spec_helper'
describe Puppet::Transaction::Report do
describe "when using the indirector" do
after { Puppet::Transaction::Report.indirection.clear_cache }
it "should be able to delegate to the :processor terminus" do
Puppet::Transaction::Report.indirection.stubs(:terminus_class).returns :processor
terminus = Puppet::Transaction::Report.indirection.terminus(:processor)
Facter.stubs(:value).returns "host.domain.com"
report = Puppet::Transaction::Report.new
terminus.expects(:process).with(report)
report.save
end
end
end

Просмотреть файл

@ -6,7 +6,7 @@
describe "Puppet::FileServing::Files", :shared => true do
it "should use the rest terminus when the 'puppet' URI scheme is used and a host name is present" do
uri = "puppet://myhost/mymod/my/file"
@indirection.terminus(:rest).expects(:find).with(uri)
@indirection.terminus(:rest).expects(:find)
@test_class.find(uri)
end
@ -14,7 +14,7 @@ describe "Puppet::FileServing::Files", :shared => true do
uri = "puppet:///mymod/my/file"
Puppet.settings.stubs(:value).with(:name).returns("puppetd")
Puppet.settings.stubs(:value).with(:modulepath).returns("")
@indirection.terminus(:rest).expects(:find).with(uri)
@indirection.terminus(:rest).expects(:find)
@test_class.find(uri)
end
@ -27,27 +27,27 @@ describe "Puppet::FileServing::Files", :shared => true do
Puppet.settings.stubs(:value).with(:libdir).returns("")
Puppet.settings.stubs(:value).with(:fileserverconfig).returns("/whatever")
Puppet.settings.stubs(:value).with(:environment).returns("")
@indirection.terminus(:file_server).expects(:find).with(uri)
@indirection.terminus(:file_server).expects(:find)
@indirection.terminus(:file_server).stubs(:authorized?).returns(true)
@test_class.find(uri)
end
it "should use the file_server terminus when the 'puppetmounts' URI scheme is used" do
uri = "puppetmounts:///mymod/my/file"
@indirection.terminus(:file_server).expects(:find).with(uri)
@indirection.terminus(:file_server).expects(:find)
@indirection.terminus(:file_server).stubs(:authorized?).returns(true)
@test_class.find(uri)
end
it "should use the file terminus when the 'file' URI scheme is used" do
uri = "file:///mymod/my/file"
@indirection.terminus(:file).expects(:find).with(uri)
@indirection.terminus(:file).expects(:find)
@test_class.find(uri)
end
it "should use the file terminus when a fully qualified path is provided" do
uri = "/mymod/my/file"
@indirection.terminus(:file).expects(:find).with(uri)
@indirection.terminus(:file).expects(:find)
@test_class.find(uri)
end
end

Просмотреть файл

@ -0,0 +1,32 @@
#
# Created by Luke Kanies on 2008-4-8.
# Copyright (c) 2008. All rights reserved.
describe "A Memory Terminus", :shared => true do
it "should find no instances by default" do
@searcher.find(@request).should be_nil
end
it "should be able to find instances that were previously saved" do
@searcher.save(@request)
@searcher.find(@request).should equal(@instance)
end
it "should replace existing saved instances when a new instance with the same name is saved" do
@searcher.save(@request)
two = stub 'second', :name => @name
trequest = stub 'request', :key => @name, :instance => two
@searcher.save(trequest)
@searcher.find(@request).should equal(two)
end
it "should be able to remove previously saved instances" do
@searcher.save(@request)
@searcher.destroy(@request)
@searcher.find(@request).should be_nil
end
it "should fail when asked to destroy an instance that does not exist" do
proc { @searcher.destroy(@request) }.should raise_error(ArgumentError)
end
end

Просмотреть файл

@ -221,4 +221,4 @@ describe Puppet::FileServing::Configuration do
@config.authorized?("/one/my/file").should be_false
end
end
end
end

Просмотреть файл

@ -132,4 +132,4 @@ describe Puppet::FileServing::Configuration::Parser do
@parser.parse
end
end
end
end

Просмотреть файл

@ -7,104 +7,118 @@ require File.dirname(__FILE__) + '/../../spec_helper'
require 'puppet/file_serving/indirection_hooks'
describe Puppet::FileServing::IndirectionHooks, " when being used to select termini" do
before do
@object = Object.new
@object.extend(Puppet::FileServing::IndirectionHooks)
end
it "should escape the key before parsing" do
uri = stub 'uri', :scheme => "puppet", :host => "blah", :path => "/something"
URI.expects(:escape).with("mykey").returns("http://myhost/blah")
URI.expects(:parse).with("http://myhost/blah").returns(uri)
@object.select_terminus("mykey")
end
it "should use the URI class to parse the key" do
uri = stub 'uri', :scheme => "puppet", :host => "blah", :path => "/something"
URI.expects(:parse).with("http://myhost/blah").returns(uri)
@object.select_terminus("http://myhost/blah")
end
it "should choose :rest when the protocol is 'puppet'" do
@object.select_terminus("puppet://host/module/file").should == :rest
end
it "should choose :file_server when the protocol is 'puppetmounts' and the mount name is not 'modules'" do
modules = mock 'modules'
@object.stubs(:terminus).with(:modules).returns(modules)
modules.stubs(:find_module).returns(nil)
@object.select_terminus("puppetmounts://host/notmodules/file").should == :file_server
end
it "should choose :file_server when no server name is provided, the process name is 'puppet', and the mount name is not 'modules'" do
modules = mock 'modules'
@object.stubs(:terminus).with(:modules).returns(modules)
modules.stubs(:find_module).returns(nil)
Puppet.settings.expects(:value).with(:name).returns("puppet")
@object.select_terminus("puppet:///notmodules/file").should == :file_server
end
it "should choose :modules if it would normally choose :file_server but the mount name is 'modules'" do
@object.select_terminus("puppetmounts://host/modules/mymod/file").should == :modules
end
it "should choose :modules it would normally choose :file_server but a module exists with the mount name" do
modules = mock 'modules'
@object.expects(:terminus).with(:modules).returns(modules)
modules.expects(:find_module).with("mymod", nil).returns(:thing)
@object.select_terminus("puppetmounts://host/mymod/file").should == :modules
end
it "should choose :rest when no server name is provided and the process name is not 'puppet'" do
Puppet.settings.expects(:value).with(:name).returns("puppetd")
@object.select_terminus("puppet:///module/file").should == :rest
end
it "should choose :file when the protocol is 'file'" do
@object.select_terminus("file://host/module/file").should == :file
end
it "should choose :file when the URI is a normal path name" do
@object.select_terminus("/module/file").should == :file
end
# This is so that we only choose modules over mounts, not file
it "should choose :file when the protocol is 'file' and the fully qualified path starts with '/modules'" do
@object.select_terminus("file://host/modules/file").should == :file
end
it "should fail when a protocol other than :puppet, :file, or :puppetmounts is used" do
proc { @object.select_terminus("http:///module/file") }.should raise_error(ArgumentError)
end
end
describe Puppet::FileServing::IndirectionHooks, " when looking for a module whose name matches the mount name" do
describe Puppet::FileServing::IndirectionHooks do
before do
@object = Object.new
@object.extend(Puppet::FileServing::IndirectionHooks)
@modules = mock 'modules'
@object.stubs(:terminus).with(:modules).returns(@modules)
@request = stub 'request', :key => "http://myhost/blah", :options => {:node => "whatever"}
end
it "should use the modules terminus to look up the module" do
@modules.expects(:find_module).with("mymod", nil)
@object.select_terminus("puppetmounts://host/mymod/my/file")
describe "when being used to select termini" do
it "should escape the key before parsing" do
uri = stub 'uri', :scheme => "puppet", :host => "blah", :path => "/something"
URI.expects(:escape).with("http://myhost/blah").returns("escaped_blah")
URI.expects(:parse).with("escaped_blah").returns(uri)
@object.select_terminus(@request)
end
it "should use the URI class to parse the key" do
uri = stub 'uri', :scheme => "puppet", :host => "blah", :path => "/something"
URI.expects(:parse).with("http://myhost/blah").returns(uri)
@object.select_terminus @request
end
it "should choose :rest when the protocol is 'puppet'" do
@request.stubs(:key).returns "puppet://host/module/file"
@object.select_terminus(@request).should == :rest
end
it "should choose :file_server when the protocol is 'puppetmounts' and the mount name is not 'modules'" do
modules = mock 'modules'
@object.stubs(:terminus).with(:modules).returns(modules)
modules.stubs(:find_module).returns(nil)
@request.stubs(:key).returns "puppetmounts://host/notmodules/file"
@object.select_terminus(@request).should == :file_server
end
it "should choose :file_server when no server name is provided, the process name is 'puppet', and the mount name is not 'modules'" do
modules = mock 'modules'
@object.stubs(:terminus).with(:modules).returns(modules)
modules.stubs(:find_module).returns(nil)
Puppet.settings.expects(:value).with(:name).returns("puppet")
@request.stubs(:key).returns "puppet:///notmodules/file"
@object.select_terminus(@request).should == :file_server
end
it "should choose :modules if it would normally choose :file_server but the mount name is 'modules'" do
@request.stubs(:key).returns "puppetmounts://host/modules/mymod/file"
@object.select_terminus(@request).should == :modules
end
it "should choose :modules if it would normally choose :file_server but a module exists with the mount name" do
modules = mock 'modules'
@object.expects(:terminus).with(:modules).returns(modules)
modules.expects(:find_module).with("mymod", @request.options[:node]).returns(:thing)
@request.stubs(:key).returns "puppetmounts://host/mymod/file"
@object.select_terminus(@request).should == :modules
end
it "should choose :rest when no server name is provided and the process name is not 'puppet'" do
Puppet.settings.expects(:value).with(:name).returns("puppetd")
@request.stubs(:key).returns "puppet:///module/file"
@object.select_terminus(@request).should == :rest
end
it "should choose :file when the protocol is 'file'" do
@request.stubs(:key).returns "file://host/module/file"
@object.select_terminus(@request).should == :file
end
it "should choose :file when the URI is a normal path name" do
@request.stubs(:key).returns "/module/file"
@object.select_terminus(@request).should == :file
end
# This is so that we only choose modules over mounts, not file
it "should choose :file when the protocol is 'file' and the fully qualified path starts with '/modules'" do
@request.stubs(:key).returns "/module/file"
@object.select_terminus(@request).should == :file
end
it "should fail when a protocol other than :puppet, :file, or :puppetmounts is used" do
@request.stubs(:key).returns "http:///module/file"
proc { @object.select_terminus(@request) }.should raise_error(ArgumentError)
end
end
it "should pass the node name to the modules terminus" do
@modules.expects(:find_module).with("mymod", nil)
@object.select_terminus("puppetmounts://host/mymod/my/file")
end
describe "when looking for a module whose name matches the mount name" do
before do
@modules = mock 'modules'
@object.stubs(:terminus).with(:modules).returns(@modules)
it "should log a deprecation warning if a module is found" do
@modules.expects(:find_module).with("mymod", nil).returns(:something)
Puppet.expects(:warning)
@object.select_terminus("puppetmounts://host/mymod/my/file")
@request.stubs(:key).returns "puppetmounts://host/mymod/file"
end
it "should use the modules terminus to look up the module" do
@modules.expects(:find_module).with("mymod", @request.options[:node])
@object.select_terminus @request
end
it "should pass the node name to the modules terminus" do
@modules.expects(:find_module).with("mymod", @request.options[:node])
@object.select_terminus @request
end
it "should log a deprecation warning if a module is found" do
@modules.expects(:find_module).with("mymod", @request.options[:node]).returns(:something)
Puppet.expects(:warning)
@object.select_terminus @request
end
end
end

Просмотреть файл

@ -21,6 +21,10 @@ describe Puppet::Indirector, "when registering an indirection" do
before do
@thingie = Class.new do
extend Puppet::Indirector
attr_reader :name
def initialize(name)
@name = name
end
end
end
@ -55,48 +59,81 @@ describe Puppet::Indirector, "when registering an indirection" do
end
end
describe Puppet::Indirector, " when redirecting a model" do
describe "Delegated Indirection Method", :shared => true do
it "should delegate to the indirection" do
@indirection.expects(@method)
@thingie.send(@method, "me")
end
it "should pass all of the passed arguments directly to the indirection instance" do
@indirection.expects(@method).with("me", :one => :two)
@thingie.send(@method, "me", :one => :two)
end
it "should return the results of the delegation as its result" do
request = mock 'request'
@indirection.expects(@method).returns "yay"
@thingie.send(@method, "me").should == "yay"
end
end
describe Puppet::Indirector, "when redirecting a model" do
before do
@thingie = Class.new do
extend Puppet::Indirector
attr_reader :name
def initialize(name)
@name = name
end
end
@indirection = @thingie.send(:indirects, :test)
end
it "should give the model the ability set a version" do
thing = @thingie.new
thing.should respond_to(:version=)
it "should include the Envelope module in the model" do
@thingie.ancestors.should be_include(Puppet::Indirector::Envelope)
end
it "should give the model the ability retrieve a version" do
thing = @thingie.new
thing.should respond_to(:version)
describe "when finding instances via the model" do
before { @method = :find }
it_should_behave_like "Delegated Indirection Method"
end
it "should give the model the ability to lookup a model instance by letting the indirection perform the lookup" do
@indirection.expects(:find)
@thingie.find
describe "when destroying instances via the model" do
before { @method = :destroy }
it_should_behave_like "Delegated Indirection Method"
end
it "should give the model the ability to remove model instances from a terminus by letting the indirection remove the instance" do
@indirection.expects(:destroy)
@thingie.destroy
describe "when searching for instances via the model" do
before { @method = :search }
it_should_behave_like "Delegated Indirection Method"
end
it "should give the model the ability to search for model instances by letting the indirection find the matching instances" do
@indirection.expects(:search)
@thingie.search
describe "when expiring instances via the model" do
before { @method = :expire }
it_should_behave_like "Delegated Indirection Method"
end
it "should give the model the ability to store a model instance by letting the indirection store the instance" do
thing = @thingie.new
@indirection.expects(:save).with(thing)
thing.save
end
# This is an instance method, so it behaves a bit differently.
describe "when saving instances via the model" do
before do
@instance = @thingie.new("me")
end
it "should give the model the ability to look up an instance's version by letting the indirection perform the lookup" do
@indirection.expects(:version).with(:thing)
@thingie.version(:thing)
it "should delegate to the indirection" do
@indirection.expects(:save)
@instance.save
end
it "should pass the instance and all arguments to the indirection's :save method" do
@indirection.expects(:save).with(@instance, :one => :two)
@instance.save :one => :two
end
it "should return the results of the delegation as its result" do
request = mock 'request'
@indirection.expects(:save).returns "yay"
@instance.save.should == "yay"
end
end
it "should give the model the ability to set the indirection terminus class" do

Просмотреть файл

@ -26,8 +26,8 @@ describe Puppet::Node::Catalog::Compiler do
Puppet::Node.stubs(:find_by_any_name).with('node1').returns(node1)
Puppet::Node.stubs(:find_by_any_name).with('node2').returns(node2)
compiler.find('node1')
compiler.find('node2')
compiler.find(stub('request', :key => 'node1', :options => {}))
compiler.find(stub('node2request', :key => 'node2', :options => {}))
end
it "should provide a method for determining if the catalog is networked" do
@ -63,19 +63,14 @@ describe Puppet::Node::Catalog::Compiler, " when finding nodes" do
@compiler = Puppet::Node::Catalog::Compiler.new
@name = "me"
@node = mock 'node'
@request = stub 'request', :key => @name, :options => {}
@compiler.stubs(:compile)
end
it "should look node information up via the Node class with the provided key" do
@node.stubs :merge
Puppet::Node.expects(:find_by_any_name).with(@name).returns(@node)
@compiler.find(@name)
end
it "should fail if it cannot find the node" do
@node.stubs :merge
Puppet::Node.expects(:find_by_any_name).with(@name).returns(nil)
proc { @compiler.find(@name) }.should raise_error(Puppet::Error)
@compiler.find(@request)
end
end
@ -88,23 +83,24 @@ describe Puppet::Node::Catalog::Compiler, " after finding nodes" do
@compiler = Puppet::Node::Catalog::Compiler.new
@name = "me"
@node = mock 'node'
@request = stub 'request', :key => @name, :options => {}
@compiler.stubs(:compile)
Puppet::Node.stubs(:find_by_any_name).with(@name).returns(@node)
end
it "should add the server's Puppet version to the node's parameters as 'serverversion'" do
@node.expects(:merge).with { |args| args["serverversion"] == "1" }
@compiler.find(@name)
@compiler.find(@request)
end
it "should add the server's fqdn to the node's parameters as 'servername'" do
@node.expects(:merge).with { |args| args["servername"] == "my.server.com" }
@compiler.find(@name)
@compiler.find(@request)
end
it "should add the server's IP address to the node's parameters as 'serverip'" do
@node.expects(:merge).with { |args| args["serverip"] == "my.ip.address" }
@compiler.find(@name)
@compiler.find(@request)
end
# LAK:TODO This is going to be difficult, because this whole process is so
@ -125,27 +121,34 @@ describe Puppet::Node::Catalog::Compiler, " when creating catalogs" do
@name = "me"
@node = Puppet::Node.new @name
@node.stubs(:merge)
@request = stub 'request', :key => @name, :options => {}
Puppet::Node.stubs(:find_by_any_name).with(@name).returns(@node)
end
it "should directly use provided nodes" do
Puppet::Node.expects(:find_by_any_name).never
@compiler.interpreter.expects(:compile).with(@node)
@compiler.find(@node)
@request.stubs(:options).returns(:node => @node)
@compiler.find(@request)
end
it "should fail if no node is passed and none can be found" do
Puppet::Node.stubs(:find_by_any_name).with(@name).returns(nil)
proc { @compiler.find(@request) }.should raise_error(ArgumentError)
end
it "should pass the found node to the interpreter for compiling" do
config = mock 'config'
@compiler.interpreter.expects(:compile).with(@node)
@compiler.find(@name)
@compiler.find(@request)
end
it "should return the results of compiling as the catalog" do
config = mock 'config'
result = mock 'result', :to_transportable => :catalog
result = mock 'result'
@compiler.interpreter.expects(:compile).with(@node).returns(result)
@compiler.find(@name).should == :catalog
@compiler.find(@request).should equal(result)
end
it "should benchmark the compile process" do
@ -154,56 +157,6 @@ describe Puppet::Node::Catalog::Compiler, " when creating catalogs" do
level == :notice and message =~ /^Compiled catalog/
end
@compiler.interpreter.stubs(:compile).with(@node)
@compiler.find(@name)
end
end
describe Puppet::Node::Catalog::Compiler, " when determining a client's available catalog version" do
before do
Puppet::Node::Facts.stubs(:find).returns(nil)
Facter.stubs(:value).returns("whatever")
@catalog = Puppet::Node::Catalog::Compiler.new
@name = "johnny"
end
it "should provide a mechanism for providing the version of a given client's catalog" do
@catalog.should respond_to(:version)
end
it "should use the client's Facts version as the available catalog version if it is the most recent" do
Puppet::Node::Facts.stubs(:version).with(@name).returns(5)
Puppet::Node.expects(:version).with(@name).returns(3)
@catalog.interpreter.stubs(:catalog_version).returns(4)
@catalog.version(@name).should == 5
end
it "should use the client's Node version as the available catalog version if it is the most recent" do
Puppet::Node::Facts.stubs(:version).with(@name).returns(3)
Puppet::Node.expects(:version).with(@name).returns(5)
@catalog.interpreter.stubs(:catalog_version).returns(4)
@catalog.version(@name).should == 5
end
it "should use the last parse date as the available catalog version if it is the most recent" do
Puppet::Node::Facts.stubs(:version).with(@name).returns(3)
Puppet::Node.expects(:version).with(@name).returns(4)
@catalog.interpreter.stubs(:catalog_version).returns(5)
@catalog.version(@name).should == 5
end
it "should return a version of 0 if no information on the node can be found" do
Puppet::Node.stubs(:find_by_any_name).returns(nil)
@catalog.version(@name).should == 0
end
it "should indicate when an update is available even if an input has clock skew" do
pending "Unclear how to implement this"
end
it "should not indicate an available update when apparent updates are a result of clock skew" do
pending "Unclear how to implement this"
@compiler.find(@request)
end
end

Просмотреть файл

@ -38,6 +38,8 @@ describe Puppet::Checksum::File do
Puppet.stubs(:[]).with(:bucketdir).returns(@dir)
@path = @store.path(@value)
@request = stub 'request', :key => @value
end
@ -76,7 +78,7 @@ describe Puppet::Checksum::File do
# The smallest test that will use the calculated path
it "should look for the calculated path" do
File.expects(:exist?).with(@path).returns(false)
@store.find(@value)
@store.find(@request)
end
it "should return an instance of Puppet::Checksum created with the content if the file exists" do
@ -87,18 +89,18 @@ describe Puppet::Checksum::File do
File.expects(:exist?).with(@path).returns(true)
File.expects(:read).with(@path).returns(content)
@store.find(@value).should equal(sum)
@store.find(@request).should equal(sum)
end
it "should return nil if no file is found" do
File.expects(:exist?).with(@path).returns(false)
@store.find(@value).should be_nil
@store.find(@request).should be_nil
end
it "should fail intelligently if a found file cannot be read" do
File.expects(:exist?).with(@path).returns(true)
File.expects(:read).with(@path).raises(RuntimeError)
proc { @store.find(@value) }.should raise_error(Puppet::Error)
proc { @store.find(@request) }.should raise_error(Puppet::Error)
end
end
@ -112,7 +114,7 @@ describe Puppet::Checksum::File do
File.expects(:open).with(@path, "w")
file = stub 'file', :name => @value
@store.save(file)
@store.save(@request)
end
it "should make any directories necessary for storage" do
@ -122,19 +124,16 @@ describe Puppet::Checksum::File do
File.expects(:directory?).with(File.dirname(@path)).returns(true)
File.expects(:open).with(@path, "w")
file = stub 'file', :name => @value
@store.save(file)
@store.save(@request)
end
end
describe Puppet::Checksum::File, " when deleting files" do
it "should remove the file at the calculated path" do
File.expects(:exist?).with(@path).returns(true)
File.expects(:unlink).with(@path)
file = stub 'file', :name => @value
@store.destroy(file)
@store.destroy(@request)
end
end
end
end

Просмотреть файл

@ -23,19 +23,21 @@ describe Puppet::Indirector::DirectFileServer do
@server = @direct_file_class.new
@uri = "file:///my/local"
@request = stub 'request', :key => @uri, :options => {}
end
describe Puppet::Indirector::DirectFileServer, "when finding a single file" do
it "should return nil if the file does not exist" do
FileTest.expects(:exists?).with("/my/local").returns false
@server.find(@uri).should be_nil
@server.find(@request).should be_nil
end
it "should return a Content instance created with the full path to the file if the file exists" do
FileTest.expects(:exists?).with("/my/local").returns true
@model.expects(:new).returns(:mycontent)
@server.find(@uri).should == :mycontent
@server.find(@request).should == :mycontent
end
end
@ -49,18 +51,20 @@ describe Puppet::Indirector::DirectFileServer do
it "should create the Content instance with the original key as the key" do
@model.expects(:new).with { |key, options| key == @uri }.returns(@data)
@server.find(@uri)
@server.find(@request)
end
it "should pass the full path to the instance" do
@model.expects(:new).with { |key, options| options[:path] == "/my/local" }.returns(@data)
@server.find(@uri)
@server.find(@request)
end
it "should pass the :links setting on to the created Content instance if the file exists and there is a value for :links" do
@model.expects(:new).returns(@data)
@data.expects(:links=).with(:manage)
@server.find(@uri, :links => :manage)
@request.stubs(:options).returns(:links => :manage)
@server.find(@request)
end
end
@ -68,25 +72,27 @@ describe Puppet::Indirector::DirectFileServer do
it "should return nil if the file does not exist" do
FileTest.expects(:exists?).with("/my/local").returns false
@server.find(@uri).should be_nil
@server.find(@request).should be_nil
end
it "should pass the original key to :path2instances" do
FileTest.expects(:exists?).with("/my/local").returns true
@server.expects(:path2instances).with { |uri, path, options| uri == @uri }
@server.search(@uri)
@server.search(@request)
end
it "should use :path2instances from the terminus_helper to return instances if the file exists" do
FileTest.expects(:exists?).with("/my/local").returns true
@server.expects(:path2instances)
@server.search(@uri)
@server.search(@request)
end
it "should pass any options on to :path2instances" do
FileTest.expects(:exists?).with("/my/local").returns true
@server.expects(:path2instances).with { |uri, path, options| options == {:testing => :one, :other => :two}}
@server.search(@uri, :testing => :one, :other => :two)
@request.stubs(:options).returns(:testing => :one, :other => :two)
@server.search(@request)
end
end
end
end

Просмотреть файл

@ -0,0 +1,47 @@
#!/usr/bin/env ruby
require File.dirname(__FILE__) + '/../../spec_helper'
require 'puppet/indirector/envelope'
describe Puppet::Indirector::Envelope do
before do
@instance = Object.new
@instance.extend(Puppet::Indirector::Envelope)
end
it "should have an expiration accessor" do
@instance.expiration = "testing"
@instance.expiration.should == "testing"
end
it "should have an expiration setter" do
@instance.should respond_to(:expiration=)
end
it "should have a means of testing whether it is expired" do
@instance.should respond_to(:expired?)
end
describe "when testing if it is expired" do
it "should return false if there is no expiration set" do
@instance.should_not be_expired
end
it "should return true if the current date is after the expiration date" do
@instance.expiration = Time.now - 10
@instance.should be_expired
end
it "should return false if the current date is prior to the expiration date" do
@instance.expiration = Time.now + 10
@instance.should_not be_expired
end
it "should return false if the current date is equal to the expiration date" do
now = Time.now
Time.stubs(:now).returns(now)
@instance.expiration = now
@instance.should_not be_expired
end
end
end

Просмотреть файл

@ -18,31 +18,33 @@ describe Puppet::Indirector::Exec do
@searcher = @exec_class.new
@searcher.command = ["/echo"]
@request = stub 'request', :key => "foo"
end
it "should throw an exception if the command is not an array" do
@searcher.command = "/usr/bin/echo"
proc { @searcher.find("foo") }.should raise_error(Puppet::DevError)
proc { @searcher.find(@request) }.should raise_error(Puppet::DevError)
end
it "should throw an exception if the command is not fully qualified" do
@searcher.command = ["mycommand"]
proc { @searcher.find("foo") }.should raise_error(ArgumentError)
proc { @searcher.find(@request) }.should raise_error(ArgumentError)
end
it "should execute the command with the object name as the only argument" do
@searcher.expects(:execute).with(%w{/echo yay})
@searcher.find("yay")
@searcher.expects(:execute).with(%w{/echo foo})
@searcher.find(@request)
end
it "should return the output of the script" do
@searcher.expects(:execute).with(%w{/echo yay}).returns("whatever")
@searcher.find("yay").should == "whatever"
@searcher.expects(:execute).with(%w{/echo foo}).returns("whatever")
@searcher.find(@request).should == "whatever"
end
it "should return nil when the command produces no output" do
@searcher.expects(:execute).with(%w{/echo yay}).returns(nil)
@searcher.find("yay").should be_nil
@searcher.expects(:execute).with(%w{/echo foo}).returns(nil)
@searcher.find(@request).should be_nil
end
it "should be able to execute commands with multiple arguments"

Просмотреть файл

@ -36,22 +36,22 @@ describe Puppet::Node::Facts::Facter do
@facter = Puppet::Node::Facts::Facter.new
Facter.stubs(:to_hash).returns({})
@name = "me"
@facts = @facter.find(@name)
@request = stub 'request', :key => @name
end
describe Puppet::Node::Facts::Facter, " when finding facts" do
it "should return a Facts instance" do
@facts.should be_instance_of(Puppet::Node::Facts)
@facter.find(@request).should be_instance_of(Puppet::Node::Facts)
end
it "should return a Facts instance with the provided key as the name" do
@facts.name.should == @name
@facter.find(@request).name.should == @name
end
it "should return the Facter facts as the values in the Facts instance" do
Facter.expects(:to_hash).returns("one" => "two")
facts = @facter.find(@name)
facts = @facter.find(@request)
facts.values["one"].should == "two"
end
end
@ -73,4 +73,4 @@ describe Puppet::Node::Facts::Facter do
describe Puppet::Node::Facts::Facter, " when loading facts from the factpath" do
it "should load every fact in each factpath directory"
end
end
end

Просмотреть файл

@ -21,6 +21,8 @@ describe Puppet::Indirector::File do
@path = "/my/file"
@dir = "/my"
@request = stub 'request', :key => @path
end
describe Puppet::Indirector::File, " when finding files" do
@ -37,7 +39,7 @@ describe Puppet::Indirector::File do
File.expects(:exist?).with(@path).returns(true)
File.expects(:read).with(@path).returns(content)
@searcher.find(@path)
@searcher.find(@request)
end
it "should create the model instance with the content as the only argument to initialization" do
@ -48,18 +50,18 @@ describe Puppet::Indirector::File do
File.expects(:exist?).with(@path).returns(true)
File.expects(:read).with(@path).returns(content)
@searcher.find(@path).should equal(file)
@searcher.find(@request).should equal(file)
end
it "should return nil if no file is found" do
File.expects(:exist?).with(@path).returns(false)
@searcher.find(@path).should be_nil
@searcher.find(@request).should be_nil
end
it "should fail intelligently if a found file cannot be read" do
File.expects(:exist?).with(@path).returns(true)
File.expects(:read).with(@path).raises(RuntimeError)
proc { @searcher.find(@path) }.should raise_error(Puppet::Error)
proc { @searcher.find(@request) }.should raise_error(Puppet::Error)
end
it "should use the path() method to calculate the path if it exists" do
@ -68,42 +70,39 @@ describe Puppet::Indirector::File do
end
File.expects(:exist?).with(@path.upcase).returns(false)
@searcher.find(@path)
@searcher.find(@request)
end
end
describe Puppet::Indirector::File, " when saving files" do
before do
@content = "my content"
@file = stub 'file', :content => @content, :path => @path, :name => @path
@request.stubs(:instance).returns @file
end
it "should provide a method to save file contents at a specified path" do
filehandle = mock 'file'
content = "my content"
File.expects(:directory?).with(@dir).returns(true)
File.expects(:open).with(@path, "w").yields(filehandle)
filehandle.expects(:print).with(content)
filehandle.expects(:print).with(@content)
file = stub 'file', :content => content, :path => @path, :name => @path
@searcher.save(file)
@searcher.save(@request)
end
it "should fail intelligently if the file's parent directory does not exist" do
File.expects(:directory?).with(@dir).returns(false)
file = stub 'file', :path => @path, :name => @path
proc { @searcher.save(file) }.should raise_error(Puppet::Error)
proc { @searcher.save(@request) }.should raise_error(Puppet::Error)
end
it "should fail intelligently if a file cannot be written" do
filehandle = mock 'file'
content = "my content"
File.expects(:directory?).with(@dir).returns(true)
File.expects(:open).with(@path, "w").yields(filehandle)
filehandle.expects(:print).with(content).raises(ArgumentError)
filehandle.expects(:print).with(@content).raises(ArgumentError)
file = stub 'file', :content => content, :path => @path, :name => @path
proc { @searcher.save(file) }.should raise_error(Puppet::Error)
proc { @searcher.save(@request) }.should raise_error(Puppet::Error)
end
it "should use the path() method to calculate the path if it exists" do
@ -111,48 +110,45 @@ describe Puppet::Indirector::File do
name.upcase
end
file = stub 'file', :name => "/yay"
# Reset the key to something without a parent dir, so no checks are necessary
@request.stubs(:key).returns "/my"
File.expects(:open).with("/YAY", "w")
@searcher.save(file)
File.expects(:open).with("/MY", "w")
@searcher.save(@request)
end
end
describe Puppet::Indirector::File, " when removing files" do
it "should provide a method to remove files at a specified path" do
file = stub 'file', :path => @path, :name => @path
File.expects(:exist?).with(@path).returns(true)
File.expects(:unlink).with(@path)
@searcher.destroy(file)
@searcher.destroy(@request)
end
it "should throw an exception if the file is not found" do
file = stub 'file', :path => @path, :name => @path
File.expects(:exist?).with(@path).returns(false)
proc { @searcher.destroy(file) }.should raise_error(Puppet::Error)
proc { @searcher.destroy(@request) }.should raise_error(Puppet::Error)
end
it "should fail intelligently if the file cannot be removed" do
file = stub 'file', :path => @path, :name => @path
File.expects(:exist?).with(@path).returns(true)
File.expects(:unlink).with(@path).raises(ArgumentError)
proc { @searcher.destroy(file) }.should raise_error(Puppet::Error)
proc { @searcher.destroy(@request) }.should raise_error(Puppet::Error)
end
it "should use the path() method to calculate the path if it exists" do
@searcher.meta_def(:path) do |name|
name.upcase
@searcher.meta_def(:path) do |thing|
thing.to_s.upcase
end
file = stub 'file', :name => "/yay"
File.expects(:exist?).with("/YAY").returns(true)
File.expects(:unlink).with("/YAY")
File.expects(:exist?).with("/MY/FILE").returns(true)
File.expects(:unlink).with("/MY/FILE")
@searcher.destroy(file)
@searcher.destroy(@request)
end
end
end
end

Просмотреть файл

@ -15,34 +15,38 @@ describe Puppet::Indirector::FileMetadata::File do
it "should be a subclass of the DirectFileServer terminus" do
Puppet::Indirector::FileMetadata::File.superclass.should equal(Puppet::Indirector::DirectFileServer)
end
end
describe Puppet::Indirector::FileMetadata::File, "when creating the instance for a single found file" do
before do
@metadata = Puppet::Indirector::FileMetadata::File.new
@uri = "file:///my/local"
@data = mock 'metadata'
@data.stubs(:collect_attributes)
FileTest.expects(:exists?).with("/my/local").returns true
describe "when creating the instance for a single found file" do
before do
@metadata = Puppet::Indirector::FileMetadata::File.new
@uri = "file:///my/local"
@data = mock 'metadata'
@data.stubs(:collect_attributes)
FileTest.expects(:exists?).with("/my/local").returns true
@request = stub 'request', :key => @uri, :options => {}
end
it "should collect its attributes when a file is found" do
@data.expects(:collect_attributes)
Puppet::FileServing::Metadata.expects(:new).returns(@data)
@metadata.find(@request).should == @data
end
end
it "should collect its attributes when a file is found" do
@data.expects(:collect_attributes)
describe "when searching for multiple files" do
before do
@metadata = Puppet::Indirector::FileMetadata::File.new
@uri = "file:///my/local"
Puppet::FileServing::Metadata.expects(:new).returns(@data)
@metadata.find(@uri).should == @data
end
end
describe Puppet::Indirector::FileMetadata::File, "when searching for multiple files" do
before do
@metadata = Puppet::Indirector::FileMetadata::File.new
@uri = "file:///my/local"
end
it "should collect the attributes of the instances returned" do
FileTest.expects(:exists?).with("/my/local").returns true
@metadata.expects(:path2instances).returns( [mock("one", :collect_attributes => nil), mock("two", :collect_attributes => nil)] )
@metadata.search(@uri)
@request = stub 'request', :key => @uri, :options => {}
end
it "should collect the attributes of the instances returned" do
FileTest.expects(:exists?).with("/my/local").returns true
@metadata.expects(:path2instances).returns( [mock("one", :collect_attributes => nil), mock("two", :collect_attributes => nil)] )
@metadata.search(@request)
end
end
end

Просмотреть файл

@ -165,4 +165,4 @@ describe Puppet::Indirector::FileServer do
@file_server.search(@uri, :testing => :one, :other => :two)
end
end
end
end

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -24,11 +24,13 @@ describe Puppet::Indirector::Ldap, " when searching ldap" do
@searcher.stubs(:search_filter).returns(:filter)
@searcher.stubs(:search_base).returns(:base)
@searcher.stubs(:process)
@request = stub 'request', :key => "yay"
end
it "should call the ldapsearch method with the name being searched for" do
@searcher.expects(:ldapsearch).with("yay")
@searcher.find "yay"
@searcher.find @request
end
it "should fail if no block is passed to the ldapsearch method" do
@ -41,7 +43,7 @@ describe Puppet::Indirector::Ldap, " when searching ldap" do
args[0].should == "mybase"
true
end
@searcher.find "yay"
@searcher.find @request
end
it "should default to the value of the :search_base setting as the result of the ldapbase method" do
@ -56,7 +58,7 @@ describe Puppet::Indirector::Ldap, " when searching ldap" do
args[3].should == :myattrs
true
end
@searcher.find "yay"
@searcher.find @request
end
it "should use the results of the :search_filter method as the search filter" do
@ -65,7 +67,7 @@ describe Puppet::Indirector::Ldap, " when searching ldap" do
args[2].should == "yay's filter"
true
end
@searcher.find "yay"
@searcher.find @request
end
it "should use depth 2 when searching" do
@ -73,13 +75,13 @@ describe Puppet::Indirector::Ldap, " when searching ldap" do
args[1].should == 2
true
end
@searcher.find "yay"
@searcher.find @request
end
it "should call process() on the first found entry" do
@connection.expects(:search).yields("myresult")
@searcher.expects(:process).with("yay", "myresult")
@searcher.find "yay"
@searcher.find @request
end
it "should reconnect and retry the search if there is a failure" do
@ -94,7 +96,7 @@ describe Puppet::Indirector::Ldap, " when searching ldap" do
end.yields("myresult")
@searcher.expects(:process).with("yay", "myresult")
@searcher.find "yay"
@searcher.find @request
end
it "should not reconnect on failure more than once" do
@ -103,7 +105,7 @@ describe Puppet::Indirector::Ldap, " when searching ldap" do
count += 1
raise ArgumentError, "yay"
end
proc { @searcher.find("whatever") }.should raise_error(Puppet::Error)
proc { @searcher.find(@request) }.should raise_error(Puppet::Error)
count.should == 2
end

Просмотреть файл

@ -3,33 +3,7 @@
require File.dirname(__FILE__) + '/../../spec_helper'
require 'puppet/indirector/memory'
describe "A Memory Terminus", :shared => true do
it "should find no instances by default" do
@searcher.find(@name).should be_nil
end
it "should be able to find instances that were previously saved" do
@searcher.save(@instance)
@searcher.find(@name).should equal(@instance)
end
it "should replace existing saved instances when a new instance with the same name is saved" do
@searcher.save(@instance)
two = stub 'second', :name => @name
@searcher.save(two)
@searcher.find(@name).should equal(two)
end
it "should be able to remove previously saved instances" do
@searcher.save(@instance)
@searcher.destroy(@instance)
@searcher.find(@name).should be_nil
end
it "should fail when asked to destroy an instance that does not exist" do
proc { @searcher.destroy(@instance) }.should raise_error(ArgumentError)
end
end
require 'shared_behaviours/memory_terminus'
describe Puppet::Indirector::Memory do
it_should_behave_like "A Memory Terminus"
@ -49,5 +23,7 @@ describe Puppet::Indirector::Memory do
@searcher = @memory_class.new
@name = "me"
@instance = stub 'instance', :name => @name
@request = stub 'request', :key => @name, :instance => @instance
end
end

Просмотреть файл

@ -11,12 +11,6 @@ describe Puppet::Node::Exec do
@searcher = Puppet::Node::Exec.new
end
it "should use the version of the facts as its version" do
version = mock 'version'
Puppet::Node::Facts.expects(:version).with("me").returns version
@searcher.version("me").should equal(version)
end
describe "when constructing the command to run" do
it "should use the external_node script as the command" do
Puppet.expects(:[]).with(:external_nodes).returns("/bin/echo")
@ -25,7 +19,7 @@ describe Puppet::Node::Exec do
it "should throw an exception if no external node command is set" do
Puppet.expects(:[]).with(:external_nodes).returns("none")
proc { @searcher.find("foo") }.should raise_error(ArgumentError)
proc { @searcher.find(stub('request', :key => "foo")) }.should raise_error(ArgumentError)
end
end
@ -40,34 +34,36 @@ describe Puppet::Node::Exec do
@searcher.meta_def(:execute) do |command|
return YAML.dump(result)
end
@request = stub 'request', :key => @name
end
it "should translate the YAML into a Node instance" do
# Use an empty hash
@searcher.find(@name).should equal(@node)
@searcher.find(@request).should equal(@node)
end
it "should set the resulting parameters as the node parameters" do
@result[:parameters] = {"a" => "b", "c" => "d"}
@node.expects(:parameters=).with "a" => "b", "c" => "d"
@searcher.find(@name)
@searcher.find(@request)
end
it "should set the resulting classes as the node classes" do
@result[:classes] = %w{one two}
@node.expects(:classes=).with %w{one two}
@searcher.find(@name)
@searcher.find(@request)
end
it "should merge the node's facts with its parameters" do
@node.expects(:fact_merge)
@searcher.find(@name)
@searcher.find(@request)
end
it "should set the node's environment if one is provided" do
@result[:environment] = "yay"
@node.expects(:environment=).with "yay"
@searcher.find(@name)
@searcher.find(@request)
end
end
end

Просмотреть файл

@ -5,13 +5,6 @@ require File.dirname(__FILE__) + '/../../../spec_helper'
require 'puppet/indirector/node/ldap'
describe Puppet::Node::Ldap do
it "should use the version of the facts as its version" do
@searcher = Puppet::Node::Ldap.new
version = mock 'version'
Puppet::Node::Facts.expects(:version).with("me").returns version
@searcher.version("me").should equal(version)
end
describe "when searching for nodes" do
before :each do
@searcher = Puppet::Node::Ldap.new
@ -31,16 +24,18 @@ describe Puppet::Node::Ldap do
@node.stubs(:fact_merge)
@name = "mynode"
Puppet::Node.stubs(:new).with(@name).returns(@node)
@request = stub 'request', :key => @name
end
it "should return nil if no results are found in ldap" do
@connection.stubs(:search)
@searcher.find("mynode").should be_nil
@searcher.find(@request).should be_nil
end
it "should return a node object if results are found in ldap" do
@entry.stubs(:to_hash).returns({})
@searcher.find("mynode").should equal(@node)
@searcher.find(@request).should equal(@node)
end
it "should deduplicate class values" do
@ -49,7 +44,7 @@ describe Puppet::Node::Ldap do
@entry.stubs(:vals).with("one").returns(%w{a b})
@entry.stubs(:vals).with("two").returns(%w{b c})
@node.expects(:classes=).with(%w{a b c})
@searcher.find("mynode")
@searcher.find(@request)
end
it "should add any values stored in the class_attributes attributes to the node classes" do
@ -58,38 +53,38 @@ describe Puppet::Node::Ldap do
@entry.stubs(:vals).with("one").returns(%w{a b})
@entry.stubs(:vals).with("two").returns(%w{c d})
@node.expects(:classes=).with(%w{a b c d})
@searcher.find("mynode")
@searcher.find(@request)
end
it "should add all entry attributes as node parameters" do
@entry.stubs(:to_hash).returns("one" => ["two"], "three" => ["four"])
@node.expects(:parameters=).with("one" => "two", "three" => "four")
@searcher.find("mynode")
@searcher.find(@request)
end
it "should set the node's environment to the environment of the results" do
@entry.stubs(:to_hash).returns("environment" => ["test"])
@node.stubs(:parameters=)
@node.expects(:environment=).with("test")
@searcher.find("mynode")
@searcher.find(@request)
end
it "should retain false parameter values" do
@entry.stubs(:to_hash).returns("one" => [false])
@node.expects(:parameters=).with("one" => false)
@searcher.find("mynode")
@searcher.find(@request)
end
it "should turn single-value parameter value arrays into single non-arrays" do
@entry.stubs(:to_hash).returns("one" => ["a"])
@node.expects(:parameters=).with("one" => "a")
@searcher.find("mynode")
@searcher.find(@request)
end
it "should keep multi-valued parametes as arrays" do
@entry.stubs(:to_hash).returns("one" => ["a", "b"])
@node.expects(:parameters=).with("one" => ["a", "b"])
@searcher.find("mynode")
@searcher.find(@request)
end
describe "and a parent node is specified" do
@ -113,7 +108,7 @@ describe Puppet::Node::Ldap do
@entry.stubs(:to_hash).returns({})
@entry.stubs(:vals).with(:parent).returns(%w{parent})
proc { @searcher.find("mynode") }.should raise_error(Puppet::Error)
proc { @searcher.find(@request) }.should raise_error(Puppet::Error)
end
it "should add any parent classes to the node's classes" do
@ -127,7 +122,7 @@ describe Puppet::Node::Ldap do
@searcher.stubs(:class_attributes).returns(%w{classes})
@node.expects(:classes=).with(%w{a b c d})
@searcher.find("mynode")
@searcher.find(@request)
end
it "should add any parent parameters to the node's parameters" do
@ -138,7 +133,7 @@ describe Puppet::Node::Ldap do
@parent.stubs(:vals).with(:parent).returns(nil)
@node.expects(:parameters=).with("one" => "two", "three" => "four")
@searcher.find("mynode")
@searcher.find(@request)
end
it "should prefer node parameters over parent parameters" do
@ -149,7 +144,7 @@ describe Puppet::Node::Ldap do
@parent.stubs(:vals).with(:parent).returns(nil)
@node.expects(:parameters=).with("one" => "two")
@searcher.find("mynode")
@searcher.find(@request)
end
it "should use the parent's environment if the node has none" do
@ -161,7 +156,7 @@ describe Puppet::Node::Ldap do
@node.stubs(:parameters=)
@node.expects(:environment=).with("parent")
@searcher.find("mynode")
@searcher.find(@request)
end
it "should prefer the node's environment to the parent's" do
@ -173,7 +168,7 @@ describe Puppet::Node::Ldap do
@node.stubs(:parameters=)
@node.expects(:environment=).with("child")
@searcher.find("mynode")
@searcher.find(@request)
end
it "should recursively look up parent information" do
@ -188,7 +183,7 @@ describe Puppet::Node::Ldap do
@parent_parent.stubs(:vals).with(:parent).returns(nil)
@node.expects(:parameters=).with("one" => "two", "three" => "four", "five" => "six")
@searcher.find("mynode")
@searcher.find(@request)
end
it "should not allow loops in parent declarations" do
@ -197,7 +192,7 @@ describe Puppet::Node::Ldap do
@parent.stubs(:to_hash).returns("three" => "four")
@parent.stubs(:vals).with(:parent).returns([@name])
proc { @searcher.find("mynode") }.should raise_error(ArgumentError)
proc { @searcher.find(@request) }.should raise_error(ArgumentError)
end
end
end

Просмотреть файл

@ -4,14 +4,15 @@ require File.dirname(__FILE__) + '/../../../spec_helper'
require 'puppet/indirector/node/memory'
# All of our behaviour is described here, so we always have to include it.
require File.dirname(__FILE__) + '/../memory'
require 'shared_behaviours/memory_terminus'
describe Puppet::Node::Memory do
before do
@name = "me"
@searcher = Puppet::Node::Memory.new
@instance = stub 'instance', :name => @name
@request = stub 'request', :key => @name, :instance => @instance
end
it_should_behave_like "A Memory Terminus"

Просмотреть файл

@ -13,12 +13,7 @@ describe Puppet::Node::Plain do
node = mock 'node'
Puppet::Node.expects(:new).with("mynode").returns(node)
node.expects(:fact_merge)
@searcher.find("mynode")
end
it "should use the version of the facts as its version" do
version = mock 'version'
Puppet::Node::Facts.expects(:version).with("me").returns version
@searcher.version("me").should equal(version)
request = stub 'request', :key => "mynode"
@searcher.find(request)
end
end

Просмотреть файл

@ -17,11 +17,13 @@ describe Puppet::Indirector::Plain do
end
@searcher = @plain_class.new
@request = stub 'request', :key => "yay"
end
it "should return return an instance of the indirected model" do
object = mock 'object'
@model.expects(:new).with("yay").returns object
@searcher.find("yay").should equal(object)
@model.expects(:new).with(@request.key).returns object
@searcher.find(@request).should equal(object)
end
end

Просмотреть файл

@ -13,7 +13,6 @@ describe Puppet::Transaction::Report::Processor do
end
end
describe Puppet::Transaction::Report::Processor, " when saving a report" do
before do
Puppet.settings.stubs(:use)
@ -24,7 +23,9 @@ describe Puppet::Transaction::Report::Processor, " when saving a report" do
Puppet::Reports.expects(:report).never
Puppet.settings.expects(:value).with(:reports).returns("none")
@reporter.save(:whatever)
request = stub 'request', :instance => mock("report")
@reporter.save(request)
end
it "should process the report with each configured report type" do
@ -44,6 +45,9 @@ describe Puppet::Transaction::Report::Processor, " when processing a report" do
@dup_report.stubs(:process)
@report = mock 'report'
@report.expects(:dup).returns(@dup_report)
@request = stub 'request', :instance => @report
Puppet::Reports.expects(:report).with("one").returns(@report_type)
@dup_report.expects(:extend).with(@report_type)
@ -53,21 +57,21 @@ describe Puppet::Transaction::Report::Processor, " when processing a report" do
# make sense to split it out, which means I just do the same test
# three times so the spec looks right.
it "should process a duplicate of the report, not the original" do
@reporter.save(@report)
@reporter.save(@request)
end
it "should extend the report with the report type's module" do
@reporter.save(@report)
@reporter.save(@request)
end
it "should call the report type's :process method" do
@dup_report.expects(:process)
@reporter.save(@report)
@reporter.save(@request)
end
it "should not raise exceptions" do
Puppet.settings.stubs(:value).with(:trace).returns(false)
@dup_report.expects(:process).raises(ArgumentError)
proc { @reporter.save(@report) }.should_not raise_error
proc { @reporter.save(@request) }.should_not raise_error
end
end

55
spec/unit/indirector/request.rb Executable file
Просмотреть файл

@ -0,0 +1,55 @@
#!/usr/bin/env ruby
require File.dirname(__FILE__) + '/../../spec_helper'
require 'puppet/indirector/request'
describe Puppet::Indirector::Request do
describe "when initializing" do
it "should require an indirection name, a key, and a method" do
lambda { Puppet::Indirector::Request.new }.should raise_error(ArgumentError)
end
it "should use provided value as the key if it is a string" do
Puppet::Indirector::Request.new(:ind, :method, "mykey").key.should == "mykey"
end
it "should use provided value as the key if it is a symbol" do
Puppet::Indirector::Request.new(:ind, :method, :mykey).key.should == :mykey
end
it "should use the name of the provided instance as its key if an instance is provided as the key instead of a string" do
instance = mock 'instance', :name => "mykey"
request = Puppet::Indirector::Request.new(:ind, :method, instance)
request.key.should == "mykey"
request.instance.should equal(instance)
end
it "should support options specified as a hash" do
lambda { Puppet::Indirector::Request.new(:ind, :method, :key, :one => :two) }.should_not raise_error(ArgumentError)
end
it "should support nil options" do
lambda { Puppet::Indirector::Request.new(:ind, :method, :key, nil) }.should_not raise_error(ArgumentError)
end
it "should support unspecified options" do
lambda { Puppet::Indirector::Request.new(:ind, :method, :key) }.should_not raise_error(ArgumentError)
end
it "should fail if options are specified as anything other than nil or a hash" do
lambda { Puppet::Indirector::Request.new(:ind, :method, :key, [:one, :two]) }.should raise_error(ArgumentError)
end
it "should use an empty options hash if nil was provided" do
Puppet::Indirector::Request.new(:ind, :method, :key, nil).options.should == {}
end
end
it "should look use the Indirection class to return the appropriate indirection" do
ind = mock 'indirection'
Puppet::Indirector::Indirection.expects(:instance).with(:myind).returns ind
request = Puppet::Indirector::Request.new(:myind, :method, :key)
request.indirection.should equal(ind)
end
end

Просмотреть файл

@ -106,60 +106,6 @@ describe Puppet::Indirector::Terminus do
@terminus.model.should == :yay
end
end
describe Puppet::Indirector::Terminus, " when managing indirected instances" do
it "should support comparing an instance's version with the terminus's version using just the instance's key" do
@terminus.should respond_to(:has_most_recent?)
end
it "should fail if the :version method has not been overridden and no :find method is available" do
proc { @terminus.version('yay') }.should raise_error(Puppet::DevError)
end
it "should use a found instance's version by default" do
name = 'instance'
instance = stub name, :version => 2
@terminus.expects(:find).with(name).returns(instance)
@terminus.version(name).should == 2
end
it "should return nil as the version if no instance can be found" do
name = 'instance'
@terminus.expects(:find).with(name).returns(nil)
@terminus.version(name).should be_nil
end
it "should consider an instance fresh if its version is more recent than the version provided" do
name = "yay"
@terminus.expects(:version).with(name).returns(5)
@terminus.has_most_recent?(name, 4).should be_true
end
it "should consider an instance fresh if its version is equal to the version provided" do
name = "yay"
@terminus.expects(:version).with(name).returns(5)
@terminus.has_most_recent?(name, 5).should be_true
end
it "should consider an instance not fresh if the provided version is more recent than its version" do
name = "yay"
@terminus.expects(:version).with(name).returns(4)
@terminus.has_most_recent?(name, 5).should be_false
end
# Times annoyingly can't be compared directly to numbers, and our
# default version is 0.
it "should convert versions to floats when checking for freshness" do
existing = mock 'existing version'
new = mock 'new version'
existing.expects(:to_f).returns(1.0)
new.expects(:to_f).returns(1.0)
name = "yay"
@terminus.expects(:version).with(name).returns(existing)
@terminus.has_most_recent?(name, new)
end
end
end
# LAK: This could reasonably be in the Indirection instances, too. It doesn't make

Просмотреть файл

@ -21,37 +21,28 @@ describe Puppet::Indirector::Yaml, " when choosing file location" do
@dir = "/what/ever"
Puppet.settings.stubs(:value).with(:yamldir).returns(@dir)
end
it "should use the mtime of the written file as the version" do
stat = mock 'stat'
FileTest.stubs(:exist?).returns true
File.expects(:stat).returns stat
time = Time.now
stat.expects(:mtime).returns time
@store.version(:me).should equal(time)
@request = stub 'request', :key => :me, :instance => @subject
end
describe Puppet::Indirector::Yaml, " when choosing file location" do
it "should store all files in a single file root set in the Puppet defaults" do
@store.send(:path, :me).should =~ %r{^#{@dir}}
@store.path(:me).should =~ %r{^#{@dir}}
end
it "should use the terminus name for choosing the subdirectory" do
@store.send(:path, :me).should =~ %r{^#{@dir}/my_yaml}
@store.path(:me).should =~ %r{^#{@dir}/my_yaml}
end
it "should use the object's name to determine the file name" do
@store.send(:path, :me).should =~ %r{me.yaml$}
@store.path(:me).should =~ %r{me.yaml$}
end
end
describe Puppet::Indirector::Yaml, " when storing objects as YAML" do
it "should only store objects that respond to :name" do
proc { @store.save(Object.new) }.should raise_error(ArgumentError)
@request.stubs(:instance).returns Object.new
proc { @store.save(@request) }.should raise_error(ArgumentError)
end
it "should convert Ruby objects to YAML and write them to disk" do
@ -62,7 +53,7 @@ describe Puppet::Indirector::Yaml, " when choosing file location" do
File.expects(:open).with(path, "w", 0660).yields(file)
file.expects(:print).with(yaml)
@store.save(@subject)
@store.save(@request)
end
it "should create the indirection subdirectory if it does not exist" do
@ -75,16 +66,11 @@ describe Puppet::Indirector::Yaml, " when choosing file location" do
File.expects(:open).with(path, "w", 0660).yields(file)
file.expects(:print).with(yaml)
@store.save(@subject)
@store.save(@request)
end
end
describe Puppet::Indirector::Yaml, " when retrieving YAML" do
it "should require the name of the object to retrieve" do
proc { @store.find(nil) }.should raise_error(ArgumentError)
end
it "should read YAML in from disk and convert it to Ruby objects" do
path = @store.send(:path, @subject.name)
@ -92,7 +78,7 @@ describe Puppet::Indirector::Yaml, " when choosing file location" do
FileTest.expects(:exist?).with(path).returns(true)
File.expects(:read).with(path).returns(yaml)
@store.find(@subject.name).instance_variable_get("@name").should == :me
@store.find(@request).instance_variable_get("@name").should == :me
end
it "should fail coherently when the stored YAML is invalid" do
@ -104,7 +90,7 @@ describe Puppet::Indirector::Yaml, " when choosing file location" do
FileTest.expects(:exist?).with(path).returns(true)
File.expects(:read).with(path).returns(yaml)
proc { @store.find(@subject.name) }.should raise_error(Puppet::Error)
proc { @store.find(@request) }.should raise_error(Puppet::Error)
end
end
end

Просмотреть файл

@ -1,6 +1,6 @@
#!/usr/bin/env ruby
require File.dirname(__FILE__) + '/../../spec_helper'
require File.dirname(__FILE__) + '/../spec_helper'
describe Puppet::Module, " when building its search path" do
include PuppetTest
@ -171,6 +171,15 @@ describe Puppet::Module, " when searching for manifests in a found module" do
Puppet::Module.find_manifests("mymod/yay/*.pp").should == %w{/one /two}
end
it "should not return directories" do
Puppet.settings.expects(:value).with(:modulepath, nil).returns("/my/modules")
File.stubs(:directory?).returns(true)
Dir.expects(:glob).with("/my/modules/mymod/manifests/yay/*.pp").returns(%w{/one /two})
FileTest.expects(:directory?).with("/one").returns false
FileTest.expects(:directory?).with("/two").returns true
Puppet::Module.find_manifests("mymod/yay/*.pp").should == %w{/one}
end
it "should default to the 'init.pp' file in the manifests directory" do
Puppet.settings.expects(:value).with(:modulepath, nil).returns("/my/modules")
File.stubs(:directory?).returns(true)

Просмотреть файл

@ -36,30 +36,6 @@ describe Puppet::Network::Client::Master, " when retrieving the catalog" do
proc { @client.getconfig }.should raise_error(Puppet::Network::ClientError)
end
it "should use the cached catalog if it is up to date" do
file = "/path/to/cachefile"
@client.stubs(:cachefile).returns(file)
FileTest.expects(:exist?).with(file).returns(true)
@client.expects(:fresh?).with(@facts).returns true
@client.class.stubs(:facts).returns(@facts)
@client.expects(:use_cached_config).returns(true)
Puppet.stubs(:info)
@client.getconfig
end
it "should log that the catalog does not need a recompile" do
file = "/path/to/cachefile"
@client.stubs(:cachefile).returns(file)
FileTest.stubs(:exist?).with(file).returns(true)
@client.stubs(:fresh?).with(@facts).returns true
@client.stubs(:use_cached_config).returns(true)
@client.class.stubs(:facts).returns(@facts)
Puppet.expects(:info).with { |m| m.include?("up to date") }
@client.getconfig
end
it "should retrieve plugins if :pluginsync is enabled" do
file = "/path/to/cachefile"
@client.stubs(:cachefile).returns(file)
@ -69,7 +45,6 @@ describe Puppet::Network::Client::Master, " when retrieving the catalog" do
@client.expects(:getplugins)
@client.stubs(:get_actual_config).returns(nil)
FileTest.stubs(:exist?).with(file).returns(true)
@client.stubs(:fresh?).with(@facts).returns true
@client.stubs(:use_cached_config).returns(true)
@client.class.stubs(:facts).returns(@facts)
@client.getconfig

Просмотреть файл

@ -133,9 +133,9 @@ end
describe Puppet::Node, " when indirecting" do
it "should redirect to the indirection" do
@indirection = mock 'indirection'
@indirection = stub 'indirection', :name => :node
Puppet::Node.stubs(:indirection).returns(@indirection)
@indirection.expects(:find).with(:my_node.to_s)
@indirection.expects(:find)
Puppet::Node.find(:my_node.to_s)
end

Просмотреть файл

@ -794,14 +794,14 @@ end
describe Puppet::Node::Catalog, " when indirecting" do
before do
@indirection = mock 'indirection'
@indirection = stub 'indirection', :name => :catalog
Puppet::Indirector::Indirection.clear_cache
end
it "should redirect to the indirection for retrieval" do
Puppet::Node::Catalog.stubs(:indirection).returns(@indirection)
@indirection.expects(:find).with(:myconfig)
@indirection.expects(:find)
Puppet::Node::Catalog.find(:myconfig)
end

Просмотреть файл

@ -6,7 +6,7 @@ require 'puppet/node/facts'
describe Puppet::Node::Facts, " when indirecting" do
before do
@indirection = mock 'indirection'
@indirection = stub 'indirection', :request => mock('request'), :name => :facts
# We have to clear the cache so that the facts ask for our indirection stub,
# instead of anything that might be cached.
@ -16,13 +16,13 @@ describe Puppet::Node::Facts, " when indirecting" do
it "should redirect to the specified fact store for retrieval" do
Puppet::Node::Facts.stubs(:indirection).returns(@indirection)
@indirection.expects(:find).with(:my_facts)
@indirection.expects(:find)
Puppet::Node::Facts.find(:my_facts)
end
it "should redirect to the specified fact store for storage" do
Puppet::Node::Facts.stubs(:indirection).returns(@indirection)
@indirection.expects(:save).with(@facts)
@indirection.expects(:save)
@facts.save
end

Просмотреть файл

@ -122,4 +122,4 @@ describe Puppet::Parser::AST::Node do
@compiler.class_scope(@middle).namespaces.should be_include(@top.namespace)
end
end
end
end

Просмотреть файл

@ -64,6 +64,13 @@ describe Puppet::Parser::Resource do
@resource[:one].should == "yay"
end
it "should have a method for converting to a ral resource" do
trans = mock 'trans', :to_type => "yay"
@resource = mkresource
@resource.expects(:to_trans).returns trans
@resource.to_type.should == "yay"
end
describe "when initializing" do
before do
@arguments = {:type => "resource", :title => "testing", :scope => stub('scope', :source => mock('source'))}

Просмотреть файл

@ -4,51 +4,59 @@ require File.dirname(__FILE__) + '/../../../spec_helper'
require 'puppet/external/nagios'
Nagios::Base.eachtype do |name, nagios_type|
puppet_type = Puppet::Type.type("nagios_" + name.to_s)
describe "Nagios resource types" do
Nagios::Base.eachtype do |name, nagios_type|
puppet_type = Puppet::Type.type("nagios_" + name.to_s)
describe puppet_type do
it "should be defined as a Puppet resource type" do
it "should have a valid type for #{name}" do
puppet_type.should_not be_nil
end
it "should have documentation" do
puppet_type.instance_variable_get("@doc").should_not == ""
end
next unless puppet_type
it "should have %s as its namevar" % nagios_type.namevar do
puppet_type.namevar.should == nagios_type.namevar
end
it "should have documentation for its %s parameter" % nagios_type.namevar do
puppet_type.attrclass(nagios_type.namevar).instance_variable_get("@doc").should_not be_nil
end
it "should have an ensure property" do
puppet_type.should be_validproperty(:ensure)
end
it "should have a target property" do
puppet_type.should be_validproperty(:target)
end
it "should have documentation for its target property" do
puppet_type.attrclass(:target).instance_variable_get("@doc").should_not be_nil
end
nagios_type.parameters.reject { |param| param == nagios_type.namevar or param.to_s =~ /^[0-9]/ }.each do |param|
it "should have a %s property" % param do
puppet_type.should be_validproperty(param)
describe puppet_type do
it "should be defined as a Puppet resource type" do
puppet_type.should_not be_nil
end
it "should have documentation for its %s property" % param do
puppet_type.attrclass(param).instance_variable_get("@doc").should_not be_nil
it "should have documentation" do
puppet_type.instance_variable_get("@doc").should_not == ""
end
end
nagios_type.parameters.find_all { |param| param.to_s =~ /^[0-9]/ }.each do |param|
it "should have not have a %s property" % param do
puppet_type.should_not be_validproperty(:param)
it "should have %s as its namevar" % nagios_type.namevar do
puppet_type.namevar.should == nagios_type.namevar
end
it "should have documentation for its %s parameter" % nagios_type.namevar do
puppet_type.attrclass(nagios_type.namevar).instance_variable_get("@doc").should_not be_nil
end
it "should have an ensure property" do
puppet_type.should be_validproperty(:ensure)
end
it "should have a target property" do
puppet_type.should be_validproperty(:target)
end
it "should have documentation for its target property" do
puppet_type.attrclass(:target).instance_variable_get("@doc").should_not be_nil
end
nagios_type.parameters.reject { |param| param == nagios_type.namevar or param.to_s =~ /^[0-9]/ }.each do |param|
it "should have a %s property" % param do
puppet_type.should be_validproperty(param)
end
it "should have documentation for its %s property" % param do
puppet_type.attrclass(param).instance_variable_get("@doc").should_not be_nil
end
end
nagios_type.parameters.find_all { |param| param.to_s =~ /^[0-9]/ }.each do |param|
it "should have not have a %s property" % param do
puppet_type.should_not be_validproperty(:param)
end
end
end
end

Просмотреть файл

@ -9,18 +9,18 @@ require 'puppet/transaction/report'
describe Puppet::Transaction::Report, " when being indirect" do
it "should redirect :find to the indirection" do
@indirection = mock 'indirection'
@indirection = stub 'indirection', :name => :report
Puppet::Transaction::Report.stubs(:indirection).returns(@indirection)
@indirection.expects(:find).with(:report)
@indirection.expects(:find)
Puppet::Transaction::Report.find(:report)
end
it "should redirect :save to the indirection" do
Facter.stubs(:value).returns("eh")
@indirection = mock 'indirection'
@indirection = stub 'indirection', :name => :report
Puppet::Transaction::Report.stubs(:indirection).returns(@indirection)
report = Puppet::Transaction::Report.new
@indirection.expects(:save).with(report)
@indirection.expects(:save)
report.save
end
@ -28,6 +28,12 @@ describe Puppet::Transaction::Report, " when being indirect" do
Puppet::Transaction::Report.indirection.terminus_class.should == :processor
end
it "should delegate its name attribute to its host method" do
report = Puppet::Transaction::Report.new
report.expects(:host).returns "me"
report.name.should == "me"
end
after do
Puppet::Indirector::Indirection.clear_cache
end

65
spec/unit/util/loadedfile.rb Executable file
Просмотреть файл

@ -0,0 +1,65 @@
#!/usr/bin/env ruby
require File.dirname(__FILE__) + '/../../spec_helper'
require 'tempfile'
require 'puppet/util/loadedfile'
describe Puppet::Util::LoadedFile do
before(:each) do
@f = Tempfile.new('loadedfile_test')
@f.puts "yayness"
@f.flush
@loaded = Puppet::Util::LoadedFile.new(@f.path)
fake_ctime = Time.now - (2 * Puppet[:filetimeout])
@stat = stub('stat', :ctime => fake_ctime)
@fake_now = Time.now + (2 * Puppet[:filetimeout])
end
it "should recognize when the file has not changed" do
# Use fake "now" so that we can be sure changed? actually checks, without sleeping
# for Puppet[:filetimeout] seconds.
Time.stubs(:now).returns(@fake_now)
@loaded.changed?.should == false
end
it "should recognize when the file has changed" do
# Fake File.stat so we don't have to depend on the filesystem granularity. Doing a flush()
# just didn't do the job.
File.stubs(:stat).returns(@stat)
# Use fake "now" so that we can be sure changed? actually checks, without sleeping
# for Puppet[:filetimeout] seconds.
Time.stubs(:now).returns(@fake_now)
@loaded.changed?.should be_an_instance_of(Time)
end
it "should not catch a change until the timeout has elapsed" do
# Fake File.stat so we don't have to depend on the filesystem granularity. Doing a flush()
# just didn't do the job.
File.stubs(:stat).returns(@stat)
@loaded.changed?.should be(false)
# Use fake "now" so that we can be sure changed? actually checks, without sleeping
# for Puppet[:filetimeout] seconds.
Time.stubs(:now).returns(@fake_now)
@loaded.changed?.should_not be(false)
end
it "should consider a file changed when that file is missing" do
@f.close!
# Use fake "now" so that we can be sure changed? actually checks, without sleeping
# for Puppet[:filetimeout] seconds.
Time.stubs(:now).returns(@fake_now)
@loaded.changed?.should_not be(false)
end
it "should disable checking if Puppet[:filetimeout] is negative" do
Puppet[:filetimeout] = -1
@loaded.changed?.should_not be(false)
end
after(:each) do
@f.close
end
end

Просмотреть файл

@ -1130,7 +1130,6 @@ file { "/tmp/yayness":
name = "sub"
mk_module(modname, :init => %w{separate}, :sub => %w{separate::sub})
Puppet.err :yay
# First try it with a namespace
klass = parser.findclass("separate", name)
assert_instance_of(AST::HostClass, klass, "Did not autoload sub class from separate file with a namespace")
@ -1160,6 +1159,14 @@ file { "/tmp/yayness":
klass = parser.findclass("", "alone::sub")
assert_instance_of(AST::HostClass, klass, "Did not autoload sub class from alone file with no namespace")
assert_equal("alone::sub", klass.classname, "Incorrect class was returned")
# and with the definition in its own file
name = "mymod"
mk_module(name, :define => true, :mydefine => ["mymod::mydefine"])
klass = parser.finddefine("", "mymod::mydefine")
assert_instance_of(AST::Definition, klass, "Did not autoload definition from its own file")
assert_equal("mymod::mydefine", klass.classname, "Incorrect definition was returned")
end
# Make sure class, node, and define methods are case-insensitive

Просмотреть файл

@ -1,2 +1,2 @@
# for backwards compatibility
require 'mocha'
require 'mocha'

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше