apps/ops-scripts/registry-usage-helper.cjs (157 lines of code) (raw):
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
/*
* Registry Usage Helper Script
* Generate ECR usage Athena queries needed for dashboard update
* * Generate athena queries for private ecr pull count by version tag
* * Generate athena queries for private ecr pull count by region
* * Query public ecr for public ecr pull count
* * Query dockerhub for dockerhub registry pull count
*/
const { writeFileSync } = require("fs");
const { execSync } = require('child_process');
const result = execSync('aws ecr describe-images --repository-name aws-for-fluent-bit --registry-id 906394416424 --output json');
const queryFromTag = "2.28.4";
const startDate = "2023-10-01T00:00:00Z";
const endDate = "2023-11-01T00:00:00Z";
const filePrefix = (new Date()).toISOString();
const description = JSON.parse(result.toString());
const tags = description.imageDetails.map(i =>
(i?.imageTags ?? [])
.filter(t => (t.charAt(0) >= '0' && t.charAt(0) <= '9'))
.filter(t => (!t.includes("-")))).flat();
const sortedTags = tags.map(t => (
{
tag: t,
semverSortable: `${t.split(".")[0].padStart(10, "0")}${t.split(".")[1].padStart(10, "0")}${t.split(".")[2].padStart(10, "0")}${(t.split(".")[0] ?? 0).padStart(10, "0")}`
}
)).sort((a,b) => a.semverSortable.localeCompare(b.semverSortable))
.map(a => a.tag);
const fromTagId = sortedTags.findIndex(t => t==queryFromTag);
const queriedTags = sortedTags.slice(fromTagId);
const ignoreTags=["stable", "latest", "windowsservercore-stable", "windowsservercore-latest", "debug"]
ignoreHash=["debug"]
const athenaQueries = queriedTags.map(searchTag => {
imgscpy = description.imageDetails.filter(i=>(i.imageTags ?? []).some(t=>(`${t}-`).includes(`${searchTag}-`)))
imgsqueryTagsRaw = imgscpy.map(c =>
c.imageTags.filter(i => !ignoreTags.some(find => i.includes(find)))).flat();
imgsqueryTags = imgsqueryTagsRaw
.map((t, idx) => ` ${(idx==0) ? "" : "OR "}requestparameters like '%"imageTag":"${t}"%'\n`);
imgsQueryHashUnprocessed = imgscpy.filter(c => c.imageTags.every(i => !ignoreHash.some(find => i.includes(find))));
imgsqueryHash = imgsQueryHashUnprocessed
.map((c, i) => ` OR requestparameters like '%${c.imageDigest.split(":")[1]}%'${(i == imgsQueryHashUnprocessed.length - 1) ? "" : "\n"}`)
return {
tag: searchTag,
query: [...imgsqueryTags, ...imgsqueryHash].flat().join(""),
};
});
const fullQuery =
`-- Combined Athena Query, Generated ${(new Date()).toLocaleString('default', {month: 'long'})} ${(new Date()).getFullYear()}, Run in classic account, us-west-2
-- Auto-generated by athena-all.js. See FireLens Datajet ops scripts for reference
-- Url: https://github.com/aws/firelens-datajet/tree/main/apps
SELECT ${
athenaQueries.map((q, i) =>
`(
SELECT COUNT(*) as call_count
FROM cloudtrail_fluentbitimage
WHERE eventsource = 'ecr.amazonaws.com'
AND eventname in ('GetDownloadUrlForLayer', 'BatchGetImage')
AND eventTime > '${startDate}'
AND eventTime < '${endDate}'
AND (
${q.query}
)
) AS call_count_v${q.tag.replaceAll(".", "_")},
`).join("")
}(
SELECT COUNT(*) as call_count
FROM cloudtrail_fluentbitimage
WHERE eventsource = 'ecr.amazonaws.com'
AND eventname in ('GetDownloadUrlForLayer', 'BatchGetImage')
AND eventTime > '${startDate}'
AND eventTime < '${endDate}'
AND (
requestparameters like '%stable%'
)
) AS call_count_stable,
(
SELECT COUNT(*) as call_count
FROM cloudtrail_fluentbitimage
WHERE eventsource = 'ecr.amazonaws.com'
AND eventname in ('GetDownloadUrlForLayer', 'BatchGetImage')
AND eventTime > '${startDate}'
AND eventTime < '${endDate}'
AND (
requestparameters like '%latest%'
)
) AS call_count_latest`;
writeFileSync(`./${filePrefix}-AthenaQuery_0_VersionTags.txt`, fullQuery);
/* Regional ecrs */
const generationMessage = `Generated ${(new Date()).toLocaleString('default', {month: 'long'})} ${(new Date()).getFullYear()}`;
const classicRegionQuery = `-- Classic Image Pulls Athena Query, ${generationMessage}, Run in classic account, us-west-2
SELECT COUNT(*) as call_count
FROM cloudtrail_fluentbitimage
WHERE
eventsource = 'ecr.amazonaws.com' AND
eventname in ('GetDownloadUrlForLayer', 'BatchGetImage') AND
eventTime > '${startDate}' AND
eventTime < '${endDate}'`
writeFileSync(`./${filePrefix}-AthenaQuery_1_Classic_906394416424_us-west-2.txt`, classicRegionQuery);
const hkgRegionQuery = `-- HKG Image Pulls Athena Query, ${generationMessage}, Run in hkg account, ap-east-1
SELECT awsRegion, COUNT(*) as call_count
FROM "cloudtrail_fluentbit"
WHERE
eventsource = 'ecr.amazonaws.com' AND
eventname in ('GetDownloadUrlForLayer', 'BatchGetImage') AND
eventTime > '${startDate}' AND
eventTime < '${endDate}'
GROUP BY
awsRegion`
writeFileSync(`./${filePrefix}-AthenaQuery_2_HKG_449074385750_ap-east-1.txt`, hkgRegionQuery);
const bahRegionQuery = `-- BAH Image Pulls Athena Query, ${generationMessage}, Run in bah account, me-south-1
SELECT awsRegion, COUNT(*) as call_count
FROM "cloudtrail_fluentbit"
WHERE
eventsource = 'ecr.amazonaws.com' AND
eventname in ('GetDownloadUrlForLayer', 'BatchGetImage') AND
eventTime > '${startDate}' AND
eventTime < '${endDate}'
GROUP BY
awsRegion`
writeFileSync(`./${filePrefix}-AthenaQuery_3_BAH_741863432321_me-south-1.txt`, bahRegionQuery);
const mxpRegionQuery = `-- MXP Image Pulls Athena Query, ${generationMessage}, Run in mxp account, us-east-1
SELECT awsRegion, COUNT(*) as call_count
FROM "cloudtrail_fluentbitimage"
WHERE
eventsource = 'ecr.amazonaws.com' AND
eventname in ('GetDownloadUrlForLayer', 'BatchGetImage') AND
eventTime > '${startDate}' AND
eventTime < '${endDate}'
GROUP BY
awsRegion`
writeFileSync(`./${filePrefix}-AthenaQuery_4_MXP_928143927712_us-east-1.txt`, mxpRegionQuery);
const cptRegionQuery = `-- CPT Image Pulls Athena Query, ${generationMessage}, Run in cpt account, us-east-1
SELECT awsRegion, COUNT(*) as call_count
FROM "cloudtrail_fluentbitimage"
WHERE
eventsource = 'ecr.amazonaws.com' AND
eventname in ('GetDownloadUrlForLayer', 'BatchGetImage') AND
eventTime > '${startDate}' AND
eventTime < '${endDate}'
GROUP BY
awsRegion`
writeFileSync(`./${filePrefix}-AthenaQuery_5_CPT_928143927712_us-east-1.txt`, cptRegionQuery);
const govRegionQuery = `-- GOV Image Pulls Athena Query, ${generationMessage}, Run in gov account, us-gov-west-1
SELECT COUNT(*) as call_count
FROM cloudtrail_fluentbitimage
WHERE
eventsource = 'ecr.amazonaws.com' AND
eventname in ('GetDownloadUrlForLayer', 'BatchGetImage') AND
eventTime > '${startDate}' AND
eventTime < '${endDate}'`
writeFileSync(`./${filePrefix}-AthenaQuery_6_GOV_928143927712_us-gov-west-1.txt`, govRegionQuery);
const publicECRTokenRaw = execSync(`curl -s -S -k https://public.ecr.aws/token/`);
const publicECRToken = JSON.parse(publicECRTokenRaw).token;
const publicECRPullCountRaw = execSync(`curl -s -S -k -H "Authorization: Bearer ${publicECRToken}" \
'https://api.us-east-1.gallery.ecr.aws/getRepositoryCatalogData' \
-H "Content-Type: application/json" --request POST \
--data '{"registryAliasName":"aws-observability","repositoryName":"aws-for-fluent-bit"}'`);
const publicECRPullCount = JSON.parse(publicECRPullCountRaw).insightData.downloadCount;
const dockerRegistryPullCountRaw = execSync(`curl -s -S -k https://hub.docker.com/v2/repositories/amazon/aws-for-fluent-bit/`)
const dockerRegistryPullCount = JSON.parse(dockerRegistryPullCountRaw).pull_count;
const enhancedGenerationMessage = `Generated ${(new Date()).toLocaleString('default', {month: 'long'})} ${(new Date()).getDate()}, ${(new Date()).getFullYear()}`;
const pullCountFile =
`## Public ECR Pull Count, ${enhancedGenerationMessage}
Public ECR aws-for-fluent-bit pull count: ${publicECRPullCount}
DockerHub pull count: ${dockerRegistryPullCount}
`;
writeFileSync(`./${filePrefix}-PublicECRPullCount.txt`, pullCountFile);