Repository: ansible/ansible-modules-extras

Issue:
blockinfile: check mode and create: yes does not work when file does not exist yet
##### ISSUE TYPE
- Bug Report
##### COMPONENT NAME

blockinfile
##### ANSIBLE VERSION

ansible 2.0.1.0  
  config file = /etc/ansible/ansible.cfg  
  configured module search path = Default w/o overrides 
##### CONFIGURATION

No changes
##### OS / ENVIRONMENT

CentOS 7.1.1503
##### SUMMARY

ansible-playbook ... --check
Fails my blockinfile task because the file(s) do not exist yet. The create=yes is properly set and during the run the system responds with "no such file or directory" errors.
##### STEPS TO REPRODUCE

Create a playbook that simply deals with a non-existent file:
- name: just testing
  blockinfile:
      dest: /etc/foobar.conf
      create: yes
      block: |
          Just for fun
          Another line 

Now run ansible-playbook --check on the file
##### EXPECTED RESULTS

The --check will fail because the file doesn't exist.
##### ACTUAL RESULTS

Here's the results from the above with --check -vvv:

```
ESTABLISH LOCAL CONNECTION FOR USER: root                                                                                                             
localhost EXEC /bin/sh -c '( umask 22 && mkdir -p "` echo $HOME/.ansible/tmp/ansible-tmp-1460553033.3-236522183380626 `" && echo "` echo $HOME/.ansib 
le/tmp/ansible-tmp-1460553033.3-236522183380626 `" )'                                                                                                 
localhost PUT /tmp/tmpjnUhnA TO /root/.ansible/tmp/ansible-tmp-1460553033.3-236522183380626/blockinfile                                               
localhost EXEC /bin/sh -c 'LANG=en_US.UTF-8 LC_ALL=en_US.UTF-8 LC_MESSAGES=en_US.UTF-8 /usr/bin/python /root/.ansible/tmp/ansible-tmp-1460553033.3-23 
6522183380626/blockinfile; rm -rf "/root/.ansible/tmp/ansible-tmp-1460553033.3-236522183380626/" > /dev/null 2>&1'                                    
An exception occurred during task execution. The full traceback is:                                                                                   
Traceback (most recent call last):                                                                                                                    
  File "/root/.ansible/tmp/ansible-tmp-1460553033.3-236522183380626/blockinfile", line 2457, in <module>                                              
    main()                                                                                                                                            
  File "/root/.ansible/tmp/ansible-tmp-1460553033.3-236522183380626/blockinfile", line 292, in main                                                   
    msg, changed = check_file_attrs(module, changed, msg)                                                                                             
  File "/root/.ansible/tmp/ansible-tmp-1460553033.3-236522183380626/blockinfile", line 166, in check_file_attrs                                       
    if module.set_file_attributes_if_different(file_args, False):                                                                                     
  File "/root/.ansible/tmp/ansible-tmp-1460553033.3-236522183380626/blockinfile", line 1308, in set_file_attributes_if_different                      
    return self.set_fs_attributes_if_different(file_args, changed)                                                                                    
  File "/root/.ansible/tmp/ansible-tmp-1460553033.3-236522183380626/blockinfile", line 1300, in set_fs_attributes_if_different                        
    file_args['path'], file_args['mode'], changed                                                                                                     
  File "/root/.ansible/tmp/ansible-tmp-1460553033.3-236522183380626/blockinfile", line 1135, in set_mode_if_different                                 
    path_stat = os.lstat(path)                                                                                                                        
OSError: [Errno 2] No such file or directory: '/etc/foobar.conf'                                                                                      

fatal: [localhost]: FAILED! => {"changed": false, "failed": true, "invocation": {"module_name": "blockinfile"}, "parsed": false} 
```



Discussion:
2.0.2 also has the same problem


Resolving patch:
diff --git a/files/blockinfile.py b/files/blockinfile.py
--- a/files/blockinfile.py
+++ b/files/blockinfile.py
@@ -212,7 +212,8 @@ def main():
         module.fail_json(rc=256,
                          msg='Destination %s is a directory !' % dest)
 
-    if not os.path.exists(dest):
+    path_exists = os.path.exists(dest)
+    if not path_exists:
         if not module.boolean(params['create']):
             module.fail_json(rc=257,
                              msg='Destination %s does not exist !' % dest)
@@ -230,6 +231,9 @@ def main():
     marker = params['marker']
     present = params['state'] == 'present'
 
+    if not present and not path_exists:
+        module.exit_json(changed=False, msg="File not present")
+
     if insertbefore is None and insertafter is None:
         insertafter = 'EOF'
 
@@ -299,10 +303,13 @@ def main():
         changed = True
 
     if changed and not module.check_mode:
-        if module.boolean(params['backup']) and os.path.exists(dest):
+        if module.boolean(params['backup']) and path_exists:
             module.backup_local(dest)
         write_changes(module, result, dest)
 
+    if module.check_mode and not path_exists:
+        module.exit_json(changed=changed, msg=msg)
+
     msg, changed = check_file_attrs(module, changed, msg)
     module.exit_json(changed=changed, msg=msg)
 


Test patch: