juju status 和 jq 过滤混合了 JSON status 中多个对象的东西

juju status and jq filtering blend stuff from multiple objects in JSON status

tl;dr

我正在尝试获取 juju status 输出的 JSON 表示,该表示将机器、实例 ID 和单元对象化,使得 JSON 看起来类似于:

{
  "0": {
          "instance-id": "i-xxxxxxxxxxxxxx",
          "unit-name": "easyrsa/0"
       },
  "1": {
          "instance-id": "i-xxxxxxxxxxxxxx",
          "unit-name": "etcd/0"
       },
  "2": {
          "instance-id": "i-xxxxxxxxxxxxxx",
          "unit-name": "kubeapi-load-balancer/0"
       },
  "10": {
          "instance-id": "i-xxxxxxxxxxxxxx",
          "unit-name": "kubernetes-worker/4"
       },
  "11": {
          "instance-id": "i-xxxxxxxxxxxxxx",
          "unit-name": "kubernetes-worker/5"
       },
  "12": {
          "instance-id": "i-xxxxxxxxxxxxxx",
          "unit-name": "kubernetes-master/3"
       }
}

长:

Munging juju status --format json 对我来说很复杂,因为要处理的数据在 JSON 中分为两个不同的主要对象。由于机器的密钥是不可迭代的,因此我以后无法像引用数组那样引用它们——或者至少我认为那是我搞砸的地方。

有些事情我尝试过但失败了(主要是因为我为如何存储 .machines 密钥以备后用而苦苦挣扎)...

juju status --format json | jq -r '.machines as $m | .machines | [foreach keys[] as $item ({m: $item, id: $m[$item]."instance-id"})]'

... | juju status --format json | jq -r '.machines | keys[] as $k...

... | juju status --format json | jq -r '.machines | keys[] as $k |...

要么我没有得到我需要的结果,要么我遇到语法错误。我从来不需要在 jq 上下文中使用 foreach 。事实上,这是我尝试用 jq 完成的最复杂的事情,所以我已经超出了我的舒适区。如有任何帮助,我们将不胜感激。

这是一个示例 juju status JSON 对象:

{
  "model": {
    "name": "xxxxxxxxxx",
    "controller": "xxxxxxxxxx",
    "cloud": "xxxxxxxxxx",
    "region": "xxxxxxxxxx",
    "version": "xxxxxxxxxx",
    "model-status": {
      "current": "xxxxxxxxxx",
      "since": "xxxxxxxxxx"
    },
    "sla": "xxxxxxxxxx"
  },
  "machines": {
    "0": {
      "juju-status": {
        "current": "xxxxxxxxxx",
        "since": "xxxxxxxxxx",
        "version": "xxxxxxxxxx"
      },
      "dns-name": "xxxxxxxxxx",
      "ip-addresses": [
        "10.0.0.229",
        "252.0.229.1"
      ],
      "instance-id": "i-xxxxxxxxxxxxxx",
      "machine-status": {
        "current": "xxxxxxxxxx",
        "message": "xxxxxxxxxx",
        "since": "xxxxxxxxxx"
      },
      "series": "xxxxxxxxxx",
      "network-interfaces": {
        "eth0": {
          "ip-addresses": [
            "10.0.0.229"
          ],
          "mac-address": "xxxxxxxxxx",
          "gateway": "xxxxxxxxxx",
          "is-up": true
        },
        "fan-252": {
          "ip-addresses": [
            "252.0.229.1"
          ],
          "mac-address": "xxxxxxxxxx",
          "is-up": true
        }
      },
      "constraints": "xxxxxxxxxx",
      "hardware": "xxxxxxxxxx"
    },
    "1": {
      "juju-status": {
        "current": "xxxxxxxxxx",
        "since": "xxxxxxxxxx",
        "version": "xxxxxxxxxx"
      },
      "dns-name": "xxxxxxxxxx",
      "ip-addresses": [
        "10.0.0.61",
        "252.0.61.1"
      ],
      "instance-id": "i-xxxxxxxxxxxxxx",
      "machine-status": {
        "current": "xxxxxxxxxx",
        "message": "xxxxxxxxxx",
        "since": "xxxxxxxxxx"
      },
      "series": "xxxxxxxxxx",
      "network-interfaces": {
        "eth0": {
          "ip-addresses": [
            "10.0.0.61"
          ],
          "mac-address": "xxxxxxxxxx",
          "gateway": "xxxxxxxxxx",
          "is-up": true
        },
        "fan-252": {
          "ip-addresses": [
            "252.0.61.1"
          ],
          "mac-address": "xxxxxxxxxx",
          "is-up": true
        }
      },
      "constraints": "xxxxxxxxxx",
      "hardware": "xxxxxxxxxx"
    },
    "10": {
      "juju-status": {
        "current": "xxxxxxxxxx",
        "since": "xxxxxxxxxx",
        "version": "xxxxxxxxxx"
      },
      "dns-name": "xxxxxxxxxx",
      "ip-addresses": [
        "10.0.0.37",
        "252.0.37.1"
      ],
      "instance-id": "i-xxxxxxxxxxxxxx",
      "machine-status": {
        "current": "xxxxxxxxxx",
        "message": "xxxxxxxxxx",
        "since": "xxxxxxxxxx"
      },
      "series": "xxxxxxxxxx",
      "network-interfaces": {
        "ens5": {
          "ip-addresses": [
            "10.0.0.37"
          ],
          "mac-address": "xxxxxxxxxx",
          "gateway": "xxxxxxxxxx",
          "is-up": true
        },
        "fan-252": {
          "ip-addresses": [
            "252.0.37.1"
          ],
          "mac-address": "xxxxxxxxxx",
          "is-up": true
        }
      },
      "constraints": "xxxxxxxxxx",
      "hardware": "xxxxxxxxxx"
    },
    "11": {
      "juju-status": {
        "current": "xxxxxxxxxx",
        "since": "xxxxxxxxxx",
        "version": "xxxxxxxxxx"
      },
      "dns-name": "xxxxxxxxxx",
      "ip-addresses": [
        "10.0.0.54"
      ],
      "instance-id": "i-xxxxxxxxxxxxxx",
      "machine-status": {
        "current": "xxxxxxxxxx",
        "message": "xxxxxxxxxx",
        "since": "xxxxxxxxxx"
      },
      "series": "xxxxxxxxxx",
      "network-interfaces": {
        "ens5": {
          "ip-addresses": [
            "10.0.0.54"
          ],
          "mac-address": "xxxxxxxxxx",
          "gateway": "xxxxxxxxxx",
          "is-up": true
        }
      },
      "constraints": "xxxxxxxxxx",
      "hardware": "xxxxxxxxxx"
    },
    "12": {
      "juju-status": {
        "current": "xxxxxxxxxx",
        "since": "xxxxxxxxxx",
        "version": "xxxxxxxxxx"
      },
      "dns-name": "xxxxxxxxxx",
      "ip-addresses": [
        "10.0.0.101"
      ],
      "instance-id": "i-xxxxxxxxxxxxxx",
      "machine-status": {
        "current": "xxxxxxxxxx",
        "message": "xxxxxxxxxx",
        "since": "xxxxxxxxxx"
      },
      "series": "xxxxxxxxxx",
      "network-interfaces": {
        "ens5": {
          "ip-addresses": [
            "10.0.0.101"
          ],
          "mac-address": "xxxxxxxxxx",
          "gateway": "xxxxxxxxxx",
          "is-up": true
        }
      },
      "constraints": "xxxxxxxxxx",
      "hardware": "xxxxxxxxxx"
    },
    "2": {
      "juju-status": {
        "current": "xxxxxxxxxx",
        "since": "xxxxxxxxxx",
        "version": "xxxxxxxxxx"
      },
      "dns-name": "xxxxxxxxxx",
      "ip-addresses": [
        "10.0.0.184",
        "252.0.184.1"
      ],
      "instance-id": "i-xxxxxxxxxxxxxx",
      "machine-status": {
        "current": "xxxxxxxxxx",
        "message": "xxxxxxxxxx",
        "since": "xxxxxxxxxx"
      },
      "series": "xxxxxxxxxx",
      "network-interfaces": {
        "eth0": {
          "ip-addresses": [
            "10.0.0.184"
          ],
          "mac-address": "xxxxxxxxxx",
          "gateway": "xxxxxxxxxx",
          "is-up": true
        },
        "fan-252": {
          "ip-addresses": [
            "252.0.184.1"
          ],
          "mac-address": "xxxxxxxxxx",
          "is-up": true
        }
      },
      "constraints": "xxxxxxxxxx",
      "hardware": "xxxxxxxxxx"
    }
  },
  "applications": {
    "easyrsa": {
      "charm": "xxxxxxxxxx",
      "series": "xxxxxxxxxx",
      "os": "xxxxxxxxxx",
      "charm-origin": "xxxxxxxxxx",
      "charm-name": "xxxxxxxxxx",
      "charm-rev": 39,
      "can-upgrade-to": "xxxxxxxxxx",
      "exposed": false,
      "application-status": {
        "current": "xxxxxxxxxx",
        "message": "xxxxxxxxxx",
        "since": "xxxxxxxxxx"
      },
      "relations": {
        "client": [
          "etcd",
          "kubeapi-load-balancer",
          "kubernetes-master",
          "kubernetes-worker"
        ]
      },
      "units": {
        "easyrsa/0": {
          "workload-status": {
            "current": "xxxxxxxxxx",
            "message": "xxxxxxxxxx",
            "since": "xxxxxxxxxx"
          },
          "juju-status": {
            "current": "xxxxxxxxxx",
            "since": "xxxxxxxxxx",
            "version": "xxxxxxxxxx"
          },
          "leader": true,
          "machine": "0",
          "public-address": "xxxxxxxxxx"
        }
      },
      "version": "xxxxxxxxxx"
    },
    "etcd": {
      "charm": "xxxxxxxxxx",
      "series": "xxxxxxxxxx",
      "os": "xxxxxxxxxx",
      "charm-origin": "xxxxxxxxxx",
      "charm-name": "xxxxxxxxxx",
      "charm-rev": 77,
      "can-upgrade-to": "xxxxxxxxxx",
      "exposed": false,
      "application-status": {
        "current": "xxxxxxxxxx",
        "message": "xxxxxxxxxx",
        "since": "xxxxxxxxxx"
      },
      "relations": {
        "certificates": [
          "easyrsa"
        ],
        "cluster": [
          "etcd"
        ],
        "db": [
          "flannel",
          "kubernetes-master"
        ]
      },
      "units": {
        "etcd/0": {
          "workload-status": {
            "current": "xxxxxxxxxx",
            "message": "xxxxxxxxxx",
            "since": "xxxxxxxxxx"
          },
          "juju-status": {
            "current": "xxxxxxxxxx",
            "since": "xxxxxxxxxx",
            "version": "xxxxxxxxxx"
          },
          "leader": true,
          "machine": "1",
          "open-ports": [
            "2379/tcp"
          ],
          "public-address": "xxxxxxxxxx"
        }
      },
      "version": "xxxxxxxxxx"
    },
    "flannel": {
      "charm": "xxxxxxxxxx",
      "series": "xxxxxxxxxx",
      "os": "xxxxxxxxxx",
      "charm-origin": "xxxxxxxxxx",
      "charm-name": "xxxxxxxxxx",
      "charm-rev": 52,
      "can-upgrade-to": "xxxxxxxxxx",
      "exposed": false,
      "application-status": {
        "current": "xxxxxxxxxx",
        "message": "xxxxxxxxxx",
        "since": "xxxxxxxxxx"
      },
      "relations": {
        "cni": [
          "kubernetes-master",
          "kubernetes-worker"
        ],
        "etcd": [
          "etcd"
        ]
      },
      "subordinate-to": [
        "kubernetes-master",
        "kubernetes-worker"
      ],
      "version": "xxxxxxxxxx"
    },
    "kubeapi-load-balancer": {
      "charm": "xxxxxxxxxx",
      "series": "xxxxxxxxxx",
      "os": "xxxxxxxxxx",
      "charm-origin": "xxxxxxxxxx",
      "charm-name": "xxxxxxxxxx",
      "charm-rev": 57,
      "can-upgrade-to": "xxxxxxxxxx",
      "exposed": true,
      "application-status": {
        "current": "xxxxxxxxxx",
        "message": "xxxxxxxxxx",
        "since": "xxxxxxxxxx"
      },
      "relations": {
        "apiserver": [
          "kubernetes-master"
        ],
        "certificates": [
          "easyrsa"
        ],
        "loadbalancer": [
          "kubernetes-master"
        ],
        "website": [
          "kubernetes-worker"
        ]
      },
      "units": {
        "kubeapi-load-balancer/0": {
          "workload-status": {
            "current": "xxxxxxxxxx",
            "message": "xxxxxxxxxx",
            "since": "xxxxxxxxxx"
          },
          "juju-status": {
            "current": "xxxxxxxxxx",
            "since": "xxxxxxxxxx",
            "version": "xxxxxxxxxx"
          },
          "leader": true,
          "machine": "2",
          "open-ports": [
            "443/tcp"
          ],
          "public-address": "xxxxxxxxxx"
        }
      },
      "version": "xxxxxxxxxx"
    },
    "kubernetes-master": {
      "charm": "xxxxxxxxxx",
      "series": "xxxxxxxxxx",
      "os": "xxxxxxxxxx",
      "charm-origin": "xxxxxxxxxx",
      "charm-name": "xxxxxxxxxx",
      "charm-rev": 102,
      "can-upgrade-to": "xxxxxxxxxx",
      "exposed": false,
      "application-status": {
        "current": "xxxxxxxxxx",
        "message": "xxxxxxxxxx",
        "since": "xxxxxxxxxx"
      },
      "relations": {
        "certificates": [
          "easyrsa"
        ],
        "cni": [
          "flannel"
        ],
        "etcd": [
          "etcd"
        ],
        "kube-api-endpoint": [
          "kubeapi-load-balancer"
        ],
        "kube-control": [
          "kubernetes-worker"
        ],
        "loadbalancer": [
          "kubeapi-load-balancer"
        ]
      },
      "units": {
        "kubernetes-master/3": {
          "workload-status": {
            "current": "xxxxxxxxxx",
            "message": "xxxxxxxxxx",
            "since": "xxxxxxxxxx"
          },
          "juju-status": {
            "current": "xxxxxxxxxx",
            "since": "xxxxxxxxxx",
            "version": "xxxxxxxxxx"
          },
          "leader": true,
          "machine": "12",
          "open-ports": [
            "6443/tcp"
          ],
          "public-address": "xxxxxxxxxx",
          "subordinates": {
            "flannel/9": {
              "workload-status": {
                "current": "xxxxxxxxxx",
                "message": "xxxxxxxxxx",
                "since": "xxxxxxxxxx"
              },
              "juju-status": {
                "current": "xxxxxxxxxx",
                "since": "xxxxxxxxxx",
                "version": "xxxxxxxxxx"
              },
              "upgrading-from": "xxxxxxxxxx",
              "public-address": "xxxxxxxxxx"
            }
          }
        }
      },
      "version": "xxxxxxxxxx"
    },
    "kubernetes-worker": {
      "charm": "xxxxxxxxxx",
      "series": "xxxxxxxxxx",
      "os": "xxxxxxxxxx",
      "charm-origin": "xxxxxxxxxx",
      "charm-name": "xxxxxxxxxx",
      "charm-rev": 114,
      "can-upgrade-to": "xxxxxxxxxx",
      "exposed": false,
      "application-status": {
        "current": "xxxxxxxxxx",
        "message": "xxxxxxxxxx",
        "since": "xxxxxxxxxx"
      },
      "relations": {
        "certificates": [
          "easyrsa"
        ],
        "cni": [
          "flannel"
        ],
        "kube-api-endpoint": [
          "kubeapi-load-balancer"
        ],
        "kube-control": [
          "kubernetes-master"
        ]
      },
      "units": {
        "kubernetes-worker/4": {
          "workload-status": {
            "current": "xxxxxxxxxx",
            "message": "xxxxxxxxxx",
            "since": "xxxxxxxxxx"
          },
          "juju-status": {
            "current": "xxxxxxxxxx",
            "since": "xxxxxxxxxx",
            "version": "xxxxxxxxxx"
          },
          "machine": "10",
          "open-ports": [
            "80/tcp",
            "443/tcp"
          ],
          "public-address": "xxxxxxxxxx",
          "subordinates": {
            "flannel/7": {
              "workload-status": {
                "current": "xxxxxxxxxx",
                "message": "xxxxxxxxxx",
                "since": "xxxxxxxxxx"
              },
              "juju-status": {
                "current": "xxxxxxxxxx",
                "since": "xxxxxxxxxx",
                "version": "xxxxxxxxxx"
              },
              "upgrading-from": "xxxxxxxxxx",
              "public-address": "xxxxxxxxxx"
            }
          }
        },
        "kubernetes-worker/5": {
          "workload-status": {
            "current": "xxxxxxxxxx",
            "message": "xxxxxxxxxx",
            "since": "xxxxxxxxxx"
          },
          "juju-status": {
            "current": "xxxxxxxxxx",
            "since": "xxxxxxxxxx",
            "version": "xxxxxxxxxx"
          },
          "leader": true,
          "machine": "11",
          "open-ports": [
            "80/tcp",
            "443/tcp"
          ],
          "public-address": "xxxxxxxxxx",
          "subordinates": {
            "flannel/8": {
              "workload-status": {
                "current": "xxxxxxxxxx",
                "message": "xxxxxxxxxx",
                "since": "xxxxxxxxxx"
              },
              "juju-status": {
                "current": "xxxxxxxxxx",
                "since": "xxxxxxxxxx",
                "version": "xxxxxxxxxx"
              },
              "leader": true,
              "upgrading-from": "xxxxxxxxxx",
              "public-address": "xxxxxxxxxx"
            }
          }
        }
      },
      "version": "xxxxxxxxxx"
    }
  }
}

我不清楚 "unit-name" 的值究竟应该如何导出,但以下内容应该可以帮助您:

def machine($id):
  first(.applications[]
    | (.units? // empty)
    | to_entries[]
    | select(.value.machine == $id)
    | .key ) ;

. as $in
| .machines
| to_entries[]
| .key as $key
| {($key): {
             "unit-name": (.value |.["instance-id"]),
             "machine": ($in|machine($key))
           } }

根据您的输入,这会生成一个对象流,开头为:

{
  "0": {
    "unit-name": "xxxxxxxxxx",
    "machine": "easyrsa/0"
  }
}
{
  "1": {
    "unit-name": "xxxxxxxxxx",
    "machine": "etcd/0"
  }
}

外卖

解决方案说明了三个值得注意的点:

  1. to_entries 当必须使用 key/value 组合时,当事先不知道(或)感兴趣的特定键(或多个键)时,

  2. to_entries 很有用;另一种方法是使用 keys_unsorted;

  3. 将不同来源的信息汇总在一起时,美元变量很方便;

  4. jq 对函数定义的支持使得编写比其他方式更具可读性和可维护性的程序成为可能。