如何反序列化 Kubernetes YAML 文件

huangapple go评论153阅读模式
英文:

How to deserialize Kubernetes YAML file

问题

你可以使用client-go库中的yaml包来将Kubernetes的YAML文件反序列化为Go结构体。以下是一个示例代码:

  1. package main
  2. import (
  3. "fmt"
  4. "k8s.io/apimachinery/pkg/util/yaml"
  5. )
  6. type Deployment struct {
  7. APIVersion string `yaml:"apiVersion"`
  8. Kind string `yaml:"kind"`
  9. Metadata struct {
  10. Name string `yaml:"name"`
  11. } `yaml:"metadata"`
  12. Spec struct {
  13. Replicas int `yaml:"replicas"`
  14. Template struct {
  15. Metadata struct {
  16. Labels struct {
  17. Run string `yaml:"run"`
  18. } `yaml:"labels"`
  19. } `yaml:"metadata"`
  20. Spec struct {
  21. Containers []struct {
  22. Name string `yaml:"name"`
  23. Image string `yaml:"image"`
  24. Ports []struct {
  25. ContainerPort int `yaml:"containerPort"`
  26. } `yaml:"ports"`
  27. } `yaml:"containers"`
  28. } `yaml:"spec"`
  29. } `yaml:"template"`
  30. } `yaml:"spec"`
  31. }
  32. func main() {
  33. service := `
  34. apiVersion: apps/v1beta1
  35. kind: Deployment
  36. metadata:
  37. name: my-nginx
  38. spec:
  39. replicas: 2
  40. template:
  41. metadata:
  42. labels:
  43. run: my-nginx
  44. spec:
  45. containers:
  46. - name: my-nginx
  47. image: nginx
  48. ports:
  49. - containerPort: 80
  50. `
  51. var deployment Deployment
  52. err := yaml.Unmarshal([]byte(service), &deployment)
  53. if err != nil {
  54. panic(err)
  55. }
  56. fmt.Printf("%#v\n", deployment)
  57. }

这个示例代码定义了一个与你提供的YAML文件结构相匹配的Go结构体Deployment。你可以使用yaml.Unmarshal函数将YAML文件反序列化为该结构体。

请注意,你需要在代码中导入k8s.io/apimachinery/pkg/util/yaml包来使用yaml.Unmarshal函数。

希望这可以帮助到你!

英文:

How can I deserialize a Kubernetes YAML file into an Go struct? I took a look into the kubectl code, but somehow I get an error for every YAML file:

  1. no kind "Deployment" is registered for version "apps/v1beta1"

This is an MWE:

  1. package main
  2. import (
  3. "fmt"
  4. "k8s.io/client-go/pkg/api"
  5. )
  6. var service = `
  7. apiVersion: apps/v1beta1
  8. kind: Deployment
  9. metadata:
  10. name: my-nginx
  11. spec:
  12. replicas: 2
  13. template:
  14. metadata:
  15. labels:
  16. run: my-nginx
  17. spec:
  18. containers:
  19. - name: my-nginx
  20. image: nginx
  21. ports:
  22. - containerPort: 80
  23. `
  24. func main() {
  25. decode := api.Codecs.UniversalDecoder().Decode
  26. //decode := api.Codecs.UniversalDeserializer().Decode
  27. obj, _, err := decode([]byte(service), nil, nil)
  28. if err != nil {
  29. panic(err)
  30. }
  31. fmt.Printf("%#v\n", obj)
  32. }

I am using client version 2.0.0. The glide.yaml looks like this:

  1. package: test/stackoverflow
  2. import:
  3. - package: k8s.io/client-go
  4. version: ^2.0.0

These are the references to kubectl:

Unfortunately, the docs are very confusing to me, so I have no idea how to tackle this problem.

Edit:

This problem also exists with other resource types:

  • no kind "Service" is registered for version "v1"

答案1

得分: 5

你需要导入_ "k8s.io/client-go/pkg/apis/extensions/install",否则模式为空,另请参阅文档

完整的工作示例如下:

  1. $ go get -u github.com/golang/dep/cmd/dep
  2. $ dep init
  3. $ go run main.go

使用以下main.go

  1. package main
  2. import (
  3. "fmt"
  4. "k8s.io/client-go/pkg/api"
  5. _ "k8s.io/client-go/pkg/api/install"
  6. _ "k8s.io/client-go/pkg/apis/extensions/install"
  7. )
  8. var deployment = `
  9. apiVersion: extensions/v1beta1
  10. kind: Deployment
  11. metadata:
  12. name: my-nginx
  13. spec:
  14. replicas: 2
  15. template:
  16. metadata:
  17. labels:
  18. run: my-nginx
  19. spec:
  20. containers:
  21. - name: my-nginx
  22. image: nginx
  23. ports:
  24. - containerPort: 80
  25. `
  26. func main() {
  27. // decode := api.Codecs.UniversalDecoder().Decode
  28. decode := api.Codecs.UniversalDeserializer().Decode
  29. obj, _, err := decode([]byte(deployment), nil, nil)
  30. if err != nil {
  31. fmt.Printf("%#v", err)
  32. }
  33. fmt.Printf("%#v\n", obj)
  34. }

请注意,我还为您导入了_ "k8s.io/client-go/pkg/api/install",这样您就可以使用v1中的对象,例如pods或services。

编辑:感谢我的同事Stefan Schimanski提出了最初的解决方案。

英文:

You need to import _ "k8s.io/client-go/pkg/apis/extensions/install" otherwise the schema is empty, see also docs.

The complete working example is:

  1. $ go get -u github.com/golang/dep/cmd/dep
  2. $ dep init
  3. $ go run main.go

With the following main.go:

  1. package main
  2. import (
  3. "fmt"
  4. "k8s.io/client-go/pkg/api"
  5. _ "k8s.io/client-go/pkg/api/install"
  6. _ "k8s.io/client-go/pkg/apis/extensions/install"
  7. )
  8. var deployment = `
  9. apiVersion: extensions/v1beta1
  10. kind: Deployment
  11. metadata:
  12. name: my-nginx
  13. spec:
  14. replicas: 2
  15. template:
  16. metadata:
  17. labels:
  18. run: my-nginx
  19. spec:
  20. containers:
  21. - name: my-nginx
  22. image: nginx
  23. ports:
  24. - containerPort: 80
  25. `
  26. func main() {
  27. // decode := api.Codecs.UniversalDecoder().Decode
  28. decode := api.Codecs.UniversalDeserializer().Decode
  29. obj, _, err := decode([]byte(deployment), nil, nil)
  30. if err != nil {
  31. fmt.Printf("%#v", err)
  32. }
  33. fmt.Printf("%#v\n", obj)
  34. }

Note that I also imported _ "k8s.io/client-go/pkg/api/install" for you so that you can use objects in v1 such as pods or services.

EDIT: Kudos to my colleague Stefan Schimanski who proposed the initial solution.

答案2

得分: 1

我一直在使用api machinery的k8s.io/apimachinery/pkg/util/yaml来解码Kubernetes的部署和服务清单。

  1. import (
  2. "fmt"
  3. "bytes"
  4. appsv1 "k8s.io/api/apps/v1"
  5. k8Yaml "k8s.io/apimachinery/pkg/util/yaml"
  6. )
  7. ...
  8. d := &appsv1.Deployment{}
  9. dec := k8Yaml.NewYAMLOrJSONDecoder(bytes.NewReader([]byte(deploymentManifest)), 1000)
  10. if err := dec.Decode(&d); err != nil {
  11. return nil, err
  12. }
  13. fmt.Printf("%+v", d)
英文:

I've been using api machinery'sk8s.io/apimachinery/pkg/util/yaml to decode kubernete's deployment and service manifests.

  1. import (
  2. "fmt"
  3. "bytes"
  4. appsv1 "k8s.io/api/apps/v1"
  5. k8Yaml "k8s.io/apimachinery/pkg/util/yaml"
  6. )
  7. ...
  8. d := &appsv1.Deployment{}
  9. dec := k8Yaml.NewYAMLOrJSONDecoder(bytes.NewReader([]byte(deploymentManifest)), 1000)
  10. if err := dec.Decode(&d); err != nil {
  11. return nil, err
  12. }
  13. fmt.Printf("%+v", d)

答案3

得分: 0

  1. import (
  2. "fmt"
  3. "gopkg.in/yaml.v2"
  4. "log"
  5. //corev1 "k8s.io/api/core/v1"
  6. "k8s.io/apimachinery/pkg/runtime/serializer/json"
  7. "k8s.io/client-go/kubernetes/scheme"
  8. v1alpha1 "github.com/argoproj/argo-cd/pkg/apis/application/v1alpha1"
  9. )
  10. ....
  11. func ParseYaml2(yaml []byte) (v1alpha1.Application, error) {
  12. // 创建一个YAML序列化器。JSON是YAML的子集,所以也支持。
  13. s := json.NewYAMLSerializer(json.DefaultMetaFactory, scheme.Scheme,
  14. scheme.Scheme)
  15. // 将YAML解码为对象。
  16. var app v1alpha1.Application
  17. _, _, err := s.Decode(yaml, nil, &app)
  18. if err != nil {
  19. panic(err)
  20. }
  21. //fmt.Printf("%#v\n", app)
  22. return app, err
  23. }
  24. ---
  25. go.mod
  26. // https://github.com/argoproj/argo-cd/issues/4055
  27. replace github.com/argoproj/argo-cd => github.com/argoproj/argo-cd v1.5.5
  28. var yaml2 = []byte(`
  29. apiVersion: argoproj.io/v1alpha1
  30. kind: Application
  31. metadata:
  32. ...
  33. var app v1alpha1.Application
  34. app,err := ParseYaml2(yaml2)
  35. // Types from https://github.com/argoproj/argo-cd/blob/master/pkg/apis/application/v1alpha1/types.go
  36. fmt.Printf("--- t:\n%s\n\n", app.Spec.Source.Path)
  37. fmt.Printf("--- t:\n%s\n\n", app.Spec.Source.Helm.ValueFiles)
  38. ----
  39. <details>
  40. <summary>英文:</summary>

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)

  1. // Decode the YAML to an object.
  2. var app v1alpha1.Application
  3. _, _, err := s.Decode(yaml, nil, &amp;app)
  4. if err != nil {
  5. panic(err)
  6. }
  7. //fmt.Printf(&quot;%#v\n&quot;, app)
  8. 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)

  1. </details>

huangapple
  • 本文由 发表于 2017年6月1日 19:41:26
  • 转载请务必保留本文链接:https://go.coder-hub.com/44306554.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定