Compare commits

..

3 Commits
main ... 7.73.0

Author SHA1 Message Date
Mykhailo Kuznietsov 73d4c2d4dd chore: Release version 7.73.0
Signed-off-by: Mykhailo Kuznietsov <mkuznets@redhat.com>
2023-08-17 15:10:38 +00:00
Mykhailo Kuznietsov 9182a9ad26 chore: Set 7.73.0 release image tags
Signed-off-by: Mykhailo Kuznietsov <mkuznets@redhat.com>
2023-08-17 14:54:19 +00:00
Mykhailo Kuznietsov 9a092355c6 chore: Bump to 7.73.1-SNAPSHOT in 7.73.x
Signed-off-by: Mykhailo Kuznietsov <mkuznets@redhat.com>
2023-08-17 14:54:18 +00:00
616 changed files with 42594 additions and 7933 deletions

View File

@ -11,19 +11,18 @@
# Red Hat, Inc. - initial API and implementation
# Dockerfile to bootstrap build and test in openshift-ci
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
# Install yq, kubectl, chectl cli.
RUN yum install --assumeyes -d1 psmisc python3-pip httpd-tools nodejs && \
RUN yum install --assumeyes -d1 python3-pip httpd-tools && \
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://che-incubator.github.io/chectl/install.sh) --channel=next
bash <(curl -sL https://www.eclipse.org/che/chectl/) --channel=next && \
curl https://mirror.openshift.com/pub/openshift-v4/clients/ocp/4.12.4/openshift-client-linux.tar.gz | tar xvzf - -C /usr/local/bin/ oc && \
chmod ug+x /usr/local/bin/oc

View File

@ -1,19 +0,0 @@
-----BEGIN CERTIFICATE-----
MIIDDDCCAfSgAwIBAgIBATANBgkqhkiG9w0BAQsFADAmMSQwIgYDVQQDDBtpbmdy
ZXNzLW9wZXJhdG9yQDE3MDI5MTczMzkwHhcNMjMxMjE4MTYzNTM4WhcNMjUxMjE3
MTYzNTM5WjAmMSQwIgYDVQQDDBtpbmdyZXNzLW9wZXJhdG9yQDE3MDI5MTczMzkw
ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDDVfcIyqKLYcrmieDOCvAq
RKFR0PXqjl54DyfhkP7TC/rA4WMaJgYamYNNRcy4rOb+i3P1yepeVlXj+4gka41W
fh1QghqDGPpQTF7I8SDhnz3qdQymgSSkrxBWOGgJZRG3Gd50CNeh+ADdNlOxzZhJ
c1HI9/36Zp0M7RHLNwrYzKf/Scrcl3t/Ps4KHKsNtjNygnPSTjGwza5TTTAvGQ+h
3+c+bKJHZp6VFoEpubmBfCG8x+vJwBNI+YauXwti9EqFutnAbOiQ4aOvqQYINngV
OQTOg3xnifnooaR2iZPOtxPLUDMydHP9sDVNGLICpnKcFN6x5JKq1fAuwOAMRMQr
AgMBAAGjRTBDMA4GA1UdDwEB/wQEAwICpDASBgNVHRMBAf8ECDAGAQH/AgEAMB0G
A1UdDgQWBBRQfZkM6C20GT1YiTiS694vRPP2MDANBgkqhkiG9w0BAQsFAAOCAQEA
qd9ug2Bo2s3CG0qjNtk19WYYAuwkEMZU9L/FbSfmPkkOTbrZB71ofZbVan8Dx9/W
SfbkN1eJQNxd7QIDlExKEW2ufJIMCDe6haLHV8x+z3fISHg3wMUCPtadLG/exafy
agfj8PQgnJ1sbA/fKl0rqcVYuIihZ0DdMe28Yj92BFcs5+TXzVYzjyeIGonUZrCR
LtW2CxV7Ngue9pkWGsqQSlRwzp3knYfZxeQLneZcGlsSV4r9LOKIAA/MhBGgpwVc
zrh7L93jajHD1AD0sRdUQp4VVhysXVmMMSAjaLkqHsvSyJp7yKJOmrts6a274qbU
J1E6cXqtfF0NwRo2D9BouQ==
-----END CERTIFICATE-----

View File

@ -1,6 +1,6 @@
#!/bin/bash
#
# Copyright (c) 2023-2024 Red Hat, Inc.
# Copyright (c) 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/
@ -32,105 +32,48 @@ export PRIVATE_REPO_WORKSPACE_NAME=${PRIVATE_REPO_WORKSPACE_NAME:-"private-repo-
export PUBLIC_PROJECT_NAME=${PUBLIC_PROJECT_NAME:-"public-repo"}
export PRIVATE_PROJECT_NAME=${PRIVATE_PROJECT_NAME:-"private-repo"}
export YAML_FILE_NAME=${YAML_FILE_NAME:-"devfile.yaml"}
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 "------- [INFO] Start provisioning Openshift OAuth user -------"
echo -e "[INFO] 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 "------- [INFO] Waiting for htpasswd auth to be working up to 5 minutes -------"
echo -e "[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
echo "======= [INFO] OpenShift OAuth htpasswd is configured. =======
======= [INFO] Login to OCP cluster with admin user credentials is success.======="
return 0
break
fi
sleep 5
sleep 10
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 -------"
oc adm new-project ${CHE_NAMESPACE}
oc project ${CHE_NAMESPACE}
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}
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:
devEnvironments:
maxNumberOfRunningWorkspacesPerUser: 10000
maxNumberOfRunningWorkspacesPerUser: 10000
END
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 ======="
echo "Generated 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
}
@ -155,40 +98,44 @@ 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 -------"
testFactoryResolverResponse $1 200
PUBLIC_REPO_URL=$1
PRIVATE_REPO_URL=$2
echo "------- [INFO] Check factory resolver for private repository with NO PAT/OAuth setup -------"
testFactoryResolverResponse $2 500
}
echo "[INFO] Check factory resolver for public repository with NO PAT/OAuth setup"
if [ "$(requestFactoryResolverGitRepoUrl ${PUBLIC_REPO_URL} | grep "HTTP/1.1 200")" ]; then
echo "[INFO] Factory resolver returned 'HTTP/1.1 200' status code."
else
echo "[ERROR] Factory resolver returned wrong status code. Expected: HTTP/1.1 200."
exit 1
fi
# 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 -------"
testFactoryResolverResponse $1 200
echo "------- [INFO] Check factory resolver for private repository with NO PAT/OAuth setup -------"
testFactoryResolverResponse $2 400
echo "[INFO] Check factory resolver for private repository with NO PAT/OAuth setup"
if [ "$(requestFactoryResolverGitRepoUrl ${PRIVATE_REPO_URL} | grep "HTTP/1.1 400")" ]; then
echo "[INFO] Factory resolver returned 'HTTP/1.1 400' status code. Expected client side error."
else
echo "[ERROR] Factory resolver returned wrong status code. Expected 'HTTP/1.1 400'."
exit 1
fi
}
# check that factory resolver returns correct value with PAT/OAuth setup
testFactoryResolverWithPatOAuth() {
echo "------- [INFO] Check factory resolver for public repository with PAT/OAuth setup -------"
testFactoryResolverResponse $1 200
PUBLIC_REPO_URL=$1
PRIVATE_REPO_URL=$2
echo "------- [INFO] Check factory resolver for private repository with PAT/OAuth setup -------"
testFactoryResolverResponse $2 200
}
testFactoryResolverResponse() {
URL=$1
RESPONSE_CODE=$2
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] Check factory resolver for public repository with PAT/OAuth setup"
if [ "$(requestFactoryResolverGitRepoUrl ${PUBLIC_REPO_URL} | grep "HTTP/1.1 200")" ]; then
echo "[INFO] Factory resolver returned 'HTTP/1.1 200' status code."
else
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. #######"
echo "[ERROR] Factory resolver returned wrong status code. Expected: HTTP/1.1 200"
exit 1
fi
echo "[INFO] Check factory resolver for private repository with PAT/OAuth setup"
if [ "$(requestFactoryResolverGitRepoUrl ${PRIVATE_REPO_URL} | grep "HTTP/1.1 200")" ]; then
echo "[INFO] Factory resolver returned 'HTTP/1.1 200' status code."
else
echo "[ERROR] Factory resolver returned wrong status code. Expected: HTTP/1.1 200"
exit 1
fi
}
@ -206,19 +153,12 @@ 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
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. ======="
if [ "$(requestProvisionNamespace | grep "HTTP/1.1 200")" ]; then
echo "[INFO] Request provision user namespace returned 'HTTP/1.1 200' status code."
else
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. #######"
echo "[ERROR] Request provision user namespace returned wrong status code. Expected: HTTP/1.1 200"
exit 1
fi
}
@ -226,9 +166,10 @@ initUserNamespace() {
setupPersonalAccessToken() {
GIT_PROVIDER_TYPE=$1
GIT_PROVIDER_URL=$2
GIT_PROVIDER_PAT=$3
GIT_PROVIDER_USER_ID=$3
GIT_PROVIDER_PAT=$4
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)
@ -238,115 +179,12 @@ setupPersonalAccessToken() {
sed -i "s#che-user-id#${CHE_USER_ID}#g" pat-secret.yaml
sed -i "s#git-provider-name#${GIT_PROVIDER_TYPE}#g" pat-secret.yaml
sed -i "s#git-provider-url#${GIT_PROVIDER_URL}#g" pat-secret.yaml
sed -i "s#git-provider-user-id#${GIT_PROVIDER_USER_ID}#g" pat-secret.yaml
sed -i "s#encoded-access-token#${ENCODED_PAT}#g" pat-secret.yaml
if [ "${GIT_PROVIDER_TYPE}" == "azure-devops" ]; then
sed -i "s#''#${GIT_PROVIDER_USERNAME}#g" pat-secret.yaml
fi
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 "-------
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)
cat .ci/openshift-ci/ssh-secret.yaml > ssh-secret.yaml
# patch the ssh-secret.yaml file
sed -i "s#ssh_private_key#${ENCODED_GIT_PRIVATE_KEY}#g" ssh-secret.yaml
sed -i "s#ssh_public_key#${ENCODED_GIT_PUBLIC_KEY}#g" ssh-secret.yaml
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
createOAuthApplicationGitLabServer() {
ADMIN_ACCESS_TOKEN=$1
CHE_URL=https://$(oc get route -n ${CHE_NAMESPACE} che -o jsonpath='{.spec.host}')
echo "------- [INFO] Create OAuth Application -------"
response=$(curl -k -X POST \
${GIT_PROVIDER_URL}/api/v4/applications \
-H "PRIVATE-TOKEN: ${ADMIN_ACCESS_TOKEN}" \
-d "name=${APPLICATION_NAME}" \
-d "redirect_uri=${CHE_URL}/api/oauth/callback" \
-d "scopes=api write_repository openid")
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')
}
# Only for GitLab server administrator users
deleteOAuthApplicationGitLabServer() {
OAUTH_ID=$1
ADMIN_ACCESS_TOKEN=$2
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
revokeAuthorizedOAuthApplication() {
APPLICATION_ID=$1
APPLICATION_SECRET=$2
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 }')
OAUTH_TOKEN=$(oc get secret $OAUTH_TOKEN_NAME -o jsonpath='{.data.token}' | base64 -d)
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
setupOAuthSecret() {
APPLICATION_ID=$1
APPLICATION_SECRET=$2
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 }')
ENCODED_APP_ID=$(echo -n "${APPLICATION_ID}" | base64 -w 0)
ENCODED_APP_SECRET=$(echo -n "${APPLICATION_SECRET}" | base64 -w 0)
cat .ci/openshift-ci/oauth-secret.yaml > oauth-secret.yaml
# patch the oauth-secret.yaml file
sed -i "s#git-provider-url#${GIT_PROVIDER_URL}#g" oauth-secret.yaml
sed -i "s#encoded-application-id#${ENCODED_APP_ID}#g" oauth-secret.yaml
sed -i "s#encoded-application-secret#${ENCODED_APP_SECRET}#g" oauth-secret.yaml
cat oauth-secret.yaml
oc apply -f oauth-secret.yaml -n ${CHE_NAMESPACE}
echo "------- [INFO] Wait updating deployment after create OAuth secret -------"
oc wait --for=delete pod/${SERVER_POD} --timeout=120s
}
runTestWorkspaceWithGitRepoUrl() {
@ -358,7 +196,6 @@ 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
@ -368,7 +205,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() {
@ -377,131 +214,46 @@ 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 "[ERROR] Project file /projects/${PROJECT_NAME}/${YAML_FILE_NAME} does not exist."
return 1
fi
}
testGitCredentialsData() {
testGitCredentials() {
OCP_USER_NAMESPACE=$1
GIT_PROVIDER_PAT=$2
GIT_PROVIDER_URL=$3
echo "------- [INFO] Check the 'git credentials' is in a workspace -------"
hostName="${GIT_PROVIDER_URL#https://}"
if [ "${GIT_PROVIDER_TYPE}" == "azure-devops" ]; then
userName="username"
else
userName=${GIT_PROVIDER_USERNAME}
fi
gitCredentials="https://${userName}:${GIT_PROVIDER_PAT}@${hostName}"
echo "[INFO] Check the 'git credentials' is in a workspace"
gitCredentials="${GIT_PROVIDER_USERNAME}:${GIT_PROVIDER_PAT}"
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. ######
###### Cause possible: PR code regress or service is changed. Need to investigate it. #######"
exit 1
echo "[ERROR] Git credentials file '/.git-credentials/credentials' does not exist or has incorrect content."
return 1
fi
}
deleteTestWorkspace() {
WS_NAME=$1
OCP_USER_NAMESPACE=$2
echo "------- [INFO] Delete test workspace -------"
oc delete dw ${WS_NAME} -n ${OCP_USER_NAMESPACE}
}
startOAuthFactoryTest() {
CHE_URL=https://$(oc get route -n ${CHE_NAMESPACE} che -o jsonpath='{.spec.host}')
# patch oauth-factory-test.yaml
cat .ci/openshift-ci/pod-oauth-factory-test.yaml > oauth-factory-test.yaml
sed -i "s#CHE_URL#${CHE_URL}#g" oauth-factory-test.yaml
sed -i "s#CHE-NAMESPACE#${CHE_NAMESPACE}#g" oauth-factory-test.yaml
sed -i "s#OCP_USER_NAME#${OCP_NON_ADMIN_USER_NAME}#g" oauth-factory-test.yaml
sed -i "s#OCP_USER_PASSWORD#${OCP_LOGIN_PASSWORD}#g" oauth-factory-test.yaml
sed -i "s#FACTORY_REPO_URL#${PRIVATE_REPO_URL}#g" oauth-factory-test.yaml
sed -i "s#GIT_BRANCH#${GIT_REPO_BRANCH}#g" oauth-factory-test.yaml
sed -i "s#GIT_PROVIDER_TYPE#${GIT_PROVIDER_TYPE}#g" oauth-factory-test.yaml
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: -------"
cat oauth-factory-test.yaml
echo "[INFO] --------------------------------------------------"
oc apply -f oauth-factory-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] Factory test started successfully. ======="
return
fi
sleep 5
n=$(( n+1 ))
done
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() {
local RESULT=$?
killProcessByPort
if [ "$RESULT" != "0" ]; then
set +e
collectEclipseCheLogs
set -e
fi
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. #######"
[[ "${RESULT}" != "0" ]] && echo "[ERROR] Job failed." || echo "[INFO] Job completed successfully."
exit $RESULT
}
@ -509,69 +261,45 @@ collectEclipseCheLogs() {
mkdir -p ${ARTIFACTS_DIR}/che-logs
# Collect all Eclipse Che logs and cluster CR
oc login -u=${OCP_ADMIN_USER_NAME} -p=${OCP_LOGIN_PASSWORD} --insecure-skip-tls-verify=false
oc get checluster -o yaml -n $CHE_NAMESPACE > "${ARTIFACTS_DIR}/che-cluster.yaml"
chectl server:logs -n $CHE_NAMESPACE --directory ${ARTIFACTS_DIR}/che-logs --telemetry off
oc get checluster -o yaml -n $CHE_NAMESPACE > "${ARTIFACTS_DIR}/che-cluster.yaml"
}
collectLogs() {
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. -------"
collectEclipseCheLogs
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
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 test | grep EXIT_CODE)
if [[ ${EXIT_CODE} != "+ EXIT_CODE=0" ]]; then
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. ======="
}
testCloneGitRepoNoProjectExists() {
WS_NAME=$1
PROJECT_NAME=$2
GIT_REPO_URL=$3
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. -------"
testProjectIsCloned ${PROJECT_NAME} ${OCP_USER_NAMESPACE} && \
{ 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
testCloneGitRepoProjectShouldExists() {
testClonePublicRepoNoPatOAuth() {
WS_NAME=$1
PROJECT_NAME=$2
GIT_REPO_URL=$3
OCP_USER_NAMESPACE=$4
runTestWorkspaceWithGitRepoUrl ${WS_NAME} ${PROJECT_NAME} ${GIT_REPO_URL} ${OCP_USER_NAMESPACE}
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. #######
###### Cause possible: PR code regress or service is changed. Need to investigate it. #######" && exit 1; }
echo "[INFO] Check the public repository is cloned with NO PAT/OAuth setup"
testProjectIsCloned ${PROJECT_NAME} ${OCP_USER_NAMESPACE} || exit 1
deleteTestWorkspace ${WS_NAME} ${OCP_USER_NAMESPACE}
}
testClonePrivateRepoNoPatOAuth() {
WS_NAME=$1
PROJECT_NAME=$2
GIT_REPO_URL=$3
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"
testProjectIsCloned ${PROJECT_NAME} ${OCP_USER_NAMESPACE} && exit 1
deleteTestWorkspace ${WS_NAME} ${OCP_USER_NAMESPACE}
}
testCloneGitRepoWithSetupPat() {
WS_NAME=$1
PROJECT_NAME=$2
GIT_REPO_URL=$3
OCP_USER_NAMESPACE=$4
GIT_PROVIDER_PATH=$5
runTestWorkspaceWithGitRepoUrl ${WS_NAME} ${PROJECT_NAME} ${GIT_REPO_URL} ${OCP_USER_NAMESPACE}
testProjectIsCloned ${PROJECT_NAME} ${OCP_USER_NAMESPACE} || exit 1
testGitCredentials ${OCP_USER_NAMESPACE} ${GIT_PROVIDER_PAT}
deleteTestWorkspace ${WS_NAME} ${OCP_USER_NAMESPACE}
}
setupTestEnvironment() {
@ -583,17 +311,3 @@ setupTestEnvironment() {
forwardPortToService
initUserNamespace ${OCP_USER_NAME}
}
setupTestEnvironmentOAuthFlow() {
ADMIN_ACCESS_TOKEN=$1
APPLICATION_ID=$2
APPLICATION_SECRET=$3
provisionOpenShiftOAuthUser
configureGitSelfSignedCertificate
createCustomResourcesFile
patchCustomResourcesFile
deployChe
createOAuthApplicationGitLabServer ${ADMIN_ACCESS_TOKEN} ${APPLICATION_NAME}
setupOAuthSecret ${APPLICATION_ID} ${APPLICATION_SECRET}
}

View File

@ -4,7 +4,6 @@ metadata:
name: ws-name
spec:
started: true
routingClass: che
template:
projects:
- name: project-name

View File

@ -1,15 +0,0 @@
kind: Secret
apiVersion: v1
metadata:
name: gitlab-oauth-secret
namespace: eclipse-che
labels:
app.kubernetes.io/part-of: che.eclipse.org
app.kubernetes.io/component: oauth-scm-configuration
annotations:
che.eclipse.org/oauth-scm-server: gitlab
che.eclipse.org/scm-server-endpoint: git-provider-url
type: Opaque
data:
id: encoded-application-id
secret: encoded-application-secret

View File

@ -9,7 +9,8 @@ metadata:
che.eclipse.org/che-userid: che-user-id
che.eclipse.org/scm-personal-access-token-name: git-provider-name
che.eclipse.org/scm-url: git-provider-url
che.eclipse.org/scm-organization: ''
che.eclipse.org/scm-userid: 'git-provider-user-id'
che.eclipse.org/scm-username: chepullreq1
data:
token: encoded-access-token
type: Opaque

View File

@ -1,77 +0,0 @@
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

@ -1,89 +0,0 @@
apiVersion: v1
kind: Pod
metadata:
name: oauth-factory-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: "Factory"
- 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_SELENIUM_FACTORY_GIT_REPO_URL
value: "FACTORY_REPO_URL"
- name: TS_SELENIUM_FACTORY_GIT_REPO_BRANCH
value: "GIT_BRANCH"
- name: TS_SELENIUM_FACTORY_GIT_PROVIDER
value: "GIT_PROVIDER_TYPE"
- name: TS_SELENIUM_GIT_PROVIDER_OAUTH
value: "true"
- name: TS_SELENIUM_GIT_PROVIDER_USERNAME
value: "GIT_PROVIDER_USER_NAME"
- name: TS_SELENIUM_GIT_PROVIDER_PASSWORD
value: "GIT_PROVIDER_USER_PASSWORD"
- 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

@ -1,15 +0,0 @@
apiVersion: v1
kind: Secret
metadata:
name: git-ssh-key
annotations:
controller.devfile.io/mount-as: subpath
controller.devfile.io/mount-path: /etc/ssh/
labels:
controller.devfile.io/mount-to-devworkspace: "true"
controller.devfile.io/watch-secret: "true"
type: Opaque
data:
dwo_ssh_key: ssh_private_key
dwo_ssh_key.pub: ssh_public_key
ssh_config: aG9zdCAqCiAgSWRlbnRpdHlGaWxlIC9ldGMvc3NoL2R3b19zc2hfa2V5CiAgU3RyaWN0SG9zdEtleUNoZWNraW5nID0gbm8K

View File

@ -1,38 +0,0 @@
#!/bin/bash
#
# Copyright (c) 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
#
# 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 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"}
# import common test functions
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )"
source "${SCRIPT_DIR}"/common.sh
trap "catchFinish" EXIT SIGINT
setupTestEnvironment ${OCP_NON_ADMIN_USER_NAME}
testFactoryResolverResponse ${PUBLIC_REPO_RAW_PATH_URL} 200
testFactoryResolverResponse ${PRIVATE_REPO_RAW_PATH_URL} 500
testCloneGitRepoNoProjectExists ${PUBLIC_REPO_WORKSPACE_NAME} ${PUBLIC_PROJECT_NAME} ${PUBLIC_REPO_RAW_PATH_URL} ${USER_CHE_NAMESPACE}
deleteTestWorkspace ${PUBLIC_REPO_WORKSPACE_NAME} ${USER_CHE_NAMESPACE}
testCloneGitRepoNoProjectExists ${PRIVATE_REPO_WORKSPACE_NAME} ${PRIVATE_PROJECT_NAME} ${PRIVATE_REPO_RAW_PATH_URL} ${USER_CHE_NAMESPACE}
deleteTestWorkspace ${PRIVATE_REPO_WORKSPACE_NAME} ${USER_CHE_NAMESPACE}

View File

@ -1,40 +0,0 @@
#!/bin/bash
#
# Copyright (c) 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
#
# 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 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"}
# import common test functions
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )"
source "${SCRIPT_DIR}"/common.sh
trap "catchFinish" EXIT SIGINT
setupTestEnvironment ${OCP_NON_ADMIN_USER_NAME}
setupSSHKeyPairs "${AZURE_PRIVATE_KEY}" "${AZURE_PUBLIC_KEY}"
testFactoryResolverResponse ${PUBLIC_REPO_SSH_URL} 200
testFactoryResolverResponse ${PRIVATE_REPO_SSH_URL} 500
testCloneGitRepoProjectShouldExists ${PUBLIC_REPO_WORKSPACE_NAME} ${PUBLIC_PROJECT_NAME} ${PUBLIC_REPO_SSH_URL} ${USER_CHE_NAMESPACE}
deleteTestWorkspace ${PUBLIC_REPO_WORKSPACE_NAME} ${USER_CHE_NAMESPACE}
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

@ -1,35 +0,0 @@
#!/bin/bash
#
# Copyright (c) 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
#
# 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 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"}
# import common test functions
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )"
source "${SCRIPT_DIR}"/common.sh
trap "catchFinish" EXIT SIGINT
setupTestEnvironment ${OCP_NON_ADMIN_USER_NAME}
testFactoryResolverNoPatOAuth ${PUBLIC_REPO_URL} ${PRIVATE_REPO_URL}
testCloneGitRepoProjectShouldExists ${PUBLIC_REPO_WORKSPACE_NAME} ${PUBLIC_PROJECT_NAME} ${PUBLIC_REPO_URL} ${USER_CHE_NAMESPACE}
deleteTestWorkspace ${PUBLIC_REPO_WORKSPACE_NAME} ${USER_CHE_NAMESPACE}
testCloneGitRepoNoProjectExists ${PRIVATE_REPO_WORKSPACE_NAME} ${PRIVATE_PROJECT_NAME} ${PRIVATE_REPO_URL} ${USER_CHE_NAMESPACE}
deleteTestWorkspace ${PRIVATE_REPO_WORKSPACE_NAME} ${USER_CHE_NAMESPACE}

View File

@ -1,59 +0,0 @@
#!/bin/bash
#
# Copyright (c) 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
#
# 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 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"}
export GIT_PROVIDER_URL=${GIT_PROVIDER_URL:-"https://dev.azure.com"}
export PRIVATE_REPO_SSH_URL=${PRIVATE_REPO_SSH_URL:-"git@ssh.dev.azure.com:v3/chepullreq1/che-pr-private/private-repo"}
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"}
# import common test functions
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )"
source "${SCRIPT_DIR}"/common.sh
trap "catchFinish" EXIT SIGINT
setupTestEnvironment ${OCP_NON_ADMIN_USER_NAME}
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 -------"
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 -------"
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 -------"
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 -------"
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

@ -1,37 +0,0 @@
#!/bin/bash
#
# Copyright (c) 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
#
# 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 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"}
# import common test functions
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )"
source "${SCRIPT_DIR}"/common.sh
trap "catchFinish" EXIT SIGINT
setupTestEnvironment ${OCP_NON_ADMIN_USER_NAME}
testFactoryResolverNoPatOAuthRaw ${PUBLIC_REPO_RAW_PATH_URL} ${PRIVATE_REPO_RAW_PATH_URL}
testCloneGitRepoProjectShouldExists ${PUBLIC_REPO_WORKSPACE_NAME} ${PUBLIC_PROJECT_NAME} ${PUBLIC_REPO_RAW_PATH_URL} ${USER_CHE_NAMESPACE}
deleteTestWorkspace ${PUBLIC_REPO_WORKSPACE_NAME} ${USER_CHE_NAMESPACE}
testCloneGitRepoNoProjectExists ${PRIVATE_REPO_WORKSPACE_NAME} ${PRIVATE_PROJECT_NAME} ${PRIVATE_REPO_RAW_PATH_URL} ${USER_CHE_NAMESPACE}
deleteTestWorkspace ${PRIVATE_REPO_WORKSPACE_NAME} ${USER_CHE_NAMESPACE}

View File

@ -1,38 +0,0 @@
#!/bin/bash
#
# Copyright (c) 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
#
# 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 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"}
# import common test functions
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )"
source "${SCRIPT_DIR}"/common.sh
trap "catchFinish" EXIT SIGINT
setupTestEnvironment ${OCP_NON_ADMIN_USER_NAME}
setupSSHKeyPairs "${BITBUCKET_PRIVATE_KEY}" "${BITBUCKET_PUBLIC_KEY}"
testFactoryResolverNoPatOAuth ${PUBLIC_REPO_SSH_URL} ${PRIVATE_REPO_SSH_URL}
testCloneGitRepoProjectShouldExists ${PUBLIC_REPO_WORKSPACE_NAME} ${PUBLIC_PROJECT_NAME} ${PUBLIC_REPO_SSH_URL} ${USER_CHE_NAMESPACE}
deleteTestWorkspace ${PUBLIC_REPO_WORKSPACE_NAME} ${USER_CHE_NAMESPACE}
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,8 +16,6 @@ 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"}
@ -29,7 +27,5 @@ trap "catchFinish" EXIT SIGINT
setupTestEnvironment ${OCP_NON_ADMIN_USER_NAME}
testFactoryResolverNoPatOAuth ${PUBLIC_REPO_URL} ${PRIVATE_REPO_URL}
testCloneGitRepoProjectShouldExists ${PUBLIC_REPO_WORKSPACE_NAME} ${PUBLIC_PROJECT_NAME} ${PUBLIC_REPO_URL} ${USER_CHE_NAMESPACE}
deleteTestWorkspace ${PUBLIC_REPO_WORKSPACE_NAME} ${USER_CHE_NAMESPACE}
testCloneGitRepoNoProjectExists ${PRIVATE_REPO_WORKSPACE_NAME} ${PRIVATE_PROJECT_NAME} ${PRIVATE_REPO_URL} ${USER_CHE_NAMESPACE}
deleteTestWorkspace ${PRIVATE_REPO_WORKSPACE_NAME} ${USER_CHE_NAMESPACE}
testClonePublicRepoNoPatOAuth ${PUBLIC_REPO_WORKSPACE_NAME} ${PUBLIC_PROJECT_NAME} ${PUBLIC_REPO_URL} ${USER_CHE_NAMESPACE}
testClonePrivateRepoNoPatOAuth ${PRIVATE_REPO_WORKSPACE_NAME} ${PRIVATE_PROJECT_NAME} ${PRIVATE_REPO_URL} ${USER_CHE_NAMESPACE}

View File

@ -1,32 +0,0 @@
#!/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

@ -1,45 +0,0 @@
#!/bin/bash
#
# Copyright (c) 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
#
# 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 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"}
# import common test functions
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )"
source "${SCRIPT_DIR}"/common.sh
trap "catchFinish" EXIT SIGINT
setupTestEnvironment ${OCP_NON_ADMIN_USER_NAME}
setupSSHKeyPairs "${GITEA_PRIVATE_KEY}" "${GITEA_PUBLIC_KEY}"
testFactoryResolverResponse ${PUBLIC_REPO_SSH_URL} 200
testFactoryResolverResponse ${PRIVATE_REPO_SSH_URL} 200
testFactoryResolverResponse ${PUBLIC_REPO_RAW_PATH_URL} 200
testCloneGitRepoProjectShouldExists ${PUBLIC_REPO_WORKSPACE_NAME} ${PUBLIC_PROJECT_NAME} ${PUBLIC_REPO_SSH_URL} ${USER_CHE_NAMESPACE}
deleteTestWorkspace ${PUBLIC_REPO_WORKSPACE_NAME} ${USER_CHE_NAMESPACE}
testCloneGitRepoNoProjectExists ${PUBLIC_REPO_WORKSPACE_NAME} ${PUBLIC_PROJECT_NAME} ${PUBLIC_REPO_RAW_PATH_URL} ${USER_CHE_NAMESPACE}
deleteTestWorkspace ${PUBLIC_REPO_WORKSPACE_NAME} ${USER_CHE_NAMESPACE}
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

@ -1,33 +0,0 @@
#!/bin/bash
#
# Copyright (c) 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
#
# 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 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
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )"
source "${SCRIPT_DIR}"/common.sh
trap "catchFinish" EXIT SIGINT
setupTestEnvironment ${OCP_NON_ADMIN_USER_NAME}
testFactoryResolverResponse ${PRIVATE_REPO_RAW_PATH_URL} 200
testCloneGitRepoNoProjectExists ${PRIVATE_REPO_WORKSPACE_NAME} ${PRIVATE_PROJECT_NAME} ${PRIVATE_REPO_RAW_PATH_URL} ${USER_CHE_NAMESPACE}
deleteTestWorkspace ${PRIVATE_REPO_WORKSPACE_NAME} ${USER_CHE_NAMESPACE}

View File

@ -1,38 +0,0 @@
#!/bin/bash
#
# Copyright (c) 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
#
# 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 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"}
# import common test functions
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )"
source "${SCRIPT_DIR}"/common.sh
trap "catchFinish" EXIT SIGINT
setupTestEnvironment ${OCP_NON_ADMIN_USER_NAME}
testFactoryResolverNoPatOAuthRaw ${PUBLIC_REPO_RAW_PATH_URL} ${PRIVATE_REPO_RAW_PATH_URL}
testCloneGitRepoNoProjectExists ${PUBLIC_REPO_WORKSPACE_NAME} ${PUBLIC_PROJECT_NAME} ${PUBLIC_REPO_RAW_PATH_URL} ${USER_CHE_NAMESPACE}
deleteTestWorkspace ${PUBLIC_REPO_WORKSPACE_NAME} ${USER_CHE_NAMESPACE}
testCloneGitRepoNoProjectExists ${PRIVATE_REPO_WORKSPACE_NAME} ${PRIVATE_PROJECT_NAME} ${PRIVATE_REPO_RAW_PATH_URL} ${USER_CHE_NAMESPACE}
deleteTestWorkspace ${PRIVATE_REPO_WORKSPACE_NAME} ${USER_CHE_NAMESPACE}

View File

@ -1,38 +0,0 @@
#!/bin/bash
#
# Copyright (c) 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
#
# 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 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"}
# import common test functions
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )"
source "${SCRIPT_DIR}"/common.sh
trap "catchFinish" EXIT SIGINT
setupTestEnvironment ${OCP_NON_ADMIN_USER_NAME}
setupSSHKeyPairs "${GITHUB_PRIVATE_KEY}" "${GITHUB_PUBLIC_KEY}"
testFactoryResolverNoPatOAuth ${PUBLIC_REPO_SSH_URL} ${PRIVATE_REPO_SSH_URL}
testCloneGitRepoProjectShouldExists ${PUBLIC_REPO_WORKSPACE_NAME} ${PUBLIC_PROJECT_NAME} ${PUBLIC_REPO_SSH_URL} ${USER_CHE_NAMESPACE}
deleteTestWorkspace ${PUBLIC_REPO_WORKSPACE_NAME} ${USER_CHE_NAMESPACE}
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,8 +16,6 @@ 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"}
@ -29,7 +27,5 @@ trap "catchFinish" EXIT SIGINT
setupTestEnvironment ${OCP_NON_ADMIN_USER_NAME}
testFactoryResolverNoPatOAuth ${PUBLIC_REPO_URL} ${PRIVATE_REPO_URL}
testCloneGitRepoProjectShouldExists ${PUBLIC_REPO_WORKSPACE_NAME} ${PUBLIC_PROJECT_NAME} ${PUBLIC_REPO_URL} ${USER_CHE_NAMESPACE}
deleteTestWorkspace ${PUBLIC_REPO_WORKSPACE_NAME} ${USER_CHE_NAMESPACE}
testCloneGitRepoNoProjectExists ${PRIVATE_REPO_WORKSPACE_NAME} ${PRIVATE_PROJECT_NAME} ${PRIVATE_REPO_URL} ${USER_CHE_NAMESPACE}
deleteTestWorkspace ${PRIVATE_REPO_WORKSPACE_NAME} ${USER_CHE_NAMESPACE}
testClonePublicRepoNoPatOAuth ${PUBLIC_REPO_WORKSPACE_NAME} ${PUBLIC_PROJECT_NAME} ${PUBLIC_REPO_URL} ${USER_CHE_NAMESPACE}
testClonePrivateRepoNoPatOAuth ${PRIVATE_REPO_WORKSPACE_NAME} ${PRIVATE_PROJECT_NAME} ${PRIVATE_REPO_URL} ${USER_CHE_NAMESPACE}

View File

@ -16,14 +16,10 @@ 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"}
export GIT_PROVIDER_URL=${GIT_PROVIDER_URL:-"https://github.com"}
export PRIVATE_REPO_RAW_PATH_URL=${PRIVATE_REPO_URL:-"https://raw.githubusercontent.com/chepullreq1/private-repo/main/devfile.yaml"}
export PRIVATE_REPO_SSH_URL=${PRIVATE_REPO_SSH_URL:-"git@github.com:chepullreq1/private-repo.git"}
# import common test functions
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )"
@ -32,28 +28,10 @@ source "${SCRIPT_DIR}"/common.sh
trap "catchFinish" EXIT SIGINT
setupTestEnvironment ${OCP_NON_ADMIN_USER_NAME}
setupPersonalAccessToken ${GIT_PROVIDER_TYPE} ${GIT_PROVIDER_URL} ${GITHUB_PAT}
setupPersonalAccessToken ${GIT_PROVIDER_TYPE} ${GIT_PROVIDER_URL} ${GITHUB_USER_ID} ${GITHUB_PAT}
requestProvisionNamespace
testFactoryResolverWithPatOAuth ${PUBLIC_REPO_URL} ${PRIVATE_REPO_URL}
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 -------"
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 -------"
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 -------"
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}
echo "[INFO] Check clone public repository with PAT setup"
testCloneGitRepoWithSetupPat ${PUBLIC_REPO_WORKSPACE_NAME} ${PUBLIC_PROJECT_NAME} ${PUBLIC_REPO_URL} ${USER_CHE_NAMESPACE} ${GITHUB_PAT}
echo "[INFO] Check clone private repository with PAT setup"
testCloneGitRepoWithSetupPat ${PRIVATE_REPO_WORKSPACE_NAME} ${PRIVATE_PROJECT_NAME} ${PRIVATE_REPO_URL} ${USER_CHE_NAMESPACE} ${GITHUB_PAT}

View File

@ -1,37 +0,0 @@
#!/bin/bash
#
# Copyright (c) 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
#
# 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 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"}
# import common test functions
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )"
source "${SCRIPT_DIR}"/common.sh
trap "catchFinish" EXIT SIGINT
setupTestEnvironment ${OCP_NON_ADMIN_USER_NAME}
testFactoryResolverNoPatOAuthRaw ${PUBLIC_REPO_RAW_PATH_URL} ${PRIVATE_REPO_RAW_PATH_URL}
testCloneGitRepoNoProjectExists ${PUBLIC_REPO_WORKSPACE_NAME} ${PUBLIC_PROJECT_NAME} ${PUBLIC_REPO_RAW_PATH_URL} ${USER_CHE_NAMESPACE}
deleteTestWorkspace ${PUBLIC_REPO_WORKSPACE_NAME} ${USER_CHE_NAMESPACE}
testCloneGitRepoNoProjectExists ${PRIVATE_REPO_WORKSPACE_NAME} ${PRIVATE_PROJECT_NAME} ${PRIVATE_REPO_RAW_PATH_URL} ${USER_CHE_NAMESPACE}
deleteTestWorkspace ${PRIVATE_REPO_WORKSPACE_NAME} ${USER_CHE_NAMESPACE}

View File

@ -1,39 +0,0 @@
#!/bin/bash
#
# Copyright (c) 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
#
# 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 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"}
# import common test functions
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )"
source "${SCRIPT_DIR}"/common.sh
trap "catchFinish" EXIT SIGINT
setupTestEnvironment ${OCP_NON_ADMIN_USER_NAME}
setupSSHKeyPairs "${GITLAB_PRIVATE_KEY}" "${GITLAB_PUBLIC_KEY}"
testFactoryResolverNoPatOAuth ${PUBLIC_REPO_SSH_URL} ${PRIVATE_REPO_SSH_URL}
testCloneGitRepoProjectShouldExists ${PUBLIC_REPO_WORKSPACE_NAME} ${PUBLIC_PROJECT_NAME} ${PUBLIC_REPO_SSH_URL} ${USER_CHE_NAMESPACE}
deleteTestWorkspace ${PUBLIC_REPO_WORKSPACE_NAME} ${USER_CHE_NAMESPACE}
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,8 +16,6 @@ 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"}
@ -29,7 +27,5 @@ trap "catchFinish" EXIT SIGINT
setupTestEnvironment ${OCP_NON_ADMIN_USER_NAME}
testFactoryResolverNoPatOAuth ${PUBLIC_REPO_URL} ${PRIVATE_REPO_URL}
testCloneGitRepoProjectShouldExists ${PUBLIC_REPO_WORKSPACE_NAME} ${PUBLIC_PROJECT_NAME} ${PUBLIC_REPO_URL} ${USER_CHE_NAMESPACE}
deleteTestWorkspace ${PUBLIC_REPO_WORKSPACE_NAME} ${USER_CHE_NAMESPACE}
testCloneGitRepoNoProjectExists ${PRIVATE_REPO_WORKSPACE_NAME} ${PRIVATE_PROJECT_NAME} ${PRIVATE_REPO_URL} ${USER_CHE_NAMESPACE}
deleteTestWorkspace ${PRIVATE_REPO_WORKSPACE_NAME} ${USER_CHE_NAMESPACE}
testClonePublicRepoNoPatOAuth ${PUBLIC_REPO_WORKSPACE_NAME} ${PUBLIC_PROJECT_NAME} ${PUBLIC_REPO_URL} ${USER_CHE_NAMESPACE}
testClonePrivateRepoNoPatOAuth ${PRIVATE_REPO_WORKSPACE_NAME} ${PRIVATE_PROJECT_NAME} ${PRIVATE_REPO_URL} ${USER_CHE_NAMESPACE}

View File

@ -1,39 +0,0 @@
#!/bin/bash
#
# Copyright (c) 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
#
# 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:-"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"}
export GIT_PROVIDER_LOGIN=${GIT_PROVIDER_LOGIN:-"admin-user"}
export PRIVATE_REPO_URL=${PRIVATE_REPO_URL:-"https://gitlab-gitlab-system.apps.git.crw-qe.com/admin-user/private-repo.git"}
export GIT_REPO_BRANCH=${PRIVATE_REPO_BRANCH:-"main"}
export APPLICATION_NAME=${APPLICATION_NAME:-"TestApp"}
export OAUTH_ID=""
export APPLICATION_ID=""
export APPLICATION_SECRET=""
# import common test functions
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )"
source "${SCRIPT_DIR}"/common.sh
trap "collectLogs" EXIT SIGINT
setupTestEnvironmentOAuthFlow ${ADMIN_ACCESS_TOKEN} ${APPLICATION_NAME} ${APPLICATION_ID} ${APPLICATION_SECRET}
startOAuthFactoryTest

View File

@ -16,14 +16,10 @@ 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"}
export GIT_PROVIDER_URL=${GIT_PROVIDER_URL:-"https://gitlab.com"}
export PRIVATE_REPO_SSH_URL=${PRIVATE_REPO_SSH_URL:-"git@gitlab.com:chepullreq1/private-repo.git"}
export PRIVATE_REPO_RAW_PATH_URL=${PRIVATE_REPO_URL:-"https://gitlab.com/chepullreq1/private-repo/-/raw/main/devfile.yaml"}
# import common test functions
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )"
@ -32,28 +28,10 @@ source "${SCRIPT_DIR}"/common.sh
trap "catchFinish" EXIT SIGINT
setupTestEnvironment ${OCP_NON_ADMIN_USER_NAME}
setupPersonalAccessToken ${GIT_PROVIDER_TYPE} ${GIT_PROVIDER_URL} ${GITLAB_PAT}
setupPersonalAccessToken ${GIT_PROVIDER_TYPE} ${GIT_PROVIDER_URL} ${GITLAB_USER_ID} ${GITLAB_PAT}
requestProvisionNamespace
testFactoryResolverWithPatOAuth ${PUBLIC_REPO_URL} ${PRIVATE_REPO_URL}
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 -------"
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 -------"
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 -------"
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}
echo "[INFO] Check clone public repository with PAT setup"
testCloneGitRepoWithSetupPat ${PUBLIC_REPO_WORKSPACE_NAME} ${PUBLIC_PROJECT_NAME} ${PUBLIC_REPO_URL} ${USER_CHE_NAMESPACE} ${GITLAB_PAT}
echo "[INFO] Check clone private repository with PAT setup"
testCloneGitRepoWithSetupPat ${PRIVATE_REPO_WORKSPACE_NAME} ${PRIVATE_PROJECT_NAME} ${PRIVATE_REPO_URL} ${USER_CHE_NAMESPACE} ${GITLAB_PAT}

5
.github/CODEOWNERS vendored
View File

@ -1,8 +1,11 @@
# Global Owners
* @SDawley @ibuziuk @vinokurig @tolusha
* @l0rd @ibuziuk @vinokurig @nickboldt @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

@ -31,23 +31,23 @@ jobs:
cache: 'maven'
- name: Login to docker.io
if: github.event_name == 'pull_request'
uses: redhat-actions/podman-login@v1
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_PASSWORD }}
registry: docker.io
- name: Login to quay.io
if: github.event_name == 'pull_request'
uses: redhat-actions/podman-login@v1
uses: docker/login-action@v2
with:
username: ${{ secrets.QUAY_USERNAME }}
password: ${{ secrets.QUAY_PASSWORD }}
registry: quay.io
- name: Build with Maven
run: mvn -B clean install -U -Pintegration
- name: Build images
- name: Build docker images
if: github.event_name == 'pull_request'
run: ./build/build.sh --tag:${{ env.PR_IMAGE_TAG }}
- name: Push images
run: ./dockerfiles/build.sh --tag:${{ env.PR_IMAGE_TAG }}
- name: Push docker images
if: github.event_name == 'pull_request'
run: podman push quay.io/eclipse/che-server:${{ env.PR_IMAGE_TAG }}
run: docker push quay.io/eclipse/che-server:${{ env.PR_IMAGE_TAG }}

View File

@ -29,28 +29,37 @@ jobs:
java-version: '11'
cache: 'maven'
- name: Login to docker.io
uses: redhat-actions/podman-login@v1
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_PASSWORD }}
registry: docker.io
- name: Login to quay.io
uses: redhat-actions/podman-login@v1
uses: docker/login-action@v2
with:
username: ${{ secrets.QUAY_USERNAME }}
password: ${{ secrets.QUAY_PASSWORD }}
registry: quay.io
- name: Build with Maven
run: mvn -B clean install -U -Pintegration
- name: Build images
- name: Build docker images
id: build
run: |
echo "short_sha1=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT
./build/build.sh --tag:next --sha-tag
./dockerfiles/build.sh --tag:next --sha-tag
- name: Push docker images
run: |
podman push quay.io/eclipse/che-server:next
podman push quay.io/eclipse/che-server:${{ steps.build.outputs.short_sha1 }}
docker push quay.io/eclipse/che-endpoint-watcher:next
docker push quay.io/eclipse/che-endpoint-watcher:${{ steps.build.outputs.short_sha1 }}
docker push quay.io/eclipse/che-keycloak:next
docker push quay.io/eclipse/che-keycloak:${{ steps.build.outputs.short_sha1 }}
docker push quay.io/eclipse/che-postgres:next
docker push quay.io/eclipse/che-postgres:${{ steps.build.outputs.short_sha1 }}
docker push quay.io/eclipse/che-server:next
docker push quay.io/eclipse/che-server:${{ steps.build.outputs.short_sha1 }}
- name: Create failure MM message
if: ${{ failure() }}
run: |

View File

@ -1,5 +1,5 @@
#
# Copyright (c) 2020-2023 Red Hat, Inc.
# Copyright (c) 2020 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/
@ -88,10 +88,11 @@ jobs:
run: |
sudo apt-get update -y || true
# install more dependencies
sudo apt-get -y -q install wget curl bash git
sudo apt-get -y -q install wget curl bash git
java -version
git --version
gh --version
# want git >=2.24, hub >=2
hub --version # hub reports git version too
# want >=5
bash --version

8
.gitignore vendored
View File

@ -1,5 +1,3 @@
.repository/
# Eclipse #
###################
@ -13,6 +11,10 @@ test-output/
maven-eclipse.xml
.factorypath
# Theia #
##################
.theia/
# Idea #
##################
*.iml
@ -46,6 +48,8 @@ maven-eclipse.xml
*.war
*.ear
# Logs and databases #
######################
*.log

View File

@ -1,82 +0,0 @@
## Developing with Eclipse Che
This project contains a [devfile v2](https://github.com/eclipse-che/che-server/blob/main/devfile.yaml) located in the project's root directory.
With this devfile you can perform the following tasks:
- Build project sources with maven.
- Build a container image.
- Push your changes to GitHub.
### Starting a Workspace within Eclipse Che
To start a new workspace within Eclipse Che, navigate to the following URL:
```sh
{CHE-HOST}/#https://github.com/eclipse-che/che-server
```
### Running Devfile Tasks for Downloading Dependencies and Building the Project
For VS Code, execute tasks defined in the devfile with these steps:
1. Open the command palette (Ctrl/Cmd + Shift + P).
2. Execute the `Tasks: Run Task` command.
3. Select the `devfile` folder and select the `1. Build sources` task to build the project sources with maven.
4. Follow steps 1 and 2 again, select the `1. Build image` task to build a container image.
5. In the workspace terminal, tag the **che-server** image with your account: `podman tag quay.io/eclipse/che-server:next <docker registry>/<your account>/che-server:next`.
6. Push the **che-server** image to your account: `podman push <docker registry>/<your account>/che-server:next`.
# Local build requirements
- Apache Maven 3.9 or later
- JDK 11
- Podman or Docker (required for running integration tests)
A Che workspace environment allows to build the image internally, using the workspace terminal.
# Start and debug
1. Deploy Che to a [Red Hat OpenShift](https://www.eclipse.org/che/docs/stable/administration-guide/installing-che-on-openshift-using-cli/) or [Minikube](https://www.eclipse.org/che/docs/stable/administration-guide/installing-che-on-minikube/) cluster by using a previously built image: `chectl server:start --platform=<openshift / minikube> --cheimage=<docker registry>/<your account>/che-server:next`.
2. Enable local debugging of the Eclipse Che server: `chectl server:debug`.
3. In your IDE, create a new Remote JVM Debug configuration on `localhost:8000`.
4. Hit a breakpoint in the code and activate the debug configuration.
# Contributing an SCM provider
An SCM provider support has to be provided by adding new maven modules to the wsmaster directory.
## Implementing che-core-api-oauth-<SCM provider name> module
This module is responsible for Oauth requests to the SCM provider and contans next implementations:
1. `<SCM provider name>OAuthAuthenticator` contains specific implementation of Oauth token requestand authentication endpoint.
2. `<SCM provider name>OAuthAuthenticatorProvider` a provider of the `OAuthAuthenticator`.
## Implementing coresponding che-core-api-factory-<SCM provider name> module
This module is responsible for API operations of the specific SCM provider.
1. `<SCM provider name>ApiClient` contains all necessary HTTP API calls like `getUser()`.
2. `<SCM provider name>AuthorisingFileContentProvider` overrides the common `AuthorisingFileContentProvider` to define the specific `isPublicRepository()` function.
3. `<SCM provider name>FactoryParameterResolver` validates SCM URL if it corresponds to the SCM provider. Also Provides specific Factory Parameters resolver for the SCM repository.
4. `<SCM provider name>PersonalAccessTokenFetcher` fetches Personal Access Token from the SCM provider by reqesting the OAuth API of the provider. Validates the token by comparing the token access scopes with the predefined scope list.
5. `<SCM provider name>FileResolver` Implementation of a resolver that can return particular file content from specified SCM repository.
6. `<SCM provider name>URLParser` Parses the string representation of the URL to an SCM specific object
7. `<SCM provider name>UserDataFetcher` Implementation of a resolver that can return particular file content from specified SCM repository.
# CI
There are several [GitHub Actions](https://github.com/eclipse-che/che-server/actions) workflows implemented for this repository:
- [![build-next](https://github.com/eclipse-che/che-server/actions/workflows/next-build.yml/badge.svg)](https://github.com/eclipse-che/che-server/actions/workflows/next-build.yml)
Builds Maven artifacts, builds container images and pushes them to [quay.io](https://quay.io/organization/eclipse) on each commit to [`main`](https://github.com/eclipse-che/che-server/tree/main) branch.
- [![Release Che Server](https://github.com/eclipse-che/che-server/actions/workflows/release.yml/badge.svg)](https://github.com/eclipse-che/che-server/actions/workflows/release.yml)
Builds Maven artifacts and container images. Images are public and pushed to [quay.io](https://quay.io/organization/eclipse). See [RELEASE.md](https://github.com/eclipse-che/che-server/blob/master/RELEASE.md) for more information about this workflow.
- [![Release Changelog](https://github.com/eclipse-che/che-server/actions/workflows/release-changelog.yml/badge.svg)](https://github.com/eclipse-che/che-server/actions/workflows/release-changelog.yml)
Creates a GitHub release which will include a generated changelog.
- [![Update Che docs variables](https://github.com/eclipse-che/che-server/actions/workflows/che-properties-docs-update.yml/badge.svg)](https://github.com/eclipse-che/che-server/actions/workflows/che-properties-docs-update.yml/badge.svg)
Runs on each commit to [`main`](https://github.com/eclipse-che/che-server/tree/main) branch.
- [![build-pr-check](https://github.com/eclipse-che/che-server/actions/workflows/build-pr-check.yml/badge.svg)](https://github.com/eclipse-che/che-server/actions/workflows/build-pr-check.yml)
Builds Maven artifacts and container images. This workflow is used as a check for all pull requests that are submitted to this project.
- [![Sonar](https://github.com/eclipse-che/che-server/actions/workflows/sonar.yaml/badge.svg)](https://github.com/eclipse-che/che-server/actions/workflows/sonar.yaml)
Runs Sonar against the main branch. The result can be seen [here](https://sonarcloud.io/dashboard?id=org.eclipse.che%3Ache-server).
- [![Try in Web IDE](https://github.com/eclipse-che/che-server/actions/workflows/try-in-web-ide.yaml/badge.svg)](https://github.com/eclipse-che/che-server/actions/workflows/try-in-web-ide.yaml)
Used as a check for pull requests that are submitted to this project.
Downstream builds can be found at the link below, which is _internal to Red Hat_. Stable builds can be found by replacing the 3.x with a specific version like 3.2.
- [server_3.x](https://main-jenkins-csb-crwqe.apps.ocp-c1.prod.psi.redhat.com/job/DS_CI/job/server_3.x/)
# Report issues
Issues are tracked on the main Eclipse Che Repository: https://github.com/eclipse/che/issues

View File

@ -1,6 +1,6 @@
# What is Che server
Che Server provides an API for managing Kubernetes namespaces and to retrieve devfile content from repositories,
hosted on GitHub, GitLab, Bitbucket and Microsoft Azure Repos.
Che Server provides an API for managing Kubernetes namespaces, and to retrieve devfile content from repositories,
hosted on GitHub, GitLab, Bitbucket, and Microsoft Azure Repos.
# Project structure
Che Server is mostly a Java web application deployed on an Apache Tomcat server in a container. Che Server uses the following modules:
@ -24,6 +24,49 @@ Che Server is mostly a Java web application deployed on an Apache Tomcat server
Other modules are deprecated and will be removed in the future.
# Build requirements
- Apache Maven 3.6.3 or later
- JDK 11
- Podman or Docker (required for running integration tests)
# Sources build
Run `mvn clean install` to build. Activate a faster profile build by adding `-Pfast`.
# Image build and push
1. Go to the `dockerfiles` directory.
2. Run `./build.sh`.
3. Tag the **che-server** image with your account: `docker tag quay.io/eclipse/che-server:next <docker registry>/<your account>/che-server:next`.
4. Push the **che-server** image to your account: `docker push <docker registry>/<your account>/che-server:next`.
# Debug
1. Deploy Che to a [Red Hat OpenShift](https://www.eclipse.org/che/docs/stable/administration-guide/installing-che-on-openshift-using-cli/) or [Minikube](https://www.eclipse.org/che/docs/stable/administration-guide/installing-che-on-minikube/) cluster by using a previously built image: `chectl server:start --platform=<openshift / minikube> --cheimage=<docker registry>/<your account>/che-server:next`.
2. Enable local debugging of the Eclipse Che server: `chectl server:debug`.
3. In your IDE, create a new Remote JVM Debug configuration on `localhost:8000`.
4. Hit a breakpoint in the code and activate the debug configuration.
# CI
There are several [GitHub Actions](https://github.com/eclipse-che/che-server/actions) workflows implemented for this repository:
- [![build-next](https://github.com/eclipse-che/che-server/actions/workflows/next-build.yml/badge.svg)](https://github.com/eclipse-che/che-server/actions/workflows/next-build.yml)
Builds Maven artifacts, builds container images and pushes them to [quay.io](https://quay.io/organization/eclipse) on each commit to [`main`](https://github.com/eclipse-che/che-server/tree/main) branch.
- [![Release Che Server](https://github.com/eclipse-che/che-server/actions/workflows/release.yml/badge.svg)](https://github.com/eclipse-che/che-server/actions/workflows/release.yml)
Builds Maven artifacts and container images. Images are public and pushed to [quay.io](https://quay.io/organization/eclipse). See [RELEASE.md](https://github.com/eclipse-che/che-server/blob/master/RELEASE.md) for more information about this workflow.
- [![Release Changelog](https://github.com/eclipse-che/che-server/actions/workflows/release-changelog.yml/badge.svg)](https://github.com/eclipse-che/che-server/actions/workflows/release-changelog.yml)
Creates a GitHub release which will include a generated changelog.
- [![Update Che docs variables](https://github.com/eclipse-che/che-server/actions/workflows/che-properties-docs-update.yml/badge.svg)](https://github.com/eclipse-che/che-server/actions/workflows/che-properties-docs-update.yml/badge.svg)
Runs on each commit to [`main`](https://github.com/eclipse-che/che-server/tree/main) branch.
- [![build-pr-check](https://github.com/eclipse-che/che-server/actions/workflows/build-pr-check.yml/badge.svg)](https://github.com/eclipse-che/che-server/actions/workflows/build-pr-check.yml)
Builds Maven artifacts and container images. This workflow is used as a check for all pull requests that are submitted to this project.
- [![Sonar](https://github.com/eclipse-che/che-server/actions/workflows/sonar.yaml/badge.svg)](https://github.com/eclipse-che/che-server/actions/workflows/sonar.yaml)
Runs Sonar against the main branch. The result can be seen [here](https://sonarcloud.io/dashboard?id=org.eclipse.che%3Ache-server).
- [![Try in Web IDE](https://github.com/eclipse-che/che-server/actions/workflows/try-in-web-ide.yaml/badge.svg)](https://github.com/eclipse-che/che-server/actions/workflows/try-in-web-ide.yaml)
Used as a check for pull requests that are submitted to this project.
Downstream builds can be found at the link below, which is _internal to Red Hat_. Stable builds can be found by replacing the 3.x with a specific version like 3.2.
- [server_3.x](https://main-jenkins-csb-crwqe.apps.ocp-c1.prod.psi.redhat.com/job/DS_CI/job/server_3.x/)
# License
- [Eclipse Public License 2.0](LICENSE)
@ -33,6 +76,6 @@ Other modules are deprecated and will be removed in the future.
The Eclipse Che community is globally reachable through public chat rooms, mailing list and weekly calls.
See the Eclipse Che Documentation about [how you can join our community](https://www.eclipse.org/che/docs/stable/overview/introduction-to-eclipse-che/#_joining_the_community).
## Builds
## Report issues
* [![release latest stable](https://github.com/eclipse-che/che-server/actions/workflows/release.yml/badge.svg)](https://github.com/eclipse-che/che-server/actions/workflows/release.yml)
Issues are tracked on the main Eclipse Che Repository: https://github.com/eclipse/che/issues

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (c) 2012-2024 Red Hat, Inc.
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/
@ -17,7 +17,7 @@
<parent>
<artifactId>che-assembly-parent</artifactId>
<groupId>org.eclipse.che</groupId>
<version>7.86.0-SNAPSHOT</version>
<version>7.73.0</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-2024 Red Hat, Inc.
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/
@ -17,7 +17,7 @@
<parent>
<artifactId>che-assembly-parent</artifactId>
<groupId>org.eclipse.che</groupId>
<version>7.86.0-SNAPSHOT</version>
<version>7.73.0</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-2024 Red Hat, Inc.
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/
@ -17,7 +17,7 @@
<parent>
<artifactId>che-assembly-parent</artifactId>
<groupId>org.eclipse.che</groupId>
<version>7.86.0-SNAPSHOT</version>
<version>7.73.0</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-2024 Red Hat, Inc.
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/
@ -17,7 +17,7 @@
<parent>
<artifactId>che-assembly-parent</artifactId>
<groupId>org.eclipse.che</groupId>
<version>7.86.0-SNAPSHOT</version>
<version>7.73.0</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-2024 Red Hat, Inc.
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/
@ -17,7 +17,7 @@
<parent>
<artifactId>che-assembly-parent</artifactId>
<groupId>org.eclipse.che</groupId>
<version>7.86.0-SNAPSHOT</version>
<version>7.73.0</version>
</parent>
<artifactId>assembly-wsmaster-war</artifactId>
<packaging>war</packaging>
@ -91,6 +91,10 @@
<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>
@ -103,10 +107,6 @@
<groupId>org.eclipse.che.core</groupId>
<artifactId>che-core-api-auth-bitbucket</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.che.core</groupId>
<artifactId>che-core-api-auth-github</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.che.core</groupId>
<artifactId>che-core-api-auth-gitlab</artifactId>
@ -155,6 +155,10 @@
<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>
@ -191,6 +195,18 @@
<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>
@ -335,6 +351,10 @@
<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-2024 Red Hat, Inc.
* 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/
@ -26,6 +26,7 @@ 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;
@ -35,7 +36,6 @@ import org.eclipse.che.api.factory.server.FactoryAcceptValidator;
import org.eclipse.che.api.factory.server.FactoryCreateValidator;
import org.eclipse.che.api.factory.server.FactoryEditValidator;
import org.eclipse.che.api.factory.server.FactoryParametersResolver;
import org.eclipse.che.api.factory.server.RawDevfileUrlFactoryParameterResolver;
import org.eclipse.che.api.factory.server.ScmFileResolver;
import org.eclipse.che.api.factory.server.ScmService;
import org.eclipse.che.api.factory.server.azure.devops.AzureDevOpsFactoryParametersResolver;
@ -47,11 +47,11 @@ import org.eclipse.che.api.factory.server.bitbucket.BitbucketServerScmFileResolv
import org.eclipse.che.api.factory.server.git.ssh.GitSshFactoryParametersResolver;
import org.eclipse.che.api.factory.server.git.ssh.GitSshScmFileResolver;
import org.eclipse.che.api.factory.server.github.GithubFactoryParametersResolver;
import org.eclipse.che.api.factory.server.github.GithubFactoryParametersResolverSecond;
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.factory.server.scm.OAuthTokenFetcher;
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;
@ -84,10 +84,13 @@ 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;
@ -101,6 +104,7 @@ import org.eclipse.che.multiuser.permission.user.UserServicePermissionsFilter;
import org.eclipse.che.security.PBKDF2PasswordEncryptor;
import org.eclipse.che.security.PasswordEncryptor;
import org.eclipse.che.security.oauth.EmbeddedOAuthAPI;
import org.eclipse.che.security.oauth.GitLabModule;
import org.eclipse.che.security.oauth.OAuthAPI;
import org.eclipse.che.security.oauth.OpenShiftOAuthModule;
import org.eclipse.che.workspace.infrastructure.kubernetes.KubernetesClientConfigFactory;
@ -122,6 +126,7 @@ 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
@ -137,10 +142,18 @@ 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);
@ -156,9 +169,6 @@ public class WsMasterModule extends AbstractModule {
Multibinder<FactoryParametersResolver> factoryParametersResolverMultibinder =
Multibinder.newSetBinder(binder(), FactoryParametersResolver.class);
factoryParametersResolverMultibinder.addBinding().to(GithubFactoryParametersResolver.class);
factoryParametersResolverMultibinder
.addBinding()
.to(GithubFactoryParametersResolverSecond.class);
factoryParametersResolverMultibinder
.addBinding()
.to(BitbucketServerAuthorizingFactoryParametersResolver.class);
@ -167,15 +177,11 @@ public class WsMasterModule extends AbstractModule {
factoryParametersResolverMultibinder
.addBinding()
.to(AzureDevOpsFactoryParametersResolver.class);
factoryParametersResolverMultibinder
.addBinding()
.to(RawDevfileUrlFactoryParameterResolver.class);
factoryParametersResolverMultibinder.addBinding().to(GitSshFactoryParametersResolver.class);
Multibinder<ScmFileResolver> scmFileResolverResolverMultibinder =
Multibinder.newSetBinder(binder(), ScmFileResolver.class);
scmFileResolverResolverMultibinder.addBinding().to(GithubScmFileResolver.class);
scmFileResolverResolverMultibinder.addBinding().to(GithubScmFileResolverSecond.class);
scmFileResolverResolverMultibinder.addBinding().to(BitbucketScmFileResolver.class);
scmFileResolverResolverMultibinder.addBinding().to(GitlabScmFileResolver.class);
scmFileResolverResolverMultibinder.addBinding().to(BitbucketServerScmFileResolver.class);
@ -199,7 +205,9 @@ 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));
@ -266,6 +274,10 @@ 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");
@ -281,9 +293,8 @@ public class WsMasterModule extends AbstractModule {
install(new FactoryModuleBuilder().build(PassThroughProxyProvisionerFactory.class));
installDefaultSecureServerExposer(infrastructure);
install(new org.eclipse.che.security.BitbucketModule());
install(new org.eclipse.che.security.oauth.GitLabModule());
install(new GitLabModule());
install(new org.eclipse.che.security.oauth.AzureDevOpsModule());
install(new org.eclipse.che.security.oauth.GithubModule());
configureMultiUserMode(persistenceProperties, infrastructure);
@ -308,6 +319,7 @@ 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());
@ -348,6 +360,9 @@ 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());
@ -394,8 +409,10 @@ public class WsMasterModule extends AbstractModule {
bind(TokenValidator.class).to(NotImplementedTokenValidator.class);
bind(ProfileDao.class).to(JpaProfileDao.class);
bind(OAuthAPI.class).to(EmbeddedOAuthAPI.class).asEagerSingleton();
bind(OAuthTokenFetcher.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-2024 Red Hat, Inc.
# 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/
@ -91,6 +91,10 @@ 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.
@ -141,42 +145,22 @@ che.oauth.azure.devops.redirecturis=https://${CHE_HOST}/api/oauth/callback
# Location of the file with GitHub client id.
che.oauth2.github.clientid_filepath=NULL
# Configuration of the GitHub OAuth2 client. Used to obtain personal access tokens.
# Location of the file with GitHub client id (The second GitHub instance).
che.oauth2.github.clientid_filepath_2=NULL
# Location of the file with GitHub client secret.
che.oauth2.github.clientsecret_filepath=NULL
# Location of the file with GitHub client secret (The second GitHub instance).
che.oauth2.github.clientsecret_filepath_2=NULL
# GitHub OAuth authorization URI.
che.oauth.github.authuri= https://github.com/login/oauth/authorize
# GitHub OAuth authorization URI (The second GitHub instance).
che.oauth.github.authuri_2= https://github.com/login/oauth/authorize
# GitHub OAuth token URI.
che.oauth.github.tokenuri= https://github.com/login/oauth/access_token
# GitHub OAuth token URI (The second GitHub instance).
che.oauth.github.tokenuri_2= https://github.com/login/oauth/access_token
# GitHub server address.
# Prerequisite: OAuth 2 integration is configured on the GitHub server.
che.integration.github.oauth_endpoint=NULL
# GitHub server address.
# Prerequisite: OAuth 2 integration is configured on the GitHub server (The second GitHub instance).
che.integration.github.oauth_endpoint_2=NULL
# GitHub server disable subdomain isolation flag.
che.integration.github.disable_subdomain_isolation=false
# GitHub server disable subdomain isolation flag (The second GitHub instance).
che.integration.github.disable_subdomain_isolation_2=false
# GitHub OAuth redirect URIs.
# Separate multiple values with comma, for example: URI,URI,URI.
che.oauth.github.redirecturis= http://localhost:${CHE_PORT}/api/oauth/callback
@ -610,7 +594,7 @@ che.factory.default_devfile_filenames=devfile.yaml,.devfile.yaml
### Devfile defaults
# Editor used for factories that are created from a remote Git repository
# which doesn't contain any {prod-short}-specific workspace descriptor.
che.factory.default_editor=eclipse/che-theia/next
che.factory.default_editor=eclipse/che-theia/latest
# File size limit for the URL fetcher which fetches files from the SCM repository.
che.factory.scm_file_fetcher_limit_bytes=102400
@ -622,7 +606,7 @@ che.factory.devfile2_files_resolution_list=.che/che-editor.yaml,.che/che-theia-p
# Default editor that should be provisioned into Devfile if there is no specified editor.
# The format is `editorPublisher/editorName/editorVersion` value.
# A `NULL` or absence of value means that default editor should not be provisioned.
che.workspace.devfile.default_editor=eclipse/che-theia/next
che.workspace.devfile.default_editor=eclipse/che-theia/latest
# Default plug-ins which should be provisioned for the default editor.
# All plug-ins from this list that aren't explicitly mentioned in the user-defined devfile
@ -659,16 +643,3 @@ che.oauth2.gitlab.clientid_filepath=NULL
# Location of the file with GitLab client secret.
che.oauth2.gitlab.clientsecret_filepath=NULL
### Advanced authorization
# Comma separated list of users allowed to access Che.
che.infra.kubernetes.advanced_authorization.allow_users=NULL
# Comma separated list of groups of users allowed to access Che.
che.infra.kubernetes.advanced_authorization.allow_groups=NULL
# Comma separated list of users denied to access Che.
che.infra.kubernetes.advanced_authorization.deny_users=NULL
# Comma separated list of groups of users denied to access Che.
che.infra.kubernetes.advanced_authorization.deny_groups=NULL

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012-2024 Red Hat, Inc.
* 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/
@ -37,7 +37,6 @@ 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 {
@ -126,7 +125,6 @@ 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-2024 Red Hat, Inc.
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/
@ -17,7 +17,7 @@
<parent>
<artifactId>che-server</artifactId>
<groupId>org.eclipse.che</groupId>
<version>7.86.0-SNAPSHOT</version>
<version>7.73.0</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>che-assembly-parent</artifactId>

View File

@ -1,40 +0,0 @@
# Copyright (c) 2018-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
#
# https://access.redhat.com/containers/?tab=tags#/registry.access.redhat.com/ubi8-minimal
FROM ubi8-minimal:8.9-1161
USER root
ENV CHE_HOME=/home/user/devspaces
ENV JAVA_HOME=/usr/lib/jvm/jre
RUN microdnf install java-11-openjdk-headless tar gzip shadow-utils findutils && \
microdnf update -y && \
microdnf -y clean all && rm -rf /var/cache/yum && echo "Installed Packages" && rpm -qa | sort -V && echo "End Of Installed Packages" && \
adduser -G root user && mkdir -p /home/user/devspaces
COPY entrypoint.sh /entrypoint.sh
ENTRYPOINT ["/entrypoint.sh"]
# see fetch-artifacts-pnc.yaml
COPY artifacts/assembly-main.tar.gz /tmp/assembly-main.tar.gz
RUN tar xzf /tmp/assembly-main.tar.gz --strip-components=1 -C /home/user/devspaces; rm -f /tmp/assembly-main.tar.gz
# this should fail if the startup script is not found in correct path /home/user/devspaces/tomcat/bin/catalina.sh
RUN mkdir /logs /data && \
chmod 0777 /logs /data && \
chgrp -R 0 /home/user /logs /data && \
chown -R user /home/user && \
chmod -R g+rwX /home/user && \
find /home/user -type d -exec chmod 777 {} \; && \
java -version && echo -n "Server startup script in: " && \
find /home/user/devspaces -name catalina.sh | grep -z /home/user/devspaces/tomcat/bin/catalina.sh
USER user
# append Brew metadata here

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (c) 2012-2024 Red Hat, Inc.
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/
@ -17,7 +17,7 @@
<parent>
<artifactId>che-core-parent</artifactId>
<groupId>org.eclipse.che.core</groupId>
<version>7.86.0-SNAPSHOT</version>
<version>7.73.0</version>
</parent>
<artifactId>che-core-api-core</artifactId>
<packaging>jar</packaging>

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012-2023 Red Hat, Inc.
* 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/
@ -11,10 +11,7 @@
*/
package org.eclipse.che.api.core.rest;
import static com.google.common.base.Strings.isNullOrEmpty;
import static java.lang.String.format;
import static java.util.Arrays.stream;
import static java.util.stream.Collectors.toList;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;
@ -22,7 +19,6 @@ import jakarta.ws.rs.ext.ExceptionMapper;
import jakarta.ws.rs.ext.Provider;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.TimeZone;
import javax.inject.Singleton;
import org.eclipse.che.api.core.rest.shared.dto.ServiceError;
@ -46,18 +42,11 @@ public class RuntimeExceptionMapper implements ExceptionMapper<RuntimeException>
final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
final String utcTime = dateFormat.format(new Date());
String message = exception.getMessage();
final String errorMessage =
isNullOrEmpty(message)
? format("Internal Server Error occurred, error time: %s", utcTime)
: message;
final String errorMessage = format("Internal Server Error occurred, error time: %s", utcTime);
LOG.error(errorMessage, exception);
List<String> trace =
stream(exception.getStackTrace()).map(StackTraceElement::toString).collect(toList());
ServiceError serviceError =
DtoFactory.newDto(ServiceError.class).withMessage(errorMessage).withTrace(trace);
ServiceError serviceError = DtoFactory.newDto(ServiceError.class).withMessage(errorMessage);
return Response.serverError()
.entity(DtoFactory.getInstance().toJson(serviceError))
.type(MediaType.APPLICATION_JSON)

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012-2023 Red Hat, Inc.
* 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/
@ -11,7 +11,6 @@
*/
package org.eclipse.che.api.core.rest.shared.dto;
import java.util.List;
import org.eclipse.che.dto.shared.DTO;
/**
@ -31,12 +30,8 @@ public interface ServiceError {
*/
String getMessage();
List<String> getTrace();
ServiceError withMessage(String message);
ServiceError withTrace(List<String> trace);
/**
* Set error message.
*

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (c) 2012-2024 Red Hat, Inc.
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/
@ -17,7 +17,7 @@
<parent>
<artifactId>che-core-parent</artifactId>
<groupId>org.eclipse.che.core</groupId>
<version>7.86.0-SNAPSHOT</version>
<version>7.73.0</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-2024 Red Hat, Inc.
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/
@ -17,7 +17,7 @@
<parent>
<artifactId>che-core-parent</artifactId>
<groupId>org.eclipse.che.core</groupId>
<version>7.86.0-SNAPSHOT</version>
<version>7.73.0</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-2024 Red Hat, Inc.
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/
@ -17,7 +17,7 @@
<parent>
<artifactId>che-core-parent</artifactId>
<groupId>org.eclipse.che.core</groupId>
<version>7.86.0-SNAPSHOT</version>
<version>7.73.0</version>
</parent>
<artifactId>che-core-api-model</artifactId>
<packaging>jar</packaging>

View File

@ -0,0 +1,47 @@
<?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.73.0</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

@ -0,0 +1,40 @@
/*
* 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

@ -0,0 +1,47 @@
/*
* 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

@ -0,0 +1,39 @@
<?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.73.0</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

@ -0,0 +1,40 @@
/*
* 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

@ -0,0 +1,43 @@
<?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.73.0</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

@ -0,0 +1,51 @@
/*
* 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

@ -0,0 +1,41 @@
/*
* 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;
}
}

113
core/che-core-db/pom.xml Normal file
View File

@ -0,0 +1,113 @@
<?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.73.0</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

@ -0,0 +1,43 @@
/*
* 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

@ -0,0 +1,89 @@
/*
* 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

@ -0,0 +1,84 @@
/*
* 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

@ -0,0 +1,79 @@
/*
* 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

@ -0,0 +1,41 @@
/*
* 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

@ -0,0 +1,106 @@
/*
* 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

@ -0,0 +1,38 @@
/*
* 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

@ -0,0 +1,45 @@
/*
* 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

@ -0,0 +1,60 @@
/*
* 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

@ -0,0 +1,38 @@
/*
* 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

@ -0,0 +1,36 @@
/*
* 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

@ -0,0 +1,39 @@
/*
* 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

@ -0,0 +1,34 @@
/*
* 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

@ -0,0 +1,27 @@
/*
* 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

@ -0,0 +1,28 @@
/*
* 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

@ -0,0 +1,27 @@
/*
* 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

@ -0,0 +1,69 @@
/*
* 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

@ -0,0 +1,40 @@
/*
* 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

@ -0,0 +1,28 @@
/*
* 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

@ -0,0 +1,31 @@
/*
* 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

@ -0,0 +1,210 @@
/*
* 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

@ -0,0 +1,122 @@
/*
* 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

@ -0,0 +1,37 @@
/*
* 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

@ -0,0 +1,57 @@
/*
* 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

@ -0,0 +1,84 @@
/*
* 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

@ -0,0 +1,55 @@
/*
* 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

@ -0,0 +1,84 @@
/*
* 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

@ -0,0 +1,123 @@
/*
* 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 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

@ -0,0 +1,353 @@
/*
* 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

@ -0,0 +1,162 @@
/*
* 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

@ -0,0 +1,67 @@
/*
* 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

@ -0,0 +1,88 @@
/*
* 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

@ -0,0 +1,35 @@
<?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

@ -0,0 +1,18 @@
--
-- 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

@ -0,0 +1,15 @@
--
-- 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

@ -0,0 +1,12 @@
--
-- 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

@ -0,0 +1,12 @@
--
-- 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-2024 Red Hat, Inc.
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/
@ -17,7 +17,7 @@
<parent>
<artifactId>che-core-parent</artifactId>
<groupId>org.eclipse.che.core</groupId>
<version>7.86.0-SNAPSHOT</version>
<version>7.73.0</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-2024 Red Hat, Inc.
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/
@ -17,7 +17,7 @@
<parent>
<artifactId>che-core-parent</artifactId>
<groupId>org.eclipse.che.core</groupId>
<version>7.86.0-SNAPSHOT</version>
<version>7.73.0</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-2024 Red Hat, Inc.
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/
@ -17,7 +17,7 @@
<parent>
<artifactId>che-core-parent</artifactId>
<groupId>org.eclipse.che.core</groupId>
<version>7.86.0-SNAPSHOT</version>
<version>7.73.0</version>
</parent>
<artifactId>che-core-tracing-core</artifactId>
<name>Che Core :: Commons :: Tracing :: Core</name>

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