Skip to content

Commit 4786932

Browse files
authored
DCNM_REST: Adding support for Encoding Type 'x-www-form-urlencoded' (#490)
* Add support for body-data encoding type 'x-www-form-urlencoded' * Fix Pep8 Error --------- Co-authored-by: = <=>
1 parent 4aa5602 commit 4786932

File tree

4 files changed

+55
-3
lines changed

4 files changed

+55
-3
lines changed

docs/cisco.dcnm.dcnm_rest_module.rst

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,21 @@ Parameters
8787
<div>REST API Path Endpoint</div>
8888
</td>
8989
</tr>
90+
<tr>
91+
<td colspan="1">
92+
<div class="ansibleOptionAnchor" id="parameter-"></div>
93+
<b>urlencoded_data</b>
94+
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
95+
<div style="font-size: small">
96+
<span style="color: purple">raw</span>
97+
</div>
98+
</td>
99+
<td>
100+
</td>
101+
<td>
102+
<div>Dictionary data to be url-encoded for x-www-form-urlencoded type REST API call</div>
103+
</td>
104+
</tr>
90105
</table>
91106
<br/>
92107

@@ -115,6 +130,12 @@ Examples
115130
path: /rest/top-down/fabrics/fabric1/vrfs/attachments
116131
json_data: '[{"vrfName":"sales66_vrf1","lanAttachList":[{"fabric":"fabric1","vrfName":"sales66_vrf1","serialNumber":"FDO21392QKM","vlan":2000,"freeformConfig":"","deployment":false,"extensionValues":"","instanceValues":"{"loopbackId":"","loopbackIpAddress":"","loopbackIpV6Address":""}"}]}]'
117132
133+
- name: Save Robot Credentials - (urlencoded)
134+
dcnm_rest:
135+
method: POST
136+
path: /rest/lanConfig/saveRobotCredentials
137+
urlencoded_data: '{"password": "password", "username": "admin"}'
138+
118139
# Read payload data from file and validate a template
119140
- set_fact:
120141
data: "{{ lookup('file', 'validate_payload') }}"

plugins/httpapi/dcnm.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ class HttpApi(HttpApiBase):
6666
def __init__(self, *args, **kwargs):
6767
super(HttpApi, self).__init__(*args, **kwargs)
6868
self.headers = {"Content-Type": "application/json"}
69+
self.urlencoded_headers = {"Content-Type": "application/x-www-form-urlencoded"}
6970
self.txt_headers = {"Content-Type": "text/plain"}
7071
self.version = None
7172
self.retrycount = DEFAULT_RETRY_COUNT
@@ -252,6 +253,10 @@ def send_request(self, method, path, json=None):
252253
"""This method handles all DCNM REST API requests other than login"""
253254
return self._send_request_internal(method, path, json or {}, self.headers)
254255

256+
def send_urlencoded_request(self, method, path, urlencoded=None):
257+
"""This method handles all DCNM REST API urlencoded requests other than login"""
258+
return self._send_request_internal(method, path, urlencoded or {}, self.urlencoded_headers)
259+
255260
def send_txt_request(self, method, path, txt=None):
256261
"""This method handles all DCNM REST API text requests other than login"""
257262
return self._send_request_internal(method, path, txt or "", self.txt_headers)

plugins/module_utils/network/dcnm/dcnm.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -500,6 +500,8 @@ def dcnm_send(module, method, path, data=None, data_type="json"):
500500

501501
if data_type == "json":
502502
return conn.send_request(method, path, data)
503+
elif data_type == "urlencoded":
504+
return conn.send_urlencoded_request(method, path, data)
503505
elif data_type == "text":
504506
return conn.send_txt_request(method, path, data)
505507

plugins/modules/dcnm_rest.py

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,11 @@
4444
- json_data
4545
required: no
4646
type: raw
47+
urlencoded_data:
48+
description:
49+
- 'Dictionary data to be url-encoded for x-www-form-urlencoded type REST API call'
50+
required: no
51+
type: raw
4752
author:
4853
- Mike Wiebe (@mikewiebe)
4954
"""
@@ -66,6 +71,12 @@
6671
path: /rest/top-down/fabrics/fabric1/vrfs/attachments
6772
json_data: '[{"vrfName":"sales66_vrf1","lanAttachList":[{"fabric":"fabric1","vrfName":"sales66_vrf1","serialNumber":"FDO21392QKM","vlan":2000,"freeformConfig":"","deployment":false,"extensionValues":"","instanceValues":"{\"loopbackId\":\"\",\"loopbackIpAddress\":\"\",\"loopbackIpV6Address\":\"\"}"}]}]'
6873
74+
- name: Save Robot Credentials - (urlencoded)
75+
dcnm_rest:
76+
method: POST
77+
path: /rest/lanConfig/saveRobotCredentials
78+
urlencoded_data: '{"password": "password", "username": "admin"}'
79+
6980
# Read payload data from file and validate a template
7081
- set_fact:
7182
data: "{{ lookup('file', 'validate_payload') }}"
@@ -89,6 +100,7 @@
89100
"""
90101

91102
import json
103+
import urllib.parse
92104
from ansible.module_utils.basic import AnsibleModule
93105
from ansible_collections.cisco.dcnm.plugins.module_utils.network.dcnm.dcnm import (
94106
dcnm_send,
@@ -101,6 +113,7 @@ def main():
101113
method=dict(required=True, choices=["GET", "POST", "PUT", "DELETE"]),
102114
path=dict(required=True, type="str"),
103115
data=dict(type="raw", required=False, default=None, aliases=["json_data"]),
116+
urlencoded_data=dict(type="raw", required=False, default=None),
104117
)
105118

106119
# seed the result dict
@@ -110,17 +123,28 @@ def main():
110123

111124
method = module.params["method"]
112125
path = module.params["path"]
113-
for key in ["json_data", "data"]:
126+
is_urlencoded = False
127+
128+
for key in ["json_data", "data", "urlencoded_data"]:
114129
data = module.params.get(key)
115130
if data is not None:
131+
if key == "urlencoded_data":
132+
is_urlencoded = True
116133
break
117134
if data is None:
118135
data = "{}"
119136

120137
# Determine if this is valid JSON or not
121138
try:
122-
json.loads(data)
123-
result["response"] = dcnm_send(module, method, path, data)
139+
json_data = json.loads(data)
140+
if is_urlencoded:
141+
# If the data is valid JSON but marked as urlencoded, we need to convert it
142+
# to a URL-encoded string before sending it.
143+
urlencoded_data = urllib.parse.urlencode(json_data)
144+
result["response"] = dcnm_send(module, method, path, urlencoded_data, "urlencoded")
145+
else:
146+
# If the data is valid JSON, send it as a JSON string
147+
result["response"] = dcnm_send(module, method, path, data)
124148
except json.JSONDecodeError:
125149
# Resend data as text since it's not valid JSON
126150
result["response"] = dcnm_send(module, method, path, data, "text")

0 commit comments

Comments
 (0)