Repository: ansible/ansible

Issue:
ini_file crash when destination file don't exists or is empty
<!---
Verify first that your issue/request is not already reported on GitHub.
Also test if the latest release, and master branch are affected too.
-->
ini_file crash when destination file don't exists

##### ISSUE TYPE
<!--- Pick one below and delete the rest: -->
Bug Report


##### COMPONENT NAME
<!--- Name of the module/plugin/task/feature -->
ini_file module

##### ANSIBLE VERSION
<!--- Paste verbatim output from “ansible --version” between quotes below -->
```
ansible 2.3.0 (ini_file_bug 62897725cd) last updated 2017/03/01 12:19:00 (GMT +200)
  config file = /home/ben/.ansible.cfg
  configured module search path = Default w/o overrides
```

##### CONFIGURATION
<!---
Mention any settings you have changed/added/removed in ansible.cfg
(or using the ANSIBLE_* environment variables).
-->
host_key_checking=False
roles_path = ~/ansible/roles
retry_files_enabled = False

##### OS / ENVIRONMENT
<!---
Mention the OS you are running Ansible from, and the OS you are
managing, or say “N/A” for anything that is not platform-specific.
-->
Ubuntu 16.04 

##### SUMMARY
<!--- Explain the problem briefly -->
Ansible-playbook crash when using ini_file module with non existing file or empty file

##### STEPS TO REPRODUCE
<!---
For bugs, show exactly how to reproduce the problem, using a minimal test-case.
For new features, show how the feature would be used.
-->

<!--- Paste example playbooks or commands between quotes below -->
```yaml
- hosts: localhost
  become: true
  tasks:
    - ini_file: 
        dest: "/tmp/test.ini" 
        section: "mysection" 
        option: "myoption" 
        value: "myvalue"
```

<!--- You can also paste gist.github.com links for larger files -->

##### EXPECTED RESULTS
<!--- What did you expect to happen when running the steps above? -->
No crash

##### ACTUAL RESULTS
<!--- What actually happened? If possible run with extra verbosity (-vvvv) -->
crash

<!--- Paste verbatim command output between quotes below -->
```
An exception occurred during task execution. The full traceback is:
Traceback (most recent call last):
  File "/tmp/ansible_FEldtp/ansible_module_ini_file.py", line 314, in <module>
    main()
  File "/tmp/ansible_FEldtp/ansible_module_ini_file.py", line 300, in main
    (changed,backup_file,diff,msg) = do_ini(module, path, section, option, value, state, backup, no_extra_spaces, create)
  File "/tmp/ansible_FEldtp/ansible_module_ini_file.py", line 180, in do_ini
    if ini_lines[-1] == "" or ini_lines[-1][-1] != '\n':
IndexError: list index out of range

fatal: [localhost]: FAILED! => {
    "changed": false,
    "failed": true,
    "module_stderr": "Traceback (most recent call last):\n  File \"/tmp/ansible_FEldtp/ansible_module_ini_file.py\", line 314, in <module>\n    main()\n  File \"/tmp/ansible_FEldtp/ansible_module_ini_file.py\", line 300, in main\n    (changed,backup_file,diff,msg) = do_ini(module, path, section, option, value, state, backup, no_extra_spaces, create)\n  File \"/tmp/ansible_FEldtp/ansible_module_ini_file.py\", line 180, in do_ini\n    if ini_lines[-1] == \"\" or ini_lines[-1][-1] != '\\n':\nIndexError: list index out of range\n",
    "module_stdout": "",
    "msg": "MODULE FAILURE",
    "rc": 0
}
```


ini_file crash when destination file don't exists or is empty
<!---
Verify first that your issue/request is not already reported on GitHub.
Also test if the latest release, and master branch are affected too.
-->
ini_file crash when destination file don't exists

##### ISSUE TYPE
<!--- Pick one below and delete the rest: -->
Bug Report


##### COMPONENT NAME
<!--- Name of the module/plugin/task/feature -->
ini_file module

##### ANSIBLE VERSION
<!--- Paste verbatim output from “ansible --version” between quotes below -->
```
ansible 2.3.0 (ini_file_bug 62897725cd) last updated 2017/03/01 12:19:00 (GMT +200)
  config file = /home/ben/.ansible.cfg
  configured module search path = Default w/o overrides
```

##### CONFIGURATION
<!---
Mention any settings you have changed/added/removed in ansible.cfg
(or using the ANSIBLE_* environment variables).
-->
host_key_checking=False
roles_path = ~/ansible/roles
retry_files_enabled = False

##### OS / ENVIRONMENT
<!---
Mention the OS you are running Ansible from, and the OS you are
managing, or say “N/A” for anything that is not platform-specific.
-->
Ubuntu 16.04 

##### SUMMARY
<!--- Explain the problem briefly -->
Ansible-playbook crash when using ini_file module with non existing file or empty file

##### STEPS TO REPRODUCE
<!---
For bugs, show exactly how to reproduce the problem, using a minimal test-case.
For new features, show how the feature would be used.
-->

<!--- Paste example playbooks or commands between quotes below -->
```yaml
- hosts: localhost
  become: true
  tasks:
    - ini_file: 
        dest: "/tmp/test.ini" 
        section: "mysection" 
        option: "myoption" 
        value: "myvalue"
```

<!--- You can also paste gist.github.com links for larger files -->

##### EXPECTED RESULTS
<!--- What did you expect to happen when running the steps above? -->
No crash

##### ACTUAL RESULTS
<!--- What actually happened? If possible run with extra verbosity (-vvvv) -->
crash

<!--- Paste verbatim command output between quotes below -->
```
An exception occurred during task execution. The full traceback is:
Traceback (most recent call last):
  File "/tmp/ansible_FEldtp/ansible_module_ini_file.py", line 314, in <module>
    main()
  File "/tmp/ansible_FEldtp/ansible_module_ini_file.py", line 300, in main
    (changed,backup_file,diff,msg) = do_ini(module, path, section, option, value, state, backup, no_extra_spaces, create)
  File "/tmp/ansible_FEldtp/ansible_module_ini_file.py", line 180, in do_ini
    if ini_lines[-1] == "" or ini_lines[-1][-1] != '\n':
IndexError: list index out of range

fatal: [localhost]: FAILED! => {
    "changed": false,
    "failed": true,
    "module_stderr": "Traceback (most recent call last):\n  File \"/tmp/ansible_FEldtp/ansible_module_ini_file.py\", line 314, in <module>\n    main()\n  File \"/tmp/ansible_FEldtp/ansible_module_ini_file.py\", line 300, in main\n    (changed,backup_file,diff,msg) = do_ini(module, path, section, option, value, state, backup, no_extra_spaces, create)\n  File \"/tmp/ansible_FEldtp/ansible_module_ini_file.py\", line 180, in do_ini\n    if ini_lines[-1] == \"\" or ini_lines[-1][-1] != '\\n':\nIndexError: list index out of range\n",
    "module_stdout": "",
    "msg": "MODULE FAILURE",
    "rc": 0
}
```




Discussion:
cc @jpmens @noseka1
[click here for bot help](https://github.com/ansible/ansibullbot/blob/master/ISSUE_HELP.md)
<!--- boilerplate: notify --->
cc @jpmens @noseka1
[click here for bot help](https://github.com/ansible/ansibullbot/blob/master/ISSUE_HELP.md)
<!--- boilerplate: notify --->

Resolving patch:
diff --git a/lib/ansible/modules/files/ini_file.py b/lib/ansible/modules/files/ini_file.py
--- a/lib/ansible/modules/files/ini_file.py
+++ b/lib/ansible/modules/files/ini_file.py
@@ -176,6 +176,10 @@ def do_ini(module, filename, section=None, option=None, value=None,
 
     changed = False
 
+    # ini file could be empty
+    if not ini_lines:
+        ini_lines.append('\n')
+
     # last line of file may not contain a trailing newline
     if ini_lines[-1] == "" or ini_lines[-1][-1] != '\n':
         ini_lines[-1] += '\n'


Test patch: