swagger-api / swagger-api/swagger-codegen

Inheritance objects are not valid when generated to `go` model

Open
#11,292 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Mustache
Stars
17.8k
Forks
6k
PR merge metrics
No merged PRs in 30d

Description

Description
Swagger-codegen version

3.0.29

Swagger declaration file content or url

simplified file content (stripped from unnecessary stuff)

openapi: 3.0.1

info:
  title: TestKube API
  description: "TestKube provides a Kubernetes-native framework for test definition, execution and results"
  contact:
    email: testkube@kubeshop.io
  license:
    name: MIT
    url: https://opensource.org/licenses/MIT
  version: 1.0.0

externalDocs:
  description: "Find out more about testkube"
  url: http://testkube.io

tags:
  - name: api
    description: "TestKube API operations"
  - name: scripts
    description: "Script operations"
  - name: executions
    description: "Execution operations"
  - name: tests
    description: "Scripts orchestration operations"

paths:

  /tests:


components:
  schemas:

    Test:
      type: object
      properties:
        before:
          $ref: "#/components/schemas/TestStep"
          description: Run this step before whole suite
        steps:
          type: array
          items:
            $ref: "#/components/schemas/TestStep"
          description: Steps to run
        after:
          $ref: "#/components/schemas/TestStep"
          description: Run this step after whole suite
        repeats:
          type: integer
          default: 1

    TestStep: 
      type: object 
      required:
        - name
      properties:
        name: 
          type: string
          description: step name (in case of script it'll be script name)

    TestStepExecuteScript: 
      allOf:     # Combines the BasicErrorModel and the inline model
        - $ref: '#/components/schemas/TestStep'
        - type: object
          required:
            - namepace 
            - name
          properties:
            namespace:
              type: string
            name:
              type: string
            stopOnFailure:
              type: boolean
              default: true

    TestStepDelay: 
      allOf:     # Combines the TestStep and the inline model
        - $ref: '#/components/schemas/TestStep'
        - type: object
          required:
            - duration 
          properties:
            delay:
              type: integer
              default: 0 
              description: delay in milliseconds
        

command to generate those files:

swagger-codegen generate -i api/v1/testkube.yaml -l go -o tmp/api/testkube

Models generated:

type Test struct {
	Before *TestStep `json:"before,omitempty"`
	// Steps to run
	Steps   []TestStep `json:"steps,omitempty"`
	After   *TestStep  `json:"after,omitempty"`
	Repeats int32      `json:"repeats,omitempty"`
}

type TestStep struct {
	// step name (in case of script it'll be script name)
	Name string `json:"name"`
}

type TestStepExecuteScript struct {
	Name          string `json:"name"`
	Namespace     string `json:"namespace,omitempty"`
	StopOnFailure bool   `json:"stopOnFailure,omitempty"`
}

type TestStepDelay struct {
	// step name (in case of script it'll be script name)
	Name string `json:"name"`
	// delay in milliseconds
	Delay int32 `json:"delay,omitempty"`
}

It's not possible to set TestStepDelay or TestStepExecuteScript as TestStep (as they are not related in any way in code)
Maybe top level should be generated as some kind of interface?

Command line used for generation
	swagger-codegen generate -i api/v1/testkube.yaml -l go -o tmp/api/testkube
	mv tmp/api/testkube/model_*.go pkg/api/v1/testkube
	rm -rf tmp
	find ./pkg/api/v1/testkube -type f -exec sed -i '' -e "s/package swagger/package testkube/g" {} \;
	go fmt pkg/api/v1/testkube/*.go
Suggest a fix/enhancement

Generate Interface as base object - the disadvantage would be that it couldn't be used.
Question is that if fields from basic object should be generated as methods ? and should they be implemented in extended objects?

some very simplified idea:

package main

import "fmt"

type I interface{
	Name() string
}

type A struct {
	name string
}

func (a A) Name() string {
	return a.name
} 

func main() {
	a(A{})
}

func a(a I) {
	fmt.Printf("%+v", a)
}

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Reproduce the issue with the provided OpenAPI schemas and swagger-codegen generate -l go command, then inspect the generated TestStep, TestStepExecuteScript, and TestStepDelay models. Read the Go model-generation path and determine how inheritance should be represented; done means generated types preserve the declared relationship and can be used wherever the base type is expected, with generation tests covering the example.

Written by the indexing model from the issue text.

Assessment

Tech stack
go, openapi
Domain
backend-api-design, tooling
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.