spectral icon indicating copy to clipboard operation
spectral copied to clipboard

unused-components-schema for discriminator mappings

Open m-mohr opened this issue 5 years ago • 3 comments

Describe the bug

I'm getting the following warning from Spectral:

warning oas3-unused-components-schema Potentially unused components schema has been detected.

This only happens for Schemas that are only referenced in the discriminator mappings, for example:

      discriminator:
        propertyName: type
        mapping:
          spatial: '#/components/schemas/dimension_spatial'
          temporal: '#/components/schemas/dimension_temporal'
          bands: '#/components/schemas/dimension_bands'
          other: '#/components/schemas/dimension_other'

To Reproduce

Here's the OpenAPI file I'm working on: https://github.com/Open-EO/openeo-api/blob/76ec4a59/openapi.yaml I'm running: spectral lint openapi.yaml Ruleset is spectral:oas

Expected behavior No warning.

Environment (remove any that are not applicable):

  • Library version: 5.4.0
  • OS: Windows 10

m-mohr avatar Jul 01 '20 11:07 m-mohr

@m-mohr Interesting!

Few thoughts (and fair warning: I'm far from being a discriminator guru :wink:):

  • https://github.com/OAI/OpenAPI-Specification/blob/b748a884fa4571ffb6dd6ed9a4d20e38e41a878c/versions/3.0.3.md#discriminator-object doco seems to describe usage of the discriminator as a way to pick one specific schema among many (described through oneOf/anyOf). Listing all the possible schemas would make the warning disappear. Just for my understanding, what led you to choose to not list them?
  • There's an open discussion to potentially deprecate discriminator (cf. https://github.com/OAI/OpenAPI-Specification/issues/2143) in favor of other approaches

There might be ways to special case discriminator/mapping in oas3-unused-components-schema but it might not be that trivial as I doubt those mapping entries will already exist as identified references.

@m-mohr I'm curious, does the valid-examples-* rule properly properly fail when the provided example expose a valid property/value pair that match the discriminator mappings but doesn't respect the rest of the subtype schema?

@philsturgeon Would you know how common it is to only expose a discriminator without listing all the possible schemas? And from another perspective, from a tooling standpoint, does schema validation even do anything meaningful in that context?

nulltoken avatar Jul 07 '20 09:07 nulltoken

Few thoughts (and fair warning: I'm far from being a discriminator guru 😉):

Me neither, just learned to use it some weeks ago and struggled a lot.

  • https://github.com/OAI/OpenAPI-Specification/blob/b748a884fa4571ffb6dd6ed9a4d20e38e41a878c/versions/3.0.3.md#discriminator-object doco seems to describe usage of the discriminator as a way to pick one specific schema among many (described through oneOf/anyOf). Listing all the possible schemas would make the warning disappear. Just for my understanding, what led you to choose to not list them?

openapi-generator throws a warning if I list them also in oneOf/anyOf. I think they argue that you better define it as shown below (only discriminator) and then define the other schemas and use allOf to reference the parent schema (see below). At least that is how I made code generation work and it somewhat makes sense. Otherwise it feels it needs to generate a single class with all the properties that could be available in the oneOfs, but that's not the case.

Yes, that would be appreciated a lot as code generation currently is very messy. Unfortunately, a discussion doesn't help now. OpenAPI 3.1 is around the corner and the issue hasn't been tackled there so until we have a better solution it will take years for the spec + tooling support.

There might be ways to special case discriminator/mapping in oas3-unused-components-schema but it might not be that trivial as I doubt those mapping entries will already exist as identified references.

Could be, but I don't see a violation of the openAPI spec so would expect that it works as it's referenced and not unsued.

@m-mohr I'm curious, does the valid-examples-* rule properly properly fail when the provided example expose a valid property/value pair that match the discriminator mappings but doesn't respect the rest of the subtype schema?

I need to check that, but it's likely to fail as we still use it as shown below. I'd need to remove the "sub-types" that inherit with allOf to check that, but not sure how useful it is as we we actually have these sub-types and without them it's - as you said - probably not very useful.

@philsturgeon Would you know how common it is to only expose a discriminator without listing all the possible schemas? And from another perspective, from a tooling standpoint, does schema validation even do anything meaningful in that context?

As I said above, we use it as follows. It was the only way to get reasonable results from openapi-generator.

components:
  schemas:
    udf_runtime:
      type: object
      required:
        - type
        - default
      properties:
        title:
          $ref: '#/components/schemas/object_title'
        description:
          $ref: '#/components/schemas/description'
        type:
          type: string
          description: |-
            The type of the UDF runtime.

            Pre-defined types are:
            * `language` for Programming Languages and
            * `docker` for Docker Containers.
            
            The types can potentially be extended by back-ends.
        default:
          type: string
        links:
          type: array
          description: |-
            Links related to this runtime, e.g. external documentation.

            It is highly RECOMMENDED to provide at least links with
            the following `rel` (relation) types:

            1. `about`: A resource that further explains the runtime,
            e.g. a user guide or the documentation.

            For additional relation types see also the lists of
            [common relation types in openEO](#section/API-Principles/Web-Linking).
          items:
            $ref: '#/components/schemas/link'
      discriminator:
        propertyName: type
        mapping:
          language: '#/components/schemas/udf_programming_language'
          docker: '#/components/schemas/udf_docker'
    udf_programming_language:
      allOf:
        - $ref: '#/components/schemas/udf_runtime'
        - title: Programming language
          required:
            - versions
          properties:
            default:
              type: string
              description: The default version. MUST be one of the keys in the `versions` object.
            versions:
              title: Programming language versions
              description: Versions available for the programming language.
              type: object
              additionalProperties:
                x-additionalPropertiesName: Programming Language Version
                title: Programming language version
                type: object
                required:
                  - libraries
                properties:
                  libraries:
                    description: >-
                      Map of installed libraries, modules, packages
                      or extensions for the programming language.
                      The names of them are used as the property keys.
                    additionalProperties:
                      x-additionalPropertiesName: Library Name
                      title: Programming language library
                      type: object
                      required:
                        - version
                      properties:
                        version:
                          type: string
                          description: Version number of the library.
                        deprecated:
                          type: boolean
                          default: false
                          description: |-
                            Specifies that the library is deprecated with the potential to be
                            removed in any of the next versions. It should be transitioned out
                            of usage as soon as possible and users should refrain from using it
                            in new implementations.

                            A link with relation type `latest-version` SHOULD be added to the
                            `links` and MUST refer to the library or library version that can be
                            used instead.
                        links:
                          type: array
                          description: |-
                            Additional links related to this library,
                            e.g. external documentation for this library.

                            It is highly RECOMMENDED to provide links with
                            the following `rel` (relation) types:

                            1. `about`: A resource that further explains the library,
                            e.g. a user guide or the documentation.

                            2. `latest-version`: If a library has been marked as deprecated,
                            a link should point to either a new library replacing the deprecated
                            library or a latest version of the library available at the back-end.

                            For additional relation types see also the lists of
                            [common relation types in openEO](#section/API-Principles/Web-Linking).
                          items:
                            $ref: '#/components/schemas/link'
    udf_docker:
      allOf:
        - $ref: '#/components/schemas/udf_runtime'
        - title: Docker container
          required:
            - docker
            - tags
          properties:
            docker:
              type: string
              description: >-
                Identifier of a Docker image on Docker Hub or a
                private repository, i.e. the docker image name.
            default:
              type: string
              description: The default tag. MUST be one of the values in the `tags` array.
            tags:
              type: array
              description: The docker tags that are supported.
              minItems: 1
              items:
                type: string

m-mohr avatar Jul 07 '20 10:07 m-mohr

Here's another example of discriminator being used as such: https://github.com/OAI/OpenAPI-Specification/issues/2116

m-mohr avatar Jul 07 '20 11:07 m-mohr