Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add_children is not idempotent #42

Closed
mattfirtion opened this issue Dec 11, 2015 · 2 comments
Closed

add_children is not idempotent #42

mattfirtion opened this issue Dec 11, 2015 · 2 comments
Labels

Comments

@mattfirtion
Copy link

When running a task to add a child element, the child element is added on each execution.

- name: Add child element
  xml:
    file: "/tmp/ansible-xml-beers.xml"
    xpath: /business/beers
    add_children:
      - beer: "Old Rasputin"
<?xml version='1.0' encoding='UTF-8'?>
<business type="bar">
  <name>Tasty Beverage Co.</name>
  <beers>
    <beer>Rochefort 10</beer>
    <beer>St. Bernardus Abbot 12</beer>
    <beer>Schlitz</beer>
    <beer>Old Rasputin</beer>
  <beer>Old Rasputin</beer><beer>Old Rasputin</beer><beer>Old Rasputin</beer><beer
>Old Rasputin</beer></beers>
  <rating subjective="true">10</rating>
  <website>
    <mobilefriendly/>
    <address>http://tastybeverageco.com</address>
  </website>
</business>
@tbielawa
Copy link
Collaborator

That could be interpreted as expected behavior. Ansible knows not of your true intentions, nor of your XML Schema (which may state that only one instance of any element type may be a child in a given scope). It only knows that you said to add a child element to a parent.

I understand your frustration with this. There's no clear and obvious way to add a child element if it doesn't already exist.

I could see this going in several ways. Maybe even a merge of some of their ideas. Here's one:

  • An option could be added to the add_children command that allows you to specify the behavior of addition.

I can think of three common ways people approach this

  • Default behavior, just add the element where you say to, this may mean a parent adding another sibling of the same type within it's scope
  • Update behavior, if the element exists already, and does not look like what we say it should, then update the element to look as defined
  • No-replace behavior, if the element exists in the given scope -- in any form -- then skip the operation

It becomes more challenging when we consider that a variety of things may be contained in any given parent's scope. What if we have an element foo defined several times in a parent element, but each instance of foo has different attribute (values) or element text values. For example:

<funwords>
    <foo>with words!</foo>
    <foo awesome="1" />
    <foo title="The best">Mega Frobber</foo>
</funwords>

I guess you'd want to do a kind of "does it exist already?" task and register the result, and then an only_if on the subsequent add.

Or modify your playbook approach. If you're adding an element to an xml file, are you only doing that once to configure a service? Maybe split your playbook up more.

Maybe you've got a set of defined items you need to have as children somewhere, you can use yaml for variables to ensure the children of a parent are exactly defined as you say in the yaml.

This surely is an interesting issue.

@cmprescott
Copy link
Owner

I concur with @tbielawa; definitely an interesting issue. You are correct that add_children is not idempotent. However, it's counterintuitive having a command with the word "add" be idempotent.

I think the best way to handle this scenario is at the playbook level and use add_children conditionally. Depending on your need, sometimes it would make sense to use set_children in place of add_children.

I'm going to close this issue without a fix, but I am open to changing my position on how add_children should work in the future, or if it should be depreciated.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants