如何使用ReST接口从Kubernetes APIServer获取“kind”响应?

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

How to get "kind" response from Kubernetes APIServer using ReST interface

问题

我正在使用Golang的client-go库与Kubernetes API服务器进行通信,使用的是ReST GET和POST级别的通信。收到的响应既不是格式良好的JSON结构,也不是“kind”API对象。

程序片段如下:

  1. kubeconfig := filepath.Join(
  2. os.Getenv("HOME"), ".kube", "config",
  3. )
  4. config, err := clientcmd.BuildConfigFromFlags("", kubeconfig)
  5. if err != nil {
  6. log.Fatal(err)
  7. }
  8. config.NegotiatedSerializer = scheme.Codecs.WithoutConversion()
  9. groupVersion, _ := schema.ParseGroupVersion("api/v1")
  10. config.GroupVersion = &groupVersion
  11. config.ContentType = "application/json"
  12. config.AcceptContentTypes = "application/json"
  13. exampleRestClient, err := rest.RESTClientFor(config)
  14. if err != nil {
  15. panic(err)
  16. }
  17. var statusCode int
  18. var contentType string
  19. response, err := exampleRestClient.
  20. Get().
  21. Resource("nodes").
  22. Do(context.Background()).
  23. StatusCode(&statusCode).
  24. ContentType(&contentType).
  25. Get()
  26. if err != nil {
  27. panic(err)
  28. }
  29. fmt.Printf("Content-type is %s\n", contentType)
  30. fmt.Printf("Status Code is %d\n", statusCode)
  31. fmt.Printf("Received response %v\n", response)

响应的起始部分如下:

  1. Status Code is 200
  2. Received response &NodeList{ListMeta:{ 17299 <nil>},Items:[]Node{Node{ObjectMeta:{dev-cluster-control-plane 7fe038c9-8be6-41a9-9f3f-5900abb0e34b 16922 0 2023-02-19 16:32:44 +0530 IST <nil> <nil> map[beta.kubernetes.io/arch:amd64 beta.kubernetes.io/os:linux kubernetes.io/arch:amd64 kubernetes.io/hostname:dev-cluster-control-plane kubernetes.io/os:linux node-role.kubernetes.io/control-plane: node.kubernetes.io/exclude-from-external-load-balancers:] map[kubeadm.alpha.kubernetes.io/cri-socket:unix:///run/containerd/containerd.sock node.alpha.kubernetes.io/ttl:0 volumes.kubernetes.io/controller-managed-attach-detach:true] [] [] ...

我期望的输出应该像以下命令返回的结果一样:

  1. $ kubectl get --raw /api/v1/nodes
  2. {"kind":"NodeList","apiVersion":"v1","metadata":{"resourceVersion":"17481"},"items":[{"metadata":{"name":"dev-cluster-control-plane","uid":"7fe038c9-8be6-41a9-9f3f-5900abb0e34b","resourceVersion":"17351","creationTimestamp":"2023-02-19T11:02:44Z","labels":{"beta.kubernetes.io/arch":"amd64","beta.kubernetes.io/os":"linux","kubernetes.io/arch":"amd64","kubernetes.io/hostname":"dev-cluster-control-plane","kubernetes.io/os":"linux","node-role.kubernetes.io/control-plane":"","node.kubernetes.io/exclude-from-external-load-balancers":""},"annotations":{"kubeadm.alpha.kubernetes.io/cri-socket":"unix:///run/containerd/containerd.sock","node.alpha.kubernetes.io/ttl":"0" ...
英文:

I am using the Golang client-go library to communicate with the Kubernetes API Server at the ReST GET, POST level. The response received is not a well-formed JSON structure and also not a "kind" API Object.

The program snippet is:

  1. kubeconfig := filepath.Join(
  2. os.Getenv(&quot;HOME&quot;), &quot;.kube&quot;, &quot;config&quot;,
  3. )
  4. config, err := clientcmd.BuildConfigFromFlags(&quot;&quot;, kubeconfig)
  5. if err != nil {
  6. log.Fatal(err)
  7. }
  8. config.NegotiatedSerializer = scheme.Codecs.WithoutConversion()
  9. groupVersion, _ := schema.ParseGroupVersion(&quot;api/v1&quot;)
  10. config.GroupVersion = &amp;groupVersion
  11. config.ContentType = &quot;application/json&quot;
  12. config.AcceptContentTypes = &quot;application/json&quot;
  13. exampleRestClient, err := rest.RESTClientFor(config)
  14. if err != nil {
  15. panic(err)
  16. }
  17. var statusCode int
  18. var contentType string
  19. response, err := exampleRestClient.
  20. Get().
  21. Resource(&quot;nodes&quot;).
  22. Do(context.Background()).
  23. StatusCode(&amp;statusCode).
  24. ContentType(&amp;contentType).
  25. Get()
  26. if err != nil {
  27. panic(err)
  28. }
  29. fmt.Printf(&quot;Content-type is %s\n&quot;, contentType)
  30. fmt.Printf(&quot;Status Code is %d\n&quot;, statusCode)
  31. fmt.Printf(&quot;Received response %v\n&quot;, response)

The response starts as:

  1. Status Code is 200
  2. Received response &amp;NodeList{ListMeta:{ 17299 &lt;nil&gt;},Items:[]Node{Node{ObjectMeta:{dev-cluster-control-plane 7fe038c9-8be6-41a9-9f3f-5900abb0e34b 16922 0 2023-02-19 16:32:44 +0530 IST &lt;nil&gt; &lt;nil&gt; map[beta.kubernetes.io/arch:amd64 beta.kubernetes.io/os:linux kubernetes.io/arch:amd64 kubernetes.io/hostname:dev-cluster-control-plane kubernetes.io/os:linux node-role.kubernetes.io/control-plane: node.kubernetes.io/exclude-from-external-load-balancers:] map[kubeadm.alpha.kubernetes.io/cri-socket:unix:///run/containerd/containerd.sock node.alpha.kubernetes.io/ttl:0 volumes.kubernetes.io/controller-managed-attach-detach:true] [] [] ...

I expected the output to be like what the following command returns:

  1. $ kubectl get --raw /api/v1/nodes
  2. {&quot;kind&quot;:&quot;NodeList&quot;,&quot;apiVersion&quot;:&quot;v1&quot;,&quot;metadata&quot;:{&quot;resourceVersion&quot;:&quot;17481&quot;},&quot;items&quot;:[{&quot;metadata&quot;:{&quot;name&quot;:&quot;dev-cluster-control-plane&quot;,&quot;uid&quot;:&quot;7fe038c9-8be6-41a9-9f3f-5900abb0e34b&quot;,&quot;resourceVersion&quot;:&quot;17351&quot;,&quot;creationTimestamp&quot;:&quot;2023-02-19T11:02:44Z&quot;,&quot;labels&quot;:{&quot;beta.kubernetes.io/arch&quot;:&quot;amd64&quot;,&quot;beta.kubernetes.io/os&quot;:&quot;linux&quot;,&quot;kubernetes.io/arch&quot;:&quot;amd64&quot;,&quot;kubernetes.io/hostname&quot;:&quot;dev-cluster-control-plane&quot;,&quot;kubernetes.io/os&quot;:&quot;linux&quot;,&quot;node-role.kubernetes.io/control-plane&quot;:&quot;&quot;,&quot;node.kubernetes.io/exclude-from-external-load-balancers&quot;:&quot;&quot;},&quot;annotations&quot;:{&quot;kubeadm.alpha.kubernetes.io/cri-socket&quot;:&quot;unix:///run/containerd/containerd.sock&quot;,&quot;node.alpha.kubernetes.io/ttl&quot;:&quot;0&quot; ...

答案1

得分: 0

收到。以下是翻译的内容:

收到的响应不是一个格式良好的 JSON 结构

我认为你对 client-go 模块的操作方式有些困惑。

来自 REST API 的响应绝对是一个格式良好的 JSON 响应,但是它会被解组成一个 Go 数据结构(例如 这个)。

如果你想要访问返回的节点,可以使用标准的 Go 语法与结果进行交互:

  1. response, err := exampleRestClient.
  2. Get().
  3. Resource("nodes").
  4. Do(context.Background()).
  5. StatusCode(&statusCode).
  6. ContentType(&contentType).
  7. Get()
  8. if err != nil {
  9. panic(err)
  10. }
  11. nodes := response.(*v1.NodeList)
  12. for _, node := range nodes.Items {
  13. fmt.Printf("name: %s\n", node.ObjectMeta.GetName())
  14. fmt.Printf("addresses:\n")
  15. for _, addr := range node.Status.Addresses {
  16. fmt.Printf(" %s: %s\n", addr.Type, addr.Address)
  17. }
  18. }

我期望的输出结果应该像下面的命令返回的那样:

为什么?client-go 绑定返回的数据对你的 Go 代码非常有用。如果你想要生成 JSON 输出,你需要显式地将资源编组为 JSON 格式:

  1. response, err := exampleRestClient.
  2. Get().
  3. Resource("nodes").
  4. Do(context.Background()).
  5. StatusCode(&statusCode).
  6. ContentType(&contentType).
  7. Get()
  8. if err != nil {
  9. panic(err)
  10. }
  11. out, err := json.Marshal(response)
  12. fmt.Print(string(out))
英文:

> The response received is not a well-formed JSON structure

I think you are confused about how the client-go module operates.

The response from the REST API absolutely was a well-formed JSON response, but this gets unmarshaled into a Go data structure (such as this).

If you want to access the returned nodes, you interact with the result using standard Go syntax:

  1. response, err := exampleRestClient.
  2. Get().
  3. Resource(&quot;nodes&quot;).
  4. Do(context.Background()).
  5. StatusCode(&amp;statusCode).
  6. ContentType(&amp;contentType).
  7. Get()
  8. if err != nil {
  9. panic(err)
  10. }
  11. nodes := response.(*v1.NodeList)
  12. for _, node := range nodes.Items {
  13. fmt.Printf(&quot;name: %s\n&quot;, node.ObjectMeta.GetName())
  14. fmt.Printf(&quot;addresses:\n&quot;)
  15. for _, addr := range node.Status.Addresses {
  16. fmt.Printf(&quot; %s: %s\n&quot;, addr.Type, addr.Address)
  17. }
  18. }

> I expected the output to be like what the following command returns:

Why? The client-go bindings return data that's going to be useful to your Go code. If you want to produce JSON output, you need to explicitly marshal the resources to JSON format:

  1. response, err := exampleRestClient.
  2. Get().
  3. Resource(&quot;nodes&quot;).
  4. Do(context.Background()).
  5. StatusCode(&amp;statusCode).
  6. ContentType(&amp;contentType).
  7. Get()
  8. if err != nil {
  9. panic(err)
  10. }
  11. out, err := json.Marshal(response)
  12. fmt.Print(string(out))

huangapple
  • 本文由 发表于 2023年2月21日 01:57:59
  • 转载请务必保留本文链接:https://go.coder-hub.com/75512684.html
匿名

发表评论

匿名网友

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

确定