Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update procedure for Che v7.41 and earlier #2269

Merged
merged 9 commits into from
Apr 11, 2022
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions antora.yml
Original file line number Diff line number Diff line change
Expand Up @@ -64,15 +64,26 @@ asciidoc:
prod-cli: chectl
prod-deployment: che
prod-docs-url: https://www.eclipse.org/che/docs
prod-docs-url-backup-recovery: link:https://www.eclipse.org/che/docs/che-7/administration-guide/backup-and-recovery/[Backup and recovery]
prod-docs-url-enable-oauth: link:https://www.eclipse.org/che/docs/che-7/administration-guide/configuring-openshift-oauth/[Configuring OpenShift OAuth]
prod-first-version-using-dwo: v7.42
l0rd marked this conversation as resolved.
Show resolved Hide resolved
prod-home: /home/user
prod-host: che-host
prod-id-short: che
prod-id: eclipse-che
prod-last-version-pre-dwo: v7.41
prod-namespace: eclipse-che
prod-next-channel: next
prod-next-channel-catalog-source: eclipse-che-openshift-catalog-next
prod-next-channel-catalog-source-image: quay.io/eclipse/eclipse-che-openshift-opm-catalog:next
prod-next-channel-package: eclipse-che-preview-openshift
l0rd marked this conversation as resolved.
Show resolved Hide resolved
prod-operator-image-name: che-operator
prod-operator: che-operator
prod-prev-ver: "previous minor version"
prod-short: Che
prod-stable-channel: stable
prod-stable-channel-catalog-source: community-operators
prod-stable-channel-package: eclipse-che
prod-upstream: Eclipse{nbsp}Che
prod-url: "https://__<che_fqdn>__"
prod-ver-major: "7"
Expand Down
98 changes: 98 additions & 0 deletions modules/administration-guide/attachments/migration/1-prepare.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
#!/bin/bash
set -e

K8S_CLI=${K8S_CLI:-oc} # {orch-cli}
PRODUCT_DEPLOYMENT_NAME=${PRODUCT_DEPLOYMENT_NAME:-che} # {prod-deployment}
PRODUCT_ID=${PRODUCT_ID:-eclipse-che} # {prod-id}
INSTALLATION_NAMESPACE=${INSTALLATION_NAMESPACE:-eclipse-che} # {prod-namespace}
CHE_CLUSTER_CR_NAME=${CHE_CLUSTER_CR_NAME:-eclipse-che} # {prod-checluster}
IDENTITY_PROVIDER_DEPLOYMENT_NAME=${IDENTITY_PROVIDER_DEPLOYMENT_NAME:-keycloak} # {identity-provider-id}

ALL_USERS_DUMP="${PRODUCT_ID}"-users.txt
DB_DUMP="${PRODUCT_ID}"-db.sql

echo "[INFO] Getting identity provider information"

IDENTITY_PROVIDER_URL=$("${K8S_CLI}" get checluster "${CHE_CLUSTER_CR_NAME}" -n "${INSTALLATION_NAMESPACE}" -o jsonpath="{.status.keycloakURL}" )
IDENTITY_PROVIDER_SECRET=$("${K8S_CLI}" get checluster/"${CHE_CLUSTER_CR_NAME}" -n "${INSTALLATION_NAMESPACE}" -o jsonpath="{.spec.auth.identityProviderSecret}")
IDENTITY_PROVIDER_PASSWORD=$(if [ -z "${IDENTITY_PROVIDER_SECRET}" ] || [ "${IDENTITY_PROVIDER_SECRET}" == "null" ]; then "${K8S_CLI}" get checluster/"${CHE_CLUSTER_CR_NAME}" -n "${INSTALLATION_NAMESPACE}" -o jsonpath="{.spec.auth.identityProviderPassword}"; else "${K8S_CLI}" get secret "${IDENTITY_PROVIDER_SECRET}" -n "${INSTALLATION_NAMESPACE}" -o jsonpath="{.data.password}" | base64 -d; fi)
IDENTITY_PROVIDER_USERNAME=$(if [ -z "${IDENTITY_PROVIDER_SECRET}" ] || [ "${IDENTITY_PROVIDER_SECRET}" == "null" ]; then "${K8S_CLI}" get checluster/"${CHE_CLUSTER_CR_NAME}" -n "${INSTALLATION_NAMESPACE}" -o jsonpath="{.spec.auth.IdentityProviderAdminUserName}"; else "${K8S_CLI}" get secret "${IDENTITY_PROVIDER_SECRET}" -n "${INSTALLATION_NAMESPACE}" -o jsonpath="{.data.user}" | base64 -d; fi)
IDENTITY_PROVIDER_REALM=$("${K8S_CLI}" get checluster "${CHE_CLUSTER_CR_NAME}" -n "${INSTALLATION_NAMESPACE}" -o jsonpath="{.spec.auth.identityProviderRealm}")

echo "[INFO] IDENTITY_PROVIDER_URL: ${IDENTITY_PROVIDER_URL}"
echo "[INFO] IDENTITY_PROVIDER_SECRET: ${IDENTITY_PROVIDER_SECRET}"
echo "[INFO] IDENTITY_PROVIDER_USERNAME: ${IDENTITY_PROVIDER_USERNAME}"
echo "[INFO] IDENTITY_PROVIDER_REALM: ${IDENTITY_PROVIDER_REALM}"

refreshToken() {
echo "[INFO] Refreshing identity provier token"
IDENTITY_PROVIDER_TOKEN=$(curl -ks \
-d "client_id=admin-cli" \
-d "username=${IDENTITY_PROVIDER_USERNAME}" \
-d "password=${IDENTITY_PROVIDER_PASSWORD}" \
-d "grant_type=password" \
"${IDENTITY_PROVIDER_URL}/realms/master/protocol/openid-connect/token" | jq -r ".access_token")
}

scaleDownCheServer() {
echo "[INFO] Scaling down ${PRODUCT_DEPLOYMENT_NAME}"
"${K8S_CLI}" scale deployment "${PRODUCT_DEPLOYMENT_NAME}" --replicas=0 -n "${INSTALLATION_NAMESPACE}"
}

scaleDownKeycloak() {
echo "[INFO] Scaling down ${IDENTITY_PROVIDER_DEPLOYMENT_NAME}"
"${K8S_CLI}" scale deployment "${IDENTITY_PROVIDER_DEPLOYMENT_NAME}" --replicas=0 -n "${INSTALLATION_NAMESPACE}"
}

getUsers() {
rm -f "${ALL_USERS_DUMP}"
refreshToken
echo "[INFO] Dumping users list in file ${ALL_USERS_DUMP}"
ALL_USERS=$(curl -ks -H "Authorization: bearer ${IDENTITY_PROVIDER_TOKEN}" "${IDENTITY_PROVIDER_URL}/${IDENTITY_PROVIDER_USERNAME}/realms/${IDENTITY_PROVIDER_REALM}/users")
ALL_USERS_IDS=($(echo "${ALL_USERS}" | jq ".[] | .id" | tr "\r\n" " "))

for USER_ID in "${ALL_USERS_IDS[@]}"; do
refreshToken

USER_ID=$(echo "${USER_ID}" | tr -d "\"")
FEDERATED_IDENTITY=$(curl -ks -H "Authorization: bearer ${IDENTITY_PROVIDER_TOKEN}" "${IDENTITY_PROVIDER_URL}/${IDENTITY_PROVIDER_USERNAME}/realms/${IDENTITY_PROVIDER_REALM}/users/${USER_ID}/federated-identity")
IDENTITY_PROVIDER=$(echo "${FEDERATED_IDENTITY}" | jq -r ".[] | select(.identityProvider == \"openshift-v4\")")
if [ -n "${IDENTITY_PROVIDER}" ]; then
USER_PROFILE=$(echo "${ALL_USERS}" | jq -r ".[] | select(.id == \"${USER_ID}\")")
USER_EMAIL=$(echo "${USER_PROFILE}" | jq -r ".email")
USER_NAME=$(echo "${USER_PROFILE}" | jq -r ".username")
USER_FIRST_NAME=$(echo "${USER_PROFILE}" | jq -r ".firstName")
USER_LAST_NAME=$(echo "${USER_PROFILE}" | jq -r ".lastName")

OPENSHIFT_USER_ID=$(echo "${IDENTITY_PROVIDER}" | jq ".userId" | tr -d "\"")
echo "[INFO] Found ${PRODUCT_ID} user: ${USER_ID} and corresponding OpenShift user: ${OPENSHIFT_USER_ID}"
echo "${USER_ID} ${OPENSHIFT_USER_ID} username:$(echo "${USER_NAME}" | base64) email:$(echo "${USER_EMAIL}" | base64) firstName:$(echo "${USER_FIRST_NAME}" | base64) lastName:$(echo "${USER_LAST_NAME}" | base64) " >> "${ALL_USERS_DUMP}"
fi
done
echo "[INFO] Users list dump completed."

}

dumpDB() {
echo "[INFO] Dumping database in file ${DB_DUMP}"

echo "[INFO] Retriving database name"
CHE_POSTGRES_DB=$("${K8S_CLI}" get cm/che -n "${INSTALLATION_NAMESPACE}" -o jsonpath='{.data.CHE_JDBC_URL}' | awk -F '/' '{print $NF}')
if [ -z "${CHE_POSTGRES_DB}" ] || [ "${CHE_POSTGRES_DB}" = "null" ]; then CHE_POSTGRES_DB="dbche"; fi
echo "[INFO] Database name is ${CHE_POSTGRES_DB}"

echo "[INFO] Executing pg_dump"
"${K8S_CLI}" exec deploy/postgres -n "${INSTALLATION_NAMESPACE}" -- bash -c "pg_dump $CHE_POSTGRES_DB > /tmp/che.sql"

echo "[INFO] Downloading the dump"
"${K8S_CLI}" cp "${INSTALLATION_NAMESPACE}"/"$("${K8S_CLI}" get pods -l app.kubernetes.io/component=postgres -n "${INSTALLATION_NAMESPACE}" --no-headers=true -o custom-columns=":metadata.name")":/tmp/che.sql "${DB_DUMP}" > /dev/null

echo "[INFO] Database dump completed"
}

scaleDownCheServer
getUsers
scaleDownKeycloak
dumpDB

echo "[INFO] Done."
82 changes: 82 additions & 0 deletions modules/administration-guide/attachments/migration/2-migrate.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
#!/usr/bin/env bash
set -o errexit
set -o nounset
set -o pipefail

K8S_CLI=${K8S_CLI:-oc} # {orch-cli}
PRODUCT_ID=${PRODUCT_ID:-eclipse-che} # {prod-id}
INSTALLATION_NAMESPACE=${INSTALLATION_NAMESPACE:-eclipse-che} # {prod-namespace}

ALL_USERS_DUMP="${PRODUCT_ID}"-users.txt
DB_DUMP="${PRODUCT_ID}"-db.sql

echo "[INFO] Retriving ${PRODUCT_ID} database name."
CHE_POSTGRES_DB=$("${K8S_CLI}" get cm/che -n "${INSTALLATION_NAMESPACE}" -o jsonpath='{.data.CHE_JDBC_URL}' | awk -F '/' '{print $NF}')

terminatePostgresConnections() {
echo "[INFO] Terminating ${PRODUCT_ID} database connections."
"${K8S_CLI}" exec deploy/postgres -n "${INSTALLATION_NAMESPACE}" -- bash -c "psql -c \"SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE datname = '${CHE_POSTGRES_DB}'\""
}

dropExistingDatabase() {
echo "[INFO] Dropping ${PRODUCT_ID} database."
"${K8S_CLI}" exec deploy/postgres -n "${INSTALLATION_NAMESPACE}" -- bash -c "dropdb ${CHE_POSTGRES_DB}"
}

createDatabase() {
echo "[INFO] Creating a new ${PRODUCT_ID} database."
"${K8S_CLI}" exec deploy/postgres -n "${INSTALLATION_NAMESPACE}" -- bash -c "psql postgres -tAc \"CREATE DATABASE ${CHE_POSTGRES_DB}\""
}

replaceUserIDsInDBDump() {
echo "[INFO] Replacing USER_IDs in ${DB_DUMP}."
while IFS= read -r line
do
IFS=" " read -r -a IDS <<< "${line}"
USER_ID=${IDS[0]}
OPENSHIFT_USER_ID=${IDS[1]}

sed -i -e "s|${USER_ID}|${OPENSHIFT_USER_ID}|g" "${DB_DUMP}"

echo "[INFO] Replaced User ID \"${USER_ID}\" with \"${OPENSHIFT_USER_ID}\"."
done < "${ALL_USERS_DUMP}"
echo "[INFO] USER_IDs replaced."
}

restoreDatabase() {
echo "[INFO] Uploading ${DB_DUMP} to the postgreSQL pod."
"${K8S_CLI}" cp "${DB_DUMP}" "${INSTALLATION_NAMESPACE}"/"$("${K8S_CLI}" get pods -l app.kubernetes.io/component=postgres -n "${INSTALLATION_NAMESPACE}" --no-headers=true -o custom-columns=":metadata.name")":/tmp/che.sql

echo "[INFO] Restoring ${DB_DUMP} content."
"${K8S_CLI}" exec deploy/postgres -n "${INSTALLATION_NAMESPACE}" -- bash -c "psql ${CHE_POSTGRES_DB} < /tmp/che.sql"
}

migrateUserProfiles() {
echo "[INFO] Extract users profiles from ${ALL_USERS_DUMP} and insert them in ${CHE_POSTGRES_DB} database."
while IFS= read -r line
do
IFS=" " read -r -a IDS <<< "${line}"
OPENSHIFT_USER_ID=${IDS[1]}
USER_NAME=$(echo "${IDS[2]}" | cut -d ":" -f 2- | base64 -d)
USER_EMAIL=$(echo "${IDS[3]}" | cut -d ":" -f 2- | base64 -d)
USER_FIRST_NAME=$(echo "${IDS[4]}" | cut -d ":" -f 2- | base64 -d)
USER_LAST_NAME=$(echo "${IDS[5]}" | cut -d ":" -f 2- | base64 -d)

"${K8S_CLI}" exec deploy/postgres -n "${INSTALLATION_NAMESPACE}" -- bash -c "psql ${CHE_POSTGRES_DB} -tAc \"INSERT INTO profile(userid) VALUES ('${OPENSHIFT_USER_ID}');\""
"${K8S_CLI}" exec deploy/postgres -n "${INSTALLATION_NAMESPACE}" -- bash -c "psql ${CHE_POSTGRES_DB} -tAc \"INSERT INTO profile_attributes(user_id,name, value) VALUES ('${OPENSHIFT_USER_ID}', 'preferred_username', '${USER_NAME}');\""
"${K8S_CLI}" exec deploy/postgres -n "${INSTALLATION_NAMESPACE}" -- bash -c "psql ${CHE_POSTGRES_DB} -tAc \"INSERT INTO profile_attributes(user_id,name, value) VALUES ('${OPENSHIFT_USER_ID}', 'email', '${USER_EMAIL}');\""
"${K8S_CLI}" exec deploy/postgres -n "${INSTALLATION_NAMESPACE}" -- bash -c "psql ${CHE_POSTGRES_DB} -tAc \"INSERT INTO profile_attributes(user_id,name, value) VALUES ('${OPENSHIFT_USER_ID}', 'firstName', '${USER_FIRST_NAME}');\""
"${K8S_CLI}" exec deploy/postgres -n "${INSTALLATION_NAMESPACE}" -- bash -c "psql ${CHE_POSTGRES_DB} -tAc \"INSERT INTO profile_attributes(user_id,name, value) VALUES ('${OPENSHIFT_USER_ID}', 'lastName', '${USER_LAST_NAME}');\""

echo "[INFO] Added profile for \"${OPENSHIFT_USER_ID}\"."
done < "${ALL_USERS_DUMP}"
}

terminatePostgresConnections
dropExistingDatabase
createDatabase
replaceUserIDsInDBDump
restoreDatabase
migrateUserProfiles

echo "[INFO] Done."
70 changes: 70 additions & 0 deletions modules/administration-guide/attachments/migration/3-subscribe.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
#!/usr/bin/env bash
set -o errexit
set -o nounset
set -o pipefail

K8S_CLI=${K8S_CLI:-oc} # {orch-cli}
PRODUCT_ID=${PRODUCT_ID:-eclipse-che} # {prod-id}
INSTALLATION_NAMESPACE=${INSTALLATION_NAMESPACE:-eclipse-che} # {prod-namespace}
CHE_CLUSTER_CR_NAME=${CHE_CLUSTER_CR_NAME:-eclipse-che} # {prod-checluster}

OLM_STABLE_CHANNEL=${OLM_STABLE_CHANNEL:-stable} # {prod-stable-channel}
OLM_CATALOG_SOURCE=${OLM_CATALOG_SOURCE:-community-operators} # {prod-stable-channel-catalog-source}
OLM_PACKAGE=${OLM_PACKAGE:-eclipse-che} # {prod-stable-channel-package}

IDENTITY_PROVIDER_DEPLOYMENT_NAME=${IDENTITY_PROVIDER_DEPLOYMENT_NAME:-keycloak} # {?}

deleteOperatorCSV() {
echo "[INFO] Deleting operator cluster service version."
"${K8S_CLI}" delete csv "$("${K8S_CLI}" get subscription "${PRODUCT_ID}" -n "${INSTALLATION_NAMESPACE}" -o jsonpath="{.status.currentCSV}")" -n "${INSTALLATION_NAMESPACE}"
}

deleteOperatorSubscription() {
echo "[INFO] Deleting ${PRODUCT_ID} operator subscription."
"${K8S_CLI}" delete subscription "${PRODUCT_ID}" -n "${INSTALLATION_NAMESPACE}"
}

patchCheCluster() {
echo "[INFO] Updating ${CHE_CLUSTER_CR_NAME} CheCluster CR to switch to DevWorkspace and single-host."
"${K8S_CLI}" patch checluster/"${CHE_CLUSTER_CR_NAME}" -n "${INSTALLATION_NAMESPACE}" --type=json -p \
'[{"op": "replace", "path": "/spec/devWorkspace/enable", "value": true}]'
"${K8S_CLI}" patch checluster/"${CHE_CLUSTER_CR_NAME}" -n "${INSTALLATION_NAMESPACE}" --type=json -p \
'[{"op": "replace", "path": "/spec/server/serverExposureStrategy", "value": "single-host"}]'
}

cleanupIdentityProviderObjects() {
echo "[INFO] Deleting ${IDENTITY_PROVIDER_DEPLOYMENT_NAME} resources."
"${K8S_CLI}" delete route "${IDENTITY_PROVIDER_DEPLOYMENT_NAME}" -n "${INSTALLATION_NAMESPACE}"
"${K8S_CLI}" delete service "${IDENTITY_PROVIDER_DEPLOYMENT_NAME}" -n "${INSTALLATION_NAMESPACE}"
"${K8S_CLI}" delete deployment "${IDENTITY_PROVIDER_DEPLOYMENT_NAME}" -n "${INSTALLATION_NAMESPACE}"
}

createOperatorSubscription() {
echo "[INFO] Creating new ${PRODUCT_ID} operator subscription."
echo "[INFO] New subscription source: ${OLM_CATALOG_SOURCE}."
echo "[INFO] New subscription channel: ${OLM_STABLE_CHANNEL}."
echo "[INFO] New subscription name: ${OLM_PACKAGE}."

"${K8S_CLI}" apply -f - <<EOF
apiVersion: operators.coreos.com/v1alpha1
kind: Subscription
metadata:
name: "${PRODUCT_ID}"
namespace: openshift-operators
spec:
channel: "${OLM_STABLE_CHANNEL}"
installPlanApproval: Automatic
name: "${OLM_PACKAGE}"
source: "${OLM_CATALOG_SOURCE}"
sourceNamespace: openshift-marketplace
EOF

}

deleteOperatorCSV
deleteOperatorSubscription
patchCheCluster
cleanupIdentityProviderObjects
createOperatorSubscription

echo "[INFO] Done."
24 changes: 24 additions & 0 deletions modules/administration-guide/attachments/migration/4-wait.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#!/usr/bin/env bash
set -o errexit
set -o nounset
set -o pipefail

K8S_CLI=${K8S_CLI:-oc} # {orch-cli}
PRODUCT_ID=${PRODUCT_ID:-eclipse-che} # {prod-id}
INSTALLATION_NAMESPACE=${INSTALLATION_NAMESPACE:-eclipse-che} # {prod-namespace}
CHE_CLUSTER_CR_NAME=${CHE_CLUSTER_CR_NAME:-eclipse-che} # {prod-checluster}

OLM_STABLE_CHANNEL=${OLM_STABLE_CHANNEL:-stable} # {prod-stable-channel}
OLM_CATALOG_SOURCE=${OLM_CATALOG_SOURCE:-community-operators} # {prod-stable-channel-catalog-source}
OLM_PACKAGE=${OLM_PACKAGE:-eclipse-che} # {prod-stable-channel-package}

IDENTITY_PROVIDER_DEPLOYMENT_NAME=${IDENTITY_PROVIDER_DEPLOYMENT_NAME:-keycloak} # {?}

while [[ $({orch-cli} get pod -l app.kubernetes.io/component={k8s-component} -n {k8s-namespace} -o go-template='{{len .items}}') == 0 ]]
do
echo "Waiting..."
sleep 10s
done
{orch-cli} wait --for=condition=ready pod -l app.kubernetes.io/component={k8s-component} -n {k8s-namespace} --timeout=120s

echo "[INFO] Done."
1 change: 1 addition & 0 deletions modules/administration-guide/nav.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@
** xref:managing-identities-and-authorizations.adoc[]
*** xref:removing-user-data.adoc[]
* xref:upgrading-che.adoc[]
** xref:upgrading-che-7-41-on-openshift.adoc[]
** xref:upgrading-che-using-operatorhub.adoc[]
** xref:upgrading-che-using-the-cli-management-tool.adoc[]
** xref:upgrading-che-using-the-cli-management-tool-in-restricted-environment.adoc[]
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
:navtitle: Upgrading {prod-short} {prod-last-version-pre-dwo} on OpenShift
:keywords: administration-guide, migration, devworkspace
:page-aliases:

[id="upgrading-{prod-id-short}-{prod-last-version-pre-dwo}-on-openshift_{context}"]
= Upgrading {prod-short} {prod-last-version-pre-dwo} on OpenShift

A new workspace engine, the {devworkspace}, and a new authentication system has been introduced in version {prod-first-version-using-dwo} of {prod}. Upgrading from version {prod-last-version-pre-dwo} or earlier requires to follow the migration procedure described here.
l0rd marked this conversation as resolved.
Show resolved Hide resolved

.Prerequisites

* An instance of {prod-short} deployed on xref:supported-platforms.adoc[], using the default internal PostgreSQL database, and with OpenShift OAuth enabled. See {prod-docs-url-enable-oauth}.
* Command line tools `oc`, `curl`, and `jq` are available.

.Procedure

. Optionally push back changes to Git repositories in all workspaces, stop all workspaces to avoid user experience degradation, and backup {prod-short} data. See {prod-docs-url-backup-recovery}.

. Set the environment variables to use in the migration scripts:
+
[source,bash,subs="+attributes"]
----
INSTALLATION_NAMESPACE={prod-namespace} #<1>
PRODUCT_DEPLOYMENT_NAME={prod-deployment}
PRODUCT_ID={prod-id}
CHE_CLUSTER_CR_NAME={prod-checluster}
IDENTITY_PROVIDER_DEPLOYMENT_NAME={identity-provider-id}
OLM_STABLE_CHANNEL={prod-stable-channel}
OLM_CATALOG_SOURCE={prod-stable-channel-catalog-source}
OLM_PACKAGE={prod-stable-channel-package}
----
<1> Adapt to the {orch-namespace} where {prod-short} is installed.

. Download and execute the migration scripts: xref:attachment$migration/1-prepare.sh[1-prepare.sh], xref:attachment$migration/2-migrate.sh[2-migrate.sh], xref:attachment$migration/3-subscribe.sh[3-subscribe.sh], and xref:attachment$migration/4-wait.sh[4-wait.sh].
+
[source,bash,subs="+attributes"]
----
chmod +x ./1-prepare.sh ./2-migrate.sh ./3-subscribe.sh ./4-wait.sh
./1-prepare.sh <1>
./2-migrate.sh <2>
./3-subscribe.sh <3>
./4-wait.sh <4>
----
<1> Shuts down {prod-short} and {identity-provider}, fetch users data and dumps {prod-short} database.
<2> Fetches {prod-short} {identity-provider} and database data, and repopulates the database with updated data.
<3> Deletes {prod-short} Operator and {identity-provider} resources, updates CheCluster CR and creates a new Operator subscription.
<4> Waits until {prod-short} is ready.

.Verification

* Open {prod-short} dashboard and log in.