Answers: <p>As mentioned in the question and the comments on it, this isn't an area in which Ansible excels.  The "best" solution depends a bit on the type of file you're dealing with, and the structure of it.</p>
  
  <p>The cleanest way to deal with these sorts of changes in Ansible is to <a href="https://docs.ansible.com/ansible/latest/template_module.html" rel="nofollow noreferrer">templatize</a> the entire thing; this allows you to see the entire file at once, rather than piecing it together through many places, and is much less fragile than pattern- or line-based approaches.  When you need to add configuration in multiple places (for instance, different roles), that's when dynamic-loading directives become very useful, like Apache httpd's <code>Include</code>:</p>
  
  <pre><code>Include /etc/httpd/conf.d/*.conf
  </code></pre>
  
  <p>This then allows you to write individual configuration files from different places, and let the client software concatenate them.  However, as far as I can tell from a quick search, Tomcat doesn't support this, so you would need to operate with a single template file.</p>
  
  <p><code>lineinfile</code> is a hacky solution that's very fragile, and <code>template</code> is almost always a better option.  However, in this case, the node that you're adding is a self-closing one, so as long as it is top-level, it can go anywhere and <code>lineinfile</code> will work (I know you say it won't, but I'll get back to that).  <code>xml</code> is a similar option that's a bit less fragile.</p>
  
  <p>Those two you've ruled out because they can't delete the comment you have in the file.  However, I'll argue that that's an improper requirement (in most cases, and probably yours).</p>
  
  <p>When using a configuration management tool, the source of truth shifts from the files themselves on servers to the configuration that's checked in to master.  If someone wants to edit the file, they'll do so by editing the configuration management scripts, not by editing the file directly on the server.  Therefore, there is no need for comments in the resultant file that lives on the server, except perhaps one at the top that says "this is auto-generated, go look at source control instead".  The comment should be <em>in your templating code</em> - and as long as the result compiles and works correctly, you shouldn't care at all what it looks like.</p>
  
Answers: CC BY-SA 3.0
Answers: 2018-01-13T17:02:01.197Z
Answers: 2018-01-13T17:02:01.197Z
Answers: Xiong Chiamiov
Body: <p>How can I use ansible to ensure that a line is uncommented in an XML file?   In <code>/etc/tomcat8/context.xml</code> I want to ensure that the section:</p>
  
  <pre><code>&lt;!-- Uncomment this to disable session persistence across Tomcat restarts --&gt;
  &lt;!--
  &lt;Manager pathname="" /&gt;
  --&gt;
  </code></pre>
  
  <p>Is changed to:</p>
  
  <pre><code>&lt;!-- Disable session persistence across Tomcat restarts --&gt;
  &lt;Manager pathname="" /&gt;
  </code></pre>
  
  <ul>
  <li><p>The <a href="http://docs.ansible.com/ansible/latest/lineinfile_module.html" rel="noreferrer">lineinfile module</a> doesn't appear to be able to help because this is a multi-line section</p></li>
  <li><p>The <a href="https://docs.ansible.com/ansible/2.4/xml_module.html" rel="noreferrer">xml module</a> might be able to ensure that the <code>&lt;Manager...</code> is in place, but it doesn't appear to be able to delete the commented out version.</p></li>
  <li><p>I could write a script to do this with <code>sed</code> if I have to, but I find it is better to use ansible modules when possible.</p></li>
  </ul>
  
Comments: CC BY-SA 3.0
Comments: 2018-01-12T11:51:18.597Z
Comments: Suggested tags (I can't create them myself): [tag:xml] [tag:comments] [tag:line-in-file]
Comments: Stephen Ostermiller
Comments: CC BY-SA 3.0
Comments: 2018-01-12T14:34:44.343Z
Comments: There's no reason for those tags (they don't help finding the question better). In my opinion, don't go sed way, don't even go modifying files in place, either manage the whole file or not but changing lines by regex matching is brittle and likely to fail.
Comments: Tensibai
Comments: CC BY-SA 3.0
Comments: 2018-01-12T14:39:49.517Z
Comments: I find that managing entire files that get replaced by the package manager can also be frail.   Sometimes stuff gets added to new versions that really needs to be there.     Unfortunately, the tomcat configuration doesn't have a `conf.d` directory to which new files can be added easily.
Comments: Stephen Ostermiller
Comments: CC BY-SA 3.0
Comments: 2018-01-12T16:00:43.547Z
Comments: "Sometimes stuff gets added to new versions that really needs to be there" <- and if you let them slip into your production without being aware of them and their reasons you're letting the package maintainer do whatever they wish on your behalf... Better to break in CI on this update and ensure you're in line with the change done by the maintainer.
Comments: Tensibai
Comments: CC BY-SA 3.0
Comments: 2018-01-12T16:02:19.067Z
Comments: And anyway, trying to modify from line number or by regex is likely to break without prior information if the file si changed by the maintainer also, so that's up to you, but I really recommend against this practice.
Comments: Tensibai
Tags: <ansible><configuration>
Title: Ensure a line is uncommented in an XML file using ansible
UserDisplayName: Stephen Ostermiller
ThreadText: # Ensure a line is uncommented in an XML file using ansible
  
  (Asked by: username_0 on 2018-01-12)
  
  How can I use ansible to ensure that a line is uncommented in an XML file? In `/etc/tomcat8/context.xml` I want to ensure that the section:
  
  ```
  <!-- Uncomment this to disable session persistence across Tomcat restarts -->
  <!--
  <Manager pathname="" />
  -->
  
  ```
  
  Is changed to:
  
  ```
  <!-- Disable session persistence across Tomcat restarts -->
  <Manager pathname="" />
  
  ```
  
  * The [lineinfile module](http://docs.ansible.com/ansible/latest/lineinfile_module.html) doesn't appear to be able to help because this is a multi-line section
  * The [xml module](https://docs.ansible.com/ansible/2.4/xml_module.html) might be able to ensure that the `<Manager...` is in place, but it doesn't appear to be able to delete the commented out version.
  * I could write a script to do this with `sed` if I have to, but I find it is better to use ansible modules when possible.
  
  **Tags:** ansible, configuration
  
  > **Comments:**
  > **username_0**: Suggested tags (I can't create them myself): [tag:xml] [tag:comments] [tag:line-in-file]  
  > **username_1**: There's no reason for those tags (they don't help finding the question better). In my opinion, don't go sed way, don't even go modifying files in place, either manage the whole file or not but changing lines by regex matching is brittle and likely to fail.  
  > **username_0**: I find that managing entire files that get replaced by the package manager can also be frail.   Sometimes stuff gets added to new versions that really needs to be there.     Unfortunately, the tomcat configuration doesn't have a `conf.d` directory to which new files can be added easily.  
  > **username_1**: "Sometimes stuff gets added to new versions that really needs to be there" <- and if you let them slip into your production without being aware of them and their reasons you're letting the package maintainer do whatever they wish on your behalf... Better to break in CI on this update and ensure you're in line with the change done by the maintainer.  
  > **username_1**: And anyway, trying to modify from line number or by regex is likely to break without prior information if the file si changed by the maintainer also, so that's up to you, but I really recommend against this practice.  
  
  ---
  
  ## 1 answers
  
  ### Answer by username_2 on 2018-01-13. Score: 3
  
  As mentioned in the question and the comments on it, this isn't an area in which Ansible excels. The "best" solution depends a bit on the type of file you're dealing with, and the structure of it.
  
  The cleanest way to deal with these sorts of changes in Ansible is to [templatize](https://docs.ansible.com/ansible/latest/template_module.html) the entire thing; this allows you to see the entire file at once, rather than piecing it together through many places, and is much less fragile than pattern- or line-based approaches. When you need to add configuration in multiple places (for instance, different roles), that's when dynamic-loading directives become very useful, like Apache httpd's `Include`:
  
  ```
  Include /etc/httpd/conf.d/*.conf
  
  ```
  
  This then allows you to write individual configuration files from different places, and let the client software concatenate them. However, as far as I can tell from a quick search, Tomcat doesn't support this, so you would need to operate with a single template file.
  
  `lineinfile` is a hacky solution that's very fragile, and `template` is almost always a better option. However, in this case, the node that you're adding is a self-closing one, so as long as it is top-level, it can go anywhere and `lineinfile` will work (I know you say it won't, but I'll get back to that). `xml` is a similar option that's a bit less fragile.
  
  Those two you've ruled out because they can't delete the comment you have in the file. However, I'll argue that that's an improper requirement (in most cases, and probably yours).
  
  When using a configuration management tool, the source of truth shifts from the files themselves on servers to the configuration that's checked in to master. If someone wants to edit the file, they'll do so by editing the configuration management scripts, not by editing the file directly on the server. Therefore, there is no need for comments in the resultant file that lives on the server, except perhaps one at the top that says "this is auto-generated, go look at source control instead". The comment should be *in your templating code* - and as long as the result compiles and works correctly, you shouldn't care at all what it looks like.
  
  
  ---
  
  