-
-
Save krasimir/8dd6f608fc829e5e5aa9ab0136452706 to your computer and use it in GitHub Desktop.
| const spawn = require("child_process").spawn; | |
| const KEEP_AT_LEAST = 2; | |
| const CONTAINER_REGISTRIES = [ | |
| "gcr.io/<your project name>", | |
| "eu.gcr.io/<your project name>/gcf/europe-west3" | |
| ]; | |
| async function go(registry) { | |
| console.log(`> ${registry}`); | |
| const images = await command(`gcloud`, [ | |
| "container", | |
| "images", | |
| "list", | |
| `--repository=${registry}`, | |
| "--format=json", | |
| ]); | |
| for (let i = 0; i < images.length; i++) { | |
| console.log(` ${images[i].name}`); | |
| const image = images[i].name; | |
| let tags = await command(`gcloud`, [ | |
| "container", | |
| "images", | |
| "list-tags", | |
| image, | |
| "--format=json", | |
| ]); | |
| const totalImages = tags.length; | |
| // do not touch `latest` | |
| tags = tags.filter(({ tags }) => !tags.find((tag) => tag === "latest")); | |
| // sorting by date | |
| tags.sort((a, b) => { | |
| const d1 = new Date(a.timestamp.datetime); | |
| const d2 = new Date(b.timestamp.datetime); | |
| return d2.getTime() - d1.getTime(); | |
| }); | |
| // keeping at least X number of images | |
| tags = tags.filter((_, i) => i >= KEEP_AT_LEAST); | |
| console.log(` For removal: ${tags.length}/${totalImages}`); | |
| for (let j = 0; j < tags.length; j++) { | |
| console.log( | |
| ` Deleting: ${formatImageTimestamp(tags[j])} | ${tags[j].digest}` | |
| ); | |
| await command("gcloud", [ | |
| "container", | |
| "images", | |
| "delete", | |
| `${image}@${tags[j].digest}`, | |
| "--format=json", | |
| "--quiet", | |
| "--force-delete-tags", | |
| ]); | |
| } | |
| } | |
| } | |
| function command(cmd, args) { | |
| return new Promise((done, reject) => { | |
| const ps = spawn(cmd, args); | |
| let result = ""; | |
| ps.stdout.on("data", (data) => { | |
| result += data; | |
| }); | |
| ps.stderr.on("data", (data) => { | |
| result += data; | |
| }); | |
| ps.on("close", (code) => { | |
| if (code !== 0) { | |
| console.log(`process exited with code ${code}`); | |
| } | |
| try { | |
| done(JSON.parse(result)); | |
| } catch (err) { | |
| done(result); | |
| } | |
| }); | |
| }); | |
| } | |
| function formatImageTimestamp(image) { | |
| const { year, month, day, hour, minute } = image.timestamp; | |
| return `${year}-${month}-${day} ${hour}:${minute}`; | |
| } | |
| (async function () { | |
| for (let i = 0; i < CONTAINER_REGISTRIES.length; i++) { | |
| await go(CONTAINER_REGISTRIES[i]); | |
| } | |
| })(); |
@C4sse you have to run
> node delete_artifacts.js
thank you very much
i just have a question, i dont understand much of js
i have 4 buckets i would like to clear us.artifacts and keep none of the builds (const KEEP_AT_LEAST = 0;)
i have 1 storage bucket with my users images that they post i would like to keep that one untouched.
Another thing i dont need any extra set up? just inserting my project name?
As is the script written you have to amend the CONTAINER_REGISTRIES array and add what you want to clear there. At the moment KEEP_AT_LEAST constant is used for every registry so you have to change the script if you need to have different number for each item.
I have 1GB on my Container Registry, but the code didn't remove or show nothing to remove. Why is that?
@FernandoTBarros make sure that you set the correct items in CONTAINER_REGISTRIES.
I was thinking of running this script against my artifacts. One question I have though, why keep any beyond latest? When I look at the Container Registry in GCP I only see 2 entries for each container, the latest and another. Is it safe to delete the other by setting KEEP_AT_LEAST to 0? With the way the script is written with the filters in place, it seems like if I set it to 0 the filter will keep the latest and get rid of the rest. Am I incorrect?
@Jmaiers yep, you are right. I guess I wanted to have an insurance in case of latest is messed up.
@Jmaiers yep, you are right. I guess I wanted to have an insurance in case of latest is messed up.
Excellent! Thank you for the quick response
how do you use it