Skip to content

Instantly share code, notes, and snippets.

@gmoon
Last active February 13, 2024 13:32
Show Gist options
  • Save gmoon/c52c8b08e228c1f481f6a08e6645c9ca to your computer and use it in GitHub Desktop.
Save gmoon/c52c8b08e228c1f481f6a08e6645c9ca to your computer and use it in GitHub Desktop.
Update an s3-based Yum repo with a new package with minimal data transfer
#!/bin/bash -x
# Using s3 to host a yum repo has many advantages, but there is often
# a need to push new artifacts and update the metadata. To achieve
# this, we will mirror the s3 repo locally in a crafty way. We will
# grab the full repo metadata (in the repodata directory), but the packages
# will not be downloaded. Instead, the files will be created but will be
# EMPTY. This avoids large data sync's.
OPTIND=1
RPM_FILE=""
LOCAL_REPO=~/localrepo
REMOTE_REPO=s3://my-repo
while getopts "f:" opt; do
case "$opt" in
f) RPM_FILE=$OPTARG
;;
esac
done
shift $((OPTIND-1))
[ "$1" = "--" ] && shift
# get the architecture from the rpm file
ARCH=`rpm -qp --queryformat '%{ARCH}' $RPM_FILE`
mkdir -p $LOCAL_REPO
# sycn the repodata
aws s3 sync --exclude='*' --include 'repodata/*' $REMOTE_REPO $LOCAL_REPO
# sync the package files by name only, the files will be EMPTY
aws s3 sync --dryrun --exclude 'repodata/*' $REMOTE_REPO $LOCAL_REPO | perl -pe 's/^.* to //' | xargs -I{} install -D <(cat /dev/null) {}
# add the new package
cp --preserve $RPM_FILE $LOCAL_REPO/$ARCH/
# update the metadata. --skip-stat is needed because the package files from s3 are EMPTY
createrepo --verbose --skip-stat --update $LOCAL_REPO
# remove the EMPTY files
find $LOCAL_REPO -type f -size 0 -print0 | xargs -0 rm
# sync the changes to s3. The repodata file names are changed by createrepo, so we need to use the --delete flag
aws s3 sync --delete $LOCAL_REPO/repodata/ $REMOTE_REPO/repodata/
aws s3 sync $LOCAL_REPO $REMOTE_REPO
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment