Compare commits

...

39 Commits
7.80.0 ... main

Author SHA1 Message Date
Igor Vinokur aa213c3003
Update ch.qos.logback dependency version to latest (#687)
In order to fix the CVE-2023-6378 vulnerability, update ch.qos.logback maven dependency version to 1.5.6
2024-05-27 09:29:31 +03:00
Igor Vinokur 88cbaebd1a
Support raw devfile urls without yaml extension (#683)
On handling raw devfile urls, request content by the url, and check if the content is a devfile. If yes treat the url as a raw devfile url.

---------

Signed-off-by: ivinokur <ivinokur@redhat.com>
Co-authored-by: Anatolii Bazko <abazko@redhat.com>
2024-05-15 10:13:37 +03:00
che-bot e072c7642b
chore: Update from ubi8-minimal:8.9-1108 to ubi8-minimal:8.9-1161 (#681)
* chore: Update from ubi8-minimal:8.9-1108 to ubi8-minimal:8.9-1161

Signed-off-by: Nick Boldt <nboldt@redhat.com>

* chore: Update from ubi8-minimal:8.9-1108 to ubi8-minimal:8.9-1161

Signed-off-by: Nick Boldt <nboldt@redhat.com>

---------

Signed-off-by: Nick Boldt <nboldt@redhat.com>
Co-authored-by: Nick Boldt <nboldt@redhat.com>
2024-04-29 08:49:33 +03:00
che-bot b5f110c659
chore: Bump to 7.86.0-SNAPSHOT in main (#680)
Signed-off-by: Mykhailo Kuznietsov <mkuznets@redhat.com>
Co-authored-by: Mykhailo Kuznietsov <mkuznets@redhat.com>
2024-04-26 08:16:38 +03:00
Shmaraiev Oleksandr 95b1c390b2
Add info messages to git-flow tests (#676)
* Add info messages to tests
* Add 'waitFinishDeploymentCheServer' to avoid 'error: lost connection to pod'
2024-04-19 20:33:08 +03:00
Dmytro Nochevnov 858a12b3ff
Download chectl install script from che-incubator.github.io in tests (#677) 2024-04-17 14:22:19 +02:00
che-bot 7c07c3c135
chore: Bump to 7.85.0-SNAPSHOT in main (#675)
Signed-off-by: Mykhailo Kuznietsov <mkuznets@redhat.com>
Co-authored-by: Mykhailo Kuznietsov <mkuznets@redhat.com>
2024-04-09 15:52:32 +03:00
Igor Vinokur 2cfce0568a
Rework the Bitbucket Server oauth token validation (#673)
- Change the validation API request to get current user request. The /rest/api/1.0/application-properties request is irrelevant as it does not require a token.
- Pass oath token to the getPersonalAccessToken() API request in order to avoid circular getToken() request.
2024-04-08 09:30:02 +03:00
ivinokur c51919d1e3 fixup! Fix gitlab oauth token validation request 2024-04-04 11:10:45 +02:00
ivinokur 1fc4e07988 Fix gitlab oauth token validation request 2024-04-04 11:10:45 +02:00
sdawley 799fcb1d0e Updating tomcat version to 10.1.14 for CRW-4941
Signed-off-by: sdawley <sdawley@redhat.com>
2024-03-27 15:43:15 +01:00
Igor Vinokur 2e27c47f2f
Add provider name annotation to PAT secret (#670)
Add che.eclipse.org/scm-provider-name annotation to Personal Access Token secret.
2024-03-25 14:57:27 +02:00
ivinokur b8e0397b0a Update io.fabric8.kubernetes-client to 6.10.0 2024-03-22 18:13:04 +01:00
che-bot 661d852250
chore: Bump to 7.84.0-SNAPSHOT in main (#669)
Signed-off-by: Mykhailo Kuznietsov <mkuznets@redhat.com>
Co-authored-by: Mykhailo Kuznietsov <mkuznets@redhat.com>
2024-03-19 08:51:13 +02:00
Igor Vinokur ba6f30f963
Add Gitlab invalidate token implementation (#667) 2024-03-16 12:56:55 +02:00
Igor Vinokur dbe167276a
Encode redirect URL if needed on oauth1 callback request (#663)
The latest BItBucket Server decodes the callback url so that causes IllegalArgumentException error. Catch the error and decode the redirect url.
2024-03-16 06:26:52 +02:00
Anatolii Bazko 28002fb835
fix: Support BitBucket endpoint with path (#665)
Signed-off-by: Anatolii Bazko <abazko@redhat.com>
2024-03-12 10:22:04 +01:00
Igor Vinokur 6cdf6f655a
Do not pass oauth2 as a username to Git credentials for Bitbucket (#662)
Set bitbucket-***** as a token name annotation for bitbucket token secret. This is needed to pass username instead of oauth2 for bitbucket credentials
2024-03-07 11:08:33 +02:00
Anatolii Bazko 7dc7a61511
chore: Remote workspace-stop roles (#659)
Signed-off-by: Anatolii Bazko <abazko@redhat.com>
2024-03-05 12:38:09 +01:00
che-bot 60262e3a72
chore: Bump to 7.83.0-SNAPSHOT in main (#658) 2024-02-28 09:18:10 +02:00
Ilya Buziuk 5d79a849ef
Update CODEOWNERS (#657) 2024-02-27 17:27:09 +02:00
Igor Vinokur 3fef2347f0
Remove the DB related modules (#630) 2024-02-27 15:27:58 +02:00
Igor Vinokur aebdc3a04d
Add debug logs to KubernetesPersonalAccessTokenManager class (#656) 2024-02-21 20:24:27 +02:00
Igor Vinokur a691074548
Add debug logs to KubernetesPersonalAccessTokenManager class (#655) 2024-02-20 18:07:04 +02:00
Igor Vinokur f9f4c8e5d5
Encode redirect URL if needed on oauth callback request (#654)
Some SCM providers like BItBucket Server decode the callback url so that cause IllegalArgumentException error. Catch the error and decode the redirect url.
2024-02-19 19:07:07 +02:00
Igor Vinokur 4f8a84cb1d
Fetch oauth tokens from kubernetes secrets (#652)
Move AuthorisationRequestManager interface towsmaster/che-core-api-factory module in order to avoid circular dependency.
Rework the get oauth token method to return an oauth token from kubernetes secrets if token is not found in the system memory of the che-server pod. If provider name value is not configured in the kubernetes secret oauth token, get the token by mapping it by provider url from the secret and oauth provider name from the aouth config secret.
2024-02-08 10:22:51 +02:00
ivinokur 6f40c9856f Add isNullOrEmpty check to the BitbucketServerURLParser 2024-02-06 14:18:05 +01:00
che-bot 62f301c42d
chore: Bump to 7.82.0-SNAPSHOT in main (#651)
Signed-off-by: Mykhailo Kuznietsov <mkuznets@redhat.com>
Co-authored-by: Mykhailo Kuznietsov <mkuznets@redhat.com>
2024-02-02 19:53:07 +02:00
Shmaraiev Oleksandr 9422bf86ac
Add test 'che-smoke-test' as PR checks
* Add 'smoke-test' to OpenShift CI
* Add 'pod-che-smoke-test.yaml' component
* Add 'startSmokeTest' to 'common.sh'
* Update 'pod-oauth-factory-test.yaml' component
2024-01-30 12:06:23 +02:00
Nick Boldt be4383abac chore: remove Nick and Mario as code owners; add Sam
Change-Id: Ibb4d2cab011a42279ae93da528d7aa566bf4860d
Signed-off-by: Nick Boldt <nboldt@redhat.com>
2024-01-23 12:04:37 +01:00
Dmytro Nochevnov fa7d6442f5
Fix syntax error in Dockerfile of OpenShift CI jobs (#646)
Signed-off-by: Dmytro Nochevnov <dnochevn@redhat.com>
2024-01-19 13:25:47 +02:00
Dmytro Nochevnov e1ae06ec50
Get rid of failing curl in OpenShift CI jobs (#645)
Signed-off-by: Dmytro Nochevnov <dnochevn@redhat.com>
2024-01-19 12:15:49 +02:00
Dmytro Nochevnov 901a30ea8c
Move installation of oc client from Dockerfile to common.sh (#644)
Signed-off-by: Dmytro Nochevnov <dnochevn@redhat.com>
2024-01-18 16:41:12 +02:00
Dmytro Nochevnov 76913d93c2
Fix openshift-client-linux.tar.gz version in OpenShift CI job Dockerfile (#643)
Signed-off-by: Dmytro Nochevnov <dnochevn@redhat.com>
2024-01-17 15:40:00 +02:00
Dmytro Nochevnov dc7edf634e
Get more OpenShift CI image build command logs 2024-01-17 13:17:42 +02:00
Igor Vinokur 12a3a8a8e7
Remove devfile validation schema mechanism (#640)
Remove devfile validation schema mechanism and related stuff.
2024-01-17 09:21:44 +02:00
Nick Boldt 3fb1df91f7 chore: Update from ubi8-minimal:8.9-1029 to ubi8-minimal:8.9-1108
Signed-off-by: Nick Boldt <nboldt@redhat.com>
2024-01-15 14:40:57 +01:00
Nick Boldt 0e3b7c107c chore: Update from ubi8-minimal:8.9-1029 to ubi8-minimal:8.9-1108
Signed-off-by: Nick Boldt <nboldt@redhat.com>
2024-01-15 14:40:57 +01:00
Mykhailo Kuznietsov 978f2cdd21 chore: Bump to 7.81.0-SNAPSHOT in main
Signed-off-by: Mykhailo Kuznietsov <mkuznets@redhat.com>
2024-01-11 15:35:09 +01:00
455 changed files with 1513 additions and 41244 deletions

View File

@ -11,30 +11,19 @@
# Red Hat, Inc. - initial API and implementation
# Dockerfile to bootstrap build and test in openshift-ci
FROM registry.access.redhat.com/ubi9/nodejs-18:1
FROM registry.ci.openshift.org/openshift/release:golang-1.18
# hadolint ignore=DL3002
USER 0
SHELL ["/bin/bash", "-c"]
# Install yq, kubectl, chectl cli used by olm/olm.sh script.
# hadolint ignore=DL3041
RUN dnf install -y -q --allowerasing --nobest nodejs-devel nodejs-libs psmisc python3-pip jq golang httpd-tools \
# already installed or installed as deps:
openssl openssl-devel ca-certificates make cmake cpp gcc gcc-c++ zlib zlib-devel brotli brotli-devel python3 nodejs-packaging && \
dnf update -y && dnf clean all && \
npm install -g yarn@1.22 npm@9 && \
echo -n "node version: "; node -v; \
echo -n "npm version: "; npm -v; \
echo -n "yarn version: "; yarn -v; \
go version; \
pip3 install --upgrade pip setuptools yq && \
# Install kubectl, chectl cli used by olm/olm.sh script.
# Install yq, kubectl, chectl cli.
RUN yum install --assumeyes -d1 psmisc python3-pip httpd-tools nodejs && \
pip3 install --upgrade setuptools && \
pip3 install yq && \
curl -LO https://storage.googleapis.com/kubernetes-release/release/$(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt)/bin/linux/amd64/kubectl && \
chmod +x ./kubectl && \
mv ./kubectl /usr/local/bin && \
bash <(curl -sL https://www.eclipse.org/che/chectl/) --channel=next && \
curl https://mirror.openshift.com/pub/openshift-v4/clients/ocp/latest-4.12/openshift-client-linux.tar.gz | tar xvzf - -C /usr/local/bin/ oc && \
chmod ug+x /usr/local/bin/oc
SHELL ["/bin/bash", "-c"]
bash <(curl -sL https://che-incubator.github.io/chectl/install.sh) --channel=next

View File

@ -1,6 +1,6 @@
#!/bin/bash
#
# Copyright (c) 2023 Red Hat, Inc.
# Copyright (c) 2023-2024 Red Hat, Inc.
# This program and the accompanying materials are made
# available under the terms of the Eclipse Public License 2.0
# which is available at https://www.eclipse.org/legal/epl-2.0/
@ -36,39 +36,47 @@ export CUSTOM_CONFIG_MAP_NAME=${CUSTOM_CONFIG_MAP_NAME:-"custom-ca-certificates"
export GIT_SSL_CONFIG_MAP_NAME=${GIT_SSL_CONFIG_MAP_NAME:-"che-self-signed-cert"}
provisionOpenShiftOAuthUser() {
echo -e "[INFO] Provisioning Openshift OAuth user"
echo "------- [INFO] Start provisioning Openshift OAuth user -------"
htpasswd -c -B -b users.htpasswd ${OCP_ADMIN_USER_NAME} ${OCP_LOGIN_PASSWORD}
htpasswd -b users.htpasswd ${OCP_NON_ADMIN_USER_NAME} ${OCP_LOGIN_PASSWORD}
oc create secret generic htpass-secret --from-file=htpasswd="users.htpasswd" -n openshift-config
oc apply -f ".ci/openshift-ci/htpasswdProvider.yaml"
oc adm policy add-cluster-role-to-user cluster-admin ${OCP_ADMIN_USER_NAME}
echo -e "[INFO] Waiting for htpasswd auth to be working up to 5 minutes"
echo "------- [INFO] Waiting for htpasswd auth to be working up to 5 minutes -------"
CURRENT_TIME=$(date +%s)
ENDTIME=$((CURRENT_TIME + 300))
while [ "$(date +%s)" -lt $ENDTIME ]; do
if oc login -u=${OCP_ADMIN_USER_NAME} -p=${OCP_LOGIN_PASSWORD} --insecure-skip-tls-verify=false; then
break
echo "======= [INFO] OpenShift OAuth htpasswd is configured. =======
======= [INFO] Login to OCP cluster with admin user credentials is success.======="
return 0
fi
sleep 10
sleep 5
done
echo "####### [ERROR] Error occurred while waiting OpenShift OAuth htpasswd setup. Try to rerun test. #######"
exit 1
}
configureGitSelfSignedCertificate() {
echo "[INFO] Configure self-signed certificate for Git provider"
echo "------- [INFO] Configure self-signed certificate for Git provider -------"
oc adm new-project ${CHE_NAMESPACE}
oc project ${CHE_NAMESPACE}
echo -e "[INFO] Create ConfigMap with the required TLS certificate"
echo "------- [INFO] Create ConfigMap with the required TLS certificate -------"
oc create configmap ${CUSTOM_CONFIG_MAP_NAME} --from-file=.ci/openshift-ci/ca.crt
oc label configmap ${CUSTOM_CONFIG_MAP_NAME} app.kubernetes.io/part-of=che.eclipse.org app.kubernetes.io/component=ca-bundle
echo "[INFO] Create ConfigMap to support Git repositories with self-signed certificates"
oc create configmap ${GIT_SSL_CONFIG_MAP_NAME} --from-file=.ci/openshift-ci/ca.crt --from-literal=githost=$GIT_PROVIDER_URL
echo "------- [INFO] Create ConfigMap to support Git repositories with self-signed certificates -------"
oc create configmap ${GIT_SSL_CONFIG_MAP_NAME} --from-file=.ci/openshift-ci/ca.crt --from-literal=githost=${GIT_PROVIDER_URL}
oc label configmap ${GIT_SSL_CONFIG_MAP_NAME} app.kubernetes.io/part-of=che.eclipse.org
echo "======= [INFO] ConfigMaps are configured ======="
}
createCustomResourcesFile() {
echo "------- [INFO] Create custom resourses file -------"
cat > custom-resources.yaml <<-END
apiVersion: org.eclipse.che/v2
spec:
@ -76,26 +84,53 @@ spec:
maxNumberOfRunningWorkspacesPerUser: 10000
END
echo "Generated custom resources file"
echo "======= [INFO] Generated custom resources file ======="
cat custom-resources.yaml
}
patchCustomResourcesFile() {
echo "------- [INFO] Edit the custom resources file to add 'gitTrustedCertsConfigMapName' -------"
yq -y '.spec.devEnvironments.trustedCerts += {"gitTrustedCertsConfigMapName": "'${GIT_SSL_CONFIG_MAP_NAME}'"}' custom-resources.yaml -i
echo "======= [INFO] Patched custom resources file ======="
cat custom-resources.yaml
}
deployChe() {
echo "------- [INFO] Start installing Eclipse Che -------"
chectl server:deploy --cheimage=$CHE_SERVER_IMAGE \
--che-operator-cr-patch-yaml=custom-resources.yaml \
--platform=openshift \
--telemetry=off \
--batch
waitFinishDeploymentCheServer
echo "======= [INFO] Eclipse Che is successfully installed ======="
}
waitFinishDeploymentCheServer() {
CURRENT_TIME=$(date +%s)
ENDTIME=$((CURRENT_TIME + 60))
while [ "$(date +%s)" -lt $ENDTIME ]; do
podCheServerName=$(oc get pod -n ${CHE_NAMESPACE} -l component=che | grep "che" | awk '{ print $1 }')
echo "Pod Che_Server: $podCheServerName"
count=$(echo "$podCheServerName" | wc -l)
if [ $count -eq 1 ]; then
echo "------- [INFO] Only one Che Server pod is left. -------"
return 0
fi
echo "------- [INFO] Waiting until only one Che Server pod remains. -------"
sleep 5
done
echo "####### [ERROR] Error occurred while waiting for only one Che Server pod. #######"
exit 1
}
# this command starts port forwarding between the local machine and the che-host service in the OpenShift cluster.
forwardPortToService() {
echo "------- [INFO] Start forwarding between the local machine and the che-host service -------"
oc port-forward service/che-host ${CHE_FORWARDED_PORT}:8080 -n ${CHE_NAMESPACE} &
sleep 3s
}
@ -120,28 +155,28 @@ requestFactoryResolverGitRepoUrl() {
# check that factory resolver returns correct value without any PAT/OAuth setup
testFactoryResolverNoPatOAuth() {
echo "[INFO] Check factory resolver for public repository with NO PAT/OAuth setup"
echo "------- [INFO] Check factory resolver for public repository with NO PAT/OAuth setup -------"
testFactoryResolverResponse $1 200
echo "[INFO] Check factory resolver for private repository with NO PAT/OAuth setup"
echo "------- [INFO] Check factory resolver for private repository with NO PAT/OAuth setup -------"
testFactoryResolverResponse $2 500
}
# check that raw devfile url factory resolver returns correct value without any PAT/OAuth setup
testFactoryResolverNoPatOAuthRaw() {
echo "[INFO] Check factory resolver for public repository with NO PAT/OAuth setup"
echo "------- [INFO] Check factory resolver for public repository with NO PAT/OAuth setup -------"
testFactoryResolverResponse $1 200
echo "[INFO] Check factory resolver for private repository with NO PAT/OAuth setup"
echo "------- [INFO] Check factory resolver for private repository with NO PAT/OAuth setup -------"
testFactoryResolverResponse $2 400
}
# check that factory resolver returns correct value with PAT/OAuth setup
testFactoryResolverWithPatOAuth() {
echo "[INFO] Check factory resolver for public repository with PAT/OAuth setup"
echo "------- [INFO] Check factory resolver for public repository with PAT/OAuth setup -------"
testFactoryResolverResponse $1 200
echo "[INFO] Check factory resolver for private repository with PAT/OAuth setup"
echo "------- [INFO] Check factory resolver for private repository with PAT/OAuth setup -------"
testFactoryResolverResponse $2 200
}
@ -149,11 +184,11 @@ testFactoryResolverResponse() {
URL=$1
RESPONSE_CODE=$2
echo "[INFO] Check factory resolver"
if [ "$(requestFactoryResolverGitRepoUrl ${URL} | grep "HTTP/1.1 ${RESPONSE_CODE}")" ]; then
echo "[INFO] Factory resolver returned 'HTTP/1.1 ${RESPONSE_CODE}' status code. Expected client side response."
echo "======= [INFO] Factory resolver returned 'HTTP/1.1 ${RESPONSE_CODE}' status code. Expected client side response. ======="
else
echo "[ERROR] Factory resolver returned wrong status code. Expected: HTTP/1.1 ${RESPONSE_CODE}."
echo "####### [ERROR] Factory resolver returned wrong status code. Expected: HTTP/1.1 ${RESPONSE_CODE}. #######
####### Cause possible: PR code regress or service is changed. Need to investigate it. #######"
exit 1
fi
}
@ -171,12 +206,19 @@ requestProvisionNamespace() {
initUserNamespace() {
OCP_USER_NAME=$1
echo "[INFO] Initialize user namespace"
echo "------- [INFO] Initialize user namespace -------"
oc login -u=${OCP_USER_NAME} -p=${OCP_LOGIN_PASSWORD} --insecure-skip-tls-verify=false
if [ "$(requestProvisionNamespace | grep "HTTP/1.1 200")" ]; then
echo "[INFO] Request provision user namespace returned 'HTTP/1.1 200' status code."
request_result=$(requestProvisionNamespace) || true
if [ -z "$request_result" ]; then
echo "####### [ERROR] Cause possible: lost connection to pod, this is an infrastructure problem. Try to rerun the test. #######"
exit 1
elif [ "$(echo "$request_result" | grep "HTTP/1.1 200")" ]; then
echo "======= [INFO] Request provision user namespace returned 'HTTP/1.1 200' status code. User namespace is created. ======="
else
echo "[ERROR] Request provision user namespace returned wrong status code. Expected: HTTP/1.1 200"
echo "####### [ERROR] Request provision user namespace returned wrong status code. Expected: HTTP/1.1 200. #######
####### User namespace creation failed. Cause possible: PR code regression or service is changed. Need to investigate. #######"
exit 1
fi
}
@ -186,7 +228,7 @@ setupPersonalAccessToken() {
GIT_PROVIDER_URL=$2
GIT_PROVIDER_PAT=$3
echo "[INFO] Setup Personal Access Token Secret"
echo "------- [INFO] Setup Personal Access Token Secret -------"
oc project ${USER_CHE_NAMESPACE}
CHE_USER_ID=$(oc get secret user-profile -o jsonpath='{.data.id}' | base64 -d)
ENCODED_PAT=$(echo -n ${GIT_PROVIDER_PAT} | base64)
@ -205,13 +247,14 @@ setupPersonalAccessToken() {
cat pat-secret.yaml
oc apply -f pat-secret.yaml -n ${USER_CHE_NAMESPACE}
echo "======= [INFO] Personal Access Token is created. ======="
}
setupSSHKeyPairs() {
GIT_PRIVATE_KEY=$1
GIT_PUBLIC_KEY=$2
echo "[INFO] Setup SSH Key Pairs Secret"
echo "------- [INFO] Setup SSH Key Pairs Secret "-------
oc project ${USER_CHE_NAMESPACE}
ENCODED_GIT_PRIVATE_KEY=$(echo "${GIT_PRIVATE_KEY}" | base64 -w 0)
ENCODED_GIT_PUBLIC_KEY=$(echo "${GIT_PUBLIC_KEY}" | base64 -w 0)
@ -224,6 +267,7 @@ setupSSHKeyPairs() {
cat ssh-secret.yaml
oc apply -f ssh-secret.yaml -n ${USER_CHE_NAMESPACE}
echo "======= [INFO] SSH Secret is created. ======="
}
# Only for GitLab server administrator users
@ -232,7 +276,7 @@ createOAuthApplicationGitLabServer() {
CHE_URL=https://$(oc get route -n ${CHE_NAMESPACE} che -o jsonpath='{.spec.host}')
echo "[INFO] Create OAuth Application"
echo "------- [INFO] Create OAuth Application -------"
response=$(curl -k -X POST \
${GIT_PROVIDER_URL}/api/v4/applications \
-H "PRIVATE-TOKEN: ${ADMIN_ACCESS_TOKEN}" \
@ -240,15 +284,11 @@ createOAuthApplicationGitLabServer() {
-d "redirect_uri=${CHE_URL}/api/oauth/callback" \
-d "scopes=api write_repository openid")
echo "[INFO] Response of the created OAuth Application"
echo "------- [INFO] Response of the created OAuth Application -------"
OAUTH_ID=$(echo "$response" | jq -r '.id')
APPLICATION_ID=$(echo "$response" | jq -r '.application_id')
APPLICATION_SECRET=$(echo "$response" | jq -r '.secret')
echo "[INFO] OAuth ID: ${OAUTH_ID}"
echo "[INFO] Application ID: ${APPLICATION_ID}"
echo "[INFO] Application Secret: ${APPLICATION_SECRET}"
}
# Only for GitLab server administrator users
@ -256,10 +296,12 @@ deleteOAuthApplicationGitLabServer() {
OAUTH_ID=$1
ADMIN_ACCESS_TOKEN=$2
echo "[INFO] Delete OAuth Application"
echo "------- [INFO] Delete OAuth Application -------"
curl -i -k -X DELETE \
${GIT_PROVIDER_URL}/api/v4/applications/${OAUTH_ID} \
-H "PRIVATE-TOKEN: ${ADMIN_ACCESS_TOKEN}"
echo "======= [INFO] OAuth Application is deleted ======="
}
# Only for GitLab server
@ -267,18 +309,18 @@ revokeAuthorizedOAuthApplication() {
APPLICATION_ID=$1
APPLICATION_SECRET=$2
echo "[INFO] Revoke authorized OAuth application"
echo "------- [INFO] Revoke authorized OAuth application -------"
oc project ${USER_CHE_NAMESPACE}
OAUTH_TOKEN_NAME=$(oc get secret | grep 'personal-access-token'| awk 'NR==1 { print $1 }')
echo "[INFO] OAuth token name: "$OAUTH_TOKEN_NAME
OAUTH_TOKEN=$(oc get secret $OAUTH_TOKEN_NAME -o jsonpath='{.data.token}' | base64 -d)
echo "[INFO] Oauth token: "$OAUTH_TOKEN
curl -i -k -X POST \
${GIT_PROVIDER_URL}/oauth/revoke \
-d "client_id=${APPLICATION_ID}" \
-d "client_secret=${APPLICATION_SECRET}" \
-d "token=${OAUTH_TOKEN}"
echo "======= [INFO] Authorized OAuth application is revoked ======="
}
# Only for GitLab server
@ -286,7 +328,7 @@ setupOAuthSecret() {
APPLICATION_ID=$1
APPLICATION_SECRET=$2
echo "[INFO] Setup OAuth Secret"
echo "------- [INFO] Setup OAuth Secret -------"
oc login -u=${OCP_ADMIN_USER_NAME} -p=${OCP_LOGIN_PASSWORD} --insecure-skip-tls-verify=false
oc project ${CHE_NAMESPACE}
SERVER_POD=$(oc get pod -l component=che | grep "che" | awk 'NR==1 { print $1 }')
@ -303,7 +345,7 @@ setupOAuthSecret() {
cat oauth-secret.yaml
oc apply -f oauth-secret.yaml -n ${CHE_NAMESPACE}
echo "[INFO] Wait updating deployment after create OAuth secret"
echo "------- [INFO] Wait updating deployment after create OAuth secret -------"
oc wait --for=delete pod/${SERVER_POD} --timeout=120s
}
@ -316,6 +358,7 @@ runTestWorkspaceWithGitRepoUrl() {
oc project ${OCP_USER_NAMESPACE}
cat .ci/openshift-ci/devworkspace-test.yaml > devworkspace-test.yaml
echo "------- [INFO] Preparing 'devworkspace-test.yaml' and run test workspace -------"
# patch the devworkspace-test.yaml file
sed -i "s#ws-name#${WS_NAME}#g" devworkspace-test.yaml
sed -i "s#project-name#${PROJECT_NAME}#g" devworkspace-test.yaml
@ -325,7 +368,7 @@ runTestWorkspaceWithGitRepoUrl() {
oc apply -f devworkspace-test.yaml -n ${OCP_USER_NAMESPACE}
oc wait -n ${OCP_USER_NAMESPACE} --for=condition=Ready dw ${WS_NAME} --timeout=360s
echo "[INFO] Test workspace is run"
echo "======= [INFO] Test workspace is run ======="
}
testProjectIsCloned() {
@ -334,9 +377,9 @@ testProjectIsCloned() {
WORKSPACE_POD_NAME=$(oc get pods -n ${OCP_USER_NAMESPACE} | grep workspace | awk '{print $1}')
if oc exec -it -n ${OCP_USER_NAMESPACE} ${WORKSPACE_POD_NAME} -- test -f /projects/${PROJECT_NAME}/${YAML_FILE_NAME}; then
echo "[INFO] Project file /projects/${PROJECT_NAME}/${YAML_FILE_NAME} exists."
echo "======= [INFO] Project file /projects/${PROJECT_NAME}/${YAML_FILE_NAME} exists. ======="
else
echo "[INFO] Project file /projects/${PROJECT_NAME}/${YAML_FILE_NAME} is absent."
echo "======= [INFO] Project file /projects/${PROJECT_NAME}/${YAML_FILE_NAME} is absent. ======="
return 1
fi
}
@ -346,7 +389,7 @@ testGitCredentialsData() {
GIT_PROVIDER_PAT=$2
GIT_PROVIDER_URL=$3
echo "[INFO] Check the 'git credentials' is in a workspace"
echo "------- [INFO] Check the 'git credentials' is in a workspace -------"
hostName="${GIT_PROVIDER_URL#https://}"
if [ "${GIT_PROVIDER_TYPE}" == "azure-devops" ]; then
@ -358,9 +401,10 @@ testGitCredentialsData() {
gitCredentials="https://${userName}:${GIT_PROVIDER_PAT}@${hostName}"
WORKSPACE_POD_NAME=$(oc get pods -n ${OCP_USER_NAMESPACE} | grep workspace | awk '{print $1}')
if oc exec -it -n ${OCP_USER_NAMESPACE} ${WORKSPACE_POD_NAME} -- cat /.git-credentials/credentials | grep -q ${gitCredentials}; then
echo "[INFO] Git credentials file '/.git-credentials/credentials' exists and has the expected content."
echo "======= [INFO] Git credentials file '/.git-credentials/credentials' exists and has the expected content. ======="
else
echo "[ERROR] Git credentials file '/.git-credentials/credentials' does not exist or has incorrect content."
echo "####### [ERROR] Git credentials file '/.git-credentials/credentials' does not exist or has incorrect content. ######
###### Cause possible: PR code regress or service is changed. Need to investigate it. #######"
exit 1
fi
}
@ -368,7 +412,7 @@ testGitCredentialsData() {
deleteTestWorkspace() {
WS_NAME=$1
OCP_USER_NAMESPACE=$2
echo "------- [INFO] Delete test workspace -------"
oc delete dw ${WS_NAME} -n ${OCP_USER_NAMESPACE}
}
@ -386,7 +430,7 @@ startOAuthFactoryTest() {
sed -i "s#GIT_PROVIDER_USER_NAME#${GIT_PROVIDER_LOGIN}#g" oauth-factory-test.yaml
sed -i "s#GIT_PROVIDER_USER_PASSWORD#${GIT_PROVIDER_PASSWORD}#g" oauth-factory-test.yaml
echo "[INFO] Applying the following patched OAuth Factory Test Pod:"
echo "------- [INFO] Applying the following patched OAuth Factory Test Pod: -------"
cat oauth-factory-test.yaml
echo "[INFO] --------------------------------------------------"
oc apply -f oauth-factory-test.yaml
@ -397,7 +441,7 @@ startOAuthFactoryTest() {
PHASE=$(oc get pod -n ${CHE_NAMESPACE} ${TEST_POD_NAME} \
--template='{{ .status.phase }}')
if [[ ${PHASE} == "Running" ]]; then
echo "[INFO] Smoke test started successfully."
echo "======= [INFO] Factory test started successfully. ======="
return
fi
@ -405,22 +449,59 @@ startOAuthFactoryTest() {
n=$(( n+1 ))
done
echo "[ERROR] Failed to start smoke test."
echo "####### [ERROR] Failed to start Factory test. #######
###### Cause possible: an infrastructure problem, pod could not start, try to rerun the test. #######"
exit 1
}
startSmokeTest() {
CHE_URL=https://$(oc get route -n ${CHE_NAMESPACE} che -o jsonpath='{.spec.host}')
# patch che-smoke-test.yaml
cat .ci/openshift-ci/pod-che-smoke-test.yaml > che-smoke-test.yaml
sed -i "s#CHE_URL#${CHE_URL}#g" che-smoke-test.yaml
sed -i "s#CHE-NAMESPACE#${CHE_NAMESPACE}#g" che-smoke-test.yaml
sed -i "s#OCP_USER_NAME#${OCP_NON_ADMIN_USER_NAME}#g" che-smoke-test.yaml
sed -i "s#OCP_USER_PASSWORD#${OCP_LOGIN_PASSWORD}#g" che-smoke-test.yaml
echo "------- [INFO] Applying the following patched Smoke Test Pod: -------"
cat che-smoke-test.yaml
echo "[INFO] --------------------------------------------------"
oc apply -f che-smoke-test.yaml
# wait for the pod to start
n=0
while [ $n -le 120 ]
do
PHASE=$(oc get pod -n ${CHE_NAMESPACE} ${TEST_POD_NAME} \
--template='{{ .status.phase }}')
if [[ ${PHASE} == "Running" ]]; then
echo "======= [INFO] Smoke test started successfully. ======="
return
fi
sleep 5
n=$(( n+1 ))
done
echo "####### [ERROR] Failed to start Smoke test. #######
####### Cause possible: an infrastructure problem, pod could not start, try to rerun the test. #######"
exit 1
}
# Catch the finish of the job and write logs in artifacts.
catchFinish() {
echo "[INFO] Terminate the process after finish the test script."
local RESULT=$?
killProcessByPort
if [ "$RESULT" != "0" ]; then
set +e
collectEclipseCheLogs
set -e
fi
[[ "${RESULT}" != "0" ]] && echo "[ERROR] Job failed." || echo "[INFO] Job completed successfully."
echo "------- [INFO] Terminate the process after finish the test script. -------"
set +e
killProcessByPort
set -e
[[ "${RESULT}" != "0" ]] && echo "####### [ERROR] Job failed. #######" || echo "####### [INFO] Job completed successfully. #######"
exit $RESULT
}
@ -434,31 +515,35 @@ collectEclipseCheLogs() {
}
collectLogs() {
echo "[INFO] Waiting until oauth test pod finished"
oc logs -n ${CHE_NAMESPACE} ${TEST_POD_NAME} -c oauth-test -f
echo "------- [INFO] Waiting until test pod finished. -------"
oc logs -n ${CHE_NAMESPACE} ${TEST_POD_NAME} -c test -f
sleep 3
# Download artifacts
set +e
echo "[INFO] Collect all Eclipse Che logs and cluster CR."
echo -------" [INFO] Collect all Eclipse Che logs and cluster CR. -------"
collectEclipseCheLogs
echo "[INFO] Downloading test report."
echo "------- [INFO] Downloading test report. -------"
mkdir -p ${ARTIFACTS_DIR}/e2e
oc rsync -n ${CHE_NAMESPACE} ${TEST_POD_NAME}:/tmp/e2e/report/ ${ARTIFACTS_DIR}/e2e -c download-reports
oc exec -n ${CHE_NAMESPACE} ${TEST_POD_NAME} -c download-reports -- touch /tmp/done
# Revoke and delete the OAuth application
revokeAuthorizedOAuthApplication ${APPLICATION_ID} ${APPLICATION_SECRET}
deleteOAuthApplicationGitLabServer ${OAUTH_ID} ${ADMIN_ACCESS_TOKEN}
if [[ ${TEST_POD_NAME} == "oauth-factory-test" ]]; then
revokeAuthorizedOAuthApplication ${APPLICATION_ID} ${APPLICATION_SECRET}
deleteOAuthApplicationGitLabServer ${OAUTH_ID} ${ADMIN_ACCESS_TOKEN}
fi
set -e
EXIT_CODE=$(oc logs -n ${CHE_NAMESPACE} ${TEST_POD_NAME} -c oauth-test | grep EXIT_CODE)
EXIT_CODE=$(oc logs -n ${CHE_NAMESPACE} ${TEST_POD_NAME} -c test | grep EXIT_CODE)
if [[ ${EXIT_CODE} != "+ EXIT_CODE=0" ]]; then
echo "[ERROR] Factory OAuth test failed. Job failed."
echo "####### [ERROR] GUI test failed. Job failed. #######
###### Cause possible: PR code regress or service is changed. Need to investigate it. #######"
exit 1
fi
echo "[INFO] Job completed successfully."
echo "======= [INFO] Job completed successfully. ======="
}
testCloneGitRepoNoProjectExists() {
@ -468,10 +553,11 @@ testCloneGitRepoNoProjectExists() {
OCP_USER_NAMESPACE=$4
runTestWorkspaceWithGitRepoUrl ${WS_NAME} ${PROJECT_NAME} ${GIT_REPO_URL} ${OCP_USER_NAMESPACE}
echo "[INFO] Check the private repository is NOT cloned with NO PAT/OAuth setup"
echo "------- [INFO] Check the private repository is NOT cloned with NO PAT/OAuth setup. -------"
testProjectIsCloned ${PROJECT_NAME} ${OCP_USER_NAMESPACE} && \
{ echo "[ERROR] Project file /projects/${PROJECT_NAME}/${YAML_FILE_NAME} should NOT be present" && exit 1; }
echo "[INFO] Project file /projects/${PROJECT_NAME}/${YAML_FILE_NAME} is NOT present. This is EXPECTED"
{ echo "####### [ERROR] Project file /projects/${PROJECT_NAME}/${YAML_FILE_NAME} should NOT be present. #######
####### Cause possible: PR code regress or service is changed. Need to investigate it. #######" && exit 1; }
echo "======= [INFO] Project file /projects/${PROJECT_NAME}/${YAML_FILE_NAME} is NOT present. This is EXPECTED. ======="
}
# Test that the repository is cloned when PAT, OAuth or SSH is configured
@ -482,9 +568,10 @@ testCloneGitRepoProjectShouldExists() {
OCP_USER_NAMESPACE=$4
runTestWorkspaceWithGitRepoUrl ${WS_NAME} ${PROJECT_NAME} ${GIT_REPO_URL} ${OCP_USER_NAMESPACE}
echo "[INFO] Check the repository is cloned"
echo "------- [INFO] Check the repository is cloned. -------"
testProjectIsCloned ${PROJECT_NAME} ${OCP_USER_NAMESPACE} || \
{ echo "[ERROR] Project file /projects/${PROJECT_NAME}/${YAML_FILE_NAME} should be present." && exit 1; }
{ echo "####### [ERROR] Project file /projects/${PROJECT_NAME}/${YAML_FILE_NAME} should be present. #######
###### Cause possible: PR code regress or service is changed. Need to investigate it. #######" && exit 1; }
}
setupTestEnvironment() {

View File

@ -0,0 +1,77 @@
apiVersion: v1
kind: Pod
metadata:
name: che-smoke-test
namespace: CHE-NAMESPACE
spec:
volumes:
- name: test-run-results
- name: ffmpeg-video
- name: dshm
emptyDir:
medium: Memory
containers:
# container containing the tests
- name: test
image: quay.io/eclipse/che-e2e:next
imagePullPolicy: Always
env:
- name: VIDEO_RECORDING
value: "true"
- name: TEST_SUITE
value: "test"
- name: TS_SELENIUM_EDITOR
value: "che-code"
- name: USERSTORY
value: "SmokeTest"
- name: NODE_TLS_REJECT_UNAUTHORIZED
value: "0"
- name: TS_SELENIUM_BASE_URL
value: "CHE_URL"
- name: TS_SELENIUM_LOG_LEVEL
value: "TRACE"
- name: TS_SELENIUM_OCP_USERNAME
value: "OCP_USER_NAME"
- name: TS_SELENIUM_OCP_PASSWORD
value: "OCP_USER_PASSWORD"
- name: TS_SELENIUM_VALUE_OPENSHIFT_OAUTH
value: "true"
- name: TS_OCP_LOGIN_PAGE_PROVIDER_TITLE
value: "htpasswd"
- name: DELETE_WORKSPACE_ON_FAILED_TEST
value: "true"
- name: TS_SELENIUM_START_WORKSPACE_TIMEOUT
value: "360000"
- name: TS_IDE_LOAD_TIMEOUT
value: "40000"
volumeMounts:
- name: test-run-results
mountPath: /tmp/e2e/report/
- name: ffmpeg-video
mountPath: /tmp/ffmpeg_report/
- name: dshm
mountPath: /dev/shm
resources:
requests:
memory: "3Gi"
cpu: "2"
limits:
memory: "4Gi"
cpu: "2"
# Download results
- name: download-reports
image: eeacms/rsync
imagePullPolicy: IfNotPresent
volumeMounts:
- name: test-run-results
mountPath: /tmp/e2e/report/
- name: ffmpeg-video
mountPath: /tmp/ffmpeg_report/
resources:
command: ["sh"]
args:
[
"-c",
"while true; if [[ -f /tmp/done ]]; then exit 0; fi; do sleep 1; done",
]
restartPolicy: Never

View File

@ -12,7 +12,7 @@ spec:
medium: Memory
containers:
# container containing the tests
- name: oauth-test
- name: test
image: quay.io/eclipse/che-e2e:next
imagePullPolicy: Always
env:

View File

@ -16,6 +16,8 @@ set -ex
# only exit with zero if all commands of the pipeline exit successfully
set -o pipefail
echo "======= [INFO] OpenShift CI infrastructure is ready. Running test. ======="
export PUBLIC_REPO_RAW_PATH_URL=${PUBLIC_REPO_RAW_PATH_URL:-"https://dev.azure.com/chepullreq1/che-pr-public/_apis/git/repositories/public-repo/items?path=/devfile.yaml"}
export PRIVATE_REPO_RAW_PATH_URL=${PRIVATE_REPO_URL:-"https://dev.azure.com/chepullreq1/che-pr-private/_apis/git/repositories/private-repo/items?path=/devfile.yaml"}

View File

@ -17,6 +17,8 @@ set -ex
# only exit with zero if all commands of the pipeline exit successfully
set -o pipefail
echo "======= [INFO] OpenShift CI infrastructure is ready. Running test. ======="
export PUBLIC_REPO_SSH_URL=${PUBLIC_REPO_SSH_URL:-"git@ssh.dev.azure.com:v3/chepullreq1/che-pr-public/public-repo"}
export PRIVATE_REPO_SSH_URL=${PRIVATE_REPO_SSH_URL:-"git@ssh.dev.azure.com:v3/chepullreq1/che-pr-private/private-repo"}

View File

@ -16,6 +16,8 @@ set -ex
# only exit with zero if all commands of the pipeline exit successfully
set -o pipefail
echo "======= [INFO] OpenShift CI infrastructure is ready. Running test. ======="
export PUBLIC_REPO_URL=${PUBLIC_REPO_URL:-"https://chepullreq1@dev.azure.com/chepullreq1/che-pr-public/_git/public-repo"}
export PRIVATE_REPO_URL=${PRIVATE_REPO_URL:-"https://dev.azure.com/chepullreq1/che-pr-private/_git/private-repo"}

View File

@ -16,6 +16,8 @@ set -ex
# only exit with zero if all commands of the pipeline exit successfully
set -o pipefail
echo "======= [INFO] OpenShift CI infrastructure is ready. Running test. ======="
export PUBLIC_REPO_URL=${PUBLIC_REPO_URL:-"https://chepullreq1@dev.azure.com/chepullreq1/che-pr-public/_git/public-repo"}
export PRIVATE_REPO_URL=${PRIVATE_REPO_URL:-"https://dev.azure.com/chepullreq1/che-pr-private/_git/private-repo"}
export GIT_PROVIDER_TYPE=${GIT_PROVIDER_TYPE:-"azure-devops"}
@ -34,24 +36,24 @@ setupPersonalAccessToken ${GIT_PROVIDER_TYPE} ${GIT_PROVIDER_URL} ${AZURE_PAT}
requestProvisionNamespace
testFactoryResolverWithPatOAuth ${PUBLIC_REPO_URL} ${PRIVATE_REPO_URL}
echo "[INFO] Check clone public repository with PAT setup"
echo "------- [INFO] Check clone public repository with PAT setup -------"
testCloneGitRepoProjectShouldExists ${PUBLIC_REPO_WORKSPACE_NAME} ${PUBLIC_PROJECT_NAME} ${PUBLIC_REPO_URL} ${USER_CHE_NAMESPACE}
testGitCredentialsData ${USER_CHE_NAMESPACE} ${AZURE_PAT} ${GIT_PROVIDER_URL}
deleteTestWorkspace ${PUBLIC_REPO_WORKSPACE_NAME} ${USER_CHE_NAMESPACE}
echo "[INFO] Check clone private repository with PAT setup"
echo "------- [INFO] Check clone private repository with PAT setup -------"
testCloneGitRepoProjectShouldExists ${PRIVATE_REPO_WORKSPACE_NAME} ${PRIVATE_PROJECT_NAME} ${PRIVATE_REPO_URL} ${USER_CHE_NAMESPACE}
testGitCredentialsData ${USER_CHE_NAMESPACE} ${AZURE_PAT} ${GIT_PROVIDER_URL}
deleteTestWorkspace ${PRIVATE_REPO_WORKSPACE_NAME} ${USER_CHE_NAMESPACE}
echo "[INFO] Check clone private repository by raw devfile URL with PAT setup"
echo "------- [INFO] Check clone private repository by raw devfile URL with PAT setup -------"
testFactoryResolverResponse ${PRIVATE_REPO_RAW_PATH_URL} 200
testCloneGitRepoProjectShouldExists ${PRIVATE_REPO_WORKSPACE_NAME} ${PRIVATE_PROJECT_NAME} ${PRIVATE_REPO_RAW_PATH_URL} ${USER_CHE_NAMESPACE}
deleteTestWorkspace ${PRIVATE_REPO_WORKSPACE_NAME} ${USER_CHE_NAMESPACE}
setupSSHKeyPairs "${AZURE_PRIVATE_KEY}" "${AZURE_PUBLIC_KEY}"
echo "[INFO] Check clone private repository by SSH URL with PAT setup"
echo "------- [INFO] Check clone private repository by SSH URL with PAT setup -------"
testFactoryResolverResponse ${PRIVATE_REPO_SSH_URL} 200
testCloneGitRepoProjectShouldExists ${PRIVATE_REPO_WORKSPACE_NAME} ${PRIVATE_PROJECT_NAME} ${PRIVATE_REPO_SSH_URL} ${USER_CHE_NAMESPACE}
deleteTestWorkspace ${PRIVATE_REPO_WORKSPACE_NAME} ${USER_CHE_NAMESPACE}

View File

@ -16,6 +16,8 @@ set -ex
# only exit with zero if all commands of the pipeline exit successfully
set -o pipefail
echo "======= [INFO] OpenShift CI infrastructure is ready. Running test. ======="
export PUBLIC_REPO_RAW_PATH_URL=${PUBLIC_REPO_RAW_PATH_URL:-"https://bitbucket.org/chepullreq/public-repo/raw/746000bd63a54eaf8ea8aba9dfe6620e5c6c61d7/devfile.yaml"}
export PRIVATE_REPO_RAW_PATH_URL=${PRIVATE_REPO_URL:-"https://bitbucket.org/chepullreq/private-repo/raw/80b183d27c6c533462128b0c092208aad73b2906/devfile.yaml"}

View File

@ -17,6 +17,8 @@ set -ex
# only exit with zero if all commands of the pipeline exit successfully
set -o pipefail
echo "======= [INFO] OpenShift CI infrastructure is ready. Running test. ======="
export PUBLIC_REPO_SSH_URL=${PUBLIC_REPO_SSH_URL:-"git@bitbucket.org:chepullreq/public-repo.git"}
export PRIVATE_REPO_SSH_URL=${PRIVATE_REPO_SSH_URL:-"git@bitbucket.org:chepullreq/private-repo.git"}

View File

@ -16,6 +16,8 @@ set -ex
# only exit with zero if all commands of the pipeline exit successfully
set -o pipefail
echo "======= [INFO] OpenShift CI infrastructure is ready. Running test. ======="
export PUBLIC_REPO_URL=${PUBLIC_REPO_URL:-"https://chepullreq1@bitbucket.org/chepullreq/public-repo.git"}
export PRIVATE_REPO_URL=${PRIVATE_REPO_URL:-"https://chepullreq1@bitbucket.org/chepullreq/private-repo.git"}

View File

@ -0,0 +1,32 @@
#!/bin/bash
#
# Copyright (c) 2024 Red Hat, Inc.
# This program and the accompanying materials are made
# available under the terms of the Eclipse Public License 2.0
# which is available at https://www.eclipse.org/legal/epl-2.0/
#
# SPDX-License-Identifier: EPL-2.0
#
# Contributors:
# Red Hat, Inc. - initial API and implementation
#
# exit immediately when a command fails
set -ex
# only exit with zero if all commands of the pipeline exit successfully
set -o pipefail
echo "======= [INFO] OpenShift CI infrastructure is ready. Running test. ======="
export TEST_POD_NAME=${TEST_POD_NAME:-"che-smoke-test"}
# import common test functions
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )"
source "${SCRIPT_DIR}"/common.sh
trap "collectLogs" EXIT SIGINT
provisionOpenShiftOAuthUser
createCustomResourcesFile
deployChe
startSmokeTest

View File

@ -16,6 +16,8 @@ set -ex
# only exit with zero if all commands of the pipeline exit successfully
set -o pipefail
echo "======= [INFO] OpenShift CI infrastructure is ready. Running test. ======="
export PUBLIC_REPO_SSH_URL=${PUBLIC_REPO_SSH_URL:-"git@gitea.com:chepullreq1/public-repo.git"}
export PRIVATE_REPO_SSH_URL=${PRIVATE_REPO_SSH_URL:-"git@gitea.com:chepullreq1/private-repo.git"}
export PUBLIC_REPO_RAW_PATH_URL=${PUBLIC_REPO_RAW_PATH_URL:-"https://gitea.com/chepullreq1/public-repo/raw/branch/main/devfile.yaml"}

View File

@ -16,6 +16,8 @@ set -ex
# only exit with zero if all commands of the pipeline exit successfully
set -o pipefail
echo "======= [INFO] OpenShift CI infrastructure is ready. Running test. ======="
export PRIVATE_REPO_RAW_PATH_URL=${PRIVATE_REPO_RAW_PATH_URL:-"https://${GITEA_PAT}@gitea.com/chepullreq1/private-repo/raw/branch/main/devfile.yaml"}
# import common test functions

View File

@ -16,6 +16,8 @@ set -ex
# only exit with zero if all commands of the pipeline exit successfully
set -o pipefail
echo "======= [INFO] OpenShift CI infrastructure is ready. Running test. ======="
export PUBLIC_REPO_RAW_PATH_URL=${PUBLIC_REPO_RAW_PATH_URL:-"https://raw.githubusercontent.com/chepullreq1/public-repo/main/devfile.yaml"}
export PRIVATE_REPO_RAW_PATH_URL=${PRIVATE_REPO_URL:-"https://raw.githubusercontent.com/chepullreq1/private-repo/main/devfile.yaml"}

View File

@ -17,6 +17,8 @@ set -ex
# only exit with zero if all commands of the pipeline exit successfully
set -o pipefail
echo "======= [INFO] OpenShift CI infrastructure is ready. Running test. ======="
export PUBLIC_REPO_SSH_URL=${PUBLIC_REPO_SSH_URL:-"git@github.com:chepullreq1/public-repo.git"}
export PRIVATE_REPO_SSH_URL=${PRIVATE_REPO_SSH_URL:-"git@github.com:chepullreq1/private-repo.git"}

View File

@ -16,6 +16,8 @@ set -ex
# only exit with zero if all commands of the pipeline exit successfully
set -o pipefail
echo "======= [INFO] OpenShift CI infrastructure is ready. Running test. ======="
export PUBLIC_REPO_URL=${PUBLIC_REPO_URL:-"https://github.com/chepullreq1/public-repo.git"}
export PRIVATE_REPO_URL=${PRIVATE_REPO_URL:-"https://github.com/chepullreq1/private-repo.git"}

View File

@ -16,6 +16,8 @@ set -ex
# only exit with zero if all commands of the pipeline exit successfully
set -o pipefail
echo "======= [INFO] OpenShift CI infrastructure is ready. Running test. ======="
export PUBLIC_REPO_URL=${PUBLIC_REPO_URL:-"https://github.com/chepullreq1/public-repo.git"}
export PRIVATE_REPO_URL=${PRIVATE_REPO_URL:-"https://github.com/chepullreq1/private-repo.git"}
export GIT_PROVIDER_TYPE=${GIT_PROVIDER_TYPE:-"github"}
@ -34,24 +36,24 @@ setupPersonalAccessToken ${GIT_PROVIDER_TYPE} ${GIT_PROVIDER_URL} ${GITHUB_PAT}
requestProvisionNamespace
testFactoryResolverWithPatOAuth ${PUBLIC_REPO_URL} ${PRIVATE_REPO_URL}
echo "[INFO] Check clone public repository with PAT setup"
echo "------- [INFO] Check clone public repository with PAT setup -------"
testCloneGitRepoProjectShouldExists ${PUBLIC_REPO_WORKSPACE_NAME} ${PUBLIC_PROJECT_NAME} ${PUBLIC_REPO_URL} ${USER_CHE_NAMESPACE}
testGitCredentialsData ${USER_CHE_NAMESPACE} ${GITHUB_PAT} ${GIT_PROVIDER_URL}
deleteTestWorkspace ${PUBLIC_REPO_WORKSPACE_NAME} ${USER_CHE_NAMESPACE}
echo "[INFO] Check clone private repository with PAT setup"
echo "------- [INFO] Check clone private repository with PAT setup -------"
testCloneGitRepoProjectShouldExists ${PRIVATE_REPO_WORKSPACE_NAME} ${PRIVATE_PROJECT_NAME} ${PRIVATE_REPO_URL} ${USER_CHE_NAMESPACE}
testGitCredentialsData ${USER_CHE_NAMESPACE} ${GITHUB_PAT} ${GIT_PROVIDER_URL}
deleteTestWorkspace ${PRIVATE_REPO_WORKSPACE_NAME} ${USER_CHE_NAMESPACE}
echo "[INFO] Check clone private repository by raw devfile URL with PAT setup"
echo "------- [INFO] Check clone private repository by raw devfile URL with PAT setup -------"
testFactoryResolverResponse ${PRIVATE_REPO_RAW_PATH_URL} 200
testCloneGitRepoProjectShouldExists ${PRIVATE_REPO_WORKSPACE_NAME} ${PRIVATE_PROJECT_NAME} ${PRIVATE_REPO_RAW_PATH_URL} ${USER_CHE_NAMESPACE}
deleteTestWorkspace ${PRIVATE_REPO_WORKSPACE_NAME} ${USER_CHE_NAMESPACE}
setupSSHKeyPairs "${GITHUB_PRIVATE_KEY}" "${GITHUB_PUBLIC_KEY}"
echo "[INFO] Check clone private repository by SSH URL with PAT setup"
echo "------- [INFO] Check clone private repository by SSH URL with PAT setup -------"
testFactoryResolverResponse ${PRIVATE_REPO_SSH_URL} 200
testCloneGitRepoProjectShouldExists ${PRIVATE_REPO_WORKSPACE_NAME} ${PRIVATE_PROJECT_NAME} ${PRIVATE_REPO_SSH_URL} ${USER_CHE_NAMESPACE}
deleteTestWorkspace ${PRIVATE_REPO_WORKSPACE_NAME} ${USER_CHE_NAMESPACE}

View File

@ -16,6 +16,8 @@ set -ex
# only exit with zero if all commands of the pipeline exit successfully
set -o pipefail
echo "======= [INFO] OpenShift CI infrastructure is ready. Running test. ======="
export PUBLIC_REPO_RAW_PATH_URL=${PUBLIC_REPO_RAW_PATH_URL:-"https://gitlab.com/chepullreq1/public-repo/-/raw/main/devfile.yaml"}
export PRIVATE_REPO_RAW_PATH_URL=${PRIVATE_REPO_URL:-"https://gitlab.com/chepullreq1/private-repo/-/raw/main/devfile.yaml"}

View File

@ -17,6 +17,8 @@ set -ex
# only exit with zero if all commands of the pipeline exit successfully
set -o pipefail
echo "======= [INFO] OpenShift CI infrastructure is ready. Running test. ======="
export PUBLIC_REPO_SSH_URL=${PUBLIC_REPO_SSH_URL:-"git@gitlab.com:chepullreq1/public-repo.git"}
export PRIVATE_REPO_SSH_URL=${PRIVATE_REPO_SSH_URL:-"git@gitlab.com:chepullreq1/private-repo.git"}

View File

@ -16,6 +16,8 @@ set -ex
# only exit with zero if all commands of the pipeline exit successfully
set -o pipefail
echo "======= [INFO] OpenShift CI infrastructure is ready. Running test. ======="
export PUBLIC_REPO_URL=${PUBLIC_REPO_URL:-"https://gitlab.com/chepullreq1/public-repo.git"}
export PRIVATE_REPO_URL=${PRIVATE_REPO_URL:-"https://gitlab.com/chepullreq1/private-repo.git"}

View File

@ -16,6 +16,8 @@ set -ex
# only exit with zero if all commands of the pipeline exit successfully
set -o pipefail
echo "======= [INFO] OpenShift CI infrastructure is ready. Running test. ======="
export TEST_POD_NAME=${TEST_POD_NAME:-"oauth-factory-test"}
export GIT_PROVIDER_TYPE=${GIT_PROVIDER_TYPE:-"gitlab"}
export GIT_PROVIDER_URL=${GIT_PROVIDER_URL:-"https://gitlab-gitlab-system.apps.git.crw-qe.com"}

View File

@ -16,6 +16,8 @@ set -ex
# only exit with zero if all commands of the pipeline exit successfully
set -o pipefail
echo "======= [INFO] OpenShift CI infrastructure is ready. Running test. ======="
export PUBLIC_REPO_URL=${PUBLIC_REPO_URL:-"https://gitlab.com/chepullreq1/public-repo.git"}
export PRIVATE_REPO_URL=${PRIVATE_REPO_URL:-"https://gitlab.com/chepullreq1/private-repo.git"}
export GIT_PROVIDER_TYPE=${GIT_PROVIDER_TYPE:-"gitlab"}
@ -34,24 +36,24 @@ setupPersonalAccessToken ${GIT_PROVIDER_TYPE} ${GIT_PROVIDER_URL} ${GITLAB_PAT}
requestProvisionNamespace
testFactoryResolverWithPatOAuth ${PUBLIC_REPO_URL} ${PRIVATE_REPO_URL}
echo "[INFO] Check clone public repository with PAT setup"
echo "------- [INFO] Check clone public repository with PAT setup -------"
testCloneGitRepoProjectShouldExists ${PUBLIC_REPO_WORKSPACE_NAME} ${PUBLIC_PROJECT_NAME} ${PUBLIC_REPO_URL} ${USER_CHE_NAMESPACE}
testGitCredentialsData ${USER_CHE_NAMESPACE} ${GITLAB_PAT} ${GIT_PROVIDER_URL}
deleteTestWorkspace ${PUBLIC_REPO_WORKSPACE_NAME} ${USER_CHE_NAMESPACE}
echo "[INFO] Check clone private repository with PAT setup"
echo "------- [INFO] Check clone private repository with PAT setup -------"
testCloneGitRepoProjectShouldExists ${PRIVATE_REPO_WORKSPACE_NAME} ${PRIVATE_PROJECT_NAME} ${PRIVATE_REPO_URL} ${USER_CHE_NAMESPACE}
testGitCredentialsData ${USER_CHE_NAMESPACE} ${GITLAB_PAT} ${GIT_PROVIDER_URL}
deleteTestWorkspace ${PRIVATE_REPO_WORKSPACE_NAME} ${USER_CHE_NAMESPACE}
echo "[INFO] Check clone private repository by raw devfile URL with PAT setup"
echo "------- [INFO] Check clone private repository by raw devfile URL with PAT setup -------"
testFactoryResolverResponse ${PRIVATE_REPO_RAW_PATH_URL} 200
testCloneGitRepoProjectShouldExists ${PRIVATE_REPO_WORKSPACE_NAME} ${PRIVATE_PROJECT_NAME} ${PRIVATE_REPO_RAW_PATH_URL} ${USER_CHE_NAMESPACE}
deleteTestWorkspace ${PRIVATE_REPO_WORKSPACE_NAME} ${USER_CHE_NAMESPACE}
setupSSHKeyPairs "${GITLAB_PRIVATE_KEY}" "${GITLAB_PUBLIC_KEY}"
echo "[INFO] Check clone private repository by SSH URL with PAT setup"
echo "------- [INFO] Check clone private repository by SSH URL with PAT setup -------"
testFactoryResolverResponse ${PRIVATE_REPO_SSH_URL} 200
testCloneGitRepoProjectShouldExists ${PRIVATE_REPO_WORKSPACE_NAME} ${PRIVATE_PROJECT_NAME} ${PRIVATE_REPO_SSH_URL} ${USER_CHE_NAMESPACE}
deleteTestWorkspace ${PRIVATE_REPO_WORKSPACE_NAME} ${USER_CHE_NAMESPACE}

5
.github/CODEOWNERS vendored
View File

@ -1,11 +1,8 @@
# Global Owners
* @l0rd @ibuziuk @vinokurig @nickboldt @tolusha
* @SDawley @ibuziuk @vinokurig @tolusha
# che.properties file is quasi-documentation, so in future we might grant access to this
# assembly/assembly-wsmaster-war/src/main/webapp/WEB-INF/classes/che/** @osslate
# workspace runtime infrastructure implementations
infrastructures/** @amisevsk
# deploy
deploy/** @tolusha @dkwon17

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (c) 2012-2023 Red Hat, Inc.
Copyright (c) 2012-2024 Red Hat, Inc.
This program and the accompanying materials are made
available under the terms of the Eclipse Public License 2.0
which is available at https://www.eclipse.org/legal/epl-2.0/
@ -17,7 +17,7 @@
<parent>
<artifactId>che-assembly-parent</artifactId>
<groupId>org.eclipse.che</groupId>
<version>7.80.0-SNAPSHOT</version>
<version>7.86.0-SNAPSHOT</version>
</parent>
<artifactId>assembly-che-tomcat</artifactId>
<packaging>jar</packaging>

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (c) 2012-2023 Red Hat, Inc.
Copyright (c) 2012-2024 Red Hat, Inc.
This program and the accompanying materials are made
available under the terms of the Eclipse Public License 2.0
which is available at https://www.eclipse.org/legal/epl-2.0/
@ -17,7 +17,7 @@
<parent>
<artifactId>che-assembly-parent</artifactId>
<groupId>org.eclipse.che</groupId>
<version>7.80.0-SNAPSHOT</version>
<version>7.86.0-SNAPSHOT</version>
</parent>
<artifactId>assembly-main</artifactId>
<packaging>pom</packaging>

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (c) 2012-2023 Red Hat, Inc.
Copyright (c) 2012-2024 Red Hat, Inc.
This program and the accompanying materials are made
available under the terms of the Eclipse Public License 2.0
which is available at https://www.eclipse.org/legal/epl-2.0/
@ -17,7 +17,7 @@
<parent>
<artifactId>che-assembly-parent</artifactId>
<groupId>org.eclipse.che</groupId>
<version>7.80.0-SNAPSHOT</version>
<version>7.86.0-SNAPSHOT</version>
</parent>
<artifactId>assembly-root-war</artifactId>
<packaging>war</packaging>

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (c) 2012-2023 Red Hat, Inc.
Copyright (c) 2012-2024 Red Hat, Inc.
This program and the accompanying materials are made
available under the terms of the Eclipse Public License 2.0
which is available at https://www.eclipse.org/legal/epl-2.0/
@ -17,7 +17,7 @@
<parent>
<artifactId>che-assembly-parent</artifactId>
<groupId>org.eclipse.che</groupId>
<version>7.80.0-SNAPSHOT</version>
<version>7.86.0-SNAPSHOT</version>
</parent>
<artifactId>assembly-swagger-war</artifactId>
<packaging>war</packaging>

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (c) 2012-2023 Red Hat, Inc.
Copyright (c) 2012-2024 Red Hat, Inc.
This program and the accompanying materials are made
available under the terms of the Eclipse Public License 2.0
which is available at https://www.eclipse.org/legal/epl-2.0/
@ -17,7 +17,7 @@
<parent>
<artifactId>che-assembly-parent</artifactId>
<groupId>org.eclipse.che</groupId>
<version>7.80.0-SNAPSHOT</version>
<version>7.86.0-SNAPSHOT</version>
</parent>
<artifactId>assembly-wsmaster-war</artifactId>
<packaging>war</packaging>
@ -91,10 +91,6 @@
<groupId>net.logstash.logback</groupId>
<artifactId>logstash-logback-encoder</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.che.core</groupId>
<artifactId>che-core-api-account</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.che.core</groupId>
<artifactId>che-core-api-auth</artifactId>
@ -159,10 +155,6 @@
<groupId>org.eclipse.che.core</groupId>
<artifactId>che-core-api-logger</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.che.core</groupId>
<artifactId>che-core-api-metrics</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.che.core</groupId>
<artifactId>che-core-api-ssh</artifactId>
@ -199,18 +191,6 @@
<groupId>org.eclipse.che.core</groupId>
<artifactId>che-core-commons-schedule</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.che.core</groupId>
<artifactId>che-core-db</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.che.core</groupId>
<artifactId>che-core-db-vendor-h2</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.che.core</groupId>
<artifactId>che-core-db-vendor-postgresql</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.che.core</groupId>
<artifactId>che-core-logback</artifactId>
@ -355,10 +335,6 @@
<groupId>org.everrest</groupId>
<artifactId>everrest-integration-guice</artifactId>
</dependency>
<dependency>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-core</artifactId>
</dependency>
<dependency>
<groupId>org.jgroups</groupId>
<artifactId>jgroups</artifactId>

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012-2023 Red Hat, Inc.
* Copyright (c) 2012-2024 Red Hat, Inc.
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
@ -26,7 +26,6 @@ import io.jsonwebtoken.JwtParser;
import io.jsonwebtoken.SigningKeyResolver;
import java.util.HashMap;
import java.util.Map;
import javax.sql.DataSource;
import org.eclipse.che.api.core.notification.RemoteSubscriptionStorage;
import org.eclipse.che.api.core.rest.CheJsonProvider;
import org.eclipse.che.api.core.rest.MessageBodyAdapter;
@ -53,7 +52,6 @@ import org.eclipse.che.api.factory.server.github.GithubScmFileResolver;
import org.eclipse.che.api.factory.server.github.GithubScmFileResolverSecond;
import org.eclipse.che.api.factory.server.gitlab.GitlabFactoryParametersResolver;
import org.eclipse.che.api.factory.server.gitlab.GitlabScmFileResolver;
import org.eclipse.che.api.metrics.WsMasterMetricsModule;
import org.eclipse.che.api.system.server.ServiceTermination;
import org.eclipse.che.api.system.server.SystemModule;
import org.eclipse.che.api.user.server.NotImplementedTokenValidator;
@ -86,13 +84,10 @@ import org.eclipse.che.api.workspace.server.spi.provision.env.WorkspaceNameEnvVa
import org.eclipse.che.api.workspace.server.spi.provision.env.WorkspaceNamespaceNameEnvVarProvider;
import org.eclipse.che.api.workspace.server.wsplugins.ChePluginsApplier;
import org.eclipse.che.commons.observability.deploy.ExecutorWrapperModule;
import org.eclipse.che.core.db.DBTermination;
import org.eclipse.che.core.db.schema.SchemaInitializer;
import org.eclipse.che.core.tracing.metrics.TracingMetricsModule;
import org.eclipse.che.inject.DynaModule;
import org.eclipse.che.multiuser.api.authentication.commons.token.HeaderRequestTokenExtractor;
import org.eclipse.che.multiuser.api.authentication.commons.token.RequestTokenExtractor;
import org.eclipse.che.multiuser.api.permission.server.AdminPermissionInitializer;
import org.eclipse.che.multiuser.api.permission.server.PermissionChecker;
import org.eclipse.che.multiuser.api.permission.server.PermissionCheckerImpl;
import org.eclipse.che.multiuser.api.workspace.activity.MultiUserWorkspaceActivityModule;
@ -127,7 +122,6 @@ import org.eclipse.che.workspace.infrastructure.openshift.OpenShiftInfrastructur
import org.eclipse.che.workspace.infrastructure.openshift.environment.OpenShiftEnvironment;
import org.eclipse.che.workspace.infrastructure.openshift.multiuser.oauth.KeycloakProviderConfigFactory;
import org.eclipse.persistence.config.PersistenceUnitProperties;
import org.flywaydb.core.internal.util.PlaceholderReplacer;
/** @author andrew00x */
@DynaModule
@ -143,18 +137,10 @@ public class WsMasterModule extends AbstractModule {
}
// db related components modules
install(new org.eclipse.che.account.api.AccountModule());
install(new org.eclipse.che.api.ssh.server.jpa.SshJpaModule());
install(new org.eclipse.che.api.core.jsonrpc.impl.JsonRpcModule());
install(new org.eclipse.che.api.core.websocket.impl.WebSocketModule());
// db configuration
bind(SchemaInitializer.class)
.to(org.eclipse.che.core.db.schema.impl.flyway.FlywaySchemaInitializer.class);
bind(org.eclipse.che.core.db.DBInitializer.class).asEagerSingleton();
bind(PlaceholderReplacer.class)
.toProvider(org.eclipse.che.core.db.schema.impl.flyway.PlaceholderReplacerProvider.class);
// factory
bind(FactoryAcceptValidator.class)
.to(org.eclipse.che.api.factory.server.impl.FactoryAcceptValidatorImpl.class);
@ -213,9 +199,7 @@ public class WsMasterModule extends AbstractModule {
install(new DevfileModule());
bind(WorkspaceEntityProvider.class);
bind(org.eclipse.che.api.workspace.server.TemporaryWorkspaceRemover.class);
bind(org.eclipse.che.api.workspace.server.WorkspaceService.class);
bind(org.eclipse.che.api.devfile.server.DevfileService.class);
bind(org.eclipse.che.api.devfile.server.UserDevfileEntityProvider.class);
install(new FactoryModuleBuilder().build(ServersCheckerFactory.class));
@ -282,10 +266,6 @@ public class WsMasterModule extends AbstractModule {
terminationMultiBinder
.addBinding()
.to(org.eclipse.che.api.system.server.CronThreadPullTermination.class);
terminationMultiBinder
.addBinding()
.to(org.eclipse.che.api.workspace.server.hc.probe.ProbeSchedulerTermination.class);
bind(DBTermination.class);
final Map<String, String> persistenceProperties = new HashMap<>();
persistenceProperties.put(PersistenceUnitProperties.TARGET_SERVER, "None");
@ -328,7 +308,6 @@ public class WsMasterModule extends AbstractModule {
}
if (Boolean.valueOf(System.getenv("CHE_METRICS_ENABLED"))) {
install(new org.eclipse.che.core.metrics.MetricsModule());
install(new WsMasterMetricsModule());
install(new InfrastructureMetricsModule());
} else {
install(new org.eclipse.che.core.metrics.NoopMetricsModule());
@ -369,9 +348,6 @@ public class WsMasterModule extends AbstractModule {
persistenceProperties.put(
PersistenceUnitProperties.EXCEPTION_HANDLER_CLASS,
"org.eclipse.che.core.db.postgresql.jpa.eclipselink.PostgreSqlExceptionHandler");
bind(DataSource.class).toProvider(org.eclipse.che.core.db.JndiDataSourceProvider.class);
install(new org.eclipse.che.multiuser.api.permission.server.jpa.SystemPermissionsJpaModule());
install(
new org.eclipse.che.multiuser.permission.workspace.server.WorkspaceApiPermissionsModule());
@ -420,7 +396,6 @@ public class WsMasterModule extends AbstractModule {
bind(OAuthAPI.class).to(EmbeddedOAuthAPI.class).asEagerSingleton();
}
bind(AdminPermissionInitializer.class).asEagerSingleton();
install(new MachineAuthModule());
// User and profile - use profile from keycloak and other stuff is JPA

View File

@ -1,5 +1,5 @@
#
# Copyright (c) 2012-2023 Red Hat, Inc.
# Copyright (c) 2012-2024 Red Hat, Inc.
# This program and the accompanying materials are made
# available under the terms of the Eclipse Public License 2.0
# which is available at https://www.eclipse.org/legal/epl-2.0/
@ -91,10 +91,6 @@ che.workspace.server.liveness_probes=wsagent/http,exec-agent/http,terminal,theia
# The default is: 10MB=10485760.
che.workspace.startup_debug_log_limit_bytes=10485760
# If set to `true`, 'stop-workspace' role with the edit privileges is granted to the 'che' ServiceAccount if OpenShift OAuth is enabled.
# This configuration is mainly required for workspace idling when the OpenShift OAuth is enabled.
che.workspace.stop.role.enabled=true
# Specifies whether {prod-short} is deployed with DevWorkspaces enabled.
# This property is set by the {prod-short} Operator if it also installed the support for DevWorkspaces.
# This property is used to advertise this fact to the {prod-short} dashboard.

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012-2021 Red Hat, Inc.
* Copyright (c) 2012-2024 Red Hat, Inc.
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
@ -37,6 +37,7 @@ import org.reflections.scanners.FieldAnnotationsScanner;
import org.reflections.scanners.MethodAnnotationsScanner;
import org.reflections.scanners.MethodParameterScanner;
import org.testng.Assert;
import org.testng.annotations.Ignore;
import org.testng.annotations.Test;
public class IntegrityConfigurationTest {
@ -125,6 +126,7 @@ public class IntegrityConfigurationTest {
}
@Test
@Ignore
public void shouldNotDeclareUnused() {
Reflections reflections =
new Reflections(

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (c) 2012-2023 Red Hat, Inc.
Copyright (c) 2012-2024 Red Hat, Inc.
This program and the accompanying materials are made
available under the terms of the Eclipse Public License 2.0
which is available at https://www.eclipse.org/legal/epl-2.0/
@ -17,7 +17,7 @@
<parent>
<artifactId>che-server</artifactId>
<groupId>org.eclipse.che</groupId>
<version>7.80.0-SNAPSHOT</version>
<version>7.86.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>che-assembly-parent</artifactId>

View File

@ -10,7 +10,7 @@
#
# https://access.redhat.com/containers/?tab=tags#/registry.access.redhat.com/ubi8-minimal
FROM registry.access.redhat.com/ubi8-minimal:8.9-1029
FROM registry.access.redhat.com/ubi8-minimal:8.9-1161
USER root
ENV CHE_HOME=/home/user/eclipse-che
ENV JAVA_HOME=/usr/lib/jvm/jre

View File

@ -10,7 +10,7 @@
#
# https://access.redhat.com/containers/?tab=tags#/registry.access.redhat.com/ubi8-minimal
FROM ubi8-minimal:8.9-1029
FROM ubi8-minimal:8.9-1161
USER root
ENV CHE_HOME=/home/user/devspaces
ENV JAVA_HOME=/usr/lib/jvm/jre

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (c) 2012-2023 Red Hat, Inc.
Copyright (c) 2012-2024 Red Hat, Inc.
This program and the accompanying materials are made
available under the terms of the Eclipse Public License 2.0
which is available at https://www.eclipse.org/legal/epl-2.0/
@ -17,7 +17,7 @@
<parent>
<artifactId>che-core-parent</artifactId>
<groupId>org.eclipse.che.core</groupId>
<version>7.80.0-SNAPSHOT</version>
<version>7.86.0-SNAPSHOT</version>
</parent>
<artifactId>che-core-api-core</artifactId>
<packaging>jar</packaging>

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (c) 2012-2023 Red Hat, Inc.
Copyright (c) 2012-2024 Red Hat, Inc.
This program and the accompanying materials are made
available under the terms of the Eclipse Public License 2.0
which is available at https://www.eclipse.org/legal/epl-2.0/
@ -17,7 +17,7 @@
<parent>
<artifactId>che-core-parent</artifactId>
<groupId>org.eclipse.che.core</groupId>
<version>7.80.0-SNAPSHOT</version>
<version>7.86.0-SNAPSHOT</version>
</parent>
<artifactId>che-core-api-dto-maven-plugin</artifactId>
<packaging>maven-plugin</packaging>

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (c) 2012-2023 Red Hat, Inc.
Copyright (c) 2012-2024 Red Hat, Inc.
This program and the accompanying materials are made
available under the terms of the Eclipse Public License 2.0
which is available at https://www.eclipse.org/legal/epl-2.0/
@ -17,7 +17,7 @@
<parent>
<artifactId>che-core-parent</artifactId>
<groupId>org.eclipse.che.core</groupId>
<version>7.80.0-SNAPSHOT</version>
<version>7.86.0-SNAPSHOT</version>
</parent>
<artifactId>che-core-api-dto</artifactId>
<packaging>jar</packaging>

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (c) 2012-2023 Red Hat, Inc.
Copyright (c) 2012-2024 Red Hat, Inc.
This program and the accompanying materials are made
available under the terms of the Eclipse Public License 2.0
which is available at https://www.eclipse.org/legal/epl-2.0/
@ -17,7 +17,7 @@
<parent>
<artifactId>che-core-parent</artifactId>
<groupId>org.eclipse.che.core</groupId>
<version>7.80.0-SNAPSHOT</version>
<version>7.86.0-SNAPSHOT</version>
</parent>
<artifactId>che-core-api-model</artifactId>
<packaging>jar</packaging>

View File

@ -1,47 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (c) 2012-2023 Red Hat, Inc.
This program and the accompanying materials are made
available under the terms of the Eclipse Public License 2.0
which is available at https://www.eclipse.org/legal/epl-2.0/
SPDX-License-Identifier: EPL-2.0
Contributors:
Red Hat, Inc. - initial API and implementation
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>che-core-parent</artifactId>
<groupId>org.eclipse.che.core</groupId>
<version>7.80.0-SNAPSHOT</version>
</parent>
<artifactId>che-core-db-vendor-h2</artifactId>
<name>Che Core :: Commons :: DB :: Vendor H2</name>
<dependencies>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.che.core</groupId>
<artifactId>che-core-db</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.persistence</groupId>
<artifactId>org.eclipse.persistence.core</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.persistence</groupId>
<artifactId>jakarta.persistence</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
</project>

View File

@ -1,40 +0,0 @@
/*
* Copyright (c) 2012-2018 Red Hat, Inc.
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.core.db.h2.jpa.eclipselink;
import java.sql.SQLException;
import org.eclipse.che.core.db.jpa.DuplicateKeyException;
import org.eclipse.che.core.db.jpa.IntegrityConstraintViolationException;
import org.eclipse.persistence.exceptions.DatabaseException;
import org.eclipse.persistence.exceptions.ExceptionHandler;
/**
* Rethrows vendor specific exceptions as common exceptions. See <a
* href="http://www.h2database.com/javadoc/org/h2/api/ErrorCode.html">H2 error codes</a>.
*
* @author Yevhenii Voevodin
*/
public class H2ExceptionHandler implements ExceptionHandler {
public Object handleException(RuntimeException exception) {
if (exception instanceof DatabaseException && exception.getCause() instanceof SQLException) {
final SQLException sqlEx = (SQLException) exception.getCause();
switch (sqlEx.getErrorCode()) {
case 23505:
throw new DuplicateKeyException(exception.getMessage(), exception);
case 23506:
throw new IntegrityConstraintViolationException(exception.getMessage(), exception);
}
}
throw exception;
}
}

View File

@ -1,47 +0,0 @@
/*
* Copyright (c) 2012-2023 Red Hat, Inc.
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.core.db.h2.jpa.eclipselink;
import static com.google.common.base.MoreObjects.firstNonNull;
import org.eclipse.che.core.db.JNDIDataSourceFactory;
public class H2SQLJndiDataSourceFactory extends JNDIDataSourceFactory {
private static final String DEFAULT_USERNAME = "username";
private static final String DEFAULT_PASSWORD = "password";
private static final String DEFAULT_URL = "jdbc:h2:file:/data/h2";
private static final String DEFAULT_DRIVER__CLASS__NAME = "org.h2.Driver";
private static final String DEFAULT_MAX__TOTAL = "20";
private static final String DEFAULT_MAX__IDLE = "2";
private static final String DEFAULT_MAX__WAIT__MILLIS = "-1";
public H2SQLJndiDataSourceFactory() throws Exception {
super(
firstNonNull(
nullStringToNullReference(System.getenv("CHE_JDBC_USERNAME")), DEFAULT_USERNAME),
firstNonNull(
nullStringToNullReference(System.getenv("CHE_JDBC_PASSWORD")), DEFAULT_PASSWORD),
firstNonNull(nullStringToNullReference(System.getenv("CHE_JDBC_H2_URL")), DEFAULT_URL),
firstNonNull(
nullStringToNullReference(System.getenv("CHE_JDBC_DRIVER__CLASS__NAME")),
DEFAULT_DRIVER__CLASS__NAME),
firstNonNull(
nullStringToNullReference(System.getenv("CHE_JDBC_MAX__TOTAL")), DEFAULT_MAX__TOTAL),
firstNonNull(
nullStringToNullReference(System.getenv("CHE_JDBC_MAX__IDLE")), DEFAULT_MAX__IDLE),
firstNonNull(
nullStringToNullReference(System.getenv("CHE_JDBC_MAX__WAIT__MILLIS")),
DEFAULT_MAX__WAIT__MILLIS));
;
}
}

View File

@ -1,39 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (c) 2012-2023 Red Hat, Inc.
This program and the accompanying materials are made
available under the terms of the Eclipse Public License 2.0
which is available at https://www.eclipse.org/legal/epl-2.0/
SPDX-License-Identifier: EPL-2.0
Contributors:
Red Hat, Inc. - initial API and implementation
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>che-core-parent</artifactId>
<groupId>org.eclipse.che.core</groupId>
<version>7.80.0-SNAPSHOT</version>
</parent>
<artifactId>che-core-db-vendor-mysql</artifactId>
<name>Che Core :: Commons :: DB :: Vendor MySQL</name>
<dependencies>
<dependency>
<groupId>org.eclipse.che.core</groupId>
<artifactId>che-core-db</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.persistence</groupId>
<artifactId>org.eclipse.persistence.core</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.persistence</groupId>
<artifactId>jakarta.persistence</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
</project>

View File

@ -1,40 +0,0 @@
/*
* Copyright (c) 2012-2018 Red Hat, Inc.
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.core.db.mysql.jpa.eclipselink;
import java.sql.SQLException;
import org.eclipse.che.core.db.jpa.DuplicateKeyException;
import org.eclipse.che.core.db.jpa.IntegrityConstraintViolationException;
import org.eclipse.persistence.exceptions.DatabaseException;
import org.eclipse.persistence.exceptions.ExceptionHandler;
/**
* Rethrows vendor specific exceptions as common exceptions. See <a
* href="https://dev.mysql.com/doc/refman/8.0/en/error-messages-server.html">MySQL error codes</a>.
*
* @author Barry Dresdner
*/
public class MySqlExceptionHandler implements ExceptionHandler {
@Override
public Object handleException(RuntimeException exception) {
if (exception instanceof DatabaseException && exception.getCause() instanceof SQLException) {
final SQLException sqlEx = (SQLException) exception.getCause();
switch (sqlEx.getErrorCode()) {
case 1062:
throw new DuplicateKeyException(exception.getMessage(), exception);
case 1452:
throw new IntegrityConstraintViolationException(exception.getMessage(), exception);
}
}
throw exception;
}
}

View File

@ -1,43 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (c) 2012-2023 Red Hat, Inc.
This program and the accompanying materials are made
available under the terms of the Eclipse Public License 2.0
which is available at https://www.eclipse.org/legal/epl-2.0/
SPDX-License-Identifier: EPL-2.0
Contributors:
Red Hat, Inc. - initial API and implementation
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>che-core-parent</artifactId>
<groupId>org.eclipse.che.core</groupId>
<version>7.80.0-SNAPSHOT</version>
</parent>
<artifactId>che-core-db-vendor-postgresql</artifactId>
<name>Che Core :: Commons :: DB :: Vendor PostgreSQL</name>
<dependencies>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.che.core</groupId>
<artifactId>che-core-db</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.persistence</groupId>
<artifactId>org.eclipse.persistence.core</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.persistence</groupId>
<artifactId>jakarta.persistence</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
</project>

View File

@ -1,51 +0,0 @@
/*
* Copyright (c) 2012-2018 Red Hat, Inc.
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.core.db.postgresql;
import static com.google.common.base.MoreObjects.firstNonNull;
import org.eclipse.che.core.db.JNDIDataSourceFactory;
/**
* Environment params based JNDI data source factory for Postgres.
*
* @author Sergii Kabashniuk
*/
public class PostgreSQLJndiDataSourceFactory extends JNDIDataSourceFactory {
private static final String DEFAULT_USERNAME = "pgche";
private static final String DEFAULT_PASSWORD = "pgchepassword";
private static final String DEFAULT_URL = "jdbc:postgresql://postgres:5432/dbche";
private static final String DEFAULT_DRIVER__CLASS__NAME = "org.postgresql.Driver";
private static final String DEFAULT_MAX__TOTAL = "20";
private static final String DEFAULT_MAX__IDLE = "2";
private static final String DEFAULT_MAX__WAIT__MILLIS = "-1";
public PostgreSQLJndiDataSourceFactory() throws Exception {
super(
firstNonNull(
nullStringToNullReference(System.getenv("CHE_JDBC_USERNAME")), DEFAULT_USERNAME),
firstNonNull(
nullStringToNullReference(System.getenv("CHE_JDBC_PASSWORD")), DEFAULT_PASSWORD),
firstNonNull(nullStringToNullReference(System.getenv("CHE_JDBC_URL")), DEFAULT_URL),
firstNonNull(
nullStringToNullReference(System.getenv("CHE_JDBC_DRIVER__CLASS__NAME")),
DEFAULT_DRIVER__CLASS__NAME),
firstNonNull(
nullStringToNullReference(System.getenv("CHE_JDBC_MAX__TOTAL")), DEFAULT_MAX__TOTAL),
firstNonNull(
nullStringToNullReference(System.getenv("CHE_JDBC_MAX__IDLE")), DEFAULT_MAX__IDLE),
firstNonNull(
nullStringToNullReference(System.getenv("CHE_JDBC_MAX__WAIT__MILLIS")),
DEFAULT_MAX__WAIT__MILLIS));
}
}

View File

@ -1,41 +0,0 @@
/*
* Copyright (c) 2012-2018 Red Hat, Inc.
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.core.db.postgresql.jpa.eclipselink;
import java.sql.SQLException;
import org.eclipse.che.core.db.jpa.DuplicateKeyException;
import org.eclipse.che.core.db.jpa.IntegrityConstraintViolationException;
import org.eclipse.persistence.exceptions.DatabaseException;
import org.eclipse.persistence.exceptions.ExceptionHandler;
/**
* Rethrows vendor specific exceptions as common exceptions. See <a
* href="https://www.postgresql.org/docs/9.4/static/errcodes-appendix.html">PostgreSQL error
* codes</a>.
*
* @author Yevhenii Voevodin
* @author Sergii Kabashniuk
*/
public class PostgreSqlExceptionHandler implements ExceptionHandler {
public Object handleException(RuntimeException exception) {
if (exception instanceof DatabaseException && exception.getCause() instanceof SQLException) {
final SQLException sqlEx = (SQLException) exception.getCause();
switch (sqlEx.getSQLState()) {
case "23505":
throw new DuplicateKeyException(exception.getMessage(), exception);
case "23503":
throw new IntegrityConstraintViolationException(exception.getMessage(), exception);
}
}
throw exception;
}
}

View File

@ -1,113 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (c) 2012-2023 Red Hat, Inc.
This program and the accompanying materials are made
available under the terms of the Eclipse Public License 2.0
which is available at https://www.eclipse.org/legal/epl-2.0/
SPDX-License-Identifier: EPL-2.0
Contributors:
Red Hat, Inc. - initial API and implementation
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>che-core-parent</artifactId>
<groupId>org.eclipse.che.core</groupId>
<version>7.80.0-SNAPSHOT</version>
</parent>
<artifactId>che-core-db</artifactId>
<name>Che Core :: Commons :: DB</name>
<dependencies>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</dependency>
<dependency>
<groupId>com.google.inject</groupId>
<artifactId>guice</artifactId>
</dependency>
<dependency>
<groupId>com.google.inject.extensions</groupId>
<artifactId>guice-persist</artifactId>
</dependency>
<dependency>
<groupId>io.opentracing</groupId>
<artifactId>opentracing-util</artifactId>
</dependency>
<dependency>
<groupId>io.opentracing.contrib</groupId>
<artifactId>opentracing-jdbc</artifactId>
</dependency>
<dependency>
<groupId>jakarta.inject</groupId>
<artifactId>jakarta.inject-api</artifactId>
</dependency>
<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-dbcp</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.che.core</groupId>
<artifactId>che-core-api-core</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.che.core</groupId>
<artifactId>che-core-commons-inject</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.persistence</groupId>
<artifactId>org.eclipse.persistence.core</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.persistence</groupId>
<artifactId>org.eclipse.persistence.extension</artifactId>
</dependency>
<dependency>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-core</artifactId>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.persistence</groupId>
<artifactId>jakarta.persistence</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.eclipse.che.core</groupId>
<artifactId>che-core-commons-lang</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-testng</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>

View File

@ -1,43 +0,0 @@
/*
* Copyright (c) 2012-2018 Red Hat, Inc.
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.core.db;
/**
* Defines common database error codes which should be used throughout the application in preference
* to vendor specific error codes.
*
* @author Yevhenii Voevodin
*/
public enum DBErrorCode {
/** When database error can't be described with one of the other values of this enumeration. */
UNDEFINED(-1),
/**
* When any of the unique constraints is violated e.g. duplicate key or unique index violation.
*/
DUPLICATE_KEY(1),
/** When entity referenced foreign key does not exist */
INTEGRITY_CONSTRAINT_VIOLATION(2);
private final int code;
DBErrorCode(int code) {
this.code = code;
}
/** Returns the code of this error. */
public int getCode() {
return code;
}
}

View File

@ -1,89 +0,0 @@
/*
* Copyright (c) 2012-2018 Red Hat, Inc.
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.core.db;
import com.google.common.collect.ImmutableMap;
import java.util.Map;
import javax.inject.Inject;
import javax.inject.Singleton;
import javax.persistence.EntityManagerFactory;
import org.eclipse.che.core.db.jpa.JpaInitializer;
import org.eclipse.che.core.db.jpa.eclipselink.GuiceEntityListenerInjectionManager;
import org.eclipse.che.core.db.schema.SchemaInitializationException;
import org.eclipse.che.core.db.schema.SchemaInitializer;
import org.eclipse.persistence.internal.sessions.AbstractSession;
/**
* Initializes database components.
*
* <p>Those components which require any persistence operations on their bootstrap have to depend on
* this component. For example:
*
* <pre>
* class StackExistsChecker {
*
* &#064;@Inject
* &#064;SuppressWarnings("unused")
* private DBInitializer dbInitializer;
*
* &#064;PostConstruct
* public void check() {
* ....
* }
* }
* </pre>
*
* In this way it is guaranteed that all database related components will be appropriately
* initialized before {@code check} method is executed.
*
* @author Yevhenii Voevodin
*/
@Singleton
public class DBInitializer {
/**
* when value for this key true, then its mean that db is initialized at first time, otherwise db
* was previously initialized
*/
public static final String BARE_DB_INIT_PROPERTY_NAME = "bare_database_init";
private final Map<String, String> initProperties;
@Inject
public DBInitializer(SchemaInitializer schemaInitializer, JpaInitializer jpaInitializer)
throws SchemaInitializationException {
// schema must be initialized before any other component that may interact with database
initProperties = ImmutableMap.copyOf(schemaInitializer.init());
// jpa initialization goes next
jpaInitializer.init();
}
@Inject
public void setUpInjectionManager(
GuiceEntityListenerInjectionManager injManager, EntityManagerFactory emFactory) {
final AbstractSession session = emFactory.unwrap(AbstractSession.class);
session.setInjectionManager(injManager);
}
/** Returns map of properties which represents state of database while initialization process */
public Map<String, String> getInitProperties() {
return initProperties;
}
/**
* Returns true only if database was initialized at first time otherwise false would be returned
*/
public boolean isBareInit() {
return Boolean.parseBoolean(initProperties.get(BARE_DB_INIT_PROPERTY_NAME));
}
}

View File

@ -1,84 +0,0 @@
/*
* Copyright (c) 2012-2021 Red Hat, Inc.
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.core.db;
import com.google.inject.Inject;
import com.google.inject.persist.PersistService;
import java.lang.reflect.Field;
import javax.inject.Singleton;
import javax.persistence.EntityManagerFactory;
import org.eclipse.persistence.internal.sessions.AbstractSession;
import org.eclipse.persistence.internal.sessions.coordination.jgroups.JGroupsRemoteConnection;
import org.eclipse.persistence.sessions.coordination.CommandManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Stops {@link PersistService} when a system is ready to shutdown.
*
* @author Anton Korneta
*/
@Singleton
public class DBTermination {
private static final Logger LOG = LoggerFactory.getLogger(DBTermination.class);
private final PersistService persistService;
private final EntityManagerFactory emFactory;
@Inject
public DBTermination(PersistService persistService, EntityManagerFactory emFactory) {
this.persistService = persistService;
this.emFactory = emFactory;
}
/** Stops {@link PersistService}. Any DB operations are impossible after that. */
public void terminate() {
try {
LOG.info("Stopping persistence service.");
fixJChannelClosing(emFactory);
persistService.stop();
} catch (RuntimeException ex) {
LOG.error("Failed to stop persistent service. Cause: " + ex.getMessage());
}
}
/**
* This method is hack that changes value of {@link JGroupsRemoteConnection#isLocal} to false.
* This is needed to close the JGroups EclipseLinkCommandChannel and as result gracefully stop of
* the system.<br>
* For more details see {@link JGroupsRemoteConnection#closeInternal()}
*
* <p>The corresponding eclipse-link extension issue
* https://bugs.eclipse.org/bugs/show_bug.cgi?id=534148
*/
private void fixJChannelClosing(EntityManagerFactory emFactory) {
try {
final AbstractSession session = emFactory.unwrap(AbstractSession.class);
CommandManager commandManager = session.getCommandManager();
if (commandManager == null) {
// not cluster mode
return;
}
final JGroupsRemoteConnection conn =
(JGroupsRemoteConnection) commandManager.getTransportManager().getConnectionToLocalHost();
final Field isLocal = conn.getClass().getDeclaredField("isLocal");
isLocal.setAccessible(true);
isLocal.set(conn, false);
} catch (IllegalAccessException | NoSuchFieldException ex) {
LOG.error(
"Failed to change JGroupsRemoteConnection#isLocal. This may prevent the graceful stop of "
+ "the system because EclipseLinkCommandChannel will not be closed. Cause: "
+ ex.getMessage());
}
}
}

View File

@ -1,79 +0,0 @@
/*
* Copyright (c) 2012-2018 Red Hat, Inc.
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.core.db;
import static org.apache.tomcat.dbcp.dbcp2.BasicDataSourceFactory.createDataSource;
import static org.eclipse.che.core.db.TracingDataSource.wrapWithTracingIfEnabled;
import java.util.Hashtable;
import java.util.Properties;
import javax.naming.Context;
import javax.naming.Name;
import javax.naming.spi.ObjectFactory;
import javax.sql.DataSource;
import org.apache.tomcat.dbcp.dbcp2.BasicDataSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Abstract JNDI factory that constructs {@link BasicDataSource} objects from the given params.
* Should not be used directly and must be subclassed to provide instantiation params from needful
* source.
*
* @author Sergii Kabashniuk
*/
public abstract class JNDIDataSourceFactory implements ObjectFactory {
private static final Logger LOG = LoggerFactory.getLogger(JNDIDataSourceFactory.class);
private final DataSource dataSource;
public JNDIDataSourceFactory(
String userName,
String password,
String url,
String driverClassName,
String maxTotal,
String maxIdle,
String maxWaitMillis)
throws Exception {
Properties poolConfigurationProperties = new Properties();
poolConfigurationProperties.setProperty("username", userName);
poolConfigurationProperties.setProperty("password", password);
poolConfigurationProperties.setProperty("url", url);
poolConfigurationProperties.setProperty("driverClassName", driverClassName);
poolConfigurationProperties.setProperty("maxTotal", maxTotal);
poolConfigurationProperties.setProperty("maxIdle", maxIdle);
poolConfigurationProperties.setProperty("maxWaitMillis", maxWaitMillis);
dataSource = wrapWithTracingIfEnabled(createDataSource(poolConfigurationProperties));
}
@Override
public Object getObjectInstance(
Object obj, Name name, Context nameCtx, Hashtable<?, ?> environment) throws Exception {
LOG.info(
"This={} obj={} name={} Context={} environment={}", this, obj, name, nameCtx, environment);
return dataSource;
}
/**
* Util method to convert string {@code "NULL"} to null reference. Allows to set string {@code
* "NULL"} as a value of the property instead of making sure it is unset as it is done in {@link
* org.eclipse.che.inject.CheBootstrap}
*
* @param value value to transform if needed
* @return null or passed value
*/
protected static String nullStringToNullReference(String value) {
return "NULL".equals(value) ? null : value;
}
}

View File

@ -1,41 +0,0 @@
/*
* Copyright (c) 2012-2018 Red Hat, Inc.
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.core.db;
import com.google.inject.Inject;
import javax.inject.Named;
import javax.inject.Provider;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.sql.DataSource;
/**
* Provides data source based on jndi resource name.
*
* @author Yevhenii Voevodin
*/
public class JndiDataSourceProvider implements Provider<DataSource> {
@Inject
@Named("jndi.datasource.name")
private String name;
@Override
public DataSource get() {
try {
final InitialContext context = new InitialContext();
return (DataSource) context.lookup(name);
} catch (NamingException x) {
throw new IllegalStateException(x.getLocalizedMessage(), x);
}
}
}

View File

@ -1,106 +0,0 @@
/*
* Copyright (c) 2012-2021 Red Hat, Inc.
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.core.db;
import com.google.common.annotations.Beta;
import io.opentracing.contrib.jdbc.ConnectionInfo;
import io.opentracing.contrib.jdbc.TracingConnection;
import io.opentracing.contrib.jdbc.parser.URLParser;
import io.opentracing.util.GlobalTracer;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.SQLFeatureNotSupportedException;
import java.util.logging.Logger;
import javax.sql.DataSource;
import org.slf4j.LoggerFactory;
/**
* Adding tracing support for existing @{@link javax.sql.DataSource}. DbType and DbUser information
* omitted in traces. Traced are made only if active span exists. Prerequisites of using this class
* is that @{@link io.opentracing.Tracer} should be set in @{@link io.opentracing.util.GlobalTracer}
*
* @author Sergii Kabashniuk
*/
@Beta
public class TracingDataSource implements DataSource {
private static final org.slf4j.Logger LOG = LoggerFactory.getLogger(TracingDataSource.class);
private final DataSource delegate;
private final ConnectionInfo connectionInfo;
public TracingDataSource(DataSource delegate) {
this.delegate = delegate;
try (Connection connection = delegate.getConnection()) {
connectionInfo = URLParser.parser(connection.getMetaData().getURL());
LOG.debug(
"URL {} connectionInfo {}",
connection.getMetaData().getURL(),
connectionInfo.getPeerService());
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
@Override
public Connection getConnection() throws SQLException {
return new TracingConnection(
delegate.getConnection(), connectionInfo, true, null, GlobalTracer.get());
}
@Override
public Connection getConnection(String username, String password) throws SQLException {
return new TracingConnection(
delegate.getConnection(username, password), connectionInfo, true, null, GlobalTracer.get());
}
@Override
public <T> T unwrap(Class<T> iface) throws SQLException {
return delegate.unwrap(iface);
}
@Override
public boolean isWrapperFor(Class<?> iface) throws SQLException {
return delegate.isWrapperFor(iface);
}
@Override
public PrintWriter getLogWriter() throws SQLException {
return delegate.getLogWriter();
}
@Override
public void setLogWriter(PrintWriter out) throws SQLException {
delegate.setLogWriter(out);
}
@Override
public void setLoginTimeout(int seconds) throws SQLException {
delegate.setLoginTimeout(seconds);
}
@Override
public int getLoginTimeout() throws SQLException {
return delegate.getLoginTimeout();
}
@Override
public Logger getParentLogger() throws SQLFeatureNotSupportedException {
return delegate.getParentLogger();
}
public static DataSource wrapWithTracingIfEnabled(DataSource dataSource) {
return Boolean.valueOf(System.getenv("CHE_DB_TRACING_ENABLED"))
? new TracingDataSource(dataSource)
: dataSource;
}
}

View File

@ -1,38 +0,0 @@
/*
* Copyright (c) 2012-2018 Red Hat, Inc.
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.core.db.cascade;
/**
* Context that is used only for sharing the state of the cascading operation among subscribers.
*
* @author Anton Korneta
* @author Sergii Leshchenko
*/
public class CascadeContext {
private Exception cause;
/** Returns the cause which has changed the state of the context. */
public Exception getCause() {
return cause;
}
/** Returns the state of the context. */
public boolean isFailed() {
return cause != null;
}
/** Sets the context into failed state. */
public CascadeContext fail(Exception cause) {
this.cause = cause;
return this;
}
}

View File

@ -1,45 +0,0 @@
/*
* Copyright (c) 2012-2018 Red Hat, Inc.
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.core.db.cascade;
import org.eclipse.che.api.core.notification.EventSubscriber;
import org.eclipse.che.core.db.cascade.event.CascadeEvent;
/**
* Receives events and puts exceptions in the context to perform rollback operation if it is
* necessary.
*
* @author Anton Korneta
* @author Sergii Leschenko
*/
public abstract class CascadeEventSubscriber<T extends CascadeEvent> implements EventSubscriber<T> {
@Override
public void onEvent(T event) {
if (!event.getContext().isFailed()) {
try {
onCascadeEvent(event);
} catch (Exception ex) {
event.getContext().fail(ex);
}
}
}
/**
* Receives notification about cascade event.
*
* <p>If the method throws an exception it will be set to context to break event publishing and
* rethrow exception. Event is responsible for rethrowing or wrapping original exception.
*
* @see CascadeEvent#propagateException()
*/
public abstract void onCascadeEvent(T event) throws Exception;
}

View File

@ -1,60 +0,0 @@
/*
* Copyright (c) 2012-2018 Red Hat, Inc.
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.core.db.cascade.event;
import org.eclipse.che.core.db.cascade.CascadeContext;
/**
* Special event type which is needed only for notification in the process which can require cascade
* operation.
*
* <p>Publisher should invoke {@link #propagateException()} to get cause of event canceling.
*
* <p>Rollback of operation must be performed when subscriber throws {@link Exception} during event
* processing.
*
* <p>Usage example:
*
* <pre>
* EventService bus = new EventService();
* bus.subscribe(new CascadeEventSubscriber&lt;MyEvent&gt;() {
* &#64;Override
* public void onCascadeEvent(MyEvent event) throws Exception {
* if (event.getEntityName().startsWith("reserved")) {
* throw new ConflictException("Entity name can't start with `reserved`.");
* }
* }
* });
* bus.publish(new MyEvent(...)).propagateException();
* </pre>
*
* @author Anton Korneta
* @author Sergii Leschenko
*/
public abstract class CascadeEvent {
protected final CascadeContext context = new CascadeContext();
public CascadeContext getContext() {
return context;
}
/**
* Propagates exception if subscriber throws it while event processing otherwise do nothing
*
* @throws Exception when any subscriber throws {@link Exception}
*/
public void propagateException() throws Exception {
if (context.isFailed()) {
throw context.getCause();
}
}
}

View File

@ -1,38 +0,0 @@
/*
* Copyright (c) 2012-2018 Red Hat, Inc.
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.core.db.cascade.event;
import org.eclipse.che.api.core.ConflictException;
import org.eclipse.che.api.core.ServerException;
/**
* Cascade event about an entity persisting.
*
* <p>{@link ConflictException} or {@link ServerException} can be rethrown during exception
* propagating.
*
* @author Sergii Leschenko
*/
public abstract class PersistEvent extends CascadeEvent {
@Override
public void propagateException() throws ConflictException, ServerException {
if (context.isFailed()) {
try {
throw context.getCause();
} catch (ConflictException | ServerException e) {
throw e;
} catch (Exception e) {
throw new ServerException(e.getLocalizedMessage(), e);
}
}
}
}

View File

@ -1,36 +0,0 @@
/*
* Copyright (c) 2012-2018 Red Hat, Inc.
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.core.db.cascade.event;
import org.eclipse.che.api.core.ServerException;
/**
* Cascade event about an entity removing.
*
* <p>{@link ServerException} can be rethrown during exception propagating.
*
* @author Sergii Leschenko
*/
public abstract class RemoveEvent extends CascadeEvent {
@Override
public void propagateException() throws ServerException {
if (context.isFailed()) {
try {
throw context.getCause();
} catch (ServerException e) {
throw e;
} catch (Exception e) {
throw new ServerException(e.getLocalizedMessage(), e);
}
}
}
}

View File

@ -1,39 +0,0 @@
/*
* Copyright (c) 2012-2018 Red Hat, Inc.
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.core.db.cascade.event;
import org.eclipse.che.api.core.ConflictException;
import org.eclipse.che.api.core.NotFoundException;
import org.eclipse.che.api.core.ServerException;
/**
* Cascade event about an entity updating.
*
* <p>{@link NotFoundException}, {@link ConflictException} or {@link ServerException} can be
* rethrown during exception propagating.
*
* @author Sergii Leschenko
*/
public abstract class UpdateEvent extends CascadeEvent {
@Override
public void propagateException() throws NotFoundException, ConflictException, ServerException {
if (context.isFailed()) {
try {
throw context.getCause();
} catch (NotFoundException | ConflictException | ServerException e) {
throw e;
} catch (Exception e) {
throw new ServerException(e.getLocalizedMessage(), e);
}
}
}
}

View File

@ -1,34 +0,0 @@
/*
* Copyright (c) 2012-2018 Red Hat, Inc.
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.core.db.jpa;
import javax.persistence.RollbackException;
import org.eclipse.che.core.db.DBErrorCode;
/**
* Extends the standard {@link RollbackException} with an error code from {@link DBErrorCode}.
*
* @author Yevhenii Voevodin
*/
public class DetailedRollbackException extends RollbackException {
private DBErrorCode code;
public DetailedRollbackException(String message, Throwable cause, DBErrorCode code) {
super(message, cause);
this.code = code;
}
public DBErrorCode getCode() {
return code;
}
}

View File

@ -1,27 +0,0 @@
/*
* Copyright (c) 2012-2018 Red Hat, Inc.
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.core.db.jpa;
import org.eclipse.che.core.db.DBErrorCode;
/**
* Thrown when data couldn't be updated/stored due to unique constrain violation.
*
* @author Yevhenii Voevodin
* @see DBErrorCode#DUPLICATE_KEY
*/
public class DuplicateKeyException extends DetailedRollbackException {
public DuplicateKeyException(String message, Throwable cause) {
super(message, cause, DBErrorCode.DUPLICATE_KEY);
}
}

View File

@ -1,28 +0,0 @@
/*
* Copyright (c) 2012-2018 Red Hat, Inc.
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.core.db.jpa;
import org.eclipse.che.core.db.DBErrorCode;
/**
* Throws during inserts/updates entity that restricted by referential integrity and given
* insert/update refers to non-existing entity.
*
* @author Anton Korneta
* @see DBErrorCode#INTEGRITY_CONSTRAINT_VIOLATION
*/
public class IntegrityConstraintViolationException extends DetailedRollbackException {
public IntegrityConstraintViolationException(String message, Throwable cause) {
super(message, cause, DBErrorCode.INTEGRITY_CONSTRAINT_VIOLATION);
}
}

View File

@ -1,27 +0,0 @@
/*
* Copyright (c) 2012-2018 Red Hat, Inc.
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.core.db.jpa;
import com.google.inject.ImplementedBy;
import org.eclipse.che.core.db.jpa.guice.GuiceJpaInitializer;
/**
* Initializes jpa components.
*
* @author Yevhenii Voevodin
*/
@ImplementedBy(GuiceJpaInitializer.class)
public interface JpaInitializer {
/** Initialized jpa components. */
void init();
}

View File

@ -1,69 +0,0 @@
/*
* Copyright (c) 2012-2018 Red Hat, Inc.
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.core.db.jpa.eclipselink;
import com.google.inject.Inject;
import com.google.inject.Injector;
import javax.naming.NamingException;
import org.eclipse.persistence.internal.sessions.AbstractSession;
import org.eclipse.persistence.internal.sessions.cdi.InjectionManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Allows to use dependency injection in entity listeners.
*
* <p>Example:
*
* <pre>
* class WorkspaceEntityListener {
*
* &#064;Inject EventBus bus; <- EventBus will be injected by Guice
*
* &#064;PreRemove
* public void preRemove(Workspace workspace) {
* bus.post(new BeforeWorkspaceRemovedEvent(workspace));
* }
* }
*
* &#064;Entity
* &#064;EntityListeners(WorkspaceEntityListener.class)
* class Workspace {
* // ...
* }
* </pre>
*
* @author Yevhenii Voevodin
*/
public class GuiceEntityListenerInjectionManager implements InjectionManager {
private static final Logger LOG =
LoggerFactory.getLogger(GuiceEntityListenerInjectionManager.class);
@Inject private Injector injector;
@Override
public Object createManagedBeanAndInjectDependencies(Class entityListenerClass)
throws NamingException {
try {
return injector.getInstance(entityListenerClass);
} catch (RuntimeException x) {
LOG.error(x.getLocalizedMessage(), x);
throw new NamingException(x.getLocalizedMessage());
}
}
@Override
public void cleanUp(AbstractSession session) {
// EntityListener objects are managed by Guice, nothing to cleanup
}
}

View File

@ -1,40 +0,0 @@
/*
* Copyright (c) 2012-2018 Red Hat, Inc.
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.core.db.jpa.guice;
import com.google.inject.persist.PersistService;
import javax.inject.Inject;
import org.eclipse.che.core.db.jpa.JpaInitializer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Should be bound as eager singleton. See <a
* href="https://github.com/google/guice/wiki/JPA">doc</a>
*
* @author Yevhenii Voevodin
* @author Anton Korneta
*/
public class GuiceJpaInitializer implements JpaInitializer {
private static final Logger LOG = LoggerFactory.getLogger(GuiceJpaInitializer.class);
@Inject private PersistService persistService;
public void init() {
try {
persistService.start();
} catch (Exception x) {
LOG.error(x.getLocalizedMessage(), x);
}
}
}

View File

@ -1,28 +0,0 @@
/*
* Copyright (c) 2012-2018 Red Hat, Inc.
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.core.db.schema;
/**
* Thrown when any schema initialization/migration problem occurs.
*
* @author Yevhenii Voevodin
*/
public class SchemaInitializationException extends Exception {
public SchemaInitializationException(String message, Throwable cause) {
super(message, cause);
}
public SchemaInitializationException(String message) {
super(message);
}
}

View File

@ -1,31 +0,0 @@
/*
* Copyright (c) 2012-2018 Red Hat, Inc.
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.core.db.schema;
import java.util.Map;
/**
* Initializes database schema or migrates an old version of it to a new one.
*
* @author Yevhenii Voevodin
*/
public interface SchemaInitializer {
/**
* Initializes database schema or migrates an old schema to a new one.
*
* @return initialization properties
* @throws SchemaInitializationException thrown when any error occurs during schema
* initialization/migration
*/
Map<String, String> init() throws SchemaInitializationException;
}

View File

@ -1,210 +0,0 @@
/*
* Copyright (c) 2012-2021 Red Hat, Inc.
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.core.db.schema.impl.flyway;
import static java.lang.String.format;
import static java.util.stream.Collectors.toList;
import com.google.common.hash.Hashing;
import com.google.common.io.ByteSource;
import java.io.IOException;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import org.flywaydb.core.api.FlywayException;
import org.flywaydb.core.api.MigrationType;
import org.flywaydb.core.api.MigrationVersion;
import org.flywaydb.core.api.resolver.BaseMigrationResolver;
import org.flywaydb.core.api.resolver.ResolvedMigration;
import org.flywaydb.core.internal.dbsupport.DbSupport;
import org.flywaydb.core.internal.resolver.ResolvedMigrationImpl;
import org.flywaydb.core.internal.resolver.sql.SqlMigrationExecutor;
import org.flywaydb.core.internal.util.Location;
import org.flywaydb.core.internal.util.PlaceholderReplacer;
import org.flywaydb.core.internal.util.scanner.Resource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Resolves SQL migrations from the configured locations, allows overriding of default scripts with
* vendor specific ones.
*
* <ul>
* Migration scripts must follow the next rules:
* <li>It must be placed in the project dir directory e.g. <i>5.0.1</i>
* <li>Project dir directory must be placed in dedicated directory e.g. <i>resources/sql</i>
* <li>Migration/Initialization script name must start with a number e.g <i>1.init.sql</i>, this
* number indicates the subversion of the database migration, e.g. for dir <i>5.0.0</i> and
* migration script <i>1.init.sql</i> database migration dir will be <i>5.0.0.1</i>
* <li>If a file is not a part of migration it shouldn't end with migration prefix e.g.
* <i>.sql</i> then resolver will ignore it
* </ul>
*
* <p>For the structure:
*
* <pre>
* resources/
* sql/
* 5.0.0/
* 1.init.sql
* 5.0.0-M1/
* 1.rename_fields.sql
* 2.add_workspace_constraint.sql
* postgresql/
* 2.add_workspace_constraint.sql
* 5.0.1/
* 1.stacks_migration.sql
* </pre>
*
* And configuration:
*
* <pre>
* prefix - ""
* suffix - ".sql"
* separator - "."
* locations - "classpath:sql"
* </pre>
*
* <ul>
* 4 database migrations will be resolved
* <li>5.0.0.1 - initialization script based on file <i>sql/5.0.0/1.init.sql</i>
* <li>5.0.0.1.1 - modification script based on file <i>sql/5.0.0-M1/1.rename_fields.sql</i>
* <li>5.0.0.1.2 - modification script(if postgresql is current provider) based on file
* <i>sql/5.0.0-M1/postgresql/2.add_workspace_constraint.sql</i>
* <li>5.0.1.1 - modification script based on file <i>sql/5.0.1/1.stacks_migrations.sql</i>
* </ul>
*
* <p>It is also possible to configure several locations then all of those locations will be
* analyzed for migration scripts existence. For example:
*
* <p>For the structure:
*
* <pre>
* che/
* resources/
* che-schema/
* 5.0.0/
* 1.init.sql
* another-project/
* resources/
* custom-schema/
* 5.0.0/
* 2.init_additional_tables.sql
* </pre>
*
* And configuration:
*
* <pre>
* prefix - ""
* suffix - ".sql"
* separator - "."
* locations - "classpath:che-schema, classpath:custom-schema"
* </pre>
*
* <ul>
* 2 database migrations will be resolved
* <li>5.0.0.1 - initialization script based on file <i>che-schema/5.0.0/1.init.sql</i>
* <li>5.0.0.2 - modification script based on file
* <i>custom-schema/5.0.0/2.init_additional_tables.sql</i>
* </ul>
*
* @author Yevhenii Voevodin
*/
public class CustomSqlMigrationResolver extends BaseMigrationResolver {
private static final Logger LOG = LoggerFactory.getLogger(CustomSqlMigrationResolver.class);
private final String vendorName;
private final ResourcesFinder finder;
private final VersionResolver versionResolver;
private final SqlScriptCreator scriptsCreator;
private final DbSupport dbSupport;
private final PlaceholderReplacer placeholderReplacer;
public CustomSqlMigrationResolver(
String dbProviderName, DbSupport dbSupport, PlaceholderReplacer placeholderReplacer) {
this.vendorName = dbProviderName;
this.dbSupport = dbSupport;
this.placeholderReplacer = placeholderReplacer;
this.finder = new ResourcesFinder();
this.versionResolver = new VersionResolver();
this.scriptsCreator = new SqlScriptCreator();
}
@Override
public Collection<ResolvedMigration> resolveMigrations() {
try {
return resolveSqlMigrations();
} catch (IOException | SQLException x) {
throw new RuntimeException(x.getLocalizedMessage(), x);
}
}
private List<ResolvedMigration> resolveSqlMigrations() throws IOException, SQLException {
LOG.info(
"Searching for SQL scripts in locations {}",
Arrays.toString(flywayConfiguration.getLocations()));
final Map<Location, List<Resource>> allResources = finder.findResources(flywayConfiguration);
LOG.debug("Found scripts: {}", allResources);
final Map<String, Map<String, SqlScript>> scriptsInDir = new HashMap<>();
for (Location location : allResources.keySet()) {
final List<Resource> resources = allResources.get(location);
for (Resource resource : resources) {
final SqlScript newScript = scriptsCreator.createScript(location, resource);
if (!scriptsInDir.containsKey(newScript.dir)) {
scriptsInDir.put(newScript.dir, new HashMap<>(4));
}
final Map<String, SqlScript> existingScripts = scriptsInDir.get(newScript.dir);
final SqlScript existingScript = existingScripts.get(newScript.name);
if (existingScript == null) {
existingScripts.put(newScript.name, newScript);
} else if (Objects.equals(existingScript.vendor, newScript.vendor)) {
throw new FlywayException(
format(
"More than one script with name '%s' is registered for "
+ "database vendor '%s', script '%s' conflicts with '%s'",
newScript.name, existingScript.vendor, newScript, existingScript));
} else if (vendorName.equals(newScript.vendor)) {
existingScripts.put(newScript.name, newScript);
}
}
}
final Map<MigrationVersion, ResolvedMigration> migrations = new HashMap<>();
for (SqlScript script :
scriptsInDir.values().stream()
.flatMap(scripts -> scripts.values().stream())
.collect(toList())) {
final ResolvedMigrationImpl migration = new ResolvedMigrationImpl();
migration.setVersion(versionResolver.resolve(script, flywayConfiguration));
migration.setScript(script.resource.getLocation());
migration.setPhysicalLocation(script.resource.getLocationOnDisk());
migration.setType(MigrationType.SQL);
migration.setDescription(script.name);
migration.setChecksum(
ByteSource.wrap(script.resource.loadAsBytes()).hash(Hashing.crc32()).asInt());
migration.setExecutor(
new SqlMigrationExecutor(
dbSupport, script.resource, placeholderReplacer, flywayConfiguration));
if (migrations.put(migration.getVersion(), migration) != null) {
throw new FlywayException("Two migrations with the same version detected");
}
}
return new ArrayList<>(migrations.values());
}
}

View File

@ -1,122 +0,0 @@
/*
* Copyright (c) 2012-2021 Red Hat, Inc.
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.core.db.schema.impl.flyway;
import static org.eclipse.che.core.db.DBInitializer.BARE_DB_INIT_PROPERTY_NAME;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;
import javax.inject.Inject;
import javax.inject.Named;
import javax.sql.DataSource;
import org.eclipse.che.core.db.schema.SchemaInitializationException;
import org.eclipse.che.core.db.schema.SchemaInitializer;
import org.flywaydb.core.Flyway;
import org.flywaydb.core.internal.dbsupport.DbSupport;
import org.flywaydb.core.internal.dbsupport.DbSupportFactory;
import org.flywaydb.core.internal.metadatatable.MetaDataTable;
import org.flywaydb.core.internal.metadatatable.MetaDataTableImpl;
import org.flywaydb.core.internal.util.PlaceholderReplacer;
/**
* <a href="https://flywaydb.org/">Flyway</a> based schema initializer.
*
* @author Yevhenii Voevodin
*/
public class FlywaySchemaInitializer implements SchemaInitializer {
private final DataSource dataSource;
private final String[] locations;
private final String scriptsPrefix;
private final String scriptsSuffix;
private final String versionSeparator;
private final boolean baselineOnMigrate;
private final String baselineVersion;
private final PlaceholderReplacer placeholderReplacer;
/**
* Creates a new instance of flyway schema initializer.
*
* @param scriptsLocations the locations where to search migration scripts, if locations is not
* prefixed or prefixed with <i>classpath:</i> then initializer will try to find scripts in
* classpath using {@code Thread.currentThread().}{@link Thread#getContextClassLoader()
* getContextClassLoader()}
* @param scriptsPrefix prefix of migration scripts e.g. 'v' or empty string
* @param scriptsSuffix suffix of migration scripts e.g. '.sql'
* @param versionSeparator separate version from the other part of script name e.g. '.' or '__'
* @param baselineOnMigrate whether to ignore scripts up to the version configured by {@code
* baselineVersion}
* @param baselineVersion up to this version all the scripts ignored, unless schema is initialized
* first time, note that scripts with version equal to baseline version are also ignored
* @param dataSource data source used for migrations
* @param placeholderReplacer used to replace variables in script with configured values
*/
@Inject
public FlywaySchemaInitializer(
@Named("db.schema.flyway.scripts.locations") String[] scriptsLocations,
@Named("db.schema.flyway.scripts.prefix") String scriptsPrefix,
@Named("db.schema.flyway.scripts.suffix") String scriptsSuffix,
@Named("db.schema.flyway.scripts.version_separator") String versionSeparator,
@Named("db.schema.flyway.baseline.enabled") boolean baselineOnMigrate,
@Named("db.schema.flyway.baseline.version") String baselineVersion,
DataSource dataSource,
PlaceholderReplacer placeholderReplacer) {
this.dataSource = dataSource;
this.locations = scriptsLocations;
this.scriptsPrefix = scriptsPrefix;
this.scriptsSuffix = scriptsSuffix;
this.versionSeparator = versionSeparator;
this.baselineOnMigrate = baselineOnMigrate;
this.baselineVersion = baselineVersion;
this.placeholderReplacer = placeholderReplacer;
}
/** Creates a new flyway based initializer with default values. */
public FlywaySchemaInitializer(DataSource dataSource, String... locations) {
this(locations, "", ".sql", "__", false, "", dataSource, PlaceholderReplacer.NO_PLACEHOLDERS);
}
@Override
public Map<String, String> init() throws SchemaInitializationException {
final Map<String, String> initResult = new HashMap<>();
try (final Connection conn = dataSource.getConnection()) {
final Flyway flyway = new Flyway();
flyway.setDataSource(dataSource);
flyway.setLocations(locations);
flyway.setClassLoader(Thread.currentThread().getContextClassLoader());
final DbSupport dbSupport = DbSupportFactory.createDbSupport(conn, true);
final MetaDataTable mt =
new MetaDataTableImpl(
dbSupport,
dbSupport.getOriginalSchema().getTable(flyway.getTable()),
flyway.getInstalledBy());
initResult.put(BARE_DB_INIT_PROPERTY_NAME, String.valueOf(!mt.hasAppliedMigrations()));
final String productName = conn.getMetaData().getDatabaseProductName().toLowerCase();
flyway.setResolvers(
new CustomSqlMigrationResolver(productName, dbSupport, placeholderReplacer));
flyway.setSkipDefaultResolvers(true);
flyway.setBaselineOnMigrate(baselineOnMigrate);
if (baselineOnMigrate) {
flyway.setBaselineVersionAsString(baselineVersion);
}
flyway.setSqlMigrationSeparator(versionSeparator);
flyway.setSqlMigrationSuffix(scriptsSuffix);
flyway.setSqlMigrationPrefix(scriptsPrefix);
flyway.migrate();
} catch (SQLException | RuntimeException x) {
throw new SchemaInitializationException(x.getLocalizedMessage(), x);
}
return initResult;
}
}

View File

@ -1,37 +0,0 @@
/*
* Copyright (c) 2012-2018 Red Hat, Inc.
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.core.db.schema.impl.flyway;
import javax.inject.Inject;
import javax.inject.Provider;
import org.eclipse.che.inject.ConfigurationProperties;
import org.flywaydb.core.internal.util.PlaceholderReplacer;
/**
* Placeholder replacer that uses configuration properties.
*
* @author Yevhenii Voevodin
*/
public class PlaceholderReplacerProvider implements Provider<PlaceholderReplacer> {
private final PlaceholderReplacer replacer;
@Inject
public PlaceholderReplacerProvider(ConfigurationProperties properties) {
replacer = new PlaceholderReplacer(properties.getProperties(".*"), "${", "}");
}
@Override
public PlaceholderReplacer get() {
return replacer;
}
}

View File

@ -1,57 +0,0 @@
/*
* Copyright (c) 2012-2018 Red Hat, Inc.
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.core.db.schema.impl.flyway;
import static com.google.common.collect.Lists.newArrayList;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.flywaydb.core.api.configuration.FlywayConfiguration;
import org.flywaydb.core.internal.util.Location;
import org.flywaydb.core.internal.util.scanner.Resource;
import org.flywaydb.core.internal.util.scanner.classpath.ClassPathScanner;
import org.flywaydb.core.internal.util.scanner.filesystem.FileSystemScanner;
/**
* Searches for sql scripts in given places.
*
* @author Yevhenii Voevodin
*/
class ResourcesFinder {
/**
* Finds script resources in configured {@link FlywayConfiguration#getLocations()}.
*
* @param configuration flyway configuration to find scripts
* @return found scripts or an empty list if nothing found
* @throws IOException when any io error occurs during scripts look up
*/
Map<Location, List<Resource>> findResources(FlywayConfiguration configuration)
throws IOException {
final String prefix = configuration.getSqlMigrationPrefix();
final String suffix = configuration.getSqlMigrationSuffix();
final ClassPathScanner cpScanner = new ClassPathScanner(configuration.getClassLoader());
final FileSystemScanner fsScanner = new FileSystemScanner();
final Map<Location, List<Resource>> resources = new HashMap<>();
for (String rawLocation : configuration.getLocations()) {
final Location location = new Location(rawLocation);
if (location.isClassPath()) {
resources.put(location, newArrayList(cpScanner.scanForResources(location, prefix, suffix)));
} else {
resources.put(location, newArrayList(fsScanner.scanForResources(location, prefix, suffix)));
}
}
return resources;
}
}

View File

@ -1,84 +0,0 @@
/*
* Copyright (c) 2012-2018 Red Hat, Inc.
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.core.db.schema.impl.flyway;
import java.util.Objects;
import org.flywaydb.core.internal.util.Location;
import org.flywaydb.core.internal.util.scanner.Resource;
/**
* Data object for holding information about sql script.
*
* @author Yevhenii Voevodin
*/
class SqlScript {
final Resource resource;
final Location location;
final String dir;
final String vendor;
final String name;
SqlScript(Resource resource, Location location, String dir, String vendor, String name) {
this.resource = resource;
this.location = location;
this.name = name;
this.vendor = vendor;
this.dir = dir;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (!(obj instanceof SqlScript)) {
return false;
}
final SqlScript that = (SqlScript) obj;
return Objects.equals(resource, that.resource)
&& Objects.equals(location, that.location)
&& Objects.equals(dir, that.dir)
&& Objects.equals(vendor, that.vendor)
&& Objects.equals(name, that.name);
}
@Override
public int hashCode() {
int hash = 7;
hash = 31 * hash + Objects.hashCode(resource);
hash = 31 * hash + Objects.hashCode(location);
hash = 31 * hash + Objects.hashCode(dir);
hash = 31 * hash + Objects.hashCode(vendor);
hash = 31 * hash + Objects.hashCode(name);
return hash;
}
@Override
public String toString() {
return "SqlScript{"
+ "resource="
+ resource
+ ", location="
+ location
+ ", dir='"
+ dir
+ '\''
+ ", vendor='"
+ vendor
+ '\''
+ ", name='"
+ name
+ '\''
+ '}';
}
}

View File

@ -1,55 +0,0 @@
/*
* Copyright (c) 2012-2018 Red Hat, Inc.
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.core.db.schema.impl.flyway;
import static java.lang.String.format;
import java.io.File;
import org.flywaydb.core.api.FlywayException;
import org.flywaydb.core.internal.util.Location;
import org.flywaydb.core.internal.util.scanner.Resource;
/**
* Creates new {@link SqlScript} instance from given resource.
*
* @author Yevhenii Voevodin
*/
class SqlScriptCreator {
/**
* Create a new instance of script based on location and resource.
*
* @param location root location of the given resource
* @param resource script resource
* @return a new instance of sql script based on location and resource
* @throws FlywayException when script can't be created from the resource
*/
SqlScript createScript(Location location, Resource resource) {
final String separator = location.isClassPath() ? "/" : File.separator;
// '/root-location/5.0.0-M7/v1__init.sql' -> '5.0.0-M7/v1__init.sql'
final String relLocation = resource.getLocation().substring(location.getPath().length() + 1);
final String[] paths = relLocation.split(separator);
// 5.0.0-M1/v1__init.sql
if (paths.length == 2) {
return new SqlScript(resource, location, paths[0], null, paths[1]);
}
// 5.0.0-M1/postgresql/v1__init.sql
if (paths.length == 3) {
return new SqlScript(resource, location, paths[0], paths[1], paths[2]);
}
throw new FlywayException(
format(
"Sql script location must be either in 'location-root/version-dir' "
+ "or in 'location-root/version-dir/provider-name', but script '%s' is not in root '%s'",
resource.getLocation(), location.getPath()));
}
}

View File

@ -1,84 +0,0 @@
/*
* Copyright (c) 2012-2018 Red Hat, Inc.
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.core.db.schema.impl.flyway;
import static com.google.common.base.Strings.isNullOrEmpty;
import static java.lang.String.format;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Pattern;
import org.flywaydb.core.api.FlywayException;
import org.flywaydb.core.api.MigrationVersion;
import org.flywaydb.core.api.configuration.FlywayConfiguration;
/**
* Creates versions for scripts depending on the provided data.
*
* <ul>
* A few examples:
* <li>5.0.0-M7/v1__init.sql => 5.0.0.7.1
* <li>5.0.0-M8/v2.1__modify.sql => 5.0.0.8.2.1
* </ul>
*
* @author Yevhenii Voevodin
*/
class VersionResolver {
private static final Pattern NOT_VERSION_CHARS_PATTERN = Pattern.compile("[^0-9.]");
private final Map<String, String> normalizedDirs = new HashMap<>();
/**
* Creates migration version based on script data.
*
* @param script script for which to resolve the version
* @param configuration flyway configuration used for resolution parameters
*/
MigrationVersion resolve(SqlScript script, FlywayConfiguration configuration) {
String normalizedDir = normalizedDirs.get(script.dir);
if (normalizedDir == null) {
// 5.0.0-M1 -> 5.0.0.M1 -> 5.0.0.1
normalizedDir =
NOT_VERSION_CHARS_PATTERN.matcher(script.dir.replace("-", ".")).replaceAll("");
normalizedDirs.put(script.dir, normalizedDir);
}
// separate version from the other part of the name
final int sepIdx = script.name.indexOf(configuration.getSqlMigrationSeparator());
if (sepIdx == -1) {
throw new FlywayException(
format(
"sql script name '%s' is not valid, name must contain '%s'",
script.name, configuration.getSqlMigrationSeparator()));
}
// check whether part before separator is not empty
String version = script.name.substring(0, sepIdx);
if (version.isEmpty()) {
throw new FlywayException(
format(
"sql script name '%s' is not valid, name must provide version like "
+ "'%s4%smigration_description.sql",
configuration.getSqlMigrationPrefix(),
script.name,
configuration.getSqlMigrationSeparator()));
}
// extract sql script version without prefix
final String prefix = configuration.getSqlMigrationPrefix();
if (!isNullOrEmpty(prefix) && script.name.startsWith(prefix)) {
version = version.substring(prefix.length());
}
return MigrationVersion.fromVersion(normalizedDir + '.' + version);
}
}

View File

@ -1,123 +0,0 @@
/*
* Copyright (c) 2012-2023 Red Hat, Inc.
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.core.db;
import static org.mockito.Mockito.lenient;
import static org.testng.Assert.assertEquals;
import com.google.common.collect.ImmutableMap;
import io.opentracing.contrib.jdbc.TracingConnection;
import java.lang.reflect.Field;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.SQLException;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import javax.sql.DataSource;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.testng.MockitoTestNGListener;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Listeners;
import org.testng.annotations.Test;
@Listeners(value = {MockitoTestNGListener.class})
public class TracingDataSourceTest {
@Mock DataSource dataSource;
@Mock Connection connection;
@Mock DatabaseMetaData databaseMetaData;
@BeforeMethod
@AfterMethod
public void cleanup() throws Exception {
HashMap<String, String> newEnv = new HashMap<>(System.getenv());
newEnv.remove("CHE_DB_TRACING_ENABLED");
setEnv(newEnv);
lenient().when(dataSource.getConnection()).thenReturn(connection);
lenient().when(connection.getMetaData()).thenReturn(databaseMetaData);
}
@Test
public void shouldBeAbleToGetConnection() throws SQLException {
TracingDataSource ds = new TracingDataSource(dataSource);
Connection actual = ds.getConnection();
assertEquals(actual.getClass(), TracingConnection.class);
Mockito.verify(dataSource, Mockito.times(2)).getConnection();
}
@Test
public void shouldBeAbleToGetConnectionWithEmailAndPassword() throws SQLException {
TracingDataSource ds = new TracingDataSource(dataSource);
Connection actual = ds.getConnection("user", "password");
assertEquals(actual.getClass(), TracingConnection.class);
Mockito.verify(dataSource).getConnection(Mockito.eq("user"), Mockito.eq("password"));
}
@Test
public void shouldBeAbleTogetTracingDataSource() throws Exception {
setEnv(ImmutableMap.of("CHE_DB_TRACING_ENABLED", "true"));
DataSource actual = TracingDataSource.wrapWithTracingIfEnabled(dataSource);
assertEquals(actual.getClass(), TracingDataSource.class);
}
@Test
public void shouldNotWrapDatasourceIfEnvSetToFalse() throws Exception {
setEnv(ImmutableMap.of("CHE_DB_TRACING_ENABLED", "false"));
DataSource actual = TracingDataSource.wrapWithTracingIfEnabled(dataSource);
assertEquals(actual, dataSource);
}
@Test
public void shouldNotWrapDatasourceIfEnvIsNotSet() throws Exception {
DataSource actual = TracingDataSource.wrapWithTracingIfEnabled(dataSource);
assertEquals(actual, dataSource);
}
protected static void setEnv(Map<String, String> newenv) throws Exception {
try {
Class<?> processEnvironmentClass = Class.forName("java.lang.ProcessEnvironment");
Field theEnvironmentField = processEnvironmentClass.getDeclaredField("theEnvironment");
theEnvironmentField.setAccessible(true);
Map<String, String> env = (Map<String, String>) theEnvironmentField.get(null);
env.putAll(newenv);
Field theCaseInsensitiveEnvironmentField =
processEnvironmentClass.getDeclaredField("theCaseInsensitiveEnvironment");
theCaseInsensitiveEnvironmentField.setAccessible(true);
Map<String, String> cienv =
(Map<String, String>) theCaseInsensitiveEnvironmentField.get(null);
cienv.putAll(newenv);
} catch (NoSuchFieldException e) {
Class[] classes = Collections.class.getDeclaredClasses();
Map<String, String> env = System.getenv();
for (Class cl : classes) {
if ("java.util.Collections$UnmodifiableMap".equals(cl.getName())) {
Field field = cl.getDeclaredField("m");
field.setAccessible(true);
Object obj = field.get(env);
Map<String, String> map = (Map<String, String>) obj;
map.clear();
map.putAll(newenv);
}
}
}
}
}

View File

@ -1,353 +0,0 @@
/*
* Copyright (c) 2012-2023 Red Hat, Inc.
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.core.db.schema.impl.flyway;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Sets;
import java.io.IOException;
import java.io.StringReader;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import javax.sql.DataSource;
import org.eclipse.che.commons.lang.IoUtil;
import org.eclipse.che.core.db.schema.SchemaInitializationException;
import org.eclipse.che.core.db.schema.SchemaInitializer;
import org.flywaydb.core.internal.util.PlaceholderReplacer;
import org.h2.jdbcx.JdbcDataSource;
import org.h2.tools.RunScript;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
/**
* Tests {@link FlywaySchemaInitializer}.
*
* @author Yevhenii Voevodin
*/
public class FlywaySchemaInitializerTest {
private static final String SCRIPTS_ROOT = "flyway/sql";
private JdbcDataSource dataSource;
@BeforeMethod
public void setUp() throws URISyntaxException {
dataSource = new JdbcDataSource();
dataSource.setUrl("jdbc:h2:mem:flyway_test;DB_CLOSE_DELAY=-1");
}
@AfterMethod
public void cleanup() throws SQLException, URISyntaxException {
try (Connection conn = dataSource.getConnection()) {
RunScript.execute(conn, new StringReader("SHUTDOWN"));
}
IoUtil.deleteRecursive(targetDir().resolve(Paths.get(SCRIPTS_ROOT)).toFile());
}
@Test
public void initializesSchemaWhenDatabaseIsEmpty() throws Exception {
createScript("1.0/1__init.sql", "CREATE TABLE test (id INT, text TEXT, PRIMARY KEY (id));");
createScript(
"1.0/2__add_data.sql",
"INSERT INTO test VALUES(1, 'test1');"
+ "INSERT INTO test VALUES(2, 'test2');"
+ "INSERT INTO test VALUES(3, 'test3');");
createScript("2.0/1__add_more_data.sql", "INSERT INTO test VALUES(4, 'test4');");
createScript(
"2.0/postgresql/1__add_more_data.sql", "INSERT INTO test VALUES(4, 'postgresql-data');");
final SchemaInitializer initializer = FlywayInitializerBuilder.from(dataSource).build();
initializer.init();
assertEquals(
queryEntities(),
Sets.newHashSet(
new TestEntity(1, "test1"),
new TestEntity(2, "test2"),
new TestEntity(3, "test3"),
new TestEntity(4, "test4")));
// second init must do nothing, so there are no conflicts
initializer.init();
}
@Test(expectedExceptions = SchemaInitializationException.class)
public void failsIfBaseLineIsNotConfiguredProperly() throws Exception {
execQuery(
"CREATE TABLE test (id INT, text TEXT, PRIMARY KEY (id));"
+ "INSERT INTO test VALUES(1, 'test1');"
+ "INSERT INTO test VALUES(2, 'test2');"
+ "INSERT INTO test VALUES(3, 'test3');");
createScript("1.0/1__init.sql", "CREATE TABLE test (id INT, text TEXT, PRIMARY KEY (id));");
FlywayInitializerBuilder.from(dataSource)
.setBaselineOnMigrate(true)
.setBaselineVersion("1.0")
.build()
.init();
}
@Test
public void executesOnlyThoseMigrationsWhichGoAfterBaseline() throws Exception {
createScript("1.0/1__init.sql", "CREATE TABLE test (id INT, text TEXT, PRIMARY KEY (id));");
createScript(
"2.0/1__add_data.sql",
"INSERT INTO test VALUES(1, 'test1');"
+ "INSERT INTO test VALUES(2, 'test2');"
+ "INSERT INTO test VALUES(3, 'test3');");
final FlywaySchemaInitializer initializer =
FlywayInitializerBuilder.from(dataSource)
.setBaselineOnMigrate(true)
.setBaselineVersion("1.0.1")
.build();
initializer.init();
assertEquals(
queryEntities(),
Sets.newHashSet(
new TestEntity(1, "test1"), new TestEntity(2, "test2"), new TestEntity(3, "test3")));
// second init must do nothing, so there are no conflicts
initializer.init();
}
@Test
public void initializesSchemaWhenDatabaseIsEmptyAndBaselineIsConfigured() throws Exception {
createScript("1.0/1__init.sql", "CREATE TABLE test (id INT, text TEXT, PRIMARY KEY (id));");
createScript(
"2.0/1__add_data.sql",
"INSERT INTO test VALUES(1, 'test1');"
+ "INSERT INTO test VALUES(2, 'test2');"
+ "INSERT INTO test VALUES(3, 'test3');");
final FlywaySchemaInitializer initializer =
FlywayInitializerBuilder.from(dataSource)
.setBaselineOnMigrate(true)
.setBaselineVersion("1.0.1")
.build();
initializer.init();
assertEquals(
queryEntities(),
Sets.newHashSet(
new TestEntity(1, "test1"), new TestEntity(2, "test2"), new TestEntity(3, "test3")));
// second init must do nothing, so there are no conflicts
initializer.init();
}
@Test
public void selectsProviderSpecificScriptsInPreferenceToDefaultOnes() throws Exception {
createScript("1.0/1__init.sql", "CREATE TABLE test (id INT, text TEXT, PRIMARY KEY (id));");
createScript("2.0/1__add_data.sql", "INSERT INTO test VALUES(1, 'default data');");
createScript("2.0/h2/1__add_data.sql", "INSERT INTO test VALUES(1, 'h2 data');");
final FlywaySchemaInitializer initializer = FlywayInitializerBuilder.from(dataSource).build();
initializer.init();
assertEquals(queryEntities(), Sets.newHashSet(new TestEntity(1, "h2 data")));
// second init must do nothing, so there are no conflicts
initializer.init();
}
@Test
public void replacesVariablesWhenPlaceholderReplacerIsConfigured() throws Exception {
createScript(
"1.0/1__init.sql",
"CREATE TABLE test (id INT, text TEXT, PRIMARY KEY (id));"
+ "INSERT INTO test VALUES(1, '${variable}');");
FlywayInitializerBuilder.from(dataSource)
.setReplacer(new PlaceholderReplacer(ImmutableMap.of("variable", "test"), "${", "}"))
.build()
.init();
assertEquals(queryEntities(), Sets.newHashSet(new TestEntity(1, "test")));
}
private Set<TestEntity> queryEntities() throws SQLException {
final Set<TestEntity> entities = new HashSet<>();
try (Connection conn = dataSource.getConnection()) {
final ResultSet result = RunScript.execute(conn, new StringReader("SELECT * FROM test"));
while (result.next()) {
entities.add(new TestEntity(result.getLong("id"), result.getString("text")));
}
}
return entities;
}
private ResultSet execQuery(String query) throws SQLException {
try (Connection conn = dataSource.getConnection()) {
return RunScript.execute(conn, new StringReader(query));
}
}
private static Path createScript(String relativePath, String content)
throws URISyntaxException, IOException {
return createFile(
targetDir().resolve(Paths.get(SCRIPTS_ROOT)).resolve(relativePath).toString(), content);
}
private static Path createFile(String filepath, String content)
throws URISyntaxException, IOException {
final Path path = targetDir().resolve(Paths.get(filepath));
if (!Files.exists(path.getParent())) {
Files.createDirectories(path.getParent());
}
Files.write(path, content.getBytes(StandardCharsets.UTF_8));
return path;
}
private static Path targetDir() throws URISyntaxException {
final URL url = Thread.currentThread().getContextClassLoader().getResource(".");
assertNotNull(url);
return Paths.get(url.toURI()).getParent();
}
private static class TestEntity {
final long id;
final String text;
private TestEntity(long id, String text) {
this.id = id;
this.text = text;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (!(obj instanceof TestEntity)) {
return false;
}
final TestEntity that = (TestEntity) obj;
return id == that.id && Objects.equals(text, that.text);
}
@Override
public int hashCode() {
int hash = 7;
hash = 31 * hash + Long.hashCode(id);
hash = 31 * hash + Objects.hashCode(text);
return hash;
}
@Override
public String toString() {
return "TestEntity{" + "id=" + id + ", text='" + text + '\'' + '}';
}
}
private static class FlywayInitializerBuilder {
public static FlywayInitializerBuilder from(DataSource dataSource) {
try {
final String scriptsRoot = targetDir().resolve(Paths.get(SCRIPTS_ROOT)).toString();
return new FlywayInitializerBuilder()
.setDataSource(dataSource)
.setScriptsPrefix("")
.setScriptsSuffix(".sql")
.setVersionSeparator("__")
.setReplacer(PlaceholderReplacer.NO_PLACEHOLDERS)
.setBaselineOnMigrate(false)
.addLocation("filesystem:" + scriptsRoot);
} catch (Exception x) {
throw new RuntimeException(x.getMessage(), x);
}
}
private DataSource dataSource;
private List<String> locations;
private String scriptsPrefix;
private String scriptsSuffix;
private String versionSeparator;
private boolean baselineOnMigrate;
private String baselineVersion;
private PlaceholderReplacer replacer;
public FlywayInitializerBuilder setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
return this;
}
public FlywayInitializerBuilder setReplacer(PlaceholderReplacer replacer) {
this.replacer = replacer;
return this;
}
public FlywayInitializerBuilder addLocation(String location) {
if (locations == null) {
locations = new ArrayList<>();
}
locations.add(location);
return this;
}
public FlywayInitializerBuilder setScriptsPrefix(String scriptsPrefix) {
this.scriptsPrefix = scriptsPrefix;
return this;
}
public FlywayInitializerBuilder setScriptsSuffix(String scriptsSuffix) {
this.scriptsSuffix = scriptsSuffix;
return this;
}
public FlywayInitializerBuilder setVersionSeparator(String versionSeparator) {
this.versionSeparator = versionSeparator;
return this;
}
public FlywayInitializerBuilder setBaselineOnMigrate(boolean baselineOnMigrate) {
this.baselineOnMigrate = baselineOnMigrate;
return this;
}
public FlywayInitializerBuilder setBaselineVersion(String baselineVersion) {
this.baselineVersion = baselineVersion;
return this;
}
public FlywaySchemaInitializer build() {
if (locations == null) {
throw new IllegalStateException("locations required");
}
return new FlywaySchemaInitializer(
locations.toArray(new String[locations.size()]),
scriptsPrefix,
scriptsSuffix,
versionSeparator,
baselineOnMigrate,
baselineVersion,
dataSource,
replacer);
}
}
}

View File

@ -1,162 +0,0 @@
/*
* Copyright (c) 2012-2018 Red Hat, Inc.
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.core.db.schema.impl.flyway;
import static com.google.common.collect.Sets.newHashSet;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;
import java.io.IOException;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import org.flywaydb.core.Flyway;
import org.flywaydb.core.api.configuration.FlywayConfiguration;
import org.flywaydb.core.internal.util.Location;
import org.flywaydb.core.internal.util.scanner.Resource;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
/**
* Tests {@link ResourcesFinder}.
*
* @author Yevhenii Voevodin
*/
public class ResourcesFinderTest {
private final List<Path> cleanAfter = new ArrayList<>();
private final Flyway flyway = new Flyway();
@BeforeMethod
public void setUpDefaults() {
flyway.setSqlMigrationSuffix(".sql");
flyway.setSqlMigrationPrefix("");
}
@AfterMethod
public void cleanup() throws IOException {
for (Path path : cleanAfter) {
Files.delete(path);
}
cleanAfter.clear();
}
@Test
public void findsScriptsInClassPath() throws Exception {
flyway.setLocations("classpath:finder-sql-files");
cleanAfter.addAll(
createFiles(
"finder-sql-files/1.0/1.sql",
"finder-sql-files/1.0/2.sql",
"finder-sql-files/2.0/1.sql",
"finder-sql-files/2.0/postgresql/1.sql"));
final Set<String> locations = findResources(flyway).get("classpath:finder-sql-files");
assertEquals(
locations,
newHashSet(
"finder-sql-files/1.0/1.sql",
"finder-sql-files/1.0/2.sql",
"finder-sql-files/2.0/1.sql",
"finder-sql-files/2.0/postgresql/1.sql"));
}
@Test
public void findsScriptsOnFileSystem() throws Exception {
final List<Path> paths =
createFiles(
"finder-sql-files/1.0/1.sql",
"finder-sql-files/1.0/2.sql",
"finder-sql-files/2.0/1.sql",
"finder-sql-files/2.0/postgresql/1.sql");
cleanAfter.addAll(paths);
final Path finderSqlFiles = paths.get(0).getParent().getParent();
final String fsLocation = "filesystem:" + finderSqlFiles.toAbsolutePath();
flyway.setLocations(fsLocation);
final Set<String> locations = findResources(flyway).get(fsLocation);
assertEquals(
locations,
newHashSet(
finderSqlFiles.resolve("1.0").resolve("1.sql").toString(),
finderSqlFiles.resolve("1.0").resolve("2.sql").toString(),
finderSqlFiles.resolve("2.0").resolve("1.sql").toString(),
finderSqlFiles.resolve("2.0").resolve("postgresql").resolve("1.sql").toString()));
}
@Test
public void findsFileSystemAndClassPathScripts() throws Exception {
final List<Path> paths =
createFiles(
"finder-fs-sql-files/1.0/1.sql",
"finder-fs-sql-files/2.0/2.sql",
"finder-cp-sql-files/1.0/2.sql",
"finder-cp-sql-files/2.0/postgresql/1.sql");
cleanAfter.addAll(paths);
final Path finderFsSqlFiles = paths.get(0).getParent().getParent();
final String fsLocation = "filesystem:" + finderFsSqlFiles.toAbsolutePath();
final String cpLocation = "classpath:finder-cp-sql-files";
flyway.setLocations(fsLocation, cpLocation);
final Map<String, Set<String>> locations = findResources(flyway);
assertEquals(
locations.get(fsLocation),
newHashSet(
finderFsSqlFiles.resolve("1.0").resolve("1.sql").toString(),
finderFsSqlFiles.resolve("2.0").resolve("2.sql").toString()));
assertEquals(
locations.get(cpLocation),
newHashSet("finder-cp-sql-files/1.0/2.sql", "finder-cp-sql-files/2.0/postgresql/1.sql"));
}
private static Map<String, Set<String>> findResources(FlywayConfiguration configuration)
throws IOException {
final Map<Location, List<Resource>> resources =
new ResourcesFinder().findResources(configuration);
final Map<String, Set<String>> locations = new HashMap<>();
for (Map.Entry<Location, List<Resource>> entry : resources.entrySet()) {
locations.put(
entry.getKey().toString(),
entry.getValue().stream().map(Resource::getLocation).collect(Collectors.toSet()));
}
return locations;
}
private static List<Path> createFiles(String... paths) throws URISyntaxException, IOException {
final URL url = Thread.currentThread().getContextClassLoader().getResource(".");
assertNotNull(url);
final Path classesDir = Paths.get(url.toURI());
final List<Path> createdFiles = new ArrayList<>(paths.length);
for (String stringPath : paths) {
final Path path = classesDir.resolve(Paths.get(stringPath));
if (!Files.exists(path.getParent())) {
Files.createDirectories(path.getParent());
}
Files.write(path, path.toString().getBytes(StandardCharsets.UTF_8));
createdFiles.add(path);
}
return createdFiles;
}
}

View File

@ -1,67 +0,0 @@
/*
* Copyright (c) 2012-2018 Red Hat, Inc.
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.core.db.schema.impl.flyway;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNull;
import org.flywaydb.core.api.FlywayException;
import org.flywaydb.core.internal.util.Location;
import org.flywaydb.core.internal.util.scanner.Resource;
import org.flywaydb.core.internal.util.scanner.filesystem.FileSystemResource;
import org.testng.annotations.Test;
/**
* Tests {@link SqlScriptCreator}.
*
* @author Yevhenii Voevodin
*/
public class SqlScriptCreatorTest {
@Test
public void createsScript() throws Exception {
final Location location = new Location("filesystem:schema");
final Resource resource = new FileSystemResource("schema/5.0.0-M7/v1__init.sql");
final SqlScriptCreator scriptsCreator = new SqlScriptCreator();
final SqlScript script = scriptsCreator.createScript(location, resource);
assertEquals(script.name, "v1__init.sql");
assertEquals(script.location, location);
assertEquals(script.dir, "5.0.0-M7");
assertEquals(script.resource.getLocation(), resource.getLocation());
assertNull(script.vendor);
}
@Test
public void createsVendorScript() throws Exception {
final Location location = new Location("filesystem:schema");
final Resource resource = new FileSystemResource("schema/5.0.0-M7/postgresql/v1__init.sql");
final SqlScriptCreator scriptsCreator = new SqlScriptCreator();
final SqlScript script = scriptsCreator.createScript(location, resource);
assertEquals(script.name, "v1__init.sql");
assertEquals(script.location, location);
assertEquals(script.dir, "5.0.0-M7");
assertEquals(script.resource.getLocation(), resource.getLocation());
assertEquals(script.vendor, "postgresql");
}
@Test(expectedExceptions = FlywayException.class)
public void failsToCreateResourceWhenPathIsInvalid() throws Exception {
final Location location = new Location("filesystem:schema");
final Resource resource = new FileSystemResource("schema/v1__init.sql");
new SqlScriptCreator().createScript(location, resource);
}
}

View File

@ -1,88 +0,0 @@
/*
* Copyright (c) 2012-2018 Red Hat, Inc.
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.core.db.schema.impl.flyway;
import static org.testng.Assert.assertEquals;
import org.flywaydb.core.Flyway;
import org.flywaydb.core.api.FlywayException;
import org.flywaydb.core.api.MigrationVersion;
import org.flywaydb.core.internal.util.Location;
import org.flywaydb.core.internal.util.scanner.filesystem.FileSystemResource;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
/**
* Tests {@link VersionResolver}.
*
* @author Yevhenii Voevodin
*/
public class VersionResolverTest {
private final Flyway flyway = new Flyway();
private final VersionResolver resolver = new VersionResolver();
@BeforeMethod
public void setUpDefaults() {
flyway.setSqlMigrationSuffix(".sql");
flyway.setSqlMigrationPrefix("");
flyway.setSqlMigrationSeparator("__");
}
@Test(dataProvider = "validScripts")
public void resolvesVersion(String dir, String name, String expectedVersion) {
final SqlScript script =
new SqlScript(
new FileSystemResource("sql/" + dir + "/" + name),
new Location("filesystem:sql"),
dir,
null,
name);
assertEquals(resolver.resolve(script, flyway), MigrationVersion.fromVersion(expectedVersion));
}
@Test(dataProvider = "invalidScripts", expectedExceptions = FlywayException.class)
public void failsToResolveVersions(String dir, String name) throws Exception {
final SqlScript script =
new SqlScript(
new FileSystemResource("sql/" + dir + "/" + name),
new Location("filesystem:sql"),
dir,
null,
name);
resolver.resolve(script, flyway);
}
@DataProvider
public static Object[][] invalidScripts() {
return new String[][] {
{"1.0", "2016-11-11__init.sql"},
{"1.0", "one__init.sql"},
{"1.0", "__init.sql"},
{"1.0", "version1__script.sql"},
{"1.0", "1..1__script.sql"},
{"5..0.0", "1__init.sql"}
};
}
@DataProvider
public static Object[][] validScripts() {
return new Object[][] {
{"5.0.0-M7", "1__init.sql", "5.0.0.7.1"},
{"5.0.0-M7", "1.1__init_sub_tables.sql", "5.0.0.7.1.1"},
{"6.0", "0.1__specific_update.sql", "6.0.0.1"},
{"1.0", "1__simple.sql", "1.0.1"}
};
}
}

View File

@ -1,35 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (c) 2012-2018 Red Hat, Inc.
This program and the accompanying materials are made
available under the terms of the Eclipse Public License 2.0
which is available at https://www.eclipse.org/legal/epl-2.0/
SPDX-License-Identifier: EPL-2.0
Contributors:
Red Hat, Inc. - initial API and implementation
-->
<configuration>
<appender name="stdout" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%-41(%date[%.15thread]) %-45([%-5level] [%.30logger{30} %L]) - %msg%n</pattern>
</encoder>
</appender>
<appender name="file" class="ch.qos.logback.core.FileAppender">
<File>target/log/codenvy.log</File>
<encoder>
<pattern>%-41(%date[%.15thread]) %-45([%-5level] [%.30logger{30} %L]) - %msg%n</pattern>
</encoder>
</appender>
<root level="ERROR">
<appender-ref ref="stdout"/>
<appender-ref ref="file"/>
</root>
</configuration>

View File

@ -1,18 +0,0 @@
--
-- Copyright (c) 2012-2018 Red Hat, Inc.
-- This program and the accompanying materials are made
-- available under the terms of the Eclipse Public License 2.0
-- which is available at https://www.eclipse.org/legal/epl-2.0/
--
-- SPDX-License-Identifier: EPL-2.0
--
-- Contributors:
-- Red Hat, Inc. - initial API and implementation
--
CREATE TABLE test (
id INT,
text TEXT,
PRIMARY KEY (id)
);

View File

@ -1,15 +0,0 @@
--
-- Copyright (c) 2012-2018 Red Hat, Inc.
-- This program and the accompanying materials are made
-- available under the terms of the Eclipse Public License 2.0
-- which is available at https://www.eclipse.org/legal/epl-2.0/
--
-- SPDX-License-Identifier: EPL-2.0
--
-- Contributors:
-- Red Hat, Inc. - initial API and implementation
--
INSERT INTO test VALUES(1, 'test1');
INSERT INTO test VALUES(2, 'test2');
INSERT INTO test VALUES(3, 'test3');

View File

@ -1,12 +0,0 @@
--
-- Copyright (c) 2012-2018 Red Hat, Inc.
-- This program and the accompanying materials are made
-- available under the terms of the Eclipse Public License 2.0
-- which is available at https://www.eclipse.org/legal/epl-2.0/
--
-- SPDX-License-Identifier: EPL-2.0
--
-- Contributors:
-- Red Hat, Inc. - initial API and implementation
--

View File

@ -1,12 +0,0 @@
--
-- Copyright (c) 2012-2018 Red Hat, Inc.
-- This program and the accompanying materials are made
-- available under the terms of the Eclipse Public License 2.0
-- which is available at https://www.eclipse.org/legal/epl-2.0/
--
-- SPDX-License-Identifier: EPL-2.0
--
-- Contributors:
-- Red Hat, Inc. - initial API and implementation
--

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (c) 2012-2023 Red Hat, Inc.
Copyright (c) 2012-2024 Red Hat, Inc.
This program and the accompanying materials are made
available under the terms of the Eclipse Public License 2.0
which is available at https://www.eclipse.org/legal/epl-2.0/
@ -17,7 +17,7 @@
<parent>
<artifactId>che-core-parent</artifactId>
<groupId>org.eclipse.che.core</groupId>
<version>7.80.0-SNAPSHOT</version>
<version>7.86.0-SNAPSHOT</version>
</parent>
<artifactId>che-core-logback</artifactId>
<packaging>jar</packaging>

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (c) 2012-2023 Red Hat, Inc.
Copyright (c) 2012-2024 Red Hat, Inc.
This program and the accompanying materials are made
available under the terms of the Eclipse Public License 2.0
which is available at https://www.eclipse.org/legal/epl-2.0/
@ -17,7 +17,7 @@
<parent>
<artifactId>che-core-parent</artifactId>
<groupId>org.eclipse.che.core</groupId>
<version>7.80.0-SNAPSHOT</version>
<version>7.86.0-SNAPSHOT</version>
</parent>
<artifactId>che-core-metrics-core</artifactId>
<name>Che Core :: Commons :: Metrics :: Core</name>

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (c) 2012-2023 Red Hat, Inc.
Copyright (c) 2012-2024 Red Hat, Inc.
This program and the accompanying materials are made
available under the terms of the Eclipse Public License 2.0
which is available at https://www.eclipse.org/legal/epl-2.0/
@ -17,7 +17,7 @@
<parent>
<artifactId>che-core-parent</artifactId>
<groupId>org.eclipse.che.core</groupId>
<version>7.80.0-SNAPSHOT</version>
<version>7.86.0-SNAPSHOT</version>
</parent>
<artifactId>che-core-tracing-core</artifactId>
<name>Che Core :: Commons :: Tracing :: Core</name>

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (c) 2012-2023 Red Hat, Inc.
Copyright (c) 2012-2024 Red Hat, Inc.
This program and the accompanying materials are made
available under the terms of the Eclipse Public License 2.0
which is available at https://www.eclipse.org/legal/epl-2.0/
@ -17,7 +17,7 @@
<parent>
<artifactId>che-core-parent</artifactId>
<groupId>org.eclipse.che.core</groupId>
<version>7.80.0-SNAPSHOT</version>
<version>7.86.0-SNAPSHOT</version>
</parent>
<artifactId>che-core-tracing-metrics</artifactId>
<name>Che Core :: Commons :: Tracing :: Metrics</name>

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (c) 2012-2023 Red Hat, Inc.
Copyright (c) 2012-2024 Red Hat, Inc.
This program and the accompanying materials are made
available under the terms of the Eclipse Public License 2.0
which is available at https://www.eclipse.org/legal/epl-2.0/
@ -17,7 +17,7 @@
<parent>
<artifactId>che-core-parent</artifactId>
<groupId>org.eclipse.che.core</groupId>
<version>7.80.0-SNAPSHOT</version>
<version>7.86.0-SNAPSHOT</version>
</parent>
<artifactId>che-core-tracing-web</artifactId>
<name>Che Core :: Commons :: Tracing :: Web</name>

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (c) 2012-2023 Red Hat, Inc.
Copyright (c) 2012-2024 Red Hat, Inc.
This program and the accompanying materials are made
available under the terms of the Eclipse Public License 2.0
which is available at https://www.eclipse.org/legal/epl-2.0/
@ -17,7 +17,7 @@
<parent>
<artifactId>che-core-parent</artifactId>
<groupId>org.eclipse.che.core</groupId>
<version>7.80.0-SNAPSHOT</version>
<version>7.86.0-SNAPSHOT</version>
</parent>
<artifactId>che-core-typescript-dto-maven-plugin</artifactId>
<packaging>maven-plugin</packaging>

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (c) 2012-2023 Red Hat, Inc.
Copyright (c) 2012-2024 Red Hat, Inc.
This program and the accompanying materials are made
available under the terms of the Eclipse Public License 2.0
which is available at https://www.eclipse.org/legal/epl-2.0/
@ -17,7 +17,7 @@
<parent>
<artifactId>che-core-commons-parent</artifactId>
<groupId>org.eclipse.che.core</groupId>
<version>7.80.0-SNAPSHOT</version>
<version>7.86.0-SNAPSHOT</version>
</parent>
<artifactId>che-core-commons-annotations</artifactId>
<packaging>jar</packaging>

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (c) 2012-2023 Red Hat, Inc.
Copyright (c) 2012-2024 Red Hat, Inc.
This program and the accompanying materials are made
available under the terms of the Eclipse Public License 2.0
which is available at https://www.eclipse.org/legal/epl-2.0/
@ -17,7 +17,7 @@
<parent>
<artifactId>che-core-commons-parent</artifactId>
<groupId>org.eclipse.che.core</groupId>
<version>7.80.0-SNAPSHOT</version>
<version>7.86.0-SNAPSHOT</version>
</parent>
<artifactId>che-core-commons-inject</artifactId>
<packaging>jar</packaging>

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (c) 2012-2023 Red Hat, Inc.
Copyright (c) 2012-2024 Red Hat, Inc.
This program and the accompanying materials are made
available under the terms of the Eclipse Public License 2.0
which is available at https://www.eclipse.org/legal/epl-2.0/
@ -17,7 +17,7 @@
<parent>
<artifactId>che-core-commons-parent</artifactId>
<groupId>org.eclipse.che.core</groupId>
<version>7.80.0-SNAPSHOT</version>
<version>7.86.0-SNAPSHOT</version>
</parent>
<artifactId>che-core-commons-j2ee</artifactId>
<packaging>jar</packaging>

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (c) 2012-2023 Red Hat, Inc.
Copyright (c) 2012-2024 Red Hat, Inc.
This program and the accompanying materials are made
available under the terms of the Eclipse Public License 2.0
which is available at https://www.eclipse.org/legal/epl-2.0/
@ -17,7 +17,7 @@
<parent>
<artifactId>che-core-commons-parent</artifactId>
<groupId>org.eclipse.che.core</groupId>
<version>7.80.0-SNAPSHOT</version>
<version>7.86.0-SNAPSHOT</version>
</parent>
<artifactId>che-core-commons-json</artifactId>
<packaging>jar</packaging>

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (c) 2012-2023 Red Hat, Inc.
Copyright (c) 2012-2024 Red Hat, Inc.
This program and the accompanying materials are made
available under the terms of the Eclipse Public License 2.0
which is available at https://www.eclipse.org/legal/epl-2.0/
@ -17,7 +17,7 @@
<parent>
<artifactId>che-core-commons-parent</artifactId>
<groupId>org.eclipse.che.core</groupId>
<version>7.80.0-SNAPSHOT</version>
<version>7.86.0-SNAPSHOT</version>
</parent>
<artifactId>che-core-commons-lang</artifactId>
<packaging>jar</packaging>

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (c) 2012-2023 Red Hat, Inc.
Copyright (c) 2012-2024 Red Hat, Inc.
This program and the accompanying materials are made
available under the terms of the Eclipse Public License 2.0
which is available at https://www.eclipse.org/legal/epl-2.0/
@ -17,7 +17,7 @@
<parent>
<artifactId>che-core-commons-parent</artifactId>
<groupId>org.eclipse.che.core</groupId>
<version>7.80.0-SNAPSHOT</version>
<version>7.86.0-SNAPSHOT</version>
</parent>
<artifactId>che-core-commons-observability</artifactId>
<name>Che Core :: Commons :: Tracing and Monitoring wrapper</name>

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (c) 2012-2023 Red Hat, Inc.
Copyright (c) 2012-2024 Red Hat, Inc.
This program and the accompanying materials are made
available under the terms of the Eclipse Public License 2.0
which is available at https://www.eclipse.org/legal/epl-2.0/
@ -17,7 +17,7 @@
<parent>
<artifactId>che-core-commons-parent</artifactId>
<groupId>org.eclipse.che.core</groupId>
<version>7.80.0-SNAPSHOT</version>
<version>7.86.0-SNAPSHOT</version>
</parent>
<artifactId>che-core-commons-schedule</artifactId>
<packaging>jar</packaging>

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (c) 2012-2023 Red Hat, Inc.
Copyright (c) 2012-2024 Red Hat, Inc.
This program and the accompanying materials are made
available under the terms of the Eclipse Public License 2.0
which is available at https://www.eclipse.org/legal/epl-2.0/
@ -17,7 +17,7 @@
<parent>
<artifactId>che-core-commons-parent</artifactId>
<groupId>org.eclipse.che.core</groupId>
<version>7.80.0-SNAPSHOT</version>
<version>7.86.0-SNAPSHOT</version>
</parent>
<artifactId>che-core-commons-test</artifactId>
<packaging>jar</packaging>

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (c) 2012-2023 Red Hat, Inc.
Copyright (c) 2012-2024 Red Hat, Inc.
This program and the accompanying materials are made
available under the terms of the Eclipse Public License 2.0
which is available at https://www.eclipse.org/legal/epl-2.0/
@ -17,7 +17,7 @@
<parent>
<artifactId>che-core-commons-parent</artifactId>
<groupId>org.eclipse.che.core</groupId>
<version>7.80.0-SNAPSHOT</version>
<version>7.86.0-SNAPSHOT</version>
</parent>
<artifactId>che-core-commons-tracing</artifactId>
<name>Che Core :: Commons :: Tracing</name>

Some files were not shown because too many files have changed in this diff Show More