Skip to content

Instantly share code, notes, and snippets.

@ball6847
Created June 4, 2018 16:51
Show Gist options
  • Save ball6847/645dd326b85c8278c88e2e4f534a540f to your computer and use it in GitHub Desktop.
Save ball6847/645dd326b85c8278c88e2e4f534a540f to your computer and use it in GitHub Desktop.
clear gitlab container registry image in gitlab.com ... taken from https://gitlab.com/gitlab-org/gitlab-ce/issues/25322#note_54099611
<?php
/**
* Created by: pckofstad
*/
$GITLAB_CI_TOKEN=
$REPO = "{user}/{project}
$REGISTRY_ID = 11111; // only way i found this was to inspect the calls done from the webpage
$TAGS_TO_WHITELIST = ['dev', 'master'];
$AGE_OF_CONTAINERS_TO_KEEP = '1 day'; // using php strtotime function
$BASE_URL = 'https://gitlab.com/';
$DEBUG = false;
// Variables
$FETCH_HEADER_URL = $BASE_URL . $REPO . '/container_registry';
$FETCH_TAGS_URL = $BASE_URL . $REPO . '/registry/repository/' . $REGISTRY_ID . '/tags?format=json';
$TAG_DELETE_URL = $BASE_URL . $REPO . '/registry/repository/' . $REGISTRY_ID . '/tags/';
$header = [];
// Setup header that is needed to do delete tag calls.
function setupProperHeaders()
{
global $GITLAB_CI_TOKEN, $header, $FETCH_HEADER_URL;
$ch = curl_init();
$options = [
CURLOPT_URL => $FETCH_HEADER_URL,
CURLOPT_RETURNTRANSFER => 1,
CURLOPT_HEADER => 1,
CURLOPT_HTTPHEADER => ['PRIVATE-TOKEN: ' . $GITLAB_CI_TOKEN]
];
curl_setopt_array($ch, $options);
$response = curl_exec($ch);
$header_size = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
$header_text = substr($response, 0, $header_size);
$body_text = substr($response, $header_size);
curl_close($ch);
$headers = [];
foreach (explode("\r\n", $header_text) as $i => $line) {
if ($i === 0) {
$headers['http_code'] = $line;
} else {
$data = explode(': ', $line);
if (count($data) == 2) {
list ($key, $value) = $data;
$headers[$key] = $value;
}
}
};
preg_match_all('/<meta *.*csrf-token*.* content="(.*|\n*?)" * \/>/'
, $body_text
, $regexOut
, PREG_PATTERN_ORDER
, 0);
$X_CSRF_TOKEN = $regexOut[1][0];
$COOKIE = $headers['Set-Cookie'];
$header = [
'X-CSRF-Token: ' . $X_CSRF_TOKEN,
'Accept: application/json, text/plain, */*',
'Cookie: ' . $COOKIE,
'X-Requested-With: XMLHttpRequest',
'PRIVATE-TOKEN: ' . $GITLAB_CI_TOKEN
];
}
// Wrapper for curl requests
function curlWrapper($url, $header = [], $asDeleteRequest = false)
{
global $DEBUG;
$ch = curl_init();
$options = [
CURLOPT_URL => $url,
CURLOPT_USERAGENT => 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.1.4322)',
CURLOPT_RETURNTRANSFER => 1,
CURLOPT_CONNECTTIMEOUT => 15,
CURLOPT_TIMEOUT => 5,
];
curl_setopt_array($ch, $options);
if ($asDeleteRequest) {
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "DELETE");
}
if (!empty($header)) {
curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
}
if (!empty($username)) {
curl_setopt($ch, CURLOPT_USERPWD, $username . ':' . $password);
}
$data = curl_exec($ch);
$httpcode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if (empty($data) && $DEBUG) {
$error = curl_error($ch);
$errorno = curl_errno($ch);
echo PHP_EOL . 'ERROR - ' . $error . ' --- ' . $errorno;
}
curl_close($ch);
if ($httpcode >= 200 && $httpcode < 300) {
return $data;
}
return false;
}
// taken from http://jeffreysambells.com/2012/10/25/human-readable-filesize-php
function human_filesize($bytes, $decimals = 2)
{
$size = array('B', 'kB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB');
$factor = floor((strlen($bytes) - 1) / 3);
return sprintf("%.{$decimals}f", $bytes / pow(1024, $factor)) . @$size[$factor];
}
// --- Script startes here --- //
$i = 0;
$all_tags = [];
echo PHP_EOL . "Retrieving tags";
while (true || $i > 100) {
$i += 1;
$retrived_tags = json_decode(curlWrapper($FETCH_TAGS_URL . '&page=' . $i,
['PRIVATE-TOKEN: ' . $GITLAB_CI_TOKEN]));
if (empty($retrived_tags)) {
break;
}
echo '.';
$all_tags = array_merge($all_tags, $retrived_tags);
}
if (!empty($all_tags)) {
echo PHP_EOL . "Registry list fetched " . count($all_tags) . ' found';
}
if (count($all_tags) == 0) {
echo " - Nothing found" . PHP_EOL;
return;
}
setupProperHeaders();
$newest_timestamp_to_keep = strtotime('-' . $AGE_OF_CONTAINERS_TO_KEEP);
$deletedCount = 0;
$total_size = 0;
foreach ($all_tags as $tag) {
if (empty($tag->name) || in_array($tag->name, $TAGS_TO_WHITELIST)) {
continue;
}
$tag_date = date_create_from_format('Y-m-d\TH:i:s.u+T', $tag->created_at);
$test = empty($tag->created_at) ? '' : $tag_date->getTimestamp();
if (!empty($tag->created_at) && $newest_timestamp_to_keep < $tag_date->getTimestamp()) {
continue;
}
echo PHP_EOL . "Trying to delete " . $tag->name . ' - created at ' . $tag->created_at;
$call = curlWrapper($TAG_DELETE_URL . $tag->name, $header, true);
// returns empty call if sucess, null if failed
if ($call == '') {
echo " - deleted ";
$deletedCount++;
$total_size += $tag->total_size;
}
}
if ($deletedCount == 0) {
echo PHP_EOL . PHP_EOL . "None of the tags was set to be deleted" . PHP_EOL;
} else {
echo PHP_EOL . PHP_EOL . "You deleted: " . $deletedCount . " - Cleaned up: " . human_filesize($total_size) . PHP_EOL;
}
// end for script
?>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment