summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Bode <dan@puppetlabs.com>2012-08-07 20:48:54 -0700
committerDan Bode <dan@puppetlabs.com>2012-08-13 17:09:10 -0700
commitba789deac588dea83a129544f8aa00813db30bf0 (patch)
tree8975d4e7b71bb650ec15e032eeae8e7af7ef91a4
parentdeafe88e02499a7bdababf0b5dc264fcc3edecf1 (diff)
Add function ensure_resource and defined_with_params
This commit adds 2 new functions with unit tests. defined_with_params works similarily to puppet's defined function, except it allows you to also specify a hash of params. defined_with_params will return true if a resource also exists that matches the specified type/title (just like with defined) as well as all of the specified params. ensure_resource is a function that basically combines defined_with_params with create_resources to conditionally create resources only if the specified resource (title, type, params) does not already exist. These functions are created to serve as an alternative to using defined as follows: if ! defined(Package['some_package']) { package { 'some_package': ensure => present, } The issue with this usage is that there is no guarentee about what parameters were set in the previous definition of the package that made its way into the catalog. ensure_resource could be used instead, as: ensure_resource('package', 'some_package', { 'ensure' => 'present' }) This will creat the package resources only if another resource does not exist with the specified parameters.
-rw-r--r--lib/puppet/parser/functions/defined_with_params.rb33
-rw-r--r--lib/puppet/parser/functions/ensure_resource.rb28
-rw-r--r--spec/functions/defined_with_params_spec.rb31
-rw-r--r--spec/functions/ensure_resource_spec.rb35
4 files changed, 127 insertions, 0 deletions
diff --git a/lib/puppet/parser/functions/defined_with_params.rb b/lib/puppet/parser/functions/defined_with_params.rb
new file mode 100644
index 0000000..e09e41c
--- /dev/null
+++ b/lib/puppet/parser/functions/defined_with_params.rb
@@ -0,0 +1,33 @@
+# Test whether a given class or definition is defined
+require 'puppet/parser/functions'
+
+Puppet::Parser::Functions.newfunction(:defined_with_params,
+ :type => :rvalue,
+ :doc => <<-'ENDOFDOC'
+Takes a resource reference and an optional hash of attributes.
+
+Returns true if a resource with the specified attributes has already been added
+to the catalog, and false otherwise.
+
+ user { 'dan':
+ ensure => present,
+ }
+
+ if ! defined_with_params(User[dan], {'ensure' => 'present' }) {
+ user { 'dan': ensure => present, }
+ }
+ENDOFDOC
+) do |vals|
+ reference, params = vals
+ raise(ArgumentError, 'Must specify a reference') unless reference
+ params ||= {}
+ ret = false
+ if resource = findresource(reference.to_s)
+ matches = params.collect do |key, value|
+ resource[key] == value
+ end
+ ret = params.empty? || !matches.include?(false)
+ end
+ Puppet.debug("Resource #{reference} was not determined to be defined")
+ ret
+end
diff --git a/lib/puppet/parser/functions/ensure_resource.rb b/lib/puppet/parser/functions/ensure_resource.rb
new file mode 100644
index 0000000..8f9eadf
--- /dev/null
+++ b/lib/puppet/parser/functions/ensure_resource.rb
@@ -0,0 +1,28 @@
+# Test whether a given class or definition is defined
+require 'puppet/parser/functions'
+
+Puppet::Parser::Functions.newfunction(:ensure_resource,
+ :type => :statement,
+ :doc => <<-'ENDOFDOC'
+Takes a resource type, title, and a list of attributes that describe a
+resource.
+
+ user { 'dan':
+ ensure => present,
+ }
+
+This example only creates the resource if it does not already exist:
+
+ ensure_resource('user, 'dan', {'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 ||= {}
+ if function_defined_with_params(["#{type}[#{title}]", params])
+ Puppet.debug("Resource #{type}[#{title}] does not need to be created b/c it already exists")
+ else
+ function_create_resources([type.capitalize, { title => params }])
+ end
+end
diff --git a/spec/functions/defined_with_params_spec.rb b/spec/functions/defined_with_params_spec.rb
new file mode 100644
index 0000000..21c08a0
--- /dev/null
+++ b/spec/functions/defined_with_params_spec.rb
@@ -0,0 +1,31 @@
+#! /usr/bin/env ruby -S rspec
+require 'spec_helper'
+
+require 'rspec-puppet'
+describe 'defined_with_params' do
+ describe 'when a resource is not specified' do
+ it { should run.with_params().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]', {}).and_return(true)
+ should run.with_params('User[bob]', {}).and_return(false)
+ should run.with_params('User[dan]', {'foo' => 'bar'}).and_return(false)
+ end
+ end
+
+ describe 'when comparted against a resource with attributes' do
+ let :pre_condition do
+ 'user { "dan": ensure => present, shell => "/bin/csh", managehome => false}'
+ end
+ it do
+ should run.with_params('User[dan]', {}).and_return(true)
+ should run.with_params('User[dan]', {'ensure' => 'present'}).and_return(true)
+ should run.with_params('User[dan]', {'ensure' => 'present', 'managehome' => false}).and_return(true)
+ should run.with_params('User[dan]', {'ensure' => 'absent', 'managehome' => false}).and_return(false)
+ end
+ end
+end
diff --git a/spec/functions/ensure_resource_spec.rb b/spec/functions/ensure_resource_spec.rb
new file mode 100644
index 0000000..e45a6d0
--- /dev/null
+++ b/spec/functions/ensure_resource_spec.rb
@@ -0,0 +1,35 @@
+#! /usr/bin/env ruby -S rspec
+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
+ 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', {})
+ compiler.catalog.resource('User[dan]').to_s.should == 'User[dan]'
+ end
+ end
+
+ describe 'when comparted against a resource with attributes' 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', {'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)
+ end
+ end
+end