summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore2
-rw-r--r--CHANGELOG33
-rw-r--r--LICENSE5
-rw-r--r--Modulefile19
-rw-r--r--README.markdown52
-rw-r--r--RELEASE_PROCESS.markdown13
-rw-r--r--lib/puppet/parser/functions/getvar.rb23
-rw-r--r--lib/puppet/parser/functions/has_key.rb27
-rw-r--r--lib/puppet/parser/functions/loadyaml.rb20
-rw-r--r--lib/puppet/parser/functions/merge.rb30
-rw-r--r--lib/puppet/parser/functions/validate_array.rb35
-rw-r--r--lib/puppet/parser/functions/validate_bool.rb39
-rw-r--r--lib/puppet/parser/functions/validate_hash.rb37
-rw-r--r--lib/puppet/parser/functions/validate_re.rb35
-rw-r--r--lib/puppet/parser/functions/validate_string.rb35
-rw-r--r--lib/puppet/provider/whole_line/ruby.rb15
-rw-r--r--lib/puppet/type/anchor.rb32
-rw-r--r--lib/puppet/type/whole_line.rb44
-rw-r--r--manifests/init.pp18
-rw-r--r--manifests/stages.pp42
-rw-r--r--spec/spec.opts2
-rw-r--r--[-rwxr-xr-x]spec/spec_helper.rb0
-rw-r--r--spec/unit/puppet/parser/functions/getvar_spec.rb53
-rw-r--r--spec/unit/puppet/parser/functions/has_key_spec.rb46
-rw-r--r--spec/unit/puppet/parser/functions/merge_spec.rb54
-rw-r--r--spec/unit/puppet/parser/functions/validate_array_spec.rb63
-rw-r--r--spec/unit/puppet/parser/functions/validate_bool_spec.rb76
-rw-r--r--spec/unit/puppet/parser/functions/validate_hash_spec.rb63
-rw-r--r--spec/unit/puppet/parser/functions/validate_string_spec.rb83
-rw-r--r--spec/unit/puppet/provider/whole_line/ruby_spec.rb30
-rw-r--r--spec/unit/puppet/type/anchor_spec.rb11
-rw-r--r--spec/unit/puppet/type/whole_line_spec.rb24
-rw-r--r--tests/init.pp1
-rw-r--r--tests/whole_line.pp7
34 files changed, 1047 insertions, 22 deletions
diff --git a/.gitignore b/.gitignore
index 7ad8fca..481fc81 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,4 @@
pkg/
+.DS_Store
+metadata.json
coverage/
diff --git a/CHANGELOG b/CHANGELOG
new file mode 100644
index 0000000..ecffa9e
--- /dev/null
+++ b/CHANGELOG
@@ -0,0 +1,33 @@
+2011-08-04 Puppet Labs <support@puppetlabs.com> - 1.1.0
+* Rename append_line to whole_line
+* This is an API change and as such motivating a 1.1.0 release.
+
+2011-08-04 Puppet Labs <support@puppetlabs.com> - 1.0.0
+* Initial stable release
+* Add validate_array and validate_string functions
+* Make merge() function work with Ruby 1.8.5
+* Add hash merging function
+* Add has_key function
+* Add loadyaml() function
+* Add append_line native
+
+2011-06-21 Jeff McCune <jeff@puppetlabs.com> - 0.1.7
+* Add validate_hash() and getvar() functions
+
+2011-06-15 Jeff McCune <jeff@puppetlabs.com> - 0.1.6
+* Add anchor resource type to provide containment for composite classes
+
+2011-06-03 Jeff McCune <jeff@puppetlabs.com> - 0.1.5
+* Add validate_bool() function to stdlib
+
+0.1.4 2011-05-26 Jeff McCune <jeff@puppetlabs.com>
+* Move most stages after main
+
+0.1.3 2011-05-25 Jeff McCune <jeff@puppetlabs.com>
+* Add validate_re() function
+
+0.1.2 2011-05-24 Jeff McCune <jeff@puppetlabs.com>
+* Update to add annotated tag
+
+0.1.1 2011-05-24 Jeff McCune <jeff@puppetlabs.com>
+* Add stdlib::stages class with a standard set of stages
diff --git a/LICENSE b/LICENSE
index b6b37d9..ec0587c 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,7 +1,8 @@
-Puppet - Automating Configuration Management.
+Copyright (C) 2011 Puppet Labs Inc
+
+and some parts:
Copyright (C) 2011 Krzysztof Wilczynski
-Copyright (C) 2011 Puppet Labs Inc
Puppet Labs can be contacted at: info@puppetlabs.com
diff --git a/Modulefile b/Modulefile
index a886ae6..cc84ec9 100644
--- a/Modulefile
+++ b/Modulefile
@@ -1,8 +1,11 @@
-name 'puppetlabs-functions'
-version '0.0.1'
-source 'https://github.com/puppetlabs/puppetlabs-functions'
-author 'Krzysztof Wilczynski'
-license 'Apache License 2.0'
-summary 'A set of basic functions for puppet.'
-description 'This module provides a set of basic functions for puppet that extend the standard library.'
-project_page 'https://github.com/puppetlabs/puppetlabs-functions'
+name 'puppetlabs-stdlib'
+version '1.1.0'
+source 'git://github.com/puppetlabs/puppetlabs-stdlib'
+author 'puppetlabs'
+license 'Apache 2.0'
+summary 'Puppet Module Standard Library'
+description 'Standard Library for Puppet Modules'
+project_page 'https://github.com/puppetlabs/puppetlabs-stdlib'
+
+## Add dependencies, if any:
+# dependency 'username/name', '>= 1.2.0'
diff --git a/README.markdown b/README.markdown
index a15338f..68186c2 100644
--- a/README.markdown
+++ b/README.markdown
@@ -1,23 +1,51 @@
-## puppetlabs-functions module
+# Puppet Labs Standard Library #
-### Overview
+This module provides a "standard library" of resources for developing Puppet
+Modules. This modules will include the following additions to Puppet
-This is the puppet-functions module. Here we are providing a library of various functions that extend the basic function library that is provided in Puppet.
+ * Stages
+ * Facts
+ * Functions
+ * Defined resource types
+ * Types
+ * Providers
-### Disclaimer
+This module is officially curated and provided by Puppet Labs. The modules
+Puppet Labs writes and distributes will make heavy use of this standard
+library.
-Warning! While this software is written in the best interest of quality it has not been formally tested by our QA teams. Use at your own risk, but feel free to enjoy and perhaps improve it while you do.
+# Compatibility #
-Please see the included Apache Software License for more legal details regarding warranty.
+This module is designed to work with Puppet version 2.6 and later. It may be
+forked if Puppet 2.7 specific features are added. There are currently no plans
+for a Puppet 0.25 standard library module.
-### Installation
+# Functions #
-From github, download the module into your modulepath on your Puppetmaster. If you are not sure where your module path is try this command:
+ Please see `puppet doc -r function` for documentation on each function. The
+ current list of functions is:
- puppet --configprint modulepath
+ * getvar
+ * has\_key
+ * loadyaml
+ * merge.rb
+ * validate\_array
+ * validate\_bool
+ * validate\_hash
+ * validate\_re
+ * validate\_string
-Depending on the version of Puppet, you may need to restart the puppetmasterd (or Apache) process before the functions will work.
+## validate\_hash ##
-## Functions
+ $somehash = { 'one' => 'two' }
+ validate\_hash($somehash)
-TODO
+## getvar() ##
+
+This function aims to look up variables in user-defined namespaces within
+puppet. Note, if the namespace is a class, it should already be evaluated
+before the function is used.
+
+ $namespace = 'site::data'
+ include "${namespace}"
+ $myvar = getvar("${namespace}::myvar")
diff --git a/RELEASE_PROCESS.markdown b/RELEASE_PROCESS.markdown
new file mode 100644
index 0000000..ea40d5d
--- /dev/null
+++ b/RELEASE_PROCESS.markdown
@@ -0,0 +1,13 @@
+# Releasing this module #
+
+ * Work in a topic branch
+ * Submit a github pull request
+ * Address any comments / feeback
+ * Merge into master using --no-ff
+ * Update the CHANGELOG
+ * Update the Modulefile
+ * Create an annotated tag with git tag -a X.Y.Z -m 'version X.Y.Z'
+ * Push the tag with git push origin --tags
+ * Build a new package with puppet-module
+ * Publish the new package to the forge
+
diff --git a/lib/puppet/parser/functions/getvar.rb b/lib/puppet/parser/functions/getvar.rb
new file mode 100644
index 0000000..ffd774d
--- /dev/null
+++ b/lib/puppet/parser/functions/getvar.rb
@@ -0,0 +1,23 @@
+module Puppet::Parser::Functions
+
+ newfunction(:getvar, :type => :rvalue, :doc => <<-'ENDHEREDOC') do |args|
+ Lookup a variable in a remote namespace.
+
+ For example:
+
+ $foo = getvar('site::data::foo')
+
+ This is useful if the namespace itself is stored in a string:
+
+ $bar = getvar("${datalocation}::bar")
+ ENDHEREDOC
+
+ unless args.length == 1
+ raise Puppet::ParseError, ("getvar(): wrong number of arguments (#{args.length}; must be 1)")
+ end
+
+ self.lookupvar("#{args[0]}")
+
+ end
+
+end
diff --git a/lib/puppet/parser/functions/has_key.rb b/lib/puppet/parser/functions/has_key.rb
new file mode 100644
index 0000000..9c1c4c3
--- /dev/null
+++ b/lib/puppet/parser/functions/has_key.rb
@@ -0,0 +1,27 @@
+module Puppet::Parser::Functions
+
+ newfunction(:has_key, :type => :rvalue, :doc => <<-'ENDHEREDOC') do |args|
+ determine if a hash has a certain key value.
+
+ Example:
+ $my_hash = {'key_one' => 'value_one'}
+ if has_key($my_hash, 'key_two') {
+ notice('we will not reach here')
+ }
+ if has_key($my_hash, 'key_one') {
+ notice('this will be printed')
+ }
+
+ ENDHEREDOC
+
+ unless args.length == 2
+ raise Puppet::ParseError, ("has_key(): wrong number of arguments (#{args.length}; must be 2)")
+ end
+ unless args[0].is_a?(Hash)
+ raise Puppet::ParseError, "has_key(): expects the first argument to be a hash, got #{args[0].inspect} which is of type #{args[0].class}"
+ end
+ args[0].has_key?(args[1])
+
+ end
+
+end
diff --git a/lib/puppet/parser/functions/loadyaml.rb b/lib/puppet/parser/functions/loadyaml.rb
new file mode 100644
index 0000000..0f16f69
--- /dev/null
+++ b/lib/puppet/parser/functions/loadyaml.rb
@@ -0,0 +1,20 @@
+module Puppet::Parser::Functions
+
+ newfunction(:loadyaml, :type => :rvalue, :doc => <<-'ENDHEREDOC') do |args|
+ Load a YAML file and return the data if it contains an Array, String, or Hash
+ as a Puppet variable.
+
+ For example:
+
+ $myhash = loadyaml('/etc/puppet/data/myhash.yaml')
+ ENDHEREDOC
+
+ unless args.length == 1
+ raise Puppet::ParseError, ("loadyaml(): wrong number of arguments (#{args.length}; must be 1)")
+ end
+
+ YAML.load_file(args[0])
+
+ end
+
+end
diff --git a/lib/puppet/parser/functions/merge.rb b/lib/puppet/parser/functions/merge.rb
new file mode 100644
index 0000000..d2dc0f9
--- /dev/null
+++ b/lib/puppet/parser/functions/merge.rb
@@ -0,0 +1,30 @@
+module Puppet::Parser::Functions
+ newfunction(:merge, :type => :rvalue, :doc => <<-'ENDHEREDOC') do |args|
+ Merges two or more hashes together and returns the resulting hash.
+
+ For example:
+
+ $hash1 = {'one' => 1, 'two', => 2}
+ $hash1 = {'two' => 2, 'three', => 2}
+ $merged_hash = merge($hash1, $hash2)
+ # merged_hash = {'one' => 1, 'two' => 2, 'three' => 2}
+
+ ENDHEREDOC
+
+ if args.length < 2
+ raise Puppet::ParseError, ("merge(): wrong number of arguments (#{args.length}; must be at least 2)")
+ end
+
+ # The hash we accumulate into
+ accumulator = Hash.new
+ # Merge into the accumulator hash
+ args.each do |arg|
+ unless arg.is_a?(Hash)
+ raise Puppet::ParseError, "merge: unexpected argument type #{arg.class}, only expects hash arguments"
+ end
+ accumulator.merge!(arg)
+ end
+ # Return the fully merged hash
+ accumulator
+ end
+end
diff --git a/lib/puppet/parser/functions/validate_array.rb b/lib/puppet/parser/functions/validate_array.rb
new file mode 100644
index 0000000..a7a7165
--- /dev/null
+++ b/lib/puppet/parser/functions/validate_array.rb
@@ -0,0 +1,35 @@
+module Puppet::Parser::Functions
+
+ newfunction(:validate_array, :doc => <<-'ENDHEREDOC') do |args|
+ Validate all passed values are a Array data structure
+ value does not pass the check.
+
+ Example:
+
+ These values validate
+
+ $my_array = [ 'one', 'two' ]
+ validate_array($my_array)
+
+ These values do NOT validate
+
+ validate_array(true)
+ validate_array('some_string')
+ $undefined = undef
+ validate_array($undefined)
+
+ ENDHEREDOC
+
+ unless args.length > 0 then
+ raise Puppet::ParseError, ("validate_array(): wrong number of arguments (#{args.length}; must be > 0)")
+ end
+
+ args.each do |arg|
+ unless arg.is_a?(Array)
+ raise Puppet::ParseError, ("#{arg.inspect} is not an Array. It looks to be a #{arg.class}")
+ end
+ end
+
+ end
+
+end
diff --git a/lib/puppet/parser/functions/validate_bool.rb b/lib/puppet/parser/functions/validate_bool.rb
new file mode 100644
index 0000000..49e6378
--- /dev/null
+++ b/lib/puppet/parser/functions/validate_bool.rb
@@ -0,0 +1,39 @@
+module Puppet::Parser::Functions
+
+ newfunction(:validate_bool, :doc => <<-'ENDHEREDOC') do |args|
+ Validate all passed values are true or false. Abort catalog compilation if the
+ value does not pass the check.
+
+ Example:
+
+ These booleans validate
+
+ $iamtrue = true
+ validate_bool(true)
+ validate_bool(true, true, false, $iamtrue)
+
+ These strings do NOT validate and will abort catalog compilation
+
+ $some_array = [ true ]
+ validate_bool("false")
+ validate_bool("true")
+ validate_bool($some_array)
+
+ * Jeff McCune <jeff@puppetlabs.com>
+ * Dan Bode <dan@puppetlabs.com>
+
+ ENDHEREDOC
+
+ unless args.length > 0 then
+ raise Puppet::ParseError, ("validate_bool(): wrong number of arguments (#{args.length}; must be > 0)")
+ end
+
+ args.each do |arg|
+ unless (arg.is_a?(TrueClass) || arg.is_a?(FalseClass))
+ raise Puppet::ParseError, ("#{arg.inspect} is not a boolean. It looks to be a #{arg.class}")
+ end
+ end
+
+ end
+
+end
diff --git a/lib/puppet/parser/functions/validate_hash.rb b/lib/puppet/parser/functions/validate_hash.rb
new file mode 100644
index 0000000..1443318
--- /dev/null
+++ b/lib/puppet/parser/functions/validate_hash.rb
@@ -0,0 +1,37 @@
+module Puppet::Parser::Functions
+
+ newfunction(:validate_hash, :doc => <<-'ENDHEREDOC') do |args|
+ Validate all passed values are a Hash data structure
+ value does not pass the check.
+
+ Example:
+
+ These values validate
+
+ $my_hash = { 'one' => 'two' }
+ validate_hash($my_hash)
+
+ These values do NOT validate
+
+ validate_hash(true)
+ validate_hash('some_string')
+ $undefined = undef
+ validate_hash($undefined)
+
+ * Jeff McCune <jeff@puppetlabs.com>
+
+ ENDHEREDOC
+
+ unless args.length > 0 then
+ raise Puppet::ParseError, ("validate_hash(): wrong number of arguments (#{args.length}; must be > 0)")
+ end
+
+ args.each do |arg|
+ unless arg.is_a?(Hash)
+ raise Puppet::ParseError, ("#{arg.inspect} is not a Hash. It looks to be a #{arg.class}")
+ end
+ end
+
+ end
+
+end
diff --git a/lib/puppet/parser/functions/validate_re.rb b/lib/puppet/parser/functions/validate_re.rb
new file mode 100644
index 0000000..583f26a
--- /dev/null
+++ b/lib/puppet/parser/functions/validate_re.rb
@@ -0,0 +1,35 @@
+module Puppet::Parser::Functions
+
+ newfunction(:validate_re, :doc => <<-'ENDHEREDOC') do |args|
+ Perform simple validation of a string against a regular expression. The second
+ argument of the function should be a string regular expression (without the //'s)
+ or an array of regular expressions. If none of the regular expressions in the array
+ match the string passed in, then an exception will be raised.
+
+ Example:
+
+ These strings validate against the regular expressions
+
+ validate_re('one', '^one$')
+ validate_re('one', [ '^one', '^two' ])
+
+ These strings do NOT validate
+
+ validate_re('one', [ '^two', '^three' ])
+
+ Jeff McCune <jeff@puppetlabs.com>
+
+ ENDHEREDOC
+ if args.length != 2 then
+ raise Puppet::ParseError, ("validate_re(): wrong number of arguments (#{args.length}; must be 2)")
+ end
+
+ msg = "validate_re(): #{args[0].inspect} does not match #{args[1].inspect}"
+
+ raise Puppet::ParseError, (msg) unless args[1].any? do |re_str|
+ args[0] =~ Regexp.compile(re_str)
+ end
+
+ end
+
+end
diff --git a/lib/puppet/parser/functions/validate_string.rb b/lib/puppet/parser/functions/validate_string.rb
new file mode 100644
index 0000000..d0e1376
--- /dev/null
+++ b/lib/puppet/parser/functions/validate_string.rb
@@ -0,0 +1,35 @@
+module Puppet::Parser::Functions
+
+ newfunction(:validate_string, :doc => <<-'ENDHEREDOC') do |args|
+ Validate all passed values are a string data structure
+ value does not pass the check.
+
+ Example:
+
+ These values validate
+
+ $my_string = "one two"
+ validate_string($my_string)
+
+ These values do NOT validate
+
+ validate_string(true)
+ validate_string([ 'some', 'array' ])
+ $undefined = undef
+ validate_string($undefined)
+
+ ENDHEREDOC
+
+ unless args.length > 0 then
+ raise Puppet::ParseError, ("validate_string(): wrong number of arguments (#{args.length}; must be > 0)")
+ end
+
+ args.each do |arg|
+ unless arg.is_a?(String)
+ raise Puppet::ParseError, ("#{arg.inspect} is not a string. It looks to be a #{arg.class}")
+ end
+ end
+
+ end
+
+end
diff --git a/lib/puppet/provider/whole_line/ruby.rb b/lib/puppet/provider/whole_line/ruby.rb
new file mode 100644
index 0000000..156f255
--- /dev/null
+++ b/lib/puppet/provider/whole_line/ruby.rb
@@ -0,0 +1,15 @@
+Puppet::Type.type(:whole_line).provide(:ruby) do
+
+ def exists?
+ File.readlines(resource[:path]).find do |line|
+ line.chomp == resource[:line].chomp
+ end
+ end
+
+ def create
+ File.open(resource[:path], 'a') do |fh|
+ fh.puts resource[:line]
+ end
+ end
+
+end
diff --git a/lib/puppet/type/anchor.rb b/lib/puppet/type/anchor.rb
new file mode 100644
index 0000000..0c28b1c
--- /dev/null
+++ b/lib/puppet/type/anchor.rb
@@ -0,0 +1,32 @@
+Puppet::Type.newtype(:anchor) do
+ desc <<-'ENDOFDESC'
+ A simple resource type intended to be used as an anchor in a composite class.
+
+ class ntp {
+ class { 'ntp::package': }
+ -> class { 'ntp::config': }
+ -> class { 'ntp::service': }
+
+ # These two resources "anchor" the composed classes
+ # such that the end user may use "require" and "before"
+ # relationships with Class['ntp']
+ anchor { 'ntp::begin': } -> class { 'ntp::package': }
+ class { 'ntp::service': } -> anchor { 'ntp::end': }
+ }
+
+ This resource allows all of the classes in the ntp module to be contained
+ within the ntp class from a dependency management point of view.
+
+ This allows the end user of the ntp module to establish require and before
+ relationships easily:
+
+ class { 'ntp': } -> class { 'mcollective': }
+ class { 'mcollective': } -> class { 'ntp': }
+
+ ENDOFDESC
+
+ newparam :name do
+ desc "The name of the anchor resource."
+ end
+
+end
diff --git a/lib/puppet/type/whole_line.rb b/lib/puppet/type/whole_line.rb
new file mode 100644
index 0000000..f231602
--- /dev/null
+++ b/lib/puppet/type/whole_line.rb
@@ -0,0 +1,44 @@
+Puppet::Type.newtype(:whole_line) do
+
+ desc <<-EOT
+ Type that can append whole a line to a file if it does not already contain it.
+
+ Example:
+
+ whole_line { 'sudo_rule':
+ path => '/etc/sudoers',
+ line => '%admin ALL=(ALL) ALL',
+ }
+
+ EOT
+
+ ensurable do
+ defaultto :present
+ newvalue(:present) do
+ provider.create
+ end
+ end
+
+ newparam(:name, :namevar => true) do
+ desc 'arbitrary name used as identity'
+ end
+
+ newparam(:line) do
+ desc 'The line to be appended to the path.'
+ end
+
+ newparam(:path) do
+ desc 'File to possibly append a line to.'
+ validate do |value|
+ unless (Puppet.features.posix? and value =~ /^\//) or (Puppet.features.microsoft_windows? and (value =~ /^.:\// or value =~ /^\/\/[^\/]+\/[^\/]+/))
+ raise(Puppet::Error, "File paths must be fully qualified, not '#{value}'")
+ end
+ end
+ end
+
+ validate do
+ unless self[:line] and self[:path]
+ raise(Puppet::Error, "Both line and path are required attributes")
+ end
+ end
+end
diff --git a/manifests/init.pp b/manifests/init.pp
new file mode 100644
index 0000000..c804568
--- /dev/null
+++ b/manifests/init.pp
@@ -0,0 +1,18 @@
+# Class: stdlib
+#
+# This module manages stdlib
+#
+# Parameters:
+#
+# Actions:
+#
+# Requires:
+#
+# Sample Usage:
+#
+# [Remember: No empty lines between comments and class definition]
+class stdlib {
+
+ class { 'stdlib::stages': }
+
+}
diff --git a/manifests/stages.pp b/manifests/stages.pp
new file mode 100644
index 0000000..365b905
--- /dev/null
+++ b/manifests/stages.pp
@@ -0,0 +1,42 @@
+# Class: stdlib::stages
+#
+# This class manages a standard set of Run Stages for Puppet.
+#
+# The high level stages are (In order):
+#
+# * setup
+# * main
+# * runtime
+# * setup_infra
+# * deploy_infra
+# * setup_app
+# * deploy_app
+# * deploy
+#
+# Parameters:
+#
+# Actions:
+#
+# Declares various run-stages for deploying infrastructure,
+# language runtimes, and application layers.
+#
+# Requires:
+#
+# Sample Usage:
+#
+# node default {
+# include stdlib::stages
+# class { java: stage => 'runtime' }
+# }
+#
+class stdlib::stages {
+
+ stage { 'setup': before => Stage['main'] }
+ stage { 'runtime': require => Stage['main'] }
+ -> stage { 'setup_infra': }
+ -> stage { 'deploy_infra': }
+ -> stage { 'setup_app': }
+ -> stage { 'deploy_app': }
+ -> stage { 'deploy': }
+
+}
diff --git a/spec/spec.opts b/spec/spec.opts
index 425f0ed..91cd642 100644
--- a/spec/spec.opts
+++ b/spec/spec.opts
@@ -1,4 +1,6 @@
--format
s
--colour
+--loadby
+mtime
--backtrace
diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb
index fdc04bc..fdc04bc 100755..100644
--- a/spec/spec_helper.rb
+++ b/spec/spec_helper.rb
diff --git a/spec/unit/puppet/parser/functions/getvar_spec.rb b/spec/unit/puppet/parser/functions/getvar_spec.rb
new file mode 100644
index 0000000..16edd98
--- /dev/null
+++ b/spec/unit/puppet/parser/functions/getvar_spec.rb
@@ -0,0 +1,53 @@
+require 'puppet'
+
+# We don't need this for the basic tests we're doing
+# require 'spec_helper'
+
+# Dan mentioned that Nick recommended the function method call
+# to return the string value for the test description.
+# this will not even try the test if the function cannot be
+# loaded.
+describe Puppet::Parser::Functions.function(:getvar) do
+
+ # Pulled from Dan's create_resources function
+ def get_scope
+ @topscope = Puppet::Parser::Scope.new
+ # This is necessary so we don't try to use the compiler to discover our parent.
+ @topscope.parent = nil
+ @scope = Puppet::Parser::Scope.new
+ @scope.compiler = Puppet::Parser::Compiler.new(Puppet::Node.new("floppy", :environment => 'production'))
+ @scope.parent = @topscope
+ @compiler = @scope.compiler
+ end
+
+ describe 'when calling getvar from puppet' do
+
+ it "should not compile when no arguments are passed" do
+ Puppet[:code] = 'getvar()'
+ get_scope
+ expect { @scope.compiler.compile }.should raise_error(Puppet::ParseError, /wrong number of arguments/)
+ end
+ it "should not compile when too many arguments are passed" do
+ Puppet[:code] = 'getvar("foo::bar", "baz")'
+ get_scope
+ expect { @scope.compiler.compile }.should raise_error(Puppet::ParseError, /wrong number of arguments/)
+ end
+
+ it "should lookup variables in other namespaces" do
+ pending "Puppet doesn't appear to think getvar is an rvalue function... BUG?"
+ Puppet[:code] = <<-'ENDofPUPPETcode'
+ class site::data { $foo = 'baz' }
+ include site::data
+ $foo = getvar("site::data::foo")
+ if $foo != 'baz' {
+ fail('getvar did not return what we expect')
+ }
+ ENDofPUPPETcode
+ get_scope
+ @scope.compiler.compile
+ end
+
+ end
+
+end
+
diff --git a/spec/unit/puppet/parser/functions/has_key_spec.rb b/spec/unit/puppet/parser/functions/has_key_spec.rb
new file mode 100644
index 0000000..d1dcd15
--- /dev/null
+++ b/spec/unit/puppet/parser/functions/has_key_spec.rb
@@ -0,0 +1,46 @@
+require 'puppet'
+require 'mocha'
+describe Puppet::Parser::Functions.function(:has_key) do
+
+ # Pulled from Dan's create_resources function
+ # TODO - this should be moved to spec_helper since the
+ # logic is likely to be applied to multiple rspec files.
+ let(:compiler) {
+ topscope = Puppet::Parser::Scope.new
+ # This is necessary so we don't try to use the compiler to discover our parent.
+ topscope.parent = nil
+ my_scope = Puppet::Parser::Scope.new
+ my_scope.compiler = Puppet::Parser::Compiler.new(Puppet::Node.new("floppy", :environment => 'production'))
+ my_scope.parent = topscope
+ compiler = my_scope.compiler
+ }
+ let(:scope) {
+ scope = Puppet::Parser::Scope.new
+ scope.stubs(:environment).returns(Puppet::Node::Environment.new('production'))
+ scope
+ }
+
+ describe 'when calling has_key from puppet' do
+ it "should not compile when no arguments are passed" do
+ Puppet[:code] = 'has_key()'
+ expect { compiler.compile }.should raise_error(Puppet::ParseError, /wrong number of arguments/)
+ end
+ it "should not compile when 1 argument is passed" do
+ Puppet[:code] = "has_key('foo')"
+ expect { compiler.compile }.should raise_error(Puppet::ParseError, /wrong number of arguments/)
+ end
+ it "should require the first value to be a Hash" do
+ Puppet[:code] = "has_key('foo', 'bar')"
+ expect { compiler.compile }.should raise_error(Puppet::ParseError, /expects the first argument to be a hash/)
+ end
+ end
+ describe 'when calling the function has_key from a scope instance' do
+ it 'should detect existing keys' do
+ scope.function_has_key([{'one' => 1}, 'one']).should be_true
+ end
+ it 'should detect existing keys' do
+ scope.function_has_key([{'one' => 1}, 'two']).should be_false
+ end
+ end
+
+end
diff --git a/spec/unit/puppet/parser/functions/merge_spec.rb b/spec/unit/puppet/parser/functions/merge_spec.rb
new file mode 100644
index 0000000..71e1869
--- /dev/null
+++ b/spec/unit/puppet/parser/functions/merge_spec.rb
@@ -0,0 +1,54 @@
+require 'puppet'
+require 'mocha'
+describe Puppet::Parser::Functions.function(:merge) do
+
+ # Pulled from Dan's create_resources function
+ # TODO - these let statements should be moved somewhere
+ # where they can be resued
+ let(:compiler) {
+ topscope = Puppet::Parser::Scope.new
+ # This is necessary so we don't try to use the compiler to discover our parent.
+ topscope.parent = nil
+ my_scope = Puppet::Parser::Scope.new
+ my_scope.compiler = Puppet::Parser::Compiler.new(Puppet::Node.new("floppy", :environment => 'production'))
+ my_scope.parent = topscope
+ compiler = my_scope.compiler
+ }
+ let(:scope) {
+ scope = Puppet::Parser::Scope.new
+ scope.stubs(:environment).returns(Puppet::Node::Environment.new('production'))
+ scope
+ }
+
+ describe 'when calling merge from puppet' do
+ it "should not compile when no arguments are passed" do
+ Puppet[:code] = 'merge()'
+ expect { compiler.compile }.should raise_error(Puppet::ParseError, /wrong number of arguments/)
+ end
+ it "should not compile when 1 argument is passed" do
+ Puppet[:code] = "$my_hash={'one' => 1}\nmerge($my_hash)"
+ expect { compiler.compile }.should raise_error(Puppet::ParseError, /wrong number of arguments/)
+ end
+ end
+ describe 'when calling merge on the scope instance' do
+ it 'should require all parameters are hashes' do
+ expect { new_hash = scope.function_merge([{}, '2'])}.should raise_error(Puppet::ParseError, /unexpected argument type String/)
+
+ end
+ it 'should be able to merge two hashes' do
+ new_hash = scope.function_merge([{'one' => '1', 'two' => '1'}, {'two' => '2', 'three' => '2'}])
+ new_hash['one'].should == '1'
+ new_hash['two'].should == '2'
+ new_hash['three'].should == '2'
+ end
+ it 'should merge multiple hashes' do
+ hash = scope.function_merge([{'one' => 1}, {'one' => '2'}, {'one' => '3'}])
+ hash['one'].should == '3'
+ end
+ it 'should accept empty hashes' do
+ scope.function_merge([{},{},{}]).should == {}
+ end
+
+ end
+
+end
diff --git a/spec/unit/puppet/parser/functions/validate_array_spec.rb b/spec/unit/puppet/parser/functions/validate_array_spec.rb
new file mode 100644
index 0000000..37ae09d
--- /dev/null
+++ b/spec/unit/puppet/parser/functions/validate_array_spec.rb
@@ -0,0 +1,63 @@
+require 'puppet'
+
+# We don't need this for the basic tests we're doing
+# require 'spec_helper'
+
+# Dan mentioned that Nick recommended the function method call
+# to return the string value for the test description.
+# this will not even try the test if the function cannot be
+# loaded.
+describe Puppet::Parser::Functions.function(:validate_array) do
+
+ # Pulled from Dan's create_resources function
+ def get_scope
+ @topscope = Puppet::Parser::Scope.new
+ # This is necessary so we don't try to use the compiler to discover our parent.
+ @topscope.parent = nil
+ @scope = Puppet::Parser::Scope.new
+ @scope.compiler = Puppet::Parser::Compiler.new(Puppet::Node.new("floppy", :environment => 'production'))
+ @scope.parent = @topscope
+ @compiler = @scope.compiler
+ end
+
+ describe 'when calling validate_array from puppet' do
+
+ %w{ true false }.each do |the_string|
+
+ it "should not compile when #{the_string} is a string" do
+ Puppet[:code] = "validate_array('#{the_string}')"
+ get_scope
+ expect { @scope.compiler.compile }.should raise_error(Puppet::ParseError, /is not an Array/)
+ end
+
+ it "should not compile when #{the_string} is a bare word" do
+ Puppet[:code] = "validate_array(#{the_string})"
+ get_scope
+ expect { @scope.compiler.compile }.should raise_error(Puppet::ParseError, /is not an Array/)
+ end
+
+ end
+
+ it "should compile when multiple array arguments are passed" do
+ Puppet[:code] = <<-'ENDofPUPPETcode'
+ $foo = [ ]
+ $bar = [ 'one', 'two' ]
+ validate_array($foo, $bar)
+ ENDofPUPPETcode
+ get_scope
+ @scope.compiler.compile
+ end
+
+ it "should not compile when an undef variable is passed" do
+ Puppet[:code] = <<-'ENDofPUPPETcode'
+ $foo = undef
+ validate_array($foo)
+ ENDofPUPPETcode
+ get_scope
+ expect { @scope.compiler.compile }.should raise_error(Puppet::ParseError, /is not an Array/)
+ end
+
+ end
+
+end
+
diff --git a/spec/unit/puppet/parser/functions/validate_bool_spec.rb b/spec/unit/puppet/parser/functions/validate_bool_spec.rb
new file mode 100644
index 0000000..e95c396
--- /dev/null
+++ b/spec/unit/puppet/parser/functions/validate_bool_spec.rb
@@ -0,0 +1,76 @@
+require 'puppet'
+
+# We don't need this for the basic tests we're doing
+# require 'spec_helper'
+
+# Dan mentioned that Nick recommended the function method call
+# to return the string value for the test description.
+# this will not even try the test if the function cannot be
+# loaded.
+describe Puppet::Parser::Functions.function(:validate_bool) do
+
+ # Pulled from Dan's create_resources function
+ def get_scope
+ @topscope = Puppet::Parser::Scope.new
+ # This is necessary so we don't try to use the compiler to discover our parent.
+ @topscope.parent = nil
+ @scope = Puppet::Parser::Scope.new
+ @scope.compiler = Puppet::Parser::Compiler.new(Puppet::Node.new("floppy", :environment => 'production'))
+ @scope.parent = @topscope
+ @compiler = @scope.compiler
+ end
+
+ describe 'when calling validate_bool from puppet' do
+
+ %w{ true false }.each do |the_string|
+
+ it "should not compile when #{the_string} is a string" do
+ Puppet[:code] = "validate_bool('#{the_string}')"
+ get_scope
+ expect { @scope.compiler.compile }.should raise_error(Puppet::ParseError, /is not a boolean/)
+ end
+
+ it "should compile when #{the_string} is a bare word" do
+ Puppet[:code] = "validate_bool(#{the_string})"
+ get_scope
+ @scope.compiler.compile
+ end
+
+ end
+
+ it "should not compile when an arbitrary string is passed" do
+ Puppet[:code] = 'validate_bool("jeff and dan are awesome")'
+ get_scope
+ expect { @scope.compiler.compile }.should raise_error(Puppet::ParseError, /is not a boolean/)
+ end
+
+ it "should not compile when no arguments are passed" do
+ Puppet[:code] = 'validate_bool()'
+ get_scope
+ expect { @scope.compiler.compile }.should raise_error(Puppet::ParseError, /wrong number of arguments/)
+ end
+
+ it "should compile when multiple boolean arguments are passed" do
+ Puppet[:code] = <<-'ENDofPUPPETcode'
+ $foo = true
+ $bar = false
+ validate_bool($foo, $bar, true, false)
+ ENDofPUPPETcode
+ get_scope
+ @scope.compiler.compile
+ end
+
+ it "should compile when multiple boolean arguments are passed" do
+ Puppet[:code] = <<-'ENDofPUPPETcode'
+ $foo = true
+ $bar = false
+ validate_bool($foo, $bar, true, false, 'jeff')
+ ENDofPUPPETcode
+ get_scope
+ expect { @scope.compiler.compile }.should raise_error(Puppet::ParseError, /is not a boolean/)
+ end
+
+ end
+
+end
+
diff --git a/spec/unit/puppet/parser/functions/validate_hash_spec.rb b/spec/unit/puppet/parser/functions/validate_hash_spec.rb
new file mode 100644
index 0000000..8cc0b3d
--- /dev/null
+++ b/spec/unit/puppet/parser/functions/validate_hash_spec.rb
@@ -0,0 +1,63 @@
+require 'puppet'
+
+# We don't need this for the basic tests we're doing
+# require 'spec_helper'
+
+# Dan mentioned that Nick recommended the function method call
+# to return the string value for the test description.
+# this will not even try the test if the function cannot be
+# loaded.
+describe Puppet::Parser::Functions.function(:validate_hash) do
+
+ # Pulled from Dan's create_resources function
+ def get_scope
+ @topscope = Puppet::Parser::Scope.new
+ # This is necessary so we don't try to use the compiler to discover our parent.
+ @topscope.parent = nil
+ @scope = Puppet::Parser::Scope.new
+ @scope.compiler = Puppet::Parser::Compiler.new(Puppet::Node.new("floppy", :environment => 'production'))
+ @scope.parent = @topscope
+ @compiler = @scope.compiler
+ end
+
+ describe 'when calling validate_hash from puppet' do
+
+ %w{ true false }.each do |the_string|
+
+ it "should not compile when #{the_string} is a string" do
+ Puppet[:code] = "validate_hash('#{the_string}')"
+ get_scope
+ expect { @scope.compiler.compile }.should raise_error(Puppet::ParseError, /is not a Hash/)
+ end
+
+ it "should not compile when #{the_string} is a bare word" do
+ Puppet[:code] = "validate_hash(#{the_string})"
+ get_scope
+ expect { @scope.compiler.compile }.should raise_error(Puppet::ParseError, /is not a Hash/)
+ end
+
+ end
+
+ it "should compile when multiple hash arguments are passed" do
+ Puppet[:code] = <<-'ENDofPUPPETcode'
+ $foo = {}
+ $bar = { 'one' => 'two' }
+ validate_hash($foo, $bar)
+ ENDofPUPPETcode
+ get_scope
+ @scope.compiler.compile
+ end
+
+ it "should not compile when an undef variable is passed" do
+ Puppet[:code] = <<-'ENDofPUPPETcode'
+ $foo = undef
+ validate_hash($foo)
+ ENDofPUPPETcode
+ get_scope
+ expect { @scope.compiler.compile }.should raise_error(Puppet::ParseError, /is not a Hash/)
+ end
+
+ end
+
+end
+
diff --git a/spec/unit/puppet/parser/functions/validate_string_spec.rb b/spec/unit/puppet/parser/functions/validate_string_spec.rb
new file mode 100644
index 0000000..92392da
--- /dev/null
+++ b/spec/unit/puppet/parser/functions/validate_string_spec.rb
@@ -0,0 +1,83 @@
+require 'puppet'
+
+# We don't need this for the basic tests we're doing
+# require 'spec_helper'
+
+# Dan mentioned that Nick recommended the function method call
+# to return the string value for the test description.
+# this will not even try the test if the function cannot be
+# loaded.
+describe Puppet::Parser::Functions.function(:validate_string) do
+
+ # Pulled from Dan's create_resources function
+ def get_scope
+ @topscope = Puppet::Parser::Scope.new
+ # This is necessary so we don't try to use the compiler to discover our parent.
+ @topscope.parent = nil
+ @scope = Puppet::Parser::Scope.new
+ @scope.compiler = Puppet::Parser::Compiler.new(Puppet::Node.new("floppy", :environment => 'production'))
+ @scope.parent = @topscope
+ @compiler = @scope.compiler
+ end
+
+ describe 'when calling validate_string from puppet' do
+
+ %w{ foo bar baz }.each do |the_string|
+
+ it "should compile when #{the_string} is a string" do
+ Puppet[:code] = "validate_string('#{the_string}')"
+ get_scope
+ @scope.compiler.compile
+ end
+
+ it "should compile when #{the_string} is a bare word" do
+ Puppet[:code] = "validate_string(#{the_string})"
+ get_scope
+ @scope.compiler.compile
+ end
+
+ end
+
+ %w{ true false }.each do |the_string|
+ it "should compile when #{the_string} is a string" do
+ Puppet[:code] = "validate_string('#{the_string}')"
+ get_scope
+ @scope.compiler.compile
+ end
+
+ it "should not compile when #{the_string} is a bare word" do
+ Puppet[:code] = "validate_string(#{the_string})"
+ get_scope
+ expect { @scope.compiler.compile }.should raise_error(Puppet::ParseError, /is not a string/)
+ end
+ end
+
+ it "should compile when multiple string arguments are passed" do
+ Puppet[:code] = <<-'ENDofPUPPETcode'
+ $foo = ''
+ $bar = 'two'
+ validate_string($foo, $bar)
+ ENDofPUPPETcode
+ get_scope
+ @scope.compiler.compile
+ end
+
+ it "should compile when an explicitly undef variable is passed (NOTE THIS MAY NOT BE DESIRABLE)" do
+ Puppet[:code] = <<-'ENDofPUPPETcode'
+ $foo = undef
+ validate_string($foo)
+ ENDofPUPPETcode
+ get_scope
+ @scope.compiler.compile
+ end
+
+ it "should compile when an undefined variable is passed (NOTE THIS MAY NOT BE DESIRABLE)" do
+ Puppet[:code] = <<-'ENDofPUPPETcode'
+ validate_string($foobarbazishouldnotexist)
+ ENDofPUPPETcode
+ get_scope
+ @scope.compiler.compile
+ end
+ end
+end
+
diff --git a/spec/unit/puppet/provider/whole_line/ruby_spec.rb b/spec/unit/puppet/provider/whole_line/ruby_spec.rb
new file mode 100644
index 0000000..9faff2c
--- /dev/null
+++ b/spec/unit/puppet/provider/whole_line/ruby_spec.rb
@@ -0,0 +1,30 @@
+require 'puppet'
+require 'tempfile'
+provider_class = Puppet::Type.type(:whole_line).provider(:ruby)
+describe provider_class do
+ before :each do
+ tmp = Tempfile.new('tmp')
+ @tmpfile = tmp.path
+ tmp.close!
+ @resource = Puppet::Type::Whole_line.new(
+ {:name => 'foo', :path => @tmpfile, :line => 'foo'}
+ )
+ @provider = provider_class.new(@resource)
+ end
+ it 'should detect if the line exists in the file' do
+ File.open(@tmpfile, 'w') do |fh|
+ fh.write('foo')
+ end
+ @provider.exists?.should be_true
+ end
+ it 'should detect if the line does not exist in the file' do
+ File.open(@tmpfile, 'w') do |fh|
+ fh.write('foo1')
+ end
+ @provider.exists?.should be_nil
+ end
+ it 'should append to an existing file when creating' do
+ @provider.create
+ File.read(@tmpfile).chomp.should == 'foo'
+ end
+end
diff --git a/spec/unit/puppet/type/anchor_spec.rb b/spec/unit/puppet/type/anchor_spec.rb
new file mode 100644
index 0000000..2030b83
--- /dev/null
+++ b/spec/unit/puppet/type/anchor_spec.rb
@@ -0,0 +1,11 @@
+#!/usr/bin/env ruby
+
+require 'puppet'
+
+anchor = Puppet::Type.type(:anchor).new(:name => "ntp::begin")
+
+describe anchor do
+ it "should stringify normally" do
+ anchor.to_s.should == "Anchor[ntp::begin]"
+ end
+end
diff --git a/spec/unit/puppet/type/whole_line_spec.rb b/spec/unit/puppet/type/whole_line_spec.rb
new file mode 100644
index 0000000..f273baa
--- /dev/null
+++ b/spec/unit/puppet/type/whole_line_spec.rb
@@ -0,0 +1,24 @@
+require 'puppet'
+require 'tempfile'
+describe Puppet::Type.type(:whole_line) do
+ before :each do
+ @whole_line = Puppet::Type.type(:whole_line).new(:name => 'foo', :line => 'line', :path => '/tmp/path')
+ end
+ it 'should accept a line and path' do
+ @whole_line[:line] = 'my_line'
+ @whole_line[:line].should == 'my_line'
+ end
+ it 'should accept posix filenames' do
+ @whole_line[:path] = '/tmp/path'
+ @whole_line[:path].should == '/tmp/path'
+ end
+ it 'should not accept unqualified path' do
+ expect { @whole_line[:path] = 'file' }.should raise_error(Puppet::Error, /File paths must be fully qualified/)
+ end
+ it 'should require that a line is specified' do
+ expect { Puppet::Type.type(:whole_line).new(:name => 'foo', :path => '/tmp/file') }.should raise_error(Puppet::Error, /Both line and path are required attributes/)
+ end
+ it 'should require that a file is specified' do
+ expect { Puppet::Type.type(:whole_line).new(:name => 'foo', :line => 'path') }.should raise_error(Puppet::Error, /Both line and path are required attributes/)
+ end
+end
diff --git a/tests/init.pp b/tests/init.pp
new file mode 100644
index 0000000..9675d83
--- /dev/null
+++ b/tests/init.pp
@@ -0,0 +1 @@
+include stdlib
diff --git a/tests/whole_line.pp b/tests/whole_line.pp
new file mode 100644
index 0000000..1302989
--- /dev/null
+++ b/tests/whole_line.pp
@@ -0,0 +1,7 @@
+file { '/tmp/dansfile':
+ ensure => present
+}->
+whole_line { 'dans_line':
+ line => 'dan is awesome',
+ path => '/tmp/dansfile',
+}