rbw / pysnow

ServiceNow API Client Library
MIT License
204 stars 90 forks source link

Update a change request record using pysnow.response.Response update() fails. #166

Open ksanand opened 3 years ago

ksanand commented 3 years ago

I am trying to update the description of a standard change request like shown below but getting error

 api_path = /sn_chg_rest/change/standard/7fb6375cdb4624106377cae43a961924
    base_path = /api
    client = pysnow.Client(instance=instance, user=os.environ["USERNAME"], password=os.environ["PASSWORD"])
    resource = client.resource(base_path=base_path,api_path=api_path)
    result = resource.get()
    print(result.__dict__)
    ####{'_stream': False, '_chunk_size': 8192, '_count': 0, '_response': <Response [200]>, '_resource': <Resource [/sn_chg_rest/change/standard/7fb6375cdb4624106377cae43a961924/api] at 0x7f41460f5350>}
    result.update({"description": "blah"})  

File "/apps/home/u208825/.local/lib/python2.7/site-packages/pysnow/response.py", line 262, in update return self._resource.update({"sys_id": self["sys_id"]}, payload) File "/apps/home/u208825/.local/lib/python2.7/site-packages/pysnow/response.py", line 48, in getitem return self.one().get(key) File "/apps/home/u208825/.local/lib/python2.7/site-packages/pysnow/response.py", line 231, in one result, count = self._get_buffered_response() File "/apps/home/u208825/.local/lib/python2.7/site-packages/pysnow/response.py", line 159, in _get_buffered_response result = self._response.json().get("result", None) File "/apps/home/u208825/.local/lib/python2.7/site-packages/requests/models.py", line 897, in json return complexjson.loads(self.text, **kwargs) File "/usr/lib64/python2.7/json/init.py", line 338, in loads return _default_decoder.decode(s) File "/usr/lib64/python2.7/json/decoder.py", line 366, in decode obj, end = self.raw_decode(s, idx=_w(s, 0).end()) File "/usr/lib64/python2.7/json/decoder.py", line 384, in raw_decode raise ValueError("No JSON object could be decoded")

When I ran pdb, the failure happens in the following line

return self._resource.update({"sys_id": self["sys_id"]}, payload)

The above returned the error. There is no sys_id. How can resolve this issue?
ksanand commented 3 years ago

I think what is happening is,

131             """
132     
133             if not isinstance(payload, dict):
134                 raise InvalidUsage("Update payload must be of type dict")
135     
136  ->         record = self.get(query=query).one()
137     
138             self._url = self._get_custom_endpoint(record["sys_id"])
139             return self._get_response("PUT", data=json.dumps(payload))

Line 136 returns 2 values in the array - first one being the actual data and second one being the meta data

>>> print(a[0]["task_effective_number"])
{'display_value': 'CHG0211852', 'value': 'CHG0211852'}
>>> print(a[1])
{'__meta': {'fields': {'applied': ['number'], 'ignored': []}, 'encodedQuery': 'number=CHG0211852'}}

Hence self.get(query=query).one() results in the following exception.

*** MultipleResults: Expected single-record result, got multiple

Can anyone help me fixing this?

ksanand commented 3 years ago

I made the following changes to see if it works but got 405 with PUT request

> /apps/home/u208825/.local/lib/python2.7/site-packages/pysnow/request.py(136)update()
-> record = self.get(query=query).all()
(Pdb) 
> /apps/home/u208825/.local/lib/python2.7/site-packages/pysnow/request.py(138)update()
-> self._url = self._get_custom_endpoint(record[0]["sys_id"])

Error as below

{'cookies': <<class 'requests.cookies.RequestsCookieJar'>[]>, '_content': '{"error":{"message":"Method not Supported","detail":"PUT method not supported for API"},"status":"failure"}', 'headers': {'Strict-Transport-Security': 'max-age=63072000; includeSubDomains', 'Content-Encoding': 'gzip', 'Transfer-Encoding': 'chunked', 'Expires': '0', 'Server': 'ServiceNow', 'Pragma': 'no-store,no-cache', 'Cache-Control': 'no-cache,no-store,must-revalidate,max-age=-1', 'Date': 'Mon, 01 Feb 2021 00:37:10 GMT', 'Content-Type': 'application/json;charset=UTF-8'}, 'url': u'xxxxx/api/sn_chg_rest/change/standard/7fb6375cdb4624106377cae43a961924?sysparm_limit=10000&sysparm_fields=&sysparm_display_value=False&sysparm_suppress_pagination_header=False&sysparm_offset=0&sysparm_query=sys_id%3D7fb6375cdb4624106377cae43a961924&sysparm_view=&sysparm_exclude_reference_link=False', 'status_code': 405, '_content_consumed': True, 'encoding': 'UTF-8', 'request': <PreparedRequest [PUT]>, 'connection': <requests.adapters.HTTPAdapter object at 0x7f4e6fc3c8d0>, 'elapsed': datetime.timedelta(0, 0, 22889), 'raw': <urllib3.response.HTTPResponse object at 0x7f4e6fc3ced0>, 'reason': 'Method Not Allowed', '_next': None, 'history': []}

rbw commented 3 years ago

Taking a look shortly.

rbw commented 3 years ago

As you pointed out, a metadata object is included in the response when fetching by ID in the Change Management API. Pysnow doesn't support this; it expects exactly one object in the response content when performing an update this way.

I'll add support for passing sys_id directly Resource.update(), which should solve the issue with updates in this API, however, updating via a Response object will remain unsupported.

Anyway, try this in the meantime:

...
resource = client.resource(base_path="/api", api_path="/sn_chg_rest/change/standard")
resource.request(
    "PATCH",
    path_append="<sys_id>",
    json={"short_description": "hello"}
)
rbw commented 3 years ago

I've created a PR to make it possible to update records in the sn_chg_rest API using standard methods: https://github.com/rbw/pysnow/pull/169

Would appreciate it if you could test it out.

And again, updating via a Response object will remain unsupported for this API.

rbw commented 3 years ago

@ksanand have you had a chance to test this out?

ksanand commented 3 years ago

Sorry, I haven’t had a chance to test it yet. I will get to it sometime this week.

Thanks, Anand.

On Sun, 21 Mar 2021 at 8:06 pm, Robert Wikman @.***> wrote:

@ksanand https://github.com/ksanand have you had a chance to test this out?

— You are receiving this because you were mentioned.

Reply to this email directly, view it on GitHub https://github.com/rbw/pysnow/issues/166#issuecomment-803537395, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAUT6K62HCWGUVB2IKYW4KLTEWZITANCNFSM4WYIGHVA .