我有一个Kubernetes Pod的json文档,下面是一个示例:
https://github.com/itaysk/kubectl-neat/blob/master/test/fixtures/pod-1-raw.json
我想遍历spec.containers[i].volumeMounts
并删除那些.name
以"default-token-"
开头的volumeMount对象。注意containers
和volumeMounts
都是数组。
使用jq,我花了1分钟来编写以下1行:try del(.spec.containers[].volumeMounts[] | select(.name | startswith("default-token-")))
。我正在尝试用Go重写它。
在寻找一个好的json库时,我选择了gjson / sjson。
由于sjson doesn't support array accessors(即#
语法)和gjson不支持获取结果的路径,因此我寻找了解决方法。
我尝试使用Result.Index
直接从字节 slice 中删除结果,并成功了,但是对于我编写的查询(spec.containers.#.volumeMounts.#(name%\"default-token-*\")|0
),索引始终为0(我尝试了它的不同变体,结果相同)。
因此,目前我有一些代码25行代码,这些代码使用gjson获取spec.containers.#.volumeMounts
并遍历结构,最后使用sjson.Delete
进行删除。
它可以工作,但是感觉比我预期的要复杂得多。
Go中有更好的方法吗?我愿意在需要时切换json库。
编辑:我宁愿避免使用类型化的架构,因为我可能需要对不同的类型执行此操作,因为有些我没有完整的架构。
(还删除了一些有关我当前实现的分散注意力的细节)
最佳答案
最简单的方法是将JSON解析为一个对象,使用该对象,然后序列化回JSON。
Kubernetes提供了一个Go客户端库,该库定义了可以使用stdlib编码/ json解组到的v1.Pod struct:
// import "k8s.io/api/core/v1"
var pod v1.Pod
if err := json.Unmarshal(podBody, &pod); err != nil {
log.Fatalf("parsing pod json: %s", err)
}
从那里您可以阅读
pod.Spec.Containers
及其VolumeMounts
:// Modify.
for c := range pod.Spec.Containers {
container := &pod.Spec.Containers[c]
for i, vol := range container.VolumeMounts {
if strings.HasPrefix(vol.Name, "default-token-") {
// Remove the VolumeMount at index i.
container.VolumeMounts = append(container.VolumeMounts[:i], container.VolumeMounts[i+1:]...)
}
}
}
https://play.golang.org/p/3r5-XKIazhK
如果您担心丢失一些可能出现在输入中的JSON,则可以改定义
var pod map[string]interface{}
,然后将其中的每个属性都类型转换为spec, ok := pod["spec"].(map[string]interface{})
,containers, ok := spec["containers"].([]map[string]interface)
等。希望能有所帮助。
ps。 “删除”是在https://github.com/golang/go/wiki/SliceTricks#delete之后