Skip to content

DCNM_REST: Add support for Encoding Type 'x-www-form-urlencoded' #462

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions plugins/httpapi/dcnm.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ def __init__(self, *args, **kwargs):
self.version = None
# Retry count for send API
self.retrycount = 5
self.token = None

def get_version(self):
return self.version
Expand Down
39 changes: 30 additions & 9 deletions plugins/module_utils/network/dcnm/dcnm.py
Original file line number Diff line number Diff line change
Expand Up @@ -803,22 +803,43 @@ def dcnm_get_protocol_and_address(module):
return [split_url[0], split_url[1]]


def dcnm_login_retrieve_token(module):
# Login to DCNM and retrieve the authentication token
conn = Connection(module._socket_path)
# If the connection has a token, we will use it.
token = conn.get_token()
if token is not None:
return token
# If the connection does not have a token, we will login
# using username and password and return the new token.
conn.login(conn.get_option("remote_user"), conn.get_option("password"))
return conn.get_token()


def dcnm_get_auth_token(module):

conn = Connection(module._socket_path)
return conn.get_token()


def dcnm_post_request(path, hdrs, verify_flag, upload_files):
def dcnm_post_request(path, hdrs, **kwargs):
# Keyword Arguments
verify_flag = kwargs.get("verify")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just curious, but why was this changed to use kwargs? Mainly readability or was it a functional problem you were fixing here?

upload_files = kwargs.get("files")
data = kwargs.get("data")

resp = requests.post(path, headers=hdrs, verify=verify_flag, files=upload_files)
json_resp = resp.json()
if json_resp:
json_resp["RETURN_CODE"] = resp.status_code
json_resp["DATA"] = json_resp["message"]
json_resp["METHOD"] = "POST"
json_resp["REQUEST_PATH"] = path
json_resp.pop("message")
resp = requests.post(path, data, headers=hdrs, verify=verify_flag, files=upload_files)
json_resp = {}
json_resp["RETURN_CODE"] = resp.status_code
json_resp["METHOD"] = "POST"
json_resp["REQUEST_PATH"] = path
try:
json_resp = resp.json()
if json_resp:
json_resp["DATA"] = json_resp["message"]
json_resp.pop("message")
except ValueError:
json_resp["DATA"] = resp.text
return json_resp


Expand Down
2 changes: 1 addition & 1 deletion plugins/modules/dcnm_image_upload.py
Original file line number Diff line number Diff line change
Expand Up @@ -636,7 +636,7 @@ def dcnm_image_upload_handle_local_file_transfer(self, elem):
if file_path:
upload_files = {"file": open(file_path, "rb")}

resp = dcnm_post_request(path, headers, False, upload_files)
resp = dcnm_post_request(path, headers, verify=False, files=upload_files)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did you test this fix with the dcnm_image_upload module?


self.result["response"].append(resp)

Expand Down
30 changes: 26 additions & 4 deletions plugins/modules/dcnm_rest.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,12 @@
- json_data
required: no
type: raw
encoding:
description:
- 'Type of body encoding to use for the request'
choices: ['json', 'text', 'urlencoded']
default: json
type: str
author:
- Mike Wiebe (@mikewiebe)
"""
Expand Down Expand Up @@ -91,8 +97,7 @@
import json
from ansible.module_utils.basic import AnsibleModule
from ansible_collections.cisco.dcnm.plugins.module_utils.network.dcnm.dcnm import (
dcnm_send,
)
dcnm_send, dcnm_post_request, dcnm_login_retrieve_token)


def main():
Expand All @@ -101,6 +106,7 @@ def main():
method=dict(required=True, choices=["GET", "POST", "PUT", "DELETE"]),
path=dict(required=True, type="str"),
data=dict(type="raw", required=False, default=None, aliases=["json_data"]),
encoding=dict(type="str", default="json", choices=["json", "text", "urlencoded"]),
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would prefer we follow the same method we used for text and not require the user to pass in the encoding type. Do we get back a python exception for urlencoded that we can use similar to text?

)

# seed the result dict
Expand All @@ -116,14 +122,30 @@ def main():
break
if data is None:
data = "{}"
encoding = module.params["encoding"]

# Determine if this is valid JSON or not
try:
json.loads(data)
result["response"] = dcnm_send(module, method, path, data)
if encoding == "urlencoded":
headers = {}
auth_token = dcnm_login_retrieve_token(module)
headers.update(auth_token)
headers.update({'Content-Type': 'application/x-www-form-urlencoded'})
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should not need to login directly here in this module. Can you explore handling this as another option like we do for json and text in our connection plugin?

See:

self.headers = {"Content-Type": "application/json"}

resp = dcnm_post_request(path, headers, data=data, verify=False)
result["response"] = resp
elif encoding == "json":
result["response"] = dcnm_send(module, method, path, data)
else:
msg = "Encoding type '{}' is not supported for input data".format(encoding)
module.fail_json(msg=msg)
except json.JSONDecodeError:
# Resend data as text since it's not valid JSON
result["response"] = dcnm_send(module, method, path, data, "text")
if encoding == "text":
result["response"] = dcnm_send(module, method, path, data, "text")
else:
msg = "Encoding type '{}' is not supported for input data".format(encoding)
module.fail_json(msg=msg)

if result["response"]["RETURN_CODE"] >= 400:
module.fail_json(msg=result["response"])
Expand Down