在 yaml 中打印密钥,以便它们可以用于 jsonpath

问题描述 投票:0回答:3
echo "apiVersion: v1
kind: Node
metadata:
  name: host-cluster-control-plane-64j47
  labels:
    beta.kubernetes.io/arch: amd64
" | yq -o p

结果:

apiVersion = v1
kind = Node
metadata.name = host-cluster-control-plane-64j47
metadata.labels.beta.kubernetes.io/arch = amd64

这几乎就是我想要的。我正在寻找获得价值的关键。

我可以像这样使用

metadata.name

echo "apiVersion: v1
kind: Node
metadata:
  name: host-cluster-control-plane-64j47
  labels:
    beta.kubernetes.io/arch: amd64
" | yq '.metadata.name'

但是如果需要,

-o p
yq
选项不会引用密钥。

我不能使用

metadata.labels.beta.kubernetes.io/arch
作为键,因为正确的语法是
metadata.labels["beta.kubernetes.io/arch"]
.

是否有一种自动获取 yaml 文件密钥的方法,以便我可以在

yq
(或
jq
)中使用这些密钥?

期望的输出是这样的:

apiVersion = v1
kind = Node
metadata.name = host-cluster-control-plane-64j47
metadata.labels["beta.kubernetes.io/arch"] = amd64

我正在寻找有效的密钥,因为我想创建第二个命令行来选择这些值。

例如:

❯ k get nodes -o yaml | yq '.items[].metadata.labels["beta.kubernetes.io/arch"]'

amd64
amd64
amd64
kubernetes jq jsonpath yq
3个回答
5
投票

您可以通过执行以下操作来接近:

yq '(.. | key | select(test("\."))) |= ("[\"" + . + "\"]")' file.yaml -op

apiVersion = v1
kind = Node
metadata.name = host-cluster-control-plane-64j47
metadata.labels.["beta.kubernetes.io/arch"] = amd64

或者你可以这样做:

yq '(.. | key | select(test("\."))) |= sub("\.", "\.")' file.yaml -op

apiVersion = v1
kind = Node
metadata.name = host-cluster-control-plane-64j47
metadata.labels.beta\\.kubernetes\\.io/arch = amd64

顺便说一句 - 我不确定它应该如何在属性文件中转义,我愿意更新 yq 以在本地完成它有人在 github 上提出了一个包含详细信息的错误...

免责声明:我写了yq


3
投票

预先警告你试图滥用半生不熟的 yq -o=props 输出但它不会做你想要的,即使它被正确实现1 因为 JSONPath 使用

\.
来转义那些点,即使这可能是 kubectl-ism,因为该语法没有记录

$ kubectl get no -o jsonpath='{.items[*].metadata.labels.beta\.kubernetes\.io/arch}'
amd64

可以对

annotations:
labels:
selector:
和您感兴趣的 kubernetes 对象中的其他自由格式键值对进行特殊处理,但可以肯定的是,它不会在一般情况下工作按照您想要的方式进行包装

对这里的

jq
表示歉意,我不知道如何在
yq
中做到这一点,当然你可以使用你喜欢的任何占位符,我只知道制表符不能出现在kubernetes注释中,也标签

$ echo '
apiVersion: v1
kind: Node
metadata:
  labels:
    beta.kubernetes.io/arch: amd64
' | yq -o=json | jq '
.metadata.labels = (
  [.metadata.labels|to_entries[]
  | {key: .key|gsub("[.]";"\t"), value}
  ]
  |from_entries)' | yq -o=p | sed -Ee 's@\\t@\\.@g'
apiVersion = v1
kind = Node
metadata.labels.beta\.kubernetes\.io/arch = amd64

fn 1: 其他人 提出了同样的问题,结果同样糟糕,我说“实施不正确”,因为

echo '{"alpha.beta":{"charlie":1}}' | yq -o=p | yq -p=p
没有往返

似乎属性库不允许转义

.
。我什至尝试偷偷摸摸地使用
beta\u002Ekubernetes
但似乎 unicode 转义处理发生在密钥词法分析之前,因此遭受相同的错误


0
投票

蟒蛇

意识到问题是

yq
,但是作为开箱即用的思维选项,可以使用python脚本打印密钥。基于
Python 3
,使用Python模块
argparse
pyyaml
,使用
pip3

安装

执行脚本:

python3 yaml_to_json.py <file>

脚本:yaml_to_json.py

import argparse
import yaml

def print_keys(data, prefix=""):
    if isinstance(data, dict):
        for key, value in data.items():
            new_prefix = f"{prefix}.{key}" if prefix else key
            if isinstance(value, dict):
                print_keys(value, new_prefix)
            elif isinstance(value, list):
                for i, item in enumerate(value):
                    print_keys(item, f"{new_prefix}[{i}]")
            else:
                if "." in key:
                    print(f'{new_prefix}["{key}"] = {value}')
                else:
                    print(f'{new_prefix} = {value}')

if __name__ == "__main__":
    parser = argparse.ArgumentParser(description="Print keys in a YAML file for JSONPath")
    parser.add_argument("yaml_file", type=str, help="path to YAML file")
    args = parser.parse_args()

    with open(args.yaml_file, "r") as f:
        data = yaml.safe_load(f)
        for key, value in data.items():
            if isinstance(value, dict):
                for k, v in value.items():
                    if isinstance(v, dict):
                        for sub_k, sub_v in v.items():
                            new_key = f"{k}[\"{sub_k}\"]"
                            print(f"metadata.{new_key} = {sub_v}")
                    else:
                        new_key = f"metadata.{k}"
                        print(f"{new_key} = {v}")
            else:
                print(f"{key} = {value}")

说明:

  • 第一个块定义了一个函数来打印将递归遍历数据的键,并以与 JSONPath 一起使用的格式打印键/值。
  • 第二个块定义了 argparse 解析器来解析文件的命令行参数。
  • 第三块打开文件,使用yaml.safe_load()加载数据,遍历数据打印键。元数据前缀被添加到键以匹配所需的输出格式。
© www.soinside.com 2019 - 2024. All rights reserved.