微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何在 Shell 脚本/Yaml 中使用 YQ 查找和替换?

如何解决如何在 Shell 脚本/Yaml 中使用 YQ 查找和替换?

我有大约 200-300 个 yaml 文件,我想要实现的是仅更改图像:在我的几个 yaml 文件中的选项,我有一个可以获取所需 yaml 文件的 shell 脚本,并且我只想实现改变图像:key only。

尝试的解决方案:

使用工具 yq v4:

for i in ${deployment[@]}
 do
 yq eval '( select(.spec.template.spec.containers[0].image |= "gcr.io/myrepo/myNginx:1.2.3"'  deployment-$i.yaml
done

此命令的作用是实现更改映像的预期结果,但它还会将更改附加到部署文件的所有部分,例如在文件中每个规范的末尾:

        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

如何在不将图像附加到部署文件的每个部分的情况下达到预期的结果?

解决方法

必须是 yq 吗?

我会用一个相当简单的 bash one-liner,使用 sed

for i in {1..3}; do sed -i "s/image.*/image: mysql:latest/" deployment-$i.yaml; done

上面的命令搜索字符串 "image" 后跟任何其他字符,直到行尾(因此它需要整个字符串 image: "my-fancy-image-name")并用全新的字符串替换它 - 在上例中的新字符串是 image: mysql:latest

选项 -i--in-place 用于就地编辑文件,即原始文件被编辑并与新内容一起保存。

唯一的假设是您的部署文件有固定的命名约定,即上述示例的正确名称是:deployment-1.yamldeployment-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" 字符串在您的 Deployment 中只出现一次。如果是这种情况,您无需担心为全局替换添加 g 选项(搜索字符串的每次出现)。上面的示例将仅在 "image" 字符串第一次出现时执行替换,这应该满足您的要求。如果您的部署包含多个容器,例如init 容器或 sidecar,很可能您不会有兴趣将此类部署中的每个 image 更改为相同的单个值。

,

这应该会让你得到预期的结果:

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

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。