I tried asking this in users and I'm not sure if that was the best place, 
so I'll try here.  It's probably best to start off by explaining *why* I 
would ever want to do this.  There are edge cases that have been around 
since the long long ago that are hard to meet with puppet.  These mainly 
surround instances where you have what is otherwise a simple file that 
could easily be templated but want to mix in virtual or exported resources 
into that template(IE: export arbitrary data).  Alternatives to that 
approach would be to write a full blown provider for the resource in 
question(overkill in a lot of cases), manage the entire resource with 
augeas(lots and lots of resources, hard to order the file[Important for 
things like activemq.conf.xml], rather incoherant), manually define 
everything in hiera/an enc/create a third party tool(which kind of defeats 
the purpose of automation), or to split the resource into templated/dynamic 
sections and concat the results(perhaps filebucketting it) with something 
like a refreshonly exec call out to cat(but then you're both not *really* 
managing the resource as a single unit and you're destroying coherance).

So what I settled on as an ideal that doesn't completely break the puppet 
paradigm is something like this:

define data($data = {} ) {  /* may have resources */ }

@@data { 'test': data => {} }
@@data { 'bar': data => { }. tag => "collect" }
@@data { 'foo': data => { }, tag => "collect" }

$objects = Data<<| tag == collect |>>
and then objects should contain something like [ { :name => 'bar', :data => 
{} }, { :name => 'foo, :data => {} } ] and you can iterate through that 
array in erb or your manifest or wherever.


Which simply would give you all resources matching a given criteria, their 
names and their parameters.  Except, as far as I know, you can't do that, 
even now.  So previously I had tried to set up some custom Parser functions 
to replicate that behavior as follows:
1.  Collect all resources of a given type that currently exist in the 
catalog and have/should have been applied with the structure as above.
2.  A set of parser functions that hook into Puppet::Parser::Collector and 
collect all virtual and/or exported resources that match a given criteria 
ALA the realize function, optionally add them to the compiler and/or 
evaluate/execute them.  

However, they never quite worked right and after plowing through a ton of 
puppet internals I figured I was wasting more time then I'd spend in a year 
of manual management.  Well that year has passed and we're now in the 
middle of refactoring our modules(as well as going from 2.7 to 3.2/3.3) and 
it's time to give this another shot.

For the first, what I wound up with broadly looks like this:

type = Puppet::Resource.new(resource_type, "whatever").type
results = self.catalog.resources.find_all { |resource| resource.type == 
type }
return results.map { |a| { :name => a.name }.merge{ a.to_hash } } if results
return []


And then set up the manifest something like so:

define virtual_test( $foo = "bar" ) {}

class setup_virtual {
  @@virtual_test { "foo": foo => "blah" }
  @@virtual_test { "bar": foo => "test", tag => "test" }
}

class realize_virtual { 
  require setup_virtual
  Virtual_test <<| tag == "test" |>>
}

class test_collect {
  require realize_virtual
  $virtual_tests = collect_resource_params('test')
}


However, this doesn't seem to respect the collection or actually represent 
the current catalog state - it's too greedy(I get all instances of 
virtual_test).  I try to control on virtual? and exported? but these don't 
apparently get cleared outside the realize function, and trying the 
compiler instead of the catalog doesn't change the results.  There's 
something simple I must be missing here, maybe improper scoping.

For the second, two functions that differ only slightly, so we'll stick 
with the exported version:

collection = Puppet::Parser::Collector.new(self, resource, conditions, nil, 
:exported)
results = collection.instance_eval("collect_exported")

self.compiler.add_coll(collection) if realize and collection # 
alternatively call collection.evaluate
return results.map { |a| { :name => a.name }.merge{ a.to_hash } } if results
return []


Now this works about as I expected it to, except I could never figure out 
how to set up the Puppet::Parser::AST::CollExpr for the conditions from a 
string so I get everything and need to manually parse out what I actually 
want.

So can anyone either help me fix these or point me towards a better/safer 
way to do this?

Thanks,
--Nick

-- 
You received this message because you are subscribed to the Google Groups 
"Puppet Developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
Visit this group at http://groups.google.com/group/puppet-dev.
For more options, visit https://groups.google.com/groups/opt_out.

Reply via email to