Merge branch 'main' into dependabot/maven/org.apache.maven.plugins-maven-antrun-plugin-3.1.0
commit
2acd86d688
|
|
@ -0,0 +1,40 @@
|
|||
#!/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
|
||||
|
||||
# Dockerfile to bootstrap build and test in openshift-ci
|
||||
FROM registry.access.redhat.com/ubi9/nodejs-18:1
|
||||
# hadolint ignore=DL3002
|
||||
USER 0
|
||||
|
||||
# Install yq, kubectl, chectl cli used by olm/olm.sh script.
|
||||
# hadolint ignore=DL3041
|
||||
RUN dnf install -y -q --allowerasing --nobest nodejs-devel nodejs-libs psmisc python3-pip jq golang httpd-tools \
|
||||
# already installed or installed as deps:
|
||||
openssl openssl-devel ca-certificates make cmake cpp gcc gcc-c++ zlib zlib-devel brotli brotli-devel python3 nodejs-packaging && \
|
||||
dnf update -y && dnf clean all && \
|
||||
npm install -g yarn@1.22 npm@9 && \
|
||||
echo -n "node version: "; node -v; \
|
||||
echo -n "npm version: "; npm -v; \
|
||||
echo -n "yarn version: "; yarn -v; \
|
||||
go version; \
|
||||
pip3 install --upgrade pip setuptools yq && \
|
||||
|
||||
# Install kubectl, chectl cli used by olm/olm.sh script.
|
||||
curl -LO https://storage.googleapis.com/kubernetes-release/release/$(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt)/bin/linux/amd64/kubectl && \
|
||||
chmod +x ./kubectl && \
|
||||
mv ./kubectl /usr/local/bin && \
|
||||
bash <(curl -sL https://www.eclipse.org/che/chectl/) --channel=next && \
|
||||
curl https://mirror.openshift.com/pub/openshift-v4/clients/ocp/latest-4.12/openshift-client-linux.tar.gz | tar xvzf - -C /usr/local/bin/ oc && \
|
||||
chmod ug+x /usr/local/bin/oc
|
||||
|
||||
SHELL ["/bin/bash", "-c"]
|
||||
|
||||
|
|
@ -0,0 +1,319 @@
|
|||
#!/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
|
||||
#
|
||||
|
||||
set -e
|
||||
# only exit with zero if all commands of the pipeline exit successfully
|
||||
set -o pipefail
|
||||
|
||||
PR_IMAGE_TAG="pr-${PULL_NUMBER}"
|
||||
|
||||
export CHE_NAMESPACE=${CHE_NAMESPACE:-"eclipse-che"}
|
||||
export CHE_SERVER_IMAGE=${CHE_SERVER_IMAGE:-"quay.io/eclipse/che-server:${PR_IMAGE_TAG}"}
|
||||
export ARTIFACTS_DIR=${ARTIFACT_DIR:-"/tmp/artifacts"}
|
||||
export CHE_FORWARDED_PORT="8081"
|
||||
export OCP_ADMIN_USER_NAME=${OCP_ADMIN_USER_NAME:-"admin"}
|
||||
export OCP_NON_ADMIN_USER_NAME=${OCP_NON_ADMIN_USER_NAME:-"user"}
|
||||
export OCP_LOGIN_PASSWORD=${OCP_LOGIN_PASSWORD:-"passw"}
|
||||
export ADMIN_CHE_NAMESPACE=${OCP_ADMIN_USER_NAME}"-che"
|
||||
export USER_CHE_NAMESPACE=${OCP_NON_ADMIN_USER_NAME}"-che"
|
||||
export GIT_PROVIDER_USERNAME=${GIT_PROVIDER_USERNAME:-"chepullreq1"}
|
||||
export PUBLIC_REPO_WORKSPACE_NAME=${PUBLIC_REPO_WORKSPACE_NAME:-"public-repo-wksp-testname"}
|
||||
export PRIVATE_REPO_WORKSPACE_NAME=${PRIVATE_REPO_WORKSPACE_NAME:-"private-repo-wksp-testname"}
|
||||
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"}
|
||||
|
||||
provisionOpenShiftOAuthUser() {
|
||||
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 -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
|
||||
break
|
||||
fi
|
||||
sleep 10
|
||||
done
|
||||
}
|
||||
|
||||
createCustomResourcesFile() {
|
||||
cat > custom-resources.yaml <<-END
|
||||
apiVersion: org.eclipse.che/v2
|
||||
spec:
|
||||
devEnvironments:
|
||||
maxNumberOfRunningWorkspacesPerUser: 10000
|
||||
END
|
||||
|
||||
echo "Generated custom resources file"
|
||||
cat custom-resources.yaml
|
||||
}
|
||||
|
||||
deployChe() {
|
||||
chectl server:deploy --cheimage=$CHE_SERVER_IMAGE \
|
||||
--che-operator-cr-patch-yaml=custom-resources.yaml \
|
||||
--platform=openshift \
|
||||
--telemetry=off \
|
||||
--batch
|
||||
}
|
||||
|
||||
# this command starts port forwarding between the local machine and the che-host service in the OpenShift cluster.
|
||||
forwardPortToService() {
|
||||
oc port-forward service/che-host ${CHE_FORWARDED_PORT}:8080 -n ${CHE_NAMESPACE} &
|
||||
sleep 3s
|
||||
}
|
||||
|
||||
killProcessByPort() {
|
||||
fuser -k ${CHE_FORWARDED_PORT}/tcp
|
||||
}
|
||||
|
||||
requestFactoryResolverGitRepoUrl() {
|
||||
GIT_REPO_URL=$1
|
||||
CLUSTER_ACCESS_TOKEN=$(oc whoami -t)
|
||||
|
||||
curl -i -X 'POST' \
|
||||
http://localhost:${CHE_FORWARDED_PORT}/api/factory/resolver \
|
||||
-H 'accept: */*' \
|
||||
-H "Authorization: Bearer ${CLUSTER_ACCESS_TOKEN}" \
|
||||
-H 'Content-Type: application/json' \
|
||||
-d '{
|
||||
"url": "'${GIT_REPO_URL}'"
|
||||
}'
|
||||
}
|
||||
|
||||
# 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
|
||||
|
||||
echo "[INFO] Check factory resolver for private repository with NO PAT/OAuth setup"
|
||||
testFactoryResolverResponse $2 400
|
||||
}
|
||||
|
||||
# check that factory resolver returns correct value with PAT/OAuth setup
|
||||
testFactoryResolverWithPatOAuth() {
|
||||
echo "[INFO] Check factory resolver for public repository with PAT/OAuth setup"
|
||||
testFactoryResolverResponse $1 200
|
||||
|
||||
echo "[INFO] Check factory resolver for private repository with PAT/OAuth setup"
|
||||
testFactoryResolverResponse $2 200
|
||||
}
|
||||
|
||||
testFactoryResolverResponse() {
|
||||
URL=$1
|
||||
RESPONSE_CODE=$2
|
||||
|
||||
echo "[INFO] Check factory resolver"
|
||||
if [ "$(requestFactoryResolverGitRepoUrl ${URL} | grep "HTTP/1.1 ${RESPONSE_CODE}")" ]; then
|
||||
echo "[INFO] Factory resolver returned 'HTTP/1.1 ${RESPONSE_CODE}' status code. Expected client side response."
|
||||
else
|
||||
echo "[ERROR] Factory resolver returned wrong status code. Expected: HTTP/1.1 ${RESPONSE_CODE}."
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
requestProvisionNamespace() {
|
||||
CLUSTER_ACCESS_TOKEN=$(oc whoami -t)
|
||||
|
||||
curl -i -X 'POST' \
|
||||
http://localhost:${CHE_FORWARDED_PORT}/api/kubernetes/namespace/provision \
|
||||
-H 'accept: application/json' \
|
||||
-H "Authorization: Bearer ${CLUSTER_ACCESS_TOKEN}" \
|
||||
-d ''
|
||||
}
|
||||
|
||||
initUserNamespace() {
|
||||
OCP_USER_NAME=$1
|
||||
|
||||
echo "[INFO] Initialize user namespace"
|
||||
oc login -u=${OCP_USER_NAME} -p=${OCP_LOGIN_PASSWORD} --insecure-skip-tls-verify=false
|
||||
if [ "$(requestProvisionNamespace | grep "HTTP/1.1 200")" ]; then
|
||||
echo "[INFO] Request provision user namespace returned 'HTTP/1.1 200' status code."
|
||||
else
|
||||
echo "[ERROR] Request provision user namespace returned wrong status code. Expected: HTTP/1.1 200"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
setupPersonalAccessToken() {
|
||||
GIT_PROVIDER_TYPE=$1
|
||||
GIT_PROVIDER_URL=$2
|
||||
GIT_PROVIDER_PAT=$3
|
||||
|
||||
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)
|
||||
cat .ci/openshift-ci/pat-secret.yaml > pat-secret.yaml
|
||||
|
||||
# patch the pat-secret.yaml file
|
||||
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#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}
|
||||
}
|
||||
|
||||
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}
|
||||
}
|
||||
|
||||
runTestWorkspaceWithGitRepoUrl() {
|
||||
WS_NAME=$1
|
||||
PROJECT_NAME=$2
|
||||
GIT_REPO_URL=$3
|
||||
OCP_USER_NAMESPACE=$4
|
||||
|
||||
oc project ${OCP_USER_NAMESPACE}
|
||||
cat .ci/openshift-ci/devworkspace-test.yaml > devworkspace-test.yaml
|
||||
|
||||
# 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
|
||||
sed -i "s#git-repo-url#${GIT_REPO_URL}#g" devworkspace-test.yaml
|
||||
|
||||
cat devworkspace-test.yaml
|
||||
|
||||
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"
|
||||
}
|
||||
|
||||
testProjectIsCloned() {
|
||||
PROJECT_NAME=$1
|
||||
OCP_USER_NAMESPACE=$2
|
||||
|
||||
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."
|
||||
else
|
||||
echo "[INFO] Project file /projects/${PROJECT_NAME}/${YAML_FILE_NAME} is absent."
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
testGitCredentialsData() {
|
||||
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}"
|
||||
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."
|
||||
else
|
||||
echo "[ERROR] Git credentials file '/.git-credentials/credentials' does not exist or has incorrect content."
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
deleteTestWorkspace() {
|
||||
WS_NAME=$1
|
||||
OCP_USER_NAMESPACE=$2
|
||||
|
||||
oc delete dw ${WS_NAME} -n ${OCP_USER_NAMESPACE}
|
||||
}
|
||||
|
||||
# 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
|
||||
|
||||
[[ "${RESULT}" != "0" ]] && echo "[ERROR] Job failed." || echo "[INFO] Job completed successfully."
|
||||
exit $RESULT
|
||||
}
|
||||
|
||||
collectEclipseCheLogs() {
|
||||
mkdir -p ${ARTIFACTS_DIR}/che-logs
|
||||
|
||||
# Collect all Eclipse Che logs and cluster CR
|
||||
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"
|
||||
}
|
||||
|
||||
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" && 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() {
|
||||
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." && exit 1; }
|
||||
}
|
||||
|
||||
setupTestEnvironment() {
|
||||
OCP_USER_NAME=$1
|
||||
|
||||
provisionOpenShiftOAuthUser
|
||||
createCustomResourcesFile
|
||||
deployChe
|
||||
forwardPortToService
|
||||
initUserNamespace ${OCP_USER_NAME}
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
kind: DevWorkspace
|
||||
apiVersion: workspace.devfile.io/v1alpha2
|
||||
metadata:
|
||||
name: ws-name
|
||||
spec:
|
||||
started: true
|
||||
template:
|
||||
projects:
|
||||
- name: project-name
|
||||
git:
|
||||
remotes:
|
||||
origin: git-repo-url
|
||||
contributions:
|
||||
- name: che-code
|
||||
uri: https://eclipse-che.github.io/che-plugin-registry/main/v3/plugins/che-incubator/che-code/latest/devfile.yaml
|
||||
components:
|
||||
- name: che-code-runtime-description
|
||||
container:
|
||||
env:
|
||||
- name: CODE_HOST
|
||||
value: 0.0.0.0
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
apiVersion: config.openshift.io/v1
|
||||
kind: OAuth
|
||||
metadata:
|
||||
name: cluster
|
||||
spec:
|
||||
identityProviders:
|
||||
- name: htpasswd
|
||||
mappingMethod: claim
|
||||
type: HTPasswd
|
||||
htpasswd:
|
||||
fileData:
|
||||
name: htpass-secret
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
kind: Secret
|
||||
apiVersion: v1
|
||||
metadata:
|
||||
name: personal-access-token
|
||||
labels:
|
||||
app.kubernetes.io/component: scm-personal-access-token
|
||||
app.kubernetes.io/part-of: che.eclipse.org
|
||||
annotations:
|
||||
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: ''
|
||||
data:
|
||||
token: encoded-access-token
|
||||
type: Opaque
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
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
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
#!/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
|
||||
|
||||
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}
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
|
||||
#!/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
|
||||
|
||||
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}
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
#!/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
|
||||
|
||||
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}
|
||||
# due to the issue https://github.com/eclipse/che/issues/22469
|
||||
# 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}
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
#!/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
|
||||
|
||||
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}
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
#!/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
|
||||
|
||||
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}
|
||||
testFactoryResolverNoPatOAuth ${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}
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
|
||||
#!/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
|
||||
|
||||
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}
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
#!/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
|
||||
|
||||
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"}
|
||||
|
||||
# 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}
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
#!/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
|
||||
|
||||
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}
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
#!/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
|
||||
|
||||
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}
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
#!/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
|
||||
|
||||
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}
|
||||
testFactoryResolverNoPatOAuth ${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}
|
||||
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
|
||||
#!/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
|
||||
|
||||
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}
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
#!/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
|
||||
|
||||
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"}
|
||||
|
||||
# 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}
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
#!/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
|
||||
|
||||
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 )"
|
||||
source "${SCRIPT_DIR}"/common.sh
|
||||
|
||||
trap "catchFinish" EXIT SIGINT
|
||||
|
||||
setupTestEnvironment ${OCP_NON_ADMIN_USER_NAME}
|
||||
setupPersonalAccessToken ${GIT_PROVIDER_TYPE} ${GIT_PROVIDER_URL} ${GITHUB_PAT}
|
||||
requestProvisionNamespace
|
||||
testFactoryResolverWithPatOAuth ${PUBLIC_REPO_URL} ${PRIVATE_REPO_URL}
|
||||
|
||||
echo "[INFO] Check clone public repository with PAT setup"
|
||||
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}
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
#!/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
|
||||
|
||||
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}
|
||||
testFactoryResolverNoPatOAuth ${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}
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
|
||||
#!/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
|
||||
|
||||
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}
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
#!/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
|
||||
|
||||
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"}
|
||||
|
||||
# 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}
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
#!/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
|
||||
|
||||
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 )"
|
||||
source "${SCRIPT_DIR}"/common.sh
|
||||
|
||||
trap "catchFinish" EXIT SIGINT
|
||||
|
||||
setupTestEnvironment ${OCP_NON_ADMIN_USER_NAME}
|
||||
setupPersonalAccessToken ${GIT_PROVIDER_TYPE} ${GIT_PROVIDER_URL} ${GITLAB_PAT}
|
||||
requestProvisionNamespace
|
||||
testFactoryResolverWithPatOAuth ${PUBLIC_REPO_URL} ${PRIVATE_REPO_URL}
|
||||
|
||||
echo "[INFO] Check clone public repository with PAT setup"
|
||||
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}
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
# Global Owners
|
||||
* @l0rd @ibuziuk @vinokurig @nickboldt
|
||||
* @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
|
||||
|
|
@ -9,6 +9,3 @@ infrastructures/** @amisevsk
|
|||
|
||||
# deploy
|
||||
deploy/** @tolusha @dkwon17
|
||||
|
||||
# e2e tests
|
||||
tests/e2e/** @musienko-maxim
|
||||
|
|
|
|||
|
|
@ -11,6 +11,9 @@ name: build-pr-check
|
|||
|
||||
on: [push, pull_request]
|
||||
|
||||
env:
|
||||
PR_IMAGE_TAG: pr-${{ github.event.pull_request.number }}
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-22.04
|
||||
|
|
@ -26,5 +29,25 @@ jobs:
|
|||
distribution: 'temurin'
|
||||
java-version: '11'
|
||||
cache: 'maven'
|
||||
- name: Login to docker.io
|
||||
if: github.event_name == 'pull_request'
|
||||
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: 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 docker images
|
||||
if: github.event_name == 'pull_request'
|
||||
run: ./dockerfiles/build.sh --tag:${{ env.PR_IMAGE_TAG }}
|
||||
- name: Push docker images
|
||||
if: github.event_name == 'pull_request'
|
||||
run: docker push quay.io/eclipse/che-server:${{ env.PR_IMAGE_TAG }}
|
||||
|
|
|
|||
|
|
@ -45,8 +45,7 @@ jobs:
|
|||
- name: Build docker images
|
||||
id: build
|
||||
run: |
|
||||
SHORT_SHA1=$(git rev-parse --short HEAD)
|
||||
echo ::set-output name=short_sha1::${SHORT_SHA1}
|
||||
echo "short_sha1=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT
|
||||
./dockerfiles/build.sh --tag:next --sha-tag
|
||||
- name: Push docker images
|
||||
run: |
|
||||
|
|
|
|||
|
|
@ -145,17 +145,17 @@ jobs:
|
|||
prerelease: false
|
||||
tag: ${{ github.event.inputs.version }}
|
||||
token: ${{ secrets.CHE_BOT_GITHUB_TOKEN }}
|
||||
- name: Create failure MM message
|
||||
if: ${{ failure() }}
|
||||
run: |
|
||||
echo "{\"text\":\":no_entry_sign: Che Server ${{ github.event.inputs.version }} release has failed: https://github.com/eclipse-che/che-server/actions/workflows/release.yml\"}" > mattermost.json
|
||||
- name: Create success MM message
|
||||
run: |
|
||||
echo "{\"text\":\":white_check_mark: Che Server ${{ github.event.inputs.version }} has been released: https://quay.io/eclipse/che-server:${{ github.event.inputs.version }}\"}" > mattermost.json
|
||||
- name: Send MM message
|
||||
if: ${{ success() }} || ${{ failure() }}
|
||||
uses: mattermost/action-mattermost-notify@1.1.0
|
||||
env:
|
||||
MATTERMOST_WEBHOOK_URL: ${{ secrets.MATTERMOST_WEBHOOK_URL }}
|
||||
MATTERMOST_CHANNEL: eclipse-che-releases
|
||||
MATTERMOST_USERNAME: che-bot
|
||||
#- name: Create failure MM message
|
||||
#if: ${{ failure() }}
|
||||
#run: |
|
||||
#echo "{\"text\":\":no_entry_sign: Che Server ${{ github.event.inputs.version }} release has failed: https://github.com/eclipse-che/che-server/actions/workflows/release.yml\"}" > mattermost.json
|
||||
#- name: Create success MM message
|
||||
#run: |
|
||||
#echo "{\"text\":\":white_check_mark: Che Server ${{ github.event.inputs.version }} has been released: https://quay.io/eclipse/che-server:${{ github.event.inputs.version }}\"}" > mattermost.json
|
||||
#- name: Send MM message
|
||||
#if: ${{ success() }} || ${{ failure() }}
|
||||
#uses: mattermost/action-mattermost-notify@1.1.0
|
||||
#env:
|
||||
#MATTERMOST_WEBHOOK_URL: ${{ secrets.MATTERMOST_WEBHOOK_URL }}
|
||||
#MATTERMOST_CHANNEL: eclipse-che-releases
|
||||
#MATTERMOST_USERNAME: che-bot
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
.repository/
|
||||
|
||||
# Eclipse #
|
||||
###################
|
||||
|
||||
|
|
@ -11,10 +13,6 @@ test-output/
|
|||
maven-eclipse.xml
|
||||
.factorypath
|
||||
|
||||
# Theia #
|
||||
##################
|
||||
.theia/
|
||||
|
||||
# Idea #
|
||||
##################
|
||||
*.iml
|
||||
|
|
@ -48,8 +46,6 @@ maven-eclipse.xml
|
|||
*.war
|
||||
*.ear
|
||||
|
||||
|
||||
|
||||
# Logs and databases #
|
||||
######################
|
||||
*.log
|
||||
|
|
|
|||
|
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"recommendations": [
|
||||
"redhat.java",
|
||||
"redhat.fabric8-analytics",
|
||||
"vscjava.vscode-maven",
|
||||
"vscjava.vscode-java-debug",
|
||||
"vscjava.vscode-java-test"
|
||||
]
|
||||
}
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"java.jdt.ls.vmargs": "-XX:+UseParallelGC -XX:GCTimeRatio=4 -XX:AdaptiveSizePolicyWeight=90 -Dsun.zip.disableMemoryMapping=true -Xmx6G -Xms100m -Xlog:disable"
|
||||
}
|
||||
|
|
@ -0,0 +1,82 @@
|
|||
## 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:
|
||||
|
||||
- [](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.
|
||||
- [](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.
|
||||
- [](https://github.com/eclipse-che/che-server/actions/workflows/release-changelog.yml)
|
||||
Creates a GitHub release which will include a generated changelog.
|
||||
- [](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.
|
||||
- [](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.
|
||||
- [](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).
|
||||
- [](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
|
||||
69
README.md
69
README.md
|
|
@ -1,49 +1,28 @@
|
|||
# What is Che server
|
||||
Che Server is a core component of the [Eclipse Che](https://github.com/eclipse/che/). This component is responsible for creation and managing of Che workspaces, but will some day be replaced by the [Dev Workspace Operator](https://github.com/devfile/devworkspace-operator).
|
||||
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 a Apache Tomcat server in a container.
|
||||
- ['pom.xml'](https://github.com/eclipse-che/che-server/tree/main/pom.xml) The root Maven module, that lists all dependencies and structure.
|
||||
- ['assembly'](https://github.com/eclipse-che/che-server/tree/main/assembly) - module for final assemblies of Che web applications
|
||||
- ['dockerfiles'](https://github.com/eclipse-che/che-server/tree/main/dockerfiles) - directory contains image Dockerfile for Che Server, as well as additional images.
|
||||
- ['core'](https://github.com/eclipse-che/che-server/tree/main/core) - core and utility modules for Che.
|
||||
- ['wsmaster'](https://github.com/eclipse-che/che-server/tree/main/wsmaster) - primary modules of the Che Server API.
|
||||
- ['multiuser'](https://github.com/eclipse-che/che-server/tree/main/multiuser) - modules related to multiuser implementation of Che.
|
||||
- ['infrastructure'](https://github.com/eclipse-che/che-server/tree/main/infrastructure) - implementations for the underlying infrastructure, on which Che is running (Kubernetes, Openshift, etc.)
|
||||
- ['deploy'](https://github.com/eclipse-che/che-server/tree/main/deploy) - deployment files for Helm installation.
|
||||
- ['typescript-dto'](https://github.com/eclipse-che/che-server/tree/main/typescript-dto) module, that provides DTO objects for typescript projects that may depend on Che Server, such as Che Theia.
|
||||
Che Server is mostly a Java web application deployed on an Apache Tomcat server in a container. Che Server uses the following modules:
|
||||
### OAuth1 / OAuth2 API implementations
|
||||
- wsmaster/che-core-api-auth
|
||||
- wsmaster/che-core-api-azure-devops
|
||||
- wsmaster/che-core-api-bitbucket
|
||||
- wsmaster/che-core-api-github
|
||||
- wsmaster/che-core-api-gitlab
|
||||
### Factory flow implementations
|
||||
- wsmaster/che-core-api-factory-azure-devops
|
||||
- wsmaster/che-core-api-factory-bitbucket
|
||||
- wsmaster/che-core-api-factory-bitbucket-server
|
||||
- wsmaster/che-core-api-factory-github
|
||||
- wsmaster/che-core-api-factory-gitlab
|
||||
- wsmaster/che-core-api-factory-shared
|
||||
### Kubernetes namespace provisioning
|
||||
- infrastructures/kubernetes
|
||||
- infrastructure/openshift
|
||||
- infrastructures/infrastructure-factory
|
||||
|
||||
# Build requirements
|
||||
- Apache Maven 3.6.3 or Higher
|
||||
- JDK Version 11
|
||||
- Podman or Docker (required for running integration tests)
|
||||
|
||||
# Build and debug
|
||||
Run `mvn clean install` to build
|
||||
Activate a faster profile build by adding `-Pfast`
|
||||
To debug, run `mvn clean install -X` and connect your IDE to the debug port
|
||||
|
||||
# CI
|
||||
There are several [GitHub Actions](https://github.com/eclipse-che/che-server/actions) workflows implemented for this repository:
|
||||
|
||||
- [](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.
|
||||
- [](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.
|
||||
- [](https://github.com/eclipse-che/che-server/actions/workflows/release-changelog.yml)
|
||||
Creates a GitHub release which will include a generated changelog.
|
||||
- [](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.
|
||||
- [](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.
|
||||
- [](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).
|
||||
- [](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/)
|
||||
Other modules are deprecated and will be removed in the future.
|
||||
|
||||
# License
|
||||
|
||||
|
|
@ -52,8 +31,4 @@ Downstream builds can be found at the link below, which is _internal to Red Hat_
|
|||
# Join the community
|
||||
|
||||
The Eclipse Che community is globally reachable through public chat rooms, mailing list and weekly calls.
|
||||
See https://www.eclipse.org/che/docs/che-7/overview/introduction-to-eclipse-che/#_joining_the_community
|
||||
|
||||
## Report issues
|
||||
|
||||
Issues are tracked on the main Eclipse Che Repository: https://github.com/eclipse/che/issues
|
||||
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).
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
<parent>
|
||||
<artifactId>che-assembly-parent</artifactId>
|
||||
<groupId>org.eclipse.che</groupId>
|
||||
<version>7.64.0-SNAPSHOT</version>
|
||||
<version>7.76.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>assembly-che-tomcat</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
<parent>
|
||||
<artifactId>che-assembly-parent</artifactId>
|
||||
<groupId>org.eclipse.che</groupId>
|
||||
<version>7.64.0-SNAPSHOT</version>
|
||||
<version>7.76.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>assembly-main</artifactId>
|
||||
<packaging>pom</packaging>
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
<parent>
|
||||
<artifactId>che-assembly-parent</artifactId>
|
||||
<groupId>org.eclipse.che</groupId>
|
||||
<version>7.64.0-SNAPSHOT</version>
|
||||
<version>7.76.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>assembly-root-war</artifactId>
|
||||
<packaging>war</packaging>
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
<parent>
|
||||
<artifactId>che-assembly-parent</artifactId>
|
||||
<groupId>org.eclipse.che</groupId>
|
||||
<version>7.64.0-SNAPSHOT</version>
|
||||
<version>7.76.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>assembly-swagger-war</artifactId>
|
||||
<packaging>war</packaging>
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
<parent>
|
||||
<artifactId>che-assembly-parent</artifactId>
|
||||
<groupId>org.eclipse.che</groupId>
|
||||
<version>7.64.0-SNAPSHOT</version>
|
||||
<version>7.76.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>assembly-wsmaster-war</artifactId>
|
||||
<packaging>war</packaging>
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ 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;
|
||||
|
|
@ -176,6 +177,9 @@ public class WsMasterModule extends AbstractModule {
|
|||
factoryParametersResolverMultibinder
|
||||
.addBinding()
|
||||
.to(AzureDevOpsFactoryParametersResolver.class);
|
||||
factoryParametersResolverMultibinder
|
||||
.addBinding()
|
||||
.to(RawDevfileUrlFactoryParameterResolver.class);
|
||||
factoryParametersResolverMultibinder.addBinding().to(GitSshFactoryParametersResolver.class);
|
||||
|
||||
Multibinder<ScmFileResolver> scmFileResolverResolverMultibinder =
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
<parent>
|
||||
<artifactId>che-server</artifactId>
|
||||
<groupId>org.eclipse.che</groupId>
|
||||
<version>7.64.0-SNAPSHOT</version>
|
||||
<version>7.76.0-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
<artifactId>che-assembly-parent</artifactId>
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
<parent>
|
||||
<artifactId>che-core-parent</artifactId>
|
||||
<groupId>org.eclipse.che.core</groupId>
|
||||
<version>7.64.0-SNAPSHOT</version>
|
||||
<version>7.76.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>che-core-api-core</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2012-2021 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/
|
||||
|
|
@ -11,7 +11,10 @@
|
|||
*/
|
||||
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;
|
||||
|
|
@ -19,6 +22,7 @@ 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;
|
||||
|
|
@ -42,11 +46,18 @@ 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());
|
||||
final String errorMessage = format("Internal Server Error occurred, error time: %s", utcTime);
|
||||
String message = exception.getMessage();
|
||||
final String errorMessage =
|
||||
isNullOrEmpty(message)
|
||||
? format("Internal Server Error occurred, error time: %s", utcTime)
|
||||
: message;
|
||||
|
||||
LOG.error(errorMessage, exception);
|
||||
|
||||
ServiceError serviceError = DtoFactory.newDto(ServiceError.class).withMessage(errorMessage);
|
||||
List<String> trace =
|
||||
stream(exception.getStackTrace()).map(StackTraceElement::toString).collect(toList());
|
||||
ServiceError serviceError =
|
||||
DtoFactory.newDto(ServiceError.class).withMessage(errorMessage).withTrace(trace);
|
||||
return Response.serverError()
|
||||
.entity(DtoFactory.getInstance().toJson(serviceError))
|
||||
.type(MediaType.APPLICATION_JSON)
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2012-2018 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/
|
||||
|
|
@ -11,6 +11,7 @@
|
|||
*/
|
||||
package org.eclipse.che.api.core.rest.shared.dto;
|
||||
|
||||
import java.util.List;
|
||||
import org.eclipse.che.dto.shared.DTO;
|
||||
|
||||
/**
|
||||
|
|
@ -30,8 +31,12 @@ public interface ServiceError {
|
|||
*/
|
||||
String getMessage();
|
||||
|
||||
List<String> getTrace();
|
||||
|
||||
ServiceError withMessage(String message);
|
||||
|
||||
ServiceError withTrace(List<String> trace);
|
||||
|
||||
/**
|
||||
* Set error message.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
<parent>
|
||||
<artifactId>che-core-parent</artifactId>
|
||||
<groupId>org.eclipse.che.core</groupId>
|
||||
<version>7.64.0-SNAPSHOT</version>
|
||||
<version>7.76.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>che-core-api-dto-maven-plugin</artifactId>
|
||||
<packaging>maven-plugin</packaging>
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
<parent>
|
||||
<artifactId>che-core-parent</artifactId>
|
||||
<groupId>org.eclipse.che.core</groupId>
|
||||
<version>7.64.0-SNAPSHOT</version>
|
||||
<version>7.76.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>che-core-api-dto</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
<parent>
|
||||
<artifactId>che-core-parent</artifactId>
|
||||
<groupId>org.eclipse.che.core</groupId>
|
||||
<version>7.64.0-SNAPSHOT</version>
|
||||
<version>7.76.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>che-core-api-model</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
<parent>
|
||||
<artifactId>che-core-parent</artifactId>
|
||||
<groupId>org.eclipse.che.core</groupId>
|
||||
<version>7.64.0-SNAPSHOT</version>
|
||||
<version>7.76.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>che-core-db-vendor-h2</artifactId>
|
||||
<name>Che Core :: Commons :: DB :: Vendor H2</name>
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
<parent>
|
||||
<artifactId>che-core-parent</artifactId>
|
||||
<groupId>org.eclipse.che.core</groupId>
|
||||
<version>7.64.0-SNAPSHOT</version>
|
||||
<version>7.76.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>che-core-db-vendor-mysql</artifactId>
|
||||
<name>Che Core :: Commons :: DB :: Vendor MySQL</name>
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
<parent>
|
||||
<artifactId>che-core-parent</artifactId>
|
||||
<groupId>org.eclipse.che.core</groupId>
|
||||
<version>7.64.0-SNAPSHOT</version>
|
||||
<version>7.76.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>che-core-db-vendor-postgresql</artifactId>
|
||||
<name>Che Core :: Commons :: DB :: Vendor PostgreSQL</name>
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
<parent>
|
||||
<artifactId>che-core-parent</artifactId>
|
||||
<groupId>org.eclipse.che.core</groupId>
|
||||
<version>7.64.0-SNAPSHOT</version>
|
||||
<version>7.76.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>che-core-db</artifactId>
|
||||
<name>Che Core :: Commons :: DB</name>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2012-2021 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/
|
||||
|
|
@ -77,7 +77,7 @@ public class TracingDataSourceTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void shouldNotWrapDatasourceIfEnvSetToFalseØ() throws Exception {
|
||||
public void shouldNotWrapDatasourceIfEnvSetToFalse() throws Exception {
|
||||
setEnv(ImmutableMap.of("CHE_DB_TRACING_ENABLED", "false"));
|
||||
|
||||
DataSource actual = TracingDataSource.wrapWithTracingIfEnabled(dataSource);
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
<parent>
|
||||
<artifactId>che-core-parent</artifactId>
|
||||
<groupId>org.eclipse.che.core</groupId>
|
||||
<version>7.64.0-SNAPSHOT</version>
|
||||
<version>7.76.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>che-core-logback</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
<parent>
|
||||
<artifactId>che-core-parent</artifactId>
|
||||
<groupId>org.eclipse.che.core</groupId>
|
||||
<version>7.64.0-SNAPSHOT</version>
|
||||
<version>7.76.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>che-core-metrics-core</artifactId>
|
||||
<name>Che Core :: Commons :: Metrics :: Core</name>
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
<parent>
|
||||
<artifactId>che-core-parent</artifactId>
|
||||
<groupId>org.eclipse.che.core</groupId>
|
||||
<version>7.64.0-SNAPSHOT</version>
|
||||
<version>7.76.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>che-core-tracing-core</artifactId>
|
||||
<name>Che Core :: Commons :: Tracing :: Core</name>
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
<parent>
|
||||
<artifactId>che-core-parent</artifactId>
|
||||
<groupId>org.eclipse.che.core</groupId>
|
||||
<version>7.64.0-SNAPSHOT</version>
|
||||
<version>7.76.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>che-core-tracing-metrics</artifactId>
|
||||
<name>Che Core :: Commons :: Tracing :: Metrics</name>
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
<parent>
|
||||
<artifactId>che-core-parent</artifactId>
|
||||
<groupId>org.eclipse.che.core</groupId>
|
||||
<version>7.64.0-SNAPSHOT</version>
|
||||
<version>7.76.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>che-core-tracing-web</artifactId>
|
||||
<name>Che Core :: Commons :: Tracing :: Web</name>
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
<parent>
|
||||
<artifactId>che-core-parent</artifactId>
|
||||
<groupId>org.eclipse.che.core</groupId>
|
||||
<version>7.64.0-SNAPSHOT</version>
|
||||
<version>7.76.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>che-core-typescript-dto-maven-plugin</artifactId>
|
||||
<packaging>maven-plugin</packaging>
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
<parent>
|
||||
<artifactId>che-core-commons-parent</artifactId>
|
||||
<groupId>org.eclipse.che.core</groupId>
|
||||
<version>7.64.0-SNAPSHOT</version>
|
||||
<version>7.76.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>che-core-commons-annotations</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
<parent>
|
||||
<artifactId>che-core-commons-parent</artifactId>
|
||||
<groupId>org.eclipse.che.core</groupId>
|
||||
<version>7.64.0-SNAPSHOT</version>
|
||||
<version>7.76.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>che-core-commons-inject</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
<parent>
|
||||
<artifactId>che-core-commons-parent</artifactId>
|
||||
<groupId>org.eclipse.che.core</groupId>
|
||||
<version>7.64.0-SNAPSHOT</version>
|
||||
<version>7.76.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>che-core-commons-j2ee</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
<parent>
|
||||
<artifactId>che-core-commons-parent</artifactId>
|
||||
<groupId>org.eclipse.che.core</groupId>
|
||||
<version>7.64.0-SNAPSHOT</version>
|
||||
<version>7.76.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>che-core-commons-json</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
<parent>
|
||||
<artifactId>che-core-commons-parent</artifactId>
|
||||
<groupId>org.eclipse.che.core</groupId>
|
||||
<version>7.64.0-SNAPSHOT</version>
|
||||
<version>7.76.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>che-core-commons-lang</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
<parent>
|
||||
<artifactId>che-core-commons-parent</artifactId>
|
||||
<groupId>org.eclipse.che.core</groupId>
|
||||
<version>7.64.0-SNAPSHOT</version>
|
||||
<version>7.76.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>che-core-commons-observability</artifactId>
|
||||
<name>Che Core :: Commons :: Tracing and Monitoring wrapper</name>
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
<parent>
|
||||
<artifactId>che-core-commons-parent</artifactId>
|
||||
<groupId>org.eclipse.che.core</groupId>
|
||||
<version>7.64.0-SNAPSHOT</version>
|
||||
<version>7.76.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>che-core-commons-schedule</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
<parent>
|
||||
<artifactId>che-core-commons-parent</artifactId>
|
||||
<groupId>org.eclipse.che.core</groupId>
|
||||
<version>7.64.0-SNAPSHOT</version>
|
||||
<version>7.76.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>che-core-commons-test</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
<parent>
|
||||
<artifactId>che-core-commons-parent</artifactId>
|
||||
<groupId>org.eclipse.che.core</groupId>
|
||||
<version>7.64.0-SNAPSHOT</version>
|
||||
<version>7.76.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>che-core-commons-tracing</artifactId>
|
||||
<name>Che Core :: Commons :: Tracing</name>
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
<parent>
|
||||
<artifactId>che-core-parent</artifactId>
|
||||
<groupId>org.eclipse.che.core</groupId>
|
||||
<version>7.64.0-SNAPSHOT</version>
|
||||
<version>7.76.0-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
<artifactId>che-core-commons-parent</artifactId>
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
<parent>
|
||||
<artifactId>che-server</artifactId>
|
||||
<groupId>org.eclipse.che</groupId>
|
||||
<version>7.64.0-SNAPSHOT</version>
|
||||
<version>7.76.0-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
<groupId>org.eclipse.che.core</groupId>
|
||||
|
|
|
|||
40
devfile.yaml
40
devfile.yaml
|
|
@ -1,21 +1,25 @@
|
|||
apiVersion: 1.0.0
|
||||
schemaVersion: 2.2.0
|
||||
metadata:
|
||||
name: che-server-in-che
|
||||
generateName: che-server
|
||||
components:
|
||||
- type: dockerimage
|
||||
image: quay.io/eclipse/che-java11-maven:nightly
|
||||
alias: maven
|
||||
mountSources: true
|
||||
memoryLimit: 2Gi
|
||||
volumes:
|
||||
- name: m2
|
||||
containerPath: /home/user/.m2
|
||||
- type: chePlugin
|
||||
id: redhat/java11/latest
|
||||
- container:
|
||||
image: quay.io/devfile/universal-developer-image:ubi8-latest
|
||||
memoryLimit: 12Gi
|
||||
mountSources: true
|
||||
volumeMounts:
|
||||
- name: m2
|
||||
path: /home/user/.m2
|
||||
name: tools
|
||||
- name: m2
|
||||
volume: {}
|
||||
commands:
|
||||
- name: build without tests
|
||||
actions:
|
||||
- type: exec
|
||||
component: maven
|
||||
command: mvn clean install -DskipTests
|
||||
workdir: ${CHE_PROJECTS_ROOT}/che
|
||||
- id: build
|
||||
exec:
|
||||
label: "1. Build"
|
||||
component: tools
|
||||
workingDir: ${PROJECT_SOURCE}
|
||||
commandLine: |
|
||||
mvn clean install -DskipTests
|
||||
group:
|
||||
kind: build
|
||||
isDefault: true
|
||||
|
|
|
|||
|
|
@ -10,11 +10,11 @@
|
|||
#
|
||||
|
||||
# https://access.redhat.com/containers/?tab=tags#/registry.access.redhat.com/ubi8-minimal
|
||||
FROM registry.access.redhat.com/ubi8-minimal:8.7-1085
|
||||
FROM registry.access.redhat.com/ubi8-minimal:8.8-1072
|
||||
USER root
|
||||
ENV CHE_HOME=/home/user/eclipse-che
|
||||
ENV JAVA_HOME=/usr/lib/jvm/jre
|
||||
RUN microdnf install java-11-openjdk-headless tar gzip shadow-utils findutils && \
|
||||
RUN microdnf install java-17-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/eclipse-che
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -17,7 +17,7 @@
|
|||
<parent>
|
||||
<artifactId>che-infrastructures-parent</artifactId>
|
||||
<groupId>org.eclipse.che.infrastructure</groupId>
|
||||
<version>7.64.0-SNAPSHOT</version>
|
||||
<version>7.76.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>infrastructure-distributed</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
|
|
|
|||
|
|
@ -17,12 +17,16 @@
|
|||
<parent>
|
||||
<artifactId>che-infrastructures-parent</artifactId>
|
||||
<groupId>org.eclipse.che.infrastructure</groupId>
|
||||
<version>7.64.0-SNAPSHOT</version>
|
||||
<version>7.76.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>infrastructure-factory</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
<name>Infrastructure :: Factory components</name>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.google.code.gson</groupId>
|
||||
<artifactId>gson</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava</artifactId>
|
||||
|
|
@ -33,7 +37,7 @@
|
|||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.fabric8</groupId>
|
||||
<artifactId>kubernetes-client</artifactId>
|
||||
<artifactId>kubernetes-client-api</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.fabric8</groupId>
|
||||
|
|
@ -43,6 +47,14 @@
|
|||
<groupId>jakarta.inject</groupId>
|
||||
<artifactId>jakarta.inject-api</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>jakarta.ws.rs</groupId>
|
||||
<artifactId>jakarta.ws.rs-api</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.che.core</groupId>
|
||||
<artifactId>che-core-api-auth</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.che.core</groupId>
|
||||
<artifactId>che-core-api-core</artifactId>
|
||||
|
|
@ -55,6 +67,10 @@
|
|||
<groupId>org.eclipse.che.core</groupId>
|
||||
<artifactId>che-core-api-workspace</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.che.core</groupId>
|
||||
<artifactId>che-core-commons-annotations</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.che.core</groupId>
|
||||
<artifactId>che-core-commons-lang</artifactId>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2012-2021 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/
|
||||
|
|
@ -12,13 +12,16 @@
|
|||
package org.eclipse.che.api.factory.server.scm;
|
||||
|
||||
import com.google.inject.AbstractModule;
|
||||
import org.eclipse.che.api.factory.server.scm.kubernetes.KubernetesAuthorisationRequestManager;
|
||||
import org.eclipse.che.api.factory.server.scm.kubernetes.KubernetesGitCredentialManager;
|
||||
import org.eclipse.che.api.factory.server.scm.kubernetes.KubernetesPersonalAccessTokenManager;
|
||||
import org.eclipse.che.security.oauth.AuthorisationRequestManager;
|
||||
|
||||
public class KubernetesScmModule extends AbstractModule {
|
||||
@Override
|
||||
protected void configure() {
|
||||
bind(GitCredentialManager.class).to(KubernetesGitCredentialManager.class);
|
||||
bind(PersonalAccessTokenManager.class).to(KubernetesPersonalAccessTokenManager.class);
|
||||
bind(AuthorisationRequestManager.class).to(KubernetesAuthorisationRequestManager.class);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,145 @@
|
|||
/*
|
||||
* 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.api.factory.server.scm.kubernetes;
|
||||
|
||||
import static com.google.common.base.Strings.isNullOrEmpty;
|
||||
import static org.eclipse.che.commons.lang.UrlUtils.getParameter;
|
||||
import static org.eclipse.che.commons.lang.UrlUtils.getQueryParametersFromState;
|
||||
import static org.eclipse.che.commons.lang.UrlUtils.getRequestUrl;
|
||||
import static org.eclipse.che.commons.lang.UrlUtils.getState;
|
||||
import static org.eclipse.che.workspace.infrastructure.kubernetes.namespace.AbstractWorkspaceServiceAccount.PREFERENCES_CONFIGMAP_NAME;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import io.fabric8.kubernetes.api.model.ConfigMap;
|
||||
import io.fabric8.kubernetes.client.KubernetesClient;
|
||||
import jakarta.ws.rs.core.UriInfo;
|
||||
import java.net.URL;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
import org.eclipse.che.api.factory.server.scm.exception.ScmConfigurationPersistenceException;
|
||||
import org.eclipse.che.api.factory.server.scm.exception.UnsatisfiedScmPreconditionException;
|
||||
import org.eclipse.che.api.workspace.server.spi.InfrastructureException;
|
||||
import org.eclipse.che.security.oauth.AuthorisationRequestManager;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.CheServerKubernetesClientFactory;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.api.shared.KubernetesNamespaceMeta;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.namespace.KubernetesNamespaceFactory;
|
||||
|
||||
/** Store and retrieve rejected authorisation requests in the Kubernetes ConfigMap. */
|
||||
@Singleton
|
||||
public class KubernetesAuthorisationRequestManager implements AuthorisationRequestManager {
|
||||
private final KubernetesNamespaceFactory namespaceFactory;
|
||||
private final CheServerKubernetesClientFactory cheServerKubernetesClientFactory;
|
||||
private static final String SKIP_AUTHORISATION_MAP_KEY = "skip-authorisation";
|
||||
|
||||
@Inject
|
||||
public KubernetesAuthorisationRequestManager(
|
||||
KubernetesNamespaceFactory namespaceFactory,
|
||||
CheServerKubernetesClientFactory cheServerKubernetesClientFactory) {
|
||||
this.namespaceFactory = namespaceFactory;
|
||||
this.cheServerKubernetesClientFactory = cheServerKubernetesClientFactory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void store(String scmProviderName) {
|
||||
if (isStored(scmProviderName)) {
|
||||
return;
|
||||
}
|
||||
ConfigMap configMap = getConfigMap();
|
||||
HashSet<String> fromJson = getSkipAuthorisationValues();
|
||||
fromJson.add(scmProviderName);
|
||||
|
||||
configMap.setData(Map.of(SKIP_AUTHORISATION_MAP_KEY, fromJson.toString()));
|
||||
|
||||
patchConfigMap(configMap);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove(String scmProviderName) {
|
||||
if (!isStored(scmProviderName)) {
|
||||
return;
|
||||
}
|
||||
ConfigMap configMap = getConfigMap();
|
||||
HashSet<String> fromJson = getSkipAuthorisationValues();
|
||||
fromJson.remove(scmProviderName);
|
||||
|
||||
configMap.setData(Map.of(SKIP_AUTHORISATION_MAP_KEY, fromJson.toString()));
|
||||
|
||||
patchConfigMap(configMap);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isStored(String scmProviderName) {
|
||||
return getSkipAuthorisationValues().contains(scmProviderName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void callback(UriInfo uriInfo, List<String> errorValues) {
|
||||
URL requestUrl = getRequestUrl(uriInfo);
|
||||
Map<String, List<String>> params = getQueryParametersFromState(getState(requestUrl));
|
||||
errorValues = errorValues == null ? uriInfo.getQueryParameters().get("error") : errorValues;
|
||||
if (errorValues != null && errorValues.contains("access_denied")) {
|
||||
store(getParameter(params, "oauth_provider"));
|
||||
}
|
||||
}
|
||||
|
||||
private ConfigMap getConfigMap() {
|
||||
try (KubernetesClient kubernetesClient = cheServerKubernetesClientFactory.create()) {
|
||||
String namespace = getFirstNamespace();
|
||||
return kubernetesClient
|
||||
.configMaps()
|
||||
.inNamespace(namespace)
|
||||
.withName(PREFERENCES_CONFIGMAP_NAME)
|
||||
.get();
|
||||
} catch (UnsatisfiedScmPreconditionException
|
||||
| ScmConfigurationPersistenceException
|
||||
| InfrastructureException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private void patchConfigMap(ConfigMap configMap) {
|
||||
try (KubernetesClient kubernetesClient = cheServerKubernetesClientFactory.create()) {
|
||||
kubernetesClient
|
||||
.configMaps()
|
||||
.inNamespace(getFirstNamespace())
|
||||
.withName(PREFERENCES_CONFIGMAP_NAME)
|
||||
.patch(configMap);
|
||||
} catch (UnsatisfiedScmPreconditionException
|
||||
| ScmConfigurationPersistenceException
|
||||
| InfrastructureException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private HashSet<String> getSkipAuthorisationValues() {
|
||||
String data = getConfigMap().getData().get(SKIP_AUTHORISATION_MAP_KEY);
|
||||
return new Gson().fromJson(isNullOrEmpty(data) ? "[]" : data, HashSet.class);
|
||||
}
|
||||
|
||||
private String getFirstNamespace()
|
||||
throws UnsatisfiedScmPreconditionException, ScmConfigurationPersistenceException {
|
||||
try {
|
||||
return namespaceFactory.list().stream()
|
||||
.map(KubernetesNamespaceMeta::getName)
|
||||
.findFirst()
|
||||
.orElseThrow(
|
||||
() ->
|
||||
new UnsatisfiedScmPreconditionException(
|
||||
"No user namespace found. Cannot read SCM credentials."));
|
||||
} catch (InfrastructureException e) {
|
||||
throw new ScmConfigurationPersistenceException(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -11,6 +11,7 @@
|
|||
*/
|
||||
package org.eclipse.che.api.factory.server.scm.kubernetes;
|
||||
|
||||
import static com.google.common.base.Strings.isNullOrEmpty;
|
||||
import static java.lang.String.format;
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
import static org.eclipse.che.api.factory.server.scm.PersonalAccessTokenFetcher.OAUTH_2_PREFIX;
|
||||
|
|
@ -43,7 +44,7 @@ import org.eclipse.che.api.factory.server.scm.exception.UnsatisfiedScmPreconditi
|
|||
import org.eclipse.che.api.workspace.server.spi.InfrastructureException;
|
||||
import org.eclipse.che.commons.lang.NameGenerator;
|
||||
import org.eclipse.che.commons.lang.StringUtils;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.KubernetesClientFactory;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.CheServerKubernetesClientFactory;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.api.shared.KubernetesNamespaceMeta;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.namespace.KubernetesNamespaceFactory;
|
||||
|
||||
|
|
@ -86,13 +87,14 @@ public class KubernetesGitCredentialManager implements GitCredentialManager {
|
|||
ANNOTATION_DEV_WORKSPACE_MOUNT_PATH, CREDENTIALS_MOUNT_PATH);
|
||||
|
||||
private final KubernetesNamespaceFactory namespaceFactory;
|
||||
private final KubernetesClientFactory clientFactory;
|
||||
private final CheServerKubernetesClientFactory cheServerKubernetesClientFactory;
|
||||
|
||||
@Inject
|
||||
public KubernetesGitCredentialManager(
|
||||
KubernetesNamespaceFactory namespaceFactory, KubernetesClientFactory clientFactory) {
|
||||
KubernetesNamespaceFactory namespaceFactory,
|
||||
CheServerKubernetesClientFactory cheServerKubernetesClientFactory) {
|
||||
this.namespaceFactory = namespaceFactory;
|
||||
this.clientFactory = clientFactory;
|
||||
this.cheServerKubernetesClientFactory = cheServerKubernetesClientFactory;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -100,7 +102,7 @@ public class KubernetesGitCredentialManager implements GitCredentialManager {
|
|||
throws UnsatisfiedScmPreconditionException, ScmConfigurationPersistenceException {
|
||||
try {
|
||||
final String namespace = getFirstNamespace();
|
||||
final KubernetesClient client = clientFactory.create();
|
||||
final KubernetesClient client = cheServerKubernetesClientFactory.create();
|
||||
// to avoid duplicating secrets we try to reuse existing one by matching
|
||||
// hostname/username if possible, and update it. Otherwise, create new one.
|
||||
Optional<Secret> existing =
|
||||
|
|
@ -124,11 +126,7 @@ public class KubernetesGitCredentialManager implements GitCredentialManager {
|
|||
'/'))
|
||||
&& personalAccessToken
|
||||
.getCheUserId()
|
||||
.equals(s.getMetadata().getAnnotations().get(ANNOTATION_CHE_USERID))
|
||||
&& personalAccessToken
|
||||
.getScmUserName()
|
||||
.equals(
|
||||
s.getMetadata().getAnnotations().get(ANNOTATION_SCM_USERNAME)))
|
||||
.equals(s.getMetadata().getAnnotations().get(ANNOTATION_CHE_USERID)))
|
||||
.findFirst();
|
||||
|
||||
Secret secret =
|
||||
|
|
@ -136,7 +134,6 @@ public class KubernetesGitCredentialManager implements GitCredentialManager {
|
|||
() -> {
|
||||
Map<String, String> annotations = new HashMap<>(DEFAULT_SECRET_ANNOTATIONS);
|
||||
annotations.put(ANNOTATION_SCM_URL, personalAccessToken.getScmProviderUrl());
|
||||
annotations.put(ANNOTATION_SCM_USERNAME, personalAccessToken.getScmUserName());
|
||||
annotations.put(ANNOTATION_CHE_USERID, personalAccessToken.getCheUserId());
|
||||
ObjectMeta meta =
|
||||
new ObjectMetaBuilder()
|
||||
|
|
@ -155,9 +152,7 @@ public class KubernetesGitCredentialManager implements GitCredentialManager {
|
|||
format(
|
||||
"%s://%s:%s@%s%s",
|
||||
scmUrl.getProtocol(),
|
||||
personalAccessToken.getScmTokenName().startsWith(OAUTH_2_PREFIX)
|
||||
? "oauth2"
|
||||
: personalAccessToken.getScmUserName(),
|
||||
getUsernameSegment(personalAccessToken),
|
||||
URLEncoder.encode(personalAccessToken.getToken(), UTF_8),
|
||||
scmUrl.getHost(),
|
||||
scmUrl.getPort() != 80 && scmUrl.getPort() != -1
|
||||
|
|
@ -170,6 +165,21 @@ public class KubernetesGitCredentialManager implements GitCredentialManager {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns username URL segment for git credentials. For OAuth2 tokens it is "oauth2", for others
|
||||
* - {@param personalAccessToken#getScmUserName()} or just "username" string if the token has a
|
||||
* non-null {@param personalAccessToken#getScmOrganization()}. This is needed to support providers
|
||||
* that do not have username in their user object. Such providers have an additional organization
|
||||
* field.
|
||||
*/
|
||||
private String getUsernameSegment(PersonalAccessToken personalAccessToken) {
|
||||
return personalAccessToken.getScmTokenName().startsWith(OAUTH_2_PREFIX)
|
||||
? "oauth2"
|
||||
: isNullOrEmpty(personalAccessToken.getScmOrganization())
|
||||
? personalAccessToken.getScmUserName()
|
||||
: "username";
|
||||
}
|
||||
|
||||
/**
|
||||
* It is not guaranteed that this code will always return same namespace, but since credentials
|
||||
* are now added into manually pre-created user namespace, we can expect always the same result
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ import javax.inject.Singleton;
|
|||
import org.eclipse.che.api.factory.server.scm.GitCredentialManager;
|
||||
import org.eclipse.che.api.factory.server.scm.PersonalAccessToken;
|
||||
import org.eclipse.che.api.factory.server.scm.PersonalAccessTokenManager;
|
||||
import org.eclipse.che.api.factory.server.scm.PersonalAccessTokenParams;
|
||||
import org.eclipse.che.api.factory.server.scm.ScmPersonalAccessTokenFetcher;
|
||||
import org.eclipse.che.api.factory.server.scm.exception.ScmCommunicationException;
|
||||
import org.eclipse.che.api.factory.server.scm.exception.ScmConfigurationPersistenceException;
|
||||
|
|
@ -37,11 +38,12 @@ import org.eclipse.che.api.factory.server.scm.exception.ScmUnauthorizedException
|
|||
import org.eclipse.che.api.factory.server.scm.exception.UnknownScmProviderException;
|
||||
import org.eclipse.che.api.factory.server.scm.exception.UnsatisfiedScmPreconditionException;
|
||||
import org.eclipse.che.api.workspace.server.spi.InfrastructureException;
|
||||
import org.eclipse.che.commons.annotation.Nullable;
|
||||
import org.eclipse.che.commons.env.EnvironmentContext;
|
||||
import org.eclipse.che.commons.lang.NameGenerator;
|
||||
import org.eclipse.che.commons.lang.StringUtils;
|
||||
import org.eclipse.che.commons.subject.Subject;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.KubernetesClientFactory;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.CheServerKubernetesClientFactory;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.api.shared.KubernetesNamespaceMeta;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.namespace.KubernetesNamespaceFactory;
|
||||
|
||||
|
|
@ -58,8 +60,6 @@ public class KubernetesPersonalAccessTokenManager implements PersonalAccessToken
|
|||
public static final String NAME_PATTERN = "personal-access-token-";
|
||||
|
||||
public static final String ANNOTATION_CHE_USERID = "che.eclipse.org/che-userid";
|
||||
public static final String ANNOTATION_SCM_USERID = "che.eclipse.org/scm-userid";
|
||||
public static final String ANNOTATION_SCM_USERNAME = "che.eclipse.org/scm-username";
|
||||
public static final String ANNOTATION_SCM_ORGANIZATION = "che.eclipse.org/scm-organization";
|
||||
public static final String ANNOTATION_SCM_PERSONAL_ACCESS_TOKEN_ID =
|
||||
"che.eclipse.org/scm-personal-access-token-id";
|
||||
|
|
@ -69,18 +69,18 @@ public class KubernetesPersonalAccessTokenManager implements PersonalAccessToken
|
|||
public static final String TOKEN_DATA_FIELD = "token";
|
||||
|
||||
private final KubernetesNamespaceFactory namespaceFactory;
|
||||
private final KubernetesClientFactory clientFactory;
|
||||
private final CheServerKubernetesClientFactory cheServerKubernetesClientFactory;
|
||||
private final ScmPersonalAccessTokenFetcher scmPersonalAccessTokenFetcher;
|
||||
private final GitCredentialManager gitCredentialManager;
|
||||
|
||||
@Inject
|
||||
public KubernetesPersonalAccessTokenManager(
|
||||
KubernetesNamespaceFactory namespaceFactory,
|
||||
KubernetesClientFactory clientFactory,
|
||||
CheServerKubernetesClientFactory cheServerKubernetesClientFactory,
|
||||
ScmPersonalAccessTokenFetcher scmPersonalAccessTokenFetcher,
|
||||
GitCredentialManager gitCredentialManager) {
|
||||
this.namespaceFactory = namespaceFactory;
|
||||
this.clientFactory = clientFactory;
|
||||
this.cheServerKubernetesClientFactory = cheServerKubernetesClientFactory;
|
||||
this.scmPersonalAccessTokenFetcher = scmPersonalAccessTokenFetcher;
|
||||
this.gitCredentialManager = gitCredentialManager;
|
||||
}
|
||||
|
|
@ -96,8 +96,6 @@ public class KubernetesPersonalAccessTokenManager implements PersonalAccessToken
|
|||
.withAnnotations(
|
||||
new ImmutableMap.Builder<String, String>()
|
||||
.put(ANNOTATION_CHE_USERID, personalAccessToken.getCheUserId())
|
||||
.put(ANNOTATION_SCM_USERID, personalAccessToken.getScmUserId())
|
||||
.put(ANNOTATION_SCM_USERNAME, personalAccessToken.getScmUserName())
|
||||
.put(ANNOTATION_SCM_URL, personalAccessToken.getScmProviderUrl())
|
||||
.put(
|
||||
ANNOTATION_SCM_PERSONAL_ACCESS_TOKEN_ID,
|
||||
|
|
@ -120,7 +118,11 @@ public class KubernetesPersonalAccessTokenManager implements PersonalAccessToken
|
|||
personalAccessToken.getToken().getBytes(StandardCharsets.UTF_8))))
|
||||
.build();
|
||||
|
||||
clientFactory.create().secrets().inNamespace(namespace).createOrReplace(secret);
|
||||
cheServerKubernetesClientFactory
|
||||
.create()
|
||||
.secrets()
|
||||
.inNamespace(namespace)
|
||||
.createOrReplace(secret);
|
||||
} catch (KubernetesClientException | InfrastructureException e) {
|
||||
throw new ScmConfigurationPersistenceException(e.getMessage(), e);
|
||||
}
|
||||
|
|
@ -140,7 +142,36 @@ public class KubernetesPersonalAccessTokenManager implements PersonalAccessToken
|
|||
public Optional<PersonalAccessToken> get(Subject cheUser, String scmServerUrl)
|
||||
throws ScmConfigurationPersistenceException, ScmUnauthorizedException,
|
||||
ScmCommunicationException {
|
||||
return doGetPersonalAccessToken(cheUser, null, scmServerUrl);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PersonalAccessToken get(String scmServerUrl)
|
||||
throws ScmConfigurationPersistenceException, ScmUnauthorizedException,
|
||||
ScmCommunicationException, UnknownScmProviderException,
|
||||
UnsatisfiedScmPreconditionException {
|
||||
Subject subject = EnvironmentContext.getCurrent().getSubject();
|
||||
Optional<PersonalAccessToken> tokenOptional = get(subject, scmServerUrl);
|
||||
if (tokenOptional.isPresent()) {
|
||||
return tokenOptional.get();
|
||||
} else {
|
||||
// try to authenticate for the given URL
|
||||
return fetchAndSave(subject, scmServerUrl);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<PersonalAccessToken> get(
|
||||
Subject cheUser, String oAuthProviderName, @Nullable String scmServerUrl)
|
||||
throws ScmConfigurationPersistenceException, ScmUnauthorizedException,
|
||||
ScmCommunicationException {
|
||||
return doGetPersonalAccessToken(cheUser, oAuthProviderName, scmServerUrl);
|
||||
}
|
||||
|
||||
private Optional<PersonalAccessToken> doGetPersonalAccessToken(
|
||||
Subject cheUser, @Nullable String oAuthProviderName, @Nullable String scmServerUrl)
|
||||
throws ScmConfigurationPersistenceException, ScmUnauthorizedException,
|
||||
ScmCommunicationException {
|
||||
try {
|
||||
for (KubernetesNamespaceMeta namespaceMeta : namespaceFactory.list()) {
|
||||
List<Secret> secrets =
|
||||
|
|
@ -152,28 +183,41 @@ public class KubernetesPersonalAccessTokenManager implements PersonalAccessToken
|
|||
Map<String, String> annotations = secret.getMetadata().getAnnotations();
|
||||
String trimmedUrl = StringUtils.trimEnd(annotations.get(ANNOTATION_SCM_URL), '/');
|
||||
if (annotations.get(ANNOTATION_CHE_USERID).equals(cheUser.getUserId())
|
||||
&& trimmedUrl.equals(StringUtils.trimEnd(scmServerUrl, '/'))) {
|
||||
&& (oAuthProviderName == null
|
||||
|| oAuthProviderName.equals(
|
||||
annotations.get(ANNOTATION_SCM_PERSONAL_ACCESS_TOKEN_NAME)))
|
||||
&& (scmServerUrl == null
|
||||
|| trimmedUrl.equals(StringUtils.trimEnd(scmServerUrl, '/')))) {
|
||||
String token =
|
||||
new String(Base64.getDecoder().decode(secret.getData().get("token"))).trim();
|
||||
PersonalAccessToken personalAccessToken =
|
||||
new PersonalAccessToken(
|
||||
trimmedUrl,
|
||||
annotations.get(ANNOTATION_CHE_USERID),
|
||||
annotations.get(ANNOTATION_SCM_ORGANIZATION),
|
||||
annotations.get(ANNOTATION_SCM_USERNAME),
|
||||
annotations.get(ANNOTATION_SCM_USERID),
|
||||
annotations.get(ANNOTATION_SCM_PERSONAL_ACCESS_TOKEN_NAME),
|
||||
annotations.get(ANNOTATION_SCM_PERSONAL_ACCESS_TOKEN_ID),
|
||||
token);
|
||||
if (scmPersonalAccessTokenFetcher.isValid(personalAccessToken)) {
|
||||
String providerName = annotations.get(ANNOTATION_SCM_PERSONAL_ACCESS_TOKEN_NAME);
|
||||
String tokenId = annotations.get(ANNOTATION_SCM_PERSONAL_ACCESS_TOKEN_ID);
|
||||
String organization = annotations.get(ANNOTATION_SCM_ORGANIZATION);
|
||||
Optional<String> scmUsername =
|
||||
scmPersonalAccessTokenFetcher.getScmUsername(
|
||||
new PersonalAccessTokenParams(
|
||||
trimmedUrl, providerName, tokenId, token, organization));
|
||||
if (scmUsername.isPresent()) {
|
||||
PersonalAccessToken personalAccessToken =
|
||||
new PersonalAccessToken(
|
||||
trimmedUrl,
|
||||
annotations.get(ANNOTATION_CHE_USERID),
|
||||
organization,
|
||||
scmUsername.get(),
|
||||
providerName,
|
||||
tokenId,
|
||||
token);
|
||||
return Optional.of(personalAccessToken);
|
||||
} else {
|
||||
// Removing token that is no longer valid. If several tokens exist the next one could
|
||||
// be valid. If no valid token can be found, the caller should react in the same way
|
||||
// as it reacts if no token exists. Usually, that means that process of new token
|
||||
// retrieval would be initiated.
|
||||
clientFactory.create().secrets().inNamespace(namespaceMeta.getName()).delete(secret);
|
||||
}
|
||||
// Removing token that is no longer valid. If several tokens exist the next one could
|
||||
// be valid. If no valid token can be found, the caller should react in the same way
|
||||
// as it reacts if no token exists. Usually, that means that process of new token
|
||||
// retrieval would be initiated.
|
||||
cheServerKubernetesClientFactory
|
||||
.create()
|
||||
.secrets()
|
||||
.inNamespace(namespaceMeta.getName())
|
||||
.delete(secret);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -188,19 +232,23 @@ public class KubernetesPersonalAccessTokenManager implements PersonalAccessToken
|
|||
throws ScmCommunicationException, ScmConfigurationPersistenceException,
|
||||
UnknownScmProviderException, UnsatisfiedScmPreconditionException,
|
||||
ScmUnauthorizedException {
|
||||
Subject subject = EnvironmentContext.getCurrent().getSubject();
|
||||
Optional<PersonalAccessToken> tokenOptional = get(subject, scmServerUrl);
|
||||
PersonalAccessToken personalAccessToken;
|
||||
if (tokenOptional.isPresent()) {
|
||||
personalAccessToken = tokenOptional.get();
|
||||
} else {
|
||||
// try to authenticate for the given URL
|
||||
personalAccessToken = fetchAndSave(subject, scmServerUrl);
|
||||
}
|
||||
PersonalAccessToken personalAccessToken = get(scmServerUrl);
|
||||
gitCredentialManager.createOrReplace(personalAccessToken);
|
||||
return personalAccessToken;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void store(String scmServerUrl)
|
||||
throws UnsatisfiedScmPreconditionException, ScmConfigurationPersistenceException,
|
||||
ScmCommunicationException, ScmUnauthorizedException {
|
||||
Subject subject = EnvironmentContext.getCurrent().getSubject();
|
||||
Optional<PersonalAccessToken> tokenOptional = get(subject, scmServerUrl);
|
||||
if (tokenOptional.isPresent()) {
|
||||
PersonalAccessToken personalAccessToken = tokenOptional.get();
|
||||
gitCredentialManager.createOrReplace(personalAccessToken);
|
||||
}
|
||||
}
|
||||
|
||||
private String getFirstNamespace()
|
||||
throws UnsatisfiedScmPreconditionException, ScmConfigurationPersistenceException {
|
||||
try {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,197 @@
|
|||
/*
|
||||
* 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.api.factory.server.scm.kubernetes;
|
||||
|
||||
import static org.eclipse.che.workspace.infrastructure.kubernetes.namespace.AbstractWorkspaceServiceAccount.PREFERENCES_CONFIGMAP_NAME;
|
||||
import static org.mockito.ArgumentMatchers.anyMap;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
import static org.testng.Assert.assertEquals;
|
||||
import static org.testng.Assert.assertFalse;
|
||||
import static org.testng.Assert.assertTrue;
|
||||
|
||||
import io.fabric8.kubernetes.api.model.ConfigMap;
|
||||
import io.fabric8.kubernetes.api.model.ConfigMapList;
|
||||
import io.fabric8.kubernetes.client.KubernetesClient;
|
||||
import io.fabric8.kubernetes.client.dsl.MixedOperation;
|
||||
import io.fabric8.kubernetes.client.dsl.NonNamespaceOperation;
|
||||
import io.fabric8.kubernetes.client.dsl.Resource;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.CheServerKubernetesClientFactory;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.api.server.impls.KubernetesNamespaceMetaImpl;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.api.shared.KubernetesNamespaceMeta;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.namespace.KubernetesNamespaceFactory;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.testng.MockitoTestNGListener;
|
||||
import org.testng.annotations.BeforeMethod;
|
||||
import org.testng.annotations.Listeners;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
@Listeners(MockitoTestNGListener.class)
|
||||
public class KubernetesAuthorisationRequestManagerTest {
|
||||
@Mock private KubernetesNamespaceFactory namespaceFactory;
|
||||
|
||||
@Mock
|
||||
private MixedOperation<ConfigMap, ConfigMapList, Resource<ConfigMap>> configMapsMixedOperation;
|
||||
|
||||
@Mock NonNamespaceOperation<ConfigMap, ConfigMapList, Resource<ConfigMap>> nonNamespaceOperation;
|
||||
|
||||
@Mock private Resource<ConfigMap> configMapResource;
|
||||
|
||||
@Mock private ConfigMap configMap;
|
||||
|
||||
@Mock private KubernetesClient kubeClient;
|
||||
|
||||
@Mock private CheServerKubernetesClientFactory cheServerKubernetesClientFactory;
|
||||
|
||||
private KubernetesAuthorisationRequestManager authorisationRequestManager;
|
||||
|
||||
@BeforeMethod
|
||||
protected void init() throws Exception {
|
||||
KubernetesNamespaceMeta meta = new KubernetesNamespaceMetaImpl("test");
|
||||
when(namespaceFactory.list()).thenReturn(Collections.singletonList(meta));
|
||||
|
||||
when(cheServerKubernetesClientFactory.create()).thenReturn(kubeClient);
|
||||
when(kubeClient.configMaps()).thenReturn(configMapsMixedOperation);
|
||||
when(configMapsMixedOperation.inNamespace(eq(meta.getName())))
|
||||
.thenReturn(nonNamespaceOperation);
|
||||
when(nonNamespaceOperation.withName(eq(PREFERENCES_CONFIGMAP_NAME)))
|
||||
.thenReturn(configMapResource);
|
||||
when(configMapResource.get()).thenReturn(configMap);
|
||||
|
||||
authorisationRequestManager =
|
||||
new KubernetesAuthorisationRequestManager(
|
||||
namespaceFactory, cheServerKubernetesClientFactory);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldStoreAuthorisationRequestToEmptyConfigMap() {
|
||||
// given
|
||||
ArgumentCaptor<Map<String, String>> captor = ArgumentCaptor.forClass(Map.class);
|
||||
|
||||
// when
|
||||
authorisationRequestManager.store("test-provider");
|
||||
|
||||
// then
|
||||
verify(configMap).setData(captor.capture());
|
||||
Map<String, String> value = captor.getValue();
|
||||
assertEquals(value.get("skip-authorisation"), "[test-provider]");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldStoreAuthorisationRequestToNonEmptyConfigMap() {
|
||||
// given
|
||||
when(configMap.getData()).thenReturn(Map.of("skip-authorisation", "[existing-provider]"));
|
||||
ArgumentCaptor<Map<String, String>> captor = ArgumentCaptor.forClass(Map.class);
|
||||
|
||||
// when
|
||||
authorisationRequestManager.store("test-provider");
|
||||
|
||||
// then
|
||||
verify(configMap).setData(captor.capture());
|
||||
Map<String, String> value = captor.getValue();
|
||||
assertEquals(value.get("skip-authorisation"), "[test-provider, existing-provider]");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldNotStoreAuthorisationRequestIfAlreadyStored() {
|
||||
// given
|
||||
when(configMap.getData()).thenReturn(Map.of("skip-authorisation", "[test-provider]"));
|
||||
|
||||
// when
|
||||
authorisationRequestManager.store("test-provider");
|
||||
|
||||
// then
|
||||
verify(configMap, never()).setData(anyMap());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldRemoveAuthorisationRequestFromNonEmptyConfigMap() {
|
||||
// given
|
||||
when(configMap.getData())
|
||||
.thenReturn(Map.of("skip-authorisation", "[test-provider, existing-provider]"));
|
||||
ArgumentCaptor<Map<String, String>> captor = ArgumentCaptor.forClass(Map.class);
|
||||
|
||||
// when
|
||||
authorisationRequestManager.remove("test-provider");
|
||||
|
||||
// then
|
||||
verify(configMap).setData(captor.capture());
|
||||
Map<String, String> value = captor.getValue();
|
||||
assertEquals(value.get("skip-authorisation"), "[existing-provider]");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldRemoveAuthorisationRequestFromSingleValueConfigMap() {
|
||||
// given
|
||||
when(configMap.getData()).thenReturn(Map.of("skip-authorisation", "[test-provider]"));
|
||||
ArgumentCaptor<Map<String, String>> captor = ArgumentCaptor.forClass(Map.class);
|
||||
|
||||
// when
|
||||
authorisationRequestManager.remove("test-provider");
|
||||
|
||||
// then
|
||||
verify(configMap).setData(captor.capture());
|
||||
Map<String, String> value = captor.getValue();
|
||||
assertEquals(value.get("skip-authorisation"), "[]");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldNotRemoveAuthorisationRequestIfAlreadyRemoved() {
|
||||
// given
|
||||
when(configMap.getData()).thenReturn(Map.of("skip-authorisation", "[]"));
|
||||
|
||||
// when
|
||||
authorisationRequestManager.remove("test-provider");
|
||||
|
||||
// then
|
||||
verify(configMap, never()).setData(anyMap());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldReturnFalseAuthorisationRequestStateFromEmptyConfigMap() {
|
||||
// when
|
||||
boolean stored = authorisationRequestManager.isStored("test-provider");
|
||||
|
||||
// then
|
||||
assertFalse(stored);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldReturnFalseAuthorisationRequestStateFromNonEmptyConfigMap() {
|
||||
// given
|
||||
when(configMap.getData()).thenReturn(Map.of("skip-authorisation", "[existing-provider]"));
|
||||
|
||||
// when
|
||||
boolean stored = authorisationRequestManager.isStored("test-provider");
|
||||
|
||||
// then
|
||||
assertFalse(stored);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldReturnTrueAuthorisationRequestStateFromNonEmptyConfigMap() {
|
||||
// given
|
||||
when(configMap.getData())
|
||||
.thenReturn(Map.of("skip-authorisation", "[existing-provider, test-provider]"));
|
||||
|
||||
// when
|
||||
boolean stored = authorisationRequestManager.isStored("test-provider");
|
||||
|
||||
// then
|
||||
assertTrue(stored);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2012-2021 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/
|
||||
|
|
@ -15,7 +15,6 @@ import static java.util.Collections.emptyList;
|
|||
import static java.util.Collections.singletonList;
|
||||
import static org.eclipse.che.api.factory.server.scm.kubernetes.KubernetesGitCredentialManager.ANNOTATION_CHE_USERID;
|
||||
import static org.eclipse.che.api.factory.server.scm.kubernetes.KubernetesGitCredentialManager.ANNOTATION_SCM_URL;
|
||||
import static org.eclipse.che.api.factory.server.scm.kubernetes.KubernetesGitCredentialManager.ANNOTATION_SCM_USERNAME;
|
||||
import static org.eclipse.che.api.factory.server.scm.kubernetes.KubernetesGitCredentialManager.DEFAULT_SECRET_ANNOTATIONS;
|
||||
import static org.eclipse.che.api.factory.server.scm.kubernetes.KubernetesGitCredentialManager.NAME_PATTERN;
|
||||
import static org.mockito.ArgumentMatchers.anyMap;
|
||||
|
|
@ -43,7 +42,7 @@ import java.util.HashMap;
|
|||
import java.util.Map;
|
||||
import org.eclipse.che.api.factory.server.scm.PersonalAccessToken;
|
||||
import org.eclipse.che.commons.lang.NameGenerator;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.KubernetesClientFactory;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.CheServerKubernetesClientFactory;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.api.server.impls.KubernetesNamespaceMetaImpl;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.api.shared.KubernetesNamespaceMeta;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.namespace.KubernetesNamespaceFactory;
|
||||
|
|
@ -58,14 +57,14 @@ import org.testng.annotations.Test;
|
|||
public class KubernetesGitCredentialManagerTest {
|
||||
|
||||
@Mock private KubernetesNamespaceFactory namespaceFactory;
|
||||
@Mock private KubernetesClientFactory clientFactory;
|
||||
@Mock private CheServerKubernetesClientFactory cheServerKubernetesClientFactory;
|
||||
@Mock private KubernetesClient kubeClient;
|
||||
|
||||
@Mock private MixedOperation<Secret, SecretList, Resource<Secret>> secretsMixedOperation;
|
||||
|
||||
@Mock NonNamespaceOperation<Secret, SecretList, Resource<Secret>> nonNamespaceOperation;
|
||||
|
||||
@Mock private FilterWatchListDeletable<Secret, SecretList> filterWatchDeletable;
|
||||
@Mock private FilterWatchListDeletable<Secret, SecretList, Resource<Secret>> filterWatchDeletable;
|
||||
|
||||
@Mock private SecretList secretList;
|
||||
|
||||
|
|
@ -74,7 +73,7 @@ public class KubernetesGitCredentialManagerTest {
|
|||
@BeforeMethod
|
||||
protected void init() {
|
||||
kubernetesGitCredentialManager =
|
||||
new KubernetesGitCredentialManager(namespaceFactory, clientFactory);
|
||||
new KubernetesGitCredentialManager(namespaceFactory, cheServerKubernetesClientFactory);
|
||||
assertNotNull(this.kubernetesGitCredentialManager);
|
||||
}
|
||||
|
||||
|
|
@ -83,7 +82,7 @@ public class KubernetesGitCredentialManagerTest {
|
|||
KubernetesNamespaceMeta meta = new KubernetesNamespaceMetaImpl("test");
|
||||
when(namespaceFactory.list()).thenReturn(Collections.singletonList(meta));
|
||||
|
||||
when(clientFactory.create()).thenReturn(kubeClient);
|
||||
when(cheServerKubernetesClientFactory.create()).thenReturn(kubeClient);
|
||||
when(kubeClient.secrets()).thenReturn(secretsMixedOperation);
|
||||
when(secretsMixedOperation.inNamespace(eq(meta.getName()))).thenReturn(nonNamespaceOperation);
|
||||
when(nonNamespaceOperation.withLabels(anyMap())).thenReturn(filterWatchDeletable);
|
||||
|
|
@ -93,13 +92,7 @@ public class KubernetesGitCredentialManagerTest {
|
|||
|
||||
PersonalAccessToken token =
|
||||
new PersonalAccessToken(
|
||||
"https://bitbucket.com",
|
||||
"cheUser",
|
||||
"username",
|
||||
"userId",
|
||||
"token-name",
|
||||
"tid-23434",
|
||||
"token123");
|
||||
"https://bitbucket.com", "cheUser", "username", "token-name", "tid-23434", "token123");
|
||||
|
||||
// when
|
||||
kubernetesGitCredentialManager.createOrReplace(token);
|
||||
|
|
@ -114,12 +107,63 @@ public class KubernetesGitCredentialManagerTest {
|
|||
assertFalse(createdSecret.getMetadata().getName().contains(token.getScmUserName()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldUseHardcodedUsernameIfScmOrganizationIsDefined() throws Exception {
|
||||
// given
|
||||
KubernetesNamespaceMeta namespaceMeta = new KubernetesNamespaceMetaImpl("test");
|
||||
PersonalAccessToken token =
|
||||
new PersonalAccessToken(
|
||||
"https://bitbucket-server.com:5648",
|
||||
"cheUser",
|
||||
"cheOrganization",
|
||||
"username",
|
||||
"token-name",
|
||||
"tid-23434",
|
||||
"token123");
|
||||
|
||||
Map<String, String> annotations = new HashMap<>(DEFAULT_SECRET_ANNOTATIONS);
|
||||
|
||||
annotations.put(ANNOTATION_SCM_URL, token.getScmProviderUrl() + "/");
|
||||
annotations.put(ANNOTATION_CHE_USERID, token.getCheUserId());
|
||||
ObjectMeta objectMeta =
|
||||
new ObjectMetaBuilder()
|
||||
.withName(NameGenerator.generate(NAME_PATTERN, 5))
|
||||
.withAnnotations(annotations)
|
||||
.build();
|
||||
Secret existing =
|
||||
new SecretBuilder()
|
||||
.withMetadata(objectMeta)
|
||||
.withData(Map.of("credentials", "foo 123"))
|
||||
.build();
|
||||
|
||||
when(namespaceFactory.list()).thenReturn(Collections.singletonList(namespaceMeta));
|
||||
|
||||
when(cheServerKubernetesClientFactory.create()).thenReturn(kubeClient);
|
||||
when(kubeClient.secrets()).thenReturn(secretsMixedOperation);
|
||||
when(secretsMixedOperation.inNamespace(eq(namespaceMeta.getName())))
|
||||
.thenReturn(nonNamespaceOperation);
|
||||
when(nonNamespaceOperation.withLabels(anyMap())).thenReturn(filterWatchDeletable);
|
||||
when(filterWatchDeletable.list()).thenReturn(secretList);
|
||||
when(secretList.getItems()).thenReturn(singletonList(existing));
|
||||
|
||||
// when
|
||||
kubernetesGitCredentialManager.createOrReplace(token);
|
||||
// then
|
||||
ArgumentCaptor<Secret> captor = ArgumentCaptor.forClass(Secret.class);
|
||||
verify(nonNamespaceOperation).createOrReplace(captor.capture());
|
||||
Secret createdSecret = captor.getValue();
|
||||
assertNotNull(createdSecret);
|
||||
assertEquals(
|
||||
new String(Base64.getDecoder().decode(createdSecret.getData().get("credentials"))),
|
||||
"https://username:token123@bitbucket-server.com:5648");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateAndSaveNewOAuthGitCredential() throws Exception {
|
||||
KubernetesNamespaceMeta meta = new KubernetesNamespaceMetaImpl("test");
|
||||
when(namespaceFactory.list()).thenReturn(Collections.singletonList(meta));
|
||||
|
||||
when(clientFactory.create()).thenReturn(kubeClient);
|
||||
when(cheServerKubernetesClientFactory.create()).thenReturn(kubeClient);
|
||||
when(kubeClient.secrets()).thenReturn(secretsMixedOperation);
|
||||
when(secretsMixedOperation.inNamespace(eq(meta.getName()))).thenReturn(nonNamespaceOperation);
|
||||
when(nonNamespaceOperation.withLabels(anyMap())).thenReturn(filterWatchDeletable);
|
||||
|
|
@ -132,7 +176,6 @@ public class KubernetesGitCredentialManagerTest {
|
|||
"https://bitbucket.com",
|
||||
"cheUser",
|
||||
"username",
|
||||
"userId",
|
||||
"oauth2-token-name",
|
||||
"tid-23434",
|
||||
"token123");
|
||||
|
|
@ -158,7 +201,6 @@ public class KubernetesGitCredentialManagerTest {
|
|||
"https://bitbucket.com:5648",
|
||||
"cheUser",
|
||||
"username",
|
||||
"userId",
|
||||
"token-name",
|
||||
"tid-23434",
|
||||
"token123");
|
||||
|
|
@ -166,7 +208,6 @@ public class KubernetesGitCredentialManagerTest {
|
|||
Map<String, String> annotations = new HashMap<>(DEFAULT_SECRET_ANNOTATIONS);
|
||||
|
||||
annotations.put(ANNOTATION_SCM_URL, token.getScmProviderUrl() + "/");
|
||||
annotations.put(ANNOTATION_SCM_USERNAME, token.getScmUserName());
|
||||
annotations.put(ANNOTATION_CHE_USERID, token.getCheUserId());
|
||||
ObjectMeta objectMeta =
|
||||
new ObjectMetaBuilder()
|
||||
|
|
@ -181,7 +222,7 @@ public class KubernetesGitCredentialManagerTest {
|
|||
|
||||
when(namespaceFactory.list()).thenReturn(Collections.singletonList(namespaceMeta));
|
||||
|
||||
when(clientFactory.create()).thenReturn(kubeClient);
|
||||
when(cheServerKubernetesClientFactory.create()).thenReturn(kubeClient);
|
||||
when(kubeClient.secrets()).thenReturn(secretsMixedOperation);
|
||||
when(secretsMixedOperation.inNamespace(eq(namespaceMeta.getName())))
|
||||
.thenReturn(nonNamespaceOperation);
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@
|
|||
package org.eclipse.che.api.factory.server.scm.kubernetes;
|
||||
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
import static java.util.Collections.singletonList;
|
||||
import static org.eclipse.che.api.factory.server.scm.kubernetes.KubernetesPersonalAccessTokenManager.ANNOTATION_CHE_USERID;
|
||||
import static org.eclipse.che.api.factory.server.scm.kubernetes.KubernetesPersonalAccessTokenManager.ANNOTATION_SCM_PERSONAL_ACCESS_TOKEN_ID;
|
||||
import static org.eclipse.che.api.factory.server.scm.kubernetes.KubernetesPersonalAccessTokenManager.ANNOTATION_SCM_URL;
|
||||
|
|
@ -37,15 +38,15 @@ import io.fabric8.kubernetes.client.dsl.NonNamespaceOperation;
|
|||
import io.fabric8.kubernetes.client.dsl.Resource;
|
||||
import java.util.Arrays;
|
||||
import java.util.Base64;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import org.eclipse.che.api.factory.server.scm.GitCredentialManager;
|
||||
import org.eclipse.che.api.factory.server.scm.PersonalAccessToken;
|
||||
import org.eclipse.che.api.factory.server.scm.PersonalAccessTokenParams;
|
||||
import org.eclipse.che.api.factory.server.scm.ScmPersonalAccessTokenFetcher;
|
||||
import org.eclipse.che.commons.subject.SubjectImpl;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.KubernetesClientFactory;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.CheServerKubernetesClientFactory;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.api.server.impls.KubernetesNamespaceMetaImpl;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.api.shared.KubernetesNamespaceMeta;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.namespace.KubernetesNamespace;
|
||||
|
|
@ -64,7 +65,7 @@ import org.testng.annotations.Test;
|
|||
public class KubernetesPersonalAccessTokenManagerTest {
|
||||
|
||||
@Mock private KubernetesNamespaceFactory namespaceFactory;
|
||||
@Mock private KubernetesClientFactory clientFactory;
|
||||
@Mock private CheServerKubernetesClientFactory cheServerKubernetesClientFactory;
|
||||
@Mock private ScmPersonalAccessTokenFetcher scmPersonalAccessTokenFetcher;
|
||||
|
||||
@Mock private KubernetesClient kubeClient;
|
||||
|
|
@ -80,19 +81,23 @@ public class KubernetesPersonalAccessTokenManagerTest {
|
|||
protected void init() {
|
||||
personalAccessTokenManager =
|
||||
new KubernetesPersonalAccessTokenManager(
|
||||
namespaceFactory, clientFactory, scmPersonalAccessTokenFetcher, gitCredentialManager);
|
||||
namespaceFactory,
|
||||
cheServerKubernetesClientFactory,
|
||||
scmPersonalAccessTokenFetcher,
|
||||
gitCredentialManager);
|
||||
assertNotNull(this.personalAccessTokenManager);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldTrimBlankCharsInToken() throws Exception {
|
||||
KubernetesNamespaceMeta meta = new KubernetesNamespaceMetaImpl("test");
|
||||
when(namespaceFactory.list()).thenReturn(Collections.singletonList(meta));
|
||||
when(namespaceFactory.list()).thenReturn(singletonList(meta));
|
||||
KubernetesNamespace kubernetesnamespace = Mockito.mock(KubernetesNamespace.class);
|
||||
KubernetesSecrets secrets = Mockito.mock(KubernetesSecrets.class);
|
||||
when(namespaceFactory.access(eq(null), eq(meta.getName()))).thenReturn(kubernetesnamespace);
|
||||
when(kubernetesnamespace.secrets()).thenReturn(secrets);
|
||||
when(scmPersonalAccessTokenFetcher.isValid(any(PersonalAccessToken.class))).thenReturn(true);
|
||||
when(scmPersonalAccessTokenFetcher.getScmUsername(any(PersonalAccessTokenParams.class)))
|
||||
.thenReturn(Optional.of("user"));
|
||||
|
||||
Map<String, String> data =
|
||||
Map.of("token", Base64.getEncoder().encodeToString(" token_value \n".getBytes(UTF_8)));
|
||||
|
|
@ -121,22 +126,16 @@ public class KubernetesPersonalAccessTokenManagerTest {
|
|||
public void testSavingOfPersonalAccessToken() throws Exception {
|
||||
|
||||
KubernetesNamespaceMeta meta = new KubernetesNamespaceMetaImpl("test");
|
||||
when(namespaceFactory.list()).thenReturn(Collections.singletonList(meta));
|
||||
when(namespaceFactory.list()).thenReturn(singletonList(meta));
|
||||
|
||||
when(clientFactory.create()).thenReturn(kubeClient);
|
||||
when(cheServerKubernetesClientFactory.create()).thenReturn(kubeClient);
|
||||
when(kubeClient.secrets()).thenReturn(secretsMixedOperation);
|
||||
when(secretsMixedOperation.inNamespace(eq(meta.getName()))).thenReturn(nonNamespaceOperation);
|
||||
ArgumentCaptor<Secret> captor = ArgumentCaptor.forClass(Secret.class);
|
||||
|
||||
PersonalAccessToken token =
|
||||
new PersonalAccessToken(
|
||||
"https://bitbucket.com",
|
||||
"cheUser",
|
||||
"username",
|
||||
"userId",
|
||||
"token-name",
|
||||
"tid-24",
|
||||
"token123");
|
||||
"https://bitbucket.com", "cheUser", "username", "token-name", "tid-24", "token123");
|
||||
|
||||
// when
|
||||
personalAccessTokenManager.save(token);
|
||||
|
|
@ -159,12 +158,13 @@ public class KubernetesPersonalAccessTokenManagerTest {
|
|||
public void testGetTokenFromNamespace() throws Exception {
|
||||
|
||||
KubernetesNamespaceMeta meta = new KubernetesNamespaceMetaImpl("test");
|
||||
when(namespaceFactory.list()).thenReturn(Collections.singletonList(meta));
|
||||
when(namespaceFactory.list()).thenReturn(singletonList(meta));
|
||||
KubernetesNamespace kubernetesnamespace = Mockito.mock(KubernetesNamespace.class);
|
||||
KubernetesSecrets secrets = Mockito.mock(KubernetesSecrets.class);
|
||||
when(namespaceFactory.access(eq(null), eq(meta.getName()))).thenReturn(kubernetesnamespace);
|
||||
when(kubernetesnamespace.secrets()).thenReturn(secrets);
|
||||
when(scmPersonalAccessTokenFetcher.isValid(any(PersonalAccessToken.class))).thenReturn(true);
|
||||
when(scmPersonalAccessTokenFetcher.getScmUsername(any(PersonalAccessTokenParams.class)))
|
||||
.thenReturn(Optional.of("user"));
|
||||
|
||||
Map<String, String> data1 =
|
||||
Map.of("token", Base64.getEncoder().encodeToString("token1".getBytes(UTF_8)));
|
||||
|
|
@ -209,15 +209,96 @@ public class KubernetesPersonalAccessTokenManagerTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testGetTokenFromNamespaceWithTrailingSlashMismatch() throws Exception {
|
||||
public void shouldGetTokenFromASecretWithSCMUsername() throws Exception {
|
||||
|
||||
KubernetesNamespaceMeta meta = new KubernetesNamespaceMetaImpl("test");
|
||||
when(namespaceFactory.list()).thenReturn(Collections.singletonList(meta));
|
||||
when(namespaceFactory.list()).thenReturn(singletonList(meta));
|
||||
KubernetesNamespace kubernetesnamespace = Mockito.mock(KubernetesNamespace.class);
|
||||
KubernetesSecrets secrets = Mockito.mock(KubernetesSecrets.class);
|
||||
when(namespaceFactory.access(eq(null), eq(meta.getName()))).thenReturn(kubernetesnamespace);
|
||||
when(kubernetesnamespace.secrets()).thenReturn(secrets);
|
||||
when(scmPersonalAccessTokenFetcher.isValid(any(PersonalAccessToken.class))).thenReturn(true);
|
||||
when(scmPersonalAccessTokenFetcher.getScmUsername(any(PersonalAccessTokenParams.class)))
|
||||
.thenReturn(Optional.of("user"));
|
||||
|
||||
Map<String, String> data =
|
||||
Map.of("token", Base64.getEncoder().encodeToString("token1".getBytes(UTF_8)));
|
||||
|
||||
ObjectMeta metaData =
|
||||
new ObjectMetaBuilder()
|
||||
.withAnnotations(
|
||||
Map.of(
|
||||
ANNOTATION_CHE_USERID,
|
||||
"user1",
|
||||
ANNOTATION_SCM_URL,
|
||||
"http://host1",
|
||||
"che.eclipse.org/scm-username",
|
||||
"scm-username"))
|
||||
.build();
|
||||
|
||||
Secret secret = new SecretBuilder().withMetadata(metaData).withData(data).build();
|
||||
|
||||
when(secrets.get(any(LabelSelector.class))).thenReturn(singletonList(secret));
|
||||
|
||||
// when
|
||||
Optional<PersonalAccessToken> tokenOptional =
|
||||
personalAccessTokenManager.get(
|
||||
new SubjectImpl("user", "user1", "t1", false), "http://host1");
|
||||
|
||||
// then
|
||||
assertTrue(tokenOptional.isPresent());
|
||||
assertEquals(tokenOptional.get().getCheUserId(), "user1");
|
||||
assertEquals(tokenOptional.get().getScmProviderUrl(), "http://host1");
|
||||
assertEquals(tokenOptional.get().getToken(), "token1");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldGetTokenFromASecretWithoutSCMUsername() throws Exception {
|
||||
|
||||
KubernetesNamespaceMeta meta = new KubernetesNamespaceMetaImpl("test");
|
||||
when(namespaceFactory.list()).thenReturn(singletonList(meta));
|
||||
KubernetesNamespace kubernetesnamespace = Mockito.mock(KubernetesNamespace.class);
|
||||
KubernetesSecrets secrets = Mockito.mock(KubernetesSecrets.class);
|
||||
when(namespaceFactory.access(eq(null), eq(meta.getName()))).thenReturn(kubernetesnamespace);
|
||||
when(kubernetesnamespace.secrets()).thenReturn(secrets);
|
||||
when(scmPersonalAccessTokenFetcher.getScmUsername(any(PersonalAccessTokenParams.class)))
|
||||
.thenReturn(Optional.of("user"));
|
||||
|
||||
Map<String, String> data =
|
||||
Map.of("token", Base64.getEncoder().encodeToString("token1".getBytes(UTF_8)));
|
||||
|
||||
ObjectMeta metaData =
|
||||
new ObjectMetaBuilder()
|
||||
.withAnnotations(
|
||||
Map.of(ANNOTATION_CHE_USERID, "user1", ANNOTATION_SCM_URL, "http://host1"))
|
||||
.build();
|
||||
|
||||
Secret secret = new SecretBuilder().withMetadata(metaData).withData(data).build();
|
||||
|
||||
when(secrets.get(any(LabelSelector.class))).thenReturn(singletonList(secret));
|
||||
|
||||
// when
|
||||
Optional<PersonalAccessToken> tokenOptional =
|
||||
personalAccessTokenManager.get(
|
||||
new SubjectImpl("user", "user1", "t1", false), "http://host1");
|
||||
|
||||
// then
|
||||
assertTrue(tokenOptional.isPresent());
|
||||
assertEquals(tokenOptional.get().getCheUserId(), "user1");
|
||||
assertEquals(tokenOptional.get().getScmProviderUrl(), "http://host1");
|
||||
assertEquals(tokenOptional.get().getToken(), "token1");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetTokenFromNamespaceWithTrailingSlashMismatch() throws Exception {
|
||||
|
||||
KubernetesNamespaceMeta meta = new KubernetesNamespaceMetaImpl("test");
|
||||
when(namespaceFactory.list()).thenReturn(singletonList(meta));
|
||||
KubernetesNamespace kubernetesnamespace = Mockito.mock(KubernetesNamespace.class);
|
||||
KubernetesSecrets secrets = Mockito.mock(KubernetesSecrets.class);
|
||||
when(namespaceFactory.access(eq(null), eq(meta.getName()))).thenReturn(kubernetesnamespace);
|
||||
when(kubernetesnamespace.secrets()).thenReturn(secrets);
|
||||
when(scmPersonalAccessTokenFetcher.getScmUsername(any(PersonalAccessTokenParams.class)))
|
||||
.thenReturn(Optional.of("user"));
|
||||
|
||||
Map<String, String> data1 =
|
||||
Map.of("token", Base64.getEncoder().encodeToString("token1".getBytes(UTF_8)));
|
||||
|
|
@ -259,13 +340,14 @@ public class KubernetesPersonalAccessTokenManagerTest {
|
|||
public void shouldDeleteInvalidTokensOnGet() throws Exception {
|
||||
// given
|
||||
KubernetesNamespaceMeta meta = new KubernetesNamespaceMetaImpl("test");
|
||||
when(namespaceFactory.list()).thenReturn(Collections.singletonList(meta));
|
||||
when(namespaceFactory.list()).thenReturn(singletonList(meta));
|
||||
KubernetesNamespace kubernetesnamespace = Mockito.mock(KubernetesNamespace.class);
|
||||
KubernetesSecrets secrets = Mockito.mock(KubernetesSecrets.class);
|
||||
when(namespaceFactory.access(eq(null), eq(meta.getName()))).thenReturn(kubernetesnamespace);
|
||||
when(kubernetesnamespace.secrets()).thenReturn(secrets);
|
||||
when(scmPersonalAccessTokenFetcher.isValid(any(PersonalAccessToken.class))).thenReturn(false);
|
||||
when(clientFactory.create()).thenReturn(kubeClient);
|
||||
when(scmPersonalAccessTokenFetcher.getScmUsername(any(PersonalAccessTokenParams.class)))
|
||||
.thenReturn(Optional.empty());
|
||||
when(cheServerKubernetesClientFactory.create()).thenReturn(kubeClient);
|
||||
when(kubeClient.secrets()).thenReturn(secretsMixedOperation);
|
||||
when(secretsMixedOperation.inNamespace(eq(meta.getName()))).thenReturn(nonNamespaceOperation);
|
||||
Map<String, String> data1 =
|
||||
|
|
@ -290,19 +372,21 @@ public class KubernetesPersonalAccessTokenManagerTest {
|
|||
public void shouldReturnFirstValidToken() throws Exception {
|
||||
// given
|
||||
KubernetesNamespaceMeta meta = new KubernetesNamespaceMetaImpl("test");
|
||||
when(namespaceFactory.list()).thenReturn(Collections.singletonList(meta));
|
||||
when(namespaceFactory.list()).thenReturn(singletonList(meta));
|
||||
KubernetesNamespace kubernetesnamespace = Mockito.mock(KubernetesNamespace.class);
|
||||
KubernetesSecrets secrets = Mockito.mock(KubernetesSecrets.class);
|
||||
when(namespaceFactory.access(eq(null), eq(meta.getName()))).thenReturn(kubernetesnamespace);
|
||||
when(kubernetesnamespace.secrets()).thenReturn(secrets);
|
||||
when(scmPersonalAccessTokenFetcher.isValid(any(PersonalAccessToken.class)))
|
||||
when(scmPersonalAccessTokenFetcher.getScmUsername(any(PersonalAccessTokenParams.class)))
|
||||
.thenAnswer(
|
||||
(Answer<Boolean>)
|
||||
(Answer<Optional<String>>)
|
||||
invocation -> {
|
||||
PersonalAccessToken token = invocation.getArgument(0);
|
||||
return "id2".equals(token.getScmTokenId());
|
||||
PersonalAccessTokenParams params = invocation.getArgument(0);
|
||||
return "id2".equals(params.getScmTokenId())
|
||||
? Optional.of("user")
|
||||
: Optional.empty();
|
||||
});
|
||||
when(clientFactory.create()).thenReturn(kubeClient);
|
||||
when(cheServerKubernetesClientFactory.create()).thenReturn(kubeClient);
|
||||
when(kubeClient.secrets()).thenReturn(secretsMixedOperation);
|
||||
when(secretsMixedOperation.inNamespace(eq(meta.getName()))).thenReturn(nonNamespaceOperation);
|
||||
Map<String, String> data1 =
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
<parent>
|
||||
<artifactId>che-infrastructures-parent</artifactId>
|
||||
<groupId>org.eclipse.che.infrastructure</groupId>
|
||||
<version>7.64.0-SNAPSHOT</version>
|
||||
<version>7.76.0-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
<artifactId>infrastructure-metrics</artifactId>
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
<parent>
|
||||
<artifactId>che-infrastructures-parent</artifactId>
|
||||
<groupId>org.eclipse.che.infrastructure</groupId>
|
||||
<version>7.64.0-SNAPSHOT</version>
|
||||
<version>7.76.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>infrastructure-permission</artifactId>
|
||||
<name>Infrastructure :: Kubernetes Permissions</name>
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
<parent>
|
||||
<artifactId>che-infrastructures-parent</artifactId>
|
||||
<groupId>org.eclipse.che.infrastructure</groupId>
|
||||
<version>7.64.0-SNAPSHOT</version>
|
||||
<version>7.76.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>infrastructure-kubernetes</artifactId>
|
||||
<name>Infrastructure :: Kubernetes</name>
|
||||
|
|
@ -63,7 +63,7 @@
|
|||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.fabric8</groupId>
|
||||
<artifactId>kubernetes-client</artifactId>
|
||||
<artifactId>kubernetes-client-api</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.fabric8</groupId>
|
||||
|
|
|
|||
|
|
@ -11,7 +11,6 @@
|
|||
*/
|
||||
package org.eclipse.che.workspace.infrastructure.kubernetes;
|
||||
|
||||
import io.fabric8.kubernetes.client.BaseKubernetesClient;
|
||||
import io.fabric8.kubernetes.client.Config;
|
||||
import io.fabric8.kubernetes.client.DefaultKubernetesClient;
|
||||
import io.fabric8.kubernetes.client.KubernetesClient;
|
||||
|
|
@ -19,7 +18,6 @@ import io.fabric8.kubernetes.client.http.HttpClient;
|
|||
import io.fabric8.kubernetes.client.utils.HttpClientUtils;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
import okhttp3.OkHttpClient;
|
||||
import org.eclipse.che.api.workspace.server.spi.InfrastructureException;
|
||||
import org.eclipse.che.commons.annotation.Nullable;
|
||||
|
||||
|
|
@ -94,12 +92,12 @@ public class KubernetesClientFactory {
|
|||
}
|
||||
|
||||
/**
|
||||
* Creates instance of {@link KubernetesClient} that uses an {@link OkHttpClient} instance derived
|
||||
* Creates instance of {@link KubernetesClient} that uses an {@link HttpClient} instance derived
|
||||
* from the shared {@code httpClient} instance in which interceptors are overridden to
|
||||
* authenticate with the credentials (user/password or Oauth token) contained in the {@code
|
||||
* config} parameter.
|
||||
*/
|
||||
protected BaseKubernetesClient<?> create(Config config) {
|
||||
protected KubernetesClient create(Config config) {
|
||||
return new UnclosableKubernetesClient(httpClient, config);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -41,7 +41,6 @@ public class KubernetesInfrastructure extends RuntimeInfrastructure {
|
|||
private final KubernetesRuntimeContextFactory runtimeContextFactory;
|
||||
private final KubernetesRuntimeStateCache runtimeStatusesCache;
|
||||
private final KubernetesNamespaceFactory namespaceFactory;
|
||||
private final KubernetesClientFactory kubernetesClientFactory;
|
||||
|
||||
@Inject
|
||||
public KubernetesInfrastructure(
|
||||
|
|
@ -49,8 +48,7 @@ public class KubernetesInfrastructure extends RuntimeInfrastructure {
|
|||
KubernetesRuntimeContextFactory runtimeContextFactory,
|
||||
Set<InternalEnvironmentProvisioner> internalEnvProvisioners,
|
||||
KubernetesRuntimeStateCache runtimeStatusesCache,
|
||||
KubernetesNamespaceFactory namespaceFactory,
|
||||
KubernetesClientFactory kubernetesClientFactory) {
|
||||
KubernetesNamespaceFactory namespaceFactory) {
|
||||
super(
|
||||
NAME,
|
||||
ImmutableSet.of(KubernetesEnvironment.TYPE, Constants.NO_ENVIRONMENT_RECIPE_TYPE),
|
||||
|
|
@ -59,7 +57,6 @@ public class KubernetesInfrastructure extends RuntimeInfrastructure {
|
|||
this.runtimeContextFactory = runtimeContextFactory;
|
||||
this.runtimeStatusesCache = runtimeStatusesCache;
|
||||
this.namespaceFactory = namespaceFactory;
|
||||
this.kubernetesClientFactory = kubernetesClientFactory;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@ import io.fabric8.kubernetes.api.model.Pod;
|
|||
import io.fabric8.kubernetes.api.model.PodSpec;
|
||||
import io.fabric8.kubernetes.api.model.PodStatus;
|
||||
import io.fabric8.kubernetes.api.model.ServiceAccount;
|
||||
import io.fabric8.kubernetes.api.model.StatusDetails;
|
||||
import io.fabric8.kubernetes.api.model.apps.Deployment;
|
||||
import io.fabric8.kubernetes.api.model.apps.DeploymentBuilder;
|
||||
import io.fabric8.kubernetes.client.KubernetesClientException;
|
||||
|
|
@ -71,7 +72,6 @@ import java.util.function.Predicate;
|
|||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
import okhttp3.Response;
|
||||
import org.eclipse.che.api.workspace.server.spi.InfrastructureException;
|
||||
import org.eclipse.che.commons.annotation.Nullable;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.KubernetesClientFactory;
|
||||
|
|
@ -301,7 +301,7 @@ public class KubernetesDeployments {
|
|||
CompletableFuture<Pod> future = new CompletableFuture<>();
|
||||
try {
|
||||
|
||||
PodResource<Pod> podResource =
|
||||
PodResource podResource =
|
||||
clientFactory.create(workspaceId).pods().inNamespace(namespace).withName(podName);
|
||||
|
||||
Watch watch =
|
||||
|
|
@ -366,7 +366,7 @@ public class KubernetesDeployments {
|
|||
final CompletableFuture<Void> podRunningFuture = new CompletableFuture<>();
|
||||
try {
|
||||
final String podName = getPodName(name);
|
||||
final PodResource<Pod> podResource =
|
||||
final PodResource podResource =
|
||||
clientFactory.create(workspaceId).pods().inNamespace(namespace).withName(podName);
|
||||
final Watch watch =
|
||||
podResource.watch(
|
||||
|
|
@ -941,18 +941,18 @@ public class KubernetesDeployments {
|
|||
// If we have a Pod, we have to watch to make sure it is deleted, otherwise, we watch the
|
||||
// Deployment we are deleting.
|
||||
if (!Strings.isNullOrEmpty(podName)) {
|
||||
PodResource<Pod> podResource =
|
||||
PodResource podResource =
|
||||
clientFactory.create(workspaceId).pods().inNamespace(namespace).withName(podName);
|
||||
watch = podResource.watch(new DeleteWatcher<>(deleteFuture));
|
||||
toCloseOnException = watch;
|
||||
} else {
|
||||
watch = deploymentResource.watch(new DeleteWatcher<Deployment>(deleteFuture));
|
||||
watch = deploymentResource.watch(new DeleteWatcher<>(deleteFuture));
|
||||
toCloseOnException = watch;
|
||||
}
|
||||
|
||||
Boolean deleteSucceeded = deploymentResource.withPropagationPolicy(BACKGROUND).delete();
|
||||
List<StatusDetails> deleted = deploymentResource.withPropagationPolicy(BACKGROUND).delete();
|
||||
|
||||
if (deleteSucceeded == null || !deleteSucceeded) {
|
||||
if (deleted == null || deleted.isEmpty()) {
|
||||
deleteFuture.complete(null);
|
||||
}
|
||||
return deleteFuture.whenComplete(
|
||||
|
|
@ -978,7 +978,7 @@ public class KubernetesDeployments {
|
|||
protected CompletableFuture<Void> doDeletePod(String podName) throws InfrastructureException {
|
||||
Watch toCloseOnException = null;
|
||||
try {
|
||||
PodResource<Pod> podResource =
|
||||
PodResource podResource =
|
||||
clientFactory.create(workspaceId).pods().inNamespace(namespace).withName(podName);
|
||||
if (podResource.get() == null) {
|
||||
throw new InfrastructureException(format("No pod found to delete for name %s", podName));
|
||||
|
|
@ -988,8 +988,8 @@ public class KubernetesDeployments {
|
|||
final Watch watch = podResource.watch(new DeleteWatcher<>(deleteFuture));
|
||||
toCloseOnException = watch;
|
||||
|
||||
Boolean deleteSucceeded = podResource.withPropagationPolicy(BACKGROUND).delete();
|
||||
if (deleteSucceeded == null || !deleteSucceeded) {
|
||||
List<StatusDetails> deleted = podResource.withPropagationPolicy(BACKGROUND).delete();
|
||||
if (deleted == null || deleted.isEmpty()) {
|
||||
deleteFuture.complete(null);
|
||||
}
|
||||
return deleteFuture.whenComplete(
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ import java.util.concurrent.TimeoutException;
|
|||
import java.util.function.Predicate;
|
||||
import org.eclipse.che.api.workspace.server.spi.InfrastructureException;
|
||||
import org.eclipse.che.api.workspace.server.spi.InternalInfrastructureException;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.KubernetesClientFactory;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.CheServerKubernetesClientFactory;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.KubernetesInfrastructureException;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
|
@ -73,18 +73,15 @@ public class KubernetesNamespace {
|
|||
private final KubernetesServices services;
|
||||
private final KubernetesPersistentVolumeClaims pvcs;
|
||||
private final KubernetesIngresses ingresses;
|
||||
/** Factory for workspace related operations clients */
|
||||
private final KubernetesClientFactory clientFactory;
|
||||
/** Factory for cluster related operations clients (like labeling the namespaces) */
|
||||
private final KubernetesClientFactory cheSAClientFactory;
|
||||
private final CheServerKubernetesClientFactory cheSAClientFactory;
|
||||
|
||||
private final KubernetesSecrets secrets;
|
||||
private final KubernetesConfigsMaps configMaps;
|
||||
|
||||
@VisibleForTesting
|
||||
protected KubernetesNamespace(
|
||||
KubernetesClientFactory clientFactory,
|
||||
KubernetesClientFactory cheSAClientFactory,
|
||||
CheServerKubernetesClientFactory cheSAClientFactory,
|
||||
String workspaceId,
|
||||
String name,
|
||||
KubernetesDeployments deployments,
|
||||
|
|
@ -93,7 +90,6 @@ public class KubernetesNamespace {
|
|||
KubernetesIngresses kubernetesIngresses,
|
||||
KubernetesSecrets secrets,
|
||||
KubernetesConfigsMaps configMaps) {
|
||||
this.clientFactory = clientFactory;
|
||||
this.cheSAClientFactory = cheSAClientFactory;
|
||||
this.workspaceId = workspaceId;
|
||||
this.name = name;
|
||||
|
|
@ -106,21 +102,19 @@ public class KubernetesNamespace {
|
|||
}
|
||||
|
||||
public KubernetesNamespace(
|
||||
KubernetesClientFactory clientFactory,
|
||||
KubernetesClientFactory cheSAClientFactory,
|
||||
CheServerKubernetesClientFactory cheSAClientFactory,
|
||||
Executor executor,
|
||||
String name,
|
||||
String workspaceId) {
|
||||
this.clientFactory = clientFactory;
|
||||
this.cheSAClientFactory = cheSAClientFactory;
|
||||
this.workspaceId = workspaceId;
|
||||
this.name = name;
|
||||
this.deployments = new KubernetesDeployments(name, workspaceId, clientFactory, executor);
|
||||
this.services = new KubernetesServices(name, workspaceId, clientFactory);
|
||||
this.pvcs = new KubernetesPersistentVolumeClaims(name, workspaceId, clientFactory);
|
||||
this.ingresses = new KubernetesIngresses(name, workspaceId, clientFactory);
|
||||
this.secrets = new KubernetesSecrets(name, workspaceId, clientFactory);
|
||||
this.configMaps = new KubernetesConfigsMaps(name, workspaceId, clientFactory);
|
||||
this.deployments = new KubernetesDeployments(name, workspaceId, cheSAClientFactory, executor);
|
||||
this.services = new KubernetesServices(name, workspaceId, cheSAClientFactory);
|
||||
this.pvcs = new KubernetesPersistentVolumeClaims(name, workspaceId, cheSAClientFactory);
|
||||
this.ingresses = new KubernetesIngresses(name, workspaceId, cheSAClientFactory);
|
||||
this.secrets = new KubernetesSecrets(name, workspaceId, cheSAClientFactory);
|
||||
this.configMaps = new KubernetesConfigsMaps(name, workspaceId, cheSAClientFactory);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -270,7 +264,7 @@ public class KubernetesNamespace {
|
|||
* @throws InfrastructureException if any unexpected exception occurs during namespace deletion
|
||||
*/
|
||||
void delete() throws InfrastructureException {
|
||||
KubernetesClient client = clientFactory.create(workspaceId);
|
||||
KubernetesClient client = cheSAClientFactory.create(workspaceId);
|
||||
|
||||
try {
|
||||
delete(name, client);
|
||||
|
|
|
|||
|
|
@ -46,7 +46,6 @@ import org.eclipse.che.api.core.ValidationException;
|
|||
import org.eclipse.che.api.core.model.workspace.Workspace;
|
||||
import org.eclipse.che.api.core.model.workspace.runtime.RuntimeIdentity;
|
||||
import org.eclipse.che.api.user.server.PreferenceManager;
|
||||
import org.eclipse.che.api.user.server.UserManager;
|
||||
import org.eclipse.che.api.workspace.server.spi.InfrastructureException;
|
||||
import org.eclipse.che.api.workspace.server.spi.NamespaceResolutionContext;
|
||||
import org.eclipse.che.commons.annotation.Nullable;
|
||||
|
|
@ -56,7 +55,6 @@ import org.eclipse.che.commons.lang.Pair;
|
|||
import org.eclipse.che.commons.subject.Subject;
|
||||
import org.eclipse.che.inject.ConfigurationException;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.CheServerKubernetesClientFactory;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.KubernetesClientFactory;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.api.server.impls.KubernetesNamespaceMetaImpl;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.api.shared.KubernetesNamespaceMeta;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.namespace.configurator.NamespaceConfigurator;
|
||||
|
|
@ -95,10 +93,8 @@ public class KubernetesNamespaceFactory {
|
|||
protected final Map<String, String> namespaceLabels;
|
||||
protected final Map<String, String> namespaceAnnotations;
|
||||
|
||||
private final KubernetesClientFactory clientFactory;
|
||||
private final KubernetesClientFactory cheClientFactory;
|
||||
private final CheServerKubernetesClientFactory cheServerKubernetesClientFactory;
|
||||
private final boolean namespaceCreationAllowed;
|
||||
private final UserManager userManager;
|
||||
private final PreferenceManager preferenceManager;
|
||||
protected final Set<NamespaceConfigurator> namespaceConfigurators;
|
||||
protected final KubernetesSharedPool sharedPool;
|
||||
|
|
@ -112,16 +108,12 @@ public class KubernetesNamespaceFactory {
|
|||
@Named("che.infra.kubernetes.namespace.labels") String namespaceLabels,
|
||||
@Named("che.infra.kubernetes.namespace.annotations") String namespaceAnnotations,
|
||||
Set<NamespaceConfigurator> namespaceConfigurators,
|
||||
KubernetesClientFactory clientFactory,
|
||||
CheServerKubernetesClientFactory cheClientFactory,
|
||||
UserManager userManager,
|
||||
CheServerKubernetesClientFactory cheServerKubernetesClientFactory,
|
||||
PreferenceManager preferenceManager,
|
||||
KubernetesSharedPool sharedPool)
|
||||
throws ConfigurationException {
|
||||
this.namespaceCreationAllowed = namespaceCreationAllowed;
|
||||
this.userManager = userManager;
|
||||
this.clientFactory = clientFactory;
|
||||
this.cheClientFactory = cheClientFactory;
|
||||
this.cheServerKubernetesClientFactory = cheServerKubernetesClientFactory;
|
||||
this.defaultNamespaceName = defaultNamespaceName;
|
||||
this.preferenceManager = preferenceManager;
|
||||
this.sharedPool = sharedPool;
|
||||
|
|
@ -168,7 +160,7 @@ public class KubernetesNamespaceFactory {
|
|||
@VisibleForTesting
|
||||
KubernetesNamespace doCreateNamespaceAccess(String workspaceId, String name) {
|
||||
return new KubernetesNamespace(
|
||||
clientFactory, cheClientFactory, sharedPool.getExecutor(), name, workspaceId);
|
||||
cheServerKubernetesClientFactory, sharedPool.getExecutor(), name, workspaceId);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -241,7 +233,8 @@ public class KubernetesNamespaceFactory {
|
|||
public Optional<KubernetesNamespaceMeta> fetchNamespace(String name)
|
||||
throws InfrastructureException {
|
||||
try {
|
||||
Namespace namespace = cheClientFactory.create().namespaces().withName(name).get();
|
||||
Namespace namespace =
|
||||
cheServerKubernetesClientFactory.create().namespaces().withName(name).get();
|
||||
if (namespace == null) {
|
||||
return Optional.empty();
|
||||
} else {
|
||||
|
|
@ -501,7 +494,12 @@ public class KubernetesNamespaceFactory {
|
|||
NamespaceResolutionContext namespaceCtx) throws InfrastructureException {
|
||||
try {
|
||||
List<Namespace> workspaceNamespaces =
|
||||
cheClientFactory.create().namespaces().withLabels(namespaceLabels).list().getItems();
|
||||
cheServerKubernetesClientFactory
|
||||
.create()
|
||||
.namespaces()
|
||||
.withLabels(namespaceLabels)
|
||||
.list()
|
||||
.getItems();
|
||||
if (!workspaceNamespaces.isEmpty()) {
|
||||
Map<String, String> evaluatedAnnotations = evaluateAnnotationPlaceholders(namespaceCtx);
|
||||
return workspaceNamespaces.stream()
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2012-2021 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/
|
||||
|
|
@ -22,7 +22,7 @@ import io.fabric8.kubernetes.api.model.LabelSelector;
|
|||
import io.fabric8.kubernetes.api.model.ObjectMeta;
|
||||
import io.fabric8.kubernetes.api.model.PersistentVolumeClaim;
|
||||
import io.fabric8.kubernetes.api.model.PersistentVolumeClaimBuilder;
|
||||
import io.fabric8.kubernetes.api.model.PersistentVolumeClaimFluent.SpecNested;
|
||||
import io.fabric8.kubernetes.api.model.PersistentVolumeClaimFluent;
|
||||
import io.fabric8.kubernetes.api.model.PersistentVolumeClaimVolumeSource;
|
||||
import io.fabric8.kubernetes.api.model.PersistentVolumeClaimVolumeSourceBuilder;
|
||||
import io.fabric8.kubernetes.api.model.Quantity;
|
||||
|
|
@ -199,13 +199,15 @@ public class KubernetesObjectUtil {
|
|||
*/
|
||||
public static PersistentVolumeClaim newPVC(
|
||||
String name, String accessMode, String quantity, String storageClassName) {
|
||||
SpecNested<PersistentVolumeClaimBuilder> specs =
|
||||
new PersistentVolumeClaimBuilder()
|
||||
.withNewMetadata()
|
||||
.withName(name)
|
||||
.endMetadata()
|
||||
.withNewSpec()
|
||||
.withAccessModes(accessMode);
|
||||
PersistentVolumeClaimFluent<PersistentVolumeClaimBuilder>.SpecNested<
|
||||
PersistentVolumeClaimBuilder>
|
||||
specs =
|
||||
new PersistentVolumeClaimBuilder()
|
||||
.withNewMetadata()
|
||||
.withName(name)
|
||||
.endMetadata()
|
||||
.withNewSpec()
|
||||
.withAccessModes(accessMode);
|
||||
if (!isNullOrEmpty(storageClassName)) {
|
||||
specs.withStorageClassName(storageClassName);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2012-2021 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/
|
||||
|
|
@ -11,15 +11,20 @@
|
|||
*/
|
||||
package org.eclipse.che.workspace.infrastructure.kubernetes.namespace.configurator;
|
||||
|
||||
import static org.eclipse.che.workspace.infrastructure.kubernetes.namespace.AbstractWorkspaceServiceAccount.CREDENTIALS_SECRET_NAME;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import io.fabric8.kubernetes.api.model.Secret;
|
||||
import io.fabric8.kubernetes.api.model.SecretBuilder;
|
||||
import java.util.Base64;
|
||||
import java.util.Map;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
import org.eclipse.che.api.factory.server.scm.PersonalAccessTokenManager;
|
||||
import org.eclipse.che.api.factory.server.scm.exception.ScmCommunicationException;
|
||||
import org.eclipse.che.api.factory.server.scm.exception.ScmConfigurationPersistenceException;
|
||||
import org.eclipse.che.api.factory.server.scm.exception.ScmUnauthorizedException;
|
||||
import org.eclipse.che.api.factory.server.scm.exception.UnsatisfiedScmPreconditionException;
|
||||
import org.eclipse.che.api.workspace.server.spi.InfrastructureException;
|
||||
import org.eclipse.che.api.workspace.server.spi.NamespaceResolutionContext;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.KubernetesClientFactory;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.CheServerKubernetesClientFactory;
|
||||
|
||||
/**
|
||||
* This {@link NamespaceConfigurator} ensures that Secret {@link
|
||||
|
|
@ -29,27 +34,57 @@ import org.eclipse.che.workspace.infrastructure.kubernetes.KubernetesClientFacto
|
|||
@Singleton
|
||||
public class CredentialsSecretConfigurator implements NamespaceConfigurator {
|
||||
|
||||
private final KubernetesClientFactory clientFactory;
|
||||
private final CheServerKubernetesClientFactory cheServerKubernetesClientFactory;
|
||||
private final PersonalAccessTokenManager personalAccessTokenManager;
|
||||
|
||||
private static final Map<String, String> SEARCH_LABELS =
|
||||
ImmutableMap.of(
|
||||
"app.kubernetes.io/part-of", "che.eclipse.org",
|
||||
"app.kubernetes.io/component", "scm-personal-access-token");
|
||||
private static final String ANNOTATION_SCM_URL = "che.eclipse.org/scm-url";
|
||||
private static final String MERGED_GIT_CREDENTIALS_SECRET_NAME =
|
||||
"devworkspace-merged-git-credentials";
|
||||
|
||||
@Inject
|
||||
public CredentialsSecretConfigurator(KubernetesClientFactory clientFactory) {
|
||||
this.clientFactory = clientFactory;
|
||||
public CredentialsSecretConfigurator(
|
||||
CheServerKubernetesClientFactory cheServerKubernetesClientFactory,
|
||||
PersonalAccessTokenManager personalAccessTokenManager) {
|
||||
this.cheServerKubernetesClientFactory = cheServerKubernetesClientFactory;
|
||||
this.personalAccessTokenManager = personalAccessTokenManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configure(NamespaceResolutionContext namespaceResolutionContext, String namespaceName)
|
||||
throws InfrastructureException {
|
||||
var client = clientFactory.create();
|
||||
if (client.secrets().inNamespace(namespaceName).withName(CREDENTIALS_SECRET_NAME).get()
|
||||
== null) {
|
||||
Secret secret =
|
||||
new SecretBuilder()
|
||||
.withType("opaque")
|
||||
.withNewMetadata()
|
||||
.withName(CREDENTIALS_SECRET_NAME)
|
||||
.endMetadata()
|
||||
.build();
|
||||
client.secrets().inNamespace(namespaceName).create(secret);
|
||||
}
|
||||
var client = cheServerKubernetesClientFactory.create();
|
||||
Secret mergedCredentialsSecret =
|
||||
client
|
||||
.secrets()
|
||||
.inNamespace(namespaceName)
|
||||
.withName(MERGED_GIT_CREDENTIALS_SECRET_NAME)
|
||||
.get();
|
||||
|
||||
client.secrets().inNamespace(namespaceName).withLabels(SEARCH_LABELS).list().getItems().stream()
|
||||
.filter(
|
||||
s ->
|
||||
mergedCredentialsSecret == null
|
||||
|| !getSecretData(mergedCredentialsSecret, "credentials")
|
||||
.contains(getSecretData(s, "token")))
|
||||
.forEach(
|
||||
s -> {
|
||||
try {
|
||||
personalAccessTokenManager.store(
|
||||
s.getMetadata().getAnnotations().get(ANNOTATION_SCM_URL));
|
||||
} catch (ScmCommunicationException
|
||||
| ScmConfigurationPersistenceException
|
||||
| UnsatisfiedScmPreconditionException
|
||||
| ScmUnauthorizedException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private String getSecretData(Secret secret, String key) {
|
||||
return new String(Base64.getDecoder().decode(secret.getData().get(key).getBytes()));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,42 +22,41 @@ import java.util.Set;
|
|||
import javax.inject.Inject;
|
||||
import org.eclipse.che.api.factory.server.scm.GitUserData;
|
||||
import org.eclipse.che.api.factory.server.scm.GitUserDataFetcher;
|
||||
import org.eclipse.che.api.factory.server.scm.exception.ScmCommunicationException;
|
||||
import org.eclipse.che.api.factory.server.scm.exception.ScmUnauthorizedException;
|
||||
import org.eclipse.che.api.user.server.UserManager;
|
||||
import org.eclipse.che.api.factory.server.scm.exception.*;
|
||||
import org.eclipse.che.api.workspace.server.spi.InfrastructureException;
|
||||
import org.eclipse.che.api.workspace.server.spi.NamespaceResolutionContext;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.KubernetesClientFactory;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.CheServerKubernetesClientFactory;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class GitconfigUserDataConfigurator implements NamespaceConfigurator {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(GitconfigUserDataConfigurator.class);
|
||||
private final KubernetesClientFactory clientFactory;
|
||||
private final CheServerKubernetesClientFactory cheServerKubernetesClientFactory;
|
||||
private final Set<GitUserDataFetcher> gitUserDataFetchers;
|
||||
private static final String CONFIGMAP_DATA_KEY = "gitconfig";
|
||||
private final UserManager userManager;
|
||||
|
||||
@Inject
|
||||
public GitconfigUserDataConfigurator(
|
||||
KubernetesClientFactory clientFactory,
|
||||
Set<GitUserDataFetcher> gitUserDataFetchers,
|
||||
UserManager userManager) {
|
||||
this.clientFactory = clientFactory;
|
||||
CheServerKubernetesClientFactory cheServerKubernetesClientFactory,
|
||||
Set<GitUserDataFetcher> gitUserDataFetchers) {
|
||||
this.cheServerKubernetesClientFactory = cheServerKubernetesClientFactory;
|
||||
this.gitUserDataFetchers = gitUserDataFetchers;
|
||||
this.userManager = userManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configure(NamespaceResolutionContext namespaceResolutionContext, String namespaceName)
|
||||
throws InfrastructureException {
|
||||
var client = clientFactory.create();
|
||||
var client = cheServerKubernetesClientFactory.create();
|
||||
GitUserData gitUserData = null;
|
||||
for (GitUserDataFetcher fetcher : gitUserDataFetchers) {
|
||||
try {
|
||||
gitUserData = fetcher.fetchGitUserData();
|
||||
break;
|
||||
} catch (ScmUnauthorizedException | ScmCommunicationException e) {
|
||||
} catch (ScmUnauthorizedException
|
||||
| ScmCommunicationException
|
||||
| ScmConfigurationPersistenceException
|
||||
| ScmItemNotFoundException
|
||||
| ScmBadRequestException e) {
|
||||
LOG.debug("No GitUserDataFetcher is configured. " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2012-2021 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/
|
||||
|
|
@ -18,7 +18,7 @@ import io.fabric8.kubernetes.api.model.ConfigMapBuilder;
|
|||
import javax.inject.Inject;
|
||||
import org.eclipse.che.api.workspace.server.spi.InfrastructureException;
|
||||
import org.eclipse.che.api.workspace.server.spi.NamespaceResolutionContext;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.KubernetesClientFactory;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.CheServerKubernetesClientFactory;
|
||||
|
||||
/**
|
||||
* This {@link NamespaceConfigurator} ensures that ConfigMap {@link
|
||||
|
|
@ -27,17 +27,18 @@ import org.eclipse.che.workspace.infrastructure.kubernetes.KubernetesClientFacto
|
|||
*/
|
||||
public class PreferencesConfigMapConfigurator implements NamespaceConfigurator {
|
||||
|
||||
private final KubernetesClientFactory clientFactory;
|
||||
private final CheServerKubernetesClientFactory cheServerKubernetesClientFactory;
|
||||
|
||||
@Inject
|
||||
public PreferencesConfigMapConfigurator(KubernetesClientFactory clientFactory) {
|
||||
this.clientFactory = clientFactory;
|
||||
public PreferencesConfigMapConfigurator(
|
||||
CheServerKubernetesClientFactory cheServerKubernetesClientFactory) {
|
||||
this.cheServerKubernetesClientFactory = cheServerKubernetesClientFactory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configure(NamespaceResolutionContext namespaceResolutionContext, String namespaceName)
|
||||
throws InfrastructureException {
|
||||
var client = clientFactory.create();
|
||||
var client = cheServerKubernetesClientFactory.create();
|
||||
if (client.configMaps().inNamespace(namespaceName).withName(PREFERENCES_CONFIGMAP_NAME).get()
|
||||
== null) {
|
||||
ConfigMap configMap =
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ import org.eclipse.che.api.ssh.server.model.impl.SshPairImpl;
|
|||
import org.eclipse.che.api.ssh.shared.model.SshPair;
|
||||
import org.eclipse.che.api.workspace.server.spi.InfrastructureException;
|
||||
import org.eclipse.che.api.workspace.server.spi.NamespaceResolutionContext;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.KubernetesClientFactory;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.CheServerKubernetesClientFactory;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
|
|
@ -55,7 +55,7 @@ public class SshKeysConfigurator implements NamespaceConfigurator {
|
|||
|
||||
private final SshManager sshManager;
|
||||
|
||||
private final KubernetesClientFactory clientFactory;
|
||||
private final CheServerKubernetesClientFactory cheServerKubernetesClientFactory;
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(SshKeysConfigurator.class);
|
||||
|
||||
|
|
@ -63,16 +63,17 @@ public class SshKeysConfigurator implements NamespaceConfigurator {
|
|||
Pattern.compile("^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$");
|
||||
|
||||
@Inject
|
||||
public SshKeysConfigurator(SshManager sshManager, KubernetesClientFactory clientFactory) {
|
||||
public SshKeysConfigurator(
|
||||
SshManager sshManager, CheServerKubernetesClientFactory cheServerKubernetesClientFactory) {
|
||||
this.sshManager = sshManager;
|
||||
this.clientFactory = clientFactory;
|
||||
this.cheServerKubernetesClientFactory = cheServerKubernetesClientFactory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configure(NamespaceResolutionContext namespaceResolutionContext, String namespaceName)
|
||||
throws InfrastructureException {
|
||||
|
||||
var client = clientFactory.create();
|
||||
var client = cheServerKubernetesClientFactory.create();
|
||||
List<SshPairImpl> vcsSshPairs = getVcsSshPairs(namespaceResolutionContext);
|
||||
|
||||
List<String> invalidSshKeyNames =
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2012-2021 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,7 +26,6 @@ import org.eclipse.che.api.workspace.server.spi.InfrastructureException;
|
|||
import org.eclipse.che.api.workspace.server.spi.NamespaceResolutionContext;
|
||||
import org.eclipse.che.commons.annotation.Nullable;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.CheServerKubernetesClientFactory;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.KubernetesClientFactory;
|
||||
|
||||
/**
|
||||
* This {@link NamespaceConfigurator} ensures that User has assigned configured ClusterRoles from
|
||||
|
|
@ -37,13 +36,13 @@ import org.eclipse.che.workspace.infrastructure.kubernetes.KubernetesClientFacto
|
|||
public class UserPermissionConfigurator implements NamespaceConfigurator {
|
||||
|
||||
private final Set<String> userClusterRoles;
|
||||
private final KubernetesClientFactory clientFactory;
|
||||
private final CheServerKubernetesClientFactory cheServerKubernetesClientFactory;
|
||||
|
||||
@Inject
|
||||
public UserPermissionConfigurator(
|
||||
@Nullable @Named("che.infra.kubernetes.user_cluster_roles") String userClusterRoles,
|
||||
CheServerKubernetesClientFactory cheClientFactory) {
|
||||
this.clientFactory = cheClientFactory;
|
||||
CheServerKubernetesClientFactory cheServerKubernetesClientFactory) {
|
||||
this.cheServerKubernetesClientFactory = cheServerKubernetesClientFactory;
|
||||
if (!isNullOrEmpty(userClusterRoles)) {
|
||||
this.userClusterRoles =
|
||||
Sets.newHashSet(
|
||||
|
|
@ -58,7 +57,7 @@ public class UserPermissionConfigurator implements NamespaceConfigurator {
|
|||
throws InfrastructureException {
|
||||
if (!userClusterRoles.isEmpty()) {
|
||||
bindRoles(
|
||||
clientFactory.create(),
|
||||
cheServerKubernetesClientFactory.create(),
|
||||
namespaceName,
|
||||
namespaceResolutionContext.getUserName(),
|
||||
userClusterRoles);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2012-2022 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/
|
||||
|
|
@ -15,10 +15,7 @@ import com.google.common.annotations.VisibleForTesting;
|
|||
import io.fabric8.kubernetes.api.model.Secret;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
import org.eclipse.che.api.user.server.PreferenceManager;
|
||||
import org.eclipse.che.api.user.server.UserManager;
|
||||
import org.eclipse.che.api.workspace.server.spi.NamespaceResolutionContext;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.KubernetesClientFactory;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
|
|
@ -36,19 +33,8 @@ public class UserPreferencesConfigurator implements NamespaceConfigurator {
|
|||
private static final String USER_PREFERENCES_SECRET_MOUNT_PATH = "/config/user/preferences";
|
||||
private static final int PREFERENCE_NAME_MAX_LENGTH = 253;
|
||||
|
||||
private final KubernetesClientFactory clientFactory;
|
||||
private final UserManager userManager;
|
||||
private final PreferenceManager preferenceManager;
|
||||
|
||||
@Inject
|
||||
public UserPreferencesConfigurator(
|
||||
KubernetesClientFactory clientFactory,
|
||||
UserManager userManager,
|
||||
PreferenceManager preferenceManager) {
|
||||
this.clientFactory = clientFactory;
|
||||
this.userManager = userManager;
|
||||
this.preferenceManager = preferenceManager;
|
||||
}
|
||||
public UserPreferencesConfigurator() {}
|
||||
|
||||
@Override
|
||||
public void configure(
|
||||
|
|
|
|||
|
|
@ -24,10 +24,9 @@ import java.util.HashMap;
|
|||
import java.util.Map;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
import org.eclipse.che.api.user.server.UserManager;
|
||||
import org.eclipse.che.api.workspace.server.spi.InfrastructureException;
|
||||
import org.eclipse.che.api.workspace.server.spi.NamespaceResolutionContext;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.KubernetesClientFactory;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.CheServerKubernetesClientFactory;
|
||||
|
||||
/**
|
||||
* Creates {@link Secret} with user profile information such as his id, name and email. This serves
|
||||
|
|
@ -40,13 +39,12 @@ public class UserProfileConfigurator implements NamespaceConfigurator {
|
|||
private static final String USER_PROFILE_SECRET_NAME = "user-profile";
|
||||
private static final String USER_PROFILE_SECRET_MOUNT_PATH = "/config/user/profile";
|
||||
|
||||
private final KubernetesClientFactory clientFactory;
|
||||
private final UserManager userManager;
|
||||
private final CheServerKubernetesClientFactory cheServerKubernetesClientFactory;
|
||||
|
||||
@Inject
|
||||
public UserProfileConfigurator(KubernetesClientFactory clientFactory, UserManager userManager) {
|
||||
this.clientFactory = clientFactory;
|
||||
this.userManager = userManager;
|
||||
public UserProfileConfigurator(
|
||||
CheServerKubernetesClientFactory cheServerKubernetesClientFactory) {
|
||||
this.cheServerKubernetesClientFactory = cheServerKubernetesClientFactory;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -54,7 +52,7 @@ public class UserProfileConfigurator implements NamespaceConfigurator {
|
|||
throws InfrastructureException {
|
||||
Secret userProfileSecret = prepareProfileSecret(namespaceResolutionContext);
|
||||
try {
|
||||
clientFactory
|
||||
cheServerKubernetesClientFactory
|
||||
.create()
|
||||
.secrets()
|
||||
.inNamespace(namespaceName)
|
||||
|
|
@ -83,6 +81,7 @@ public class UserProfileConfigurator implements NamespaceConfigurator {
|
|||
.withName(USER_PROFILE_SECRET_NAME)
|
||||
.addToLabels(DEV_WORKSPACE_MOUNT_LABEL, "true")
|
||||
.addToLabels(DEV_WORKSPACE_WATCH_SECRET_LABEL, "true")
|
||||
.addToLabels("app.kubernetes.io/part-of", "che.eclipse.org")
|
||||
.addToAnnotations(DEV_WORKSPACE_MOUNT_AS_ANNOTATION, "file")
|
||||
.addToAnnotations(DEV_WORKSPACE_MOUNT_PATH_ANNOTATION, USER_PROFILE_SECRET_MOUNT_PATH)
|
||||
.endMetadata()
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2012-2021 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/
|
||||
|
|
@ -24,7 +24,7 @@ import javax.inject.Singleton;
|
|||
import org.eclipse.che.api.workspace.server.spi.InfrastructureException;
|
||||
import org.eclipse.che.api.workspace.server.spi.NamespaceResolutionContext;
|
||||
import org.eclipse.che.commons.annotation.Nullable;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.KubernetesClientFactory;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.CheServerKubernetesClientFactory;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.namespace.KubernetesWorkspaceServiceAccount;
|
||||
|
||||
/**
|
||||
|
|
@ -34,7 +34,7 @@ import org.eclipse.che.workspace.infrastructure.kubernetes.namespace.KubernetesW
|
|||
@Singleton
|
||||
public class WorkspaceServiceAccountConfigurator implements NamespaceConfigurator {
|
||||
|
||||
private final KubernetesClientFactory clientFactory;
|
||||
private final CheServerKubernetesClientFactory cheServerKubernetesClientFactory;
|
||||
|
||||
private final String serviceAccountName;
|
||||
private final Set<String> clusterRoleNames;
|
||||
|
|
@ -43,8 +43,8 @@ public class WorkspaceServiceAccountConfigurator implements NamespaceConfigurato
|
|||
public WorkspaceServiceAccountConfigurator(
|
||||
@Nullable @Named("che.infra.kubernetes.service_account_name") String serviceAccountName,
|
||||
@Nullable @Named("che.infra.kubernetes.workspace_sa_cluster_roles") String clusterRoleNames,
|
||||
KubernetesClientFactory clientFactory) {
|
||||
this.clientFactory = clientFactory;
|
||||
CheServerKubernetesClientFactory cheServerKubernetesClientFactory) {
|
||||
this.cheServerKubernetesClientFactory = cheServerKubernetesClientFactory;
|
||||
this.serviceAccountName = serviceAccountName;
|
||||
if (!isNullOrEmpty(clusterRoleNames)) {
|
||||
this.clusterRoleNames =
|
||||
|
|
@ -69,6 +69,10 @@ public class WorkspaceServiceAccountConfigurator implements NamespaceConfigurato
|
|||
public KubernetesWorkspaceServiceAccount doCreateServiceAccount(
|
||||
String workspaceId, String namespaceName) {
|
||||
return new KubernetesWorkspaceServiceAccount(
|
||||
workspaceId, namespaceName, serviceAccountName, clusterRoleNames, clientFactory);
|
||||
workspaceId,
|
||||
namespaceName,
|
||||
serviceAccountName,
|
||||
clusterRoleNames,
|
||||
cheServerKubernetesClientFactory);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,14 +12,11 @@
|
|||
package org.eclipse.che.workspace.infrastructure.kubernetes;
|
||||
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import io.fabric8.kubernetes.client.Config;
|
||||
import java.util.Collections;
|
||||
import org.eclipse.che.api.core.notification.EventService;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.cache.KubernetesRuntimeStateCache;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.namespace.KubernetesNamespaceFactory;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.testng.MockitoTestNGListener;
|
||||
import org.testng.annotations.BeforeMethod;
|
||||
import org.testng.annotations.Listeners;
|
||||
|
|
@ -27,7 +24,6 @@ import org.testng.annotations.Listeners;
|
|||
@Listeners(MockitoTestNGListener.class)
|
||||
public class KubernetesInfrastructureTest {
|
||||
|
||||
@Mock private KubernetesClientFactory factory;
|
||||
private KubernetesInfrastructure infra;
|
||||
|
||||
@BeforeMethod
|
||||
|
|
@ -38,9 +34,6 @@ public class KubernetesInfrastructureTest {
|
|||
mock(KubernetesRuntimeContextFactory.class),
|
||||
Collections.emptySet(),
|
||||
mock(KubernetesRuntimeStateCache.class),
|
||||
mock(KubernetesNamespaceFactory.class),
|
||||
factory);
|
||||
|
||||
when(factory.getDefaultConfig()).thenReturn(mock(Config.class));
|
||||
mock(KubernetesNamespaceFactory.class));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -843,7 +843,7 @@ public class KubernetesInternalRuntimeTest {
|
|||
}
|
||||
|
||||
private static IntOrString intOrString(int port) {
|
||||
return new IntOrStringBuilder().withIntVal(port).withStrVal(String.valueOf(port)).build();
|
||||
return new IntOrStringBuilder().withValue(port).withValue(String.valueOf(port)).build();
|
||||
}
|
||||
|
||||
private static class MapBasedRuntimeStateCache implements KubernetesRuntimeStateCache {
|
||||
|
|
|
|||
|
|
@ -25,8 +25,8 @@ import com.google.common.collect.ImmutableMap;
|
|||
import io.fabric8.kubernetes.api.model.ConfigMap;
|
||||
import io.fabric8.kubernetes.api.model.ConfigMapBuilder;
|
||||
import io.fabric8.kubernetes.api.model.ConfigMapList;
|
||||
import io.fabric8.kubernetes.client.GracePeriodConfigurable;
|
||||
import io.fabric8.kubernetes.client.KubernetesClient;
|
||||
import io.fabric8.kubernetes.client.dsl.EditReplacePatchDeletable;
|
||||
import io.fabric8.kubernetes.client.dsl.MixedOperation;
|
||||
import io.fabric8.kubernetes.client.dsl.Resource;
|
||||
import java.util.Arrays;
|
||||
|
|
@ -70,7 +70,7 @@ public class CheNamespaceTest {
|
|||
@Mock
|
||||
private MixedOperation<ConfigMap, ConfigMapList, Resource<ConfigMap>> kubeConfigMapsWithLabel;
|
||||
|
||||
@Mock private EditReplacePatchDeletable<ConfigMap> kubeConfigMapsWithPropagationPolicy;
|
||||
@Mock private GracePeriodConfigurable gracePeriodConfigurable;
|
||||
|
||||
@Mock private InternalRuntime internalRuntime;
|
||||
|
||||
|
|
@ -237,12 +237,12 @@ public class CheNamespaceTest {
|
|||
when(kubeConfigMapsInNamespace.withLabel(CHE_WORKSPACE_ID_LABEL, WORKSPACE_ID))
|
||||
.thenReturn(kubeConfigMapsWithLabel);
|
||||
when(kubeConfigMapsWithLabel.withPropagationPolicy(BACKGROUND))
|
||||
.thenReturn(kubeConfigMapsWithPropagationPolicy);
|
||||
.thenReturn(gracePeriodConfigurable);
|
||||
|
||||
// when
|
||||
cheNamespace.cleanUp(WORKSPACE_ID);
|
||||
|
||||
// then
|
||||
verify(kubeConfigMapsWithPropagationPolicy).delete();
|
||||
verify(gracePeriodConfigurable).delete();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ package org.eclipse.che.workspace.infrastructure.kubernetes.namespace;
|
|||
|
||||
import static io.fabric8.kubernetes.api.model.DeletionPropagation.BACKGROUND;
|
||||
import static java.util.Arrays.asList;
|
||||
import static java.util.Collections.emptyList;
|
||||
import static java.util.Collections.singletonList;
|
||||
import static org.eclipse.che.workspace.infrastructure.kubernetes.Constants.POD_STATUS_PHASE_FAILED;
|
||||
import static org.eclipse.che.workspace.infrastructure.kubernetes.Constants.POD_STATUS_PHASE_RUNNING;
|
||||
|
|
@ -55,12 +56,12 @@ import io.fabric8.kubernetes.api.model.apps.DeploymentBuilder;
|
|||
import io.fabric8.kubernetes.api.model.apps.DeploymentList;
|
||||
import io.fabric8.kubernetes.api.model.apps.DeploymentSpec;
|
||||
import io.fabric8.kubernetes.api.model.apps.DeploymentSpecBuilder;
|
||||
import io.fabric8.kubernetes.client.GracePeriodConfigurable;
|
||||
import io.fabric8.kubernetes.client.KubernetesClient;
|
||||
import io.fabric8.kubernetes.client.KubernetesClientException;
|
||||
import io.fabric8.kubernetes.client.Watch;
|
||||
import io.fabric8.kubernetes.client.Watcher;
|
||||
import io.fabric8.kubernetes.client.dsl.AppsAPIGroupDSL;
|
||||
import io.fabric8.kubernetes.client.dsl.EditReplacePatchDeletable;
|
||||
import io.fabric8.kubernetes.client.dsl.FilterWatchListDeletable;
|
||||
import io.fabric8.kubernetes.client.dsl.MixedOperation;
|
||||
import io.fabric8.kubernetes.client.dsl.NonNamespaceOperation;
|
||||
|
|
@ -119,12 +120,12 @@ public class KubernetesDeploymentsTest {
|
|||
@Mock private Deployment deployment;
|
||||
@Mock private ObjectMeta deploymentMetadata;
|
||||
@Mock private DeploymentSpec deploymentSpec;
|
||||
@Mock private EditReplacePatchDeletable<Deployment> deploymentEditReplacePatchDeletable;
|
||||
@Mock private GracePeriodConfigurable gracePeriodConfigurable;
|
||||
|
||||
// Pod Mocks
|
||||
@Mock private Pod pod;
|
||||
@Mock private PodStatus status;
|
||||
@Mock private PodResource<Pod> podResource;
|
||||
@Mock private PodResource podResource;
|
||||
@Mock private ObjectMeta metadata;
|
||||
@Mock private MixedOperation podsMixedOperation;
|
||||
@Mock private NonNamespaceOperation podsNamespaceOperation;
|
||||
|
|
@ -491,7 +492,7 @@ public class KubernetesDeploymentsTest {
|
|||
public void testDeleteNonExistingPodBeforeWatch() throws Exception {
|
||||
final String POD_NAME = "nonExistingPod";
|
||||
|
||||
doReturn(Boolean.FALSE).when(podResource).delete();
|
||||
doReturn(emptyList()).when(podResource).delete();
|
||||
doReturn(podResource).when(podResource).withPropagationPolicy(eq(BACKGROUND));
|
||||
Watch watch = mock(Watch.class);
|
||||
doReturn(watch).when(podResource).watch(any());
|
||||
|
|
@ -527,7 +528,7 @@ public class KubernetesDeploymentsTest {
|
|||
public void testDeleteNonExistingDeploymentBeforeWatch() throws Exception {
|
||||
final String DEPLOYMENT_NAME = "nonExistingPod";
|
||||
doReturn(deploymentResource).when(deploymentResource).withPropagationPolicy(eq(BACKGROUND));
|
||||
doReturn(Boolean.FALSE).when(deploymentResource).delete();
|
||||
doReturn(emptyList()).when(deploymentResource).delete();
|
||||
Watch watch = mock(Watch.class);
|
||||
doReturn(watch).when(podResource).watch(any());
|
||||
|
||||
|
|
@ -587,9 +588,9 @@ public class KubernetesDeploymentsTest {
|
|||
public void testDeleteDeploymentThrowingAnyExceptionShouldCloseWatch() throws Exception {
|
||||
final String DEPLOYMENT_NAME = "nonExistingPod";
|
||||
when(deploymentResource.withPropagationPolicy(eq(BACKGROUND)))
|
||||
.thenReturn(deploymentEditReplacePatchDeletable);
|
||||
.thenReturn(gracePeriodConfigurable);
|
||||
doThrow(new RuntimeException("testDeleteDeploymentThrowingAnyExceptionShouldCloseWatch msg"))
|
||||
.when(deploymentEditReplacePatchDeletable)
|
||||
.when(gracePeriodConfigurable)
|
||||
.delete();
|
||||
Watch watch = mock(Watch.class);
|
||||
doReturn(watch).when(podResource).watch(any());
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue