#!/bin/bash -e
# This script is used to migrate all the repos, artifacts, users and permissions to the new artifactory.
# I make no promises if this runs properly or not, I guess I'm more using this as documentation. Some commands may require manual intervention.
# This assumes you have used `jfrog c add` and have the `artifactory-prod1` and `artifactory-aws`
# Use a PASSWORD for AWS, NOT an API key. The API key will be destroyed by importing access.
# as well as kubectl access to prod1 and dev-aws via the `prod1` and `dev-aws` contexts

function log() {
    echo -ne '\033[0;36m'
    echo -n "$@"
    echo -e '\033[0m'
}

function jfrogrtcl() {
    # stupid dumb workaround for dns flakiness
    # i would check for curl return code 6, but the jfrog cli swallows the return code and returns 1 regardless
    # so here's a horrible jank solution
    for _ in {1..3}; do
        failed=0
        jfrog rt cl "$@" || failed=1
        if [[ $failed -eq 0 ]]; then return; fi
    done
    return 1
}

mkdir -p /tmp/artifactory-migration
cd /tmp/artifactory-migration

log Exporting access data from prod1
kubectl --context prod1 port-forward -n artifactory artifactory-ha-artifactory-ha-primary-0 8081 &
sleep 2
read -sp "Enter prod1 access-admin password: " ACCESS_ADMIN_PASS
curl "-uaccess-admin:$ACCESS_ADMIN_PASS" -XPOST "http://localhost:8081/access/api/v1/system/backup/export" -v
sleep 1
kill %1

ACCESS_BACKUP_FILENAME=$(kubectl --context prod1 exec -n artifactory artifactory-ha-artifactory-ha-primary-0 -c artifactory-ha -- ls -t /opt/jfrog/artifactory/access/backup|head -n1)
log Access filename is $ACCESS_BACKUP_FILENAME
kubectl --context prod1 cp -n artifactory "artifactory-ha-artifactory-ha-primary-0:/opt/jfrog/artifactory/access/backup/$ACCESS_BACKUP_FILENAME" '/tmp/artifactory-migration/access.backup.json'

PROD1_SERVER_ID=$(jfrogrtcl --server-id artifactory-prod1 /api/system/service_id)
AWS_SERVER_ID=$(jfrogrtcl --server-id artifactory-aws /api/system/service_id)
log Replacing server ID $PROD1_SERVER_ID with $AWS_SERVER_ID
sed -i "s/$PROD1_SERVER_ID/$AWS_SERVER_ID/g" /tmp/artifactory-migration/access.backup.json

kubectl --context dev-aws cp -n artifactory '/tmp/artifactory-migration/access.backup.json' 'artifactory-artifactory-ha-primary-0:/opt/jfrog/artifactory/var/etc/access/access.bootstrap.json'
log Importing access configuration
# we need a token to import access in artifactory 7, username/pass don't work
read -p "Go to the AWS artifactory and create an admin token, then paste it here (a expiry of 1 hour should be fine): " AWS_ADMIN_ACCESS_TOKEN
kubectl --context dev-aws port-forward -n artifactory artifactory-artifactory-ha-primary-0 8082 &
sleep 2
curl -H "Authorization: Bearer $AWS_ADMIN_ACCESS_TOKEN" -XPOST "http://localhost:8082/access/api/v1/system/backup/import" -v
sleep 1
kill %1
log Access import succeeded
rm /tmp/artifactory-migration/access.backup.json
log Artifactory should restart, so waiting a minute for good measure...
sleep 60

log Restart mission control for good measure
kubectl --context dev-aws delete pod -n artifactory artifactory-mission-control-{0..2}

log You need to relogin to Artifactory.
jfrog c edit artifactory-aws

log Exporting and importing list of repos. Will attempt to patch the repo which may result in 404s, this is fine
REPOS=$(jfrogrtcl --server-id artifactory-prod1 /api/repositories -s |jq -r '.[].key')
for i in $REPOS; do
    jfrogrtcl --server-id artifactory-prod1 "/api/repositories/$i" -s --fail-with-body > $i.json
    if ! jfrogrtcl --server-id artifactory-aws "/api/repositories/$i" -XPOST -s -H 'Content-Type: application/json' --upload-file $i.json --fail-with-body; then
        log "Repo doesn't currently exist, creating"
        jfrogrtcl --server-id artifactory-aws "/api/repositories/$i" -XPUT -s -H 'Content-Type: application/json' --upload-file $i.json --fail-with-body
        log Successfully created repo
    fi
done

log Setting up replication from prod1 to aws
LOCAL_REPOS=$(jfrogrtcl --server-id artifactory-prod1 /api/repositories |jq -r '.[]|select(.type == "LOCAL")|.key')
RPLC_TEMPLATE='{"cronExp":"0 0 12 * * ?","enableEventReplication":"true","repoKey":"${repo}","serverId":"artifactory-aws","syncDeletes":"true","syncProperties":"true","syncStatistics":"true","targetRepoKey":"${repo}","enabled":"true","socketTimeoutMillis":"600000"}'
echo "$RPLC_TEMPLATE" > replication-template.json
for i in $LOCAL_REPOS; do
    jfrog rt rplc --server-id artifactory-prod1 --vars "repo=$i" replication-template.json
    log Setup for $i
done

LOCAL_REPOS=$(jfrogrtcl --server-id artifactory-prod1 /api/repositories |jq -r '.[]|select(.type == "LOCAL")|.key')
log Triggering all replications
for i in $LOCAL_REPOS; do
    jfrogrtcl --server-id artifactory-prod1 -XPOST /api/replication/execute/$i
done
echo $LOCAL_REPOS > remaining

log Waiting for everything to finish replicating and keep retrying failed attempts
while [[ ! -z $(cat remaining) ]]; do
    date
    RESULT=$(for i in `cat remaining`; do echo -n "$i "; jfrog rt cl /api/replication/$i -s | jq '.status'; done | tee /dev/fd/2)
    ERRORS=$(echo "$RESULT" | grep error | cut -d ' ' -f 1)
    REMAINING=$(echo "$RESULT" | grep -v '"ok"' | cut -d ' ' -f 1)
    for repo in $ERRORS; do
        jfrogrtcl --server-id artifactory-prod1 -XPOST /api/replication/execute/$repo
    done
    echo "$REMAINING" > remaining
    sleep 30
done

log "We're done!"
cd -
rm -rf /tmp/artifactory-migration
