#json #kubernetes #select #jq
Вопрос:
Я пытаюсь вывести значение для .metadata.name затем следует имя учащегося в массиве .spec.template.spec.containers[].students[] с использованием функции regex test() в jq.
У меня возникли проблемы с получением отдельного значения массива, так как для массива students[] не указан ключ.
Например, если я проверю массив students [], содержит ли он слово «Джефф», я хотел бы, чтобы вывод отображался, как показано ниже:
student-deployment: Jefferson
Что я пробовал:
Я попробовал команду ниже, которая несколько работает, но я не уверен, как получить только значение «Джефферсон». Приведенная ниже команда выведет все значения массива students [], что мне не нужно. Я использую Powershell для выполнения приведенной ниже команды.
kubectl get deployments -o json | jq -r '.items[] | select(.spec.template.spec.containers[].students[]?|test(""^Jeff."")) | .metadata.name, "":t"", .spec.template.spec.containers[].students'
Есть ли способ вывести конкретное значение массива с учетом условия в jq, если ключ не указан? Кроме того, будет ли решение работать при наличии нескольких развертываний?
Приведенный ниже шаблон развертывания выполнен в формате json, и я сократил его только до соответствующих частей.
{
"apiVersion": "v1",
"items": [
{
"apiVersion": "apps/v1",
"kind": "Deployment",
"metadata": {
"name": "student-deployment",
"namespace": "default"
},
"spec": {
"template": {
"spec": {
"containers": [
{
"students": [
"Alice",
"Bob",
"Peter",
"Sally",
"Jefferson"
]
}
]
}
}
}
}
]
}
Ответ №1:
Для этого подхода мы вводим переменную $pattern
. Вы можете установить его в --arg pattern
свое регулярное выражение, например "Jeff"
"^Al"
, или "e$"
отфильтровать список учащихся test
, или оставить его пустым, чтобы увидеть всех учащихся.
Теперь мы повторяем все .item[]
элементы (т. е. «все развертывания»). Для каждого найденного мы выводим содержимое .metadata.name
, за которым следует буквальное двоеточие и пробел. Затем мы повторяем все снова .spec.template.spec.containers[].students[]
, выполняем шаблон test
и объединяем результат.
Чтобы распечатать необработанные строки вместо JSON, мы используем эту -r
опцию при вызове jq
.
kubectl get deployments -o json
| jq --arg pattern "Jeff" -r '
.items[]
| .metadata.name ": " (
.spec.template.spec.containers[].students[]
| select(test($pattern))
)
'
Комментарии:
1. Спасибо! Это сработало отлично. Могу ли я узнать, можно ли добиться того же с помощью запроса JSONPath? Для моего запроса JSONPath я попытался выполнить запрос ниже:
kubectl get deployment -o=jsonpath="{range .items[?(@.spec.template.spec.containers[*].students[*])]}{'n'}{.metadata.name}{':t'}{range .spec.template.spec.containers[*]}{.students[?(@=="Alice")]}{end}{end}"
Но это работает только для оценки соответствия слов. Можно ли было бы использовать JSONPath для запроса этого, поскольку я читал, что регулярное выражение JSONPath =~ не работает?2. @calmmash Извините, я абсолютно ничего не знаю о kubernetes/kubectl и его опциях (на самом деле, в своем ответе я просто повторил ваш вызов и попросил jq выполнить дальнейшую обработку). Подумайте о том, чтобы задать новый вопрос, посвященный именно этой проблеме, чтобы привлечь внимание экспертов kubernetes/kubectl.
3. Ладно, не беспокойся. Спасибо.
Ответ №2:
Чтобы получить массив(ы) «студенты» во входных данных, вы можете использовать этот фильтр:
.items[]
| paths(objects) as $p
| getpath($p)
| select( objects | has("students") )
| .students
Затем вы можете добавить дополнительные фильтры для выбора конкретного учащегося(ов), представляющего интерес, например
| .[]
| select(test("Jeff"))
А затем добавьте любые фильтры постобработки, например
| "student-deployment: (.)"
Конечно, вы можете получить students
массив множеством других способов.