Repository: ansible/ansible

Issue:
junos_config fails if config format is xml
<!---
Verify first that your issue/request is not already reported on GitHub.
Also test if the latest release, and master branch are affected too.
-->

##### ISSUE TYPE
<!--- Pick one below and delete the rest: -->
 - Bug Report

##### COMPONENT NAME
<!--- Name of the module/plugin/task/feature -->
junos_config

##### ANSIBLE VERSION
<!--- Paste verbatim output from “ansible --version” between quotes below -->
```
2.3
```

##### CONFIGURATION
<!---
Mention any settings you have changed/added/removed in ansible.cfg
(or using the ANSIBLE_* environment variables).
-->

##### 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.
-->

##### SUMMARY
<!--- Explain the problem briefly -->

##### STEPS TO REPRODUCE
```
Create a file with junos config in xml format
$ cat junos_config.xml
<interfaces>
    <interface>
        <name>ae11</name>
        <unit>
            <name>0</name>
            <description>Test</description>
        </unit>
    </interface>
</interfaces>
```
-->

<!--- Paste example playbooks or commands between quotes below -->
```yaml
  - name: Run junos_config
    junos_config:
      src:  junos_config.xml
      comment: update config
      host: "{{ ansible_ssh_host }}"
      username: "{{ juniper_user }}"
      password: "{{ juniper_passwd }}"
```

<!--- You can also paste gist.github.com links for larger files -->

##### EXPECTED RESULTS
<!--- What did you expect to happen when running the steps above? -->
Run should configure interface on device
##### ACTUAL RESULTS
<!--- What actually happened? If possible run with extra verbosity (-vvvv) -->
Fails with error message.
<!--- Paste verbatim command output between quotes below -->
```
 "msg": "<?xml version=\"1.0\" encoding=\"UTF-8\"?><rpc-error xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\" xmlns:junos=\"http://xml.juniper.net/junos/15.1X49/junos\" xmlns:nc=\"urn:ietf:params:xml:ns:netconf:base:1.0\">\n<error-type>protocol</error-type>\n<error-tag>operation-failed</error-tag>\n<error-severity>error</error-severity>\n<error-message>syntax error, expecting &lt;/configuration&gt;</error-message>\n<error-info>\n<bad-element>&lt;interfaces&gt;\n    &lt;interface&gt;\n        &lt;name&gt;ae11&lt;/name&gt;\n        &lt;unit&gt;\n            &lt;name&gt;0&lt;/name&gt;\n            &lt;description&gt;Test&lt;/description&gt;\n        &lt;/unit&gt;\n    &lt;/interface&gt;\n&lt;/interfaces&gt;</bad-element>\n</error-info>\n</rpc-error>\n"
```



Discussion:

Resolving patch:
diff --git a/lib/ansible/module_utils/junos.py b/lib/ansible/module_utils/junos.py
--- a/lib/ansible/module_utils/junos.py
+++ b/lib/ansible/module_utils/junos.py
@@ -18,7 +18,7 @@
 #
 from contextlib import contextmanager
 
-from xml.etree.ElementTree import Element, SubElement
+from xml.etree.ElementTree import Element, SubElement, fromstring
 
 from ansible.module_utils.basic import env_fallback, return_values
 from ansible.module_utils.netconf import send_request, children
@@ -108,10 +108,12 @@ def load_configuration(module, candidate=None, action='merge', rollback=None, fo
             cfg = SubElement(obj, lookup[format])
 
         if isinstance(candidate, string_types):
-            cfg.text = candidate
+            if format == 'xml':
+                cfg.append(fromstring(candidate))
+            else:
+                cfg.text = candidate
         else:
             cfg.append(candidate)
-
     return send_request(module, obj)
 
 def get_configuration(module, compare=False, format='xml', rollback='0'):


Test patch: