python 如何使用jq合并两个JSON对象

cwtwac6a  于 2022-12-02  发布在  Python
关注(0)|答案(1)|浏览(108)

我有两个文件:kube-apiserver.json

{
    "apiVersion": "v1",
    "kind": "Pod",
    "metadata": {
        [...]
    },
    "spec": {
        "containers": [
            {
                "command": [
                    "kube-apiserver",
                    "--advertise-address=192.168.49.2",
                    "--allow-privileged=true",
                    "--authorization-mode=Node,RBAC",
                    "--client-ca-file=/var/lib/minikube/certs/ca.crt",
                    "--enable-admission-plugins=NamespaceLifecycle,LimitRanger,ServiceAccount,DefaultStorageClass,DefaultTolerationSeconds,NodeRestriction,MutatingAdmissionWebhook,ValidatingAdmissionWebhook,ResourceQuota",
                    "--enable-bootstrap-token-auth=true",
                    "--etcd-cafile=/var/lib/minikube/certs/etcd/ca.crt",
                    "--etcd-certfile=/var/lib/minikube/certs/apiserver-etcd-client.crt",
                    "--etcd-keyfile=/var/lib/minikube/certs/apiserver-etcd-client.key",
                    "--etcd-servers=https://127.0.0.1:2379",
                    "--kubelet-client-certificate=/var/lib/minikube/certs/apiserver-kubelet-client.crt",
                    "--kubelet-client-key=/var/lib/minikube/certs/apiserver-kubelet-client.key",
                    "--kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname",
                    "--proxy-client-cert-file=/var/lib/minikube/certs/front-proxy-client.crt",
                    "--proxy-client-key-file=/var/lib/minikube/certs/front-proxy-client.key",
                    "--requestheader-allowed-names=front-proxy-client",
                    "--requestheader-client-ca-file=/var/lib/minikube/certs/front-proxy-ca.crt",
                    "--requestheader-extra-headers-prefix=X-Remote-Extra-",
                    "--requestheader-group-headers=X-Remote-Group",
                    "--requestheader-username-headers=X-Remote-User",
                    "--secure-port=8443",
                    "--service-account-issuer=https://kubernetes.default.svc.cluster.local",
                    "--service-account-key-file=/var/lib/minikube/certs/sa.pub",
                    "--service-account-signing-key-file=/var/lib/minikube/certs/sa.key",
                    "--service-cluster-ip-range=10.96.0.0/12",
                    "--tls-cert-file=/var/lib/minikube/certs/apiserver.crt",
                    "--tls-private-key-file=/var/lib/minikube/certs/apiserver.key"
                ],
                [...]
                "volumeMounts": [
                    {
                        "mountPath": "/etc/ssl/certs",
                        "name": "ca-certs",
                        "readOnly": true
                    },
                    {
                        "mountPath": "/etc/ca-certificates",
                        "name": "etc-ca-certificates",
                        "readOnly": true
                    },
                    {
                        "mountPath": "/var/lib/minikube/certs",
                        "name": "k8s-certs",
                        "readOnly": true
                    },
                    {
                        "mountPath": "/usr/local/share/ca-certificates",
                        "name": "usr-local-share-ca-certificates",
                        "readOnly": true
                    },
                    {
                        "mountPath": "/usr/share/ca-certificates",
                        "name": "usr-share-ca-certificates",
                        "readOnly": true
                    }
                ]
            }
        ],
        [...]
        "volumes": [
            {
                "hostPath": {
                    "path": "/etc/ssl/certs",
                    "type": "DirectoryOrCreate"
                },
                "name": "ca-certs"
            },
            {
                "hostPath": {
                    "path": "/etc/ca-certificates",
                    "type": "DirectoryOrCreate"
                },
                "name": "etc-ca-certificates"
            },
            {
                "hostPath": {
                    "path": "/var/lib/minikube/certs",
                    "type": "DirectoryOrCreate"
                },
                "name": "k8s-certs"
            },
            {
                "hostPath": {
                    "path": "/usr/local/share/ca-certificates",
                    "type": "DirectoryOrCreate"
                },
                "name": "usr-local-share-ca-certificates"
            },
            {
                "hostPath": {
                    "path": "/usr/share/ca-certificates",
                    "type": "DirectoryOrCreate"
                },
                "name": "usr-share-ca-certificates"
            }
        ]
    },
    "status": {
        [...]
    }
}

和patch.json

{
    "apiVersion": "v1",
    "kind": "Pod",
    "metadata": {
    },
    "spec": {
        "containers": [
            {
                "command": [
                    "--audit-policy-file=/etc/kubernetes/audit-policy.yaml",
                    "--audit-log-path=/var/log/kubernetes/audit/audit.log"
                ],
                "volumeMounts": [
                    {
                        "mountPath": "/etc/kubernetes/audit-policy.yaml",
                        "name": "audit",
                        "readOnly": true
                    },
                    {
                        "mountPath": "/var/log/kubernetes/audit/",
                        "name": "audit-log",
                        "readOnly": true
                    }
                ]
            }
        ],
        "volumes": [
            {
                "hostPath": {
                    "path": "/etc/kubernetes/audit-policy.yaml",
                    "type": "FileOrCreate"
                },
                "name": "audit"
            },
            {
                "hostPath": {
                    "path": "/var/log/kubernetes/audit/",
                    "type": "DirectoryOrCreate"
                },
                "name": "audit-log"
            }
        ]
    },
    "status": {
    }
}

当我尝试执行jq -s '.[0] * .[1]' kube-apiserver.json patch.json > patched-apiserver.json时,patch.json中的项覆盖了kube-apiserver.json中的项,因此它看起来像这样:

{
  "apiVersion": "v1",
  "kind": "Pod",
  "metadata": {
    [...]
  "spec": {
    "containers": [
      {
        "command": [
          "--audit-policy-file=/etc/kubernetes/audit-policy.yaml",
          "--audit-log-path=/var/log/kubernetes/audit/audit.log"
        ],
        "volumeMounts": [
          {
            "mountPath": "/etc/kubernetes/audit-policy.yaml",
            "name": "audit",
            "readOnly": true
          },
          {
            "mountPath": "/var/log/kubernetes/audit/",
            "name": "audit-log",
            "readOnly": true
          }
        ]
      }
    ],
    [..].
    "volumes": [
      {
        "hostPath": {
          "path": "/etc/kubernetes/audit-policy.yaml",
          "type": "FileOrCreate"
        },
        "name": "audit"
      },
      {
        "hostPath": {
          "path": "/var/log/kubernetes/audit/",
          "type": "DirectoryOrCreate"
        },
        "name": "audit-log"
      }
    ]
  },
  "status": {
    [...]
  }
}

我希望我的文件看起来像这样:

{
    "apiVersion": "v1",
    "kind": "Pod",
    "metadata": {
        [...]
    },
    "spec": {
        "containers": [
            {
                "command": [
                    "kube-apiserver",
                    "--advertise-address=192.168.49.2",
                    "--allow-privileged=true",
                    "--authorization-mode=Node,RBAC",
                    "--client-ca-file=/var/lib/minikube/certs/ca.crt",
                    "--enable-admission-plugins=NamespaceLifecycle,LimitRanger,ServiceAccount,DefaultStorageClass,DefaultTolerationSeconds,NodeRestriction,MutatingAdmissionWebhook,ValidatingAdmissionWebhook,ResourceQuota",
                    "--enable-bootstrap-token-auth=true",
                    "--etcd-cafile=/var/lib/minikube/certs/etcd/ca.crt",
                    "--etcd-certfile=/var/lib/minikube/certs/apiserver-etcd-client.crt",
                    "--etcd-keyfile=/var/lib/minikube/certs/apiserver-etcd-client.key",
                    "--etcd-servers=https://127.0.0.1:2379",
                    "--kubelet-client-certificate=/var/lib/minikube/certs/apiserver-kubelet-client.crt",
                    "--kubelet-client-key=/var/lib/minikube/certs/apiserver-kubelet-client.key",
                    "--kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname",
                    "--proxy-client-cert-file=/var/lib/minikube/certs/front-proxy-client.crt",
                    "--proxy-client-key-file=/var/lib/minikube/certs/front-proxy-client.key",
                    "--requestheader-allowed-names=front-proxy-client",
                    "--requestheader-client-ca-file=/var/lib/minikube/certs/front-proxy-ca.crt",
                    "--requestheader-extra-headers-prefix=X-Remote-Extra-",
                    "--requestheader-group-headers=X-Remote-Group",
                    "--requestheader-username-headers=X-Remote-User",
                    "--secure-port=8443",
                    "--service-account-issuer=https://kubernetes.default.svc.cluster.local",
                    "--service-account-key-file=/var/lib/minikube/certs/sa.pub",
                    "--service-account-signing-key-file=/var/lib/minikube/certs/sa.key",
                    "--service-cluster-ip-range=10.96.0.0/12",
                    "--tls-cert-file=/var/lib/minikube/certs/apiserver.crt",
                    "--tls-private-key-file=/var/lib/minikube/certs/apiserver.key",
                    "--audit-policy-file=/etc/kubernetes/audit-policy.yaml",
                    "--audit-log-path=/var/log/kubernetes/audit/audit.log"
                ],
                [...]
                "volumeMounts": [
                    {
                        "mountPath": "/etc/ssl/certs",
                        "name": "ca-certs",
                        "readOnly": true
                    },
                    {
                        "mountPath": "/etc/ca-certificates",
                        "name": "etc-ca-certificates",
                        "readOnly": true
                    },
                    {
                        "mountPath": "/var/lib/minikube/certs",
                        "name": "k8s-certs",
                        "readOnly": true
                    },
                    {
                        "mountPath": "/usr/local/share/ca-certificates",
                        "name": "usr-local-share-ca-certificates",
                        "readOnly": true
                    },
                    {
                        "mountPath": "/usr/share/ca-certificates",
                        "name": "usr-share-ca-certificates",
                        "readOnly": true
                    },
                    {
                        "mountPath": "/etc/kubernetes/audit-policy.yaml",
                        "name": "audit",
                        "readOnly": true
                    },
                    {
                        "mountPath": "/var/log/kubernetes/audit/",
                        "name": "audit-log",
                        "readOnly": true
                    }
                ]
            }
        ],
        [...]
        "volumes": [
            {
                "hostPath": {
                    "path": "/etc/ssl/certs",
                    "type": "DirectoryOrCreate"
                },
                "name": "ca-certs"
            },
            {
                "hostPath": {
                    "path": "/etc/ca-certificates",
                    "type": "DirectoryOrCreate"
                },
                "name": "etc-ca-certificates"
            },
            {
                "hostPath": {
                    "path": "/var/lib/minikube/certs",
                    "type": "DirectoryOrCreate"
                },
                "name": "k8s-certs"
            },
            {
                "hostPath": {
                    "path": "/usr/local/share/ca-certificates",
                    "type": "DirectoryOrCreate"
                },
                "name": "usr-local-share-ca-certificates"
            },
            {
                "hostPath": {
                    "path": "/usr/share/ca-certificates",
                    "type": "DirectoryOrCreate"
                },
                "name": "usr-share-ca-certificates"
            },
            {
                "hostPath": {
                    "path": "/etc/kubernetes/audit-policy.yaml",
                    "type": "FileOrCreate"
                },
                "name": "audit"
            },
            {
                "hostPath": {
                    "path": "/var/log/kubernetes/audit/",
                    "type": "DirectoryOrCreate"
                },
                "name": "audit-log"
            }
        ]
    },
    "status": {
        [...]
    }
}

有人知道如何用jq/python/bash/whatever来解决这个问题吗?

8i9zcol2

8i9zcol21#

jq --slurpfile patch patch.json '
  (.spec.containers |= map(.command      |= (. + $patch[].spec.containers[0].command      | unique) |
                           .volumeMounts |= (. + $patch[].spec.containers[0].volumeMounts | unique))) |
  (.spec.volumes    |= (. + $patch[].spec.volumes | unique))
' kube-apiserver.json

我添加了unique,以确保commandsvolumeMountsvolumes只出现一次。这样做的副作用是对数组进行排序。如果您不想使用unique,可以将其删除。您的问题中有一个问题:spec.containers是一个数组。在你的例子中,这个数组只包含一个元素,我的代码将补丁中的第一个元素添加到每个容器中。或者你想根据位置合并补丁吗?在这种情况下,这个解决方案不起作用。

相关问题