summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gemfile5
-rw-r--r--.gemspec40
-rw-r--r--.gitignore4
-rw-r--r--.project23
-rw-r--r--.travis.yml29
-rw-r--r--CHANGELOG105
-rw-r--r--CONTRIBUTING.md65
-rw-r--r--Gemfile42
-rw-r--r--Modulefile4
-rw-r--r--README.markdown383
-rw-r--r--README_SPECS.markdown7
-rw-r--r--lib/facter/facter_dot_d.rb202
-rw-r--r--lib/puppet/parser/functions/any2array.rb33
-rw-r--r--lib/puppet/parser/functions/base64.rb37
-rw-r--r--lib/puppet/parser/functions/concat.rb37
-rw-r--r--lib/puppet/parser/functions/count.rb22
-rw-r--r--lib/puppet/parser/functions/difference.rb36
-rw-r--r--lib/puppet/parser/functions/dirname.rb15
-rw-r--r--lib/puppet/parser/functions/ensure_resource.rb22
-rw-r--r--lib/puppet/parser/functions/flatten.rb2
-rw-r--r--lib/puppet/parser/functions/floor.rb20
-rw-r--r--lib/puppet/parser/functions/getparam.rb35
-rw-r--r--lib/puppet/parser/functions/hash.rb2
-rw-r--r--lib/puppet/parser/functions/intersection.rb34
-rw-r--r--lib/puppet/parser/functions/is_float.rb2
-rw-r--r--lib/puppet/parser/functions/is_function_available.rb23
-rw-r--r--lib/puppet/parser/functions/is_integer.rb2
-rw-r--r--lib/puppet/parser/functions/is_numeric.rb2
-rw-r--r--lib/puppet/parser/functions/max.rb10
-rw-r--r--lib/puppet/parser/functions/merge.rb1
-rw-r--r--lib/puppet/parser/functions/min.rb10
-rw-r--r--lib/puppet/parser/functions/num2bool.rb43
-rw-r--r--lib/puppet/parser/functions/prefix.rb6
-rw-r--r--lib/puppet/parser/functions/str2bool.rb5
-rw-r--r--lib/puppet/parser/functions/suffix.rb45
-rw-r--r--lib/puppet/parser/functions/union.rb34
-rw-r--r--lib/puppet/parser/functions/validate_augeas.rb81
-rw-r--r--lib/puppet/parser/functions/validate_cmd.rb47
-rw-r--r--lib/puppet/provider/file_line/ruby.rb2
-rw-r--r--lib/puppet/type/anchor.rb5
-rw-r--r--spec/classes/anchor_spec.rb32
-rw-r--r--spec/functions/ensure_resource_spec.rb60
-rw-r--r--spec/functions/getparam_spec.rb34
-rw-r--r--spec/unit/facter/pe_required_facts_spec.rb69
-rw-r--r--spec/unit/puppet/parser/functions/any2array_spec.rb55
-rwxr-xr-xspec/unit/puppet/parser/functions/base64_spec.rb34
-rw-r--r--spec/unit/puppet/parser/functions/concat_spec.rb15
-rw-r--r--spec/unit/puppet/parser/functions/count_spec.rb31
-rw-r--r--spec/unit/puppet/parser/functions/difference_spec.rb19
-rwxr-xr-xspec/unit/puppet/parser/functions/dirname_spec.rb24
-rwxr-xr-xspec/unit/puppet/parser/functions/flatten_spec.rb4
-rw-r--r--spec/unit/puppet/parser/functions/floor_spec.rb39
-rw-r--r--spec/unit/puppet/parser/functions/get_module_path_spec.rb6
-rw-r--r--spec/unit/puppet/parser/functions/intersection_spec.rb19
-rw-r--r--spec/unit/puppet/parser/functions/is_float_spec.rb4
-rw-r--r--spec/unit/puppet/parser/functions/is_function_available.rb31
-rw-r--r--spec/unit/puppet/parser/functions/is_integer_spec.rb5
-rw-r--r--spec/unit/puppet/parser/functions/is_numeric_spec.rb10
-rwxr-xr-xspec/unit/puppet/parser/functions/max_spec.rb4
-rw-r--r--spec/unit/puppet/parser/functions/merge_spec.rb7
-rwxr-xr-xspec/unit/puppet/parser/functions/min_spec.rb4
-rw-r--r--spec/unit/puppet/parser/functions/num2bool_spec.rb49
-rw-r--r--spec/unit/puppet/parser/functions/str2bool_spec.rb7
-rw-r--r--spec/unit/puppet/parser/functions/str2saltedsha512_spec.rb6
-rw-r--r--spec/unit/puppet/parser/functions/suffix_spec.rb19
-rw-r--r--spec/unit/puppet/parser/functions/union_spec.rb19
-rw-r--r--spec/unit/puppet/parser/functions/validate_array_spec.rb6
-rw-r--r--spec/unit/puppet/parser/functions/validate_augeas_spec.rb102
-rw-r--r--spec/unit/puppet/parser/functions/validate_bool_spec.rb8
-rw-r--r--spec/unit/puppet/parser/functions/validate_cmd_spec.rb81
-rw-r--r--spec/unit/puppet/parser/functions/validate_hash_spec.rb6
-rwxr-xr-xspec/unit/puppet/parser/functions/validate_slength_spec.rb2
-rw-r--r--spec/unit/puppet/parser/functions/validate_string_spec.rb2
-rw-r--r--spec/unit/puppet/type/file_line_spec.rb6
74 files changed, 2204 insertions, 137 deletions
diff --git a/.gemfile b/.gemfile
deleted file mode 100644
index 9aad840..0000000
--- a/.gemfile
+++ /dev/null
@@ -1,5 +0,0 @@
-source :rubygems
-
-puppetversion = ENV.key?('PUPPET_VERSION') ? "= #{ENV['PUPPET_VERSION']}" : ['>= 2.7']
-gem 'puppet', puppetversion
-gem 'puppetlabs_spec_helper', '>= 0.1.0'
diff --git a/.gemspec b/.gemspec
new file mode 100644
index 0000000..e274950
--- /dev/null
+++ b/.gemspec
@@ -0,0 +1,40 @@
+#
+# -*- encoding: utf-8 -*-
+
+Gem::Specification.new do |s|
+ s.name = "puppetmodule-stdlib"
+
+ s.version = "4.0.2"
+
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
+ s.authors = ["Puppet Labs"]
+ s.date = "2013-04-12"
+ s.description = [ 'This Gem format of the stdlib module is intended to make',
+ 'it easier for _module authors_ to resolve dependencies',
+ 'using a Gemfile when running automated testing jobs like',
+ 'Travis or Jenkins. The recommended best practice for',
+ 'installation by end users is to use the `puppet module',
+ 'install` command to install stdlib from the [Puppet',
+ 'Forge](http://forge.puppetlabs.com/puppetlabs/stdlib).' ].join(' ')
+ s.email = "puppet-dev@puppetlabs.com"
+ s.executables = []
+ s.files = [ 'CHANGELOG', 'CONTRIBUTING.md', 'Gemfile', 'LICENSE', 'Modulefile',
+ 'README.markdown', 'README_DEVELOPER.markdown', 'RELEASE_PROCESS.markdown',
+ 'Rakefile', 'spec/spec.opts' ]
+ s.files += Dir['lib/**/*.rb'] + Dir['manifests/**/*.pp'] + Dir['tests/**/*.pp'] + Dir['spec/**/*.rb']
+ s.homepage = "http://forge.puppetlabs.com/puppetlabs/stdlib"
+ s.rdoc_options = ["--title", "Puppet Standard Library Development Gem", "--main", "README.markdown", "--line-numbers"]
+ s.require_paths = ["lib"]
+ s.rubyforge_project = "puppetmodule-stdlib"
+ s.rubygems_version = "1.8.24"
+ s.summary = "This gem provides a way to make the standard library available for other module spec testing tasks."
+
+ if s.respond_to? :specification_version then
+ s.specification_version = 3
+
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
+ else
+ end
+ else
+ end
+end
diff --git a/.gitignore b/.gitignore
index 481fc81..2e3ca63 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,3 +2,7 @@ pkg/
.DS_Store
metadata.json
coverage/
+spec/fixtures/
+Gemfile.lock
+.bundle/
+vendor/bundle/
diff --git a/.project b/.project
new file mode 100644
index 0000000..4e2c033
--- /dev/null
+++ b/.project
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>stdlib</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.cloudsmith.geppetto.pp.dsl.ui.modulefileBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.xtext.ui.shared.xtextBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.cloudsmith.geppetto.pp.dsl.ui.puppetNature</nature>
+ <nature>org.eclipse.xtext.ui.shared.xtextNature</nature>
+ </natures>
+</projectDescription>
diff --git a/.travis.yml b/.travis.yml
index 0ec5a08..1bb1889 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,16 +1,25 @@
language: ruby
+bundler_args: --without development
+script: "bundle exec rake spec SPEC_OPTS='--color --format documentation'"
rvm:
- 1.8.7
-before_script:
-after_script:
-script: "rake spec_full"
-branches:
- only:
- - master
+ - 1.9.3
+ - 2.0.0
+ - ruby-head
env:
- - PUPPET_VERSION=2.7.13
- - PUPPET_VERSION=2.7.6
- - PUPPET_VERSION=2.6.9
+ - PUPPET_GEM_VERSION=">= 3.0.0"
+matrix:
+ allow_failures:
+ - rvm: 2.0.0
+ - rvm: ruby-head
+ include:
+ - rvm: 1.8.7
+ env: PUPPET_GEM_VERSION="~> 2.7"
notifications:
email: false
-gemfile: .gemfile
+ webhooks:
+ urls:
+ - https://puppet-dev-community.herokuapp.com/event/travis-ci/
+ on_success: always
+ on_failure: always
+ on_start: yes
diff --git a/CHANGELOG b/CHANGELOG
index 313b83c..e1a095f 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,5 +1,106 @@
-2012-11-28 - Peter Meier <peter.meier@immerda.ch> - 3.2.0
- * Add reject() function (a79b2cd)
+2013-05-06 - Jeff McCune <jeff@puppetlabs.com> - 4.1.0
+ * (#20582) Restore facter_dot_d to stdlib for PE users (3b887c8)
+ * (maint) Update Gemfile with GEM_FACTER_VERSION (f44d535)
+
+2013-05-06 - Alex Cline <acline@us.ibm.com> - 4.1.0
+ * Terser method of string to array conversion courtesy of ethooz. (d38bce0)
+
+2013-05-06 - Alex Cline <acline@us.ibm.com> 4.1.0
+ * Refactor ensure_resource expectations (b33cc24)
+
+2013-05-06 - Alex Cline <acline@us.ibm.com> 4.1.0
+ * Changed str-to-array conversion and removed abbreviation. (de253db)
+
+2013-05-03 - Alex Cline <acline@us.ibm.com> 4.1.0
+ * (#20548) Allow an array of resource titles to be passed into the ensure_resource function (e08734a)
+
+2013-05-02 - Raphaël Pinson <raphael.pinson@camptocamp.com> - 4.1.0
+ * Add a dirname function (2ba9e47)
+
+2013-04-29 - Mark Smith-Guerrero <msmithgu@gmail.com> - 4.1.0
+ * (maint) Fix a small typo in hash() description (928036a)
+
+2013-04-12 - Jeff McCune <jeff@puppetlabs.com> - 4.0.2
+ * Update user information in gemspec to make the intent of the Gem clear.
+
+2013-04-11 - Jeff McCune <jeff@puppetlabs.com> - 4.0.1
+ * Fix README function documentation (ab3e30c)
+
+2013-04-11 - Jeff McCune <jeff@puppetlabs.com> - 4.0.0
+ * stdlib 4.0 drops support with Puppet 2.7
+ * stdlib 4.0 preserves support with Puppet 3
+
+2013-04-11 - Jeff McCune <jeff@puppetlabs.com> - 4.0.0
+ * Add ability to use puppet from git via bundler (9c5805f)
+
+2013-04-10 - Jeff McCune <jeff@puppetlabs.com> - 4.0.0
+ * (maint) Make stdlib usable as a Ruby GEM (e81a45e)
+
+2013-04-10 - Erik Dalén <dalen@spotify.com> - 4.0.0
+ * Add a count function (f28550e)
+
+2013-03-31 - Amos Shapira <ashapira@atlassian.com> - 4.0.0
+ * (#19998) Implement any2array (7a2fb80)
+
+2013-03-29 - Steve Huff <shuff@vecna.org> - 4.0.0
+ * (19864) num2bool match fix (8d217f0)
+
+2013-03-20 - Erik Dalén <dalen@spotify.com> - 4.0.0
+ * Allow comparisons of Numeric and number as String (ff5dd5d)
+
+2013-03-26 - Richard Soderberg <rsoderberg@mozilla.com> - 4.0.0
+ * add suffix function to accompany the prefix function (88a93ac)
+
+2013-03-19 - Kristof Willaert <kristof.willaert@gmail.com> - 4.0.0
+ * Add floor function implementation and unit tests (0527341)
+
+2012-04-03 - Eric Shamow <eric@puppetlabs.com> - 4.0.0
+ * (#13610) Add is_function_available to stdlib (961dcab)
+
+2012-12-17 - Justin Lambert <jlambert@eml.cc> - 4.0.0
+ * str2bool should return a boolean if called with a boolean (5d5a4d4)
+
+2012-10-23 - Uwe Stuehler <ustuehler@team.mobile.de> - 4.0.0
+ * Fix number of arguments check in flatten() (e80207b)
+
+2013-03-11 - Jeff McCune <jeff@puppetlabs.com> - 4.0.0
+ * Add contributing document (96e19d0)
+
+2013-03-04 - Raphaël Pinson <raphael.pinson@camptocamp.com> - 4.0.0
+ * Add missing documentation for validate_augeas and validate_cmd to README.markdown (a1510a1)
+
+2013-02-14 - Joshua Hoblitt <jhoblitt@cpan.org> - 4.0.0
+ * (#19272) Add has_element() function (95cf3fe)
+
+2013-02-07 - Raphaël Pinson <raphael.pinson@camptocamp.com> - 4.0.0
+ * validate_cmd(): Use Puppet::Util::Execution.execute when available (69248df)
+
+2012-12-06 - Raphaël Pinson <raphink@gmail.com> - 4.0.0
+ * Add validate_augeas function (3a97c23)
+
+2012-12-06 - Raphaël Pinson <raphink@gmail.com> - 4.0.0
+ * Add validate_cmd function (6902cc5)
+
+2013-01-14 - David Schmitt <david@dasz.at> - 4.0.0
+ * Add geppetto project definition (b3fc0a3)
+
+2013-01-02 - Jaka Hudoklin <jakahudoklin@gmail.com> - 4.0.0
+ * Add getparam function to get defined resource parameters (20e0e07)
+
+2013-01-05 - Jeff McCune <jeff@puppetlabs.com> - 4.0.0
+ * (maint) Add Travis CI Support (d082046)
+
+2012-12-04 - Jeff McCune <jeff@puppetlabs.com> - 4.0.0
+ * Clarify that stdlib 3 supports Puppet 3 (3a6085f)
+
+2012-11-30 - Erik Dalén <dalen@spotify.com> - 4.0.0
+ * maint: style guideline fixes (7742e5f)
+
+2012-11-09 - James Fryman <james@frymanet.com> - 4.0.0
+ * puppet-lint cleanup (88acc52)
+
+2012-11-06 - Joe Julian <me@joejulian.name> - 4.0.0
+ * Add function, uriescape, to URI.escape strings. Redmine #17459 (fd52b8d)
2012-09-18 - Chad Metcalf <chad@wibidata.com> - 3.2.0
* Add an ensure_packages function. (8a8c09e)
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
new file mode 100644
index 0000000..bd11f63
--- /dev/null
+++ b/CONTRIBUTING.md
@@ -0,0 +1,65 @@
+# How to contribute
+
+Third-party patches are essential for keeping stdlib great. We simply can't
+access the huge number of platforms and myriad configurations for running
+stdlib. We want to keep it as easy as possible to contribute changes that
+get things working in your environment. There are a few guidelines that we
+need contributors to follow so that we can have a chance of keeping on
+top of things.
+
+## Getting Started
+
+* Make sure you have a [Redmine account](http://projects.puppetlabs.com)
+* Make sure you have a [GitHub account](https://github.com/signup/free)
+* Submit a ticket for your issue, assuming one does not already exist.
+ * Clearly describe the issue including steps to reproduce when it is a bug.
+ * Make sure you fill in the earliest version that you know has the issue.
+* Fork the repository on GitHub
+
+## Making Changes
+
+* Create a topic branch from where you want to base your work.
+ * This is usually the master branch.
+ * Only target release branches if you are certain your fix must be on that
+ branch.
+ * To quickly create a topic branch based on master; `git branch
+ fix/master/my_contribution master` then checkout the new branch with `git
+ checkout fix/master/my_contribution`. Please avoid working directly on the
+ `master` branch.
+* Make commits of logical units.
+* Check for unnecessary whitespace with `git diff --check` before committing.
+* Make sure your commit messages are in the proper format.
+
+````
+ (#99999) Make the example in CONTRIBUTING imperative and concrete
+
+ Without this patch applied the example commit message in the CONTRIBUTING
+ document is not a concrete example. This is a problem because the
+ contributor is left to imagine what the commit message should look like
+ based on a description rather than an example. This patch fixes the
+ problem by making the example concrete and imperative.
+
+ The first line is a real life imperative statement with a ticket number
+ from our issue tracker. The body describes the behavior without the patch,
+ why this is a problem, and how the patch fixes the problem when applied.
+````
+
+* Make sure you have added the necessary tests for your changes.
+* Run _all_ the tests to assure nothing else was accidentally broken.
+
+## Submitting Changes
+
+* Sign the [Contributor License Agreement](http://links.puppetlabs.com/cla).
+* Push your changes to a topic branch in your fork of the repository.
+* Submit a pull request to the repository in the puppetlabs organization.
+* Update your Redmine ticket to mark that you have submitted code and are ready for it to be reviewed.
+ * Include a link to the pull request in the ticket
+
+# Additional Resources
+
+* [More information on contributing](http://links.puppetlabs.com/contribute-to-puppet)
+* [Bug tracker (Redmine)](http://projects.puppetlabs.com)
+* [Contributor License Agreement](http://links.puppetlabs.com/cla)
+* [General GitHub documentation](http://help.github.com/)
+* [GitHub pull request documentation](http://help.github.com/send-pull-requests/)
+* #puppet-dev IRC channel on freenode.org
diff --git a/Gemfile b/Gemfile
new file mode 100644
index 0000000..197cc6b
--- /dev/null
+++ b/Gemfile
@@ -0,0 +1,42 @@
+source "https://rubygems.org"
+
+def location_for(place, fake_version = nil)
+ mdata = /^(git:[^#]*)#(.*)/.match(place)
+ if mdata
+ [fake_version, { :git => mdata[1], :branch => mdata[2], :require => false }].compact
+ elsif place =~ /^file:\/\/(.*)/
+ ['>= 0', { :path => File.expand_path(mdata[1]), :require => false }]
+ else
+ [place, { :require => false }]
+ end
+end
+
+group :development do
+ gem 'watchr'
+end
+
+group :development, :test do
+ gem 'rake'
+ gem 'puppetmodule-stdlib', ">= 1.0.0", :path => File.expand_path("..", __FILE__)
+ gem 'rspec', "~> 2.11.0", :require => false
+ gem 'mocha', "~> 0.10.5", :require => false
+ gem 'puppetlabs_spec_helper', :require => false
+ gem 'rspec-puppet', :require => false
+end
+
+facterversion = ENV['GEM_FACTER_VERSION']
+if facterversion
+ gem 'facter', *location_for(facterversion)
+else
+ gem 'facter', :require => false
+end
+
+ENV['GEM_PUPPET_VERSION'] ||= ENV['PUPPET_GEM_VERSION']
+puppetversion = ENV['GEM_PUPPET_VERSION']
+if puppetversion
+ gem 'puppet', *location_for(puppetversion)
+else
+ gem 'puppet', :require => false
+end
+
+# vim:ft=ruby
diff --git a/Modulefile b/Modulefile
index 34564fa..9d2e8c2 100644
--- a/Modulefile
+++ b/Modulefile
@@ -1,6 +1,6 @@
name 'puppetlabs-stdlib'
-version '3.2.0'
-source 'git://github.com/puppetlabs/puppetlabs-stdlib'
+version '4.1.0'
+source 'git://github.com/puppetlabs/puppetlabs-stdlib.git'
author 'puppetlabs'
license 'Apache 2.0'
summary 'Puppet Module Standard Library'
diff --git a/README.markdown b/README.markdown
index a33add3..0e40f51 100644
--- a/README.markdown
+++ b/README.markdown
@@ -1,5 +1,7 @@
# Puppet Labs Standard Library #
+[![Build Status](https://travis-ci.org/puppetlabs/puppetlabs-stdlib.png?branch=master)](https://travis-ci.org/puppetlabs/puppetlabs-stdlib)
+
This module provides a "standard library" of resources for developing Puppet
Modules. This modules will include the following additions to Puppet
@@ -26,9 +28,11 @@ older versions of Puppet Enterprise that Puppet Labs still supports will have
bugfix maintenance branches periodically "merged up" into master. The current
list of integration branches are:
- * v2.1.x (v2.1.1 released in PE 1.2, 1.2.1, 1.2.3, 1.2.4)
+ * v2.1.x (v2.1.1 released in PE 1)
* v2.2.x (Never released as part of PE, only to the Forge)
- * v2.3.x (Released in PE 2.5.x)
+ * v2.3.x (Released in PE 2)
+ * v3.0.x (Never released as part of PE, only to the Forge)
+ * v4.0.x (Drops support for Puppet 2.7)
* master (mainline development branch)
The first Puppet Enterprise version including the stdlib module is Puppet
@@ -36,6 +40,12 @@ Enterprise 1.2.
# Compatibility #
+Puppet Versions | < 2.6 | 2.6 | 2.7 | 3.x |
+:---------------|:-----:|:---:|:---:|:----:
+**stdlib 2.x** | no | **yes** | **yes** | no
+**stdlib 3.x** | no | no | **yes** | **yes**
+**stdlib 4.x** | no | no | no | **yes**
+
The stdlib module does not work with Puppet versions released prior to Puppet
2.6.0.
@@ -48,12 +58,36 @@ All stdlib releases in the 2.0 major version support Puppet 2.6 and Puppet 2.7.
The 3.0 major release of stdlib drops support for Puppet 2.6. Stdlib 3.x
supports Puppet 2 and Puppet 3.
+## stdlib 4.x ##
+
+The 4.0 major release of stdlib drops support for Puppet 2.7. Stdlib 4.x
+supports Puppet 3. Notably, ruby 1.8.5 is no longer supported though ruby
+1.8.7, 1.9.3, and 2.0.0 are fully supported.
+
# Functions #
abs
---
-Returns the absolute value of a number, for example -34.56 becomes 34.56. Takes
-a single integer and float value as an argument.
+Returns the absolute value of a number, for example -34.56 becomes
+34.56. Takes a single integer and float value as an argument.
+
+
+- *Type*: rvalue
+
+any2array
+---------
+This converts any object to an array containing that object. Empty argument
+lists are converted to an empty array. Arrays are left untouched. Hashes are
+converted to arrays of alternating keys and values.
+
+
+- *Type*: rvalue
+
+base64
+--------
+Converts a string to and from base64 encoding.
+Requires an action ['encode','decode'] and either a plain or base64 encoded
+string
- *Type*: rvalue
@@ -78,9 +112,9 @@ Requires either a single string or an array as an input.
chomp
-----
-Removes the record separator from the end of a string or an array of strings,
-for example `hello\n` becomes `hello`. Requires a single string or array as an
-input.
+Removes the record separator from the end of a string or an array of
+strings, for example `hello\n` becomes `hello`.
+Requires a single string or array as an input.
- *Type*: rvalue
@@ -96,6 +130,30 @@ Requires a string or array of strings as input.
- *Type*: rvalue
+concat
+------
+Appends the contents of array 2 onto array 1.
+
+*Example:*
+
+ concat(['1','2','3'],['4','5','6'])
+
+Would result in:
+
+ ['1','2','3','4','5','6']
+
+
+- *Type*: rvalue
+
+count
+-----
+Takes an array as first argument and an optional second argument.
+Count the number of elements in array that matches second argument.
+If called with only an array it counts the number of elements that are not nil/undef.
+
+
+- *Type*: rvalue
+
defined_with_params
-------------------
Takes a resource reference and an optional hash of attributes.
@@ -116,13 +174,19 @@ to the catalog, and false otherwise.
delete
------
-Deletes a selected element from an array.
+Deletes all instances of a given element from an array, substring from a
+string, or key from a hash.
*Examples:*
- delete(['a','b','c'], 'b')
+ delete(['a','b','c','b'], 'b')
+ Would return: ['a','c']
-Would return: ['a','c']
+ delete({'a'=>1,'b'=>2,'c'=>3}, 'b')
+ Would return: {'a'=>1,'c'=>3}
+
+ delete('abracadabra', 'bra')
+ Would return: 'acada'
- *Type*: rvalue
@@ -140,6 +204,28 @@ Would return: ['a','c']
- *Type*: rvalue
+difference
+----------
+This function returns the difference between two arrays.
+The returned array is a copy of the original array, removing any items that
+also appear in the second array.
+
+*Examples:*
+
+ difference(["a","b","c"],["b","c","d"])
+
+Would return: ["a"]
+
+dirname
+-------
+Returns the `dirname` of a path.
+
+*Examples:*
+
+ dirname('/path/to/a/file.ext')
+
+Would return: '/path/to/a'
+
downcase
--------
Converts the case of a string or all strings in an array to lower case.
@@ -154,6 +240,13 @@ Returns true if the variable is empty.
- *Type*: rvalue
+ensure_packages
+---------------
+Takes a list of packages and only installs them if they don't already exist.
+
+
+- *Type*: statement
+
ensure_resource
---------------
Takes a resource type, title, and a list of attributes that describe a
@@ -171,6 +264,11 @@ If the resource already exists but does not match the specified parameters,
this function will attempt to recreate the resource leading to a duplicate
resource definition error.
+An array of resources can also be passed in and each will be created with
+the type and parameters specified if it doesn't already exist.
+
+ ensure_resource('user', ['dan','alex'], {'ensure' => 'present'})
+
- *Type*: statement
@@ -189,6 +287,14 @@ Would return: ['a','b','c']
- *Type*: rvalue
+floor
+-----
+Returns the largest integer less or equal to the argument.
+Takes a single numeric value as an argument.
+
+
+- *Type*: rvalue
+
fqdn_rotate
-----------
Rotates an array a random number of times based on a nodes fqdn.
@@ -207,6 +313,27 @@ Example:
- *Type*: rvalue
+getparam
+--------
+Takes a resource reference and name of the parameter and
+returns value of resource's parameter.
+
+*Examples:*
+
+ define example_resource($param) {
+ }
+
+ example_resource { "example_resource_instance":
+ param => "param_value"
+ }
+
+ getparam(Example_resource["example_resource_instance"], "param")
+
+Would return: param_value
+
+
+- *Type*: rvalue
+
getvar
------
Lookup a variable in a remote namespace.
@@ -241,6 +368,44 @@ Would return:
- *Type*: rvalue
+has_interface_with
+------------------
+Returns boolean based on kind and value:
+* macaddress
+* netmask
+* ipaddress
+* network
+
+has_interface_with("macaddress", "x:x:x:x:x:x")
+has_interface_with("ipaddress", "127.0.0.1") => true
+etc.
+
+If no "kind" is given, then the presence of the interface is checked:
+has_interface_with("lo") => true
+
+
+- *Type*: rvalue
+
+has_ip_address
+--------------
+Returns true if the client has the requested IP address on some interface.
+
+This function iterates through the 'interfaces' fact and checks the
+'ipaddress_IFACE' facts, performing a simple string comparison.
+
+
+- *Type*: rvalue
+
+has_ip_network
+--------------
+Returns true if the client has an IP address within the requested network.
+
+This function iterates through the 'interfaces' fact and checks the
+'network_IFACE' facts, performing a simple string comparision.
+
+
+- *Type*: rvalue
+
has_key
-------
Determine if a hash has a certain key value.
@@ -261,7 +426,7 @@ Example:
hash
----
-This function converts and array into a hash.
+This function converts an array into a hash.
*Examples:*
@@ -272,24 +437,39 @@ Would return: {'a'=>1,'b'=>2,'c'=>3}
- *Type*: rvalue
+intersection
+-----------
+This function returns an array an intersection of two.
+
+*Examples:*
+
+ intersection(["a","b","c"],["b","c","d"])
+
+Would return: ["b","c"]
+
is_array
--------
Returns true if the variable passed to this function is an array.
-
- *Type*: rvalue
is_domain_name
--------------
Returns true if the string passed to this function is a syntactically correct domain name.
-
- *Type*: rvalue
is_float
--------
Returns true if the variable passed to this function is a float.
+- *Type*: rvalue
+
+is_function_available
+---------------------
+This function accepts a string as an argument, determines whether the
+Puppet runtime has access to a function by that name. It returns a
+true if the function exists, false if not.
- *Type*: rvalue
@@ -297,42 +477,36 @@ is_hash
-------
Returns true if the variable passed to this function is a hash.
-
- *Type*: rvalue
is_integer
----------
Returns true if the variable returned to this string is an integer.
-
- *Type*: rvalue
is_ip_address
-------------
Returns true if the string passed to this function is a valid IP address.
-
- *Type*: rvalue
is_mac_address
--------------
Returns true if the string passed to this function is a valid mac address.
-
- *Type*: rvalue
is_numeric
----------
Returns true if the variable passed to this function is a number.
-
- *Type*: rvalue
is_string
---------
Returns true if the variable passed to this function is a string.
-
- *Type*: rvalue
join
@@ -345,6 +519,19 @@ This function joins an array into a string using a seperator.
Would result in: "a,b,c"
+- *Type*: rvalue
+
+join_keys_to_values
+-------------------
+This function joins each key of a hash to that key's corresponding value with a
+separator. Keys and values are cast to strings. The return value is an array in
+which each element is one joined key/value pair.
+
+*Examples:*
+
+ join_keys_to_values({'a'=>1,'b'=>2}, " is ")
+
+Would result in: ["a is 1","b is 2"]
- *Type*: rvalue
@@ -352,7 +539,6 @@ keys
----
Returns the keys of a hash as an array.
-
- *Type*: rvalue
loadyaml
@@ -371,6 +557,12 @@ lstrip
------
Strips leading spaces to the left of a string.
+- *Type*: rvalue
+
+max
+---
+Returns the highest value of all arguments.
+Requires at least one argument.
- *Type*: rvalue
@@ -388,7 +580,6 @@ Would return: true
Would return: false
-
- *Type*: rvalue
merge
@@ -405,15 +596,20 @@ For example:
When there is a duplicate key, the key in the rightmost hash will "win."
+- *Type*: rvalue
+min
+---
+Returns the lowest value of all arguments.
+Requires at least one argument.
- *Type*: rvalue
num2bool
--------
-This function converts a number into a true boolean. Zero becomes false. Numbers
-higher then 0 become true.
-
+This function converts a number or a string representation of a number into a
+true boolean. Zero or anything non-numeric becomes false. Numbers higher then 0
+become true.
- *Type*: rvalue
@@ -422,7 +618,6 @@ parsejson
This function accepts JSON as a string and converts into the correct Puppet
structure.
-
- *Type*: rvalue
parseyaml
@@ -430,6 +625,22 @@ parseyaml
This function accepts YAML as a string and converts it into the correct
Puppet structure.
+- *Type*: rvalue
+
+pick
+----
+This function is similar to a coalesce function in SQL in that it will return
+the first value in a list of values that is not undefined or an empty string
+(two things in Puppet that will return a boolean false value). Typically,
+this function is used to check for a value in the Puppet Dashboard/Enterprise
+Console, and failover to a default value like the following:
+
+ $real_jenkins_version = pick($::jenkins_version, '1.449')
+
+The value of $real_jenkins_version will first look for a top-scope variable
+called 'jenkins_version' (note that parameters set in the Puppet Dashboard/
+Enterprise Console are brought into Puppet as top-scope variables), and,
+failing that, will use a default value of 1.449.
- *Type*: rvalue
@@ -437,13 +648,12 @@ prefix
------
This function applies a prefix to all elements in an array.
-*Examles:*
+*Examples:*
prefix(['a','b','c'], 'p')
Will return: ['pa','pb','pc']
-
- *Type*: rvalue
range
@@ -470,6 +680,21 @@ Will return: ["a","b","c"]
Will return: ["host01", "host02", ..., "host09", "host10"]
+- *Type*: rvalue
+
+reject
+------
+This function searches through an array and rejects all elements that match
+the provided regular expression.
+
+*Examples:*
+
+ reject(['aaa','bbb','ccc','aaaddd'], 'aaa')
+
+Would return:
+
+ ['bbb','ccc']
+
- *Type*: rvalue
@@ -477,35 +702,30 @@ reverse
-------
Reverses the order of a string or array.
-
- *Type*: rvalue
rstrip
------
Strips leading spaces to the right of the string.
-
- *Type*: rvalue
shuffle
-------
Randomizes the order of a string or array elements.
-
- *Type*: rvalue
size
----
Returns the number of elements in a string or array.
-
- *Type*: rvalue
sort
----
Sorts strings and arrays lexically.
-
- *Type*: rvalue
squeeze
@@ -513,7 +733,6 @@ squeeze
Returns a new string where runs of the same character that occur in this set
are replaced by a single character.
-
- *Type*: rvalue
str2bool
@@ -527,10 +746,10 @@ like: 0, f, n, false, no to 'false'.
str2saltedsha512
----------------
-This converts a string to a salted-SHA512 password hash (which is used for OS X
-versions >= 10.7). Given any simple string, you will get a hex version of a
-salted-SHA512 password hash that can be inserted into your Puppet manifests as
-a valid password attribute.
+This converts a string to a salted-SHA512 password hash (which is used for
+OS X versions >= 10.7). Given any simple string, you will get a hex version
+of a salted-SHA512 password hash that can be inserted into your Puppet
+manifests as a valid password attribute.
- *Type*: rvalue
@@ -619,6 +838,19 @@ Would result in: "aaa"
- *Type*: rvalue
+suffix
+------
+This function applies a suffix to all elements in an array.
+
+*Examples:*
+
+ suffix(['a','b','c'], 'p')
+
+Will return: ['ap','bp','cp']
+
+
+- *Type*: rvalue
+
swapcase
--------
This function will swap the existing case of a string.
@@ -667,6 +899,17 @@ Returns the type when passed a variable. Type can be one of:
- *Type*: rvalue
+union
+-----
+This function returns a union of two arrays.
+
+*Examples:*
+
+ union(["a","b","c"],["b","c","d"])
+
+Would return: ["a","b","c","d"]
+
+
unique
------
This function will remove duplicates from strings and arrays.
@@ -705,6 +948,14 @@ Will return:
- *Type*: rvalue
+uriescape
+---------
+Urlencodes a string or array of strings.
+Requires either a single string or an array as an input.
+
+
+- *Type*: rvalue
+
validate_absolute_path
----------------------
Validate the string represents an absolute path in the filesystem. This function works
@@ -751,6 +1002,39 @@ The following values will fail, causing compilation to abort:
- *Type*: statement
+validate_augeas
+---------------
+Perform validation of a string using an Augeas lens
+The first argument of this function should be a string to
+test, and the second argument should be the name of the Augeas lens to use.
+If Augeas fails to parse the string with the lens, the compilation will
+abort with a parse error.
+
+A third argument can be specified, listing paths which should
+not be found in the file. The `$file` variable points to the location
+of the temporary file being tested in the Augeas tree.
+
+For example, if you want to make sure your passwd content never contains
+a user `foo`, you could write:
+
+ validate_augeas($passwdcontent, 'Passwd.lns', ['$file/foo'])
+
+Or if you wanted to ensure that no users used the '/bin/barsh' shell,
+you could use:
+
+ validate_augeas($passwdcontent, 'Passwd.lns', ['$file/*[shell="/bin/barsh"]']
+
+If a fourth argument is specified, this will be the error message raised and
+seen by the user.
+
+A helpful error message can be returned like this:
+
+ validate_augeas($sudoerscontent, 'Sudoers.lns', [], 'Failed to validate sudoers content with Augeas')
+
+
+
+- *Type*: statement
+
validate_bool
-------------
Validate that all passed values are either true or false. Abort catalog
@@ -773,6 +1057,28 @@ The following values will fail, causing compilation to abort:
- *Type*: statement
+validate_cmd
+------------
+Perform validation of a string with an external command.
+The first argument of this function should be a string to
+test, and the second argument should be a path to a test command
+taking a file as last argument. If the command, launched against
+a tempfile containing the passed string, returns a non-null value,
+compilation will abort with a parse error.
+
+If a third argument is specified, this will be the error message raised and
+seen by the user.
+
+A helpful error message can be returned like this:
+
+Example:
+
+ validate_cmd($sudoerscontent, '/usr/sbin/visudo -c -f', 'Visudo failed to validate sudoers content')
+
+
+
+- *Type*: statement
+
validate_hash
-------------
Validate that all passed values are hash data structures. Abort catalog
@@ -862,7 +1168,6 @@ The following values will fail, causing compilation to abort:
validate_string($undefined)
-
- *Type*: statement
values
@@ -927,3 +1232,5 @@ Would result in:
- *Type*: rvalue
+
+*This page autogenerated on 2013-04-11 13:54:25 -0700*
diff --git a/README_SPECS.markdown b/README_SPECS.markdown
new file mode 100644
index 0000000..917b631
--- /dev/null
+++ b/README_SPECS.markdown
@@ -0,0 +1,7 @@
+NOTE
+====
+
+This project's specs depend on puppet core, and thus they require the
+`puppetlabs_spec_helper` project. For more information please see the README
+in that project, which can be found here: [puppetlabs spec
+helper](https://github.com/puppetlabs/puppetlabs_spec_helper)
diff --git a/lib/facter/facter_dot_d.rb b/lib/facter/facter_dot_d.rb
new file mode 100644
index 0000000..e414b20
--- /dev/null
+++ b/lib/facter/facter_dot_d.rb
@@ -0,0 +1,202 @@
+# A Facter plugin that loads facts from /etc/facter/facts.d
+# and /etc/puppetlabs/facter/facts.d.
+#
+# Facts can be in the form of JSON, YAML or Text files
+# and any executable that returns key=value pairs.
+#
+# In the case of scripts you can also create a file that
+# contains a cache TTL. For foo.sh store the ttl as just
+# a number in foo.sh.ttl
+#
+# The cache is stored in /tmp/facts_cache.yaml as a mode
+# 600 file and will have the end result of not calling your
+# fact scripts more often than is needed
+
+class Facter::Util::DotD
+ require 'yaml'
+
+ def initialize(dir="/etc/facts.d", cache_file="/tmp/facts_cache.yml")
+ @dir = dir
+ @cache_file = cache_file
+ @cache = nil
+ @types = {".txt" => :txt, ".json" => :json, ".yaml" => :yaml}
+ end
+
+ def entries
+ Dir.entries(@dir).reject{|f| f =~ /^\.|\.ttl$/}.sort.map {|f| File.join(@dir, f) }
+ rescue
+ []
+ end
+
+ def fact_type(file)
+ extension = File.extname(file)
+
+ type = @types[extension] || :unknown
+
+ type = :script if type == :unknown && File.executable?(file)
+
+ return type
+ end
+
+ def txt_parser(file)
+ File.readlines(file).each do |line|
+ if line =~ /^(.+)=(.+)$/
+ var = $1; val = $2
+
+ Facter.add(var) do
+ setcode { val }
+ end
+ end
+ end
+ rescue Exception => e
+ Facter.warn("Failed to handle #{file} as text facts: #{e.class}: #{e}")
+ end
+
+ def json_parser(file)
+ begin
+ require 'json'
+ rescue LoadError
+ retry if require 'rubygems'
+ raise
+ end
+
+ JSON.load(File.read(file)).each_pair do |f, v|
+ Facter.add(f) do
+ setcode { v }
+ end
+ end
+ rescue Exception => e
+ Facter.warn("Failed to handle #{file} as json facts: #{e.class}: #{e}")
+ end
+
+ def yaml_parser(file)
+ require 'yaml'
+
+ YAML.load_file(file).each_pair do |f, v|
+ Facter.add(f) do
+ setcode { v }
+ end
+ end
+ rescue Exception => e
+ Facter.warn("Failed to handle #{file} as yaml facts: #{e.class}: #{e}")
+ end
+
+ def script_parser(file)
+ result = cache_lookup(file)
+ ttl = cache_time(file)
+
+ unless result
+ result = Facter::Util::Resolution.exec(file)
+
+ if ttl > 0
+ Facter.debug("Updating cache for #{file}")
+ cache_store(file, result)
+ cache_save!
+ end
+ else
+ Facter.debug("Using cached data for #{file}")
+ end
+
+ result.split("\n").each do |line|
+ if line =~ /^(.+)=(.+)$/
+ var = $1; val = $2
+
+ Facter.add(var) do
+ setcode { val }
+ end
+ end
+ end
+ rescue Exception => e
+ Facter.warn("Failed to handle #{file} as script facts: #{e.class}: #{e}")
+ Facter.debug(e.backtrace.join("\n\t"))
+ end
+
+ def cache_save!
+ cache = load_cache
+ File.open(@cache_file, "w", 0600) {|f| f.write(YAML.dump(cache)) }
+ rescue
+ end
+
+ def cache_store(file, data)
+ load_cache
+
+ @cache[file] = {:data => data, :stored => Time.now.to_i}
+ rescue
+ end
+
+ def cache_lookup(file)
+ cache = load_cache
+
+ return nil if cache.empty?
+
+ ttl = cache_time(file)
+
+ if cache[file]
+ now = Time.now.to_i
+
+ return cache[file][:data] if ttl == -1
+ return cache[file][:data] if (now - cache[file][:stored]) <= ttl
+ return nil
+ else
+ return nil
+ end
+ rescue
+ return nil
+ end
+
+ def cache_time(file)
+ meta = file + ".ttl"
+
+ return File.read(meta).chomp.to_i
+ rescue
+ return 0
+ end
+
+ def load_cache
+ unless @cache
+ if File.exist?(@cache_file)
+ @cache = YAML.load_file(@cache_file)
+ else
+ @cache = {}
+ end
+ end
+
+ return @cache
+ rescue
+ @cache = {}
+ return @cache
+ end
+
+ def create
+ entries.each do |fact|
+ type = fact_type(fact)
+ parser = "#{type}_parser"
+
+ if respond_to?("#{type}_parser")
+ Facter.debug("Parsing #{fact} using #{parser}")
+
+ send(parser, fact)
+ end
+ end
+ end
+end
+
+
+mdata = Facter.version.match(/(\d+)\.(\d+)\.(\d+)/)
+if mdata
+ (major, minor, patch) = mdata.captures.map { |v| v.to_i }
+ if major < 2
+ # Facter 1.7 introduced external facts support directly
+ unless major == 1 and minor > 6
+ Facter::Util::DotD.new("/etc/facter/facts.d").create
+ Facter::Util::DotD.new("/etc/puppetlabs/facter/facts.d").create
+
+ # Windows has a different configuration directory that defaults to a vendor
+ # specific sub directory of the %COMMON_APPDATA% directory.
+ if Dir.const_defined? 'COMMON_APPDATA' then
+ windows_facts_dot_d = File.join(Dir::COMMON_APPDATA, 'PuppetLabs', 'facter', 'facts.d')
+ Facter::Util::DotD.new(windows_facts_dot_d).create
+ end
+ end
+ end
+end
diff --git a/lib/puppet/parser/functions/any2array.rb b/lib/puppet/parser/functions/any2array.rb
new file mode 100644
index 0000000..e71407e
--- /dev/null
+++ b/lib/puppet/parser/functions/any2array.rb
@@ -0,0 +1,33 @@
+#
+# any2array.rb
+#
+
+module Puppet::Parser::Functions
+ newfunction(:any2array, :type => :rvalue, :doc => <<-EOS
+This converts any object to an array containing that object. Empty argument
+lists are converted to an empty array. Arrays are left untouched. Hashes are
+converted to arrays of alternating keys and values.
+ EOS
+ ) do |arguments|
+
+ if arguments.empty?
+ return []
+ end
+
+ if arguments.length == 1
+ if arguments[0].kind_of?(Array)
+ return arguments[0]
+ elsif arguments[0].kind_of?(Hash)
+ result = []
+ arguments[0].each do |key, value|
+ result << key << value
+ end
+ return result
+ end
+ end
+
+ return arguments
+ end
+end
+
+# vim: set ts=2 sw=2 et :
diff --git a/lib/puppet/parser/functions/base64.rb b/lib/puppet/parser/functions/base64.rb
new file mode 100644
index 0000000..d9a590a
--- /dev/null
+++ b/lib/puppet/parser/functions/base64.rb
@@ -0,0 +1,37 @@
+module Puppet::Parser::Functions
+
+ newfunction(:base64, :type => :rvalue, :doc => <<-'ENDHEREDOC') do |args|
+
+ Base64 encode or decode a string based on the command and the string submitted
+
+ Usage:
+
+ $encodestring = base64('encode','thestring')
+ $decodestring = base64('decode','dGhlc3RyaW5n')
+
+ ENDHEREDOC
+
+ require 'base64'
+
+ raise Puppet::ParseError, ("base64(): Wrong number of arguments (#{args.length}; must be = 2)") unless args.length == 2
+
+ actions = ['encode','decode']
+
+ unless actions.include?(args[0])
+ raise Puppet::ParseError, ("base64(): the first argument must be one of 'encode' or 'decode'")
+ end
+
+ unless args[1].is_a?(String)
+ raise Puppet::ParseError, ("base64(): the second argument must be a string to base64")
+ end
+
+ case args[0]
+ when 'encode'
+ result = Base64.encode64(args[1])
+ when 'decode'
+ result = Base64.decode64(args[1])
+ end
+
+ return result
+ end
+end
diff --git a/lib/puppet/parser/functions/concat.rb b/lib/puppet/parser/functions/concat.rb
new file mode 100644
index 0000000..c86aa00
--- /dev/null
+++ b/lib/puppet/parser/functions/concat.rb
@@ -0,0 +1,37 @@
+#
+# concat.rb
+#
+
+module Puppet::Parser::Functions
+ newfunction(:concat, :type => :rvalue, :doc => <<-EOS
+Appends the contents of array 2 onto array 1.
+
+*Example:*
+
+ concat(['1','2','3'],['4','5','6'])
+
+Would result in:
+
+ ['1','2','3','4','5','6']
+ EOS
+ ) do |arguments|
+
+ # Check that 2 arguments have been given ...
+ raise(Puppet::ParseError, "concat(): Wrong number of arguments " +
+ "given (#{arguments.size} for 2)") if arguments.size != 2
+
+ a = arguments[0]
+ b = arguments[1]
+
+ # Check that both args are arrays.
+ unless a.is_a?(Array) and b.is_a?(Array)
+ raise(Puppet::ParseError, 'concat(): Requires array to work with')
+ end
+
+ result = a.concat(b)
+
+ return result
+ end
+end
+
+# vim: set ts=2 sw=2 et :
diff --git a/lib/puppet/parser/functions/count.rb b/lib/puppet/parser/functions/count.rb
new file mode 100644
index 0000000..52de1b8
--- /dev/null
+++ b/lib/puppet/parser/functions/count.rb
@@ -0,0 +1,22 @@
+module Puppet::Parser::Functions
+ newfunction(:count, :type => :rvalue, :arity => -2, :doc => <<-EOS
+Takes an array as first argument and an optional second argument.
+Count the number of elements in array that matches second argument.
+If called with only an array it counts the number of elements that are not nil/undef.
+ EOS
+ ) do |args|
+
+ if (args.size > 2) then
+ raise(ArgumentError, "count(): Wrong number of arguments "+
+ "given #{args.size} for 1 or 2.")
+ end
+
+ collection, item = args
+
+ if item then
+ collection.count item
+ else
+ collection.count { |obj| obj != nil && obj != :undef && obj != '' }
+ end
+ end
+end
diff --git a/lib/puppet/parser/functions/difference.rb b/lib/puppet/parser/functions/difference.rb
new file mode 100644
index 0000000..cd258f7
--- /dev/null
+++ b/lib/puppet/parser/functions/difference.rb
@@ -0,0 +1,36 @@
+#
+# difference.rb
+#
+
+module Puppet::Parser::Functions
+ newfunction(:difference, :type => :rvalue, :doc => <<-EOS
+This function returns the difference between two arrays.
+The returned array is a copy of the original array, removing any items that
+also appear in the second array.
+
+*Examples:*
+
+ difference(["a","b","c"],["b","c","d"])
+
+Would return: ["a"]
+ EOS
+ ) do |arguments|
+
+ # Two arguments are required
+ raise(Puppet::ParseError, "difference(): Wrong number of arguments " +
+ "given (#{arguments.size} for 2)") if arguments.size != 2
+
+ first = arguments[0]
+ second = arguments[1]
+
+ unless first.is_a?(Array) && second.is_a?(Array)
+ raise(Puppet::ParseError, 'difference(): Requires 2 arrays')
+ end
+
+ result = first - second
+
+ return result
+ end
+end
+
+# vim: set ts=2 sw=2 et :
diff --git a/lib/puppet/parser/functions/dirname.rb b/lib/puppet/parser/functions/dirname.rb
new file mode 100644
index 0000000..ea8cc1e
--- /dev/null
+++ b/lib/puppet/parser/functions/dirname.rb
@@ -0,0 +1,15 @@
+module Puppet::Parser::Functions
+ newfunction(:dirname, :type => :rvalue, :doc => <<-EOS
+ Returns the dirname of a path.
+ EOS
+ ) do |arguments|
+
+ raise(Puppet::ParseError, "dirname(): Wrong number of arguments " +
+ "given (#{arguments.size} for 1)") if arguments.size < 1
+
+ path = arguments[0]
+ return File.dirname(path)
+ end
+end
+
+# vim: set ts=2 sw=2 et :
diff --git a/lib/puppet/parser/functions/ensure_resource.rb b/lib/puppet/parser/functions/ensure_resource.rb
index fba2035..a9a1733 100644
--- a/lib/puppet/parser/functions/ensure_resource.rb
+++ b/lib/puppet/parser/functions/ensure_resource.rb
@@ -19,17 +19,27 @@ If the resource already exists but does not match the specified parameters,
this function will attempt to recreate the resource leading to a duplicate
resource definition error.
+An array of resources can also be passed in and each will be created with
+the type and parameters specified if it doesn't already exist.
+
+ ensure_resource('user', ['dan','alex'], {'ensure' => 'present'})
+
ENDOFDOC
) do |vals|
type, title, params = vals
raise(ArgumentError, 'Must specify a type') unless type
raise(ArgumentError, 'Must specify a title') unless title
params ||= {}
- Puppet::Parser::Functions.function(:defined_with_params)
- if function_defined_with_params(["#{type}[#{title}]", params])
- Puppet.debug("Resource #{type}[#{title}] not created b/c it already exists")
- else
- Puppet::Parser::Functions.function(:create_resources)
- function_create_resources([type.capitalize, { title => params }])
+
+ items = [title].flatten
+
+ items.each do |item|
+ Puppet::Parser::Functions.function(:defined_with_params)
+ if function_defined_with_params(["#{type}[#{item}]", params])
+ Puppet.debug("Resource #{type}[#{item}] not created because it already exists")
+ else
+ Puppet::Parser::Functions.function(:create_resources)
+ function_create_resources([type.capitalize, { item => params }])
+ end
end
end
diff --git a/lib/puppet/parser/functions/flatten.rb b/lib/puppet/parser/functions/flatten.rb
index 781da78..a1ed183 100644
--- a/lib/puppet/parser/functions/flatten.rb
+++ b/lib/puppet/parser/functions/flatten.rb
@@ -16,7 +16,7 @@ Would return: ['a','b','c']
) do |arguments|
raise(Puppet::ParseError, "flatten(): Wrong number of arguments " +
- "given (#{arguments.size} for 1)") if arguments.size < 1
+ "given (#{arguments.size} for 1)") if arguments.size != 1
array = arguments[0]
diff --git a/lib/puppet/parser/functions/floor.rb b/lib/puppet/parser/functions/floor.rb
new file mode 100644
index 0000000..a401923
--- /dev/null
+++ b/lib/puppet/parser/functions/floor.rb
@@ -0,0 +1,20 @@
+module Puppet::Parser::Functions
+ newfunction(:floor, :type => :rvalue, :doc => <<-EOS
+ Returns the largest integer less or equal to the argument.
+ Takes a single numeric value as an argument.
+ EOS
+ ) do |arguments|
+
+ raise(Puppet::ParseError, "floor(): Wrong number of arguments " +
+ "given (#{arguments.size} for 1)") if arguments.size != 1
+
+ arg = arguments[0]
+
+ raise(Puppet::ParseError, "floor(): Wrong argument type " +
+ "given (#{arg.class} for Numeric)") if arg.is_a?(Numeric) == false
+
+ arg.floor
+ end
+end
+
+# vim: set ts=2 sw=2 et :
diff --git a/lib/puppet/parser/functions/getparam.rb b/lib/puppet/parser/functions/getparam.rb
new file mode 100644
index 0000000..6d51006
--- /dev/null
+++ b/lib/puppet/parser/functions/getparam.rb
@@ -0,0 +1,35 @@
+# Test whether a given class or definition is defined
+require 'puppet/parser/functions'
+
+Puppet::Parser::Functions.newfunction(:getparam,
+ :type => :rvalue,
+ :doc => <<-'ENDOFDOC'
+Takes a resource reference and name of the parameter and
+returns value of resource's parameter.
+
+*Examples:*
+
+ define example_resource($param) {
+ }
+
+ example_resource { "example_resource_instance":
+ param => "param_value"
+ }
+
+ getparam(Example_resource["example_resource_instance"], "param")
+
+Would return: param_value
+ENDOFDOC
+) do |vals|
+ reference, param = vals
+ raise(ArgumentError, 'Must specify a reference') unless reference
+ raise(ArgumentError, 'Must specify name of a parameter') unless param and param.instance_of? String
+
+ return '' if param.empty?
+
+ if resource = findresource(reference.to_s)
+ return resource[param] if resource[param]
+ end
+
+ return ''
+end
diff --git a/lib/puppet/parser/functions/hash.rb b/lib/puppet/parser/functions/hash.rb
index 453ba1e..8cc4823 100644
--- a/lib/puppet/parser/functions/hash.rb
+++ b/lib/puppet/parser/functions/hash.rb
@@ -4,7 +4,7 @@
module Puppet::Parser::Functions
newfunction(:hash, :type => :rvalue, :doc => <<-EOS
-This function converts and array into a hash.
+This function converts an array into a hash.
*Examples:*
diff --git a/lib/puppet/parser/functions/intersection.rb b/lib/puppet/parser/functions/intersection.rb
new file mode 100644
index 0000000..48f02e9
--- /dev/null
+++ b/lib/puppet/parser/functions/intersection.rb
@@ -0,0 +1,34 @@
+#
+# intersection.rb
+#
+
+module Puppet::Parser::Functions
+ newfunction(:intersection, :type => :rvalue, :doc => <<-EOS
+This function returns an array an intersection of two.
+
+*Examples:*
+
+ intersection(["a","b","c"],["b","c","d"])
+
+Would return: ["b","c"]
+ EOS
+ ) do |arguments|
+
+ # Two arguments are required
+ raise(Puppet::ParseError, "intersection(): Wrong number of arguments " +
+ "given (#{arguments.size} for 2)") if arguments.size != 2
+
+ first = arguments[0]
+ second = arguments[1]
+
+ unless first.is_a?(Array) && second.is_a?(Array)
+ raise(Puppet::ParseError, 'intersection(): Requires 2 arrays')
+ end
+
+ result = first & second
+
+ return result
+ end
+end
+
+# vim: set ts=2 sw=2 et :
diff --git a/lib/puppet/parser/functions/is_float.rb b/lib/puppet/parser/functions/is_float.rb
index 2fc05ba..911f3c2 100644
--- a/lib/puppet/parser/functions/is_float.rb
+++ b/lib/puppet/parser/functions/is_float.rb
@@ -15,7 +15,7 @@ Returns true if the variable passed to this function is a float.
value = arguments[0]
- if value != value.to_f.to_s then
+ if value != value.to_f.to_s and !value.is_a? Float then
return false
else
return true
diff --git a/lib/puppet/parser/functions/is_function_available.rb b/lib/puppet/parser/functions/is_function_available.rb
new file mode 100644
index 0000000..6cbd35c
--- /dev/null
+++ b/lib/puppet/parser/functions/is_function_available.rb
@@ -0,0 +1,23 @@
+#
+# is_function_available.rb
+#
+
+module Puppet::Parser::Functions
+ newfunction(:is_function_available, :type => :rvalue, :doc => <<-EOS
+This function accepts a string as an argument, determines whether the
+Puppet runtime has access to a function by that name. It returns a
+true if the function exists, false if not.
+ EOS
+ ) do |arguments|
+
+ if (arguments.size != 1) then
+ raise(Puppet::ParseError, "is_function_available?(): Wrong number of arguments "+
+ "given #{arguments.size} for 1")
+ end
+
+ function = Puppet::Parser::Functions.function(arguments[0].to_sym)
+ function.is_a?(String) and not function.empty?
+ end
+end
+
+# vim: set ts=2 sw=2 et :
diff --git a/lib/puppet/parser/functions/is_integer.rb b/lib/puppet/parser/functions/is_integer.rb
index 8ee34f6..6b29e98 100644
--- a/lib/puppet/parser/functions/is_integer.rb
+++ b/lib/puppet/parser/functions/is_integer.rb
@@ -15,7 +15,7 @@ Returns true if the variable returned to this string is an integer.
value = arguments[0]
- if value != value.to_i.to_s then
+ if value != value.to_i.to_s and !value.is_a? Fixnum then
return false
else
return true
diff --git a/lib/puppet/parser/functions/is_numeric.rb b/lib/puppet/parser/functions/is_numeric.rb
index ce13ece..abf0321 100644
--- a/lib/puppet/parser/functions/is_numeric.rb
+++ b/lib/puppet/parser/functions/is_numeric.rb
@@ -15,7 +15,7 @@ Returns true if the variable passed to this function is a number.
value = arguments[0]
- if value == value.to_f.to_s or value == value.to_i.to_s then
+ if value == value.to_f.to_s or value == value.to_i.to_s or value.is_a? Numeric then
return true
else
return false
diff --git a/lib/puppet/parser/functions/max.rb b/lib/puppet/parser/functions/max.rb
index 10b6f74..60fb94a 100644
--- a/lib/puppet/parser/functions/max.rb
+++ b/lib/puppet/parser/functions/max.rb
@@ -8,6 +8,14 @@ module Puppet::Parser::Functions
raise(Puppet::ParseError, "max(): Wrong number of arguments " +
"need at least one") if args.size == 0
- return args.max
+ # Sometimes we get numbers as numerics and sometimes as strings.
+ # We try to compare them as numbers when possible
+ return args.max do |a,b|
+ if a.to_s =~ /\A-?\d+(.\d+)?\z/ and b.to_s =~ /\A-?\d+(.\d+)?\z/ then
+ a.to_f <=> b.to_f
+ else
+ a.to_s <=> b.to_s
+ end
+ end
end
end
diff --git a/lib/puppet/parser/functions/merge.rb b/lib/puppet/parser/functions/merge.rb
index 6ec085e..1b39f20 100644
--- a/lib/puppet/parser/functions/merge.rb
+++ b/lib/puppet/parser/functions/merge.rb
@@ -22,6 +22,7 @@ module Puppet::Parser::Functions
accumulator = Hash.new
# Merge into the accumulator hash
args.each do |arg|
+ next if arg.is_a? String and arg.empty? # empty string is synonym for puppet's undef
unless arg.is_a?(Hash)
raise Puppet::ParseError, "merge: unexpected argument type #{arg.class}, only expects hash arguments"
end
diff --git a/lib/puppet/parser/functions/min.rb b/lib/puppet/parser/functions/min.rb
index abf1b62..6bd6ebf 100644
--- a/lib/puppet/parser/functions/min.rb
+++ b/lib/puppet/parser/functions/min.rb
@@ -8,6 +8,14 @@ module Puppet::Parser::Functions
raise(Puppet::ParseError, "min(): Wrong number of arguments " +
"need at least one") if args.size == 0
- return args.min
+ # Sometimes we get numbers as numerics and sometimes as strings.
+ # We try to compare them as numbers when possible
+ return args.min do |a,b|
+ if a.to_s =~ /\A^-?\d+(.\d+)?\z/ and b.to_s =~ /\A-?\d+(.\d+)?\z/ then
+ a.to_f <=> b.to_f
+ else
+ a.to_s <=> b.to_s
+ end
+ end
end
end
diff --git a/lib/puppet/parser/functions/num2bool.rb b/lib/puppet/parser/functions/num2bool.rb
index 874db22..af0e6ed 100644
--- a/lib/puppet/parser/functions/num2bool.rb
+++ b/lib/puppet/parser/functions/num2bool.rb
@@ -2,38 +2,41 @@
# num2bool.rb
#
-# TODO(Krzysztof Wilczynski): We probably need to approach numeric values differently ...
-
module Puppet::Parser::Functions
newfunction(:num2bool, :type => :rvalue, :doc => <<-EOS
-This function converts a number into a true boolean. Zero becomes false. Numbers
-higher then 0 become true.
+This function converts a number or a string representation of a number into a
+true boolean. Zero or anything non-numeric becomes false. Numbers higher then 0
+become true.
EOS
) do |arguments|
raise(Puppet::ParseError, "num2bool(): Wrong number of arguments " +
- "given (#{arguments.size} for 1)") if arguments.size < 1
+ "given (#{arguments.size} for 1)") if arguments.size != 1
number = arguments[0]
- # Only numbers allowed ...
- unless number.match(/^\-?\d+$/)
- raise(Puppet::ParseError, 'num2bool(): Requires integer to work with')
+ case number
+ when Numeric
+ # Yay, it's a number
+ when String
+ begin
+ number = Float(number)
+ rescue ArgumentError => ex
+ raise(Puppet::ParseError, "num2bool(): '#{number}' does not look like a number: #{ex.message}")
+ end
+ else
+ begin
+ number = number.to_s
+ rescue NoMethodError => ex
+ raise(Puppet::ParseError, "num2bool(): Unable to parse argument: #{ex.message}")
+ end
end
- result = case number
- when /^0$/
- false
- when /^\-?\d+$/
- # Numbers in Puppet are often string-encoded which is troublesome ...
- number = number.to_i
- # We yield true for any positive number and false otherwise ...
- number > 0 ? true : false
- else
- raise(Puppet::ParseError, 'num2bool(): Unknown numeric format given')
- end
+ # Truncate Floats
+ number = number.to_i
- return result
+ # Return true for any positive number and false otherwise
+ return number > 0
end
end
diff --git a/lib/puppet/parser/functions/prefix.rb b/lib/puppet/parser/functions/prefix.rb
index 4593976..62211ae 100644
--- a/lib/puppet/parser/functions/prefix.rb
+++ b/lib/puppet/parser/functions/prefix.rb
@@ -6,7 +6,7 @@ module Puppet::Parser::Functions
newfunction(:prefix, :type => :rvalue, :doc => <<-EOS
This function applies a prefix to all elements in an array.
-*Examles:*
+*Examples:*
prefix(['a','b','c'], 'p')
@@ -21,14 +21,14 @@ Will return: ['pa','pb','pc']
array = arguments[0]
unless array.is_a?(Array)
- raise(Puppet::ParseError, 'prefix(): Requires array to work with')
+ raise Puppet::ParseError, "prefix(): expected first argument to be an Array, got #{array.inspect}"
end
prefix = arguments[1] if arguments[1]
if prefix
unless prefix.is_a?(String)
- raise(Puppet::ParseError, 'prefix(): Requires string to work with')
+ raise Puppet::ParseError, "prefix(): expected second argument to be a String, got #{suffix.inspect}"
end
end
diff --git a/lib/puppet/parser/functions/str2bool.rb b/lib/puppet/parser/functions/str2bool.rb
index 0509c2b..fece7a6 100644
--- a/lib/puppet/parser/functions/str2bool.rb
+++ b/lib/puppet/parser/functions/str2bool.rb
@@ -14,6 +14,11 @@ like: 0, f, n, false, no to 'false'.
"given (#{arguments.size} for 1)") if arguments.size < 1
string = arguments[0]
+
+ # If string is already Boolean, return it
+ if !!string == string
+ return string
+ end
unless string.is_a?(String)
raise(Puppet::ParseError, 'str2bool(): Requires either ' +
diff --git a/lib/puppet/parser/functions/suffix.rb b/lib/puppet/parser/functions/suffix.rb
new file mode 100644
index 0000000..f7792d6
--- /dev/null
+++ b/lib/puppet/parser/functions/suffix.rb
@@ -0,0 +1,45 @@
+#
+# suffix.rb
+#
+
+module Puppet::Parser::Functions
+ newfunction(:suffix, :type => :rvalue, :doc => <<-EOS
+This function applies a suffix to all elements in an array.
+
+*Examples:*
+
+ suffix(['a','b','c'], 'p')
+
+Will return: ['ap','bp','cp']
+ EOS
+ ) do |arguments|
+
+ # Technically we support two arguments but only first is mandatory ...
+ raise(Puppet::ParseError, "suffix(): Wrong number of arguments " +
+ "given (#{arguments.size} for 1)") if arguments.size < 1
+
+ array = arguments[0]
+
+ unless array.is_a?(Array)
+ raise Puppet::ParseError, "suffix(): expected first argument to be an Array, got #{array.inspect}"
+ end
+
+ suffix = arguments[1] if arguments[1]
+
+ if suffix
+ unless suffix.is_a? String
+ raise Puppet::ParseError, "suffix(): expected second argument to be a String, got #{suffix.inspect}"
+ end
+ end
+
+ # Turn everything into string same as join would do ...
+ result = array.collect do |i|
+ i = i.to_s
+ suffix ? i + suffix : i
+ end
+
+ return result
+ end
+end
+
+# vim: set ts=2 sw=2 et :
diff --git a/lib/puppet/parser/functions/union.rb b/lib/puppet/parser/functions/union.rb
new file mode 100644
index 0000000..c91bb80
--- /dev/null
+++ b/lib/puppet/parser/functions/union.rb
@@ -0,0 +1,34 @@
+#
+# union.rb
+#
+
+module Puppet::Parser::Functions
+ newfunction(:union, :type => :rvalue, :doc => <<-EOS
+This function returns a union of two arrays.
+
+*Examples:*
+
+ union(["a","b","c"],["b","c","d"])
+
+Would return: ["a","b","c","d"]
+ EOS
+ ) do |arguments|
+
+ # Two arguments are required
+ raise(Puppet::ParseError, "union(): Wrong number of arguments " +
+ "given (#{arguments.size} for 2)") if arguments.size != 2
+
+ first = arguments[0]
+ second = arguments[1]
+
+ unless first.is_a?(Array) && second.is_a?(Array)
+ raise(Puppet::ParseError, 'union(): Requires 2 arrays')
+ end
+
+ result = first | second
+
+ return result
+ end
+end
+
+# vim: set ts=2 sw=2 et :
diff --git a/lib/puppet/parser/functions/validate_augeas.rb b/lib/puppet/parser/functions/validate_augeas.rb
new file mode 100644
index 0000000..154d660
--- /dev/null
+++ b/lib/puppet/parser/functions/validate_augeas.rb
@@ -0,0 +1,81 @@
+module Puppet::Parser::Functions
+ newfunction(:validate_augeas, :doc => <<-'ENDHEREDOC') do |args|
+ Perform validation of a string using an Augeas lens
+ The first argument of this function should be a string to
+ test, and the second argument should be the name of the Augeas lens to use.
+ If Augeas fails to parse the string with the lens, the compilation will
+ abort with a parse error.
+
+ A third argument can be specified, listing paths which should
+ not be found in the file. The `$file` variable points to the location
+ of the temporary file being tested in the Augeas tree.
+
+ For example, if you want to make sure your passwd content never contains
+ a user `foo`, you could write:
+
+ validate_augeas($passwdcontent, 'Passwd.lns', ['$file/foo'])
+
+ Or if you wanted to ensure that no users used the '/bin/barsh' shell,
+ you could use:
+
+ validate_augeas($passwdcontent, 'Passwd.lns', ['$file/*[shell="/bin/barsh"]']
+
+ If a fourth argument is specified, this will be the error message raised and
+ seen by the user.
+
+ A helpful error message can be returned like this:
+
+ validate_augeas($sudoerscontent, 'Sudoers.lns', [], 'Failed to validate sudoers content with Augeas')
+
+ ENDHEREDOC
+ unless Puppet.features.augeas?
+ raise Puppet::ParseError, ("validate_augeas(): this function requires the augeas feature. See http://projects.puppetlabs.com/projects/puppet/wiki/Puppet_Augeas#Pre-requisites for how to activate it.")
+ end
+
+ if (args.length < 2) or (args.length > 4) then
+ raise Puppet::ParseError, ("validate_augeas(): wrong number of arguments (#{args.length}; must be 2, 3, or 4)")
+ end
+
+ msg = args[3] || "validate_augeas(): Failed to validate content against #{args[1].inspect}"
+
+ require 'augeas'
+ aug = Augeas::open(nil, nil, Augeas::NO_MODL_AUTOLOAD)
+ begin
+ content = args[0]
+
+ # Test content in a temporary file
+ tmpfile = Tempfile.new("validate_augeas")
+ begin
+ tmpfile.write(content)
+ ensure
+ tmpfile.close
+ end
+
+ # Check for syntax
+ lens = args[1]
+ aug.transform(
+ :lens => lens,
+ :name => 'Validate_augeas',
+ :incl => tmpfile.path
+ )
+ aug.load!
+
+ unless aug.match("/augeas/files#{tmpfile.path}//error").empty?
+ error = aug.get("/augeas/files#{tmpfile.path}//error/message")
+ msg += " with error: #{error}"
+ raise Puppet::ParseError, (msg)
+ end
+
+ # Launch unit tests
+ tests = args[2] || []
+ aug.defvar('file', "/files#{tmpfile.path}")
+ tests.each do |t|
+ msg += " testing path #{t}"
+ raise Puppet::ParseError, (msg) unless aug.match(t).empty?
+ end
+ ensure
+ aug.close
+ tmpfile.unlink
+ end
+ end
+end
diff --git a/lib/puppet/parser/functions/validate_cmd.rb b/lib/puppet/parser/functions/validate_cmd.rb
new file mode 100644
index 0000000..344a80c
--- /dev/null
+++ b/lib/puppet/parser/functions/validate_cmd.rb
@@ -0,0 +1,47 @@
+require 'puppet/util/execution'
+
+module Puppet::Parser::Functions
+ newfunction(:validate_cmd, :doc => <<-'ENDHEREDOC') do |args|
+ Perform validation of a string with an external command.
+ The first argument of this function should be a string to
+ test, and the second argument should be a path to a test command
+ taking a file as last argument. If the command, launched against
+ a tempfile containing the passed string, returns a non-null value,
+ compilation will abort with a parse error.
+
+ If a third argument is specified, this will be the error message raised and
+ seen by the user.
+
+ A helpful error message can be returned like this:
+
+ Example:
+
+ validate_cmd($sudoerscontent, '/usr/sbin/visudo -c -f', 'Visudo failed to validate sudoers content')
+
+ ENDHEREDOC
+ if (args.length < 2) or (args.length > 3) then
+ raise Puppet::ParseError, ("validate_cmd(): wrong number of arguments (#{args.length}; must be 2 or 3)")
+ end
+
+ msg = args[2] || "validate_cmd(): failed to validate content with command #{args[1].inspect}"
+
+ content = args[0]
+ checkscript = args[1]
+
+ # Test content in a temporary file
+ tmpfile = Tempfile.new("validate_cmd")
+ begin
+ tmpfile.write(content)
+ if Puppet::Util::Execution.respond_to?('execute')
+ Puppet::Util::Execution.execute("#{checkscript} #{tmpfile.path}")
+ else
+ Puppet::Util.execute("#{checkscript} #{tmpfile.path}")
+ end
+ rescue Puppet::ExecutionFailure => detail
+ msg += "\n#{detail}"
+ raise Puppet::ParseError, msg
+ ensure
+ tmpfile.unlink
+ end
+ end
+end
diff --git a/lib/puppet/provider/file_line/ruby.rb b/lib/puppet/provider/file_line/ruby.rb
index e21eaa8..a3219d3 100644
--- a/lib/puppet/provider/file_line/ruby.rb
+++ b/lib/puppet/provider/file_line/ruby.rb
@@ -34,7 +34,7 @@ Puppet::Type.type(:file_line).provide(:ruby) do
def handle_create_with_match()
regex = resource[:match] ? Regexp.new(resource[:match]) : nil
- match_count = lines.select { |l| regex.match(l) }.count
+ match_count = lines.select { |l| regex.match(l) }.size
if match_count > 1
raise Puppet::Error, "More than one line in file '#{resource[:path]}' matches pattern '#{resource[:match]}'"
end
diff --git a/lib/puppet/type/anchor.rb b/lib/puppet/type/anchor.rb
index 6b81732..fe1e5aa 100644
--- a/lib/puppet/type/anchor.rb
+++ b/lib/puppet/type/anchor.rb
@@ -38,4 +38,9 @@ Puppet::Type.newtype(:anchor) do
desc "The name of the anchor resource."
end
+ def refresh
+ # We don't do anything with them, but we need this to
+ # show that we are "refresh aware" and not break the
+ # chain of propagation.
+ end
end
diff --git a/spec/classes/anchor_spec.rb b/spec/classes/anchor_spec.rb
new file mode 100644
index 0000000..2dd17de
--- /dev/null
+++ b/spec/classes/anchor_spec.rb
@@ -0,0 +1,32 @@
+require 'puppet'
+require 'rspec-puppet'
+
+describe "anchorrefresh" do
+ let(:node) { 'testhost.example.com' }
+ let :pre_condition do
+ <<-ANCHORCLASS
+class anchored {
+ anchor { 'anchored::begin': }
+ ~> anchor { 'anchored::end': }
+}
+
+class anchorrefresh {
+ notify { 'first': }
+ ~> class { 'anchored': }
+ ~> anchor { 'final': }
+}
+ ANCHORCLASS
+ end
+
+ def apply_catalog_and_return_exec_rsrc
+ catalog = subject.to_ral
+ transaction = catalog.apply
+ transaction.resource_status("Anchor[final]")
+ end
+
+ it 'propagates events through the anchored class' do
+ resource = apply_catalog_and_return_exec_rsrc
+
+ expect(resource.restarted).to eq(true)
+ end
+end
diff --git a/spec/functions/ensure_resource_spec.rb b/spec/functions/ensure_resource_spec.rb
index 611666e..2e8aefc 100644
--- a/spec/functions/ensure_resource_spec.rb
+++ b/spec/functions/ensure_resource_spec.rb
@@ -4,17 +4,16 @@ require 'spec_helper'
require 'rspec-puppet'
describe 'ensure_resource' do
describe 'when a type or title is not specified' do
- it do
- should run.with_params().and_raise_error(ArgumentError)
- should run.with_params(['type']).and_raise_error(ArgumentError)
- end
+ it { should run.with_params().and_raise_error(ArgumentError) }
+ it { should run.with_params(['type']).and_raise_error(ArgumentError) }
end
+
describe 'when compared against a resource with no attributes' do
let :pre_condition do
'user { "dan": }'
end
- it do
- should run.with_params('user', 'dan', {})
+ it "should contain the the ensured resources" do
+ subject.should run.with_params('user', 'dan', {})
compiler.catalog.resource('User[dan]').to_s.should == 'User[dan]'
end
end
@@ -23,18 +22,43 @@ describe 'ensure_resource' do
let :pre_condition do
'user { "dan": ensure => present, shell => "/bin/csh", managehome => false}'
end
- it do
- # these first three should not fail
- should run.with_params('User', 'dan', {})
- should run.with_params('User', 'dan', '')
- should run.with_params('User', 'dan', {'ensure' => 'present'})
- should run.with_params('User', 'dan',
- {'ensure' => 'present', 'managehome' => false}
- )
- # test that this fails
- should run.with_params('User', 'dan',
- {'ensure' => 'absent', 'managehome' => false}
- ).and_raise_error(Puppet::Error)
+ # these first three should not fail
+ it { should run.with_params('User', 'dan', {}) }
+ it { should run.with_params('User', 'dan', '') }
+ it { should run.with_params('User', 'dan', {'ensure' => 'present'}) }
+ it { should run.with_params('User', 'dan', {'ensure' => 'present', 'managehome' => false}) }
+ # test that this fails
+ it { should run.with_params('User', 'dan', {'ensure' => 'absent', 'managehome' => false}).and_raise_error(Puppet::Error) }
+ end
+
+ describe 'when an array of new resources are passed in' do
+ it "should contain the ensured resources" do
+ subject.should run.with_params('User', ['dan', 'alex'], {})
+ compiler.catalog.resource('User[dan]').to_s.should == 'User[dan]'
+ compiler.catalog.resource('User[alex]').to_s.should == 'User[alex]'
+ end
+ end
+
+ describe 'when an array of existing resources is compared against existing resources' do
+ let :pre_condition do
+ 'user { "dan": ensure => present; "alex": ensure => present }'
+ end
+ it "should return the existing resources" do
+ subject.should run.with_params('User', ['dan', 'alex'], {})
+ compiler.catalog.resource('User[dan]').to_s.should == 'User[dan]'
+ compiler.catalog.resource('User[alex]').to_s.should == 'User[alex]'
+ end
+ end
+
+ describe 'when compared against existing resources with attributes' do
+ let :pre_condition do
+ 'user { "dan": ensure => present; "alex": ensure => present }'
end
+ # These should not fail
+ it { should run.with_params('User', ['dan', 'alex'], {}) }
+ it { should run.with_params('User', ['dan', 'alex'], '') }
+ it { should run.with_params('User', ['dan', 'alex'], {'ensure' => 'present'}) }
+ # This should fail
+ it { should run.with_params('User', ['dan', 'alex'], {'ensure' => 'absent'}).and_raise_error(Puppet::Error) }
end
end
diff --git a/spec/functions/getparam_spec.rb b/spec/functions/getparam_spec.rb
new file mode 100644
index 0000000..d9c50a6
--- /dev/null
+++ b/spec/functions/getparam_spec.rb
@@ -0,0 +1,34 @@
+#! /usr/bin/env ruby -S rspec
+require 'spec_helper'
+
+require 'rspec-puppet'
+describe 'getparam' do
+ describe 'when a resource is not specified' do
+ it do
+ should run.with_params().and_raise_error(ArgumentError)
+ should run.with_params('User[dan]').and_raise_error(ArgumentError)
+ should run.with_params('User[dan]', {}).and_raise_error(ArgumentError)
+ should run.with_params('User[dan]', '').and_return('')
+ end
+ end
+ describe 'when compared against a resource with no params' do
+ let :pre_condition do
+ 'user { "dan": }'
+ end
+ it do
+ should run.with_params('User[dan]', 'shell').and_return('')
+ end
+ end
+
+ describe 'when compared against a resource with params' do
+ let :pre_condition do
+ 'user { "dan": ensure => present, shell => "/bin/sh", managehome => false}'
+ end
+ it do
+ should run.with_params('User[dan]', 'shell').and_return('/bin/sh')
+ should run.with_params('User[dan]', '').and_return('')
+ should run.with_params('User[dan]', 'ensure').and_return('present')
+ should run.with_params('User[dan]', 'managehome').and_return(false)
+ end
+ end
+end
diff --git a/spec/unit/facter/pe_required_facts_spec.rb b/spec/unit/facter/pe_required_facts_spec.rb
new file mode 100644
index 0000000..f219b37
--- /dev/null
+++ b/spec/unit/facter/pe_required_facts_spec.rb
@@ -0,0 +1,69 @@
+# Puppet Enterprise requires the following facts to be set in order to operate.
+# These facts are set using the file ???? and the two facts are
+# `fact_stomp_port`, and `fact_stomp_server`.
+#
+
+require 'spec_helper'
+
+describe "External facts in /etc/puppetlabs/facter/facts.d/puppet_enterprise_installer.txt" do
+ context "With Facter 1.6.17 which does not have external facts support" do
+ before :each do
+ Facter.stubs(:version).returns("1.6.17")
+ # Stub out the filesystem for stdlib
+ Dir.stubs(:entries).with("/etc/puppetlabs/facter/facts.d").
+ returns(['puppet_enterprise_installer.txt'])
+ Dir.stubs(:entries).with("/etc/facter/facts.d").returns([])
+ File.stubs(:readlines).with('/etc/puppetlabs/facter/facts.d/puppet_enterprise_installer.txt').
+ returns([
+ "fact_stomp_port=61613\n",
+ "fact_stomp_server=puppetmaster.acme.com\n",
+ "fact_is_puppetagent=true\n",
+ "fact_is_puppetmaster=false\n",
+ "fact_is_puppetca=false\n",
+ "fact_is_puppetconsole=false\n",
+ ])
+ if Facter.collection.respond_to? :load
+ Facter.collection.load(:facter_dot_d)
+ else
+ Facter.collection.loader.load(:facter_dot_d)
+ end
+ end
+
+ it 'defines fact_stomp_port' do
+ Facter.fact(:fact_stomp_port).value.should == '61613'
+ end
+ it 'defines fact_stomp_server' do
+ Facter.fact(:fact_stomp_server).value.should == 'puppetmaster.acme.com'
+ end
+ it 'defines fact_is_puppetagent' do
+ Facter.fact(:fact_is_puppetagent).value.should == 'true'
+ end
+ it 'defines fact_is_puppetmaster' do
+ Facter.fact(:fact_is_puppetmaster).value.should == 'false'
+ end
+ it 'defines fact_is_puppetca' do
+ Facter.fact(:fact_is_puppetca).value.should == 'false'
+ end
+ it 'defines fact_is_puppetconsole' do
+ Facter.fact(:fact_is_puppetconsole).value.should == 'false'
+ end
+ end
+
+ [ '1.7.1', '2.0.1' ].each do |v|
+ context "With Facter #{v} which has external facts support" do
+ before :each do
+ Facter.stubs(:version).returns(v)
+ end
+
+ it 'does not call Facter::Util::DotD.new' do
+ Facter::Util::DotD.expects(:new).never
+
+ if Facter.collection.respond_to? :load
+ Facter.collection.load(:facter_dot_d)
+ else
+ Facter.collection.loader.load(:facter_dot_d)
+ end
+ end
+ end
+ end
+end
diff --git a/spec/unit/puppet/parser/functions/any2array_spec.rb b/spec/unit/puppet/parser/functions/any2array_spec.rb
new file mode 100644
index 0000000..b266e84
--- /dev/null
+++ b/spec/unit/puppet/parser/functions/any2array_spec.rb
@@ -0,0 +1,55 @@
+#! /usr/bin/env ruby -S rspec
+require 'spec_helper'
+
+describe "the any2array function" do
+ let(:scope) { PuppetlabsSpec::PuppetInternals.scope }
+
+ it "should exist" do
+ Puppet::Parser::Functions.function("any2array").should == "function_any2array"
+ end
+
+ it "should return an empty array if there is less than 1 argument" do
+ result = scope.function_any2array([])
+ result.should(eq([]))
+ end
+
+ it "should convert boolean true to [ true ] " do
+ result = scope.function_any2array([true])
+ result.should(eq([true]))
+ end
+
+ it "should convert one object to [object]" do
+ result = scope.function_any2array(['one'])
+ result.should(eq(['one']))
+ end
+
+ it "should convert multiple objects to [objects]" do
+ result = scope.function_any2array(['one', 'two'])
+ result.should(eq(['one', 'two']))
+ end
+
+ it "should return empty array it was called with" do
+ result = scope.function_any2array([[]])
+ result.should(eq([]))
+ end
+
+ it "should return one-member array it was called with" do
+ result = scope.function_any2array([['string']])
+ result.should(eq(['string']))
+ end
+
+ it "should return multi-member array it was called with" do
+ result = scope.function_any2array([['one', 'two']])
+ result.should(eq(['one', 'two']))
+ end
+
+ it "should return members of a hash it was called with" do
+ result = scope.function_any2array([{ 'key' => 'value' }])
+ result.should(eq(['key', 'value']))
+ end
+
+ it "should return an empty array if it was called with an empty hash" do
+ result = scope.function_any2array([{ }])
+ result.should(eq([]))
+ end
+end
diff --git a/spec/unit/puppet/parser/functions/base64_spec.rb b/spec/unit/puppet/parser/functions/base64_spec.rb
new file mode 100755
index 0000000..5faa5e6
--- /dev/null
+++ b/spec/unit/puppet/parser/functions/base64_spec.rb
@@ -0,0 +1,34 @@
+#! /usr/bin/env ruby -S rspec
+
+require 'spec_helper'
+
+describe "the base64 function" do
+ let(:scope) { PuppetlabsSpec::PuppetInternals.scope }
+
+ it "should exist" do
+ Puppet::Parser::Functions.function("base64").should == "function_base64"
+ end
+
+ it "should raise a ParseError if there are other than 2 arguments" do
+ expect { scope.function_base64([]) }.to(raise_error(Puppet::ParseError))
+ expect { scope.function_base64(["asdf"]) }.to(raise_error(Puppet::ParseError))
+ expect { scope.function_base64(["asdf","moo","cow"]) }.to(raise_error(Puppet::ParseError))
+ end
+
+ it "should raise a ParseError if argument 1 isn't 'encode' or 'decode'" do
+ expect { scope.function_base64(["bees","astring"]) }.to(raise_error(Puppet::ParseError, /first argument must be one of/))
+ end
+
+ it "should raise a ParseError if argument 2 isn't a string" do
+ expect { scope.function_base64(["encode",["2"]]) }.to(raise_error(Puppet::ParseError, /second argument must be a string/))
+ end
+
+ it "should encode a encoded string" do
+ result = scope.function_base64(["encode",'thestring'])
+ result.should =~ /\AdGhlc3RyaW5n\n\Z/
+ end
+ it "should decode a base64 encoded string" do
+ result = scope.function_base64(["decode",'dGhlc3RyaW5n'])
+ result.should == 'thestring'
+ end
+end
diff --git a/spec/unit/puppet/parser/functions/concat_spec.rb b/spec/unit/puppet/parser/functions/concat_spec.rb
new file mode 100644
index 0000000..123188b
--- /dev/null
+++ b/spec/unit/puppet/parser/functions/concat_spec.rb
@@ -0,0 +1,15 @@
+#! /usr/bin/env ruby -S rspec
+require 'spec_helper'
+
+describe "the concat function" do
+ let(:scope) { PuppetlabsSpec::PuppetInternals.scope }
+
+ it "should raise a ParseError if there is less than 1 arguments" do
+ lambda { scope.function_concat([]) }.should( raise_error(Puppet::ParseError))
+ end
+
+ it "should be able to concat an array" do
+ result = scope.function_concat([['1','2','3'],['4','5','6']])
+ result.should(eq(['1','2','3','4','5','6']))
+ end
+end
diff --git a/spec/unit/puppet/parser/functions/count_spec.rb b/spec/unit/puppet/parser/functions/count_spec.rb
new file mode 100644
index 0000000..2453815
--- /dev/null
+++ b/spec/unit/puppet/parser/functions/count_spec.rb
@@ -0,0 +1,31 @@
+#! /usr/bin/env ruby -S rspec
+
+require 'spec_helper'
+
+describe "the count function" do
+ let(:scope) { PuppetlabsSpec::PuppetInternals.scope }
+
+ it "should exist" do
+ Puppet::Parser::Functions.function("count").should == "function_count"
+ end
+
+ it "should raise a ArgumentError if there is more than 2 arguments" do
+ lambda { scope.function_count(['foo', 'bar', 'baz']) }.should( raise_error(ArgumentError))
+ end
+
+ it "should be able to count arrays" do
+ scope.function_count([["1","2","3"]]).should(eq(3))
+ end
+
+ it "should be able to count matching elements in arrays" do
+ scope.function_count([["1", "2", "2"], "2"]).should(eq(2))
+ end
+
+ it "should not count nil or empty strings" do
+ scope.function_count([["foo","bar",nil,""]]).should(eq(2))
+ end
+
+ it 'does not count an undefined hash key or an out of bound array index (which are both :undef)' do
+ expect(scope.function_count([["foo",:undef,:undef]])).to eq(1)
+ end
+end
diff --git a/spec/unit/puppet/parser/functions/difference_spec.rb b/spec/unit/puppet/parser/functions/difference_spec.rb
new file mode 100644
index 0000000..9feff09
--- /dev/null
+++ b/spec/unit/puppet/parser/functions/difference_spec.rb
@@ -0,0 +1,19 @@
+#! /usr/bin/env ruby -S rspec
+require 'spec_helper'
+
+describe "the difference function" do
+ let(:scope) { PuppetlabsSpec::PuppetInternals.scope }
+
+ it "should exist" do
+ Puppet::Parser::Functions.function("difference").should == "function_difference"
+ end
+
+ it "should raise a ParseError if there are fewer than 2 arguments" do
+ lambda { scope.function_difference([]) }.should( raise_error(Puppet::ParseError) )
+ end
+
+ it "should return the difference between two arrays" do
+ result = scope.function_difference([["a","b","c"],["b","c","d"]])
+ result.should(eq(["a"]))
+ end
+end
diff --git a/spec/unit/puppet/parser/functions/dirname_spec.rb b/spec/unit/puppet/parser/functions/dirname_spec.rb
new file mode 100755
index 0000000..fb3b4fe
--- /dev/null
+++ b/spec/unit/puppet/parser/functions/dirname_spec.rb
@@ -0,0 +1,24 @@
+#! /usr/bin/env ruby -S rspec
+require 'spec_helper'
+
+describe "the dirname function" do
+ let(:scope) { PuppetlabsSpec::PuppetInternals.scope }
+
+ it "should exist" do
+ Puppet::Parser::Functions.function("dirname").should == "function_dirname"
+ end
+
+ it "should raise a ParseError if there is less than 1 arguments" do
+ lambda { scope.function_dirname([]) }.should( raise_error(Puppet::ParseError))
+ end
+
+ it "should return dirname for an absolute path" do
+ result = scope.function_dirname(['/path/to/a/file.ext'])
+ result.should(eq('/path/to/a'))
+ end
+
+ it "should return dirname for a relative path" do
+ result = scope.function_dirname(['path/to/a/file.ext'])
+ result.should(eq('path/to/a'))
+ end
+end
diff --git a/spec/unit/puppet/parser/functions/flatten_spec.rb b/spec/unit/puppet/parser/functions/flatten_spec.rb
index d4dfd20..dba7a6b 100755
--- a/spec/unit/puppet/parser/functions/flatten_spec.rb
+++ b/spec/unit/puppet/parser/functions/flatten_spec.rb
@@ -11,6 +11,10 @@ describe "the flatten function" do
lambda { scope.function_flatten([]) }.should( raise_error(Puppet::ParseError))
end
+ it "should raise a ParseError if there is more than 1 argument" do
+ lambda { scope.function_flatten([[], []]) }.should( raise_error(Puppet::ParseError))
+ end
+
it "should flatten a complex data structure" do
result = scope.function_flatten([["a","b",["c",["d","e"],"f","g"]]])
result.should(eq(["a","b","c","d","e","f","g"]))
diff --git a/spec/unit/puppet/parser/functions/floor_spec.rb b/spec/unit/puppet/parser/functions/floor_spec.rb
new file mode 100644
index 0000000..dbc8c77
--- /dev/null
+++ b/spec/unit/puppet/parser/functions/floor_spec.rb
@@ -0,0 +1,39 @@
+#! /usr/bin/env ruby -S rspec
+
+require 'spec_helper'
+
+describe "the floor function" do
+ let(:scope) { PuppetlabsSpec::PuppetInternals.scope }
+
+ it "should exist" do
+ Puppet::Parser::Functions.function("floor").should == "function_floor"
+ end
+
+ it "should raise a ParseError if there is less than 1 argument" do
+ lambda { scope.function_floor([]) }.should( raise_error(Puppet::ParseError, /Wrong number of arguments/))
+ end
+
+ it "should should raise a ParseError if input isn't numeric (eg. String)" do
+ lambda { scope.function_floor(["foo"]) }.should( raise_error(Puppet::ParseError, /Wrong argument type/))
+ end
+
+ it "should should raise a ParseError if input isn't numeric (eg. Boolean)" do
+ lambda { scope.function_floor([true]) }.should( raise_error(Puppet::ParseError, /Wrong argument type/))
+ end
+
+ it "should return an integer when a numeric type is passed" do
+ result = scope.function_floor([12.4])
+ result.is_a?(Integer).should(eq(true))
+ end
+
+ it "should return the input when an integer is passed" do
+ result = scope.function_floor([7])
+ result.should(eq(7))
+ end
+
+ it "should return the largest integer less than or equal to the input" do
+ result = scope.function_floor([3.8])
+ result.should(eq(3))
+ end
+end
+
diff --git a/spec/unit/puppet/parser/functions/get_module_path_spec.rb b/spec/unit/puppet/parser/functions/get_module_path_spec.rb
index e761706..486bef6 100644
--- a/spec/unit/puppet/parser/functions/get_module_path_spec.rb
+++ b/spec/unit/puppet/parser/functions/get_module_path_spec.rb
@@ -15,11 +15,11 @@ describe Puppet::Parser::Functions.function(:get_module_path) do
end
it 'should only allow one argument' do
- expect { scope.function_get_module_path([]) }.should raise_error(Puppet::ParseError, /Wrong number of arguments, expects one/)
- expect { scope.function_get_module_path(['1','2','3']) }.should raise_error(Puppet::ParseError, /Wrong number of arguments, expects one/)
+ expect { scope.function_get_module_path([]) }.to raise_error(Puppet::ParseError, /Wrong number of arguments, expects one/)
+ expect { scope.function_get_module_path(['1','2','3']) }.to raise_error(Puppet::ParseError, /Wrong number of arguments, expects one/)
end
it 'should raise an exception when the module cannot be found' do
- expect { scope.function_get_module_path(['foo']) }.should raise_error(Puppet::ParseError, /Could not find module/)
+ expect { scope.function_get_module_path(['foo']) }.to raise_error(Puppet::ParseError, /Could not find module/)
end
describe 'when locating a module' do
let(:modulepath) { "/tmp/does_not_exist" }
diff --git a/spec/unit/puppet/parser/functions/intersection_spec.rb b/spec/unit/puppet/parser/functions/intersection_spec.rb
new file mode 100644
index 0000000..fd44f7f
--- /dev/null
+++ b/spec/unit/puppet/parser/functions/intersection_spec.rb
@@ -0,0 +1,19 @@
+#! /usr/bin/env ruby -S rspec
+require 'spec_helper'
+
+describe "the intersection function" do
+ let(:scope) { PuppetlabsSpec::PuppetInternals.scope }
+
+ it "should exist" do
+ Puppet::Parser::Functions.function("intersection").should == "function_intersection"
+ end
+
+ it "should raise a ParseError if there are fewer than 2 arguments" do
+ lambda { scope.function_intersection([]) }.should( raise_error(Puppet::ParseError) )
+ end
+
+ it "should return the intersection of two arrays" do
+ result = scope.function_intersection([["a","b","c"],["b","c","d"]])
+ result.should(eq(["b","c"]))
+ end
+end
diff --git a/spec/unit/puppet/parser/functions/is_float_spec.rb b/spec/unit/puppet/parser/functions/is_float_spec.rb
index 2f527d9..b7d73b0 100644
--- a/spec/unit/puppet/parser/functions/is_float_spec.rb
+++ b/spec/unit/puppet/parser/functions/is_float_spec.rb
@@ -26,4 +26,8 @@ describe "the is_float function" do
result = scope.function_is_float(["3"])
result.should(eq(false))
end
+ it "should return true if a float is created from an arithmetical operation" do
+ result = scope.function_is_float([3.2*2])
+ result.should(eq(true))
+ end
end
diff --git a/spec/unit/puppet/parser/functions/is_function_available.rb b/spec/unit/puppet/parser/functions/is_function_available.rb
new file mode 100644
index 0000000..bd40c51
--- /dev/null
+++ b/spec/unit/puppet/parser/functions/is_function_available.rb
@@ -0,0 +1,31 @@
+#!/usr/bin/env rspec
+require 'spec_helper'
+
+describe "the is_function_available function" do
+ before :all do
+ Puppet::Parser::Functions.autoloader.loadall
+ end
+
+ before :each do
+ @scope = Puppet::Parser::Scope.new
+ end
+
+ it "should exist" do
+ Puppet::Parser::Functions.function("is_function_available").should == "function_is_function_available"
+ end
+
+ it "should raise a ParseError if there is less than 1 arguments" do
+ lambda { @scope.function_is_function_available([]) }.should( raise_error(Puppet::ParseError))
+ end
+
+ it "should return false if a nonexistent function is passed" do
+ result = @scope.function_is_function_available(['jeff_mccunes_left_sock'])
+ result.should(eq(false))
+ end
+
+ it "should return true if an available function is passed" do
+ result = @scope.function_is_function_available(['require'])
+ result.should(eq(true))
+ end
+
+end
diff --git a/spec/unit/puppet/parser/functions/is_integer_spec.rb b/spec/unit/puppet/parser/functions/is_integer_spec.rb
index 5afbba4..4335795 100644
--- a/spec/unit/puppet/parser/functions/is_integer_spec.rb
+++ b/spec/unit/puppet/parser/functions/is_integer_spec.rb
@@ -26,4 +26,9 @@ describe "the is_integer function" do
result = scope.function_is_integer(["asdf"])
result.should(eq(false))
end
+
+ it "should return true if an integer is created from an arithmetical operation" do
+ result = scope.function_is_integer([3*2])
+ result.should(eq(true))
+ end
end
diff --git a/spec/unit/puppet/parser/functions/is_numeric_spec.rb b/spec/unit/puppet/parser/functions/is_numeric_spec.rb
index 4078b37..d7440fb 100644
--- a/spec/unit/puppet/parser/functions/is_numeric_spec.rb
+++ b/spec/unit/puppet/parser/functions/is_numeric_spec.rb
@@ -22,6 +22,16 @@ describe "the is_numeric function" do
result.should(eq(true))
end
+ it "should return true if an integer is created from an arithmetical operation" do
+ result = scope.function_is_numeric([3*2])
+ result.should(eq(true))
+ end
+
+ it "should return true if a float is created from an arithmetical operation" do
+ result = scope.function_is_numeric([3.2*2])
+ result.should(eq(true))
+ end
+
it "should return false if a string" do
result = scope.function_is_numeric(["asdf"])
result.should(eq(false))
diff --git a/spec/unit/puppet/parser/functions/max_spec.rb b/spec/unit/puppet/parser/functions/max_spec.rb
index 604927e..ff6f2b3 100755
--- a/spec/unit/puppet/parser/functions/max_spec.rb
+++ b/spec/unit/puppet/parser/functions/max_spec.rb
@@ -20,4 +20,8 @@ describe "the max function" do
it "should be able to compare numbers" do
scope.function_max([6,8,4]).should(eq(8))
end
+
+ it "should be able to compare a number with a stringified number" do
+ scope.function_max([1,"2"]).should(eq("2"))
+ end
end
diff --git a/spec/unit/puppet/parser/functions/merge_spec.rb b/spec/unit/puppet/parser/functions/merge_spec.rb
index db7d837..8a170bb 100644
--- a/spec/unit/puppet/parser/functions/merge_spec.rb
+++ b/spec/unit/puppet/parser/functions/merge_spec.rb
@@ -25,7 +25,12 @@ describe Puppet::Parser::Functions.function(:merge) do
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/)
+ expect { new_hash = scope.function_merge([{}, '2'])}.to raise_error(Puppet::ParseError, /unexpected argument type String/)
+ expect { new_hash = scope.function_merge([{}, 2])}.to raise_error(Puppet::ParseError, /unexpected argument type Fixnum/)
+ end
+
+ it 'should accept empty strings as puppet undef' do
+ expect { new_hash = scope.function_merge([{}, ''])}.not_to raise_error(Puppet::ParseError, /unexpected argument type String/)
end
it 'should be able to merge two hashes' do
diff --git a/spec/unit/puppet/parser/functions/min_spec.rb b/spec/unit/puppet/parser/functions/min_spec.rb
index 781422c..71d593e 100755
--- a/spec/unit/puppet/parser/functions/min_spec.rb
+++ b/spec/unit/puppet/parser/functions/min_spec.rb
@@ -20,4 +20,8 @@ describe "the min function" do
it "should be able to compare numbers" do
scope.function_min([6,8,4]).should(eq(4))
end
+
+ it "should be able to compare a number with a stringified number" do
+ scope.function_min([1,"2"]).should(eq(1))
+ end
end
diff --git a/spec/unit/puppet/parser/functions/num2bool_spec.rb b/spec/unit/puppet/parser/functions/num2bool_spec.rb
index 640c689..b56196d 100644
--- a/spec/unit/puppet/parser/functions/num2bool_spec.rb
+++ b/spec/unit/puppet/parser/functions/num2bool_spec.rb
@@ -8,17 +8,60 @@ describe "the num2bool function" do
Puppet::Parser::Functions.function("num2bool").should == "function_num2bool"
end
- it "should raise a ParseError if there is less than 1 arguments" do
+ it "should raise a ParseError if there are no arguments" do
lambda { scope.function_num2bool([]) }.should( raise_error(Puppet::ParseError))
end
- it "should return true if 1" do
+ it "should raise a ParseError if there are more than 1 arguments" do
+ lambda { scope.function_num2bool(["foo","bar"]) }.should( raise_error(Puppet::ParseError))
+ end
+
+ it "should raise a ParseError if passed something non-numeric" do
+ lambda { scope.function_num2bool(["xyzzy"]) }.should( raise_error(Puppet::ParseError))
+ end
+
+ it "should return true if passed string 1" do
result = scope.function_num2bool(["1"])
result.should(be_true)
end
- it "should return false if 0" do
+ it "should return true if passed string 1.5" do
+ result = scope.function_num2bool(["1.5"])
+ result.should(be_true)
+ end
+
+ it "should return true if passed number 1" do
+ result = scope.function_num2bool([1])
+ result.should(be_true)
+ end
+
+ it "should return false if passed string 0" do
result = scope.function_num2bool(["0"])
result.should(be_false)
end
+
+ it "should return false if passed number 0" do
+ result = scope.function_num2bool([0])
+ result.should(be_false)
+ end
+
+ it "should return false if passed string -1" do
+ result = scope.function_num2bool(["-1"])
+ result.should(be_false)
+ end
+
+ it "should return false if passed string -1.5" do
+ result = scope.function_num2bool(["-1.5"])
+ result.should(be_false)
+ end
+
+ it "should return false if passed number -1" do
+ result = scope.function_num2bool([-1])
+ result.should(be_false)
+ end
+
+ it "should return false if passed float -1.5" do
+ result = scope.function_num2bool([-1.5])
+ result.should(be_false)
+ end
end
diff --git a/spec/unit/puppet/parser/functions/str2bool_spec.rb b/spec/unit/puppet/parser/functions/str2bool_spec.rb
index 2782bbe..ef6350f 100644
--- a/spec/unit/puppet/parser/functions/str2bool_spec.rb
+++ b/spec/unit/puppet/parser/functions/str2bool_spec.rb
@@ -21,4 +21,11 @@ describe "the str2bool function" do
result = scope.function_str2bool(["undef"])
result.should(eq(false))
end
+
+ it "should return the boolean it was called with" do
+ result = scope.function_str2bool([true])
+ result.should(eq(true))
+ result = scope.function_str2bool([false])
+ result.should(eq(false))
+ end
end
diff --git a/spec/unit/puppet/parser/functions/str2saltedsha512_spec.rb b/spec/unit/puppet/parser/functions/str2saltedsha512_spec.rb
index a692c31..df8fb8e 100644
--- a/spec/unit/puppet/parser/functions/str2saltedsha512_spec.rb
+++ b/spec/unit/puppet/parser/functions/str2saltedsha512_spec.rb
@@ -9,11 +9,11 @@ describe "the str2saltedsha512 function" do
end
it "should raise a ParseError if there is less than 1 argument" do
- expect { scope.function_str2saltedsha512([]) }.should( raise_error(Puppet::ParseError) )
+ expect { scope.function_str2saltedsha512([]) }.to( raise_error(Puppet::ParseError) )
end
it "should raise a ParseError if there is more than 1 argument" do
- expect { scope.function_str2saltedsha512(['foo', 'bar', 'baz']) }.should( raise_error(Puppet::ParseError) )
+ expect { scope.function_str2saltedsha512(['foo', 'bar', 'baz']) }.to( raise_error(Puppet::ParseError) )
end
it "should return a salted-sha512 password hash 136 characters in length" do
@@ -22,7 +22,7 @@ describe "the str2saltedsha512 function" do
end
it "should raise an error if you pass a non-string password" do
- expect { scope.function_str2saltedsha512([1234]) }.should( raise_error(Puppet::ParseError) )
+ expect { scope.function_str2saltedsha512([1234]) }.to( raise_error(Puppet::ParseError) )
end
it "should generate a valid password" do
diff --git a/spec/unit/puppet/parser/functions/suffix_spec.rb b/spec/unit/puppet/parser/functions/suffix_spec.rb
new file mode 100644
index 0000000..c28f719
--- /dev/null
+++ b/spec/unit/puppet/parser/functions/suffix_spec.rb
@@ -0,0 +1,19 @@
+#! /usr/bin/env ruby -S rspec
+require 'spec_helper'
+
+describe "the suffix function" do
+ let(:scope) { PuppetlabsSpec::PuppetInternals.scope }
+
+ it "should exist" do
+ Puppet::Parser::Functions.function("suffix").should == "function_suffix"
+ end
+
+ it "should raise a ParseError if there is less than 1 arguments" do
+ lambda { scope.function_suffix([]) }.should( raise_error(Puppet::ParseError))
+ end
+
+ it "should return a suffixed array" do
+ result = scope.function_suffix([['a','b','c'], 'p'])
+ result.should(eq(['ap','bp','cp']))
+ end
+end
diff --git a/spec/unit/puppet/parser/functions/union_spec.rb b/spec/unit/puppet/parser/functions/union_spec.rb
new file mode 100644
index 0000000..0d282ca
--- /dev/null
+++ b/spec/unit/puppet/parser/functions/union_spec.rb
@@ -0,0 +1,19 @@
+#! /usr/bin/env ruby -S rspec
+require 'spec_helper'
+
+describe "the union function" do
+ let(:scope) { PuppetlabsSpec::PuppetInternals.scope }
+
+ it "should exist" do
+ Puppet::Parser::Functions.function("union").should == "function_union"
+ end
+
+ it "should raise a ParseError if there are fewer than 2 arguments" do
+ lambda { scope.function_union([]) }.should( raise_error(Puppet::ParseError) )
+ end
+
+ it "should join two arrays together" do
+ result = scope.function_union([["a","b","c"],["b","c","d"]])
+ result.should(eq(["a","b","c","d"]))
+ end
+end
diff --git a/spec/unit/puppet/parser/functions/validate_array_spec.rb b/spec/unit/puppet/parser/functions/validate_array_spec.rb
index 8eee72a..4b31cfd 100644
--- a/spec/unit/puppet/parser/functions/validate_array_spec.rb
+++ b/spec/unit/puppet/parser/functions/validate_array_spec.rb
@@ -9,12 +9,12 @@ describe Puppet::Parser::Functions.function(:validate_array) 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}')"
- expect { scope.compiler.compile }.should raise_error(Puppet::ParseError, /is not an Array/)
+ expect { scope.compiler.compile }.to 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})"
- expect { scope.compiler.compile }.should raise_error(Puppet::ParseError, /is not an Array/)
+ expect { scope.compiler.compile }.to raise_error(Puppet::ParseError, /is not an Array/)
end
end
@@ -32,7 +32,7 @@ describe Puppet::Parser::Functions.function(:validate_array) do
$foo = undef
validate_array($foo)
ENDofPUPPETcode
- expect { scope.compiler.compile }.should raise_error(Puppet::ParseError, /is not an Array/)
+ expect { scope.compiler.compile }.to raise_error(Puppet::ParseError, /is not an Array/)
end
end
end
diff --git a/spec/unit/puppet/parser/functions/validate_augeas_spec.rb b/spec/unit/puppet/parser/functions/validate_augeas_spec.rb
new file mode 100644
index 0000000..ab5c140
--- /dev/null
+++ b/spec/unit/puppet/parser/functions/validate_augeas_spec.rb
@@ -0,0 +1,102 @@
+require 'spec_helper'
+
+describe Puppet::Parser::Functions.function(:validate_augeas), :if => Puppet.features.augeas? do
+ let(:scope) { PuppetlabsSpec::PuppetInternals.scope }
+
+ # The subject of these examplres is the method itself.
+ subject do
+ # This makes sure the function is loaded within each test
+ function_name = Puppet::Parser::Functions.function(:validate_augeas)
+ scope.method(function_name)
+ end
+
+ context 'Using Puppet::Parser::Scope.new' do
+
+ describe 'Garbage inputs' do
+ inputs = [
+ [ nil ],
+ [ [ nil ] ],
+ [ { 'foo' => 'bar' } ],
+ [ { } ],
+ [ '' ],
+ [ "one", "one", "MSG to User", "4th arg" ],
+ ]
+
+ inputs.each do |input|
+ it "validate_augeas(#{input.inspect}) should fail" do
+ expect { subject.call [input] }.to raise_error Puppet::ParseError
+ end
+ end
+ end
+
+ describe 'Valid inputs' do
+ inputs = [
+ [ "root:x:0:0:root:/root:/bin/bash\n", 'Passwd.lns' ],
+ [ "proc /proc proc nodev,noexec,nosuid 0 0\n", 'Fstab.lns'],
+ ]
+
+ inputs.each do |input|
+ it "validate_augeas(#{input.inspect}) should not fail" do
+ expect { subject.call input }.not_to raise_error
+ end
+ end
+ end
+
+ describe "Valid inputs which should raise an exception without a message" do
+ # The intent here is to make sure valid inputs raise exceptions when they
+ # don't specify an error message to display. This is the behvior in
+ # 2.2.x and prior.
+ inputs = [
+ [ "root:x:0:0:root\n", 'Passwd.lns' ],
+ [ "127.0.1.1\n", 'Hosts.lns' ],
+ ]
+
+ inputs.each do |input|
+ it "validate_augeas(#{input.inspect}) should fail" do
+ expect { subject.call input }.to raise_error /validate_augeas.*?matched less than it should/
+ end
+ end
+ end
+
+ describe "Nicer Error Messages" do
+ # The intent here is to make sure the function returns the 3rd argument
+ # in the exception thrown
+ inputs = [
+ [ "root:x:0:0:root\n", 'Passwd.lns', [], 'Failed to validate passwd content' ],
+ [ "127.0.1.1\n", 'Hosts.lns', [], 'Wrong hosts content' ],
+ ]
+
+ inputs.each do |input|
+ it "validate_augeas(#{input.inspect}) should fail" do
+ expect { subject.call input }.to raise_error /#{input[2]}/
+ end
+ end
+ end
+
+ describe "Passing simple unit tests" do
+ inputs = [
+ [ "root:x:0:0:root:/root:/bin/bash\n", 'Passwd.lns', ['$file/foobar']],
+ [ "root:x:0:0:root:/root:/bin/bash\n", 'Passwd.lns', ['$file/root/shell[.="/bin/sh"]', 'foobar']],
+ ]
+
+ inputs.each do |input|
+ it "validate_augeas(#{input.inspect}) should fail" do
+ expect { subject.call input }.not_to raise_error
+ end
+ end
+ end
+
+ describe "Failing simple unit tests" do
+ inputs = [
+ [ "foobar:x:0:0:root:/root:/bin/bash\n", 'Passwd.lns', ['$file/foobar']],
+ [ "root:x:0:0:root:/root:/bin/sh\n", 'Passwd.lns', ['$file/root/shell[.="/bin/sh"]', 'foobar']],
+ ]
+
+ inputs.each do |input|
+ it "validate_augeas(#{input.inspect}) should fail" do
+ expect { subject.call input }.to raise_error /testing path/
+ end
+ end
+ 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
index 31ab8fb..261fb23 100644
--- a/spec/unit/puppet/parser/functions/validate_bool_spec.rb
+++ b/spec/unit/puppet/parser/functions/validate_bool_spec.rb
@@ -10,7 +10,7 @@ describe Puppet::Parser::Functions.function(:validate_bool) do
it "should not compile when #{the_string} is a string" do
Puppet[:code] = "validate_bool('#{the_string}')"
- expect { scope.compiler.compile }.should raise_error(Puppet::ParseError, /is not a boolean/)
+ expect { scope.compiler.compile }.to raise_error(Puppet::ParseError, /is not a boolean/)
end
it "should compile when #{the_string} is a bare word" do
@@ -22,12 +22,12 @@ describe Puppet::Parser::Functions.function(:validate_bool) do
it "should not compile when an arbitrary string is passed" do
Puppet[:code] = 'validate_bool("jeff and dan are awesome")'
- expect { scope.compiler.compile }.should raise_error(Puppet::ParseError, /is not a boolean/)
+ expect { scope.compiler.compile }.to raise_error(Puppet::ParseError, /is not a boolean/)
end
it "should not compile when no arguments are passed" do
Puppet[:code] = 'validate_bool()'
- expect { scope.compiler.compile }.should raise_error(Puppet::ParseError, /wrong number of arguments/)
+ expect { scope.compiler.compile }.to raise_error(Puppet::ParseError, /wrong number of arguments/)
end
it "should compile when multiple boolean arguments are passed" do
@@ -45,7 +45,7 @@ describe Puppet::Parser::Functions.function(:validate_bool) do
$bar = false
validate_bool($foo, $bar, true, false, 'jeff')
ENDofPUPPETcode
- expect { scope.compiler.compile }.should raise_error(Puppet::ParseError, /is not a boolean/)
+ expect { scope.compiler.compile }.to raise_error(Puppet::ParseError, /is not a boolean/)
end
end
end
diff --git a/spec/unit/puppet/parser/functions/validate_cmd_spec.rb b/spec/unit/puppet/parser/functions/validate_cmd_spec.rb
new file mode 100644
index 0000000..69ea7f4
--- /dev/null
+++ b/spec/unit/puppet/parser/functions/validate_cmd_spec.rb
@@ -0,0 +1,81 @@
+require 'spec_helper'
+
+describe Puppet::Parser::Functions.function(:validate_cmd) do
+ let(:scope) { PuppetlabsSpec::PuppetInternals.scope }
+
+ # The subject of these examplres is the method itself.
+ subject do
+ # This makes sure the function is loaded within each test
+ function_name = Puppet::Parser::Functions.function(:validate_cmd)
+ scope.method(function_name)
+ end
+
+ context 'Using Puppet::Parser::Scope.new' do
+
+ describe 'Garbage inputs' do
+ inputs = [
+ [ nil ],
+ [ [ nil ] ],
+ [ { 'foo' => 'bar' } ],
+ [ { } ],
+ [ '' ],
+ [ "one", "one", "MSG to User", "4th arg" ],
+ ]
+
+ inputs.each do |input|
+ it "validate_cmd(#{input.inspect}) should fail" do
+ expect { subject.call [input] }.to raise_error Puppet::ParseError
+ end
+ end
+ end
+
+ describe 'Valid inputs' do
+ inputs = [
+ [ '/full/path/to/something', '/bin/echo' ],
+ [ '/full/path/to/something', '/bin/cat' ],
+ ]
+
+ inputs.each do |input|
+ it "validate_cmd(#{input.inspect}) should not fail" do
+ expect { subject.call input }.not_to raise_error
+ end
+ end
+ end
+
+ describe "Valid inputs which should raise an exception without a message" do
+ # The intent here is to make sure valid inputs raise exceptions when they
+ # don't specify an error message to display. This is the behvior in
+ # 2.2.x and prior.
+ inputs = [
+ [ "hello", "/bin/false" ],
+ ]
+
+ inputs.each do |input|
+ it "validate_cmd(#{input.inspect}) should fail" do
+ expect { subject.call input }.to raise_error /validate_cmd.*?failed to validate content with command/
+ end
+ end
+ end
+
+ describe "Nicer Error Messages" do
+ # The intent here is to make sure the function returns the 3rd argument
+ # in the exception thrown
+ inputs = [
+ [ "hello", [ "bye", "later", "adios" ], "MSG to User" ],
+ [ "greetings", "salutations", "Error, greetings does not match salutations" ],
+ ]
+
+ inputs.each do |input|
+ it "validate_cmd(#{input.inspect}) should fail" do
+ expect { subject.call input }.to raise_error /#{input[2]}/
+ end
+ end
+ end
+
+ describe "Test output message" do
+ it "validate_cmd('whatever', 'kthnksbye') should fail" do
+ expect { subject.call ['whatever', 'kthnksbye'] }.to raise_error /kthnksbye.* returned 1/
+ end
+ 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
index 06d77a1..a0c35c2 100644
--- a/spec/unit/puppet/parser/functions/validate_hash_spec.rb
+++ b/spec/unit/puppet/parser/functions/validate_hash_spec.rb
@@ -11,12 +11,12 @@ describe Puppet::Parser::Functions.function(:validate_hash) do
it "should not compile when #{the_string} is a string" do
Puppet[:code] = "validate_hash('#{the_string}')"
- expect { scope.compiler.compile }.should raise_error(Puppet::ParseError, /is not a Hash/)
+ expect { scope.compiler.compile }.to 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})"
- expect { scope.compiler.compile }.should raise_error(Puppet::ParseError, /is not a Hash/)
+ expect { scope.compiler.compile }.to raise_error(Puppet::ParseError, /is not a Hash/)
end
end
@@ -35,7 +35,7 @@ describe Puppet::Parser::Functions.function(:validate_hash) do
$foo = undef
validate_hash($foo)
ENDofPUPPETcode
- expect { scope.compiler.compile }.should raise_error(Puppet::ParseError, /is not a Hash/)
+ expect { scope.compiler.compile }.to raise_error(Puppet::ParseError, /is not a Hash/)
end
end
diff --git a/spec/unit/puppet/parser/functions/validate_slength_spec.rb b/spec/unit/puppet/parser/functions/validate_slength_spec.rb
index eccf908..b363e7a 100755
--- a/spec/unit/puppet/parser/functions/validate_slength_spec.rb
+++ b/spec/unit/puppet/parser/functions/validate_slength_spec.rb
@@ -35,7 +35,7 @@ describe "the validate_slength function" do
end
it "should fail if you pass something other than a string or array" do
- expect { scope.function_validate_slength([Hash.new["moo" => "7"],6]) }.to(raise_error(Puppet::ParseError), /please pass a string, or an array of strings/)
+ expect { scope.function_validate_slength([Hash.new["moo" => "7"],6]) }.to(raise_error(Puppet::ParseError, /please pass a string, or an array of strings/))
end
it "should not fail if string is smaller or equal to size" do
diff --git a/spec/unit/puppet/parser/functions/validate_string_spec.rb b/spec/unit/puppet/parser/functions/validate_string_spec.rb
index 007b4ca..3b4fb3e 100644
--- a/spec/unit/puppet/parser/functions/validate_string_spec.rb
+++ b/spec/unit/puppet/parser/functions/validate_string_spec.rb
@@ -29,7 +29,7 @@ describe Puppet::Parser::Functions.function(:validate_string) do
it "should not compile when #{the_string} is a bare word" do
Puppet[:code] = "validate_string(#{the_string})"
- expect { scope.compiler.compile }.should raise_error(Puppet::ParseError, /is not a string/)
+ expect { scope.compiler.compile }.to raise_error(Puppet::ParseError, /is not a string/)
end
end
diff --git a/spec/unit/puppet/type/file_line_spec.rb b/spec/unit/puppet/type/file_line_spec.rb
index 0cd8a26..edc64bd 100644
--- a/spec/unit/puppet/type/file_line_spec.rb
+++ b/spec/unit/puppet/type/file_line_spec.rb
@@ -37,13 +37,13 @@ describe Puppet::Type.type(:file_line) do
file_line[:path].should == '/tmp/path'
end
it 'should not accept unqualified path' do
- expect { file_line[:path] = 'file' }.should raise_error(Puppet::Error, /File paths must be fully qualified/)
+ expect { file_line[:path] = 'file' }.to raise_error(Puppet::Error, /File paths must be fully qualified/)
end
it 'should require that a line is specified' do
- expect { Puppet::Type.type(:file_line).new(:name => 'foo', :path => '/tmp/file') }.should raise_error(Puppet::Error, /Both line and path are required attributes/)
+ expect { Puppet::Type.type(:file_line).new(:name => 'foo', :path => '/tmp/file') }.to 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(:file_line).new(:name => 'foo', :line => 'path') }.should raise_error(Puppet::Error, /Both line and path are required attributes/)
+ expect { Puppet::Type.type(:file_line).new(:name => 'foo', :line => 'path') }.to raise_error(Puppet::Error, /Both line and path are required attributes/)
end
it 'should default to ensure => present' do
file_line[:ensure].should eq :present