TABLE OF CONTENTS


Prerequisites


  • KCP admin account with Kublr username/password authentication.
    In case an external authentication provider is used for all accounts including the Kublr admin, the scripts may have to be modified to acquire token in the ID provider specific way.
  • Linux
  • bash
  • curl
  • jq 


Data Export


Use kublr-export.sh to export KCP objects (spaces, secrets, clusters, roles, etc) and save them locally in files in json format.


Data Import


Use kublr-import.sh to import KCP objects (spaces, secrets, clusters, roles, etc) previously exported by kublr-export.sh script.


The script runs in a dry-run mode by default.

Environment variable IMPORT must be set to true for the script to actually modify data in the KCP.

It is safe to run the script in a dry run mode to review modifications to be made.


The script does not import deleted clusters


The script does not modify objects with the same name that already exist.


Scripts


kublr-export.sh


Create kublr-export.sh file and paste the following code there.

Change the file mode to exec: chmod a+x kublr-export.sh


The script requires that environment variables KCP_URL, KCP_USERNAME, and KCP_PASSWORD are set so that the script can access the KCP.


Run script: ./kublr-export.sh


The script will download all KCP objects (spaces, secrets, clusters, roles, etc) and save them locally in files in json format:

  • kublr-space.json
  • kublr-globalrole.json

  • kublr-globalrolebinding.json

  • kublr-cluster-<space>.json

  • kublr-secret-<space>.json

  • kublr-spacerole-<space>.json

  • kublr-spacerolebinding-<space>.json


#!/bin/bash

set -e

if [ -z "${KCP_URL}" ] ; then
    echo "ERROR: KCP_URL environment variable is not defined"
    exit 1
fi

if [ -z "${KCP_USERNAME}" ] ; then
    echo "ERROR: KCP_USERNAME environment variable is not defined"
    exit 1
fi

if [ -z "${KCP_PASSWORD}" ] ; then
    echo "ERROR: KCP_PASSWORD environment variable is not defined"
    exit 1
fi

function exportRes() {
    local URL="${1}"
    local FILE="${2}"
    curl -ksSf -H "Authorization: Bearer ${TOKEN}" -XGET "${URL}" > "tmp-${FILE}" &&
        mv "tmp-${FILE}" "${FILE}" || { rm -rf "tmp-${FILE}" ; return 1 ; }
}

eval "$(curl -s -k \
    -d "grant_type=password" \
    -d "scope=openid" \
    -d "client_id=kublr-ui" \
    -d "username=${KCP_USERNAME}" \
    -d "password=${KCP_PASSWORD}" \
    "${KCP_URL}/auth/realms/kublr-ui/protocol/openid-connect/token" | \
    jq -r '"REFRESH_TOKEN="+.refresh_token,"TOKEN="+.access_token,"ID_TOKEN="+.id_token')"

# This is to workaround Kublr 1.20.0 and 1.20.1 issue with the token validity window.
# This delay can be removed for any other version of Kublr.
sleep 3

echo "Exporting global objects"

exportRes "${KCP_URL}/api/space" "kublr-space.json"
echo "Exported spaces: $(jq '.total' kublr-space.json)"

exportRes "${KCP_URL}/api/globalrole" "kublr-globalrole.json"
echo "Exported globalroles: $(jq '.total' kublr-globalrole.json)"

exportRes "${KCP_URL}/api/globalrolebinding" "kublr-globalrolebinding.json"
echo "Exported globalrolebindings: $(jq '.total' kublr-globalrolebinding.json)"

for S in $(jq -r '.items[].metadata.name' kublr-space.json) ; do
    echo "Exporting space '${S}'"

    exportRes "${KCP_URL}/api/spaces/${S}/secret" "kublr-secret-${S}.json"
    echo "  Exported secrets: $(jq '.total' "kublr-secret-${S}.json")"

    exportRes "${KCP_URL}/api/spaces/${S}/cluster" "kublr-cluster-${S}.json"
    echo "  Exported clusters: $(jq '.total' "kublr-cluster-${S}.json")"

    exportRes "${KCP_URL}/api/spaces/${S}/spacerole" "kublr-spacerole-${S}.json"
    echo "  Exported spaceroles: $(jq '.total' "kublr-spacerole-${S}.json")"

    exportRes "${KCP_URL}/api/spaces/${S}/spacerolebinding" "kublr-spacerolebinding-${S}.json"
    echo "  Exported spacerolebindings: $(jq '.total' "kublr-spacerolebinding-${S}.json")"
done


kublr-import.sh


Create kublr-import.sh file and paste the following code there.

Change the file mode to exec: chmod a+x kublr-import.sh


The script requires that environment variables KCP_URL, KCP_USERNAME, and KCP_PASSWORD are set so that the script can access the KCP.


The script expects previous kublr-export.sh script output files in the current directory.


Run script (dry run mode): ./kublr-import.sh


Run script (real import): IMPORT=true ./kublr-import.sh


#!/bin/bash

set -e

if [ -z "${KCP_URL}" ] ; then
    echo "ERROR: KCP_URL environment variable is not defined"
    exit 1
fi

if [ -z "${KCP_USERNAME}" ] ; then
    echo "ERROR: KCP_USERNAME environment variable is not defined"
    exit 1
fi

if [ -z "${KCP_PASSWORD}" ] ; then
    echo "ERROR: KCP_PASSWORD environment variable is not defined"
    exit 1
fi

if [ "${IMPORT}" != "true" ]; then
    echo "IMPORT is not set to 'true', the script will run in a dry run mode"
    DRY_RUN_MSG="; dry run"
else
    DRY_RUN_MSG=""
fi

function importRes() {
    local URL="${1}"
    local FILE="${2}"

    for I in $(jq -r 'range(.items | length)' "${FILE}") ; do
        local N="$(jq -r '.items[$ind].metadata.name' --argjson ind "${I}" "${FILE}")"
        local DEL="$(jq -r '.items[$ind].deleted' --argjson ind "${I}" "${FILE}")"
        if [ "${DEL}" == "true" ]; then
            echo "    Deleted==true for '${N}'; ignoring"
            continue
        fi
        local RESP="$(curl -ksSf -H "Authorization: Bearer ${TOKEN}" \
            -I -XGET -o /dev/null -w '%{http_code}' "${URL}/${N}" 2>/dev/null || true)"
        if [ "${RESP}" == "404" ]; then
            echo "    Importing '${N}'${DRY_RUN_MSG}"
            if [ "${IMPORT}" == "true" ]; then
                jq '.items[$ind] | del(.id)' --argjson ind "${I}" "${FILE}" | \
                    curl -ksSf -H "Authorization: Bearer ${TOKEN}" -H 'content-type: application/json' \
                        -XPOST --data-binary '@-' "${URL}" > /dev/null || return 1
            fi
        elif [ "${RESP:0:1}" == "2" ]; then
            echo "    Exists '${N}'; skip"
        else
            echo "    Unexpected response code '${RESP}' for '${N}'; ERROR"
            return 1
        fi
    done
}

eval "$(curl -s -k \
    -d "grant_type=password" \
    -d "scope=openid" \
    -d "client_id=kublr-ui" \
    -d "username=${KCP_USERNAME}" \
    -d "password=${KCP_PASSWORD}" \
    "${KCP_URL}/auth/realms/kublr-ui/protocol/openid-connect/token" | \
    jq -r '"REFRESH_TOKEN="+.refresh_token,"TOKEN="+.access_token,"ID_TOKEN="+.id_token')"

# This is to workaround Kublr 1.20.0 and 1.20.1 issue with the token validity window.
# This delay can be removed for any other version of Kublr.
sleep 3

echo "Importing spaces"
importRes "${KCP_URL}/api/space" "kublr-space.json"

echo "Importing globalroles"
importRes "${KCP_URL}/api/globalrole" "kublr-globalrole.json"

echo "Importing globalrolebindings"
importRes "${KCP_URL}/api/globalrolebinding" "kublr-globalrolebinding.json"

for S in $(jq -r '.items[].metadata.name' kublr-space.json) ; do
    echo "Importing space '${S}'"

    echo "  Importing secrets"
    importRes "${KCP_URL}/api/spaces/${S}/secret" "kublr-secret-${S}.json"

    echo "  Importing clusters"
    importRes "${KCP_URL}/api/spaces/${S}/cluster" "kublr-cluster-${S}.json"

    echo "  Importing spaceroles"
    importRes "${KCP_URL}/api/spaces/${S}/spacerole" "kublr-spacerole-${S}.json"

    echo "  Importing spacerolebindings"
    importRes "${KCP_URL}/api/spaces/${S}/spacerolebinding" "kublr-spacerolebinding-${S}.json"
done