问题描述
我有一个Go结构,我想为其自动生成一个OpenAPI模式.一旦有了该结构的OpenAPI定义,我就想生成该结构的JSONSchema,以便可以验证输入的数据并将其解析为这些结构.
I have a Go struct for which I want to generate an OpenAPI schema automatically. Once I have an OpenAPI definition of that struct I wanna generate JSONSchema of it, so that I can validate the input data that comes and is gonna be parsed into those structs.
结构如下:
// mySpec: io.myapp.MinimalPod
type MinimalPod struct {
Name string `json:"name"`
// k8s: io.k8s.kubernetes.pkg.api.v1.PodSpec
v1.PodSpec
}
以上结构显然是Kubernetes PodSpec
的增强.
Above struct is clearly an augmentation of what Kubernetes PodSpec
is.
现在我使用的方法是为我的结构MinimalPod
生成definition
部分,对于PodSpec
的定义将来自 Kubernetes的上游OpenAPI规范. PodSpec
在上游OpenAPI规范,此定义是从在我的媒体资源中.现在,在解析上述结构的代码中,我有了如果结构字段为string
.
Now the approach that I have used is to generate definition
part for my struct MinimalPod
, the definition for PodSpec
will come from upstream OpenAPI spec of Kubernetes. PodSpec
has a key io.k8s.kubernetes.pkg.api.v1.PodSpec
in the upstream OpenAPI spec, this definition is injected from there in my Properties. Now in my code that parses above struct I have templates of what to do if struct field is string
.
如果该字段的注释是开头的k8s: ...
的下一部分是Kubernetes对象的 OpenAPI定义键.在我们的例子中, OpenAPI定义键是io.k8s.kubernetes.pkg.api.v1.PodSpec
.因此,我从上游OpenAPI定义中检索该字段的定义,并将其嵌入到我的结构的定义中.
If the field has a comment that starts with k8s: ...
the next part is Kubernetes object's OpenAPI definition key. In our case the OpenAPI definition key is io.k8s.kubernetes.pkg.api.v1.PodSpec
. So I retrieve that field's definition from the upstream OpenAPI definition and embed it into the definition of my struct.
一旦我为这个结构生成了一个OpenAPI定义,它将以io.myapp.MinimalPod
键插入Kubernetes OpenAPI模式的定义中.现在,我可以使用工具 openapi2jsonschema
从此工具生成JSONSchema.会生成一个名为MinimalPod.json
的JSONSchema文件.
Once I have generated an OpenAPI definition for this struct which is injected in Kubernetes OpenAPI schema's definition with key being io.myapp.MinimalPod
. Now I can use the tool openapi2jsonschema
to generate JSONSchema out of this one. Which generates a JSONSchema file named MinimalPod.json
.
现在jsonschema
工具和文件MinimalPod.json
可用于验证工具解析器提供的输入,以查看是否所有字段均正确.
Now jsonschema
tool and the file MinimalPod.json
can be used for validating input given to my tool parser to see if all fields were given right.
这是正确的处理方法,还是有工具/库,如果我向其提供Go结构,它会为我提供OpenAPI架构吗?如果它甚至无法自动解析Go结构并确定OpenAPI定义,也无法确定在哪里注入Kubernetes OpenAPI模式,那将是很好的.
Is this the right approach of doing things, or is there a tool/library and if I feed Go structs to it, it gives me OpenAPI schema? It would be fine if it does not identify where to inject Kubernetes OpenAPI schema from even automatic parsing of Go structs and giving OpenAPI definition would be much appreciated.
按照@mehdy的说明进行操作之后,这就是我尝试过的方法:
After following @mehdy 's instructions, this is what I have tried:
我已使用此导入路径github.com/kedgeproject/kedge/vendor/k8s.io/client-go/pkg/api/v1
而不是k8s.io/api/core/v1
来导入PodSpec
定义,并且代码如下所示:
I have used this import path github.com/kedgeproject/kedge/vendor/k8s.io/client-go/pkg/api/v1
to import the PodSpec
definition instead of k8s.io/api/core/v1
and code looks like this:
package foomodel
import "github.com/kedgeproject/kedge/vendor/k8s.io/client-go/pkg/api/v1"
// MinimalPod is a minimal pod.
// +k8s:openapi-gen=true
type MinimalPod struct {
Name string `json:"name"`
v1.PodSpec
}
现在,当我使用标记-i
生成相同的内容时,将其从k8s.io/api/core/v1
更改为github.com/kedgeproject/kedge/vendor/k8s.io/client-go/pkg/api/v1
Now when I generate the same with flag -i
changed from k8s.io/api/core/v1
to github.com/kedgeproject/kedge/vendor/k8s.io/client-go/pkg/api/v1
$ go run example/openapi-gen/main.go -i k8s.io/kube-openapi/example/model,github.com/kedgeproject/kedge/vendor/k8s.io/client-go/pkg/api/v1 -h example/foomodel/header.txt -p k8s.io/kube-openapi/example/foomodel
这是生成的:
$ cat openapi_generated.go
// +build !ignore_autogenerated
/*
======
Some random text
======
*/
// This file was autogenerated by openapi-gen. Do not edit it manually!
package foomodel
import (
spec "github.com/go-openapi/spec"
common "k8s.io/kube-openapi/pkg/common"
)
func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenAPIDefinition {
return map[string]common.OpenAPIDefinition{
"k8s.io/kube-openapi/example/model.Container": {
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
Description: "Container defines a single application container that you want to run within a pod.",
Properties: map[string]spec.Schema{
"health": {
SchemaProps: spec.SchemaProps{
Description: "One common definitions for 'livenessProbe' and 'readinessProbe' this allows to have only one place to define both probes (if they are the same) Periodic probe of container liveness and readiness. Container will be restarted if the probe fails. Cannot be updated. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes",
Ref: ref("k8s.io/client-go/pkg/api/v1.Probe"),
},
},
"Container": {
SchemaProps: spec.SchemaProps{
Ref: ref("k8s.io/client-go/pkg/api/v1.Container"),
},
},
},
Required: []string{"Container"},
},
},
Dependencies: []string{
"k8s.io/client-go/pkg/api/v1.Container", "k8s.io/client-go/pkg/api/v1.Probe"},
},
}
}
我仅获得生成的大部分配置.当我切换回"k8s.io/api/core/v1"
时,会自动生成超过8k行的配置代码.我在这里想念什么?
I get only this much of the configuration generated. While when I switch back to "k8s.io/api/core/v1"
I get config code auto generated which is more than 8k lines. What am I missing here?
当我使用k8s.io/api/core/v1
进行导入时,这里缺少k8s.io/client-go/pkg/api/v1.Container
和k8s.io/client-go/pkg/api/v1.Probe
的定义.
Here definition of k8s.io/client-go/pkg/api/v1.Container
and k8s.io/client-go/pkg/api/v1.Probe
is missing while when I use k8s.io/api/core/v1
as import everything is generated.
注意:要生成上述步骤,请GOPATH
中的git clone https://github.com/kedgeproject/kedge
.
Note: To generate above steps, please git clone https://github.com/kedgeproject/kedge
in GOPATH
.
推荐答案
您可以使用 kube-openapi 包.我将向回购中添加一个样本,但是我已经测试了这个简单的模型:
You can use kube-openapi package for this. I am going to add a sample to the repo but I've tested this simple model:
// Car is a simple car model.
// +k8s:openapi-gen=true
type Car struct {
Color string
Capacity int
// +k8s:openapi-gen=false
HiddenFeature string
}
如果您假设在
go run example/openapi-gen/main.go -h example/model/header.txt -i k8s.io/kube-openapi/example/model -p k8s.io/kube-openapi/example/model
(您还需要添加header.txt文件).您应该看到在example/model文件夹中创建了一个名为openapi_genic.go的新文件.这是一个中间生成的文件,其中包含您的OpenAPI模型:
(you also need to add a header.txt file). You should see a new file created in example/model folder called openapi_generated.go. This is an intermediate generated file that has your OpenAPI model in it:
func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenAPIDefinition {
return map[string]common.OpenAPIDefinition{
"k8s.io/kube-openapi/example/model.Car": {
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
Description: "Car is a simple car model.",
Properties: map[string]spec.Schema{
"Color": {
SchemaProps: spec.SchemaProps{
Type: []string{"string"},
Format: "",
},
},
"Capacity": {
SchemaProps: spec.SchemaProps{
Type: []string{"integer"},
Format: "int32",
},
},
},
Required: []string{"Color", "Capacity"},
},
},
Dependencies: []string{},
},
}
}
从那里,您应该能够调用生成的方法,获取Type的模型并获取其Schema.
From there you should be able to call the generated method, get the model for your Type and get its Schema.
有了一些魔术,稍微更改了命令行,我便能够为您的模型生成模型.这是您应在代码中进行的更改:
With some go get magic and changing the command line a little, I was able to generate the model for your model. Here is what you should change in your code:
package model
import "k8s.io/api/core/v1"
// MinimalPod is a minimal pod.
// +k8s:openapi-gen=true
type MinimalPod struct {
Name string `json:"name"`
v1.PodSpec
}
,然后稍稍更改运行命令以将PodSpec包括在该代中:
and then change the run command a little to include PodSpec in the generation:
go run example/openapi-gen/main.go -h example/model/header.txt -i k8s.io/kube-openapi/example/model,k8s.io/api/core/v1 -p k8s.io/kube-openapi/example/model
这就是我得到的: https://gist.github.com/mbohlool/e399ac2458d12e48cc13081289efc55a
这篇关于将结构转到OpenAPI自动生成JSONSchema的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!