Skip to content

Add OpenAPI v2 JSON spec as generated file #4581

@Rycieos

Description

@Rycieos

What would you like to be added:
Similar to the main Kubernetes project, I want an OpenAPI v2 spec in JSON that can be consumed by clients.

The Kubernetes project handles this by spinning up the API server and GETing its OpenAPI v2 spec endpoint:
https://github.com/kubernetes/kubernetes/blob/54241eea4dbdf1ac4bce83748f748a49488a70c1/hack/update-openapi-spec.sh#L115-L118

This outputs this file:
https://github.com/kubernetes/kubernetes/blob/master/api/openapi-spec/swagger.json

This project does get halfway there by generating an OpenAPI spec, but it's in a Go file, not a JSON spec:
https://github.com/kubernetes-sigs/gateway-api/blob/main/pkg/generated/openapi/zz_generated.openapi.go

As part of hack/update-clientset.sh, the zz_generated.openapi.go file should be read and a swagger.json file should be output beside it.

Why this is needed:
The pkg/generated/openapi/zz_generated.openapi.go is useful for clients written in Go, but other languages are left with no API definition. Anyone wanting to use one of the many OpenAPI library generators will need an OpenAPI spec in JSON.

Suggested solution:
I have a "working" hack that can spit out a JSON spec, but it is too hacky an incomplete for me to open a PR with it. I will add it below in case it helps with understanding this request, getting started on a solution, or for anyone in my situation who just needs a JSON spec right now.

First, write a tiny Go program to convert the Go spec to JSON:

// pkg/generated/swagger.go
package main

import (
    "encoding/json"
    "os"

    "k8s.io/kube-openapi/pkg/validation/spec"
    "sigs.k8s.io/gateway-api/pkg/generated/openapi"
)

func main() {
    b, _ := json.Marshal(openapi.GetOpenAPIDefinitions(func(path string) (spec.Ref) {
        return spec.MustCreateRef(path);
    }));
    os.Stdout.Write(b);
}

This outputs the definitions part of a OpenAPI v2 spec, though it isn't exactly matching the spec (it has a Schema key under each definition that needs to be folded out).

Then, convert it to a conformant OpenAPI v2 spec file:

go run pkg/generated/swagger.go \
  | jq '{"swagger":"2.0","info":{"title":"gateway-api","version":"v1.5.0-rc.1"},"paths":{},"definitions":(.|map_values(.Schema))}' \
  | sed 's|k8s.io/apimachinery/pkg/apis/meta/|io.k8s.apimachinery.pkg.apis.meta.|' \
  | sed 's|k8s.io/apimachinery/pkg/runtime/|io.k8s.apimachinery.pkg.runtime.|' \
  | sed -E 's|sigs.k8s.io/gateway-api/apis(x)?/|io.k8s.sigs.gateway-api.apis\1.|' \
  > pkg/generated/openapi/swagger.json

This is spec compliant, matches the definition name format of the Kubernetes spec, and worked on the generator I tried and made model objects.

Besides feeling like a huge hack, the biggest issue is the lack of paths. I do not know how to solve that, as this project doesn't have any knowledge or control over API paths AFAIK, since it uses the CRD API points in Kubernetes. However, they could and probably should be documented somehow (ex: /apis/gateway.networking.k8s.io/v1/namespaces/{namespace}/httproutes).

Metadata

Metadata

Assignees

No one assigned

    Labels

    kind/featureCategorizes issue or PR as related to a new feature.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions