|
#!/bin/bash |
|
|
|
# Script to clean up Google Container Registry images older than a specified number of days. |
|
# Supports a dry-run mode to simulate deletions without performing them. |
|
|
|
# Exit immediately if a command exits with a non-zero status |
|
set -e |
|
|
|
# Variables |
|
PROJECT_ID="your-gcp-project-id" # Replace with your GCP Project ID |
|
GCR_REPO="your-container-registry" # Replace with your GCR repository name, e.g., "gcr.io/project-id" |
|
OLDER_THAN_DAYS=30 # Number of days to consider for deletion |
|
|
|
# Default mode is actual deletion |
|
DRY_RUN=false |
|
|
|
# Function to display usage |
|
usage() { |
|
echo "Usage: $0 [--dry-run]" |
|
echo "" |
|
echo "Options:" |
|
echo " --dry-run Simulate deletions without removing any images." |
|
echo " -h, --help Display this help message." |
|
exit 1 |
|
} |
|
|
|
# Parse command-line arguments |
|
while [[ "$#" -gt 0 ]]; do |
|
case $1 in |
|
--dry-run) |
|
DRY_RUN=true |
|
shift |
|
;; |
|
-h|--help) |
|
usage |
|
;; |
|
*) |
|
echo "Unknown parameter passed: $1" |
|
usage |
|
;; |
|
esac |
|
done |
|
|
|
# Set the project |
|
gcloud config set project "${PROJECT_ID}" |
|
|
|
# Get the current date and calculate the cutoff date |
|
CUTOFF_DATE=$(date -d "-${OLDER_THAN_DAYS} days" +%s) |
|
|
|
# Fetch all images in the GCR repository |
|
echo "Fetching images from ${GCR_REPO}..." |
|
IMAGES=$(gcloud container images list --repository="${GCR_REPO}" --format="value(NAME)") |
|
|
|
if [[ -z "$IMAGES" ]]; then |
|
echo "No images found in the repository: ${GCR_REPO}." |
|
exit 0 |
|
fi |
|
|
|
# Iterate through each image and check tags |
|
for IMAGE in $IMAGES; do |
|
echo "Processing image: $IMAGE" |
|
|
|
# Get all tags for the image in JSON format |
|
TAGS=$(gcloud container images list-tags "$IMAGE" --format="json") |
|
|
|
if [[ "$TAGS" == "[]" ]]; then |
|
echo "No tags found for $IMAGE. Skipping..." |
|
continue |
|
fi |
|
|
|
# Process each tag |
|
echo "$TAGS" | jq -c '.[]' | while read -r TAG; do |
|
# Extract timestamp, digest, and tag name |
|
TIMESTAMP=$(echo "$TAG" | jq -r '.timestamp.datetime') |
|
DIGEST=$(echo "$TAG" | jq -r '.digest') |
|
TAG_NAME=$(echo "$TAG" | jq -r '.tags[]?') |
|
|
|
# Convert timestamp to seconds since epoch |
|
TIMESTAMP_SECONDS=$(date -d "$TIMESTAMP" +%s) |
|
|
|
# Check if the image is older than the cutoff date |
|
if [[ $TIMESTAMP_SECONDS -lt $CUTOFF_DATE ]]; then |
|
if $DRY_RUN; then |
|
echo "[Dry-Run] Would delete: $IMAGE@$DIGEST (tag: $TAG_NAME, timestamp: $TIMESTAMP)" |
|
else |
|
echo "Deleting old image: $IMAGE@$DIGEST (tag: $TAG_NAME, timestamp: $TIMESTAMP)" |
|
# Delete the specific digest |
|
gcloud container images delete "${IMAGE}@${DIGEST}" --quiet --force-delete-tags |
|
fi |
|
else |
|
echo "Skipping recent image: $IMAGE@$DIGEST (tag: $TAG_NAME, timestamp: $TIMESTAMP)" |
|
fi |
|
done |
|
done |
|
|
|
if $DRY_RUN; then |
|
echo "Dry-run completed. No images were deleted." |
|
else |
|
echo "Cleanup completed." |
|
fi |