Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Bug]: OpenAPI - Discriminator properties are not consistently marked as required #4444

Open
4 tasks done
johngallardo opened this issue Sep 13, 2024 · 0 comments
Open
4 tasks done
Labels
bug Something isn't working emitter:openapi3 Issues for @typespec/openapi3 emitter triaged:core

Comments

@johngallardo
Copy link
Member

Describe the bug

AutoRest requires that discriminator properties are marked as required in their schemas:
DiscriminatorNotRequired | Semantic violation: Discriminator must be a required property.

However, schemas emitted by OpenAPI3 emitter do not consistently appear in the set of required properties for both @createsResource and @updatesResource decorated operations.

Reproduction

import "@typespec/http";
import "@typespec/rest";
import "@typespec/openapi";
import "@typespec/openapi3";

using TypeSpec.Http;
using TypeSpec.OpenAPI;
using TypeSpec.Rest;

@service({
    title: "A Zoo Service"
})

namespace Zoo;

@discriminator("kind")
model Animal {
    @visibility("read", "create") id: string;
    name?: string;
}

model Cat extends Animal {
    kind: "cat";
    whiskerCount?: integer;
}

model Penguin extends Animal {
    kind: "penguin";
}

@route("/zoo")
interface Zoo {
    @listsResource(Animal)
    read(): Animal[];

    @operationId("getAnimalById")
    readById(@path id: string): Animal;

    @createsResource(Animal)
    add(@body animal: Animal): Animal;

    @updatesResource(Animal)
    patch(@path id: string, @body animal: Animal): Animal;
}

Produces:

openapi: 3.0.0
info:
  title: A Zoo Service
  version: 0.0.0
tags: []
paths:
  /zoo:
    get:
      operationId: Zoo_read
      parameters: []
      responses:
        '200':
          description: The request has succeeded.
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/Animal'
    post:
      operationId: Zoo_add
      parameters: []
      responses:
        '200':
          description: The request has succeeded.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Animal'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/Animal'
  /zoo/{id}:
    get:
      operationId: getAnimalById
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
      responses:
        '200':
          description: The request has succeeded.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Animal'
    patch:
      operationId: Zoo_patch
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
      responses:
        '200':
          description: The request has succeeded.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Animal'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/AnimalUpdate'
components:
  schemas:
    Animal:
      type: object
      required:
        - id
      properties:
        id:
          type: string
        name:
          type: string
        kind:
          type: string
          description: Discriminator property for Animal.
      discriminator:
        propertyName: kind
        mapping:
          cat: '#/components/schemas/Cat'
          penguin: '#/components/schemas/Penguin'
    AnimalUpdate:
      type: object
      properties:
        name:
          type: string
        kind:
          type: string
          description: Discriminator property for Animal.
      discriminator:
        propertyName: kind
        mapping:
          cat: '#/components/schemas/CatUpdate'
          penguin: '#/components/schemas/PenguinUpdate'
    Cat:
      type: object
      required:
        - kind
      properties:
        kind:
          type: string
          enum:
            - cat
        whiskerCount:
          type: integer
      allOf:
        - $ref: '#/components/schemas/Animal'
    CatUpdate:
      type: object
      properties:
        kind:
          type: string
          enum:
            - cat
        whiskerCount:
          type: integer
      allOf:
        - $ref: '#/components/schemas/AnimalUpdate'
    Penguin:
      type: object
      required:
        - kind
      properties:
        kind:
          type: string
          enum:
            - penguin
      allOf:
        - $ref: '#/components/schemas/Animal'
    PenguinUpdate:
      type: object
      properties:
        kind:
          type: string
          enum:
            - penguin
      allOf:
        - $ref: '#/components/schemas/AnimalUpdate'

When attempting to generate autorest:

PS C:\src\typespectest> autorest --input-file='.\tsp-output\@typespec\openapi3\openapi.yaml' --typescript
AutoRest code generation utility [cli version: 3.7.1; node: v18.18.0]
(C) 2018 Microsoft Corporation.
https://aka.ms/autorest
info    | AutoRest core version selected from configuration: ^3.7.0.
info    |    Loading AutoRest core      'C:\Users\jgalla\.autorest\@[email protected]\nodemodules\@autorest\core\dist' (3.10.2)
info    |    Loading AutoRest extension '@autorest/typescript' (latest->6.0.27)
info    |    Loading AutoRest extension '@autorest/modelerfour' (4.26.2->4.26.2)
error   | DiscriminatorNotRequired | Semantic violation: Discriminator must be a required property. (components > schemas > Animal)
  discriminator: {
  propertyName: 'kind',
  mapping: {
    cat: 'file:///C:/src/typespectest/tsp-output/@typespec/openapi3/openapi.yaml#/components/schemas/Cat',
    penguin: 'file:///C:/src/typespectest/tsp-output/@typespec/openapi3/openapi.yaml#/components/schemas/Penguin'
  }
}
    - file:///C:/src/typespectest/tsp-output/@typespec/openapi3/openapi.yaml:75:5
fatal   | Process() cancelled due to failure
error   | DiscriminatorNotRequired | Semantic violation: Discriminator must be a required property. (components > schemas > AnimalUpdate)
  discriminator: {
  propertyName: 'kind',
  mapping: {
    cat: 'file:///C:/src/typespectest/tsp-output/@typespec/openapi3/openapi.yaml#/components/schemas/CatUpdate',
    penguin: 'file:///C:/src/typespectest/tsp-output/@typespec/openapi3/openapi.yaml#/components/schemas/PenguinUpdate'
  }
}
    - file:///C:/src/typespectest/tsp-output/@typespec/openapi3/openapi.yaml:92:5
error   |   Error: Semantic validation failed. There was some errors
error   | Autorest completed with an error. If you think the error message is unclear, or is a bug, please declare an issues at https://github.com/Azure/autorest/issues with the error message you are seeing.

One can attempt to work around by modifying the Animal model as follows:

@discriminator("kind")
model Animal {
    @visibility("read", "create") id: string;
    kind: string;
    name?: string;
}

This fixes the schema that is used for Create and Read, but the schema for update loses kind as a required property:

    AnimalUpdate:
      type: object
      properties:
        kind:
          type: string
        name:
          type: string
      discriminator:
        propertyName: kind
        mapping:
          cat: '#/components/schemas/CatUpdate'
          penguin: '#/components/schemas/PenguinUpdate'

Checklist

@johngallardo johngallardo added the bug Something isn't working label Sep 13, 2024
@markcowl markcowl added this to the [2024] November milestone Sep 16, 2024
@markcowl markcowl added triaged:core emitter:openapi3 Issues for @typespec/openapi3 emitter labels Sep 16, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working emitter:openapi3 Issues for @typespec/openapi3 emitter triaged:core
Projects
None yet
Development

No branches or pull requests

2 participants