Skip to content

Instantly share code, notes, and snippets.

@JohnStrunk
Last active March 22, 2023 17:57
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save JohnStrunk/40ec88dea3b201da6af997dee427da90 to your computer and use it in GitHub Desktop.
Save JohnStrunk/40ec88dea3b201da6af997dee427da90 to your computer and use it in GitHub Desktop.
"Rename" a bound PVC
#! /bin/bash
set -e -o pipefail
function usage {
cat - <<USAGE
Usage:
$0 -n namespace -s source -d destination
USAGE
}
while getopts "d:hn:s:" opt; do
case ${opt} in
d)
DESTINATION_NAME="$OPTARG";;
h)
usage "$0"
exit 0;;
n)
NAMESPACE="$OPTARG";;
s)
SOURCE_NAME="$OPTARG";;
\?)
usage "$0"
exit 1;;
esac
done
shift $((OPTIND-1))
if [[ -z "$DESTINATION_NAME" || -z "$SOURCE_NAME" || -z "$NAMESPACE" ]]; then
usage "$0"
exit 1
fi
# Save source PVC
SOURCE_PVC=$(mktemp /tmp/pvc-XXXXXX.json)
kubectl -n "$NAMESPACE" get pvc "$SOURCE_NAME" -ojson > "$SOURCE_PVC"
# Create destination from source
# Strip out unneeded info & change name
DESTINATION_PVC=$(mktemp /tmp/pvc-XXXXXX.json)
jq "del(.metadata.annotations.\"pv.kubernetes.io/bind-completed\") |
del(.metadata.creationTimestamp) |
del(.metadata.finalizers[] | select(. == \"kubernetes.io/pvc-protection\")) |
del(.metadata.resourceVersion) |
del(.metadata.selfLink) |
del(.metadata.uid) |
del(.status) |
.metadata.name = \"$DESTINATION_NAME\"" \
"$SOURCE_PVC" > "$DESTINATION_PVC"
kubectl create -f "$DESTINATION_PVC"
# Set PV to retain
PV_NAME=$(jq -r .spec.volumeName "$SOURCE_PVC")
ORIG_RECLAIM=$(kubectl get pv "$PV_NAME" -ojson | jq -r .spec.persistentVolumeReclaimPolicy)
kubectl patch pv "$PV_NAME" --patch '{"spec": {"persistentVolumeReclaimPolicy": "Retain"}}'
# Delete source PVC
kubectl -n "$NAMESPACE" delete pvc "$SOURCE_NAME"
# Wait for PV to be Released
while [[ "$(kubectl get pv "$PV_NAME" -ojson | jq -r .status.phase)" != "Released" ]]; do
echo "Waiting for PV to be Released"
sleep 5
done
# Change PV to point to dest, mark available
kubectl patch pv "$PV_NAME" --type json --patch \
"[
{\"op\": \"replace\", \"path\": \"/spec/claimRef/name\", \"value\": \"$DESTINATION_NAME\"},
{\"op\": \"remove\", \"path\": \"/spec/claimRef/resourceVersion\"},
{\"op\": \"remove\", \"path\": \"/spec/claimRef/uid\"},
{\"op\": \"replace\", \"path\": \"/status.phase\", \"value\": \"Available\"},
]"
# Wait for PV to bind to new PVC
while [[ "$(kubectl -n "$NAMESPACE" get pvc "$DESTINATION_NAME" -ojson | jq -r .status.phase)" != "Bound" ]]; do
echo "Waiting for PVC to Bind"
sleep 5
done
while [[ "$(kubectl get pv "$PV_NAME" -ojson | jq -r .status.phase)" != "Bound" ]]; do
echo "Waiting for PV to Bind"
sleep 5
done
# Change PV to back to original reclaim policy
kubectl patch pv "$PV_NAME" --patch "{\"spec\": {\"persistentVolumeReclaimPolicy\": \"$ORIG_RECLAIM\"}}"
rm "$SOURCE_PVC" "$DESTINATION_PVC"
@guymguym
Copy link

guymguym commented Mar 4, 2021

nice!

@vshlapakov
Copy link

Thanks a lot, works like a charm 👍

A small addition is that the last 3 kubectl commands (2 while-s and the patch) also require a namespace parameter 👌

@JohnStrunk
Copy link
Author

Thanks for pointing that out. I updated L78 to have the namespace. The others reference PVs which aren't namespaced, so those should be ok as is.

@augusto-gtns
Copy link

tks

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment