anancarv / python-artifactory

Typed interactions with the Jfrog Artifactory REST API
MIT License
55 stars 50 forks source link

Remote repository update fails with Object of type 'SecretStr' is not JSON serializable #99

Closed mlaaksonen-csc closed 2 years ago

mlaaksonen-csc commented 2 years ago

Describe the bug Trying to update an existing Maven remote repository configuration fails with "TypeError: Object of type 'SecretStr' is not JSON serializable"

To Reproduce Steps to reproduce the behavior:

from pyartifactory import Artifactory

url = <url to artifactory instance>
auth = (<username>, <password>)
art = Artifactory(url=url, auth=auth)

remote_repo = art.repositories.get('ml-test-remote')
remote_repo.excludesPattern = '**/fake-*'

art.repositories.update_repo(remote_repo)

Executing the above code causes the following error:

Traceback (most recent call last):
  File "./art_test.py", line 13, in <module>
    art.repositories.update_repo(remote_repo)
  File "/home/mlaakson/.local/lib/python3.6/site-packages/pyartifactory/objects.py", line 552, in update_repo
    self._post(f"api/{self._uri}/{repo_name}", json=repo.dict())
  File "/home/mlaakson/.local/lib/python3.6/site-packages/pyartifactory/artifactory_object.py", line 38, in _post
    return self._generic_http_method_request("post", route, **kwargs)
  File "/home/mlaakson/.local/lib/python3.6/site-packages/pyartifactory/artifactory_object.py", line 72, in _generic_http_method_request
    cert=self._cert,
  File "/usr/local/lib/python3.6/site-packages/requests/sessions.py", line 581, in post
    return self.request('POST', url, data=data, json=json, **kwargs)
  File "/usr/local/lib/python3.6/site-packages/requests/sessions.py", line 519, in request
    prep = self.prepare_request(req)
  File "/usr/local/lib/python3.6/site-packages/requests/sessions.py", line 462, in prepare_request
    hooks=merge_hooks(request.hooks, self.hooks),
  File "/usr/local/lib/python3.6/site-packages/requests/models.py", line 316, in prepare
    self.prepare_body(data, files, json)
  File "/usr/local/lib/python3.6/site-packages/requests/models.py", line 466, in prepare_body
    body = complexjson.dumps(json)
  File "/usr/lib64/python3.6/json/__init__.py", line 231, in dumps
    return _default_encoder.encode(obj)
  File "/usr/lib64/python3.6/json/encoder.py", line 199, in encode
    chunks = self.iterencode(o, _one_shot=True)
  File "/usr/lib64/python3.6/json/encoder.py", line 257, in iterencode
    return _iterencode(o, 0)
  File "/usr/lib64/python3.6/json/encoder.py", line 180, in default
    o.__class__.__name__)
TypeError: Object of type 'SecretStr' is not JSON serializable

Expected behavior Remote repository configuration is updated.

Environment:

Additional context I think this is related to https://github.com/anancarv/python-artifactory/issues/74 and https://github.com/anancarv/python-artifactory/pull/75 where a similar problem with create_repo() was fixed.

I tried to hack the same changes to update_repo():

    def update_repo(self, repo: AnyRepository) -> AnyRepositoryResponse:
        """
        Updates a local, virtual or remote repository
        :param repo: Either a local, virtual or remote repository
        :return: LocalRepositoryResponse, VirtualRepositoryResponse or RemoteRepositoryResponse object
        """
        repo_name = repo.key
        self.get_repo(repo_name)
        data = json.dumps(repo, default=custom_encoder)
        self._post(
            f"api/{self._uri}/{repo_name}",
            headers={"Content-Type": "application/json"},
            data=data,
        )
        logger.debug("Repository %s successfully updated", repo_name)
        return self.get_repo(repo_name)

and that got me past the JSON serialization error but the operation still failed, this time with HTTP 400 error response:

Traceback (most recent call last):
  File "./art_test.py", line 13, in <module>
    art.repositories.update_repo(remote_repo)
  File "/home/mlaakson/.local/lib/python3.6/site-packages/pyartifactory/objects.py", line 556, in update_repo
    data=data,
  File "/home/mlaakson/.local/lib/python3.6/site-packages/pyartifactory/artifactory_object.py", line 38, in _post
    return self._generic_http_method_request("post", route, **kwargs)
  File "/home/mlaakson/.local/lib/python3.6/site-packages/pyartifactory/artifactory_object.py", line 75, in _generic_http_method_request
    response.raise_for_status()
  File "/usr/local/lib/python3.6/site-packages/requests/models.py", line 940, in raise_for_status
    raise HTTPError(http_error_msg, response=self)
requests.exceptions.HTTPError: 400 Client Error: Bad Request for url: https://REDACTED/api/repositories/ml-test-remote

and on the Artifactory side the following error was printed in artifactory-service.log:

2021-10-07T12:51:54.149Z [jfrt ] [ERROR] [8c6c5edf8c4c65e3] [o.a.a.r.RestAddonImpl:1306    ] [-nio-8081-exec-10747] - Unable to update repository: null
java.lang.reflect.InvocationTargetException: null
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
...
    at java.base/java.lang.Thread.run(Thread.java:834)
Caused by: java.lang.NullPointerException: null
    at org.artifactory.repo.HttpRepositoryConfigurationImpl.setBowerRegistryUrl(HttpRepositoryConfigurationImpl.java:700)
    ... 87 common frames omitted

After removing the following properties from the remote_repo object defined in the example above, the update_repo() function call succeeded:

bowerRegistryUrl
composerRegistryUrl
pyPIRegistryUrl
vcsType
vcsGitProvider
vcsGitDownloadUrl
anancarv commented 2 years ago

Hi @mlaaksonen-csc , thanks for pointing it out. We'll fix it ASAP