Bash 如何在Shell脚本/Yaml中使用YQ查找和替换?
我有大约200-300个yaml文件,我试图实现的是只更改image:option在我的一些yaml文件中,我有一个shell脚本,可以获得所需的yaml文件,我只想实现更改image:key only 已尝试解决方案: 使用工具v4: 此命令的作用是实现更改映像的预期结果,但它还将更改附加到部署文件的所有部分上,例如文件中每个规范的末尾:Bash 如何在Shell脚本/Yaml中使用YQ查找和替换?,bash,shell,kubernetes,yaml,yq,Bash,Shell,Kubernetes,Yaml,Yq,我有大约200-300个yaml文件,我试图实现的是只更改image:option在我的一些yaml文件中,我有一个shell脚本,可以获得所需的yaml文件,我只想实现更改image:key only 已尝试解决方案: 使用工具v4: 此命令的作用是实现更改映像的预期结果,但它还将更改附加到部署文件的所有部分上,例如文件中每个规范的末尾: apiVersion: apps/v1 kind: Deployment metadata:
apiVersion: apps/v1
kind: Deployment
metadata:
name: portal-1
spec:
selector:
matchLabels:
component: portal-1
role: ui
replicas: 1
template:
metadata:
labels:
component: reactportal
role: ui
spec:
containers:
- name: portal
image: gcr.io/myrepo/mynginx:4.52 <<< Desired CHange Happens Here >>>
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /$1
nginx.ingress.kubernetes.io/enable-cors: "false"
nginx.ingress.kubernetes.io/cors-allow-origin: "https://example.com"
name: portal-ingress
spec:
rules:
- host: mydomain.com
http:
paths:
- backend:
serviceName: portal-svc
servicePort: 80
path: /(.*)
template: <<<< THIS IS ALSO GETTING APPENDED >>>
spec:
containers:
- image: gcr.io/myrepo/mynginx:1.2.3
apiVersion:apps/v1
种类:部署
元数据:
名称:portal-1
规格:
选择器:
火柴标签:
构成部分:portal-1
角色:用户界面
副本:1份
模板:
元数据:
标签:
组件:reactportal
角色:用户界面
规格:
容器:
-名称:门户
图片:gcr.io/myrepo/mynginx:4.52>
---
apiVersion:extensions/v1beta1
种类:入口
元数据:
注释:
nginx.ingres.kubernetes.io/rewrite-target://$1
nginx.ingres.kubernetes.io/enable-cors:“false”
nginx.ingres.kubernetes.io/cors-allow-origin:“https://example.com"
名称:入口入口
规格:
规则:
-主持人:mydomain.com
http:
路径:
-后端:
服务名称:门户svc
服务端口:80
路径:/(*)
模板:
规格:
容器:
-图片:gcr.io/myrepo/mynginx:1.2.3
如何在不将映像附加到部署文件的每个部分的情况下获得所需的结果?必须这样做吗
我会使用相当简单的bash
一行程序,使用sed
:
for i in {1..3}; do sed -i "s/image.*/image: mysql:latest/" deployment-$i.yaml; done
上面的命令搜索字符串“image”
,后跟任何其他字符,直到行尾(因此它获取整个字符串image:“我喜欢的图像名称”
),并用全新的字符串替换它-在上面的示例中,新字符串是image:mysql:latest
选项-i
或--in-place
用于在位编辑文件,即使用新内容编辑和保存原始文件
唯一的假设是您的部署文件有一个固定的命名约定,即上面示例的正确名称是:deployment-1.yaml
,deployment-2.yaml
等
如果您想像示例中那样将图像名称用双引号括起来,可以这样做:
for i in {1..3}; do sed -i "s/image.*/image: \"gcr.io\/myrepo\/mynginx:1.2.3\"/" deployment-$i.yaml; done
如您所见,某些对sed
命令有特殊意义的字符,如“
或/
必须使用\
字符进行转义,以便在替换字符串中使用
实际上,在使用上述脚本时,还有一个假设,即
“image”
字符串在部署中只出现一次。如果是这种情况,您不必担心为全局替换添加g
选项(搜索字符串的每次出现)。以上示例仅在第一次出现“图像时执行替换“
string,应该满足您的要求。如果部署有多个容器,例如init容器或sidecar,则很可能您不会有兴趣将部署中的每个映像更改为相同的单个值。这将获得预期结果:
for i in ${deployment[@]}; do
yq eval '.spec|=select(.selector.matchLabels.component=="portal-1")
.template.spec.containers[0].image =
"gcr.io/myrepo/mynginx:1.2.3"' deployment-$i.yaml
done
请提供一份报告。在本例中,您不显示输入YAML,而且如果每个YAML文件都出现问题,您处理多个YAML文件似乎也不相关,因此最好只显示一个出现问题的精简YAML输入文件,即实际输出和所需输出。关于这个问题,关闭两个括号可能会有所帮助。谢谢你,马里奥,这是最简单的方法。我不确定我能不能把这个弄小一点
for i in ${deployment[@]}; do
yq eval '.spec|=select(.selector.matchLabels.component=="portal-1")
.template.spec.containers[0].image =
"gcr.io/myrepo/mynginx:1.2.3"' deployment-$i.yaml
done