saltstack / salt

Software to automate the management and configuration of any infrastructure or application at scale. Get access to the Salt software package repository here:
https://repo.saltproject.io/
Apache License 2.0
14.11k stars 5.47k forks source link

[BUG] serialization issue in kubernetes show_namespace through salt-api #61371

Open gg17 opened 2 years ago

gg17 commented 2 years ago

Description When the kubernetes.show_namespace function is called through the salt-api it returns an "500 Internal Server Error". Calling the same function through the salt commandline does work.

root@salt-master-55d7dc7477-vwdmz:/# curl -i --insecure -X POST https://localhost:8001 -H 'Content-type: application/json' -H 'X-Auth-Token:0c99cf51e4eb713b690e44ea08f3d8271cc89583' -d '{"client":"local","tgt":"8YVR363","fun":"kubernetes.show_namespace","arg":["test123"]}'
HTTP/1.1 500 Internal Server Error
Content-Type: text/html;charset=utf-8
Server: CherryPy/18.6.1
Date: Wed, 15 Dec 2021 14:19:16 GMT
Allow: GET, HEAD, POST
Access-Control-Allow-Origin: *
Access-Control-Expose-Headers: GET, POST
Access-Control-Allow-Credentials: true
Cache-Control: private
Content-Length: 2324
Vary: Accept-Encoding
Set-Cookie: session_id=0c99cf51e4eb713b690e44ea08f3d8271cc89583; expires=Thu, 16 Dec 2021 00:19:16 GMT; Max-Age=36000; Path=/

<!DOCTYPE html PUBLIC
"-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8"></meta>
    <title>500 Internal Server Error</title>
    <style type="text/css">
    #powered_by {
        margin-top: 20px;
        border-top: 2px solid black;
        font-style: italic;
    }

    #traceback {
        color: red;
    }
    </style>
</head>
    <body>
        <h2>500 Internal Server Error</h2>
        <p>Could not serialize the return data from Salt.</p>
        <pre id="traceback">Traceback (most recent call last):
  File "/usr/lib/python3/dist-packages/salt/netapi/rest_cherrypy/app.py", line 909, in hypermedia_handler
    response = out(ret)
  File "/usr/lib/python3/dist-packages/salt/utils/json.py", line 149, in dumps
    return json_module.dumps(obj, **kwargs)  # future lint: blacklisted-function
  File "/usr/lib/python3.7/json/__init__.py", line 238, in dumps
    **kw).encode(obj)
  File "/usr/lib/python3.7/json/encoder.py", line 199, in encode
    chunks = self.iterencode(o, _one_shot=True)
  File "/usr/lib/python3.7/json/encoder.py", line 257, in iterencode
    return _iterencode(o, 0)
  File "/usr/lib/python3.7/json/encoder.py", line 179, in default
    raise TypeError(f'Object of type {o.__class__.__name__} '
TypeError: Object of type datetime is not JSON serializable

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/local/lib/python3.7/dist-packages/cherrypy/_cprequest.py", line 638, in respond
    self._do_respond(path_info)
  File "/usr/local/lib/python3.7/dist-packages/cherrypy/_cprequest.py", line 697, in _do_respond
    response.body = self.handler()
  File "/usr/local/lib/python3.7/dist-packages/cherrypy/lib/encoding.py", line 223, in __call__
    self.body = self.oldhandler(*args, **kwargs)
  File "/usr/lib/python3/dist-packages/salt/netapi/rest_cherrypy/app.py", line 914, in hypermedia_handler
    raise cherrypy.HTTPError(500, msg)
cherrypy._cperror.HTTPError: (500, 'Could not serialize the return data from Salt.')
</pre>
    <div id="powered_by">
      <span>
        Powered by <a href="http://www.cherrypy.org">CherryPy 18.6.1</a>
      </span>
    </div>
    </body>
</html>
root@salt-master-55d7dc7477-vwdmz:/# salt 8YVR363 kubernetes.show_namespace test123
8YVR363:
    ----------
    api_version:
        v1
    kind:
        Namespace
    metadata:
        ----------
        annotations:
            None
        cluster_name:
            None
        creation_timestamp:
        deletion_grace_period_seconds:
            None
        deletion_timestamp:
            None
        finalizers:
            None
        generate_name:
            None
        generation:
            None
        labels:
            None
        managed_fields:
            |_
              ----------
              api_version:
                  v1
              fields_type:
                  FieldsV1
              fields_v1:
                  ----------
                  f:status:
                      ----------
                      f:phase:
                          ----------
              manager:
                  OpenAPI-Generator
              operation:
                  Update
              time:
        name:
            test123
        namespace:
            None
        owner_references:
            None
        resource_version:
            101416
        self_link:
            None
        uid:
            72e1a2b1-0afe-426a-bde7-ef516e354ec6
    spec:
        ----------
        finalizers:
            - kubernetes
    status:
        ----------
        conditions:
            None
        phase:
            Active
root@salt-master-55d7dc7477-vwdmz:/# salt 8YVR363 kubernetes.show_namespace test123 --out raw
{'8YVR363': {'api_version': 'v1', 'kind': 'Namespace', 'metadata': {'annotations': None, 'cluster_name': None, 'creation_timestamp': datetime.datetime(2021, 12, 15, 12, 48, 40), 'deletion_grace_period_seconds': None, 'deletion_timestamp': None, 'finalizers': None, 'generate_name': None, 'generation': None, 'labels': None, 'managed_fields': [{'api_version': 'v1', 'fields_type': 'FieldsV1', 'fields_v1': {'f:status': {'f:phase': {}}}, 'manager': 'OpenAPI-Generator', 'operation': 'Update', 'time': datetime.datetime(2021, 12, 15, 12, 48, 40)}], 'name': 'test123', 'namespace': None, 'owner_references': None, 'resource_version': '101416', 'self_link': None, 'uid': '72e1a2b1-0afe-426a-bde7-ef516e354ec6'}, 'spec': {'finalizers': ['kubernetes']}, 'status': {'conditions': None, 'phase': 'Active'}}}

In the raw output from the commandline it can be observed that a 'creation_timestamp': datetime.datetime(2021, 12, 15, 12, 48, 40), object is returned, which likely corresponds with the error of the server TypeError: Object of type datetime is not JSON serializable.

Setup

Our salt-minion is running on-prem directly on the kubernetes host. Our salt-master is running in a container, together with the salt-api in a different kubernetes cluster. The salt-minion connects to the service IP of the salt-master container.

Steps to Reproduce the behavior Call the salt-api with: curl -i --insecure -X POST https://localhost:8001 -H 'Content-type: application/json' -H 'X-Auth-Token:<auth-token>' -d '{"client":"local","tgt":"<minion-id>","fun":"kubernetes.show_namespace","arg":["<namespace-to-show>"]}' on a salt-minion running on a kubernetes host and query for a specific, existing namespace.

Expected behavior The return should be similar to the cmdline output:

root@salt-master-55d7dc7477-vwdmz:/# salt 8YVR363 kubernetes.show_namespace test123 --out json
{
    "8YVR363": {
        "api_version": "v1",
        "kind": "Namespace",
        "metadata": {
            "annotations": null,
            "cluster_name": null,
            "creation_timestamp": "datetime.datetime(2021, 12, 15, 12, 48, 40)",
            "deletion_grace_period_seconds": null,
            "deletion_timestamp": null,
            "finalizers": null,
            "generate_name": null,
            "generation": null,
            "labels": null,
            "managed_fields": [
                {
                    "api_version": "v1",
                    "fields_type": "FieldsV1",
                    "fields_v1": {
                        "f:status": {
                            "f:phase": {}
                        }
                    },
                    "manager": "OpenAPI-Generator",
                    "operation": "Update",
                    "time": "datetime.datetime(2021, 12, 15, 12, 48, 40)"
                }
            ],
            "name": "test123",
            "namespace": null,
            "owner_references": null,
            "resource_version": "101416",
            "self_link": null,
            "uid": "72e1a2b1-0afe-426a-bde7-ef516e354ec6"
        },
        "spec": {
            "finalizers": [
                "kubernetes"
            ]
        },
        "status": {
            "conditions": null,
            "phase": "Active"
        }
    }
}

Versions Report

salt --versions-report (Provided by running salt --versions-report. Please also mention any differences in master/minion versions.) ``` root@salt-master-55d7dc7477-vwdmz:/# salt-run --versions-report Salt Version: Salt: 3003.3 Dependency Versions: cffi: Not Installed cherrypy: 18.6.1 dateutil: 2.7.3 docker-py: Not Installed gitdb: Not Installed gitpython: Not Installed Jinja2: 2.10 libgit2: 0.27.7 M2Crypto: Not Installed Mako: Not Installed msgpack: 0.5.6 msgpack-pure: Not Installed mysql-python: Not Installed pycparser: 2.19 pycrypto: Not Installed pycryptodome: 3.6.1 pygit2: 0.27.4 Python: 3.7.3 (default, Jan 22 2021, 20:04:44) python-gnupg: Not Installed PyYAML: 3.13 PyZMQ: 17.1.2 smmap: Not Installed timelib: Not Installed Tornado: 4.5.3 ZMQ: 4.3.1 System Versions: dist: debian 10 buster locale: utf-8 machine: x86_64 release: 5.4.109+ system: Linux version: Debian GNU/Linux 10 buster ```

Additional context Add any other context about the problem here.

welcome[bot] commented 2 years ago

Hi there! Welcome to the Salt Community! Thank you for making your first contribution. We have a lengthy process for issues and PRs. Someone from the Core Team will follow up as soon as possible. In the meantime, here’s some information that may help as you continue your Salt journey. Please be sure to review our Code of Conduct. Also, check out some of our community resources including:

There are lots of ways to get involved in our community. Every month, there are around a dozen opportunities to meet with other contributors and the Salt Core team and collaborate in real time. The best way to keep track is by subscribing to the Salt Community Events Calendar. If you have additional questions, email us at saltproject@vmware.com. We’re glad you’ve joined our community and look forward to doing awesome things with you!

waynew commented 2 years ago

@gg17 thanks for the report! that definitely looks like a problem. I'm not sure if we're just not using a custom JSONEncoder for the api like we are within Salt, but for whoever picks this up, that would be a good place to start looking.

Either we should be encoding the datetime as a repr string, i.e. it should be the string "datetime.datetime(...)", or we should be converting the timestamp to the ISO8601 version. Depends on how the API is passing/expecting information back.