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 all 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
6 changes: 6 additions & 0 deletions antora.yml
Original file line number Diff line number Diff line change
Expand Up @@ -64,15 +64,21 @@ 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-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-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
127 changes: 127 additions & 0 deletions modules/administration-guide/attachments/migration/1-prepare.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
#!/usr/bin/env bash
set -o errexit
set -o nounset
set -o pipefail

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}"-original-db.sql
MIGRATED_DB_DUMP="${PRODUCT_ID}"-migrated-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}"

sed_in_place() {
SHORT_UNAME=$(uname -s)
if [ "$(uname)" == "Darwin" ]; then
sed -i '' "$@"
elif [ "${SHORT_UNAME:0:5}" == "Linux" ]; then
sed -i "$@"
fi
}

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")
IFS=" " read -r -a 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"
}

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

sed_in_place -e "s|${USER_ID}|${OPENSHIFT_USER_ID}|g" "${MIGRATED_DB_DUMP}"

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

scaleDownCheServer
getUsers
scaleDownKeycloak
dumpDB
replaceUserIDsInDBDump

echo "[INFO] Done."
66 changes: 66 additions & 0 deletions modules/administration-guide/attachments/migration/2-migrate.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
#!/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
MIGRATED_DB_DUMP="${PRODUCT_ID}"-migrated-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}\""
}

restoreDatabase() {
echo "[INFO] Uploading ${MIGRATED_DB_DUMP} to the postgreSQL pod."
"${K8S_CLI}" cp "${MIGRATED_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] Populating ${CHE_POSTGRES_DB} database with the new 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
restoreDatabase
migrateUserProfiles

echo "[INFO] Done."
83 changes: 83 additions & 0 deletions modules/administration-guide/attachments/migration/3-subscribe.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
#!/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}
PRODUCT_OPERATOR_NAME=${PRODUCT_OPERATOR_NAME:-che-operator} # {prod-operator}

IDENTITY_PROVIDER_DEPLOYMENT_NAME=${IDENTITY_PROVIDER_DEPLOYMENT_NAME:-keycloak} # {identity-provider-id}

deleteOperatorCSV() {
if "${K8S_CLI}" get subscription "${PRODUCT_ID}" -n "${INSTALLATION_NAMESPACE}" > /dev/null 2>&1 ; then
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}"
else
echo "[INFO] Skipping CSV deletion. No ${PRODUCT_ID} operator subscription found."
fi
}

deleteOperatorSubscription() {
if "${K8S_CLI}" get subscription "${PRODUCT_ID}" -n "${INSTALLATION_NAMESPACE}" > /dev/null 2>&1 ; then
echo "[INFO] Deleting ${PRODUCT_ID} operator subscription."
"${K8S_CLI}" delete subscription "${PRODUCT_ID}" -n "${INSTALLATION_NAMESPACE}"
else
echo "[INFO] Skipping subscription deletion as no ${PRODUCT_ID} operator subscription was found."
echo "[INFO] Deleting the ${PRODUCT_ID} operator deployment instead."
"${K8S_CLI}" delete deployment "${PRODUCT_OPERATOR_NAME}" -n "${INSTALLATION_NAMESPACE}"
fi
echo "[INFO] Waiting 30s for the old ${PRODUCT_ID} operator deletion."
sleep 30
}

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}" > /dev/null 2>&1 || echo "[INFO] Route ${IDENTITY_PROVIDER_DEPLOYMENT_NAME} not found."
"${K8S_CLI}" delete service "${IDENTITY_PROVIDER_DEPLOYMENT_NAME}" -n "${INSTALLATION_NAMESPACE}" > /dev/null 2>&1 || echo "[INFO] Service ${IDENTITY_PROVIDER_DEPLOYMENT_NAME} not found."
"${K8S_CLI}" delete deployment "${IDENTITY_PROVIDER_DEPLOYMENT_NAME}" -n "${INSTALLATION_NAMESPACE}" > /dev/null 2>&1 || echo "[INFO] Deployment ${IDENTITY_PROVIDER_DEPLOYMENT_NAME} not found."
}

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."
29 changes: 29 additions & 0 deletions modules/administration-guide/attachments/migration/4-wait.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#!/usr/bin/env bash
set -o errexit
set -o nounset
set -o pipefail

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

PRODUCT_OPERATOR_NAME=${PRODUCT_OPERATOR_NAME:-che-operator} # {prod-operator}
OPERATOR_NAMESPACE=${OPERATOR_NAMESPACE:-openshift-operators} # {?}

waitForComponent() {
component=$1
namespace=$2
echo "[INFO] Waiting for ${component} Pod to be created"
while [[ $("${K8S_CLI}" get pod -l app.kubernetes.io/component="${component}" -n "${namespace}" -o go-template='{{len .items}}') == 0 ]]
do
echo "[INFO] Waiting..."
sleep 10
done
echo "[INFO] Waiting for ${component} Pod to be ready"
"${K8S_CLI}" wait --for=condition=ready pod -l app.kubernetes.io/component="${component}" -n "${namespace}" --timeout=120s
}

waitForComponent "${PRODUCT_DEPLOYMENT_NAME}" "${INSTALLATION_NAMESPACE}"
waitForComponent "${PRODUCT_OPERATOR_NAME}" "${OPERATOR_NAMESPACE}"

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,54 @@
: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

The workspace engine and authentication system used until version {prod-last-version-pre-dwo} are deprecated. Upgrading from version {prod-last-version-pre-dwo} requires manual steps.

.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.
* The host running the upgrade commands is running on Linux.

.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_OPERATOR_NAME={prod-operator}
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 (it can take more than 5 minutes).

.Verification

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