Cirrus: Print images that should be pruned

Over time unless they're removed, the project could grow quite a large
collection of VM images.  While generally cheap (less than a penny each,
per month), these will become a significant cost item if not kept
in-check.

Add a specialized container for handling image-pruning, but limit
it to only finding and printing (not actually deleting) images.

Also update the image-building workflow so that base-images used to
compose cache-images are also labeled with metadata.

N/B: As an additional safeguard, the service account which
     executes the new container in production *DOES NOT*
     have access to delete images.  This can be enabled
     by adding the GCE IAM role: CustomComputeImagePrune

Signed-off-by: Chris Evich <cevich@redhat.com>
This commit is contained in:
Chris Evich
2019-06-14 13:28:47 -04:00
parent 547cb4e55e
commit e8564dc44f
8 changed files with 207 additions and 39 deletions

View File

@ -7,14 +7,14 @@ RUN yum -y update && \
yum -y install google-cloud-sdk && \
yum clean all
COPY /contrib/imgts/entrypoint.sh /usr/local/bin/entrypoint.sh
ENV GCPJSON="__unknown__" \
GCPNAME="__unknown__" \
GCPPROJECT="__unknown__" \
IMGNAMES="__unknown__" \
TIMESTAMP="__unknown__" \
BUILDID="__unknown__" \
REPOREF="__unknown__"
COPY ["/contrib/imgts/entrypoint.sh", "/contrib/imgts/lib_entrypoint.sh", "/usr/local/bin/"]
RUN chmod 755 /usr/local/bin/entrypoint.sh
ENTRYPOINT ["/usr/local/bin/entrypoint.sh"]

View File

@ -2,45 +2,22 @@
set -e
RED="\e[1;36;41m"
YEL="\e[1;33;44m"
NOR="\e[0m"
source /usr/local/bin/lib_entrypoint.sh
die() {
echo -e "$2" >&2
exit "$1"
}
req_env_var GCPJSON GCPNAME GCPPROJECT IMGNAMES BUILDID REPOREF
SENTINEL="__unknown__" # default set in dockerfile
gcloud_init
[[ "$GCPJSON" != "$SENTINEL" ]] || \
die 1 "Must specify service account JSON in \$GCPJSON"
[[ "$GCPNAME" != "$SENTINEL" ]] || \
die 2 "Must specify service account name in \$GCPNAME"
[[ "$GCPPROJECT" != "$SENTINEL" ]] || \
die 4 "Must specify GCP Project ID in \$GCPPROJECT"
[[ -n "$GCPPROJECT" ]] || \
die 5 "Must specify non-empty GCP Project ID in \$GCPPROJECT"
[[ "$IMGNAMES" != "$SENTINEL" ]] || \
die 6 "Must specify space separated list of GCE image names in \$IMGNAMES"
[[ "$BUILDID" != "$SENTINEL" ]] || \
die 7 "Must specify the number of current build in \$BUILDID"
[[ "$REPOREF" != "$SENTINEL" ]] || \
die 8 "Must specify a PR number or Branch name in \$REPOREF"
ARGS="
--update-labels=last-used=$(date +%s)
--update-labels=build-id=$BUILDID
--update-labels=repo-ref=$REPOREF
--update-labels=project=$GCPPROJECT
"
ARGS="--update-labels=last-used=$(date +%s)"
# optional
[[ -z "$BUILDID" ]] || ARGS="$ARGS --update-labels=build-id=$BUILDID"
[[ -z "$REPOREF" ]] || ARGS="$ARGS --update-labels=repo-ref=$REPOREF"
[[ -z "$GCPPROJECT" ]] || ARGS="$ARGS --update-labels=project=$GCPPROJECT"
gcloud config set account "$GCPNAME"
gcloud config set project "$GCPPROJECT"
echo "$GCPJSON" > /tmp/gcp.json
gcloud auth activate-service-account --key-file=/tmp/gcp.json || rm /tmp/gcp.json
for image in $IMGNAMES
do
gcloud compute images update "$image" $ARGS &
$GCLOUD compute images update "$image" $ARGS &
done
set +e # Actual update failures are only warnings
wait || die 0 "${RED}WARNING:$NOR ${YEL}Failed to update labels on one or more images:$NOR '$IMGNAMES'"
wait || echo "Warning: No \$IMGNAMES were specified."

View File

@ -0,0 +1,44 @@
#!/bin/bash
set -e
RED="\e[1;36;41m"
YEL="\e[1;33;44m"
NOR="\e[0m"
SENTINEL="__unknown__" # default set in dockerfile
# Disable all input prompts
# https://cloud.google.com/sdk/docs/scripting-gcloud
GCLOUD="gcloud --quiet"
die() {
EXIT=$1
PFX=$2
shift 2
MSG="$@"
echo -e "${RED}${PFX}:${NOR} ${YEL}$MSG${NOR}"
[[ "$EXIT" -eq "0" ]] || exit "$EXIT"
}
# Pass in a list of one or more envariable names; exit non-zero with
# helpful error message if any value is empty
req_env_var() {
for i; do
if [[ -z "${!i}" ]]
then
die 1 FATAL entrypoint.sh requires \$$i to be non-empty.
elif [[ "${!i}" == "$SENTINEL" ]]
then
die 2 FATAL entrypoint.sh requires \$$i to be explicitly set.
fi
done
}
gcloud_init() {
set +xe
TMPF=$(mktemp -p '' .$(uuidgen)XXXX)
trap "rm -f $TMPF" EXIT
echo "$GCPJSON" > $TMPF && \
$GCLOUD auth activate-service-account --project "$GCPPROJECT" --key-file=$TMPF || \
die 5 FATAL auth
rm -f $TMPF
}