如何反序列化 Kubernetes YAML 文件
How to deserialize Kubernetes YAML file
如何将 Kubernetes YAML 文件反序列化为 Go 结构?我查看了 kubectl
代码,但不知何故,每个 YAML 文件都出现错误:
no kind "Deployment" is registered for version "apps/v1beta1"
这是一个 MWE:
package main
import (
"fmt"
"k8s.io/client-go/pkg/api"
)
var service = `
apiVersion: apps/v1beta1
kind: Deployment
metadata:
name: my-nginx
spec:
replicas: 2
template:
metadata:
labels:
run: my-nginx
spec:
containers:
- name: my-nginx
image: nginx
ports:
- containerPort: 80
`
func main() {
decode := api.Codecs.UniversalDecoder().Decode
//decode := api.Codecs.UniversalDeserializer().Decode
obj, _, err := decode([]byte(service), nil, nil)
if err != nil {
panic(err)
}
fmt.Printf("%#v\n", obj)
}
我使用的是客户端版本2.0.0
。 glide.yaml
看起来像这样:
package: test/Whosebug
import:
- package: k8s.io/client-go
version: ^2.0.0
这些是对 kubectl
的引用:
- https://github.com/kubernetes/kubernetes/blob/43ac38e29e6ecf83e78bc7c5d9f804310b051c95/pkg/kubectl/cmd/apply.go#L637
- https://github.com/kubernetes/kubernetes/blob/43ac38e29e6ecf83e78bc7c5d9f804310b051c95/pkg/kubectl/cmd/util/factory_client_access.go#L205-L213
不幸的是,docs 让我很困惑,所以我不知道如何解决这个问题。
编辑:
其他资源类型也存在此问题:
no kind "Service" is registered for version "v1"
您需要导入 _ "k8s.io/client-go/pkg/apis/extensions/install"
否则架构为空,另请参阅 docs。
完整的工作示例是:
$ go get -u github.com/golang/dep/cmd/dep
$ dep init
$ go run main.go
与以下main.go
:
package main
import (
"fmt"
"k8s.io/client-go/pkg/api"
_ "k8s.io/client-go/pkg/api/install"
_ "k8s.io/client-go/pkg/apis/extensions/install"
)
var deployment = `
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: my-nginx
spec:
replicas: 2
template:
metadata:
labels:
run: my-nginx
spec:
containers:
- name: my-nginx
image: nginx
ports:
- containerPort: 80
`
func main() {
// decode := api.Codecs.UniversalDecoder().Decode
decode := api.Codecs.UniversalDeserializer().Decode
obj, _, err := decode([]byte(deployment), nil, nil)
if err != nil {
fmt.Printf("%#v", err)
}
fmt.Printf("%#v\n", obj)
}
请注意,我还为您导入了 _ "k8s.io/client-go/pkg/api/install"
,以便您可以使用 v1
中的对象,例如 pods 或服务。
编辑:感谢提出初始解决方案的同事 Stefan Schimanski。
我一直在使用 api 机器的k8s.io/apimachinery/pkg/util/yaml
来解码 kubernete 的部署和服务清单。
import (
"fmt"
"bytes"
appsv1 "k8s.io/api/apps/v1"
k8Yaml "k8s.io/apimachinery/pkg/util/yaml"
)
...
d := &appsv1.Deployment{}
dec := k8Yaml.NewYAMLOrJSONDecoder(bytes.NewReader([]byte(deploymentManifest)), 1000)
if err := dec.Decode(&d); err != nil {
return nil, err
}
fmt.Printf("%+v", d)
import (
"fmt"
"gopkg.in/yaml.v2"
"log"
//corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/runtime/serializer/json"
"k8s.io/client-go/kubernetes/scheme"
v1alpha1 "github.com/argoproj/argo-cd/pkg/apis/application/v1alpha1"
)
....
func ParseYaml2(yaml []byte) (v1alpha1.Application, error) {
// Create a YAML serializer. JSON is a subset of YAML, so is supported too.
s := json.NewYAMLSerializer(json.DefaultMetaFactory, scheme.Scheme,
scheme.Scheme)
// Decode the YAML to an object.
var app v1alpha1.Application
_, _, err := s.Decode(yaml, nil, &app)
if err != nil {
panic(err)
}
//fmt.Printf("%#v\n", app)
return app, err
}
---
go.mod
// https://github.com/argoproj/argo-cd/issues/4055
replace github.com/argoproj/argo-cd => github.com/argoproj/argo-cd v1.5.5
var yaml2 = []byte(`
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
...
var app v1alpha1.Application
app,err := ParseYaml2(yaml2)
// Types from https://github.com/argoproj/argo-cd/blob/master/pkg/apis/application/v1alpha1/types.go
fmt.Printf("--- t:\n%s\n\n", app.Spec.Source.Path)
fmt.Printf("--- t:\n%s\n\n", app.Spec.Source.Helm.ValueFiles)
----
如何将 Kubernetes YAML 文件反序列化为 Go 结构?我查看了 kubectl
代码,但不知何故,每个 YAML 文件都出现错误:
no kind "Deployment" is registered for version "apps/v1beta1"
这是一个 MWE:
package main
import (
"fmt"
"k8s.io/client-go/pkg/api"
)
var service = `
apiVersion: apps/v1beta1
kind: Deployment
metadata:
name: my-nginx
spec:
replicas: 2
template:
metadata:
labels:
run: my-nginx
spec:
containers:
- name: my-nginx
image: nginx
ports:
- containerPort: 80
`
func main() {
decode := api.Codecs.UniversalDecoder().Decode
//decode := api.Codecs.UniversalDeserializer().Decode
obj, _, err := decode([]byte(service), nil, nil)
if err != nil {
panic(err)
}
fmt.Printf("%#v\n", obj)
}
我使用的是客户端版本2.0.0
。 glide.yaml
看起来像这样:
package: test/Whosebug
import:
- package: k8s.io/client-go
version: ^2.0.0
这些是对 kubectl
的引用:
- https://github.com/kubernetes/kubernetes/blob/43ac38e29e6ecf83e78bc7c5d9f804310b051c95/pkg/kubectl/cmd/apply.go#L637
- https://github.com/kubernetes/kubernetes/blob/43ac38e29e6ecf83e78bc7c5d9f804310b051c95/pkg/kubectl/cmd/util/factory_client_access.go#L205-L213
不幸的是,docs 让我很困惑,所以我不知道如何解决这个问题。
编辑:
其他资源类型也存在此问题:
no kind "Service" is registered for version "v1"
您需要导入 _ "k8s.io/client-go/pkg/apis/extensions/install"
否则架构为空,另请参阅 docs。
完整的工作示例是:
$ go get -u github.com/golang/dep/cmd/dep
$ dep init
$ go run main.go
与以下main.go
:
package main
import (
"fmt"
"k8s.io/client-go/pkg/api"
_ "k8s.io/client-go/pkg/api/install"
_ "k8s.io/client-go/pkg/apis/extensions/install"
)
var deployment = `
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: my-nginx
spec:
replicas: 2
template:
metadata:
labels:
run: my-nginx
spec:
containers:
- name: my-nginx
image: nginx
ports:
- containerPort: 80
`
func main() {
// decode := api.Codecs.UniversalDecoder().Decode
decode := api.Codecs.UniversalDeserializer().Decode
obj, _, err := decode([]byte(deployment), nil, nil)
if err != nil {
fmt.Printf("%#v", err)
}
fmt.Printf("%#v\n", obj)
}
请注意,我还为您导入了 _ "k8s.io/client-go/pkg/api/install"
,以便您可以使用 v1
中的对象,例如 pods 或服务。
编辑:感谢提出初始解决方案的同事 Stefan Schimanski。
我一直在使用 api 机器的k8s.io/apimachinery/pkg/util/yaml
来解码 kubernete 的部署和服务清单。
import (
"fmt"
"bytes"
appsv1 "k8s.io/api/apps/v1"
k8Yaml "k8s.io/apimachinery/pkg/util/yaml"
)
...
d := &appsv1.Deployment{}
dec := k8Yaml.NewYAMLOrJSONDecoder(bytes.NewReader([]byte(deploymentManifest)), 1000)
if err := dec.Decode(&d); err != nil {
return nil, err
}
fmt.Printf("%+v", d)
import (
"fmt"
"gopkg.in/yaml.v2"
"log"
//corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/runtime/serializer/json"
"k8s.io/client-go/kubernetes/scheme"
v1alpha1 "github.com/argoproj/argo-cd/pkg/apis/application/v1alpha1"
)
....
func ParseYaml2(yaml []byte) (v1alpha1.Application, error) {
// Create a YAML serializer. JSON is a subset of YAML, so is supported too.
s := json.NewYAMLSerializer(json.DefaultMetaFactory, scheme.Scheme,
scheme.Scheme)
// Decode the YAML to an object.
var app v1alpha1.Application
_, _, err := s.Decode(yaml, nil, &app)
if err != nil {
panic(err)
}
//fmt.Printf("%#v\n", app)
return app, err
}
---
go.mod
// https://github.com/argoproj/argo-cd/issues/4055
replace github.com/argoproj/argo-cd => github.com/argoproj/argo-cd v1.5.5
var yaml2 = []byte(`
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
...
var app v1alpha1.Application
app,err := ParseYaml2(yaml2)
// Types from https://github.com/argoproj/argo-cd/blob/master/pkg/apis/application/v1alpha1/types.go
fmt.Printf("--- t:\n%s\n\n", app.Spec.Source.Path)
fmt.Printf("--- t:\n%s\n\n", app.Spec.Source.Helm.ValueFiles)
----