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.