summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLuke Kanies <luke@madstop.com>2008-04-11 13:01:42 -0500
committerLuke Kanies <luke@madstop.com>2008-04-11 13:01:42 -0500
commitfb05ef3c96038d67a46eb142202af186ad6cb0b3 (patch)
tree148e8b882e5c8104c4f3fa8ecc4288e8608f812d
parentb49fb68f768e8b98c555ef0ae08a7bd22f5d36bd (diff)
parentb49fd495622b15f96faf944db1e70cbe9e7fe7c4 (diff)
downloadpuppet-fb05ef3c96038d67a46eb142202af186ad6cb0b3.tar.gz
puppet-fb05ef3c96038d67a46eb142202af186ad6cb0b3.tar.xz
puppet-fb05ef3c96038d67a46eb142202af186ad6cb0b3.zip
Merge branch '0.24.x'
-rw-r--r--CHANGELOG35
-rwxr-xr-xbin/pi2
-rwxr-xr-xbin/puppet2
-rwxr-xr-xbin/ralsh2
-rw-r--r--conf/redhat/client.init2
-rwxr-xr-xexamples/root/bin/sleeper2
-rw-r--r--ext/emacs/puppet-mode.el165
-rw-r--r--ext/ldap/puppet.schema2
-rwxr-xr-xext/module_puppet2
-rwxr-xr-xext/nagios/check_puppet.rb117
-rw-r--r--lib/puppet/defaults.rb2
-rw-r--r--lib/puppet/dsl.rb4
-rwxr-xr-xlib/puppet/external/nagios.rb2
-rwxr-xr-xlib/puppet/external/nagios/base.rb106
-rw-r--r--lib/puppet/file_serving/indirection_hooks.rb6
-rw-r--r--lib/puppet/file_serving/metadata.rb9
-rw-r--r--lib/puppet/indirector.rb54
-rw-r--r--lib/puppet/indirector/catalog/compiler.rb34
-rw-r--r--lib/puppet/indirector/checksum/file.rb4
-rw-r--r--lib/puppet/indirector/direct_file_server.rb14
-rw-r--r--lib/puppet/indirector/envelope.rb13
-rw-r--r--lib/puppet/indirector/exec.rb4
-rw-r--r--lib/puppet/indirector/facts/facter.rb4
-rw-r--r--lib/puppet/indirector/file.rb31
-rw-r--r--lib/puppet/indirector/file_metadata/file.rb4
-rw-r--r--lib/puppet/indirector/indirection.rb164
-rw-r--r--lib/puppet/indirector/ldap.rb4
-rw-r--r--lib/puppet/indirector/memory.rb14
-rw-r--r--lib/puppet/indirector/node/exec.rb13
-rw-r--r--lib/puppet/indirector/node/ldap.rb9
-rw-r--r--lib/puppet/indirector/node/plain.rb9
-rw-r--r--lib/puppet/indirector/plain.rb4
-rw-r--r--lib/puppet/indirector/report/processor.rb4
-rw-r--r--lib/puppet/indirector/request.rb25
-rw-r--r--lib/puppet/indirector/terminus.rb27
-rw-r--r--lib/puppet/indirector/yaml.rb28
-rw-r--r--lib/puppet/metatype/attributes.rb10
-rw-r--r--lib/puppet/module.rb2
-rw-r--r--lib/puppet/network/client/master.rb58
-rw-r--r--lib/puppet/network/handler/configuration.rb184
-rw-r--r--lib/puppet/network/handler/master.rb21
-rw-r--r--lib/puppet/network/xmlrpc/client.rb5
-rwxr-xr-xlib/puppet/node/facts.rb10
-rw-r--r--lib/puppet/parser/parser_support.rb8
-rw-r--r--lib/puppet/parser/resource.rb6
-rwxr-xr-xlib/puppet/provider/service/debian.rb2
-rw-r--r--lib/puppet/reference/report.rb23
-rw-r--r--lib/puppet/reports/rrdgraph.rb6
-rw-r--r--lib/puppet/transaction/report.rb4
-rwxr-xr-xlib/puppet/type/file/group.rb20
-rwxr-xr-xlib/puppet/type/mount.rb2
-rw-r--r--lib/puppet/type/nagios_hostescalation.rb3
-rw-r--r--lib/puppet/type/nagios_servicegroup.rb3
-rwxr-xr-xlib/puppet/type/user.rb3
-rwxr-xr-xlib/puppet/util/posix.rb4
-rwxr-xr-xspec/integration/checksum.rb2
-rwxr-xr-xspec/integration/indirector/direct_file_server.rb10
-rwxr-xr-xspec/integration/node.rb104
-rwxr-xr-xspec/integration/node/catalog.rb38
-rwxr-xr-xspec/integration/node/facts.rb45
-rwxr-xr-xspec/integration/transaction/report.rb26
-rw-r--r--spec/shared_behaviours/file_serving.rb12
-rw-r--r--spec/shared_behaviours/memory_terminus.rb32
-rwxr-xr-xspec/unit/file_serving/configuration.rb2
-rwxr-xr-xspec/unit/file_serving/configuration/parser.rb2
-rwxr-xr-xspec/unit/file_serving/indirection_hooks.rb204
-rwxr-xr-xspec/unit/indirector.rb85
-rwxr-xr-xspec/unit/indirector/catalog/compiler.rb87
-rwxr-xr-xspec/unit/indirector/checksum/file.rb21
-rwxr-xr-xspec/unit/indirector/direct_file_server.rb26
-rwxr-xr-xspec/unit/indirector/envelope.rb47
-rwxr-xr-xspec/unit/indirector/exec.rb18
-rwxr-xr-xspec/unit/indirector/facts/facter.rb10
-rwxr-xr-xspec/unit/indirector/file.rb64
-rwxr-xr-xspec/unit/indirector/file_metadata/file.rb50
-rwxr-xr-xspec/unit/indirector/file_server.rb2
-rwxr-xr-xspec/unit/indirector/indirection.rb1005
-rwxr-xr-xspec/unit/indirector/ldap.rb18
-rwxr-xr-xspec/unit/indirector/memory.rb30
-rwxr-xr-xspec/unit/indirector/node/exec.rb20
-rwxr-xr-xspec/unit/indirector/node/ldap.rb43
-rwxr-xr-xspec/unit/indirector/node/memory.rb5
-rwxr-xr-xspec/unit/indirector/node/plain.rb9
-rwxr-xr-xspec/unit/indirector/plain.rb6
-rwxr-xr-xspec/unit/indirector/report/processor.rb16
-rwxr-xr-xspec/unit/indirector/request.rb55
-rwxr-xr-xspec/unit/indirector/terminus.rb54
-rwxr-xr-xspec/unit/indirector/yaml.rb34
-rwxr-xr-xspec/unit/module.rb (renamed from spec/unit/other/modules.rb)11
-rwxr-xr-xspec/unit/network/client/master.rb25
-rwxr-xr-xspec/unit/node.rb4
-rwxr-xr-xspec/unit/node/catalog.rb4
-rwxr-xr-xspec/unit/node/facts.rb6
-rwxr-xr-xspec/unit/parser/ast/node.rb2
-rwxr-xr-xspec/unit/parser/resource.rb7
-rwxr-xr-xspec/unit/ral/type/nagios.rb70
-rwxr-xr-xspec/unit/transaction/report.rb14
-rwxr-xr-xspec/unit/util/loadedfile.rb65
-rwxr-xr-xtest/language/parser.rb9
-rw-r--r--test/lib/stubba.rb2
-rwxr-xr-xtest/network/client/master.rb110
-rwxr-xr-xtest/network/handler/configuration.rb160
-rwxr-xr-xtest/network/handler/master.rb53
-rwxr-xr-xtest/rails/host.rb37
-rwxr-xr-xtest/ral/type/user.rb6
105 files changed, 2091 insertions, 1973 deletions
diff --git a/CHANGELOG b/CHANGELOG
index 2bd81df45..224762771 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -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
diff --git a/bin/pi b/bin/pi
index 5416e693f..0b700a2d0 100755
--- a/bin/pi
+++ b/bin/pi
@@ -1,4 +1,4 @@
-#!/usr/bin/ruby
+#!/usr/bin/env ruby
#
# = Synopsis
diff --git a/bin/puppet b/bin/puppet
index 9e1102a3d..bb7308997 100755
--- a/bin/puppet
+++ b/bin/puppet
@@ -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
diff --git a/bin/ralsh b/bin/ralsh
index fdf64916f..1d0036717 100755
--- a/bin/ralsh
+++ b/bin/ralsh
@@ -1,4 +1,4 @@
-#!/usr/bin/ruby
+#!/usr/bin/env ruby
# vim: softtabstop=4 shiftwidth=4 expandtab
#
# = Synopsis
diff --git a/conf/redhat/client.init b/conf/redhat/client.init
index b63729aa3..b77bd017a 100644
--- a/conf/redhat/client.init
+++ b/conf/redhat/client.init
@@ -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
diff --git a/examples/root/bin/sleeper b/examples/root/bin/sleeper
index c22d13f40..980d66ac1 100755
--- a/examples/root/bin/sleeper
+++ b/examples/root/bin/sleeper
@@ -1,4 +1,4 @@
-#!/usr/bin/ruby -w
+#!/usr/bin/env ruby -w
###
# sleep indefinitely as a debug
diff --git a/ext/emacs/puppet-mode.el b/ext/emacs/puppet-mode.el
index f331474a9..0a7ee1a5f 100644
--- a/ext/emacs/puppet-mode.el
+++ b/ext/emacs/puppet-mode.el
@@ -5,56 +5,48 @@
;;; 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
- "Syntax table in use in puppet-mode buffers.")
+(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.")
-(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)
- )
+(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.")
(defcustom puppet-indent-tabs-mode nil
"*Indentation can insert tabs in puppet mode if this is non-nil."
@@ -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\\)\\)"
diff --git a/ext/ldap/puppet.schema b/ext/ldap/puppet.schema
index bbad23eab..d8dc4260d 100644
--- a/ext/ldap/puppet.schema
+++ b/ext/ldap/puppet.schema
@@ -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 )
diff --git a/ext/module_puppet b/ext/module_puppet
index 6a3f33fe6..e4a680e1b 100755
--- a/ext/module_puppet
+++ b/ext/module_puppet
@@ -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
diff --git a/ext/nagios/check_puppet.rb b/ext/nagios/check_puppet.rb
new file mode 100755
index 000000000..b65ede33a
--- /dev/null
+++ b/ext/nagios/check_puppet.rb
@@ -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
+
diff --git a/lib/puppet/defaults.rb b/lib/puppet/defaults.rb
index 0f01c2ee2..eed1a00f3 100644
--- a/lib/puppet/defaults.rb
+++ b/lib/puppet/defaults.rb
@@ -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
diff --git a/lib/puppet/dsl.rb b/lib/puppet/dsl.rb
index 966feaf9b..714b350f8 100644
--- a/lib/puppet/dsl.rb
+++ b/lib/puppet/dsl.rb
@@ -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'
diff --git a/lib/puppet/external/nagios.rb b/lib/puppet/external/nagios.rb
index 78459fcb6..0dcae4c6d 100755
--- a/lib/puppet/external/nagios.rb
+++ b/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
diff --git a/lib/puppet/external/nagios/base.rb b/lib/puppet/external/nagios/base.rb
index efc3982b4..25c689559 100755
--- a/lib/puppet/external/nagios/base.rb
+++ b/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 :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
+ 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
+ :dependent_service_description, :execution_failure_criteria,
+ :notification_failure_criteria, :hostgroup_name,
+ :dependent_hostgroup_name
setnamevar :host_name
- end
+ end
newtype :serviceescalation do
setparameters :host_name, :service_description, :first_notification,
- :last_notification, :contact_groups, :notification_interval
+ :last_notification, :contact_groups, :notification_interval, :hostgroup_name
setnamevar :host_name
end
- newtype :serviceextinfo do
+ 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$
diff --git a/lib/puppet/file_serving/indirection_hooks.rb b/lib/puppet/file_serving/indirection_hooks.rb
index 141642efe..66ed169dc 100644
--- a/lib/puppet/file_serving/indirection_hooks.rb
+++ b/lib/puppet/file_serving/indirection_hooks.rb
@@ -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
diff --git a/lib/puppet/file_serving/metadata.rb b/lib/puppet/file_serving/metadata.rb
index 56712122c..beecaef48 100644
--- a/lib/puppet/file_serving/metadata.rb
+++ b/lib/puppet/file_serving/metadata.rb
@@ -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
diff --git a/lib/puppet/indirector.rb b/lib/puppet/indirector.rb
index c30c097b2..2402b9cbe 100644
--- a/lib/puppet/indirector.rb
+++ b/lib/puppet/indirector.rb
@@ -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
-
- def destroy(*args)
- indirection.destroy(*args)
- end
+ # Expire any cached instance.
+ def expire(*args)
+ indirection.expire *args
+ end
+
+ def find(*args)
+ indirection.find *args
+ end
- def search(*args)
- indirection.search(*args)
- end
+ def destroy(*args)
+ indirection.destroy *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
diff --git a/lib/puppet/indirector/catalog/compiler.rb b/lib/puppet/indirector/catalog/compiler.rb
index 6d769b97d..2b5e8d912 100644
--- a/lib/puppet/indirector/catalog/compiler.rb
+++ b/lib/puppet/indirector/catalog/compiler.rb
@@ -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)
diff --git a/lib/puppet/indirector/checksum/file.rb b/lib/puppet/indirector/checksum/file.rb
index 3b196a1f8..5489b40e8 100644
--- a/lib/puppet/indirector/checksum/file.rb
+++ b/lib/puppet/indirector/checksum/file.rb
@@ -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)
diff --git a/lib/puppet/indirector/direct_file_server.rb b/lib/puppet/indirector/direct_file_server.rb
index 31cc9aa16..1711356f9 100644
--- a/lib/puppet/indirector/direct_file_server.rb
+++ b/lib/puppet/indirector/direct_file_server.rb
@@ -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
diff --git a/lib/puppet/indirector/envelope.rb b/lib/puppet/indirector/envelope.rb
new file mode 100644
index 000000000..ef7952ef6
--- /dev/null
+++ b/lib/puppet/indirector/envelope.rb
@@ -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
diff --git a/lib/puppet/indirector/exec.rb b/lib/puppet/indirector/exec.rb
index 7e4ac8d18..2462e31da 100644
--- a/lib/puppet/indirector/exec.rb
+++ b/lib/puppet/indirector/exec.rb
@@ -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
diff --git a/lib/puppet/indirector/facts/facter.rb b/lib/puppet/indirector/facts/facter.rb
index a8c47e3bf..465d90c13 100644
--- a/lib/puppet/indirector/facts/facter.rb
+++ b/lib/puppet/indirector/facts/facter.rb
@@ -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)
diff --git a/lib/puppet/indirector/file.rb b/lib/puppet/indirector/file.rb
index c2d36c46b..e5382155f 100644
--- a/lib/puppet/indirector/file.rb
+++ b/lib/puppet/indirector/file.rb
@@ -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
diff --git a/lib/puppet/indirector/file_metadata/file.rb b/lib/puppet/indirector/file_metadata/file.rb
index b36846bbe..c46015c38 100644
--- a/lib/puppet/indirector/file_metadata/file.rb
+++ b/lib/puppet/indirector/file_metadata/file.rb
@@ -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 }
diff --git a/lib/puppet/indirector/indirection.rb b/lib/puppet/indirector/indirection.rb
index d47433c60..15358a801 100644
--- a/lib/puppet/indirector/indirection.rb
+++ b/lib/puppet/indirector/indirection.rb
@@ -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,83 +172,124 @@ 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)
+
+ 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]
- check_authorization(:find, terminus_name, ([key] + args))
+ # 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
- end
- def destroy(*args)
- check_authorization(:destroy, terminus_class, args)
-
- terminus.destroy(*args)
+ return nil
end
- def search(*args)
- check_authorization(:search, terminus_class, args)
+ # Remove something via the terminus.
+ def destroy(key, *args)
+ request = request(:destroy, key, *args)
+ terminus = prepare(request)
- result = terminus.search(*args)
+ terminus.destroy(request)
- terminus().post_search(result) if terminus().respond_to?(:post_search)
+ if cache? and cached = cache.find(request(:find, key, *args))
+ # Reuse the existing request, since it's equivalent.
+ cache.destroy(request)
+ end
- result
+ nil
end
- # these become instance methods
- def save(instance, *args)
- check_authorization(:save, terminus_class, ([instance] + args))
+ # Search for more than one instance. Should always return an array.
+ def search(key, *args)
+ request = request(:search, key, *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)
+ 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 version(*args)
- terminus.version(*args)
+ # Save the instance in the appropriate terminus. This method is
+ # normally an instance method on the indirected class.
+ def save(instance, *args)
+ request = request(:save, instance, *args)
+ terminus = prepare(request)
+
+ # 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]
+
+ # 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
- 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]]
+ # 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.
diff --git a/lib/puppet/indirector/ldap.rb b/lib/puppet/indirector/ldap.rb
index fb883def6..07ad38933 100644
--- a/lib/puppet/indirector/ldap.rb
+++ b/lib/puppet/indirector/ldap.rb
@@ -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
diff --git a/lib/puppet/indirector/memory.rb b/lib/puppet/indirector/memory.rb
index 5bfcec95d..19acc14e2 100644
--- a/lib/puppet/indirector/memory.rb
+++ b/lib/puppet/indirector/memory.rb
@@ -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
diff --git a/lib/puppet/indirector/node/exec.rb b/lib/puppet/indirector/node/exec.rb
index dcfc625b2..52cbc370c 100644
--- a/lib/puppet/indirector/node/exec.rb
+++ b/lib/puppet/indirector/node/exec.rb
@@ -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
diff --git a/lib/puppet/indirector/node/ldap.rb b/lib/puppet/indirector/node/ldap.rb
index 73b5cdd70..6c41c18d4 100644
--- a/lib/puppet/indirector/node/ldap.rb
+++ b/lib/puppet/indirector/node/ldap.rb
@@ -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
diff --git a/lib/puppet/indirector/node/plain.rb b/lib/puppet/indirector/node/plain.rb
index 8058563e6..37ceb064d 100644
--- a/lib/puppet/indirector/node/plain.rb
+++ b/lib/puppet/indirector/node/plain.rb
@@ -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
diff --git a/lib/puppet/indirector/plain.rb b/lib/puppet/indirector/plain.rb
index 8bdf8469c..2caa0946d 100644
--- a/lib/puppet/indirector/plain.rb
+++ b/lib/puppet/indirector/plain.rb
@@ -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
diff --git a/lib/puppet/indirector/report/processor.rb b/lib/puppet/indirector/report/processor.rb
index fa2b7f36b..135f1649d 100644
--- a/lib/puppet/indirector/report/processor.rb
+++ b/lib/puppet/indirector/report/processor.rb
@@ -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
diff --git a/lib/puppet/indirector/request.rb b/lib/puppet/indirector/request.rb
new file mode 100644
index 000000000..68b7ee160
--- /dev/null
+++ b/lib/puppet/indirector/request.rb
@@ -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
diff --git a/lib/puppet/indirector/terminus.rb b/lib/puppet/indirector/terminus.rb
index 3015c8a37..22c56a4d2 100644
--- a/lib/puppet/indirector/terminus.rb
+++ b/lib/puppet/indirector/terminus.rb
@@ -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
diff --git a/lib/puppet/indirector/yaml.rb b/lib/puppet/indirector/yaml.rb
index 4dd29159e..23bca02b8 100644
--- a/lib/puppet/indirector/yaml.rb
+++ b/lib/puppet/indirector/yaml.rb
@@ -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
diff --git a/lib/puppet/metatype/attributes.rb b/lib/puppet/metatype/attributes.rb
index b83fcdd78..3f48f22ff 100644
--- a/lib/puppet/metatype/attributes.rb
+++ b/lib/puppet/metatype/attributes.rb
@@ -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
diff --git a/lib/puppet/module.rb b/lib/puppet/module.rb
index 54212710d..b86931664 100644
--- a/lib/puppet/module.rb
+++ b/lib/puppet/module.rb
@@ -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
diff --git a/lib/puppet/network/client/master.rb b/lib/puppet/network/client/master.rb
index 4c7fa5f5b..a2b6499bb 100644
--- a/lib/puppet/network/client/master.rb
+++ b/lib/puppet/network/client/master.rb
@@ -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)
diff --git a/lib/puppet/network/handler/configuration.rb b/lib/puppet/network/handler/configuration.rb
deleted file mode 100644
index 8168ce1d5..000000000
--- a/lib/puppet/network/handler/configuration.rb
+++ /dev/null
@@ -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
diff --git a/lib/puppet/network/handler/master.rb b/lib/puppet/network/handler/master.rb
index dabfaca50..851ccc7b2 100644
--- a/lib/puppet/network/handler/master.rb
+++ b/lib/puppet/network/handler/master.rb
@@ -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
diff --git a/lib/puppet/network/xmlrpc/client.rb b/lib/puppet/network/xmlrpc/client.rb
index f6a5e8db6..357a766a1 100644
--- a/lib/puppet/network/xmlrpc/client.rb
+++ b/lib/puppet/network/xmlrpc/client.rb
@@ -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
diff --git a/lib/puppet/node/facts.rb b/lib/puppet/node/facts.rb
index c60be3fcf..8ee90b4ac 100755
--- a/lib/puppet/node/facts.rb
+++ b/lib/puppet/node/facts.rb
@@ -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
diff --git a/lib/puppet/parser/parser_support.rb b/lib/puppet/parser/parser_support.rb
index b86a4792b..d70722fdd 100644
--- a/lib/puppet/parser/parser_support.rb
+++ b/lib/puppet/parser/parser_support.rb
@@ -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
diff --git a/lib/puppet/parser/resource.rb b/lib/puppet/parser/resource.rb
index 4b48ff6cf..d214a60ee 100644
--- a/lib/puppet/parser/resource.rb
+++ b/lib/puppet/parser/resource.rb
@@ -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)
diff --git a/lib/puppet/provider/service/debian.rb b/lib/puppet/provider/service/debian.rb
index f0f6fe1ef..da38c10a2 100755
--- a/lib/puppet/provider/service/debian.rb
+++ b/lib/puppet/provider/service/debian.rb
@@ -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
diff --git a/lib/puppet/reference/report.rb b/lib/puppet/reference/report.rb
new file mode 100644
index 000000000..be8e64751
--- /dev/null
+++ b/lib/puppet/reference/report.rb
@@ -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:
+"
diff --git a/lib/puppet/reports/rrdgraph.rb b/lib/puppet/reports/rrdgraph.rb
index 2611f0369..03d8a5bdd 100644
--- a/lib/puppet/reports/rrdgraph.rb
+++ b/lib/puppet/reports/rrdgraph.rb
@@ -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/
diff --git a/lib/puppet/transaction/report.rb b/lib/puppet/transaction/report.rb
index 56f8a602a..bd62ebbe6 100644
--- a/lib/puppet/transaction/report.rb
+++ b/lib/puppet/transaction/report.rb
@@ -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)
diff --git a/lib/puppet/type/file/group.rb b/lib/puppet/type/file/group.rb
index 5f7caf342..cc482ff31 100755
--- a/lib/puppet/type/file/group.rb
+++ b/lib/puppet/type/file/group.rb
@@ -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
diff --git a/lib/puppet/type/mount.rb b/lib/puppet/type/mount.rb
index ca8e27e17..e18630cc8 100755
--- a/lib/puppet/type/mount.rb
+++ b/lib/puppet/type/mount.rb
@@ -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."
diff --git a/lib/puppet/type/nagios_hostescalation.rb b/lib/puppet/type/nagios_hostescalation.rb
new file mode 100644
index 000000000..5d18af2a6
--- /dev/null
+++ b/lib/puppet/type/nagios_hostescalation.rb
@@ -0,0 +1,3 @@
+require 'puppet/util/nagios_maker'
+
+Puppet::Util::NagiosMaker.create_nagios_type :hostescalation
diff --git a/lib/puppet/type/nagios_servicegroup.rb b/lib/puppet/type/nagios_servicegroup.rb
new file mode 100644
index 000000000..fef669639
--- /dev/null
+++ b/lib/puppet/type/nagios_servicegroup.rb
@@ -0,0 +1,3 @@
+require 'puppet/util/nagios_maker'
+
+Puppet::Util::NagiosMaker.create_nagios_type :servicegroup
diff --git a/lib/puppet/type/user.rb b/lib/puppet/type/user.rb
index 98b6a63de..0b668395d 100755
--- a/lib/puppet/type/user.rb
+++ b/lib/puppet/type/user.rb
@@ -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
diff --git a/lib/puppet/util/posix.rb b/lib/puppet/util/posix.rb
index 0b1e1c2f2..8228734ef 100755
--- a/lib/puppet/util/posix.rb
+++ b/lib/puppet/util/posix.rb
@@ -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
diff --git a/spec/integration/checksum.rb b/spec/integration/checksum.rb
index cb187c656..c94f3e47e 100755
--- a/spec/integration/checksum.rb
+++ b/spec/integration/checksum.rb
@@ -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
diff --git a/spec/integration/indirector/direct_file_server.rb b/spec/integration/indirector/direct_file_server.rb
index 383486986..40b753a6c 100755
--- a/spec/integration/indirector/direct_file_server.rb
+++ b/spec/integration/indirector/direct_file_server.rb
@@ -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"
diff --git a/spec/integration/node.rb b/spec/integration/node.rb
index 631d4403e..b0375e743 100755
--- a/spec/integration/node.rb
+++ b/spec/integration/node.rb
@@ -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 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)
+ 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
diff --git a/spec/integration/node/catalog.rb b/spec/integration/node/catalog.rb
new file mode 100755
index 000000000..ca14c2ea8
--- /dev/null
+++ b/spec/integration/node/catalog.rb
@@ -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
diff --git a/spec/integration/node/facts.rb b/spec/integration/node/facts.rb
new file mode 100755
index 000000000..c2f876578
--- /dev/null
+++ b/spec/integration/node/facts.rb
@@ -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
diff --git a/spec/integration/transaction/report.rb b/spec/integration/transaction/report.rb
new file mode 100755
index 000000000..48e59f203
--- /dev/null
+++ b/spec/integration/transaction/report.rb
@@ -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
diff --git a/spec/shared_behaviours/file_serving.rb b/spec/shared_behaviours/file_serving.rb
index b5ab6b0fd..82f207243 100644
--- a/spec/shared_behaviours/file_serving.rb
+++ b/spec/shared_behaviours/file_serving.rb
@@ -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
diff --git a/spec/shared_behaviours/memory_terminus.rb b/spec/shared_behaviours/memory_terminus.rb
new file mode 100644
index 000000000..a00dc9f74
--- /dev/null
+++ b/spec/shared_behaviours/memory_terminus.rb
@@ -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
diff --git a/spec/unit/file_serving/configuration.rb b/spec/unit/file_serving/configuration.rb
index eecaefe5f..a0710e20d 100755
--- a/spec/unit/file_serving/configuration.rb
+++ b/spec/unit/file_serving/configuration.rb
@@ -221,4 +221,4 @@ describe Puppet::FileServing::Configuration do
@config.authorized?("/one/my/file").should be_false
end
end
-end \ No newline at end of file
+end
diff --git a/spec/unit/file_serving/configuration/parser.rb b/spec/unit/file_serving/configuration/parser.rb
index df2f629d5..93d30ca1c 100755
--- a/spec/unit/file_serving/configuration/parser.rb
+++ b/spec/unit/file_serving/configuration/parser.rb
@@ -132,4 +132,4 @@ describe Puppet::FileServing::Configuration::Parser do
@parser.parse
end
end
-end \ No newline at end of file
+end
diff --git a/spec/unit/file_serving/indirection_hooks.rb b/spec/unit/file_serving/indirection_hooks.rb
index 34614b7b8..160e3ff0a 100755
--- a/spec/unit/file_serving/indirection_hooks.rb
+++ b/spec/unit/file_serving/indirection_hooks.rb
@@ -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
+describe Puppet::FileServing::IndirectionHooks 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
- before do
- @object = Object.new
- @object.extend(Puppet::FileServing::IndirectionHooks)
-
- @modules = mock 'modules'
- @object.stubs(:terminus).with(:modules).returns(@modules)
- 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")
- 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
- 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 = stub 'request', :key => "http://myhost/blah", :options => {:node => "whatever"}
+ end
+
+ 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
+
+ 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)
+
+ @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
diff --git a/spec/unit/indirector.rb b/spec/unit/indirector.rb
index 1a5867c51..1efa7b2e5 100755
--- a/spec/unit/indirector.rb
+++ b/spec/unit/indirector.rb
@@ -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 delegate to the indirection" do
+ @indirection.expects(:save)
+ @instance.save
+ 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 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
diff --git a/spec/unit/indirector/catalog/compiler.rb b/spec/unit/indirector/catalog/compiler.rb
index a4a0acd58..083a9ced5 100755
--- a/spec/unit/indirector/catalog/compiler.rb
+++ b/spec/unit/indirector/catalog/compiler.rb
@@ -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
diff --git a/spec/unit/indirector/checksum/file.rb b/spec/unit/indirector/checksum/file.rb
index 4f8ee98b2..857d7b050 100755
--- a/spec/unit/indirector/checksum/file.rb
+++ b/spec/unit/indirector/checksum/file.rb
@@ -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 \ No newline at end of file
+end
diff --git a/spec/unit/indirector/direct_file_server.rb b/spec/unit/indirector/direct_file_server.rb
index 9f3652536..a8583716a 100755
--- a/spec/unit/indirector/direct_file_server.rb
+++ b/spec/unit/indirector/direct_file_server.rb
@@ -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 \ No newline at end of file
+end
diff --git a/spec/unit/indirector/envelope.rb b/spec/unit/indirector/envelope.rb
new file mode 100755
index 000000000..17c62023a
--- /dev/null
+++ b/spec/unit/indirector/envelope.rb
@@ -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
diff --git a/spec/unit/indirector/exec.rb b/spec/unit/indirector/exec.rb
index 3baf06629..e474de8b9 100755
--- a/spec/unit/indirector/exec.rb
+++ b/spec/unit/indirector/exec.rb
@@ -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"
diff --git a/spec/unit/indirector/facts/facter.rb b/spec/unit/indirector/facts/facter.rb
index 0974a60ec..225eb153b 100755
--- a/spec/unit/indirector/facts/facter.rb
+++ b/spec/unit/indirector/facts/facter.rb
@@ -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 \ No newline at end of file
+end
diff --git a/spec/unit/indirector/file.rb b/spec/unit/indirector/file.rb
index 37740f0d0..67ead4cdb 100755
--- a/spec/unit/indirector/file.rb
+++ b/spec/unit/indirector/file.rb
@@ -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)
-
- file = stub 'file', :content => content, :path => @path, :name => @path
+ filehandle.expects(:print).with(@content).raises(ArgumentError)
- 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 \ No newline at end of file
+end
diff --git a/spec/unit/indirector/file_metadata/file.rb b/spec/unit/indirector/file_metadata/file.rb
index 0a37a6895..9474620c7 100755
--- a/spec/unit/indirector/file_metadata/file.rb
+++ b/spec/unit/indirector/file_metadata/file.rb
@@ -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
- end
+ 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
- it "should collect its attributes when a file is found" do
- @data.expects(:collect_attributes)
+ @request = stub 'request', :key => @uri, :options => {}
+ end
- Puppet::FileServing::Metadata.expects(:new).returns(@data)
- @metadata.find(@uri).should == @data
- end
-end
+ it "should collect its attributes when a file is found" do
+ @data.expects(:collect_attributes)
-describe Puppet::Indirector::FileMetadata::File, "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(@request).should == @data
+ end
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)
+ describe "when searching for multiple files" do
+ before do
+ @metadata = Puppet::Indirector::FileMetadata::File.new
+ @uri = "file:///my/local"
+
+ @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
diff --git a/spec/unit/indirector/file_server.rb b/spec/unit/indirector/file_server.rb
index 974b95e0e..79be8cc29 100755
--- a/spec/unit/indirector/file_server.rb
+++ b/spec/unit/indirector/file_server.rb
@@ -165,4 +165,4 @@ describe Puppet::Indirector::FileServer do
@file_server.search(@uri, :testing => :one, :other => :two)
end
end
-end \ No newline at end of file
+end
diff --git a/spec/unit/indirector/indirection.rb b/spec/unit/indirector/indirection.rb
index fe456b61e..e8ab9633b 100755
--- a/spec/unit/indirector/indirection.rb
+++ b/spec/unit/indirector/indirection.rb
@@ -2,579 +2,730 @@
require File.dirname(__FILE__) + '/../../spec_helper'
-require 'puppet/indirector'
+require 'puppet/indirector/indirection'
+describe "Indirection Delegator", :shared => true do
+ it "should create a request object with the appropriate method name and all of the passed arguments" do
+ request = stub 'request', :options => {}
+ @indirection.expects(:request).with(@method, "mystuff", :one => :two).returns request
-describe Puppet::Indirector::Indirection, " when initializing" do
- # (LAK) I've no idea how to test this, really.
- it "should store a reference to itself before it consumes its options" do
- proc { @indirection = Puppet::Indirector::Indirection.new(Object.new, :testingness, :not_valid_option) }.should raise_error
- Puppet::Indirector::Indirection.instance(:testingness).should be_instance_of(Puppet::Indirector::Indirection)
- Puppet::Indirector::Indirection.instance(:testingness).delete
+ @terminus.stubs(@method)
+
+ @indirection.send(@method, "mystuff", :one => :two)
end
- it "should keep a reference to the indirecting model" do
- model = mock 'model'
- @indirection = Puppet::Indirector::Indirection.new(model, :myind)
- @indirection.model.should equal(model)
+ it "should let the :select_terminus method choose the terminus using the created request if the :select_terminus method is available" do
+ # Define the method, so our respond_to? hook matches.
+ class << @indirection
+ def select_terminus(request)
+ end
+ end
+
+ request = stub 'request', :key => "me", :options => {}
+
+ @indirection.stubs(:request).returns request
+
+ @indirection.expects(:select_terminus).with(request).returns :test_terminus
+
+ @indirection.stubs(:check_authorization)
+ @terminus.expects(@method)
+
+ @indirection.send(@method, "me")
end
- it "should set the name" do
- @indirection = Puppet::Indirector::Indirection.new(mock('model'), :myind)
- @indirection.name.should == :myind
+ it "should choose the terminus returned by the :terminus_class method if no :select_terminus method is available" do
+ @indirection.expects(:terminus_class).returns :test_terminus
+
+ @terminus.expects(@method)
+
+ @indirection.send(@method, "me")
end
- it "should require indirections to have unique names" do
- @indirection = Puppet::Indirector::Indirection.new(mock('model'), :test)
- proc { Puppet::Indirector::Indirection.new(:test) }.should raise_error(ArgumentError)
+ it "should let the appropriate terminus perform the lookup" do
+ @terminus.expects(@method).with { |r| r.is_a?(Puppet::Indirector::Request) }
+ @indirection.send(@method, "me")
end
+end
- it "should extend itself with any specified module" do
- mod = Module.new
- @indirection = Puppet::Indirector::Indirection.new(mock('model'), :test, :extend => mod)
- @indirection.metaclass.included_modules.should include(mod)
+describe "Delegation Authorizer", :shared => true do
+ before do
+ # So the :respond_to? turns out correctly.
+ class << @terminus
+ def authorized?
+ end
+ end
end
- after do
- @indirection.delete if defined? @indirection
+ it "should not check authorization if a node name is not provided" do
+ @terminus.expects(:authorized?).never
+ @terminus.stubs(@method)
+
+ # The quotes are necessary here, else it looks like a block.
+ @request.stubs(:options).returns({})
+ @indirection.send(@method, "/my/key")
end
-end
-describe Puppet::Indirector::Indirection do
- before :each do
- @indirection = Puppet::Indirector::Indirection.new(mock('model'), :test)
- @terminus = stub 'terminus', :has_most_recent? => false
- @indirection.stubs(:terminus).returns(@terminus)
- @indirection.stubs(:terminus_class).returns(:whatever)
- @instance = stub 'instance', :version => nil, :version= => nil, :name => "whatever"
- @name = :mything
+ it "should pass the request to the terminus's authorization method" do
+ @terminus.expects(:authorized?).with { |r| r.is_a?(Puppet::Indirector::Request) }.returns(true)
+ @terminus.stubs(@method)
+
+ @indirection.send(@method, "/my/key", :node => "mynode")
end
-
- describe Puppet::Indirector::Indirection, " when looking for a model instance" do
- it "should let the appropriate terminus perform the lookup" do
- @terminus.expects(:find).with(@name).returns(@instance)
- @indirection.find(@name).should == @instance
- end
+ it "should fail if authorization returns false" do
+ @terminus.expects(:authorized?).returns(false)
+ @terminus.stubs(@method)
+ proc { @indirection.send(@method, "/my/key", :node => "mynode") }.should raise_error(ArgumentError)
+ end
+
+ it "should continue if authorization returns true" do
+ @terminus.expects(:authorized?).returns(true)
+ @terminus.stubs(@method)
+ @indirection.send(@method, "/my/key", :node => "mynode")
+ end
+end
- it "should not attempt to set a timestamp if the terminus cannot find the instance" do
- @terminus.expects(:find).with(@name).returns(nil)
- proc { @indirection.find(@name) }.should_not raise_error
+describe Puppet::Indirector::Indirection do
+ describe "when initializing" do
+ # (LAK) I've no idea how to test this, really.
+ it "should store a reference to itself before it consumes its options" do
+ proc { @indirection = Puppet::Indirector::Indirection.new(Object.new, :testingness, :not_valid_option) }.should raise_error
+ Puppet::Indirector::Indirection.instance(:testingness).should be_instance_of(Puppet::Indirector::Indirection)
+ Puppet::Indirector::Indirection.instance(:testingness).delete
end
- it "should pass the instance to the :post_find hook if there is one" do
- class << @terminus
- def post_find
- end
- end
- @terminus.expects(:post_find).with(@instance)
- @terminus.expects(:find).with(@name).returns(@instance)
- @indirection.find(@name)
+ it "should keep a reference to the indirecting model" do
+ model = mock 'model'
+ @indirection = Puppet::Indirector::Indirection.new(model, :myind)
+ @indirection.model.should equal(model)
end
- end
-
- describe Puppet::Indirector::Indirection, " when removing a model instance" do
- it "should let the appropriate terminus remove the instance" do
- @terminus.expects(:destroy).with(@name).returns(@instance)
- @indirection.destroy(@name).should == @instance
+ it "should set the name" do
+ @indirection = Puppet::Indirector::Indirection.new(mock('model'), :myind)
+ @indirection.name.should == :myind
end
- end
- describe Puppet::Indirector::Indirection, " when searching for multiple model instances" do
+ it "should require indirections to have unique names" do
+ @indirection = Puppet::Indirector::Indirection.new(mock('model'), :test)
+ proc { Puppet::Indirector::Indirection.new(:test) }.should raise_error(ArgumentError)
+ end
- it "should let the appropriate terminus find the matching instances" do
- @terminus.expects(:search).with(@name).returns(@instance)
- @indirection.search(@name).should == @instance
+ it "should extend itself with any specified module" do
+ mod = Module.new
+ @indirection = Puppet::Indirector::Indirection.new(mock('model'), :test, :extend => mod)
+ @indirection.metaclass.included_modules.should include(mod)
end
- it "should pass the instances to the :post_search hook if there is one" do
- class << @terminus
- def post_search
- end
- end
- @terminus.expects(:post_search).with(@instance)
- @terminus.expects(:search).with(@name).returns(@instance)
- @indirection.search(@name)
+ after do
+ @indirection.delete if defined? @indirection
end
end
- describe Puppet::Indirector::Indirection, " when storing a model instance" do
+ describe "when an instance" do
+ before :each do
+ @terminus_class = mock 'terminus_class'
+ @terminus = mock 'terminus'
+ @terminus_class.stubs(:new).returns(@terminus)
+ @cache = mock 'cache'
+ @cache_class = mock 'cache_class'
+ Puppet::Indirector::Terminus.stubs(:terminus_class).with(:test, :cache_terminus).returns(@cache_class)
+ Puppet::Indirector::Terminus.stubs(:terminus_class).with(:test, :test_terminus).returns(@terminus_class)
+
+ @indirection = Puppet::Indirector::Indirection.new(mock('model'), :test)
+ @indirection.terminus_class = :test_terminus
+
+ @instance = stub 'instance', :expiration => nil, :expiration= => nil, :name => "whatever"
+ @name = :mything
- it "should let the appropriate terminus store the instance" do
- @terminus.expects(:save).with(@instance).returns(@instance)
- @indirection.save(@instance).should == @instance
+ #@request = stub 'instance', :key => "/my/key", :instance => @instance, :options => {}
+ @request = mock 'instance'
+ end
+
+ it "should allow setting the ttl" do
+ @indirection.ttl = 300
+ @indirection.ttl.should == 300
end
- end
-
- describe Puppet::Indirector::Indirection, " when handling instance versions" do
- it "should let the appropriate terminus perform the lookup" do
- @terminus.expects(:version).with(@name).returns(5)
- @indirection.version(@name).should == 5
+ it "should default to the :runinterval setting, converted to an integer, for its ttl" do
+ Puppet.settings.expects(:value).returns "1800"
+ @indirection.ttl.should == 1800
end
- it "should add versions to found instances that do not already have them" do
- @terminus.expects(:find).with(@name).returns(@instance)
- time = mock 'time'
- time.expects(:utc).returns(:mystamp)
- Time.expects(:now).returns(time)
- @instance.expects(:version=).with(:mystamp)
- @indirection.find(@name)
+ it "should calculate the current expiration by adding the TTL to the current time" do
+ @indirection.stubs(:ttl).returns(100)
+ now = Time.now
+ Time.stubs(:now).returns now
+ @indirection.expiration.should == (Time.now + 100)
end
- it "should add versions to saved instances that do not already have them" do
- time = mock 'time'
- time.expects(:utc).returns(:mystamp)
- Time.expects(:now).returns(time)
- @instance.expects(:version=).with(:mystamp)
- @terminus.stubs(:save)
- @indirection.save(@instance)
+ it "should have a method for creating an indirection request instance" do
+ @indirection.should respond_to(:request)
end
- # We've already tested this, basically, but...
- it "should use the current time in UTC for versions" do
- @instance.expects(:version=).with do |time|
- time.utc?
+ describe "creates a request" do
+ it "should create it with its name as the request's indirection name" do
+ Puppet::Indirector::Request.expects(:new).with { |name, *other| @indirection.name == name }
+ @indirection.request(:funtest, "yayness")
+ end
+
+ it "should require a method and key" do
+ Puppet::Indirector::Request.expects(:new).with { |name, method, key, *other| method == :funtest and key == "yayness" }
+ @indirection.request(:funtest, "yayness")
+ end
+
+ it "should support optional arguments" do
+ Puppet::Indirector::Request.expects(:new).with { |name, method, key, other| other == {:one => :two} }
+ @indirection.request(:funtest, "yayness", :one => :two)
+ end
+
+ it "should default to the arguments being nil" do
+ Puppet::Indirector::Request.expects(:new).with { |name, method, key, args| args.nil? }
+ @indirection.request(:funtest, "yayness")
+ end
+
+ it "should return the request" do
+ request = mock 'request'
+ Puppet::Indirector::Request.expects(:new).returns request
+ @indirection.request(:funtest, "yayness").should equal(request)
end
- @terminus.stubs(:save)
- @indirection.save(@instance)
end
- end
+
+ describe "and looking for a model instance" do
+ before { @method = :find }
+ it_should_behave_like "Indirection Delegator"
+ it_should_behave_like "Delegation Authorizer"
- describe Puppet::Indirector::Indirection, " when an authorization hook is present" do
+ it "should return the results of the delegation" do
+ @terminus.expects(:find).returns(@instance)
+ @indirection.find("me").should equal(@instance)
+ end
- before do
- # So the :respond_to? turns out right.
- class << @terminus
- def authorized?
+ it "should set the expiration date on any instances without one set" do
+ @terminus.stubs(:find).returns(@instance)
+
+ @indirection.expects(:expiration).returns :yay
+
+ @instance.expects(:expiration).returns(nil)
+ @instance.expects(:expiration=).with(:yay)
+
+ @indirection.find("/my/key")
+ end
+
+ it "should not override an already-set expiration date on returned instances" do
+ @terminus.stubs(:find).returns(@instance)
+
+ @indirection.expects(:expiration).never
+
+ @instance.expects(:expiration).returns(:yay)
+ @instance.expects(:expiration=).never
+
+ @indirection.find("/my/key")
+ end
+
+ describe "when caching is enabled" do
+ before do
+ @indirection.cache_class = :cache_terminus
+ @cache_class.expects(:new).returns(@cache)
+
+ @instance.stubs(:expired?).returns false
+ end
+
+ it "should first look in the cache for an instance" do
+ @terminus.stubs(:find).never
+ @cache.expects(:find).returns @instance
+
+ @indirection.find("/my/key")
+ end
+
+ it "should use a request to look in the cache for cached objects" do
+ @cache.expects(:find).with { |r| r.method == :find and r.key == "/my/key" }.returns @instance
+
+ @cache.stubs(:save)
+
+ @indirection.find("/my/key")
+ end
+
+ it "should return the cached object if it is not expired" do
+ @instance.stubs(:expired?).returns false
+
+ @cache.stubs(:find).returns @instance
+ @indirection.find("/my/key").should equal(@instance)
+ end
+
+ it "should send a debug log if it is using the cached object" do
+ Puppet.expects(:debug)
+ @cache.stubs(:find).returns @instance
+
+ @indirection.find("/my/key")
+ end
+
+ it "should not return the cached object if it is expired" do
+ @instance.stubs(:expired?).returns true
+
+ @cache.stubs(:find).returns @instance
+ @terminus.stubs(:find).returns nil
+ @indirection.find("/my/key").should be_nil
+ end
+
+ it "should send an info log if it is using the cached object" do
+ Puppet.expects(:info)
+ @instance.stubs(:expired?).returns true
+
+ @cache.stubs(:find).returns @instance
+ @terminus.stubs(:find).returns nil
+ @indirection.find("/my/key")
+ end
+
+ it "should cache any objects not retrieved from the cache" do
+ @cache.expects(:find).returns nil
+
+ @terminus.expects(:find).returns(@instance)
+ @cache.expects(:save)
+
+ @indirection.find("/my/key")
+ end
+
+ it "should use a request to look in the cache for cached objects" do
+ @cache.expects(:find).with { |r| r.method == :find and r.key == "/my/key" }.returns nil
+
+ @terminus.stubs(:find).returns(@instance)
+ @cache.stubs(:save)
+
+ @indirection.find("/my/key")
+ end
+
+ it "should cache the instance using a request with the instance set to the cached object" do
+ @cache.stubs(:find).returns nil
+
+ @terminus.stubs(:find).returns(@instance)
+
+ @cache.expects(:save).with { |r| r.method == :save and r.instance == @instance }
+
+ @indirection.find("/my/key")
+ end
+
+ it "should send an info log that the object is being cached" do
+ @cache.stubs(:find).returns nil
+
+ @terminus.stubs(:find).returns(@instance)
+ @cache.stubs(:save)
+
+ Puppet.expects(:info)
+
+ @indirection.find("/my/key")
end
end
end
- it "should not check authorization if a node name is not provided" do
- @terminus.expects(:authorized?).never
- @terminus.stubs(:find)
- @indirection.find("/my/key")
- end
+ describe "and storing a model instance" do
+ before { @method = :save }
- it "should fail while finding instances if authorization returns false" do
- @terminus.expects(:authorized?).with(:find, "/my/key", :node => "mynode").returns(false)
- @terminus.stubs(:find)
- proc { @indirection.find("/my/key", :node => "mynode") }.should raise_error(ArgumentError)
- end
+ it_should_behave_like "Indirection Delegator"
+ it_should_behave_like "Delegation Authorizer"
- it "should continue finding instances if authorization returns true" do
- @terminus.expects(:authorized?).with(:find, "/my/key", :node => "mynode").returns(true)
- @terminus.stubs(:find)
- @indirection.find("/my/key", :node => "mynode")
- end
+ it "should return nil" do
+ @terminus.stubs(:save)
+ @indirection.save(@instance).should be_nil
+ end
- it "should fail while saving instances if authorization returns false" do
- @terminus.expects(:authorized?).with(:save, :myinstance, :node => "mynode").returns(false)
- @terminus.stubs(:save)
- proc { @indirection.save(:myinstance, :node => "mynode") }.should raise_error(ArgumentError)
- end
+ describe "when caching is enabled" do
+ before do
+ @indirection.cache_class = :cache_terminus
+ @cache_class.expects(:new).returns(@cache)
- it "should continue saving instances if authorization returns true" do
- instance = stub 'instance', :version => 1.0, :name => "eh"
- @terminus.expects(:authorized?).with(:save, instance, :node => "mynode").returns(true)
- @terminus.stubs(:save)
- @indirection.save(instance, :node => "mynode")
- end
+ @instance.stubs(:expired?).returns false
+ end
- it "should fail while destroying instances if authorization returns false" do
- @terminus.expects(:authorized?).with(:destroy, "/my/key", :node => "mynode").returns(false)
- @terminus.stubs(:destroy)
- proc { @indirection.destroy("/my/key", :node => "mynode") }.should raise_error(ArgumentError)
- end
+ it "should use a request to save the object to the cache" do
+ request = stub 'request', :instance => @instance, :options => {}
- it "should continue destroying instances if authorization returns true" do
- instance = stub 'instance', :version => 1.0, :name => "eh"
- @terminus.expects(:authorized?).with(:destroy, instance, :node => "mynode").returns(true)
- @terminus.stubs(:destroy)
- @indirection.destroy(instance, :node => "mynode")
- end
+ @indirection.expects(:request).returns request
- it "should fail while searching for instances if authorization returns false" do
- @terminus.expects(:authorized?).with(:search, "/my/key", :node => "mynode").returns(false)
- @terminus.stubs(:search)
- proc { @indirection.search("/my/key", :node => "mynode") }.should raise_error(ArgumentError)
+ @cache.expects(:save).with(request)
+ @terminus.stubs(:save)
+ @indirection.save(@instance)
+ end
+ end
end
+
+ describe "and removing a model instance" do
+ before { @method = :destroy }
- it "should continue searching for instances if authorization returns true" do
- @terminus.expects(:authorized?).with(:search, "/my/key", :node => "mynode").returns(true)
- @terminus.stubs(:search)
- @indirection.search("/my/key", :node => "mynode")
- end
- end
+ it_should_behave_like "Indirection Delegator"
+ it_should_behave_like "Delegation Authorizer"
- after :each do
- @indirection.delete
- Puppet::Indirector::Indirection.clear_cache
- end
-end
+ it "should return nil" do
+ @terminus.stubs(:destroy)
+ @indirection.destroy("/my/key").should be_nil
+ end
+ describe "when caching is enabled" do
+ before do
+ @indirection.cache_class = :cache_terminus
+ @cache_class.expects(:new).returns(@cache)
-describe Puppet::Indirector::Indirection, " when managing indirection instances" do
- it "should allow an indirection to be retrieved by name" do
- @indirection = Puppet::Indirector::Indirection.new(mock('model'), :test)
- Puppet::Indirector::Indirection.instance(:test).should equal(@indirection)
- end
-
- it "should return nil when the named indirection has not been created" do
- Puppet::Indirector::Indirection.instance(:test).should be_nil
- end
+ @instance.stubs(:expired?).returns false
+ end
- it "should allow an indirection's model to be retrieved by name" do
- mock_model = mock('model')
- @indirection = Puppet::Indirector::Indirection.new(mock_model, :test)
- Puppet::Indirector::Indirection.model(:test).should equal(mock_model)
- end
-
- it "should return nil when no model matches the requested name" do
- Puppet::Indirector::Indirection.model(:test).should be_nil
- end
+ it "should use a request instance to search in and remove objects from the cache" do
+ destroy = stub 'destroy_request', :key => "/my/key", :options => {}
+ find = stub 'destroy_request', :key => "/my/key", :options => {}
- after do
- @indirection.delete if defined? @indirection
- end
-end
-
-describe Puppet::Indirector::Indirection, " when choosing the terminus class" do
- before do
- @indirection = Puppet::Indirector::Indirection.new(mock('model'), :test)
- @terminus = mock 'terminus'
- @terminus_class = stub 'terminus class', :new => @terminus
- Puppet::Indirector::Terminus.stubs(:terminus_class).with(:test, :default).returns(@terminus_class)
- end
+ @indirection.expects(:request).with(:destroy, "/my/key").returns destroy
+ @indirection.expects(:request).with(:find, "/my/key").returns find
- it "should choose the default terminus class if one is specified and no specific terminus class is provided" do
- @indirection.terminus_class = :default
- @indirection.terminus_class.should equal(:default)
- end
+ cached = mock 'cache'
- it "should use the provided Puppet setting if told to do so" do
- Puppet::Indirector::Terminus.stubs(:terminus_class).with(:test, :my_terminus).returns(mock("terminus_class2"))
- Puppet.settings.expects(:value).with(:my_setting).returns("my_terminus")
- @indirection.terminus_setting = :my_setting
- @indirection.terminus_class.should equal(:my_terminus)
- end
+ @cache.expects(:find).with(find).returns cached
+ @cache.expects(:destroy).with(destroy)
- it "should fail if the provided terminus class is not valid" do
- Puppet::Indirector::Terminus.stubs(:terminus_class).with(:test, :nosuchclass).returns(nil)
- proc { @indirection.terminus_class = :nosuchclass }.should raise_error(ArgumentError)
- end
-
- it "should fail if no terminus class is picked" do
- proc { @indirection.terminus_class }.should raise_error(Puppet::DevError)
- end
+ @terminus.stubs(:destroy)
- after do
- @indirection.delete if defined? @indirection
- end
-end
+ @indirection.destroy("/my/key")
+ end
+ end
+ end
-describe Puppet::Indirector::Indirection, " when specifying the terminus class to use" do
- before do
- @indirection = Puppet::Indirector::Indirection.new(mock('model'), :test)
- @terminus = mock 'terminus'
- @terminus_class = stub 'terminus class', :new => @terminus
- end
+ describe "and searching for multiple model instances" do
+ before { @method = :search }
- it "should allow specification of a terminus type" do
- @indirection.should respond_to(:terminus_class=)
- end
+ it_should_behave_like "Indirection Delegator"
+ it_should_behave_like "Delegation Authorizer"
- it "should fail to redirect if no terminus type has been specified" do
- proc { @indirection.find("blah") }.should raise_error(Puppet::DevError)
- end
+ it "should set the expiration date on any instances without one set" do
+ @terminus.stubs(:search).returns([@instance])
- it "should fail when the terminus class name is an empty string" do
- proc { @indirection.terminus_class = "" }.should raise_error(ArgumentError)
- end
+ @indirection.expects(:expiration).returns :yay
- it "should fail when the terminus class name is nil" do
- proc { @indirection.terminus_class = nil }.should raise_error(ArgumentError)
- end
+ @instance.expects(:expiration).returns(nil)
+ @instance.expects(:expiration=).with(:yay)
- it "should fail when the specified terminus class cannot be found" do
- Puppet::Indirector::Terminus.expects(:terminus_class).with(:test, :foo).returns(nil)
- proc { @indirection.terminus_class = :foo }.should raise_error(ArgumentError)
- end
+ @indirection.search("/my/key")
+ end
- it "should select the specified terminus class if a terminus class name is provided" do
- Puppet::Indirector::Terminus.expects(:terminus_class).with(:test, :foo).returns(@terminus_class)
- @indirection.terminus(:foo).should equal(@terminus)
- end
+ it "should not override an already-set expiration date on returned instances" do
+ @terminus.stubs(:search).returns([@instance])
- it "should use the configured terminus class if no terminus name is specified" do
- Puppet::Indirector::Terminus.stubs(:terminus_class).with(:test, :foo).returns(@terminus_class)
- @indirection.terminus_class = :foo
- @indirection.terminus().should equal(@terminus)
- end
+ @indirection.expects(:expiration).never
- after do
- @indirection.delete if defined? @indirection
- end
-end
+ @instance.expects(:expiration).returns(:yay)
+ @instance.expects(:expiration=).never
-describe Puppet::Indirector::Indirection, " when a select_terminus hook is available" do
- before do
- @indirection = Puppet::Indirector::Indirection.new(mock('model'), :test)
+ @indirection.search("/my/key")
+ end
- # And provide a select_terminus hook
- @indirection.meta_def(:select_terminus) do |uri|
- :other
+ it "should return the results of searching in the terminus" do
+ @terminus.expects(:search).returns([@instance])
+ @indirection.search("/my/key").should == [@instance]
+ end
end
- @terminus = mock 'terminus'
- @terminus_class = stub 'terminus class', :new => @terminus
+ describe "and expiring a model instance" do
+ describe "when caching is not enabled" do
+ it "should do nothing" do
+ @cache_class.expects(:new).never
- @other_terminus = mock 'other_terminus'
- @other_terminus_class = stub 'other_terminus_class', :new => @other_terminus
+ @indirection.expire("/my/key")
+ end
+ end
- @cache_terminus = mock 'cache_terminus'
- @cache_terminus_class = stub 'cache_terminus_class', :new => @cache_terminus
+ describe "when caching is enabled" do
+ before do
+ @indirection.cache_class = :cache_terminus
+ @cache_class.expects(:new).returns(@cache)
- Puppet::Indirector::Terminus.stubs(:terminus_class).with(:test, :foo).returns(@terminus_class)
- Puppet::Indirector::Terminus.stubs(:terminus_class).with(:test, :other).returns(@other_terminus_class)
- Puppet::Indirector::Terminus.stubs(:terminus_class).with(:test, :cache).returns(@cache_terminus_class)
+ @instance.stubs(:expired?).returns false
- # Set it to a default type.
- @indirection.terminus_class = :foo
+ @cached = stub 'cached', :expiration= => nil, :name => "/my/key"
+ end
- @uri = "full://url/path"
- @result = stub 'result', :version => 1.0
- end
+ it "should use a request to find within the cache" do
+ @cache.expects(:find).with { |r| r.is_a?(Puppet::Indirector::Request) and r.method == :find }
+ @indirection.expire("/my/key")
+ end
- it "should use the terminus name provided by passing the key to the :select_terminus hook when finding instances" do
- # Set up the expectation
- @other_terminus.expects(:find).with(@uri).returns(@result)
+ it "should do nothing if no such instance is cached" do
+ @cache.expects(:find).returns nil
- @indirection.find(@uri)
- end
+ @indirection.expire("/my/key")
+ end
- it "should use the terminus name provided by passing the key to the :select_terminus hook when testing if a cached instance is up to date" do
- @indirection.cache_class = :cache
+ it "should log that it is expiring any found instance" do
+ @cache.expects(:find).returns @cached
+ @cache.stubs(:save)
- @other_terminus.expects(:version).with(@uri).returns(2.0)
+ Puppet.expects(:info)
- @cache_terminus.expects(:has_most_recent?).with(@uri, 2.0).returns(true)
- @cache_terminus.expects(:find).returns(:whatever)
+ @indirection.expire("/my/key")
+ end
- @indirection.find(@uri).should == :whatever
- end
+ it "should set the cached instance's expiration to a time in the past" do
+ @cache.expects(:find).returns @cached
+ @cache.stubs(:save)
- it "should pass all arguments to the :select_terminus hook" do
- @indirection.expects(:select_terminus).with(@uri, :node => "johnny").returns(:other)
- @other_terminus.stubs(:find)
+ @cached.expects(:expiration=).with { |t| t < Time.now }
- @indirection.find(@uri, :node => "johnny")
- end
+ @indirection.expire("/my/key")
+ end
- it "should pass the original key to the terminus rather than a modified key" do
- # This is the same test as before
- @other_terminus.expects(:find).with(@uri).returns(@result)
- @indirection.find(@uri)
- end
+ it "should save the now expired instance back into the cache" do
+ @cache.expects(:find).returns @cached
- after do
- @indirection.delete if defined? @indirection
- end
-end
+ @cached.expects(:expiration=).with { |t| t < Time.now }
-describe Puppet::Indirector::Indirection, " when managing terminus instances" do
- before do
- @indirection = Puppet::Indirector::Indirection.new(mock('model'), :test)
- @terminus = mock 'terminus'
- @terminus_class = mock 'terminus class'
- Puppet::Indirector::Terminus.stubs(:terminus_class).with(:test, :foo).returns(@terminus_class)
- end
+ @cache.expects(:save)
- it "should create an instance of the chosen terminus class" do
- @terminus_class.stubs(:new).returns(@terminus)
- @indirection.terminus(:foo).should equal(@terminus)
- end
+ @indirection.expire("/my/key")
+ end
- it "should allow the clearance of cached terminus instances" do
- terminus1 = mock 'terminus1'
- terminus2 = mock 'terminus2'
- @terminus_class.stubs(:new).returns(terminus1, terminus2, ArgumentError)
- @indirection.terminus(:foo).should equal(terminus1)
- @indirection.class.clear_cache
- @indirection.terminus(:foo).should equal(terminus2)
- end
+ it "should use a request to save the expired resource to the cache" do
+ @cache.expects(:find).returns @cached
- # Make sure it caches the terminus.
- it "should return the same terminus instance each time for a given name" do
- @terminus_class.stubs(:new).returns(@terminus)
- @indirection.terminus(:foo).should equal(@terminus)
- @indirection.terminus(:foo).should equal(@terminus)
- end
+ @cached.expects(:expiration=).with { |t| t < Time.now }
- it "should not create a terminus instance until one is actually needed" do
- Puppet::Indirector.expects(:terminus).never
- indirection = Puppet::Indirector::Indirection.new(mock('model'), :lazytest)
- end
+ @cache.expects(:save).with { |r| r.is_a?(Puppet::Indirector::Request) and r.instance == @cached and r.method == :save }.returns(@cached)
- after do
- @indirection.delete
- Puppet::Indirector::Indirection.clear_cache
- end
-end
+ @indirection.expire("/my/key")
+ end
+ end
+ end
-describe Puppet::Indirector::Indirection, " when deciding whether to cache" do
- before do
- @indirection = Puppet::Indirector::Indirection.new(mock('model'), :test)
- @terminus = mock 'terminus'
- @terminus_class = mock 'terminus class'
- @terminus_class.stubs(:new).returns(@terminus)
- Puppet::Indirector::Terminus.stubs(:terminus_class).with(:test, :foo).returns(@terminus_class)
- @indirection.terminus_class = :foo
+ after :each do
+ @indirection.delete
+ Puppet::Indirector::Indirection.clear_cache
+ end
end
- it "should provide a method for setting the cache terminus class" do
- @indirection.should respond_to(:cache_class=)
- end
- it "should fail to cache if no cache type has been specified" do
- proc { @indirection.cache }.should raise_error(Puppet::DevError)
- end
+ describe "when managing indirection instances" do
+ it "should allow an indirection to be retrieved by name" do
+ @indirection = Puppet::Indirector::Indirection.new(mock('model'), :test)
+ Puppet::Indirector::Indirection.instance(:test).should equal(@indirection)
+ end
+
+ it "should return nil when the named indirection has not been created" do
+ Puppet::Indirector::Indirection.instance(:test).should be_nil
+ end
- it "should fail to set the cache class when the cache class name is an empty string" do
- proc { @indirection.cache_class = "" }.should raise_error(ArgumentError)
- end
+ it "should allow an indirection's model to be retrieved by name" do
+ mock_model = mock('model')
+ @indirection = Puppet::Indirector::Indirection.new(mock_model, :test)
+ Puppet::Indirector::Indirection.model(:test).should equal(mock_model)
+ end
+
+ it "should return nil when no model matches the requested name" do
+ Puppet::Indirector::Indirection.model(:test).should be_nil
+ end
- it "should fail to set the cache class when the cache class name is nil" do
- proc { @indirection.cache_class = nil }.should raise_error(ArgumentError)
+ after do
+ @indirection.delete if defined? @indirection
+ end
end
- it "should fail to set the cache class when the specified cache class cannot be found" do
- Puppet::Indirector::Terminus.expects(:terminus_class).with(:test, :foo).returns(nil)
- proc { @indirection.cache_class = :foo }.should raise_error(ArgumentError)
- end
+ describe "when routing to the correct the terminus class" do
+ before do
+ @indirection = Puppet::Indirector::Indirection.new(mock('model'), :test)
+ @terminus = mock 'terminus'
+ @terminus_class = stub 'terminus class', :new => @terminus
+ Puppet::Indirector::Terminus.stubs(:terminus_class).with(:test, :default).returns(@terminus_class)
+ end
- after do
- @indirection.delete
- Puppet::Indirector::Indirection.clear_cache
- end
-end
+ it "should fail if no terminus class can be picked" do
+ proc { @indirection.terminus_class }.should raise_error(Puppet::DevError)
+ end
-describe Puppet::Indirector::Indirection do
- before :each do
- Puppet.settings.stubs(:value).with("test_terminus").returns("test_terminus")
- @terminus_class = mock 'terminus_class'
- @terminus = mock 'terminus'
- @terminus_class.stubs(:new).returns(@terminus)
- @cache = mock 'cache'
- @cache_class = mock 'cache_class'
- Puppet::Indirector::Terminus.stubs(:terminus_class).with(:test, :cache_terminus).returns(@cache_class)
- Puppet::Indirector::Terminus.stubs(:terminus_class).with(:test, :test_terminus).returns(@terminus_class)
- @indirection = Puppet::Indirector::Indirection.new(mock('model'), :test)
- @indirection.terminus_class = :test_terminus
+ it "should choose the default terminus class if one is specified" do
+ @indirection.terminus_class = :default
+ @indirection.terminus_class.should equal(:default)
+ end
+
+ it "should use the provided Puppet setting if told to do so" do
+ Puppet::Indirector::Terminus.stubs(:terminus_class).with(:test, :my_terminus).returns(mock("terminus_class2"))
+ Puppet.settings.expects(:value).with(:my_setting).returns("my_terminus")
+ @indirection.terminus_setting = :my_setting
+ @indirection.terminus_class.should equal(:my_terminus)
+ end
+
+ it "should fail if the provided terminus class is not valid" do
+ Puppet::Indirector::Terminus.stubs(:terminus_class).with(:test, :nosuchclass).returns(nil)
+ proc { @indirection.terminus_class = :nosuchclass }.should raise_error(ArgumentError)
+ end
+
+ after do
+ @indirection.delete if defined? @indirection
+ end
end
- describe Puppet::Indirector::Indirection, " when managing the cache terminus" do
+ describe "when specifying the terminus class to use" do
+ before do
+ @indirection = Puppet::Indirector::Indirection.new(mock('model'), :test)
+ @terminus = mock 'terminus'
+ @terminus_class = stub 'terminus class', :new => @terminus
+ end
+
+ it "should allow specification of a terminus type" do
+ @indirection.should respond_to(:terminus_class=)
+ end
- it "should not create a cache terminus at initialization" do
- # This is weird, because all of the code is in the setup. If we got
- # new() called on the cache class, we'd get an exception here.
+ it "should fail to redirect if no terminus type has been specified" do
+ proc { @indirection.find("blah") }.should raise_error(Puppet::DevError)
end
- it "should reuse the cache terminus" do
- @cache_class.expects(:new).returns(@cache)
- Puppet.settings.stubs(:value).with("test_cache").returns("cache_terminus")
- @indirection.cache_class = :cache_terminus
- @indirection.cache.should equal(@cache)
- @indirection.cache.should equal(@cache)
+ it "should fail when the terminus class name is an empty string" do
+ proc { @indirection.terminus_class = "" }.should raise_error(ArgumentError)
end
- it "should remove the cache terminus when all other terminus instances are cleared" do
- cache2 = mock 'cache2'
- @cache_class.stubs(:new).returns(@cache, cache2)
- @indirection.cache_class = :cache_terminus
- @indirection.cache.should equal(@cache)
- @indirection.clear_cache
- @indirection.cache.should equal(cache2)
+ it "should fail when the terminus class name is nil" do
+ proc { @indirection.terminus_class = nil }.should raise_error(ArgumentError)
end
- end
- describe Puppet::Indirector::Indirection, " when saving and using a cache" do
+ it "should fail when the specified terminus class cannot be found" do
+ Puppet::Indirector::Terminus.expects(:terminus_class).with(:test, :foo).returns(nil)
+ proc { @indirection.terminus_class = :foo }.should raise_error(ArgumentError)
+ end
- before do
- @indirection.cache_class = :cache_terminus
- @cache_class.expects(:new).returns(@cache)
- @name = "testing"
- @instance = stub 'instance', :version => 5, :name => @name
+ it "should select the specified terminus class if a terminus class name is provided" do
+ Puppet::Indirector::Terminus.expects(:terminus_class).with(:test, :foo).returns(@terminus_class)
+ @indirection.terminus(:foo).should equal(@terminus)
end
- it "should not update the cache or terminus if the new object is not different" do
- @cache.expects(:has_most_recent?).with(@name, 5).returns(true)
- @indirection.save(@instance)
+ it "should use the configured terminus class if no terminus name is specified" do
+ Puppet::Indirector::Terminus.stubs(:terminus_class).with(:test, :foo).returns(@terminus_class)
+ @indirection.terminus_class = :foo
+ @indirection.terminus().should equal(@terminus)
end
- it "should update the original and the cache if the cached object is different" do
- @cache.expects(:has_most_recent?).with(@name, 5).returns(false)
- @terminus.expects(:save).with(@instance)
- @cache.expects(:save).with(@instance)
- @indirection.save(@instance)
+ after do
+ @indirection.delete if defined? @indirection
end
end
-
- describe Puppet::Indirector::Indirection, " when finding and using a cache" do
+ describe "when managing terminus instances" do
before do
- @indirection.cache_class = :cache_terminus
- @cache_class.expects(:new).returns(@cache)
+ @indirection = Puppet::Indirector::Indirection.new(mock('model'), :test)
+ @terminus = mock 'terminus'
+ @terminus_class = mock 'terminus class'
+ Puppet::Indirector::Terminus.stubs(:terminus_class).with(:test, :foo).returns(@terminus_class)
+ end
+
+ it "should create an instance of the chosen terminus class" do
+ @terminus_class.stubs(:new).returns(@terminus)
+ @indirection.terminus(:foo).should equal(@terminus)
end
- it "should return the cached object if the cache is up to date" do
- cached = mock 'cached object'
+ it "should allow the clearance of cached terminus instances" do
+ terminus1 = mock 'terminus1'
+ terminus2 = mock 'terminus2'
+ @terminus_class.stubs(:new).returns(terminus1, terminus2, ArgumentError)
+ @indirection.terminus(:foo).should equal(terminus1)
+ @indirection.class.clear_cache
+ @indirection.terminus(:foo).should equal(terminus2)
+ end
- name = "myobject"
+ # Make sure it caches the terminus.
+ it "should return the same terminus instance each time for a given name" do
+ @terminus_class.stubs(:new).returns(@terminus)
+ @indirection.terminus(:foo).should equal(@terminus)
+ @indirection.terminus(:foo).should equal(@terminus)
+ end
- @terminus.expects(:version).with(name).returns(1)
- @cache.expects(:has_most_recent?).with(name, 1).returns(true)
+ it "should not create a terminus instance until one is actually needed" do
+ Puppet::Indirector.expects(:terminus).never
+ indirection = Puppet::Indirector::Indirection.new(mock('model'), :lazytest)
+ end
- @cache.expects(:find).with(name).returns(cached)
+ after do
+ @indirection.delete
+ Puppet::Indirector::Indirection.clear_cache
+ end
+ end
+
+ describe "when deciding whether to cache" do
+ before do
+ @indirection = Puppet::Indirector::Indirection.new(mock('model'), :test)
+ @terminus = mock 'terminus'
+ @terminus_class = mock 'terminus class'
+ @terminus_class.stubs(:new).returns(@terminus)
+ Puppet::Indirector::Terminus.stubs(:terminus_class).with(:test, :foo).returns(@terminus_class)
+ @indirection.terminus_class = :foo
+ end
- @indirection.find(name).should equal(cached)
+ it "should provide a method for setting the cache terminus class" do
+ @indirection.should respond_to(:cache_class=)
end
- it "should return the original object if the cache is not up to date" do
- real = stub 'real object', :version => 1
+ it "should fail to cache if no cache type has been specified" do
+ proc { @indirection.cache }.should raise_error(Puppet::DevError)
+ end
- name = "myobject"
+ it "should fail to set the cache class when the cache class name is an empty string" do
+ proc { @indirection.cache_class = "" }.should raise_error(ArgumentError)
+ end
- @cache.stubs(:save)
- @cache.expects(:has_most_recent?).with(name, 1).returns(false)
- @terminus.expects(:version).with(name).returns(1)
+ it "should fail to set the cache class when the cache class name is nil" do
+ proc { @indirection.cache_class = nil }.should raise_error(ArgumentError)
+ end
- @terminus.expects(:find).with(name).returns(real)
+ it "should fail to set the cache class when the specified cache class cannot be found" do
+ Puppet::Indirector::Terminus.expects(:terminus_class).with(:test, :foo).returns(nil)
+ proc { @indirection.cache_class = :foo }.should raise_error(ArgumentError)
+ end
- @indirection.find(name).should equal(real)
+ after do
+ @indirection.delete
+ Puppet::Indirector::Indirection.clear_cache
end
+ end
- it "should cache any newly returned objects" do
- real = stub 'real object', :version => 1
+ describe "when using a cache" do
+ before :each do
+ Puppet.settings.stubs(:value).with("test_terminus").returns("test_terminus")
+ @terminus_class = mock 'terminus_class'
+ @terminus = mock 'terminus'
+ @terminus_class.stubs(:new).returns(@terminus)
+ @cache = mock 'cache'
+ @cache_class = mock 'cache_class'
+ Puppet::Indirector::Terminus.stubs(:terminus_class).with(:test, :cache_terminus).returns(@cache_class)
+ Puppet::Indirector::Terminus.stubs(:terminus_class).with(:test, :test_terminus).returns(@terminus_class)
+ @indirection = Puppet::Indirector::Indirection.new(mock('model'), :test)
+ @indirection.terminus_class = :test_terminus
+ end
- name = "myobject"
+ describe "and managing the cache terminus" do
+ it "should not create a cache terminus at initialization" do
+ # This is weird, because all of the code is in the setup. If we got
+ # new() called on the cache class, we'd get an exception here.
+ end
- @terminus.expects(:version).with(name).returns(1)
- @cache.expects(:has_most_recent?).with(name, 1).returns(false)
+ it "should reuse the cache terminus" do
+ @cache_class.expects(:new).returns(@cache)
+ Puppet.settings.stubs(:value).with("test_cache").returns("cache_terminus")
+ @indirection.cache_class = :cache_terminus
+ @indirection.cache.should equal(@cache)
+ @indirection.cache.should equal(@cache)
+ end
- @terminus.expects(:find).with(name).returns(real)
- @cache.expects(:save).with(real)
+ it "should remove the cache terminus when all other terminus instances are cleared" do
+ cache2 = mock 'cache2'
+ @cache_class.stubs(:new).returns(@cache, cache2)
+ @indirection.cache_class = :cache_terminus
+ @indirection.cache.should equal(@cache)
+ @indirection.clear_cache
+ @indirection.cache.should equal(cache2)
+ end
+ end
- @indirection.find(name).should equal(real)
+ describe "and saving" do
+ end
+
+ describe "and finding" do
+ end
+
+ after :each do
+ @indirection.delete
+ Puppet::Indirector::Indirection.clear_cache
end
- end
-
- after :each do
- @indirection.delete
- Puppet::Indirector::Indirection.clear_cache
end
end
diff --git a/spec/unit/indirector/ldap.rb b/spec/unit/indirector/ldap.rb
index 6712ccb4f..2599bcecf 100755
--- a/spec/unit/indirector/ldap.rb
+++ b/spec/unit/indirector/ldap.rb
@@ -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
diff --git a/spec/unit/indirector/memory.rb b/spec/unit/indirector/memory.rb
index c0fca6bd9..3b754a1eb 100755
--- a/spec/unit/indirector/memory.rb
+++ b/spec/unit/indirector/memory.rb
@@ -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
diff --git a/spec/unit/indirector/node/exec.rb b/spec/unit/indirector/node/exec.rb
index b67e0fe97..09f13ab90 100755
--- a/spec/unit/indirector/node/exec.rb
+++ b/spec/unit/indirector/node/exec.rb
@@ -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
diff --git a/spec/unit/indirector/node/ldap.rb b/spec/unit/indirector/node/ldap.rb
index 34456703d..a40698662 100755
--- a/spec/unit/indirector/node/ldap.rb
+++ b/spec/unit/indirector/node/ldap.rb
@@ -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
diff --git a/spec/unit/indirector/node/memory.rb b/spec/unit/indirector/node/memory.rb
index a924c6209..71e01d4f3 100755
--- a/spec/unit/indirector/node/memory.rb
+++ b/spec/unit/indirector/node/memory.rb
@@ -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"
diff --git a/spec/unit/indirector/node/plain.rb b/spec/unit/indirector/node/plain.rb
index 943af52b4..a595998a1 100755
--- a/spec/unit/indirector/node/plain.rb
+++ b/spec/unit/indirector/node/plain.rb
@@ -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
diff --git a/spec/unit/indirector/plain.rb b/spec/unit/indirector/plain.rb
index 1277739af..aca2816f2 100755
--- a/spec/unit/indirector/plain.rb
+++ b/spec/unit/indirector/plain.rb
@@ -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
diff --git a/spec/unit/indirector/report/processor.rb b/spec/unit/indirector/report/processor.rb
index 587f512ee..bcb400bda 100755
--- a/spec/unit/indirector/report/processor.rb
+++ b/spec/unit/indirector/report/processor.rb
@@ -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
diff --git a/spec/unit/indirector/request.rb b/spec/unit/indirector/request.rb
new file mode 100755
index 000000000..cdb40b181
--- /dev/null
+++ b/spec/unit/indirector/request.rb
@@ -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
diff --git a/spec/unit/indirector/terminus.rb b/spec/unit/indirector/terminus.rb
index 86813e4e5..3fcbf9d0c 100755
--- a/spec/unit/indirector/terminus.rb
+++ b/spec/unit/indirector/terminus.rb
@@ -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
diff --git a/spec/unit/indirector/yaml.rb b/spec/unit/indirector/yaml.rb
index 339529ab0..53d12f426 100755
--- a/spec/unit/indirector/yaml.rb
+++ b/spec/unit/indirector/yaml.rb
@@ -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
diff --git a/spec/unit/other/modules.rb b/spec/unit/module.rb
index 26ca3907d..06b2d016d 100755
--- a/spec/unit/other/modules.rb
+++ b/spec/unit/module.rb
@@ -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)
diff --git a/spec/unit/network/client/master.rb b/spec/unit/network/client/master.rb
index 7bf755d88..c0ad7562f 100755
--- a/spec/unit/network/client/master.rb
+++ b/spec/unit/network/client/master.rb
@@ -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
diff --git a/spec/unit/node.rb b/spec/unit/node.rb
index bb99378d9..348e160cf 100755
--- a/spec/unit/node.rb
+++ b/spec/unit/node.rb
@@ -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
diff --git a/spec/unit/node/catalog.rb b/spec/unit/node/catalog.rb
index d607b3540..8d7692442 100755
--- a/spec/unit/node/catalog.rb
+++ b/spec/unit/node/catalog.rb
@@ -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
diff --git a/spec/unit/node/facts.rb b/spec/unit/node/facts.rb
index 743a7082e..1bfccd32e 100755
--- a/spec/unit/node/facts.rb
+++ b/spec/unit/node/facts.rb
@@ -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
diff --git a/spec/unit/parser/ast/node.rb b/spec/unit/parser/ast/node.rb
index 757934415..aaba4c2e8 100755
--- a/spec/unit/parser/ast/node.rb
+++ b/spec/unit/parser/ast/node.rb
@@ -122,4 +122,4 @@ describe Puppet::Parser::AST::Node do
@compiler.class_scope(@middle).namespaces.should be_include(@top.namespace)
end
end
-end \ No newline at end of file
+end
diff --git a/spec/unit/parser/resource.rb b/spec/unit/parser/resource.rb
index 776e9c742..6b2021916 100755
--- a/spec/unit/parser/resource.rb
+++ b/spec/unit/parser/resource.rb
@@ -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'))}
diff --git a/spec/unit/ral/type/nagios.rb b/spec/unit/ral/type/nagios.rb
index 8aca7d401..35f00b0e5 100755
--- a/spec/unit/ral/type/nagios.rb
+++ b/spec/unit/ral/type/nagios.rb
@@ -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
+ 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 parameter" % nagios_type.namevar do
- puppet_type.attrclass(nagios_type.namevar).instance_variable_get("@doc").should_not be_nil
- end
+ it "should have documentation" do
+ puppet_type.instance_variable_get("@doc").should_not == ""
+ end
- it "should have an ensure property" do
- puppet_type.should be_validproperty(:ensure)
- end
+ it "should have %s as its namevar" % nagios_type.namevar do
+ puppet_type.namevar.should == nagios_type.namevar
+ end
- it "should have a target property" do
- puppet_type.should be_validproperty(:target)
- 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 documentation for its target property" do
- puppet_type.attrclass(:target).instance_variable_get("@doc").should_not be_nil
- end
+ it "should have an ensure property" do
+ puppet_type.should be_validproperty(:ensure)
+ 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)
+ it "should have a target property" do
+ puppet_type.should be_validproperty(:target)
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 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
- 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)
+ 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
diff --git a/spec/unit/transaction/report.rb b/spec/unit/transaction/report.rb
index 8fc3f0794..644f8d709 100755
--- a/spec/unit/transaction/report.rb
+++ b/spec/unit/transaction/report.rb
@@ -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
diff --git a/spec/unit/util/loadedfile.rb b/spec/unit/util/loadedfile.rb
new file mode 100755
index 000000000..083120e20
--- /dev/null
+++ b/spec/unit/util/loadedfile.rb
@@ -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
diff --git a/test/language/parser.rb b/test/language/parser.rb
index f7e7d8762..effb2d40c 100755
--- a/test/language/parser.rb
+++ b/test/language/parser.rb
@@ -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
diff --git a/test/lib/stubba.rb b/test/lib/stubba.rb
index eade747f6..747054cfc 100644
--- a/test/lib/stubba.rb
+++ b/test/lib/stubba.rb
@@ -1,2 +1,2 @@
# for backwards compatibility
-require 'mocha' \ No newline at end of file
+require 'mocha'
diff --git a/test/network/client/master.rb b/test/network/client/master.rb
index 682d48eb5..c0d14ccee 100755
--- a/test/network/client/master.rb
+++ b/test/network/client/master.rb
@@ -305,44 +305,6 @@ end
assert_equal(RUBY_VERSION, facts["rubyversion"], "ruby version did not get added")
end
- # #424
- def test_caching_of_compile_time
- file = tempfile()
- manifest = tempfile()
- File.open(manifest, "w") { |f| f.puts "file { '#{file}': content => yay }" }
-
- Puppet::Node::Facts.indirection.stubs(:save)
-
- driver = mkmaster(:Manifest => manifest)
- driver.local = false
- master = mkclient(driver)
-
- # We have to make everything thinks it's remote, because there's no local caching info
- master.local = false
-
- assert(! master.fresh?(master.class.facts),
- "Considered fresh with no compile at all")
-
- assert_nothing_raised { master.run }
- assert(master.fresh?(master.class.facts),
- "not considered fresh after compile")
-
- # Now make sure the config time is cached
- assert(master.compile_time, "No stored config time")
- assert_equal(master.compile_time, Puppet::Util::Storage.cache(:configuration)[:compile_time], "times did not match")
- time = master.compile_time
- master.clear
- File.unlink(file)
- Puppet::Util::Storage.store
-
- # Now make a new master
- Puppet::Util::Storage.clear
- master = mkclient(driver)
- master.run
- assert_equal(time, master.compile_time, "time was not retrieved from cache")
- assert(FileTest.exists?(file), "file was not created on second run")
- end
-
# #540 - make sure downloads aren't affected by noop
def test_download_in_noop
source = tempfile
@@ -384,44 +346,6 @@ end
"Tried to load cache when it is non-existent")
end
- # #519 - cache the facts so that we notice if they change.
- def test_factchanges_cause_recompile
- $value = "one"
- Facter.add(:testfact) do
- setcode { $value }
- end
- assert_equal("one", Facter.value(:testfact), "fact was not set correctly")
- master = mkclient
- master.local = false
- driver = master.send(:instance_variable_get, "@driver")
- driver.local = false
-
- Puppet::Node::Facts.indirection.stubs(:save)
-
- assert_nothing_raised("Could not compile config") do
- master.getconfig
- end
-
- $value = "two"
- Facter.clear
- Facter.loadfacts
- Facter.add(:testfact) do
- setcode { $value }
- end
- facts = master.class.facts
- assert_equal("two", Facter.value(:testfact), "fact did not change")
-
- assert(master.send(:facts_changed?, facts),
- "master does not think facts changed")
- assert(! master.fresh?(facts),
- "master is considered fresh after facts changed")
-
- assert_nothing_raised("Could not recompile when facts changed") do
- master.getconfig
- end
-
- end
-
def test_locking
master = mkclient
@@ -455,40 +379,6 @@ end
assert_equal(100, master.timeout, "Did not get changed integer default value for timeout on second run")
end
- # #569 -- Make sure we can ignore dynamic facts.
- def test_dynamic_facts
- client = mkclient
-
- assert_equal(%w{memorysize memoryfree swapsize swapfree}, client.class.dynamic_facts,
- "Did not get correct defaults for dynamic facts")
-
- # Cache some values for comparison
- cached = {"one" => "yep", "two" => "nope"}
- Puppet::Util::Storage.cache(:configuration)[:facts] = cached
-
- assert(! client.send(:facts_changed?, cached), "Facts incorrectly considered to be changed")
-
- # Now add some values to the passed result and make sure we get a positive
- newfacts = cached.dup
- newfacts["changed"] = "something"
-
- assert(client.send(:facts_changed?, newfacts), "Did not catch changed fact")
-
- # Now add a dynamic fact and make sure it's ignored
- newfacts = cached.dup
- newfacts["memorysize"] = "something"
-
- assert(! client.send(:facts_changed?, newfacts), "Dynamic facts resulted in a false positive")
-
- # And try it with both
- cached["memorysize"] = "something else"
- assert(! client.send(:facts_changed?, newfacts), "Dynamic facts resulted in a false positive")
-
- # And finally, with only in the cache
- newfacts.delete("memorysize")
- assert(! client.send(:facts_changed?, newfacts), "Dynamic facts resulted in a false positive")
- end
-
def test_splay
client = mkclient
diff --git a/test/network/handler/configuration.rb b/test/network/handler/configuration.rb
deleted file mode 100755
index 36c5d9e54..000000000
--- a/test/network/handler/configuration.rb
+++ /dev/null
@@ -1,160 +0,0 @@
-#!/usr/bin/env ruby
-
-require File.dirname(__FILE__) + '/../../lib/puppettest'
-
-require 'puppettest'
-require 'puppet/network/handler/configuration'
-
-class TestHandlerConfiguration < Test::Unit::TestCase
- include PuppetTest
-
- Config = Puppet::Network::Handler.handler(:configuration)
-
- # Check all of the setup stuff.
- def test_initialize
- config = nil
- assert_nothing_raised("Could not create local config") do
- config = Config.new(:Local => true)
- end
-
- assert(config.local?, "Config is not considered local after being started that way")
- end
-
- # Test creation/returning of the interpreter
- def test_interpreter
- config = Config.new
-
- # First test the defaults
- config.expects(:create_interpreter).returns(:interp)
- assert_equal(:interp, config.send(:interpreter), "Did not return the interpreter")
-
- # Now run it again and make sure we get the same thing
- assert_equal(:interp, config.send(:interpreter), "Did not cache the interpreter")
- end
-
- def test_create_interpreter
- config = Config.new(:Local => false)
- args = {}
-
- # Try it first with defaults.
- Puppet::Parser::Interpreter.expects(:new).returns(:interp)
- assert_equal(:interp, config.send(:create_interpreter), "Did not return the interpreter")
- end
-
- # Make sure node objects get appropriate data added to them.
- def test_add_node_data
- # First with no classes
- config = Config.new
-
- fakenode = Object.new
- # Set the server facts to something
- config.instance_variable_set("@server_facts", :facts)
- fakenode.expects(:merge).with(:facts)
- config.send(:add_node_data, fakenode)
-
- # Now try it with classes.
- config.classes = %w{a b}
- list = []
- fakenode = Object.new
- fakenode.expects(:merge).with(:facts)
- fakenode.expects(:classes).returns(list).times(2)
- config.send(:add_node_data, fakenode)
- assert_equal(%w{a b}, list, "Did not add classes to node")
- end
-
- def test_compile
- config = Config.new
-
- # First do a local
- node = mock 'node'
- node.stubs(:name).returns(:mynode)
- node.stubs(:environment).returns(:myenv)
-
- interp = mock 'interpreter'
- interp.stubs(:environment)
- interp.expects(:compile).with(node).returns(:config)
- config.expects(:interpreter).returns(interp)
-
- Puppet.expects(:notice) # The log message from benchmarking
-
- assert_equal(:config, config.send(:compile, node), "Did not return config")
-
- # Now try it non-local
- node = mock 'node'
- node.stubs(:name).returns(:mynode)
- node.stubs(:environment).returns(:myenv)
-
- interp = mock 'interpreter'
- interp.stubs(:environment)
- interp.expects(:compile).with(node).returns(:config)
-
- config = Config.new(:Local => true)
- config.expects(:interpreter).returns(interp)
-
- assert_equal(:config, config.send(:compile, node), "Did not return config")
- end
-
- def test_set_server_facts
- config = Config.new
- assert_nothing_raised("Could not call :set_server_facts") do
- config.send(:set_server_facts)
- end
- facts = config.instance_variable_get("@server_facts")
- %w{servername serverversion serverip}.each do |fact|
- assert(facts.include?(fact), "Config did not set %s fact" % fact)
- end
- end
-
- def test_translate
- # First do a local config
- config = Config.new(:Local => true)
- assert_equal(:plain, config.send(:translate, :plain), "Attempted to translate local config")
-
- # Now a non-local
- config = Config.new(:Local => false)
- assert(! config.local?, "Config wrongly thinks it's local")
- obj = mock 'dumpee'
- yamld = mock 'yaml'
- obj.expects(:to_yaml).with(:UseBlock => true).returns(yamld)
- CGI.expects(:escape).with(yamld).returns(:translated)
- assert_equal(:translated, config.send(:translate, obj), "Did not return translated config")
- end
-
- # Check that we're storing the node freshness into the rails db. Hackilicious.
- def test_update_node_check
- # This is stupid.
- config = Config.new
- node = Object.new
- node.expects(:name).returns(:hostname)
- now = Object.new
- Time.expects(:now).returns(now)
- host = Object.new
- host.expects(:last_freshcheck=).with(now)
- host.expects(:save)
-
- # Only test the case where rails is there
- Puppet[:storeconfigs] = true
- Puppet.features.expects(:rails?).returns(true)
- Puppet::Rails.expects(:connect)
- Puppet::Rails::Host.expects(:find_or_create_by_name).with(:hostname).returns(host)
-
- config.send(:update_node_check, node)
- end
-
- def test_version
- # First try the case where we can't look up the node
- config = Config.new
- node = Object.new
- Puppet::Node.stubs(:find_by_any_name).with(:client).returns(false, node)
- interp = Object.new
- assert_instance_of(Bignum, config.version(:client), "Did not return configuration version")
-
- # And then when we find the node.
- config = Config.new
- config.expects(:update_node_check).with(node)
- interp = Object.new
- interp.expects(:configuration_version).returns(:version)
- config.expects(:interpreter).returns(interp)
- assert_equal(:version, config.version(:client), "Did not return configuration version")
- end
-end
diff --git a/test/network/handler/master.rb b/test/network/handler/master.rb
index 55522237b..e91ec2f47 100755
--- a/test/network/handler/master.rb
+++ b/test/network/handler/master.rb
@@ -13,52 +13,17 @@ class TestMaster < Test::Unit::TestCase
Puppet::Indirector::Indirection.clear_cache
end
- # Make sure that files are reread when they change.
- def test_filereread
- # Start with a normal setting
- Puppet[:filetimeout] = 15
-
- manifest = mktestmanifest()
-
- facts = Puppet::Network::Client.master.facts
- # Store them, so we don't determine frshness based on facts.
- Puppet::Util::Storage.cache(:configuration)[:facts] = facts
-
- file2 = @createdfile + "2"
- @@tmpfiles << file2
-
- client = master = nil
- Puppet[:manifest] = manifest
- assert_nothing_raised() {
- # this is the default server setup
- master = Puppet::Network::Handler.master.new(
- :Local => true
- )
- }
-
- config = master.getconfig({"hostname" => "blah"})
-
- # Cache this value for later
- parse1 = master.freshness("mynode")
-
- sleep 1.5
- # Create a new manifest
- File.open(manifest, "w") { |f|
- f.puts "file { \"%s\": ensure => file }\n" % file2
- }
-
- # Verify that the master doesn't immediately reparse the file; we
- # want to wait through the timeout
- assert_equal(parse1, master.freshness("mynode"), "Master did not wait through timeout")
-
- # Then eliminate it
- Puppet[:filetimeout] = 0
+ def test_freshness_is_always_now
+ master = Puppet::Network::Handler.master.new(
+ :Manifest => tempfile,
+ :UseNodes => true,
+ :Local => true
+ )
- # Now make sure the master does reparse
- #Puppet.notice "%s vs %s" % [parse1, master.freshness]
- assert(parse1 != master.freshness("mynode"), "Master did not reparse file")
+ now1 = mock 'now1'
+ Time.expects(:now).returns(now1)
- assert(master.getconfig({"hostname" => "blah"}) != config, "Did not use reloaded config")
+ assert_equal(master.freshness, now1, "Did not return current time as freshness")
end
# Make sure we're correctly doing clientname manipulations.
diff --git a/test/rails/host.rb b/test/rails/host.rb
index 582bebcb2..79f0ae398 100755
--- a/test/rails/host.rb
+++ b/test/rails/host.rb
@@ -151,41 +151,4 @@ class TestRailsHost < PuppetTest::TestCase
"loglevel was not added")
end
end
-
- def test_freshness_connect_update
- Puppet::Rails.init
- Puppet[:storeconfigs] = true
-
- Puppet[:code] = " "
- # this is the default server setup
- master = Puppet::Network::Handler.configuration.new(
- :Local => true
- )
-
- # Create a host
- Puppet::Rails::Host.new(:name => "test", :ip => "192.168.0.3").save
-
- assert_nothing_raised("Failed to update last_connect for unknown host") do
- master.version("created",'192.168.0.1')
- end
-
- # Make sure it created the host
- created = Puppet::Rails::Host.find_by_name("created")
- assert(created, "Freshness did not create host")
- assert(created.last_freshcheck,
- "Did not set last_freshcheck on created host")
-
- # Now check on the existing host
- assert_nothing_raised("Failed to update last_connect for unknown host") do
- master.version("test",'192.168.0.2')
- end
-
- # Recreate it, so we're not using the cached object.
- host = Puppet::Rails::Host.find_by_name("test")
-
- # Make sure it created the host
- assert(host.last_freshcheck,
- "Did not set last_freshcheck on existing host")
- end
end
-
diff --git a/test/ral/type/user.rb b/test/ral/type/user.rb
index ec9b12923..1a2de2649 100755
--- a/test/ral/type/user.rb
+++ b/test/ral/type/user.rb
@@ -362,6 +362,12 @@ class TestUser < Test::Unit::TestCase
user.delete(:groups)
end
+ def test_groups_list_must_not_contain_commas
+ assert_raise(Puppet::Error) do
+ Puppet::Type.type(:user).create :name => "luke", :groups => "root,adm"
+ end
+ end
+
def test_autorequire
file = tempfile()
comp = nil