Я пытаюсь проанализировать JSON из aws ecr describe-images
и вернуть результат с определенным тегом изображения, соответствующим шаблону, из списка. В частности, я получаю массив со многими из этих записей:
{
"imageDetails": [
{
"registryId": "997652729005",
"repositoryName": "events",
"imageDigest": "sha256:5b649219a3abc5e903b27fd947f375df8634c883432a69e40d245ac2393d67b2",
"imageTags": [
"events-test-build-340"
],
"imageSizeInBytes": 314454408,
"imagePushedAt": "2021-01-12T10:42:51-05:00",
"imageScanStatus": {
"status": "COMPLETE",
"description": "The scan was completed successfully."
},
"imageScanFindingsSummary": {
"imageScanCompletedAt": "2021-01-12T10:43:00-05:00",
"vulnerabilitySourceUpdatedAt": "2021-01-12T04:45:25-05:00",
"findingSeverityCounts": {}
},
"imageManifestMediaType": "application/vnd.docker.distribution.manifest.v2+json",
"artifactMediaType": "application/vnd.docker.container.image.v1+json"
},
{
"registryId": "997652729005",
"repositoryName": "events",
"imageDigest": "sha256:0fae259bcfe02c8cf0ec3746aae668b3166960e7119467496df9aedfbc2c8c5b",
"imageTags": [
"6debaabc26cc82a4011ea9c71854cebac7a57250-433",
"6debaabc26cc82a4011ea9c71854cebac7a57250",
"6debaabc26cc82a4011ea9c71854cebac7a57250-433-dev",
"events-prod-build-433"
],
"imageSizeInBytes": 316110570,
"imagePushedAt": "2020-12-21T03:11:52-05:00",
"imageScanStatus": {
"status": "COMPLETE",
"description": "The scan was completed successfully."
},
"imageScanFindingsSummary": {
"imageScanCompletedAt": "2020-12-21T03:12:02-05:00",
"vulnerabilitySourceUpdatedAt": "2020-11-03T20:21:09-05:00",
"findingSeverityCounts": {}
},
"imageManifestMediaType": "application/vnd.docker.distribution.manifest.v2+json",
"artifactMediaType": "application/vnd.docker.container.image.v1+json"
}
]
}
Я хотел бы, чтобы вывод был примерно таким:
{
"tag": [
"6debaabc26cc82a4011ea9c71854cebac7a57250"
],
"sha": "sha256:5b649219a3abc5e903b27fd947f375df8634c883432a69e40d245ac2393d67b2",
"imagePushedAt": "2021-01-12T10:42:51-05:00"
}
Задача состоит в том, чтобы выбрать изображения с тегом, имя которого включает *prod-build*
(развернутая производственная сборка), но затем вернуть тег без тире, который мы фактически используем. (Да, это совсем ущербно, я знаю).
Я продвинулся довольно далеко:
cat ecr-describe-images-events.json
| jq '.imageDetails[]
| {tag: .imageTags, sha: .imageDigest, date_pushed: .imagePushedAt}
| select( .tag | contains(["prod-build"]))
.tag[] |= walk(
if type= = "string" then
select(
match("^[^-]+$")
)
else
null
end
)'
Итак, из массива imageDetails
получаем и именуем элементы, затем из массива тегов выбираем узлы, у которых есть тег со строкой prod-build
. Из этих узлов найдитеtags
элемент массива, имя которого не содержит тире, и вернуть его.
Последняя часть, которую я сделал с select
, walk
и match
, ведет себя иначе, чем я ожидал. Я осознаю:
{
"tag": [
"events-test-build-340"
],
"sha": "sha256:5b649219a3abc5e903b27fd947f375df8634c883432a69e40d245ac2393d67b2",
"date_pushed": "2021-01-12T10:42:51-05:00"
}
{
"tag": [
"6debaabc26cc82a4011ea9c71854cebac7a57250",
"events-prod-build-433",
null,
null
],
"sha": "sha256:8638389b7d83869b17b1c74ff30740d7cf8eff4574100c1270f20d4686252552",
"date_pushed": "2021-02-17T13:11:42-05:00"
}
Если я не включу последнюю часть, начиная walk(...)
я получаю правильные узлы. Но когда я использую walk
с совпадением или тестом, я возвращаю элементы массива, которые не соответствуют моему регулярному выражению.
Я не зациклен на своем подходе или формате вывода: мне просто нужны три поля в какой-то структуре. Что я не понял?
Кажется, вы хотите s.t. нравиться:
jq '.imageDetails[]
| {tag: .imageTags, sha: .imageDigest, date_pushed: .imagePushedAt}
| select( any(.tag[]; test("prod-build")?))
| .tag |= map(select(test("^[^-]+$")? ))'
Вам придется настроить это, если вы хотите избежать выбора каких-либо объектов, для которых .tag в противном случае был бы пустым массивом.
Вот вариант использования contains
для обеих проверок, при этом вторая проверка отрицается с помощью not
:
jq '.imageDetails[] | select(.imageTags | any(contains("prod-build"))) | {
tag: .imageTags | map(select(contains("-") | not)),
sha: .imageDigest,
date_pushed: .imagePushedAt
}'
{
"tag": [
"6debaabc26cc82a4011ea9c71854cebac7a57250"
],
"sha": "sha256:0fae259bcfe02c8cf0ec3746aae668b3166960e7119467496df9aedfbc2c8c5b",
"date_pushed": "2020-12-21T03:11:52-05:00"
}
Вы можете использовать del
, чтобы удалить все теги, соответствующие определенному критерию:
.imageDetails[]
| {
tag: .imageTags,
sha: .imageDigest,
date_pushed: .imagePushedAt
}
| select(.tag | contains(["prod-build"]))
| del(.tag[] | select(contains("-")))
Сначала выбирает те объекты с тегом "prod-build", а затем удаляет все остальные теги из списка.
Выход:
{
"tag": [
"6debaabc26cc82a4011ea9c71854cebac7a57250"
],
"sha": "sha256:0fae259bcfe02c8cf0ec3746aae668b3166960e7119467496df9aedfbc2c8c5b",
"date_pushed": "2020-12-21T03:11:52-05:00"
}
Все хорошие ответы; ваш выигрывает как самый простой и читаемый. Спасибо!