apiVersion: batch/v1 kind: Job metadata: name: plex-archlinux-migration namespace: plex labels: app.kubernetes.io/name: plex app.kubernetes.io/component: migration spec: backoffLimit: 0 template: metadata: labels: app.kubernetes.io/name: plex app.kubernetes.io/component: migration spec: restartPolicy: Never nodeSelector: kubernetes.io/hostname: arschrock tolerations: - key: node-role.kubernetes.io/control-plane operator: Exists effect: NoSchedule containers: - name: copy image: docker.io/library/alpine@sha256:28bd5fe8b56d1bd048e5babf5b10710ebe0bae67db86916198a6eec434943f8b imagePullPolicy: IfNotPresent command: - /bin/sh - -ec - | marker=/target/.archlinux-migration-complete source='/source/Plex Media Server' destination='/target/Library/Application Support/Plex Media Server' test -d "${source}" if [ -e "${marker}" ]; then echo 'Migration marker already exists; refusing to overwrite the PVC.' >&2 exit 1 fi if find /target -mindepth 1 -maxdepth 1 ! -name lost+found -print -quit | grep -q .; then echo 'The destination PVC is not empty; refusing to overwrite it.' >&2 exit 1 fi mkdir -p '/target/Library/Application Support' cp -a "${source}" '/target/Library/Application Support/' & copy_pid=$! while kill -0 "${copy_pid}" 2>/dev/null; do kill -CONT "${copy_pid}" 2>/dev/null || true sleep 0.2 kill -STOP "${copy_pid}" 2>/dev/null || true sleep 3.8 done kill -CONT "${copy_pid}" 2>/dev/null || true wait "${copy_pid}" sync -f /target source_files=$(find "${source}" -type f | wc -l) destination_files=$(find "${destination}" -type f | wc -l) source_bytes=$(find "${source}" -type f -exec stat -c '%s' {} + | awk '{ total += $1 } END { print total + 0 }') destination_bytes=$(find "${destination}" -type f -exec stat -c '%s' {} + | awk '{ total += $1 } END { print total + 0 }') test "${source_files}" = "${destination_files}" test "${source_bytes}" = "${destination_bytes}" printf 'source_files=%s\nsource_bytes=%s\n' "${source_files}" "${source_bytes}" > "${marker}" chown 964:964 /target "${marker}" echo "Copied ${source_files} files (${source_bytes} bytes)." resources: requests: cpu: 250m memory: 256Mi securityContext: allowPrivilegeEscalation: false runAsUser: 0 runAsGroup: 0 volumeMounts: - name: source mountPath: /source readOnly: true - name: target mountPath: /target volumes: - name: source hostPath: path: /var/lib/plex type: Directory - name: target persistentVolumeClaim: claimName: plex-config