Last active
March 18, 2024 15:37
-
-
Save JamesCullum/982415c460b3a94ae92c31d4a9698361 to your computer and use it in GitHub Desktop.
Gitlab doesn't have a functionality to automatically untag old images (https://gitlab.com/gitlab-org/gitlab-ce/issues/25322). You can use this script to do that for you using the API from any host with HTTP connection (doesn't require access to the server via SSH). Please be aware that you will need a separate cronjob to purge all untagged images.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
''' | |
DEVELOPMENT SPONSORED BY | |
PANASONIC INFORMATION SYSTEMS COMPANY EUROPE | |
Interested in a job? Apply below: | |
https://application.job.panasonic.eu/data/ruP0pHQvHrGZJKvL/rc.php?nav=jobsearch&custval12=ite&lang=EN&custval11=PBSEU_GER | |
''' | |
import json, sys, os | |
from urllib.parse import urlencode | |
from urllib.error import HTTPError | |
from urllib.request import urlopen, Request | |
import logging | |
logger = logging.getLogger() | |
logger.setLevel(logging.DEBUG) | |
stdoutHandler = logging.StreamHandler(sys.stdout) | |
stdoutHandler.setLevel(logging.DEBUG) | |
logger.addHandler(stdoutHandler) | |
# Config | |
GITLAB_DOMAIN = "https://gitlab.example.com" | |
AUTH_TOKEN = "ppuYp5B4v2zXDm8ZZrnp" # to use environment variable, replace with os.environ["AUTH_TOKEN"] | |
PURGE_CRITERIA = "name_regex=.*&keep_n=3&older_than=14d" # untag all images older than 14 days, but always leave the latest 3 images | |
USE_PROXY = "example.com:80" # None or hostname:port | |
# Start of code -------------------- | |
HEADERS = {"PRIVATE-TOKEN": AUTH_TOKEN} | |
API_URL = GITLAB_DOMAIN + "/api/v4" | |
# List repopsitories | |
projreq = Request( | |
API_URL + "/projects", | |
None, | |
HEADERS | |
) | |
if USE_PROXY != None: | |
projreq.set_proxy(USE_PROXY, 'http') | |
with urlopen(projreq) as projectlist: | |
json_projectlist = json.load(projectlist) | |
logger.info("Found " + str(len(json_projectlist)) + " repositories") | |
for repository in json_projectlist: | |
# List registries within repository | |
regreq = Request( | |
API_URL + "/projects/" + str(repository["id"]) + "/registry/repositories", | |
None, | |
HEADERS | |
) | |
if USE_PROXY != None: | |
regreq.set_proxy(USE_PROXY, 'http') | |
with urlopen(regreq) as reglist: | |
json_reglist = json.load(reglist) | |
logger.info(repository["name"] + ": Found " + str(len(json_reglist)) + " registries") | |
if len(json_reglist) == 0: | |
continue | |
# Run bulk delete | |
for registry in json_reglist: | |
deletereq = Request( | |
API_URL + "/projects/" + str(repository["id"]) + "/registry/repositories/" + str(registry["id"]) + "/tags", | |
PURGE_CRITERIA.encode('ascii'), | |
HEADERS, | |
method='DELETE' | |
) | |
if USE_PROXY != None: | |
deletereq.set_proxy(USE_PROXY, 'http') | |
try: | |
with urlopen(deletereq) as deleteresponse: | |
logger.debug(repository["name"] + "/" + str(registry["id"]) + ": Bulk delete successful") | |
except HTTPError as error: | |
logger.warning(repository["name"] + "/" + str(registry["id"]) + ": Bulk delete failed => " + str(error)) | |
Thanks for the hint, but no worry - just generated a random string of the same length for illustration purposes :)
Here's another variation (in bash) that traverses all the projects of a specific group
#!/usr/bin/env bash
set -e # Stop on error
# Cleanup all gitlab registry images not located in the HEAD of any of the GIT branches
# https://gitlab.com/gitlab-org/gitlab-foss/issues/20247
GROUP="mygroup"
PRIVATE_TOKEN="vewy_vewy_pwivate"
echo "--- Getting projects"
curl --silent --header "PRIVATE-TOKEN: ${PRIVATE_TOKEN}" "https://gitlab.example.com/api/v4/groups/${GROUP}/projects" | jq -r '.[]._links.self' | while read -r PROJECT_URL; do
echo "--- Getting registry repositories for '${PROJECT_URL}'"
curl --silent --header "PRIVATE-TOKEN: ${PRIVATE_TOKEN}" "${PROJECT_URL}/registry/repositories" | jq -r '.[].id' | while read -r REPOSITORY; do
echo "--- Cleaning old registry images for project '${PROJECT_URL}' (repo id ${REPOSITORY})"
curl --silent --request DELETE --data 'keep_n=5' --data 'name_regex=.*' --data 'older_than=3month' --header "PRIVATE-TOKEN: ${PRIVATE_TOKEN}" "${PROJECT_URL}/registry/repositories/${REPOSITORY}/tags"
echo "--- Done"
done
done
echo "--- Finished requesting docker image cleanup for all project of group ${GROUP}. Don't forget to run 'gitlab-ctl registry-garbage-collect -m' when the asynchronous cleanup finises to free up disk space"
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Just making sure you didn't display your auth token in line 24.