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.
This commit is contained in:
Dan Bode 2012-08-07 20:48:54 -07:00 committed by Jeff McCune
parent 9693c04c9d
commit a0cb8cdee4
4 changed files with 127 additions and 0 deletions

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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