Argo: Discrepancy Between Generated Python OpenAPI Client And Argo Server

Created on 10 Nov 2020  路  6Comments  路  Source: argoproj/argo

Summary

I can make a request using the HTTP API that fails when using the Python client generated from the swagger.json.

Running Argo server locally, I navigate to this URL in my browser: http://localhost:2746/api/v1/workflows/argo?fields=items.metadata.name
I have a few example workflows, so the response looks like this:

{
  "items": [
    {
      "metadata": {
        "name": "example-mlcwl"
      }
    },
    {
      "metadata": {
        "name": "example-7slfm"
      }
    },
    {
      "metadata": {
        "name": "example-s86zz"
      }
    }
  ]
}

Generating the Python OpenAPI client:

docker run --rm \
      -v ${PWD}/argo-openapi-client:/local openapitools/openapi-generator-cli generate \
      -i /local/swagger.json \
      -g python \
      -o /local \
      --additional-properties=packageName=argo,projectName=argo

And using it to make the same request:

>>> import argo
>>> configuration = argo.Configuration(host='http://localhost:2746')
>>> with argo.ApiClient(configuration=configuration) as api_client:
...   api_instance = argo.WorkflowServiceApi(api_client)
...

>>> api_instance.list_workflows('argo', fields='items.metadata.name')
Traceback (most recent call last):
<snip>
ValueError: Invalid value for `spec`, must not be `None`

>>> api_instance.list_workflows('argo', fields='items.metadata.name,items.spec.affinity')
Traceback (most recent call last):
<snip>
ValueError: Invalid value for `metadata`, must not be `None`

>>> api_instance.list_workflows('argo', fields='items.metadata.name,items.spec.affinity,metadata')
{'api_version': None,
 'items': [{'api_version': None,
            'kind': None,
            'metadata': {'annotations': None,
...

Looking at the swagger.json, I can see that those fields are required, but I'm confused about how the server fulfills the same request in the browser if the request doesn't meet the requirements of the spec, and whether the generated client should match that behavior?

$ argo version
argo: latest+a00a8f1.dirty
  BuildDate: 2020-10-08T01:44:49Z
  GitCommit: a00a8f141c221f50e397aea8f86a54171441e395
  GitTreeState: dirty
  GitTag: v2.11.3
  GoVersion: go1.15.2
  Compiler: gc
  Platform: darwin/amd64


Message from the maintainers:

Impacted by this bug? Give it a 馃憤. We prioritise the issues with the most 馃憤.

bug

All 6 comments

Can you ask in the #argo-sdks channel?

While continuing to look at this, I tried the following (which did not work):

config = argo.Configuration(host="http://localhost:2746")
config.client_side_validation = False
with argo.ApiClient(configuration=config) as api_client:
    api_instance = argo.WorkflowServiceApi(api_client)
    results = api_instance.list_workflows( "argo", fields="items.metadata.name")

I noticed that this client_side_validation variable exists on the Configuration object and is always set to True. That same variable is referenced in a few places in WorkflowServiceApi like this: self.api_client.client_side_validation. It also has a corresponding idea in the generated model files, e.g. io_argoproj_workflow_v1alpha1_workflow.py:

class IoArgoprojWorkflowV1alpha1Workflow(object):
    def __init__(self, api_version=None, kind=None, metadata=None, spec=None, status=None, local_vars_configuration=None):  # noqa: E501
        """IoArgoprojWorkflowV1alpha1Workflow - a model defined in OpenAPI"""  # noqa: E501
        if local_vars_configuration is None:
            local_vars_configuration = Configuration()
        self.local_vars_configuration = local_vars_configuration

    @spec.setter
    def spec(self, spec):
        """Sets the spec of this IoArgoprojWorkflowV1alpha1Workflow.
        :param spec: The spec of this IoArgoprojWorkflowV1alpha1Workflow.  # noqa: E501
        :type spec: IoArgoprojWorkflowV1alpha1WorkflowSpec
        """
        if self.local_vars_configuration.client_side_validation and spec is None:  # noqa: E501
            raise ValueError("Invalid value for `spec`, must not be `None`")  # noqa: E501

        self._spec = spec

If the client_side_validation setting in the WorkflowServiceApi could propagate to where the models are instantiated after the request returns, then this wouldn't be a problem. As it is, the model instantiation behavior is inconsistent with the Configuration used in the request and raises the ValueError no matter what because local_vars_configuration is never populated.

@kennytrytek-wf try out https://pypi.org/project/argo-workflows ?

OK this is the argo server api correct (not submitting the workflow), this is on my todo list for above project (add an issue there? maybe we can work together on this)

OK this is the argo server api correct

Yes, this is the argo server API as it compares to the generated OpenAPI client. I know the argo-client-python project exists, but I want to use the client as generated from the OpenAPI spec to ensure it is always compatible with the version of Argo server we have deployed.

My question is more fundamental about how the OpenAPI spec and Argo server relate to each other; _should_ the server return responses that aren't supported by the spec (i.e. the example above where the response objects are missing required attributes), and _should_ the OpenAPI client relax its definitions or add support for those queries?

Was this page helpful?
0 / 5 - 0 ratings

Related issues

0xdevalias picture 0xdevalias  路  3Comments

ddseapy picture ddseapy  路  3Comments

logicfox picture logicfox  路  4Comments

CermakM picture CermakM  路  3Comments

tommyJimmy87 picture tommyJimmy87  路  3Comments