String err.Error()
is the original, meaningful and best error message you can get from Kubernetes server for the user (Or you have to translate it by yourself).
Explains:
You need to look beyond the surface of kubernetes/client-go
client library.
Each client talks to k8s server through HTTP REST APIs, which sends back response in json
. It's the client-go
library that decodes the response body and stores the result into object, if possible.
As for your case, let me give you some examples through the Namespace
resource:
- First error:
POST https://xxx.xx.xx.xx:6443/api/v1/namespaces?fieldManager=kubectl-create
Response Status: 409 Conflict
{
"kind": "Status",
"apiVersion": "v1",
"metadata": {},
"status": "Failure",
"message": "namespaces \"hotel123\" already exists",
"reason": "AlreadyExists",
"details": {
"name": "hotel123",
"kind": "namespaces"
},
"code": 409
}
- second error:
POST https://xxx.xx.xx.xx:6443/api/v1/namespaces?fieldManager=kubectl-create
Response Status: 422 Unprocessable Entity
{
"kind": "Status",
"apiVersion": "v1",
"metadata": {},
"status": "Failure",
"message": "Namespace \"hotel_123\" is invalid: metadata.name: Invalid value: \"hotel_123\": a lowercase RFC 1123 label must consist of lower case alphanumeric characters or '-', and must start and end with an alphanumeric character (e.g. 'my-name', or '123-abc', regex used for validation is '[a-z0-9]\r\n([-a-z0-9]*[a-z0-9])?')",
"reason": "Invalid",
"details": {
"name": "hotel_123",
"kind": "Namespace",
"causes": [
{
"reason": "FieldValueInvalid",
"message": "Invalid value: \"hotel_123\": a lowercase RFC 1123 label must consist of lower case alphanumeric characters or '-', and must start and end with an alphanumeric character (e.g. 'my-name', or '123-abc', regex used for validation is '[a-z0-9]([-a-z0-9]*[a-z0-9])?')",
"field": "metadata.name"
}
]
},
"code": 422
}
- normal return:
POST https://xxx.xx.xx.xx:6443/api/v1/namespaces?fieldManager=kubectl-create
Response Status: 201 Created
{
"kind": "Namespace",
"apiVersion": "v1",
"metadata": {
"name": "hotel12345",
"uid": "7a301d8b-37cd-45a5-8345-82wsufy88223456",
"resourceVersion": "12233445566",
"creationTimestamp": "2023-04-03T15:35:59Z",
"managedFields": [
{
"manager": "kubectl-create",
"operation": "Update",
"apiVersion": "v1",
"time": "2023-04-03T15:35:59Z",
"fieldsType": "FieldsV1",
"fieldsV1": {
"f:status": {
"f:phase": {}
}
}
}
]
},
"spec": {
"finalizers": [
"kubernetes"
]
},
"status": {
"phase": "Active"
}
}
In a word, if the HTTP Status is not 2xx, the returned object is of type Status and has .Status != StatusSuccess, the additional information(message
in this case) in Status will be used to enrich the error, just as the code snippets below:
createdNamespace, err := clientset.CoreV1().Namespaces().Create(context.TODO(), namespace, metav1.CreateOptions{})
if err != nil {
// print "namespaces \"hotel123\" already exists" or so
fmt.Println(err.Error())
return err.Error()
}
fmt.Printf("Created Namespace %+v in the cluster\n", createdNamespace)
return ""