英文:
How to get "kind" response from Kubernetes APIServer using ReST interface
问题
我正在使用Golang的client-go库与Kubernetes API服务器进行通信,使用的是ReST GET和POST级别的通信。收到的响应既不是格式良好的JSON结构,也不是“kind”API对象。
程序片段如下:
kubeconfig := filepath.Join(
os.Getenv("HOME"), ".kube", "config",
)
config, err := clientcmd.BuildConfigFromFlags("", kubeconfig)
if err != nil {
log.Fatal(err)
}
config.NegotiatedSerializer = scheme.Codecs.WithoutConversion()
groupVersion, _ := schema.ParseGroupVersion("api/v1")
config.GroupVersion = &groupVersion
config.ContentType = "application/json"
config.AcceptContentTypes = "application/json"
exampleRestClient, err := rest.RESTClientFor(config)
if err != nil {
panic(err)
}
var statusCode int
var contentType string
response, err := exampleRestClient.
Get().
Resource("nodes").
Do(context.Background()).
StatusCode(&statusCode).
ContentType(&contentType).
Get()
if err != nil {
panic(err)
}
fmt.Printf("Content-type is %s\n", contentType)
fmt.Printf("Status Code is %d\n", statusCode)
fmt.Printf("Received response %v\n", response)
响应的起始部分如下:
Status Code is 200
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] [] [] ...
我期望的输出应该像以下命令返回的结果一样:
$ kubectl get --raw /api/v1/nodes
{"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:
kubeconfig := filepath.Join(
os.Getenv("HOME"), ".kube", "config",
)
config, err := clientcmd.BuildConfigFromFlags("", kubeconfig)
if err != nil {
log.Fatal(err)
}
config.NegotiatedSerializer = scheme.Codecs.WithoutConversion()
groupVersion, _ := schema.ParseGroupVersion("api/v1")
config.GroupVersion = &groupVersion
config.ContentType = "application/json"
config.AcceptContentTypes = "application/json"
exampleRestClient, err := rest.RESTClientFor(config)
if err != nil {
panic(err)
}
var statusCode int
var contentType string
response, err := exampleRestClient.
Get().
Resource("nodes").
Do(context.Background()).
StatusCode(&statusCode).
ContentType(&contentType).
Get()
if err != nil {
panic(err)
}
fmt.Printf("Content-type is %s\n", contentType)
fmt.Printf("Status Code is %d\n", statusCode)
fmt.Printf("Received response %v\n", response)
The response starts as:
Status Code is 200
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] [] [] ...
I expected the output to be like what the following command returns:
$ kubectl get --raw /api/v1/nodes
{"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" ...
答案1
得分: 0
收到。以下是翻译的内容:
收到的响应不是一个格式良好的 JSON 结构
我认为你对 client-go
模块的操作方式有些困惑。
来自 REST API 的响应绝对是一个格式良好的 JSON 响应,但是它会被解组成一个 Go 数据结构(例如 这个)。
如果你想要访问返回的节点,可以使用标准的 Go 语法与结果进行交互:
response, err := exampleRestClient.
Get().
Resource("nodes").
Do(context.Background()).
StatusCode(&statusCode).
ContentType(&contentType).
Get()
if err != nil {
panic(err)
}
nodes := response.(*v1.NodeList)
for _, node := range nodes.Items {
fmt.Printf("name: %s\n", node.ObjectMeta.GetName())
fmt.Printf("addresses:\n")
for _, addr := range node.Status.Addresses {
fmt.Printf(" %s: %s\n", addr.Type, addr.Address)
}
}
我期望的输出结果应该像下面的命令返回的那样:
为什么?client-go
绑定返回的数据对你的 Go 代码非常有用。如果你想要生成 JSON 输出,你需要显式地将资源编组为 JSON 格式:
response, err := exampleRestClient.
Get().
Resource("nodes").
Do(context.Background()).
StatusCode(&statusCode).
ContentType(&contentType).
Get()
if err != nil {
panic(err)
}
out, err := json.Marshal(response)
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:
response, err := exampleRestClient.
Get().
Resource("nodes").
Do(context.Background()).
StatusCode(&statusCode).
ContentType(&contentType).
Get()
if err != nil {
panic(err)
}
nodes := response.(*v1.NodeList)
for _, node := range nodes.Items {
fmt.Printf("name: %s\n", node.ObjectMeta.GetName())
fmt.Printf("addresses:\n")
for _, addr := range node.Status.Addresses {
fmt.Printf(" %s: %s\n", addr.Type, addr.Address)
}
}
> 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:
response, err := exampleRestClient.
Get().
Resource("nodes").
Do(context.Background()).
StatusCode(&statusCode).
ContentType(&contentType).
Get()
if err != nil {
panic(err)
}
out, err := json.Marshal(response)
fmt.Print(string(out))
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论