Please hold my hand.
After studying the wiki, several unofficial pages, various mailing list
entries, and the operation of the "iptables" type as found on the net, I have
created a custom type, lovingly named ``configxml''.
It updates attributes on the first element matching a supplied XPath in a given
XML file. The first use case is configuring Atlassian JIRA to use Postgres ..
The custom type:
- Detects the need to update attribute values
- Updates attribute values
- Pretty prints to the log, ex. when run with ``puppetd -dtv''
- Solves today's immediate need, but I don't trust its ability to properly
integrate into the dependency tree, nor even its return value
Initially this was split into a type and a provider, which didn't work. I don't
clearly understand how provider functionality is invoked, nor its relationship
with a type.
How should this custom type be better structured and written?
I greatly appreciate feedback and pointers.
I've attached relevant code, sorry if its a little long ..
As you might sense from reading the code, today marks my 3rd day as a Ruby
newbie ..
---- 8< ---- manifest snippet ---- 8< ----
node 'jira' inherits 'basenode' {
...
configxml { '/opt/jira/atlassian-jira/WEB-INF/classes/entityengine.xml':
xpath => "/entity-config/datasour...@name='defaultDS']",
attributes => 'field-type-name=postgres72,schema-name=public',
}
...
}
---- 8< ---- configxml.rb ---- 8< ----
module Puppet
newtype(:configxml) do
@doc = "Modify attributes of the first element matching the
XPath expression in an XML file."
require 'rexml/document'
require 'set'
def test_it
doc = REXML::Document.new(File.open(value(:name)))
# Take the first element matching the provided XPath
expression
attrs = doc.elements[value(:xpath) + "[1]"].attributes
# Split up the comma-separated key-value pairs into an
array and then isolate the keys
keys = value(:attributes).split(/,/).map { |s|
s.split(/=/)[0] }
# Build up an array of attributes for the specified keys
keys.map { |k| "#{k}=#{attrs[k]}" }
end
def set_it
doc = REXML::Document.new(File.open(value(:name)))
# Take the first element matching the provided XPath
expression
attrs = doc.elements[value(:xpath) + "[1]"].attributes
# Split up the list comma-separated key-value pairs and
convert the array to hash
updates = Hash[*value(:attributes).split(/,/).map { |s|
s.split(/=/) }.flatten]
# Update this element's attributes
updates.each { |k, v| attrs[k] = v }
# Write the changes back
doc.write(File.open(value(:name), 'w'))
end
newparam(:name) do
desc "Full path of the XML document."
end
newparam(:xpath) do
desc "XPath expression selecting target elements; the
first of which whose attributes will be set."
end
newparam(:attributes) do
desc "An array of strings, each containing 'key=value'
expressions setting element attributes."
end
def evaluate
cur_attrs = test_it
if Set.new(value(:attributes).split(/,/)) ==
Set.new(cur_attrs)
debug("Attributes for element at
#{value(:xpath)} already #{value(:attributes)}. No changes necessary.")
return [] # TODO what goes here?
else
notice("Updating attributes for element at
#{value(:xpath)} to #{value(:attributes)}.")
set_it
return [] # TODO what goes here?
end
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 [email protected].
To unsubscribe from this group, send email to
[email protected].
For more options, visit this group at
http://groups.google.com/group/puppet-users?hl=en.