You ran off the rails at "what xmlstarlet
does" (emphsis added), and went rumbling across the countryside with talk about "need[ing ...] added
behavior" (emphsis mine). You are trying to model action rather than state, and that tends to fit poorly into Puppet's scheme of things.
It appears that the resource you want to model is a node (or maybe nodes) in a user-specified XML file, as identified by an XPath expression. That's fine. But what details of the state of such a resource can you / should you model? Here are some possibilities:
- presence / absence
- node value (== content for element nodes)
- attribute presence / absence / value when the resource is an element node
In the event that you specify an instance absent, you could perhaps rely on an optional parameter to support matched nodes being replaced with an alternative node instead of being.
In no case does a 'command' have anything to do with the state you are (should be) modeling. That's something that the type's provider should determine internally in the event that a resource instance is out of sync.
Thus, you might support any or all of these, and perhaps more:
# Matching nodes must not appear in the target file;
# the mechanism for removing any that are present is to delete them
xpath { 'Some node':
file => '/path/to/file.xml',
xpath => '/some/xpath',
ensure => 'absent'
}
or
# Matching nodes must not appear in the target file;
# the mechanism for removing any that are present is to replace them
# with the specified alternative.
xpath { 'Some node':
file => '/path/to/file.xml',
xpath => '/some/xpath',
ensure => 'absent',
replacement => '<different_node/>',
}
or
# The target file must contain (one / all possible) matching element
# nodes, their content must be as specified, and they must have
# (at least / exactly) the specified attributes.
xpath { 'Some node':
file => '/path/to/file.xml',
xpath => '/some/xpath',
ensure => 'present',
value => 'element content',
attributes => { 'a' => 'val1', 'b' => 'val2' }
}
Types should focus on identifying resources and describing their properties. How to get from here to there (and how to determine whether you are already there) is the domain of your type's provider(s), and should be exposed via the type as little as possible.