(Sorry, long post, and .. I''m replying via copy & paste from Google
Groups)
On Wed, 15 Sep 2010 19:59:35 -0700 (PDT), Patrick wrote:>Sounds like a job for Augeas or puppet-concat. I think puppet_concat
>would be a better fit.
>Augeas: http://docs.puppetlabs.com/references/stable/type.html#augeas
>puppet_concat: http://github.com/ripienaar/puppet-concat
Thank you Patrick for the suggestions.
I explored puppet_concat further, and found that it:
- Requires files to be split into several pieces to be useful i.e. the head,
body, then tail.
- Leaves fragment files (turds?) on client filesystems, however well-categorized
they may be.
So I became motivated to see if I could develop an improved solution that did
the string processing server-side, then returned the finished results to the
client.
I wrote a custom type (for Puppet 0.25.5) named "concat". In short,
you can make line-based contributions scattered across many places, and the
concat type will join them together with newlines and *somehow* make the
resulting string available. My first use-case is configuring an SNMP daemon.
But it''s incomplete:
- Resulting concatenated strings are not available from within the Puppet DSL.
- I''m not confident concatenation is being done before Puppet
ultimately provides the resulting string values for use.
The code is at the bottom of this message.
Let''s look at how to use it. Although unnecessary, I envisioned the
resulting concatenated strings would be defined in arbitrary scopes, like this:
# In file modules/jvm/manifests/init.pp :
concat { "JVM SNMP":
variable => "snmp::snmpd_conf_contributions",
lines => "proxy -m ${mib_file} -v 2c -c ${snmp_community}
localhost:1161 .1.3.6.1.4.1.42.2.145" ,
before => Class["snmp"],
}
# In file modules/postgres/manifests/init.pp :
concat { "PostgreSQL postmaster SNMP":
variable => "snmp::snmpd_conf_contributions",
lines => "proc postmaster",
before => Class["snmp"],
}
In one ideal, the custom type would:
1. Gather all lines for each given distinct variable,
2. Perform concatenation, joining lines with UNIX newlines "\n" into a
single string value, and
3. Set the appropriate variable in the appropriate scope to the final value
Continuing the above example, $snmp::snmpd_conf_contributions would have the
value "proxy -m ${mib_file} -v 2c -c ${snmp_community} localhost:1161
.1.3.6.1.4.1.42.2.145\nproc postmaster". Note that the lines could be
reversed; this implementation doesn''t consider the order of multiple
concat resources, but if the lines param is an array, order within that array is
preserved.
Now, the value could be used:
# In file modules/snmp/manifests/init.pp:
file { "/etc/snmpd.conf":
content => "blah blah\n<%= snmpd_conf_contributions %>\nblah
blah", # Easily extends to the use of template()
}
# Or, using some mechanism from within an ERB document:
<%= concatenated_value(''snmpd_conf_contributions'') %>
Well, even after studying type.rb, scope.rb, setvar.rb, and friends, I
don''t know how to finish the implementation.
Given my current level of understanding, this is about as far as I can take the
code today.
Any hints, suggestions, ideas? Even without scoping? Can this be made to work at
all?
Better yet, I hope some enterprising soul takes it from here ^_^
Ty
* I sense that modifying variable values, or appending to the value of variables
out-of-scope, might be perceived as being counter to the spirit of Puppet. But
this approach would cause me less pain and give greater control over the
contents of configuration files in a way Augeas & other methods
don''t. Although, it might all be subjective, or I might be missing
something .. It might even be a Bad Idea.
---- 8< ---- modules/common/lib/puppet/type/concat.rb ---- 8< ----
module Puppet
# Note: The following global variables cause namespace pollution
$concat_raw_map = {} # Maps identifiers to arrays of a mix of strings and
arrays of strings
$concat_processed_map = {} # Maps identifiers to each of their final string
representations
$concat_finalized = false
$concat_instance_count = 0
$concat_total_rule_count = 0
newtype(:concat) do
@doc = "Sets the string value of *TODO* to the concatenation of all
contributors. With multiple concat resources, order of
appearance in the
final concatenated string is unspecified. Multiple content
values are
concatenated by being joined together with UNIX newline \\n
characters.
The implementation is partially patterned after
iptables.rb."
newparam(:name) do
desc "The name of this concat resource. Does not influence
concatenation behavior."
isnamevar
end
newparam(:variable) do
desc "Content is concatenated to the value of this variable
identifier, typed as a string."
end
newparam(:lines) do
desc "A string, or an array of strings, the value of which is
concatenated to the value of the variable identifier. In the case of an array of
strings, line order is preserved."
end
def initialize(args)
super(args)
$concat_total_rule_count += 1
# Memorize these lines
var = value(:variable).to_s
if not $concat_raw_map.has_key?(var)
# Create a new entry for this variable
$concat_raw_map[var] = []
end
lines = value(:lines)
$concat_raw_map[var].unshift(lines)
debug("Concatenate to #{var}: ''#{[lines].flatten *
''\'', \''''}''") # Enable flatten
to handle even a non-array type
end
def evaluate
$concat_instance_count += 1
if $concat_instance_count == $concat_total_rule_count
self.finalize unless self.finalized?
end
return super
end
# finalize() runs once, after all concat resources have been declared.
# For each identifier in the raw map, do the concatenation operation,
and set the appropriate variable *TODO* to this value.
def finalize
# Any of the supplied :lines parameter values may have been arrays
themselves, so flatten them
$concat_processed_map = Hash[* $concat_raw_map.map{|k, v| [k,
v.flatten * "\n"]}.flatten]
$concat_processed_map.each { |k, v| debug("Assign #{k} =
''#{v}''") }
$concat_finalized = true
end
def finalized?
if defined? $concat_finalized
return $concat_finalized
else
return false
end
end
# Reset class variables to their initial value
def self.clear
$concat_raw_map = {}
$concat_processed_map = {}
$concat_finalized = false
$concat_instance_count = 0
$concat_total_rule_count = 0
super
end
end
end
--
You received this message because you are subscribed to the Google Groups
"Puppet Users" group.
To post to this group, send email to puppet-users@googlegroups.com.
To unsubscribe from this group, send email to
puppet-users+unsubscribe@googlegroups.com.
For more options, visit this group at
http://groups.google.com/group/puppet-users?hl=en.