如何用yq批量更新非空节点?解决Istio CEL规则与Go模板冲突
Istio CEL规则与Go模板冲突的yq替换解决方案
问题概述
Istio新增的CEL验证规则因格式问题,与自定义Go模板引擎冲突,触发语法错误:
{"GenericComponent":{"name":"istio","namespace":"test-tbv-15"},"component":"cpc-operator","controller":"genericcomponent","controllerGroup":"cpc-operator.doks.digitalocean.com","controllerKind":"GenericComponent","egid":0,"eid":0,"env":"development","err":"failed to execute template \"istio/istio.yaml.tmpl\": template: istio.yaml.tmpl:265: invalid syntax","host":"local-cpcoperator","level":"error","msg":"Reconciler error","name":"istio","namespace":"test-tbv-15","pid":1,"pname":"/bin/cpc-operator","reconcileID":"e4298d85-7ad2-4dd4-944d-3e72d7e5d570","runtime_version":"go1.22.4","time":"2024-09-06T15:05:39.642835008Z","version":"b3337a879225e324581f73229bdadde47dd881d7"}
冲突源于CEL规则中嵌套的转义单引号,导致Go模板解析失败:
x-kubernetes-validations: - message: Support kinds are core/Service and gateway.networking.k8s.io/Gateway rule: '[self.group, self.kind] in [[''core'',''Service''], ['''',''Service''], [''gateway.networking.k8s.io'',''Gateway'']]'
定位目标节点
用yq可定位到需修改的规则节点:
cat $TEMPLATE_FILE | yq '.spec.versions[1].schema.openAPIV3Schema.properties.spec.properties.targetRef.x-kubernetes-validations[0].rule'
返回结果混杂空值(null)和有效规则:
null --- [self.group, self.kind] in [['core','Service'], ['','Service'], ['gateway.networking.k8s.io','Gateway']] --- null --- null ...
通过select(.)过滤空值,仅保留非空规则:
yq '.spec.versions[0].schema.openAPIV3Schema.properties.spec.properties.targetRef.x-kubernetes-validations[0].rule | select(.)'
返回结果:
[self.group, self.kind] in [['core','Service'], ['','Service'], ['gateway.networking.k8s.io','Gateway']] --- [self.group, self.kind] in [['core','Service'], ['','Service'], ['gateway.networking.k8s.io','Gateway']] --- ...
替换失败的尝试
以下命令无法实现精准替换:
- 会修改所有节点(包括空值):
yq -i '.spec.versions[0].schema.openAPIV3Schema.properties.spec.properties.targetRef.x-kubernetes-validations[0].rule |= "test"' $TEMPLATE_FILE
- 无任何效果:
yq -i '.spec.versions[0].schema.openAPIV3Schema.properties.spec.properties.targetRefs.items.x-kubernetes-validations[0].rule | select(.) = "test"' $TEMPLATE_FILE
正确的yq替换语法
要仅替换非空规则节点,需结合select(.)和赋值操作,使用以下命令:
1. 处理单个targetRef节点
遍历所有版本,仅对非空规则赋值:
yq -i '.spec.versions[].schema.openAPIV3Schema.properties.spec.properties.targetRef.x-kubernetes-validations[0].rule |= select(.) | "test"' $TEMPLATE_FILE
2. 处理targetRefs数组项
如果需要修改targetRefs.items下的规则:
yq -i '.spec.versions[].schema.openAPIV3Schema.properties.spec.properties.targetRefs.items.x-kubernetes-validations[0].rule |= select(.) | "test"' $TEMPLATE_FILE
3. 通用匹配所有非空规则
如果不确定路径,可递归匹配所有包含非空CEL规则的节点:
yq -i '(.. | select(has("x-kubernetes-validations") and .x-kubernetes-validations[0].rule != null)).x-kubernetes-validations[0].rule = "test"' $TEMPLATE_FILE
语法说明
spec.versions[]:遍历所有版本,避免遗漏不同索引的版本(比如versions[0]或versions[1])select(.):仅保留非空的规则值,空值会被跳过|= select(.) | "test":仅对非空节点执行赋值操作
内容的提问来源于stack exchange,提问作者eomolo
相关产品推荐
相关产品推荐

