Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

Update to the latest version. #3

Merged
merged 1 commit into from

1 participant

@bodepd

Updating this modules to the same version that
was merged into 2.7 for consistency.

@bodepd bodepd updated to the latest version.
Updating this modules to the same version that
was merged into 2.7 for consistency.
5ad0dd0
@bodepd bodepd merged commit 28584b0 into from
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Jun 22, 2011
  1. @bodepd

    updated to the latest version.

    bodepd authored
    Updating this modules to the same version that
    was merged into 2.7 for consistency.
This page is out of date. Refresh to see the latest.
View
3  README
@@ -1,6 +1,9 @@
- License - Apache Version 2.0
- Copyright - Puppetlabs 2011
+*NOTE* - this has exists in 2.7.x core, it has been published seperately
+so that it can be used with 2.6.x
+
This module contains a custom function for puppet that can be used to dynamically add resources to the catalog.
I wrote this to use with an external node classifier that consumes YAML.
View
47 lib/puppet/parser/functions/create_resources.rb
@@ -1,32 +1,47 @@
Puppet::Parser::Functions::newfunction(:create_resources, :doc => '
-Converts a hash into resources and adds them to the catalog.
+Converts a hash into a set of resources and adds them to the catalog.
Takes two parameters:
create_resource($type, $resources)
Creates resources of type $type from the $resources hash. Assumes that
hash is in the following form:
- {title=>{attr=>value}}
+ {title=>{parameters}}
+ This is currently tested for defined resources, classes, as well as native types
') do |args|
- raise ArgumentError, 'requires resource type and param hash' if args.size < 2
+ raise ArgumentError, ("create_resources(): wrong number of arguments (#{args.length}; must be 2)") if args.length != 2
+ #raise ArgumentError, 'requires resource type and param hash' if args.size < 2
+ # figure out what kind of resource we are
+ type_of_resource = nil
+ type_name = args[0].downcase
+ if type_name == 'class'
+ type_of_resource = :class
+ else
+ if resource = Puppet::Type.type(type_name.to_sym)
+ type_of_resource = :type
+ elsif resource = find_definition(type_name.downcase)
+ type_of_resource = :define
+ else
+ raise ArgumentError, "could not create resource of unknown type #{type_name}"
+ end
+ end
+ # iterate through the resources to create
args[1].each do |title, params|
- # TODO - add argument to specify constraints on parameters
raise ArgumentError, 'params should not contain title' if(params['title'])
- if type = Puppet::Type.type(args[0].to_sym)
- resource = type.hash2resource(params.merge(:title => title))
- catalog.add_resource(resource)
- elsif args[0].downcase == 'class'# || args[0].downcase == 'node'
- klass = find_hostclass(title)
- klass.ensure_in_catalog(self, params)
- compiler.catalog.add_class([title])
- else
- # TODO - use ensure_in_catalog when it supports definitions
- # we assume that if nothing else mathces is must be a defined resource type
- resource = find_definition(args[0])
- p_resource = Puppet::Parser::Resource.new(args[0], title, :scope => self, :source => resource)
+ case type_of_resource
+ when :type
+ res = resource.hash2resource(params.merge(:title => title))
+ catalog.add_resource(res)
+ when :define
+ p_resource = Puppet::Parser::Resource.new(type_name, title, :scope => self, :source => resource)
params.merge(:name => title).each do |k,v|
p_resource.set_parameter(k,v)
end
resource.instantiate_resource(self, p_resource)
compiler.add_resource(self, p_resource)
+ when :class
+ klass = find_hostclass(title)
+ raise ArgumentError, "could not find hostclass #{title}" unless klass
+ klass.ensure_in_catalog(self, params)
+ compiler.catalog.add_class([title])
end
end
end
View
6 spec/spec.opts
@@ -0,0 +1,6 @@
+--format
+s
+--colour
+--loadby
+mtime
+--backtrace
View
18 spec/spec_helper.rb
@@ -0,0 +1,18 @@
+require 'pathname'
+dir = Pathname.new(__FILE__).parent
+$LOAD_PATH.unshift(dir, dir + 'lib', dir + '../lib')
+
+require 'mocha'
+require 'puppet'
+gem 'rspec', '=1.2.9'
+require 'spec/autorun'
+
+Spec::Runner.configure do |config|
+ config.mock_with :mocha
+end
+
+# We need this because the RAL uses 'should' as a method. This
+# allows us the same behaviour but with a different method name.
+class Object
+ alias :must :should
+end
View
137 spec/unit/puppet/parser/functions/create_resources_spec.rb
@@ -0,0 +1,137 @@
+require 'puppet'
+require 'spec_helper'
+
+describe 'function for dynamically creating resources' do
+
+ def get_scope
+ @topscope = Puppet::Parser::Scope.new
+ # This is necessary so we don't try to use the compiler to discover our parent.
+ @topscope.parent = nil
+ @scope = Puppet::Parser::Scope.new
+ @scope.compiler = Puppet::Parser::Compiler.new(Puppet::Node.new("floppy", :environment => 'production'))
+ @scope.parent = @topscope
+ @compiler = @scope.compiler
+ end
+ before :each do
+ get_scope
+ Puppet::Parser::Functions.function(:create_resources)
+ end
+
+ it "should exist" do
+ Puppet::Parser::Functions.function(:create_resources).should == "function_create_resources"
+ end
+ it 'should require two arguments' do
+ lambda { @scope.function_create_resources(['foo']) }.should raise_error(ArgumentError, 'create_resources(): wrong number of arguments (1; must be 2)')
+ end
+ describe 'when creating native types' do
+ before :each do
+ Puppet[:code]='notify{test:}'
+ get_scope
+ @scope.resource=Puppet::Parser::Resource.new('class', 't', :scope => @scope)
+ end
+ it 'empty hash should not cause resources to be added' do
+ @scope.function_create_resources(['file', {}])
+ @compiler.catalog.resources.size == 1
+ end
+ it 'should be able to add' do
+ @scope.function_create_resources(['file', {'/etc/foo'=>{'ensure'=>'present'}}])
+ @compiler.catalog.resource(:file, "/etc/foo")['ensure'].should == 'present'
+ end
+ it 'should accept multiple types' do
+ type_hash = {}
+ type_hash['foo'] = {'message' => 'one'}
+ type_hash['bar'] = {'message' => 'two'}
+ @scope.function_create_resources(['notify', type_hash])
+ @compiler.catalog.resource(:notify, "foo")['message'].should == 'one'
+ @compiler.catalog.resource(:notify, "bar")['message'].should == 'two'
+ end
+ it 'should fail to add non-existing type' do
+ lambda { @scope.function_create_resources(['foo', {}]) }.should raise_error(ArgumentError, 'could not create resource of unknown type foo')
+ end
+ it 'should be able to add edges' do
+ @scope.function_create_resources(['notify', {'foo'=>{'require' => 'Notify[test]'}}])
+ @scope.compiler.compile
+ rg = @scope.compiler.catalog.to_ral.relationship_graph
+ test = rg.vertices.find { |v| v.title == 'test' }
+ foo = rg.vertices.find { |v| v.title == 'foo' }
+ test.should be
+ foo.should be
+ rg.path_between(test,foo).should be
+ end
+ end
+ describe 'when dynamically creating resource types' do
+ before :each do
+ Puppet[:code]=
+'define foo($one){notify{$name: message => $one}}
+notify{test:}
+'
+ get_scope
+ @scope.resource=Puppet::Parser::Resource.new('class', 't', :scope => @scope)
+ Puppet::Parser::Functions.function(:create_resources)
+ end
+ it 'should be able to create defined resoure types' do
+ @scope.function_create_resources(['foo', {'blah'=>{'one'=>'two'}}])
+ # still have to compile for this to work...
+ # I am not sure if this constraint ruins the tests
+ @scope.compiler.compile
+ @compiler.catalog.resource(:notify, "blah")['message'].should == 'two'
+ end
+ it 'should fail if defines are missing params' do
+ @scope.function_create_resources(['foo', {'blah'=>{}}])
+ lambda { @scope.compiler.compile }.should raise_error(Puppet::ParseError, 'Must pass one to Foo[blah] at line 1')
+ end
+ it 'should be able to add multiple defines' do
+ hash = {}
+ hash['blah'] = {'one' => 'two'}
+ hash['blaz'] = {'one' => 'three'}
+ @scope.function_create_resources(['foo', hash])
+ # still have to compile for this to work...
+ # I am not sure if this constraint ruins the tests
+ @scope.compiler.compile
+ @compiler.catalog.resource(:notify, "blah")['message'].should == 'two'
+ @compiler.catalog.resource(:notify, "blaz")['message'].should == 'three'
+ end
+ it 'should be able to add edges' do
+ @scope.function_create_resources(['foo', {'blah'=>{'one'=>'two', 'require' => 'Notify[test]'}}])
+ @scope.compiler.compile
+ rg = @scope.compiler.catalog.to_ral.relationship_graph
+ test = rg.vertices.find { |v| v.title == 'test' }
+ blah = rg.vertices.find { |v| v.title == 'blah' }
+ test.should be
+ blah.should be
+ # (Yoda speak like we do)
+ rg.path_between(test,blah).should be
+ @compiler.catalog.resource(:notify, "blah")['message'].should == 'two'
+ end
+ end
+ describe 'when creating classes' do
+ before :each do
+ Puppet[:code]=
+'class bar($one){notify{test: message => $one}}
+notify{tester:}
+'
+ get_scope
+ @scope.resource=Puppet::Parser::Resource.new('class', 't', :scope => @scope)
+ Puppet::Parser::Functions.function(:create_resources)
+ end
+ it 'should be able to create classes' do
+ @scope.function_create_resources(['class', {'bar'=>{'one'=>'two'}}])
+ @scope.compiler.compile
+ @compiler.catalog.resource(:notify, "test")['message'].should == 'two'
+ @compiler.catalog.resource(:class, "bar").should_not be_nil#['message'].should == 'two'
+ end
+ it 'should fail to create non-existing classes' do
+ lambda { @scope.function_create_resources(['class', {'blah'=>{'one'=>'two'}}]) }.should raise_error(ArgumentError ,'could not find hostclass blah')
+ end
+ it 'should be able to add edges' do
+ @scope.function_create_resources(['class', {'bar'=>{'one'=>'two', 'require' => 'Notify[tester]'}}])
+ @scope.compiler.compile
+ rg = @scope.compiler.catalog.to_ral.relationship_graph
+ test = rg.vertices.find { |v| v.title == 'test' }
+ tester = rg.vertices.find { |v| v.title == 'tester' }
+ test.should be
+ tester.should be
+ rg.path_between(tester,test).should be
+ end
+ end
+end
Something went wrong with that request. Please try again.