Repository: ansible/ansible

Issue:
eos_config: re-runs using a src template file fail
##### ISSUE TYPE
 - Bug Report

##### COMPONENT NAME
eos_config

##### ANSIBLE VERSION
```
ansible-playbook 2.4.0 (devel 4522a53acf) last updated 2017/06/19 10:47:06 (GMT +100)
  config file = 
  configured module search path = [u'/Users/lynchg/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
  ansible python module location = /Users/lynchg/git/github.com/ansible/ansible/lib/ansible
  executable location = /Users/lynchg/git/github.com/ansible/ansible/bin/ansible-playbook
  python version = 2.7.13 (default, Dec 18 2016, 07:03:34) [GCC 4.2.1 Compatible Apple LLVM 7.0.2 (clang-700.1.81)]
```
and
```
ansible-playbook 2.3.1.0
  config file = 
  configured module search path = Default w/o overrides
  python version = 2.7.13 (default, Dec 18 2016, 07:03:34) [GCC 4.2.1 Compatible Apple LLVM 7.0.2 (clang-700.1.81)]
```

##### CONFIGURATION
(default)

##### OS / ENVIRONMENT
Mac OS
virtualenv

##### SUMMARY
Re-runs of eos_config fail when using a src template file

##### STEPS TO REPRODUCE
See https://gist.github.com/halberom/d15181e6403ea3d9a4296a3fa6c0df7b

##### EXPECTED RESULTS
No errors

##### ACTUAL RESULTS
See gist


Note that I attempted to use `replace: block`, but that requires the use of the `lines` param.  And using `replace: config` kindly replaces _everything_.


Discussion:
cc @privateip @trishnaguha
[click here for bot help](https://github.com/ansible/ansibullbot/blob/master/ISSUE_HELP.md)
<!--- boilerplate: notify --->
Works if I use `match: none`, but that kinda defeats the purpose.
[pasting one of the example output and errors from gist https://gist.github.com/halberom/d15181e6403ea3d9a4296a3fa6c0df7b#file-04_output here so issue search finds it...]

```
PLAY [switch-1] 
TASK [run show inventory] 
 [WARNING]: argument transport has been deprecated and will be removed in a future version
ok: [switch-1]

TASK [debug] 
ok: [switch-1] => {
    "result": {
        "changed": false,
        "stdout": [
            {
                "cardSlots": {},
                "dataLinkPortCount": 0,
                "fanTraySlots": {},
                "fpgas": {},
                "internalPortCount": 0,
                "managementPortCount": 1,
                "portCount": 3,
                "powerSupplySlots": {},
                "storageDevices": {},
                "switchedFortyGOnlyPortCount": 0,
                "switchedPortCount": 2,
                "systemInformation": {
                    "description": "vEOS",
                    "hardwareRev": "",
                    "hwEpoch": "",
                    "mfgDate": "",
                    "name": "vEOS",
                    "serialNum": ""
                },
                "unconnectedPortCount": 0,
                "xcvrSlots": {}
            }
        ],
        "stdout_lines": [
            {
                "cardSlots": {},
                "dataLinkPortCount": 0,
                "fanTraySlots": {},
                "fpgas": {},
                "internalPortCount": 0,
                "managementPortCount": 1,
                "portCount": 3,
                "powerSupplySlots": {},
                "storageDevices": {},
                "switchedFortyGOnlyPortCount": 0,
                "switchedPortCount": 2,
                "systemInformation": {
                    "description": "vEOS",
                    "hardwareRev": "",
                    "hwEpoch": "",
                    "mfgDate": "",
                    "name": "vEOS",
                    "serialNum": ""
                },
                "unconnectedPortCount": 0,
                "xcvrSlots": {}
            }
        ],
        "warnings": [
            "argument transport has been deprecated and will be removed in a future version"
        ]
    }
}

TASK [create the initial vlans] 
changed: [switch-1]

TASK [re-run vlans config and add one] 
fatal: [switch-1]: FAILED! => {"changed": false, "code": 1002, "failed": true, "msg": "CLI command 3 of 6 'name foo' failed: invalid command"}

switch-1                   : ok=3    changed=1    unreachable=0    failed=1
```
Works fine if instead of using `src: ...j2`, you use `line: "{{ lookup('template', '...j2') }}`.  

I've been looking to use `src:` so that it could handle a block of config cleanly, but it appears that won't work anyway - e.g. if you remove a command/list item, it won't be cleared, you have to have `before` logic, or do a full config replace with `replace: config`.

Resolving patch:
diff --git a/lib/ansible/modules/network/eos/eos_config.py b/lib/ansible/modules/network/eos/eos_config.py
--- a/lib/ansible/modules/network/eos/eos_config.py
+++ b/lib/ansible/modules/network/eos/eos_config.py
@@ -276,7 +276,7 @@
 
 
 def get_candidate(module):
-    candidate = NetworkConfig(indent=3)
+    candidate = NetworkConfig(indent=2)
     if module.params['src']:
         candidate.load(module.params['src'])
     elif module.params['lines']:
@@ -295,7 +295,7 @@ def get_running_config(module, config=None):
             if module.params['defaults']:
                 flags.append('all')
             contents = get_config(module, flags=flags)
-    return NetworkConfig(indent=3, contents=contents)
+    return NetworkConfig(indent=2, contents=contents)
 
 
 def main():


Test patch: