Repository: ansible/ansible-modules-extras

Issue:
Marker in blockinfile is a line prefix, not a whole line
##### ISSUE TYPE
- Bug Report
##### COMPONENT NAME

`blockinfile`
##### ANSIBLE VERSION

```
ansible 2.1.0 (devel 2e529d7a51) last updated 2016/03/29 20:29:18 (GMT +100)
  lib/ansible/modules/core: (detached HEAD 0268864211) last updated 2016/03/29 20:30:38 (GMT +100)
  lib/ansible/modules/extras: (detached HEAD 6978984244) last updated 2016/03/29 20:30:38 (GMT +100)
  config file = /etc/ansible/ansible.cfg
  configured module search path = Default w/o overrides
```
##### CONFIGURATION

N/A.
##### OS / ENVIRONMENT

N/A.
##### SUMMARY

The `blockinfile` documentation talks about `marker` being a "line template", but actually it doesn't match against a whole line, it looks for this marker at the start of the line.  This causes trouble when one marker happens to be a leading substring of another marker.
##### STEPS TO REPRODUCE

Run the following play twice:

``` yaml
- hosts: localhost
  tasks:
    - blockinfile:
        dest: /tmp/example
        block: this is an example block to insert
        create: true
    - blockinfile:
        dest: /tmp/example
        block: this is a different block
        marker: '# {mark} ANSIBLE MANAGED BLOCK: non-default marker'
```
##### EXPECTED RESULTS

File `/tmp/example` has the following contents:

```
# BEGIN ANSIBLE MANAGED BLOCK
this is an example block to insert
# END ANSIBLE MANAGED BLOCK
# BEGIN ANSIBLE MANAGED BLOCK: non-default marker
this is a different block
# END ANSIBLE MANAGED BLOCK: non-default marker
```
##### ACTUAL RESULTS

File `/tmp/example` has the following contents:

```
# BEGIN ANSIBLE MANAGED BLOCK
this is an example block to insert
# END ANSIBLE MANAGED BLOCK
# BEGIN ANSIBLE MANAGED BLOCK
this is an example block to insert
# END ANSIBLE MANAGED BLOCK
# BEGIN ANSIBLE MANAGED BLOCK: non-default marker
this is a different block
# END ANSIBLE MANAGED BLOCK: non-default marker
```

Here, on the second run, the first task has overwritten the second block, and the second task has reinserted the second block.



Discussion:
This could be solved by comparing the marker against the whole line (perhaps after first trimming whitespace from the start and end of both), but I wonder if @yaegashi knows if there's a particular reason to use [`line.startswith(marker)`](https://github.com/ansible/ansible-modules-extras/blob/9cab73b5dd29f4380897ff5de65f3af7a58d80eb/files/blockinfile.py#L255) as is currently done.

I had the same issue today. Also, I believe the marker parameter must be made mandatory and complain if {mark} is not present inside of it. Or else data loss can occur. 

I volunteer to implement this rule in cause the author of the module (or whoever is responsible) believes this is a good idea.

@yaegashi, ping. This issue is still waiting on your response.
[click here for bot help](https://github.com/ansible/ansibullbot/blob/master/ISSUE_HELP.md)

<!--- boilerplate: issue_renotify_maintainer --->

@yaegashi, ping. This issue is still waiting on your response.
[click here for bot help](https://github.com/ansible/ansibullbot/blob/master/ISSUE_HELP.md)

<!--- boilerplate: issue_renotify_maintainer --->

@yaegashi, ping. This issue is still waiting on your response.
[click here for bot help](https://github.com/ansible/ansibullbot/blob/master/ISSUE_HELP.md)

<!--- boilerplate: issue_renotify_maintainer --->

@yaegashi, ping. This issue is still waiting on your response.
[click here for bot help](https://github.com/ansible/ansibullbot/blob/master/ISSUE_HELP.md)

<!--- boilerplate: issue_renotify_maintainer --->


Resolving patch:
diff --git a/files/blockinfile.py b/files/blockinfile.py
--- a/files/blockinfile.py
+++ b/files/blockinfile.py
@@ -258,9 +258,9 @@ def main():
 
     n0 = n1 = None
     for i, line in enumerate(lines):
-        if line.startswith(marker0):
+        if line == marker0:
             n0 = i
-        if line.startswith(marker1):
+        if line == marker1:
             n1 = i
 
     if None in (n0, n1):


Test patch: