Repository: ansible/ansible

Issue:
lineinfile creating underlying directory doesn't manage exception like permission denied
##### ISSUE TYPE
 - Bug Report

##### COMPONENT NAME
lineinfile

##### ANSIBLE VERSION
```
$ ./bin/ansible --version
ansible 2.5.0 (devel 3df2561405) last updated 2018/02/06 19:46:11 (GMT +200)
  config file = /etc/ansible/ansible.cfg
  configured module search path = [u'/home/gsciorti/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
  ansible python module location = /home/gsciorti/PycharmProjects/ansible/lib/ansible
  executable location = ./bin/ansible
  python version = 2.7.14 (default, Dec 11 2017, 14:52:53) [GCC 7.2.1 20170915 (Red Hat 7.2.1-2)]
```

##### CONFIGURATION
Not relevant

##### OS / ENVIRONMENT
Fedora 26, target host: Fedora 26

##### SUMMARY
The module lineinfile creating underlying directory (when executed with the option "create=yes" doesn't manage filesystem exception like permission denied and it generate a stack trace.
The same problem was present(and has been fixed) in my [pull request](https://github.com/ansible/ansible/pull/27961#pullrequestreview-94179229) related to the module blockinfile. The source code related to "create=yes" is similar in blockinfile and lineinfile modules.

##### STEPS TO REPRODUCE

```
(ansibleenv) [user@localhost ansible]$ mkdir -p /tmp/ansible
(ansibleenv) [user@localhost ansible]$ sudo chown root /tmp/ansible
(ansibleenv) [user@localhost ansible]$ sudo chmod 700 /tmp/ansible

(ansibleenv) [user@localhost ansible]$ ./bin/ansible localhost -m lineinfile -a 'dest=/tmp/ansible/lineinfile/test state=present create=yes line=foo'
An exception occurred during task execution. To see the full traceback, use -vvv. The error was: OSError: [Errno 13] Permission denied: '/tmp/ansible/lineinfile'
localhost | FAILED! => {
    "changed": false, 
    "failed": true, 
    "module_stderr": "Traceback (most recent call last):\n  File \"/tmp/ansible_QgJFix/ansible_module_lineinfile.py\", line 503, in <module>\n    main()\n  File \"/tmp/ansible_QgJFix/ansible_module_lineinfile.py\", line 494, in main\n    ins_aft, ins_bef, create, backup, backrefs, firstmatch)\n  File \"/tmp/ansible_QgJFix/ansible_module_lineinfile.py\", line 241, in present\n    os.makedirs(b_destpath)\n  File \"/home/user/PyCharmVirtualEnv/ansibleenv/lib64/python2.7/os.py\", line 157, in makedirs\n    mkdir(name, mode)\nOSError: [Errno 13] Permission denied: '/tmp/ansible/lineinfile'\n", 
    "module_stdout": "", 
    "msg": "MODULE FAILURE", 
    "rc": 1
}

```

##### EXPECTED RESULTS
```
(ansibleenv) [user@localhost ansible]$ ./bin/ansible localhost -m lineinfile -a 'dest=/tmp/ansible/lineinfile/test state=present create=yes line=foo'
localhost | FAILED! => {
    "changed": false, 
    "failed": true, 
    "msg": "Error creating /tmp/ansible/lineinfile Error code: 13 Error description: Permission denied"
}
```

##### ACTUAL RESULTS
```
(ansibleenv) [user@localhost ansible]$ ./bin/ansible localhost -m lineinfile -a 'dest=/tmp/ansible/lineinfile/test state=present create=yes line=foo'
An exception occurred during task execution. To see the full traceback, use -vvv. The error was: OSError: [Errno 13] Permission denied: '/tmp/ansible/lineinfile'
localhost | FAILED! => {
    "changed": false, 
    "failed": true, 
    "module_stderr": "Traceback (most recent call last):\n  File \"/tmp/ansible_QgJFix/ansible_module_lineinfile.py\", line 503, in <module>\n    main()\n  File \"/tmp/ansible_QgJFix/ansible_module_lineinfile.py\", line 494, in main\n    ins_aft, ins_bef, create, backup, backrefs, firstmatch)\n  File \"/tmp/ansible_QgJFix/ansible_module_lineinfile.py\", line 241, in present\n    os.makedirs(b_destpath)\n  File \"/home/user/PyCharmVirtualEnv/ansibleenv/lib64/python2.7/os.py\", line 157, in makedirs\n    mkdir(name, mode)\nOSError: [Errno 13] Permission denied: '/tmp/ansible/lineinfile'\n", 
    "module_stdout": "", 
    "msg": "MODULE FAILURE", 
    "rc": 1
}
```



Discussion:

Resolving patch:
diff --git a/lib/ansible/modules/files/lineinfile.py b/lib/ansible/modules/files/lineinfile.py
--- a/lib/ansible/modules/files/lineinfile.py
+++ b/lib/ansible/modules/files/lineinfile.py
@@ -238,7 +238,11 @@ def present(module, dest, regexp, line, insertafter, insertbefore, create,
             module.fail_json(rc=257, msg='Destination %s does not exist !' % dest)
         b_destpath = os.path.dirname(b_dest)
         if not os.path.exists(b_destpath) and not module.check_mode:
-            os.makedirs(b_destpath)
+            try:
+                os.makedirs(b_destpath)
+            except Exception as e:
+                module.fail_json(msg='Error creating %s Error code: %s Error description: %s' % (b_destpath, e[0], e[1]))
+
         b_lines = []
     else:
         f = open(b_dest, 'rb')


Test patch: