feat: CheCluster API v2 (#1324)
* feat: CheCluster API v2 Signed-off-by: Anatolii Bazko <abazko@redhat.com>pull/1399/head
parent
af9c29d7cc
commit
0bc1049017
|
|
@ -15,7 +15,7 @@ set -e
|
|||
set -x
|
||||
|
||||
export OPERATOR_REPO=$(dirname $(dirname $(readlink -f "$0")));
|
||||
source "${OPERATOR_REPO}"/.github/bin/common.sh
|
||||
source "${OPERATOR_REPO}/.github/bin/common.sh"
|
||||
|
||||
#Stop execution on any error
|
||||
trap "catchFinish" EXIT SIGINT
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ set -x
|
|||
export CHE_REPO_BRANCH="main"
|
||||
|
||||
export OPERATOR_REPO=$(dirname $(dirname $(readlink -f "$0")));
|
||||
source "${OPERATOR_REPO}"/.github/bin/common.sh
|
||||
source "${OPERATOR_REPO}/.github/bin/common.sh"
|
||||
source <(curl -s https://raw.githubusercontent.com/eclipse/che/${CHE_REPO_BRANCH}/tests/devworkspace-happy-path/common.sh)
|
||||
|
||||
#Stop execution on any error
|
||||
|
|
@ -29,7 +29,7 @@ overrideDefaults() {
|
|||
}
|
||||
|
||||
deployChe() {
|
||||
deployEclipseCheOnWithOperator "chectl" "openshift" ${CURRENT_OPERATOR_VERSION_TEMPLATE_PATH} "true"
|
||||
deployEclipseCheWithOperator "chectl" "openshift" ${CURRENT_OPERATOR_VERSION_TEMPLATE_PATH} "true"
|
||||
}
|
||||
|
||||
initDefaults
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ set -o pipefail
|
|||
set -u
|
||||
|
||||
export OPERATOR_REPO=$(dirname $(dirname $(readlink -f "$0")));
|
||||
source "${OPERATOR_REPO}"/.github/bin/common.sh
|
||||
source "${OPERATOR_REPO}/.github/bin/common.sh"
|
||||
|
||||
# Define Disconnected tests environment
|
||||
export INTERNAL_REGISTRY_URL=${INTERNAL_REGISTRY_URL-"UNDEFINED"}
|
||||
|
|
|
|||
|
|
@ -20,8 +20,7 @@ set -e
|
|||
set -x
|
||||
|
||||
export OPERATOR_REPO=$(dirname $(dirname $(readlink -f "$0")));
|
||||
source "${OPERATOR_REPO}"/olm/olm.sh
|
||||
source "${OPERATOR_REPO}"/.github/bin/common.sh
|
||||
source "${OPERATOR_REPO}/.github/bin/common.sh"
|
||||
|
||||
#Stop execution on any error
|
||||
trap "catchFinish" EXIT SIGINT
|
||||
|
|
@ -33,7 +32,7 @@ overrideDefaults() {
|
|||
|
||||
runTests() {
|
||||
deployDevWorkspaceOperator "stable"
|
||||
deployEclipseCheOnWithOperator "chectl" "openshift" ${LAST_OPERATOR_VERSION_TEMPLATE_PATH} "false"
|
||||
deployEclipseCheWithOperator "chectl" "openshift" ${LAST_OPERATOR_VERSION_TEMPLATE_PATH} "false"
|
||||
updateEclipseChe "chectl" "openshift" ${CURRENT_OPERATOR_VERSION_TEMPLATE_PATH} "true"
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ set -o pipefail
|
|||
set -u
|
||||
|
||||
export OPERATOR_REPO=$(dirname $(dirname $(readlink -f "$0")));
|
||||
source "${OPERATOR_REPO}"/.github/bin/common.sh
|
||||
source "${OPERATOR_REPO}/.github/bin/common.sh"
|
||||
|
||||
#Stop execution on any error
|
||||
trap "catchFinish" EXIT SIGINT
|
||||
|
|
@ -29,7 +29,7 @@ overrideDefaults() {
|
|||
}
|
||||
|
||||
runTests() {
|
||||
deployEclipseCheOnWithOperator "chectl" "openshift" ${CURRENT_OPERATOR_VERSION_TEMPLATE_PATH} "true"
|
||||
deployEclipseCheWithOperator "chectl" "openshift" ${CURRENT_OPERATOR_VERSION_TEMPLATE_PATH} "true"
|
||||
}
|
||||
|
||||
initDefaults
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ set -e
|
|||
set -x
|
||||
|
||||
export OPERATOR_REPO=$(dirname $(dirname $(readlink -f "$0")));
|
||||
source "${OPERATOR_REPO}"/.github/bin/common.sh
|
||||
source "${OPERATOR_REPO}/.github/bin/common.sh"
|
||||
|
||||
#Stop execution on any error
|
||||
trap "catchFinish" EXIT SIGINT
|
||||
|
|
@ -31,12 +31,12 @@ overrideDefaults() {
|
|||
}
|
||||
|
||||
runTests() {
|
||||
createNamespace ${NAMESPACE}
|
||||
createNamespace "${NAMESPACE}"
|
||||
|
||||
useCustomOperatorImageInCSV ${OPERATOR_IMAGE}
|
||||
useCustomOperatorImageInCSV "${OPERATOR_IMAGE}"
|
||||
|
||||
echo "$(getCheClusterCRFromExistedCSV)" | oc apply -n "${NAMESPACE}" -f -
|
||||
waitEclipseCheDeployed $(getCheVersionFromExistedCSV)
|
||||
getCheClusterCRFromExistedCSV | oc apply -n "${NAMESPACE}" -f -
|
||||
waitEclipseCheDeployed "$(getCheVersionFromExistedCSV)"
|
||||
|
||||
waitDevWorkspaceControllerStarted
|
||||
}
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ compareVersions() {
|
|||
|
||||
if (( $VERSION_NEW_NUMBER <= $VERSION_CURRENT_NUMBER )); then
|
||||
echo "[ERROR] New next bundle version is less than the current one."
|
||||
echo "[ERROR] Please update next bundle with script 'make update-resources -s'"
|
||||
echo "[ERROR] Please update next bundle with script 'make update-dev-resources'"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,151 +11,29 @@
|
|||
# Red Hat, Inc. - initial API and implementation
|
||||
#
|
||||
|
||||
# Checks if repository resources are up to date:
|
||||
# - CRDs
|
||||
# - next olm bundle
|
||||
# - Dockerfile & operator.yaml
|
||||
# - DW resources
|
||||
# - Helm charts
|
||||
|
||||
set -e
|
||||
|
||||
ROOT_PROJECT_DIR="${GITHUB_WORKSPACE}"
|
||||
if [ -z "${ROOT_PROJECT_DIR}" ]; then
|
||||
SCRIPT=$(readlink -f "${BASH_SOURCE[0]}")
|
||||
ROOT_PROJECT_DIR=$(dirname $(dirname $(dirname ${SCRIPT})))
|
||||
ROOT_PROJECT_DIR=$(dirname $(dirname $(dirname "${SCRIPT}")))
|
||||
fi
|
||||
|
||||
installOperatorSDK() {
|
||||
OPERATOR_SDK_BINARY=$(command -v operator-sdk) || true
|
||||
if [[ ! -x "${OPERATOR_SDK_BINARY}" ]]; then
|
||||
OPERATOR_SDK_TEMP_DIR="$(mktemp -q -d -t "OPERATOR_SDK_XXXXXX" 2>/dev/null || mktemp -q -d)"
|
||||
|
||||
pushd "${ROOT_PROJECT_DIR}" || exit
|
||||
make download-operator-sdk OP_SDK_DIR="${OPERATOR_SDK_TEMP_DIR}"
|
||||
export OPERATOR_SDK_BINARY="${OPERATOR_SDK_TEMP_DIR}/operator-sdk"
|
||||
popd || exit
|
||||
fi
|
||||
}
|
||||
|
||||
updateResources() {
|
||||
echo "[INFO] Update resources with skipping version incrementation and timestamp..."
|
||||
|
||||
pushd "${ROOT_PROJECT_DIR}" || exit
|
||||
make update-resources NO_DATE_UPDATE="true" NO_INCREMENT="true" -s
|
||||
popd || exit
|
||||
}
|
||||
|
||||
# check_che_types function check first if api/v1/checluster_types.go file suffer modifications and
|
||||
# in case of modification should exist also modifications in config/crd/bases/* folder.
|
||||
checkCRDs() {
|
||||
echo "[INFO] Checking CRDs"
|
||||
|
||||
# files to check
|
||||
local checluster_CRD_V1="config/crd/bases/org_v1_che_crd.yaml"
|
||||
local chebackupserverconfiguration_CRD_V1="config/crd/bases/org.eclipse.che_chebackupserverconfigurations_crd.yaml"
|
||||
local checlusterbackup_CRD_V1="config/crd/bases/org.eclipse.che_checlusterbackups_crd.yaml"
|
||||
local checlusterrestore_CRD_V1="config/crd/bases/org.eclipse.che_checlusterrestores_crd.yaml"
|
||||
|
||||
changedFiles=($(cd ${ROOT_PROJECT_DIR}; git diff --name-only))
|
||||
# Check if there are any difference in the crds. If yes, then fail check.
|
||||
if [[ " ${changedFiles[*]} " =~ $checluster_CRD_V1 ]] || \
|
||||
[[ " ${changedFiles[*]} " =~ $chebackupserverconfiguration_CRD_V1 ]] || \
|
||||
[[ " ${changedFiles[*]} " =~ $checlusterbackup_CRD_V1 ]] || \
|
||||
[[ " ${changedFiles[*]} " =~ $checlusterrestore_CRD_V1 ]]
|
||||
then
|
||||
echo "[ERROR] CRD file is not up to date: ${BASH_REMATCH}"
|
||||
echo "[ERROR] Run 'make update-resources -s' to regenerate CRD files."
|
||||
exit 1
|
||||
else
|
||||
echo "[INFO] CRDs files are up to date."
|
||||
fi
|
||||
}
|
||||
|
||||
checkNextOlmBundle() {
|
||||
# files to check
|
||||
local CSV_OPENSHIFT="bundle/next/eclipse-che-preview-openshift/manifests"
|
||||
|
||||
changedFiles=($(cd ${ROOT_PROJECT_DIR}; git diff --name-only))
|
||||
if [[ " ${changedFiles[*]} " =~ $CSV_OPENSHIFT ]]; then
|
||||
echo "[ERROR] Nighlty bundle is not up to date: ${BASH_REMATCH}"
|
||||
echo "[ERROR] Run 'make update-resources -s' to regenerate next bundle files."
|
||||
exit 1
|
||||
else
|
||||
echo "[INFO] Next bundles are up to date."
|
||||
fi
|
||||
}
|
||||
|
||||
checkDockerfile() {
|
||||
# files to check
|
||||
local Dockerfile="Dockerfile"
|
||||
|
||||
changedFiles=($(cd ${ROOT_PROJECT_DIR}; git diff --name-only))
|
||||
if [[ " ${changedFiles[*]} " =~ $Dockerfile ]]; then
|
||||
echo "[ERROR] Dockerfile is not up to date"
|
||||
echo "[ERROR] Run 'make update-resources -s' to update Dockerfile"
|
||||
exit 1
|
||||
else
|
||||
echo "[INFO] Dockerfile is up to date."
|
||||
fi
|
||||
}
|
||||
|
||||
checkOperatorYaml() {
|
||||
# files to check
|
||||
local managerYaml="config/manager/manager.yaml"
|
||||
|
||||
changedFiles=($(cd ${ROOT_PROJECT_DIR}; git diff --name-only))
|
||||
if [[ " ${changedFiles[*]} " =~ $managerYaml ]]; then
|
||||
echo "[ERROR] $managerYaml is not up to date"
|
||||
echo "[ERROR] Run 'make update-resources -s' to update $managerYaml"
|
||||
exit 1
|
||||
else
|
||||
echo "[INFO] $managerYaml is up to date."
|
||||
fi
|
||||
}
|
||||
|
||||
checkRoles() {
|
||||
# files to check
|
||||
local RoleYaml="config/rbac/role.yaml"
|
||||
local ClusterRoleYaml="config/rbac/cluster_role.yaml"
|
||||
|
||||
changedFiles=(
|
||||
$(git diff --name-only)
|
||||
)
|
||||
if [[ " ${changedFiles[*]} " =~ $RoleYaml ]] || [[ " ${changedFiles[*]} " =~ $ClusterRoleYaml ]]; then
|
||||
echo "[ERROR] Roles are not up to date: ${BASH_REMATCH}"
|
||||
echo "[ERROR] Run 'make update-resources -s' to update them."
|
||||
exit 1
|
||||
else
|
||||
echo "[INFO] Roles are up to date."
|
||||
fi
|
||||
}
|
||||
|
||||
checkHelmCharts() {
|
||||
changedFiles=(
|
||||
$(git diff --name-only)
|
||||
)
|
||||
if [[ " ${changedFiles[*]} " =~ helmcharts ]]; then
|
||||
echo "[ERROR] Helm Charts are not up to date"
|
||||
echo "[ERROR] Run 'make update-resources -s' to update them."
|
||||
exit 1
|
||||
else
|
||||
echo "[INFO] Helm Charts are up to date."
|
||||
fi
|
||||
}
|
||||
|
||||
installOperatorSDK
|
||||
|
||||
pushd "${ROOT_PROJECT_DIR}" || true
|
||||
|
||||
updateResources
|
||||
checkCRDs
|
||||
checkRoles
|
||||
checkNextOlmBundle
|
||||
checkDockerfile
|
||||
checkOperatorYaml
|
||||
checkHelmCharts
|
||||
# Update resources
|
||||
make update-dev-resources INCREMENT_BUNDLE_VERSION=false
|
||||
|
||||
if [[ $(git diff --name-only | wc -l) != 0 ]]; then
|
||||
# Print difference
|
||||
git --no-pager diff
|
||||
|
||||
echo "[ERROR] Resources are not up to date."
|
||||
echo "[ERROR] Run 'make update-dev-resources' to update them."
|
||||
exit 1
|
||||
else
|
||||
echo "[INFO] Done."
|
||||
fi
|
||||
|
||||
popd || true
|
||||
|
||||
echo "[INFO] Done."
|
||||
|
|
|
|||
|
|
@ -11,6 +11,11 @@
|
|||
# Red Hat, Inc. - initial API and implementation
|
||||
#
|
||||
|
||||
export ECLIPSE_CHE_PACKAGE_NAME="eclipse-che-preview-openshift"
|
||||
export ECLIPSE_CHE_CATALOG_SOURCE_NAME="eclipse-che-custom-catalog-source"
|
||||
export ECLIPSE_CHE_SUBSCRIPTION_NAME="eclipse-che-subscription"
|
||||
export DEV_WORKSPACE_CATALOG_SOURCE_NAME="custom-devworkspace-operator-catalog"
|
||||
|
||||
catchFinish() {
|
||||
result=$?
|
||||
|
||||
|
|
@ -21,6 +26,8 @@ catchFinish() {
|
|||
echo "[INFO] Job completed successfully."
|
||||
fi
|
||||
|
||||
rm -rf ${OPERATOR_REPO}/tmp
|
||||
|
||||
echo "[INFO] Please check github actions artifacts."
|
||||
exit $result
|
||||
}
|
||||
|
|
@ -54,9 +61,11 @@ initTemplates() {
|
|||
export PREVIOUS_OPERATOR_VERSION_TEMPLATE_PATH=${CHECTL_TEMPLATES_BASE_DIR}/${PREVIOUS_PACKAGE_VERSION}
|
||||
export LAST_OPERATOR_VERSION_TEMPLATE_PATH=${CHECTL_TEMPLATES_BASE_DIR}/${LAST_PACKAGE_VERSION}
|
||||
|
||||
copyChectlTemplates "${PREVIOUS_OPERATOR_VERSION_CLONE_PATH}" "${PREVIOUS_OPERATOR_VERSION_TEMPLATE_PATH}/che-operator"
|
||||
copyChectlTemplates "${LAST_OPERATOR_VERSION_CLONE_PATH}" "${LAST_OPERATOR_VERSION_TEMPLATE_PATH}/che-operator"
|
||||
copyChectlTemplates "${OPERATOR_REPO}" "${CURRENT_OPERATOR_VERSION_TEMPLATE_PATH}/che-operator"
|
||||
pushd "${OPERATOR_REPO}" || exit 1
|
||||
make gen-chectl-tmpl SOURCE="${PREVIOUS_OPERATOR_VERSION_CLONE_PATH}" TARGET="${PREVIOUS_OPERATOR_VERSION_TEMPLATE_PATH}"
|
||||
make gen-chectl-tmpl SOURCE="${LAST_OPERATOR_VERSION_CLONE_PATH}" TARGET="${LAST_OPERATOR_VERSION_TEMPLATE_PATH}"
|
||||
make gen-chectl-tmpl SOURCE="${OPERATOR_REPO}" TARGET="${CURRENT_OPERATOR_VERSION_TEMPLATE_PATH}"
|
||||
popd || exit 1
|
||||
}
|
||||
|
||||
getLatestStableVersions() {
|
||||
|
|
@ -68,12 +77,6 @@ getLatestStableVersions() {
|
|||
git remote remove operator
|
||||
}
|
||||
|
||||
copyChectlTemplates() {
|
||||
pushd "${OPERATOR_REPO}" || exit
|
||||
make chectl-templ "SRC=${1}" "TARGET=${2}"
|
||||
popd || exit
|
||||
}
|
||||
|
||||
collectLogs() {
|
||||
mkdir -p ${ARTIFACTS_DIR}
|
||||
|
||||
|
|
@ -85,7 +88,7 @@ collectLogs() {
|
|||
|
||||
# additionally grab server logs for fast access
|
||||
chectl server:logs -n $NAMESPACE -d $ARTIFACTS_DIR
|
||||
set -ex
|
||||
set -e
|
||||
}
|
||||
|
||||
RESOURCES_DIR_NAME='resources'
|
||||
|
|
@ -181,39 +184,94 @@ collectClusterScopeResources() {
|
|||
}
|
||||
|
||||
buildCheOperatorImage() {
|
||||
docker build -t "${OPERATOR_IMAGE}" -f Dockerfile --build-arg TESTS=false . && docker save "${OPERATOR_IMAGE}" > /tmp/operator.tar
|
||||
docker build -t "${OPERATOR_IMAGE}" -f Dockerfile --build-arg SKIP_TESTS=true . && docker save "${OPERATOR_IMAGE}" > /tmp/operator.tar
|
||||
}
|
||||
|
||||
copyCheOperatorImageToMinikube() {
|
||||
eval $(minikube docker-env) && docker load -i /tmp/operator.tar && rm /tmp/operator.tar
|
||||
}
|
||||
|
||||
deployEclipseCheOnWithOperator() {
|
||||
deployEclipseCheWithHelm() {
|
||||
local chectlbin=$1
|
||||
local platform=$2
|
||||
local templates=$3
|
||||
local customimage=$4
|
||||
local channel="next"
|
||||
|
||||
# Deploy Eclipse Che to have Cert Manager and Dex installed
|
||||
deployEclipseCheWithOperator "${chectlbin}" "${platform}" "${templates}" "${customimage}"
|
||||
|
||||
# Get configuration
|
||||
local identityProvider=$(kubectl get checluster/eclipse-che -n ${NAMESPACE} -o jsonpath='{.spec.networking.auth.identityProviderURL}')
|
||||
local oAuthSecret=$(kubectl get checluster/eclipse-che -n ${NAMESPACE} -o jsonpath='{.spec.networking.auth.oAuthSecret}')
|
||||
local oAuthClientName=$(kubectl get checluster/eclipse-che -n ${NAMESPACE} -o jsonpath='{.spec.networking.auth.oAuthClientName}')
|
||||
local domain=$(kubectl get checluster/eclipse-che -n ${NAMESPACE} -o jsonpath='{.spec.networking.domain}')
|
||||
|
||||
# Delete Eclipse Che (Cert Manager and Dex are still there)
|
||||
${chectlbin} server:delete -y -n ${NAMESPACE}
|
||||
|
||||
# Prepare HelmCharts
|
||||
HELMCHART_DIR=/tmp/chectl-helmcharts
|
||||
OPERATOR_DEPLOYMENT="${HELMCHART_DIR}"/templates/che-operator.Deployment.yaml
|
||||
|
||||
rm -rf "${HELMCHART_DIR}" && cp -r "${OPERATOR_REPO}/helmcharts/${channel}" "${HELMCHART_DIR}"
|
||||
|
||||
if [[ ${customimage} == "true" ]]; then
|
||||
yq -riSY '.spec.template.spec.containers[0].image = "'${OPERATOR_IMAGE}'"' "${OPERATOR_DEPLOYMENT}"
|
||||
yq -riSY '.spec.template.spec.containers[0].imagePullPolicy = "IfNotPresent"' "${OPERATOR_DEPLOYMENT}"
|
||||
fi
|
||||
|
||||
# Deploy Eclipse Che with Helm
|
||||
pushd "${HELMCHART_DIR}" || exit 1
|
||||
helm install che \
|
||||
--create-namespace \
|
||||
--namespace eclipse-che \
|
||||
--set networking.domain="${domain}" \
|
||||
--set networking.auth.oAuthSecret="${oAuthSecret}" \
|
||||
--set networking.auth.oAuthClientName="${oAuthClientName}" \
|
||||
--set networking.auth.identityProviderURL="${identityProvider}" .
|
||||
popd
|
||||
|
||||
local cheVersion=$(yq -r '.spec.template.spec.containers[0].env[] | select(.name == "CHE_VERSION") | .value' < "${OPERATOR_DEPLOYMENT}")
|
||||
waitEclipseCheDeployed "${cheVersion}"
|
||||
|
||||
waitDevWorkspaceControllerStarted
|
||||
}
|
||||
|
||||
deployEclipseCheWithOperator() {
|
||||
local chectlbin=$1
|
||||
local platform=$2
|
||||
local templates=$3
|
||||
local customimage=$4
|
||||
|
||||
local domainFlag=""
|
||||
if [[ ${platform} == "minikube" ]]; then
|
||||
domainFlag="--domain $(minikube ip).nip.io"
|
||||
fi
|
||||
|
||||
if [[ ${customimage} == "true" ]]; then
|
||||
if [[ ${platform} == "minikube" ]]; then
|
||||
buildCheOperatorImage
|
||||
copyCheOperatorImageToMinikube
|
||||
yq -riSY '.spec.template.spec.containers[0].image = "'${OPERATOR_IMAGE}'"' "${templates}"/che-operator/kubernetes/operator.yaml
|
||||
yq -riSY '.spec.template.spec.containers[0].imagePullPolicy = "IfNotPresent"' "${templates}"/che-operator/kubernetes/operator.yaml
|
||||
else
|
||||
yq -riSY '.spec.template.spec.containers[0].image = "'${OPERATOR_IMAGE}'"' "${templates}"/che-operator/openshift/operator.yaml
|
||||
yq -riSY '.spec.template.spec.containers[0].imagePullPolicy = "IfNotPresent"' "${templates}"/che-operator/openshift/operator.yaml
|
||||
fi
|
||||
fi
|
||||
|
||||
yq -riSY '.spec.template.spec.containers[0].image = "'${OPERATOR_IMAGE}'"' ${templates}/che-operator/operator.yaml
|
||||
yq -riSY '.spec.template.spec.containers[0].imagePullPolicy = "IfNotPresent"' ${templates}/che-operator/operator.yaml
|
||||
if [[ ${platform} == "minikube" ]]; then
|
||||
checluster=$(grep -rlx "kind: CheCluster" /tmp/chectl-templates/che-operator/)
|
||||
apiVersion=$(yq -r '.apiVersion' ${checluster})
|
||||
if [[ ${apiVersion} == "org.eclipse.che/v2" ]]; then
|
||||
yq -riY '.spec.networking.domain = "'$(minikube ip).nip.io'"' ${checluster}
|
||||
yq -riY '.spec.networking.tlsSecretName = "che-tls"' ${checluster}
|
||||
else
|
||||
yq -riY '.spec.k8s.ingressDomain = "'$(minikube ip).nip.io'"' ${checluster}
|
||||
fi
|
||||
fi
|
||||
|
||||
${chectlbin} server:deploy \
|
||||
--batch \
|
||||
--platform ${platform} \
|
||||
--installer operator \
|
||||
--templates ${templates} ${domainFlag}
|
||||
--templates ${templates}
|
||||
|
||||
waitDevWorkspaceControllerStarted
|
||||
}
|
||||
|
|
@ -228,24 +286,34 @@ updateEclipseChe() {
|
|||
if [[ ${platform} == "minikube" ]]; then
|
||||
buildCheOperatorImage
|
||||
copyCheOperatorImageToMinikube
|
||||
yq -riSY '.spec.template.spec.containers[0].image = "'${OPERATOR_IMAGE}'"' ${templates}/che-operator/kubernetes/operator.yaml
|
||||
yq -riSY '.spec.template.spec.containers[0].imagePullPolicy = "IfNotPresent"' ${templates}/che-operator/kubernetes/operator.yaml
|
||||
else
|
||||
yq -riSY '.spec.template.spec.containers[0].image = "'${OPERATOR_IMAGE}'"' ${templates}/che-operator/openshift/operator.yaml
|
||||
yq -riSY '.spec.template.spec.containers[0].imagePullPolicy = "IfNotPresent"' ${templates}/che-operator/openshift/operator.yaml
|
||||
fi
|
||||
|
||||
yq -riSY '.spec.template.spec.containers[0].image = "'${OPERATOR_IMAGE}'"' ${templates}/che-operator/operator.yaml
|
||||
yq -riSY '.spec.template.spec.containers[0].imagePullPolicy = "IfNotPresent"' ${templates}/che-operator/operator.yaml
|
||||
fi
|
||||
|
||||
${chectlbin} server:update \
|
||||
--batch \
|
||||
--templates ${templates}
|
||||
|
||||
local cheVersion=$(cat ${templates}/che-operator/operator.yaml | yq -r '.spec.template.spec.containers[0].env[] | select(.name == "CHE_VERSION") | .value')
|
||||
local configManagerPath=""
|
||||
if [[ -f ${templates}/che-operator/operator.yaml ]]; then
|
||||
configManagerPath="${templates}/che-operator/operator.yaml"
|
||||
elif [[ ${platform} == "minikube" ]]; then
|
||||
configManagerPath="${templates}/che-operator/kubernetes/operator.yaml"
|
||||
else
|
||||
configManagerPath="${templates}/che-operator/openshift/operator.yaml"
|
||||
fi
|
||||
|
||||
local cheVersion=$(cat "${configManagerPath}" | yq -r '.spec.template.spec.containers[0].env[] | select(.name == "CHE_VERSION") | .value')
|
||||
waitEclipseCheDeployed ${cheVersion}
|
||||
|
||||
waitDevWorkspaceControllerStarted
|
||||
}
|
||||
|
||||
waitEclipseCheDeployed() {
|
||||
set -x
|
||||
local version=$1
|
||||
echo "[INFO] Wait for Eclipse Che '${version}' version"
|
||||
|
||||
|
|
@ -253,11 +321,11 @@ waitEclipseCheDeployed() {
|
|||
while [ $n -le 500 ]
|
||||
do
|
||||
cheVersion=$(oc get checluster/eclipse-che -n "${NAMESPACE}" -o "jsonpath={.status.cheVersion}")
|
||||
cheIsRunning=$(oc get checluster/eclipse-che -n "${NAMESPACE}" -o "jsonpath={.status.cheClusterRunning}" )
|
||||
chePhase=$(oc get checluster/eclipse-che -n "${NAMESPACE}" -o "jsonpath={.status.chePhase}" )
|
||||
oc get pods -n ${NAMESPACE}
|
||||
if [ "${cheVersion}" == "${version}" ] && [ "${cheIsRunning}" == "Available" ]
|
||||
if [[ "${cheVersion}" == "${version}" ]]
|
||||
then
|
||||
echo "[INFO] Eclipse Che '${version}' version has been succesfully deployed"
|
||||
echo "[INFO] Eclipse Che '${version}' version has been successfully deployed"
|
||||
break
|
||||
fi
|
||||
sleep 6
|
||||
|
|
@ -277,7 +345,16 @@ useCustomOperatorImageInCSV() {
|
|||
}
|
||||
|
||||
getCheClusterCRFromExistedCSV() {
|
||||
oc get csv $(getCSVName) -n openshift-operators -o yaml | yq -r ".metadata.annotations[\"alm-examples\"] | fromjson | .[] | select(.kind == \"CheCluster\")"
|
||||
CHE_CLUSTER=""
|
||||
CHE_CLUSTER_V2=$(oc get csv $(getCSVName) -n openshift-operators -o yaml | yq -r '.metadata.annotations["alm-examples"] | fromjson | .[] | select(.apiVersion == "org.eclipse.che/v2")')
|
||||
if [[ -n "${CHE_CLUSTER_V2}" ]]; then
|
||||
CHE_CLUSTER="${CHE_CLUSTER_V2}"
|
||||
else
|
||||
CHE_CLUSTER_V1=$(oc get csv $(getCSVName) -n openshift-operators -o yaml | yq -r '.metadata.annotations["alm-examples"] | fromjson | .[] | select(.apiVersion == "org.eclipse.che/v1")')
|
||||
CHE_CLUSTER="${CHE_CLUSTER_V1}"
|
||||
fi
|
||||
|
||||
echo "${CHE_CLUSTER}"
|
||||
}
|
||||
|
||||
getCheVersionFromExistedCSV() {
|
||||
|
|
@ -290,7 +367,7 @@ getCSVName() {
|
|||
|
||||
while [ $n -le 24 ]
|
||||
do
|
||||
csvNumber=$(oc get csv -n openshift-operators --no-headers=true | grep eclipse-che-preview-openshift | wc -l)
|
||||
csvNumber=$(oc get csv -n openshift-operators --no-headers=true | grep ${ECLIPSE_CHE_PACKAGE_NAME} | wc -l)
|
||||
if [[ $csvNumber == 1 ]]; then
|
||||
break
|
||||
return
|
||||
|
|
@ -404,7 +481,7 @@ EOF
|
|||
|
||||
sleep 10s
|
||||
if [[ ${installPlan} == "Manual" ]]; then
|
||||
kubectl wait subscription/${name} -n openshift-operators --for=condition=InstallPlanPending --timeout=120s
|
||||
kubectl wait subscription/"${name}" -n openshift-operators --for=condition=InstallPlanPending --timeout=120s
|
||||
fi
|
||||
}
|
||||
|
||||
|
|
@ -420,9 +497,8 @@ deployDevWorkspaceOperator() {
|
|||
devWorkspaceChannel="fast"
|
||||
fi
|
||||
|
||||
customDevWorkspaceCatalog=$(getDevWorkspaceCustomCatalogSourceName)
|
||||
createCatalogSource "${customDevWorkspaceCatalog}" ${devWorkspaceCatalogImage} "Red Hat" "DevWorkspace Operator Catalog"
|
||||
createSubscription "devworkspace-operator" "devworkspace-operator" "${devWorkspaceChannel}" "${customDevWorkspaceCatalog}" "Auto"
|
||||
createCatalogSource "${DEV_WORKSPACE_CATALOG_SOURCE_NAME}" ${devWorkspaceCatalogImage} "Red Hat" "DevWorkspace Operator Catalog"
|
||||
createSubscription "devworkspace-operator" "devworkspace-operator" "${devWorkspaceChannel}" "${DEV_WORKSPACE_CATALOG_SOURCE_NAME}" "Auto"
|
||||
|
||||
waitDevWorkspaceControllerStarted
|
||||
}
|
||||
|
|
@ -497,7 +573,7 @@ forcePullingOlmImages() {
|
|||
|
||||
echo "[INFO] Pulling image '${image}'"
|
||||
|
||||
yq -r "(.spec.template.spec.containers[0].image) = \"${image}\"" "${BASE_DIR}/force-pulling-olm-images-job.yaml" | kubectl apply -f - -n openshift-operators
|
||||
yq -r "(.spec.template.spec.containers[0].image) = \"${image}\"" "${OPERATOR_REPO}/olm/force-pulling-olm-images-job.yaml" | kubectl apply -f - -n openshift-operators
|
||||
|
||||
kubectl wait --for=condition=complete --timeout=30s job/force-pulling-olm-images-job -n openshift-operators
|
||||
kubectl delete job/force-pulling-olm-images-job -n openshift-operators
|
||||
|
|
@ -510,3 +586,13 @@ installchectl() {
|
|||
mkdir /tmp/chectl-${version}
|
||||
tar -xvzf /tmp/chectl-${version}.tar.gz -C /tmp/chectl-${version}
|
||||
}
|
||||
|
||||
getBundlePath() {
|
||||
channel="${1}"
|
||||
if [ -z "${channel}" ]; then
|
||||
echo "[ERROR] 'channel' is not specified"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "${OPERATOR_REPO}/bundle/${channel}/${ECLIPSE_CHE_PACKAGE_NAME}"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,34 @@
|
|||
#!/usr/bin/env bash
|
||||
#
|
||||
# Copyright (c) 2019-2021 Red Hat, Inc.
|
||||
# This program and the accompanying materials are made
|
||||
# available under the terms of the Eclipse Public License 2.0
|
||||
# which is available at https://www.eclipse.org/legal/epl-2.0/
|
||||
#
|
||||
# SPDX-License-Identifier: EPL-2.0
|
||||
#
|
||||
# Contributors:
|
||||
# Red Hat, Inc. - initial API and implementation
|
||||
#
|
||||
|
||||
set -e
|
||||
set -x
|
||||
|
||||
# Get absolute path for root repo directory from github actions context: https://docs.github.com/en/free-pro-team@latest/actions/reference/context-and-expression-syntax-for-github-actions
|
||||
export OPERATOR_REPO="${GITHUB_WORKSPACE}"
|
||||
if [ -z "${OPERATOR_REPO}" ]; then
|
||||
OPERATOR_REPO=$(dirname "$(dirname "$(dirname "$(dirname "$(readlink -f "${BASH_SOURCE[0]}")")")")")
|
||||
fi
|
||||
|
||||
source "${OPERATOR_REPO}/.github/bin/common.sh"
|
||||
|
||||
# Stop execution on any error
|
||||
trap "catchFinish" EXIT SIGINT
|
||||
|
||||
runTest() {
|
||||
deployEclipseCheWithHelm "chectl" "minikube" "${CURRENT_OPERATOR_VERSION_TEMPLATE_PATH}" "true"
|
||||
}
|
||||
|
||||
initDefaults
|
||||
initTemplates
|
||||
runTest
|
||||
|
|
@ -20,13 +20,13 @@ if [ -z "${OPERATOR_REPO}" ]; then
|
|||
OPERATOR_REPO=$(dirname "$(dirname "$(dirname "$(dirname "$(readlink -f "${BASH_SOURCE[0]}")")")")")
|
||||
fi
|
||||
|
||||
source "${OPERATOR_REPO}"/.github/bin/common.sh
|
||||
source "${OPERATOR_REPO}/.github/bin/common.sh"
|
||||
|
||||
# Stop execution on any error
|
||||
trap "catchFinish" EXIT SIGINT
|
||||
|
||||
runTest() {
|
||||
deployEclipseCheOnWithOperator "chectl" "minikube" ${CURRENT_OPERATOR_VERSION_TEMPLATE_PATH} "true"
|
||||
deployEclipseCheWithOperator "chectl" "minikube" ${CURRENT_OPERATOR_VERSION_TEMPLATE_PATH} "true"
|
||||
}
|
||||
|
||||
initDefaults
|
||||
|
|
|
|||
|
|
@ -20,17 +20,17 @@ if [ -z "${OPERATOR_REPO}" ]; then
|
|||
OPERATOR_REPO=$(dirname "$(dirname "$(dirname "$(dirname "$(readlink -f "${BASH_SOURCE[0]}")")")")")
|
||||
fi
|
||||
|
||||
source "${OPERATOR_REPO}"/.github/bin/common.sh
|
||||
source "${OPERATOR_REPO}/.github/bin/common.sh"
|
||||
|
||||
# Stop execution on any error
|
||||
trap "catchFinish" EXIT SIGINT
|
||||
|
||||
runTest() {
|
||||
deployEclipseCheOnWithOperator "/tmp/chectl-${LAST_PACKAGE_VERSION}/chectl/bin/run" "minikube" ${LAST_OPERATOR_VERSION_TEMPLATE_PATH} "false"
|
||||
updateEclipseChe "chectl" "minikube" ${CURRENT_OPERATOR_VERSION_TEMPLATE_PATH} "true"
|
||||
deployEclipseCheWithOperator "/tmp/chectl-${LAST_PACKAGE_VERSION}/chectl/bin/run" "minikube" "${LAST_OPERATOR_VERSION_TEMPLATE_PATH}" "false"
|
||||
updateEclipseChe "chectl" "minikube" "${CURRENT_OPERATOR_VERSION_TEMPLATE_PATH}" "true"
|
||||
}
|
||||
|
||||
initDefaults
|
||||
initTemplates
|
||||
installchectl ${LAST_PACKAGE_VERSION}
|
||||
installchectl "${LAST_PACKAGE_VERSION}"
|
||||
runTest
|
||||
|
|
|
|||
|
|
@ -20,13 +20,13 @@ if [ -z "${OPERATOR_REPO}" ]; then
|
|||
OPERATOR_REPO=$(dirname "$(dirname "$(dirname "$(dirname "$(readlink -f "${BASH_SOURCE[0]}")")")")")
|
||||
fi
|
||||
|
||||
source "${OPERATOR_REPO}"/.github/bin/common.sh
|
||||
source "${OPERATOR_REPO}/.github/bin/common.sh"
|
||||
|
||||
# Stop execution on any error
|
||||
trap "catchFinish" EXIT SIGINT
|
||||
|
||||
runTest() {
|
||||
deployEclipseCheOnWithOperator "/tmp/chectl-${PREVIOUS_PACKAGE_VERSION}/chectl/bin/run" "minikube" ${PREVIOUS_OPERATOR_VERSION_TEMPLATE_PATH} "false"
|
||||
deployEclipseCheWithOperator "/tmp/chectl-${PREVIOUS_PACKAGE_VERSION}/chectl/bin/run" "minikube" ${PREVIOUS_OPERATOR_VERSION_TEMPLATE_PATH} "false"
|
||||
updateEclipseChe "chectl" "minikube" ${LAST_OPERATOR_VERSION_TEMPLATE_PATH} "false"
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,38 @@
|
|||
#
|
||||
# Copyright (c) 2019-2021 Red Hat, Inc.
|
||||
# This program and the accompanying materials are made
|
||||
# available under the terms of the Eclipse Public License 2.0
|
||||
# which is available at https://www.eclipse.org/legal/epl-2.0/
|
||||
#
|
||||
# SPDX-License-Identifier: EPL-2.0
|
||||
#
|
||||
# Contributors:
|
||||
# Red Hat, Inc. - initial API and implementation
|
||||
#
|
||||
|
||||
name: Helm test
|
||||
on: pull_request
|
||||
jobs:
|
||||
helm-on-minikube:
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- name: Checkout source code
|
||||
uses: actions/checkout@v2.3.1
|
||||
- name: Start minikube cluster
|
||||
id: run-minikube
|
||||
uses: che-incubator/setup-minikube-action@next
|
||||
with:
|
||||
minikube-version: v1.23.2
|
||||
- name: Enable Private registry
|
||||
run: /bin/bash olm/minikube-registry-addon.sh &
|
||||
- name: Install yq
|
||||
run: sudo pip install yq
|
||||
- name: Install chectl
|
||||
run: bash <(curl -sL https://www.eclipse.org/che/chectl/) --channel=next
|
||||
- name: Run tests
|
||||
run: /bin/bash .github/bin/minikube/test-helm.sh
|
||||
- uses: actions/upload-artifact@v2
|
||||
if: ${{ always() }}
|
||||
with:
|
||||
name: artifacts
|
||||
path: /tmp/artifacts-che
|
||||
|
|
@ -51,7 +51,7 @@ jobs:
|
|||
set -e
|
||||
OP_SDK_DIR=/opt/operator-sdk
|
||||
mkdir -p $OP_SDK_DIR
|
||||
make download-operator-sdk OP_SDK_DIR="${OP_SDK_DIR}"
|
||||
make download-operator-sdk DEST="${OP_SDK_DIR}"
|
||||
export PATH="$PATH:$OP_SDK_DIR"
|
||||
export QUAY_ECLIPSE_CHE_USERNAME=${{ secrets.QUAY_USERNAME }}
|
||||
export QUAY_ECLIPSE_CHE_PASSWORD=${{ secrets.QUAY_PASSWORD }}
|
||||
|
|
|
|||
|
|
@ -88,7 +88,7 @@ jobs:
|
|||
|
||||
OP_SDK_DIR=/opt/operator-sdk
|
||||
mkdir -p $OP_SDK_DIR
|
||||
make download-operator-sdk OP_SDK_DIR="${OP_SDK_DIR}"
|
||||
make download-operator-sdk DEST="${OP_SDK_DIR}"
|
||||
|
||||
export PATH="$PATH:$OP_SDK_DIR"
|
||||
export QUAY_ECLIPSE_CHE_USERNAME=${{ secrets.QUAY_USERNAME }}
|
||||
|
|
|
|||
|
|
@ -28,7 +28,9 @@ jobs:
|
|||
with:
|
||||
go-version: 1.16
|
||||
- name: Validate operator resources
|
||||
run: ${GITHUB_WORKSPACE}/.github/bin/check-resources.sh
|
||||
run: |
|
||||
go install golang.org/x/tools/cmd/goimports@latest
|
||||
${GITHUB_WORKSPACE}/.github/bin/check-resources.sh
|
||||
bundle-version-validation:
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
|
|
|
|||
|
|
@ -1,124 +1,6 @@
|
|||
{
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"type": "bashdb",
|
||||
"request": "launch",
|
||||
"name": "Make release",
|
||||
"cwd": "${workspaceFolder}",
|
||||
"program": "${workspaceFolder}/make-release.sh",
|
||||
"args": [
|
||||
"7.30.0",
|
||||
"--release",
|
||||
"--check-resources",
|
||||
"--release-olm-files"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "bashdb",
|
||||
"request": "launch",
|
||||
"name": "Bash-Debug (release-olm-files.sh)",
|
||||
"cwd": "${workspaceFolder}",
|
||||
"program": "${workspaceFolder}/olm/release-olm-files.sh",
|
||||
"args": [
|
||||
"7.30.0"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "bashdb",
|
||||
"request": "launch",
|
||||
"name": "Bash-Debug (testCatalog.sh) openshift next",
|
||||
"cwd": "${workspaceFolder}",
|
||||
"program": "${workspaceFolder}/olm/testCatalog.sh",
|
||||
"args": [
|
||||
"-p",
|
||||
"openshift",
|
||||
"-c",
|
||||
"next",
|
||||
"-i",
|
||||
"quay.io/eclipse/eclipse-che-openshift-opm-catalog:next",
|
||||
"-n",
|
||||
"eclipse-che",
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "bashdb",
|
||||
"request": "launch",
|
||||
"name": "Bash-Debug (testCatalog.sh) openshift stable",
|
||||
"cwd": "${workspaceFolder}",
|
||||
"program": "${workspaceFolder}/olm/testCatalog.sh",
|
||||
"args": [
|
||||
"-p",
|
||||
"openshift",
|
||||
"-c",
|
||||
"stable",
|
||||
"-i",
|
||||
"quay.io/eclipse/eclipse-che-openshift-opm-catalog:test",
|
||||
"-n",
|
||||
"eclipse-che",
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "bashdb",
|
||||
"request": "launch",
|
||||
"name": "Bash-Debug (testUpdate.sh) openshift stable",
|
||||
"cwd": "${workspaceFolder}/olm",
|
||||
"program": "${workspaceFolder}/olm/testUpdate.sh",
|
||||
"args": [
|
||||
"-p",
|
||||
"openshift",
|
||||
"-c",
|
||||
"stable",
|
||||
"-i",
|
||||
"quay.io/eclipse/eclipse-che-openshift-opm-catalog:test",
|
||||
"-n",
|
||||
"eclipse-che"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "bashdb",
|
||||
"request": "launch",
|
||||
"name": "Bash-Debug (testUpdate.sh) openshift next",
|
||||
"cwd": "${workspaceFolder}/olm",
|
||||
"program": "${workspaceFolder}/olm/testUpdate.sh",
|
||||
"args": [
|
||||
"-p",
|
||||
"openshift",
|
||||
"-c",
|
||||
"next",
|
||||
"-i",
|
||||
"quay.io/eclipse/eclipse-che-openshift-opm-catalog:next",
|
||||
"-n",
|
||||
"eclipse-che"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "bashdb",
|
||||
"request": "launch",
|
||||
"name": "Bash-Debug (buildCatalog.sh) Openshift platform",
|
||||
"cwd": "${workspaceFolder}/olm",
|
||||
"program": "./buildCatalog.sh",
|
||||
"args": [
|
||||
"-p",
|
||||
"openshift",
|
||||
"-c",
|
||||
"next",
|
||||
"-i",
|
||||
"quay.io/eclipse/eclipse-che-openshift-opm-catalog:next"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "bashdb",
|
||||
"request": "launch",
|
||||
"name": "Bash-Debug (simplest configuration)",
|
||||
"program": "${file}",
|
||||
},
|
||||
{
|
||||
"name": "Launch Main *.go File",
|
||||
"type": "go",
|
||||
"request": "launch",
|
||||
"program": "${file}",
|
||||
},
|
||||
{
|
||||
"useApiV1": false,
|
||||
"dlvLoadConfig": {
|
||||
|
|
@ -133,20 +15,26 @@
|
|||
"request": "launch",
|
||||
"mode": "auto",
|
||||
"program": "${workspaceFolder}/main.go",
|
||||
"env": {
|
||||
"CHE_FLAVOR": "che",
|
||||
"CONSOLE_LINK_NAME": "che",
|
||||
"CONSOLE_LINK_DISPLAY_NAME": "Eclipse Che",
|
||||
"CONSOLE_LINK_SECTION": "Red Hat Applications",
|
||||
"CONSOLE_LINK_IMAGE": "/dashboard/assets/branding/loader.svg",
|
||||
"MAX_CONCURRENT_RECONCILES": 10,
|
||||
},
|
||||
"envFile": "/tmp/che-operator-debug.env",
|
||||
"envFile": "/tmp/che-operator-dev/vscode.env",
|
||||
"cwd": "${workspaceFolder}",
|
||||
"args": [
|
||||
"--defaults-path",
|
||||
"config/manager/manager.yaml"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "bashdb",
|
||||
"request": "launch",
|
||||
"name": "Bash-Debug",
|
||||
"cwd": "${workspaceFolder}",
|
||||
"program": "${file}",
|
||||
"args": []
|
||||
},
|
||||
{
|
||||
"name": "Launch Main *.go File",
|
||||
"type": "go",
|
||||
"request": "launch",
|
||||
"program": "${file}",
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"cSpell.words": []
|
||||
}
|
||||
|
|
@ -77,8 +77,8 @@
|
|||
"group": "build"
|
||||
},
|
||||
{
|
||||
"label": "Update resources",
|
||||
"command": "make update-resources -s",
|
||||
"label": "Update all",
|
||||
"command": "make update-dev-resources",
|
||||
"type": "shell",
|
||||
"args": [],
|
||||
"problemMatcher": [
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ FROM registry.access.redhat.com/ubi8/go-toolset:1.17.7-13 as builder
|
|||
ENV GOPATH=/go/
|
||||
ARG DEV_WORKSPACE_CONTROLLER_VERSION="v0.14.1"
|
||||
ARG DEV_HEADER_REWRITE_TRAEFIK_PLUGIN="main"
|
||||
ARG TESTS="true"
|
||||
ARG SKIP_TESTS="false"
|
||||
USER root
|
||||
|
||||
# upstream, download zips for every build
|
||||
|
|
@ -47,7 +47,7 @@ COPY pkg/ pkg/
|
|||
|
||||
# build operator
|
||||
RUN export ARCH="$(uname -m)" && if [[ ${ARCH} == "x86_64" ]]; then export ARCH="amd64"; elif [[ ${ARCH} == "aarch64" ]]; then export ARCH="arm64"; fi && \
|
||||
if [[ ${TESTS} == "true" ]]; then export MOCK_API=true && go test -mod=vendor -v ./...; fi && \
|
||||
if [[ ${SKIP_TESTS} == "false" ]]; then export MOCK_API=true && go test -mod=vendor -v ./...; fi && \
|
||||
CGO_ENABLED=0 GOOS=linux GOARCH=${ARCH} GO111MODULE=on go build -mod=vendor -a -o che-operator main.go
|
||||
|
||||
# https://access.redhat.com/containers/?tab=tags#/registry.access.redhat.com/ubi8-minimal
|
||||
|
|
|
|||
7
PROJECT
7
PROJECT
|
|
@ -22,6 +22,9 @@ resources:
|
|||
domain: eclipse.che
|
||||
group: org
|
||||
kind: CheCluster
|
||||
path: github.com/eclipse-che/che-operator/api/v2alpha1
|
||||
version: v2alpha1
|
||||
path: github.com/eclipse-che/che-operator/api/v2
|
||||
version: v2
|
||||
webhooks:
|
||||
conversion: true
|
||||
webhookVersion: v1
|
||||
version: "3"
|
||||
|
|
|
|||
22
README.md
22
README.md
|
|
@ -19,9 +19,7 @@ Che operator is implemented using [operator framework](https://github.com/operat
|
|||
|
||||
## CheCluster custom resource
|
||||
|
||||
Che operator deploys Eclipse Che using configuration stored in the Kubernetes custom resource(CR). CR object structure defined in the code using `api/v1/checluster_types.go` file. Field name defined using the serialization tag `json`, for example `json:"openShiftoAuth"`. Che operator default CR sample is stored in the `config/samples/org.eclipse.che_v1_checluster.yaml`. This file should be directly modified if you want to apply new fields with default values, or in case of changing default values for existing fields.
|
||||
Also, you can apply in the field comments Openshift UI annotations: to display some
|
||||
interactive information about these fields on the Openshift UI.
|
||||
Che operator deploys Eclipse Che using configuration stored in the Kubernetes custom resource(CR). CR object structure defined in the code using `api/v2/checluster_types.go` file. Field name defined using the serialization tag `json`. Che operator default CR sample is stored in the `config/samples/org_v2_checluster.yaml`. This file should be directly modified if you want to apply new fields with default values, or in case of changing default values for existing fields. Also, you can apply in the field comments Openshift UI annotations: to display some interactive information about these fields on the Openshift UI.
|
||||
For example:
|
||||
|
||||
```go
|
||||
|
|
@ -60,7 +58,7 @@ che-operator MAKE file provides ability to install che-operator(VSCode task `Dep
|
|||
```bash
|
||||
$ make deploy IMG=\"${IMAGE_REGISTRY_HOST}/${IMAGE_REGISTRY_USER_NAME}/che-operator:next\"
|
||||
|
||||
$ kubectl apply -f config/samples/org.eclipse.che_v1_checluster.yaml -n <NAMESPACE>
|
||||
$ kubectl apply -f config/samples/org_v2_checluster.yaml -n <NAMESPACE>
|
||||
```
|
||||
|
||||
Undeploy che-operator(VSCode task `UnDeploy che-operator`):
|
||||
|
|
@ -89,7 +87,7 @@ Where:
|
|||
If you have changed Che operator deployment, roles, cluster roles, CRD or CR then you must use `--templates` flag to point chectl to modified Che operator templates. Use make command to prepare chectl templates folder:
|
||||
|
||||
```bash
|
||||
$ make chectl-templ TARGET=<SOME_PATH>/che-operator
|
||||
$ make gen-chectl-tmpl TARGET=<SOME_PATH>
|
||||
```
|
||||
|
||||
Execute chectl:
|
||||
|
|
@ -105,7 +103,7 @@ $ chectl server:deploy --installer operator -p <PLATFORM> --che-operator-image=$
|
|||
2. Update OLM files:
|
||||
|
||||
```bash
|
||||
$ make update-resources -s
|
||||
$ make update-dev-resources
|
||||
```
|
||||
|
||||
3. Build catalog source and bundle images:
|
||||
|
|
@ -171,7 +169,7 @@ Go client grabs kubeconfig either from InClusterConfig or `~/.kube` locally. Mak
|
|||
|
||||
Where:
|
||||
* `ECLIPSE-CHE-NAMESPACE` - namespace name to deploy Che operator into, default is `che`
|
||||
* `CUSTOM_RESOURCE` - path to custom resource yaml, default is `./config/samples/org.eclipse.che_v1_checluster.yaml`
|
||||
* `CUSTOM_RESOURCE` - path to custom resource yaml, default is `./config/samples/org_v2_checluster.yaml`
|
||||
|
||||
Use VSCode debug configuration `Che Operator` to attach to the running process.
|
||||
|
||||
|
|
@ -238,7 +236,7 @@ $ make generate; make manifests
|
|||
```
|
||||
|
||||
This command will update CRD files:
|
||||
- `config/crd/bases/org_v1_che_crd.yaml`
|
||||
- `config/crd/bases/org.eclipse.che_checlusters.yaml`
|
||||
|
||||
CRD beta yamls should be used for back compatibility with Openshift 3.
|
||||
|
||||
|
|
@ -248,21 +246,21 @@ Sometimes, during development, you need to modify some YAML definitions in the `
|
|||
- operator deployment `config/manager/manager.yaml`
|
||||
- operator roles/cluster roles permissions. They are defined like role/rolebinding or cluster role/rolebinding yamls in the `config` folder.
|
||||
- operator custom resource CR `config/crd/bases/org_v1_che_cr.yaml`. This file contains the default CheCluster sample. Also this file is the default OLM CheCluster sample.
|
||||
- Che cluster custom resource definition `api/v1/checluster_types.go`. For example you want to fix some properties description or apply new Che type properties with default values. These changes affect CRD `config/crd/bases/org_v1_che_crd.yaml`.
|
||||
- Che cluster custom resource definition `api/v1/checluster_types.go`. For example you want to fix some properties description or apply new Che type properties with default values. These changes affect CRD `config/crd/bases/org.eclipse.che_checlusters.yaml`.
|
||||
- add Openshift ui annotations for Che types properties (`api/v1/checluster_types.go`) to display information or interactive elements on the Openshift user interface.
|
||||
|
||||
For all these cases it's a necessary to generate a new OLM bundle to make these changes working with OLM. Run the VSCode tasks `Update resources` or use the terminal:
|
||||
|
||||
```bash
|
||||
$ make update-resources -s
|
||||
$ make update-dev-resources
|
||||
```
|
||||
|
||||
Every changes will be included to the `bundle` folder and will override all previous changes. OLM bundle changes should be committed to the pull request.
|
||||
|
||||
To update a bundle without version incrementation and time update you can use env variables `NO_DATE_UPDATE` and `NO_INCREMENT`. For example, during development you need to update bundle a lot of times with changed che-operator deployment or role, rolebinding and etc, but you don't want to increment the bundle version and time creation, when all desired changes were completed:
|
||||
To update a bundle without version incrementation and time update:
|
||||
|
||||
```bash
|
||||
$ make update-resources NO_DATE_UPDATE="true" NO_INCREMENT="true" -s
|
||||
$ make update-dev-resources INCREMENT_BUNDLE_VERSION=false
|
||||
```
|
||||
|
||||
### Che operator PR checks
|
||||
|
|
|
|||
|
|
@ -1 +1,2 @@
|
|||
operator-sdk: v1.9.2
|
||||
opm: v1.15.1
|
||||
|
|
|
|||
|
|
@ -0,0 +1,463 @@
|
|||
//
|
||||
// Copyright (c) 2019-2022 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
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"k8s.io/apimachinery/pkg/api/resource"
|
||||
|
||||
"github.com/devfile/devworkspace-operator/pkg/infrastructure"
|
||||
chev1 "github.com/eclipse-che/che-operator/api/v1"
|
||||
chev2 "github.com/eclipse-che/che-operator/api/v2"
|
||||
"github.com/stretchr/testify/assert"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"k8s.io/utils/pointer"
|
||||
)
|
||||
|
||||
func TestConvertFromEmptyCheCluster(t *testing.T) {
|
||||
checlusterv1 := &chev1.CheCluster{}
|
||||
checlusterv2 := &chev2.CheCluster{}
|
||||
|
||||
err := checlusterv1.ConvertFrom(checlusterv2)
|
||||
assert.Nil(t, err)
|
||||
}
|
||||
|
||||
func TestConvertFromIngressOnK8s(t *testing.T) {
|
||||
infrastructure.InitializeForTesting(infrastructure.Kubernetes)
|
||||
|
||||
checlusterv2 := &chev2.CheCluster{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "eclipse-che",
|
||||
Namespace: "eclipse-che",
|
||||
},
|
||||
Spec: chev2.CheClusterSpec{
|
||||
Networking: chev2.CheClusterSpecNetworking{
|
||||
Labels: map[string]string{"a": "b", "c": "d"},
|
||||
Annotations: map[string]string{"a": "b", "c": "d", "kubernetes.io/ingress.class": "nginx"},
|
||||
Domain: "Domain",
|
||||
Hostname: "Hostname",
|
||||
TlsSecretName: "tlsSecret",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
checlusterv1 := &chev1.CheCluster{}
|
||||
err := checlusterv1.ConvertFrom(checlusterv2)
|
||||
assert.Nil(t, err)
|
||||
|
||||
assert.Equal(t, map[string]string{"a": "b", "c": "d"}, checlusterv1.Spec.Server.CheServerIngress.Annotations)
|
||||
assert.Equal(t, "Domain", checlusterv1.Spec.K8s.IngressDomain)
|
||||
assert.Equal(t, "nginx", checlusterv1.Spec.K8s.IngressClass)
|
||||
assert.Equal(t, "Hostname", checlusterv1.Spec.Server.CheHost)
|
||||
assert.Equal(t, "a=b,c=d", checlusterv1.Spec.Server.CheServerIngress.Labels)
|
||||
assert.Equal(t, "tlsSecret", checlusterv1.Spec.K8s.TlsSecretName)
|
||||
}
|
||||
|
||||
func TestConvertFromIngressOnOpenShift(t *testing.T) {
|
||||
infrastructure.InitializeForTesting(infrastructure.OpenShiftv4)
|
||||
|
||||
checlusterv2 := &chev2.CheCluster{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "eclipse-che",
|
||||
Namespace: "eclipse-che",
|
||||
},
|
||||
Spec: chev2.CheClusterSpec{
|
||||
Networking: chev2.CheClusterSpecNetworking{
|
||||
Labels: map[string]string{"a": "b", "c": "d"},
|
||||
Annotations: map[string]string{"a": "b", "c": "d"},
|
||||
Domain: "Domain",
|
||||
Hostname: "Hostname",
|
||||
TlsSecretName: "tlsSecret",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
checlusterv1 := &chev1.CheCluster{}
|
||||
err := checlusterv1.ConvertFrom(checlusterv2)
|
||||
assert.Nil(t, err)
|
||||
|
||||
assert.Equal(t, map[string]string{"a": "b", "c": "d"}, checlusterv1.Spec.Server.CheServerRoute.Annotations)
|
||||
assert.Equal(t, "Domain", checlusterv1.Spec.Server.CheServerRoute.Domain)
|
||||
assert.Equal(t, "Hostname", checlusterv1.Spec.Server.CheHost)
|
||||
assert.Equal(t, "a=b,c=d", checlusterv1.Spec.Server.CheServerRoute.Labels)
|
||||
assert.Equal(t, "tlsSecret", checlusterv1.Spec.Server.CheHostTLSSecret)
|
||||
}
|
||||
|
||||
func TestConvertFrom(t *testing.T) {
|
||||
infrastructure.InitializeForTesting(infrastructure.Kubernetes)
|
||||
|
||||
checlusterv2 := &chev2.CheCluster{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "eclipse-che",
|
||||
Namespace: "eclipse-che",
|
||||
},
|
||||
Spec: chev2.CheClusterSpec{
|
||||
Components: chev2.CheClusterComponents{
|
||||
Metrics: chev2.ServerMetrics{
|
||||
Enable: true,
|
||||
},
|
||||
Database: chev2.Database{
|
||||
ExternalDb: true,
|
||||
Deployment: chev2.Deployment{
|
||||
Containers: []chev2.Container{
|
||||
{
|
||||
Image: "DatabaseImage",
|
||||
ImagePullPolicy: corev1.PullAlways,
|
||||
Resources: chev2.ResourceRequirements{
|
||||
Requests: chev2.ResourceList{
|
||||
Memory: resource.MustParse("128Mi"),
|
||||
Cpu: resource.MustParse("1"),
|
||||
},
|
||||
Limits: chev2.ResourceList{
|
||||
Memory: resource.MustParse("228Mi"),
|
||||
Cpu: resource.MustParse("2"),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
SecurityContext: chev2.PodSecurityContext{
|
||||
RunAsUser: pointer.Int64Ptr(64),
|
||||
FsGroup: pointer.Int64Ptr(65),
|
||||
},
|
||||
},
|
||||
PostgresHostName: "PostgresHostName",
|
||||
PostgresPort: "PostgresPort",
|
||||
PostgresDb: "PostgresDb",
|
||||
CredentialsSecretName: "DatabaseCredentialsSecretName",
|
||||
Pvc: chev2.PVC{
|
||||
ClaimSize: "DatabaseClaimSize",
|
||||
StorageClass: "DatabaseStorageClass",
|
||||
},
|
||||
},
|
||||
PluginRegistry: chev2.PluginRegistry{
|
||||
Deployment: chev2.Deployment{
|
||||
Containers: []chev2.Container{
|
||||
{
|
||||
Image: "PluginRegistryImage",
|
||||
ImagePullPolicy: corev1.PullAlways,
|
||||
Resources: chev2.ResourceRequirements{
|
||||
Requests: chev2.ResourceList{
|
||||
Memory: resource.MustParse("128Mi"),
|
||||
Cpu: resource.MustParse("1"),
|
||||
},
|
||||
Limits: chev2.ResourceList{
|
||||
Memory: resource.MustParse("228Mi"),
|
||||
Cpu: resource.MustParse("2"),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
SecurityContext: chev2.PodSecurityContext{
|
||||
RunAsUser: pointer.Int64Ptr(64),
|
||||
FsGroup: pointer.Int64Ptr(65),
|
||||
},
|
||||
},
|
||||
DisableInternalRegistry: true,
|
||||
ExternalPluginRegistries: []chev2.ExternalPluginRegistry{
|
||||
{
|
||||
Url: "ExternalPluginRegistries_1",
|
||||
},
|
||||
{
|
||||
Url: "ExternalPluginRegistries_2",
|
||||
},
|
||||
},
|
||||
},
|
||||
DevfileRegistry: chev2.DevfileRegistry{
|
||||
Deployment: chev2.Deployment{
|
||||
Containers: []chev2.Container{
|
||||
{
|
||||
Image: "DevfileRegistryImage",
|
||||
ImagePullPolicy: corev1.PullAlways,
|
||||
Resources: chev2.ResourceRequirements{
|
||||
Requests: chev2.ResourceList{
|
||||
Memory: resource.MustParse("128Mi"),
|
||||
Cpu: resource.MustParse("1"),
|
||||
},
|
||||
Limits: chev2.ResourceList{
|
||||
Memory: resource.MustParse("228Mi"),
|
||||
Cpu: resource.MustParse("2"),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
SecurityContext: chev2.PodSecurityContext{
|
||||
RunAsUser: pointer.Int64Ptr(64),
|
||||
FsGroup: pointer.Int64Ptr(65),
|
||||
},
|
||||
},
|
||||
DisableInternalRegistry: true,
|
||||
ExternalDevfileRegistries: []chev2.ExternalDevfileRegistry{
|
||||
{
|
||||
Url: "ExternalDevfileRegistries",
|
||||
},
|
||||
},
|
||||
},
|
||||
Dashboard: chev2.Dashboard{
|
||||
Deployment: chev2.Deployment{
|
||||
Containers: []chev2.Container{
|
||||
{
|
||||
Image: "DashboardImage",
|
||||
ImagePullPolicy: corev1.PullAlways,
|
||||
Resources: chev2.ResourceRequirements{
|
||||
Requests: chev2.ResourceList{
|
||||
Memory: resource.MustParse("128Mi"),
|
||||
Cpu: resource.MustParse("1"),
|
||||
},
|
||||
Limits: chev2.ResourceList{
|
||||
Memory: resource.MustParse("228Mi"),
|
||||
Cpu: resource.MustParse("2"),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
SecurityContext: chev2.PodSecurityContext{
|
||||
RunAsUser: pointer.Int64Ptr(64),
|
||||
FsGroup: pointer.Int64Ptr(65),
|
||||
},
|
||||
},
|
||||
HeaderMessage: chev2.DashboardHeaderMessage{
|
||||
Show: true,
|
||||
Text: "DashboardWarning",
|
||||
},
|
||||
},
|
||||
ImagePuller: chev2.ImagePuller{
|
||||
Enable: true,
|
||||
},
|
||||
CheServer: chev2.CheServer{
|
||||
ExtraProperties: map[string]string{"a": "b", "c": "d"},
|
||||
Deployment: chev2.Deployment{
|
||||
Containers: []chev2.Container{
|
||||
{
|
||||
Image: "ServerImage:ServerTag",
|
||||
ImagePullPolicy: corev1.PullAlways,
|
||||
Resources: chev2.ResourceRequirements{
|
||||
Requests: chev2.ResourceList{
|
||||
Memory: resource.MustParse("128Mi"),
|
||||
Cpu: resource.MustParse("1"),
|
||||
},
|
||||
Limits: chev2.ResourceList{
|
||||
Memory: resource.MustParse("228Mi"),
|
||||
Cpu: resource.MustParse("2"),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
SecurityContext: chev2.PodSecurityContext{
|
||||
RunAsUser: pointer.Int64Ptr(64),
|
||||
FsGroup: pointer.Int64Ptr(65),
|
||||
},
|
||||
},
|
||||
LogLevel: "LogLevel",
|
||||
Debug: pointer.BoolPtr(true),
|
||||
ClusterRoles: []string{"ClusterRoles_1", "ClusterRoles_2"},
|
||||
Proxy: chev2.Proxy{
|
||||
Url: "ProxyUrl",
|
||||
Port: "ProxyPort",
|
||||
NonProxyHosts: []string{"NonProxyHosts_1", "NonProxyHosts_2"},
|
||||
CredentialsSecretName: "ProxyCredentialsSecretName",
|
||||
},
|
||||
},
|
||||
DevWorkspace: chev2.DevWorkspace{
|
||||
Deployment: chev2.Deployment{
|
||||
Containers: []chev2.Container{
|
||||
{
|
||||
Image: "DevWorkspaceImage",
|
||||
},
|
||||
},
|
||||
},
|
||||
RunningLimit: "RunningLimit",
|
||||
},
|
||||
},
|
||||
Networking: chev2.CheClusterSpecNetworking{
|
||||
Auth: chev2.Auth{
|
||||
IdentityProviderURL: "IdentityProviderURL",
|
||||
OAuthClientName: "OAuthClientName",
|
||||
OAuthSecret: "OAuthSecret",
|
||||
Gateway: chev2.Gateway{
|
||||
Deployment: chev2.Deployment{
|
||||
Containers: []chev2.Container{
|
||||
{
|
||||
Name: "gateway",
|
||||
Image: "GatewayImage",
|
||||
},
|
||||
{
|
||||
Name: "configbump",
|
||||
Image: "ConfigSidecarImage",
|
||||
},
|
||||
{
|
||||
Name: "oauth-proxy",
|
||||
Image: "AuthenticationSidecarImage",
|
||||
},
|
||||
{
|
||||
Name: "kube-rbac-proxy",
|
||||
Image: "AuthorizationSidecarImage",
|
||||
},
|
||||
},
|
||||
},
|
||||
ConfigLabels: map[string]string{"a": "b", "c": "d"},
|
||||
},
|
||||
},
|
||||
},
|
||||
DevEnvironments: chev2.CheClusterDevEnvironments{
|
||||
DefaultNamespace: chev2.DefaultNamespace{
|
||||
Template: "WorkspaceNamespaceName",
|
||||
},
|
||||
TrustedCerts: chev2.TrustedCerts{
|
||||
GitTrustedCertsConfigMapName: "che-git-self-signed-cert",
|
||||
},
|
||||
Storage: chev2.WorkspaceStorage{
|
||||
Pvc: chev2.PVC{
|
||||
ClaimSize: "StorageClaimSize",
|
||||
StorageClass: "StorageClass",
|
||||
},
|
||||
PvcStrategy: "PvcStrategy",
|
||||
},
|
||||
DefaultPlugins: []chev2.WorkspaceDefaultPlugins{
|
||||
{
|
||||
Editor: "Editor",
|
||||
Plugins: []string{"Plugins_1", "Plugins_2"},
|
||||
},
|
||||
},
|
||||
NodeSelector: map[string]string{"a": "b", "c": "d"},
|
||||
Tolerations: []corev1.Toleration{{
|
||||
Key: "Key",
|
||||
Operator: "Operator",
|
||||
Value: "Value",
|
||||
Effect: "Effect",
|
||||
}},
|
||||
},
|
||||
ContainerRegistry: chev2.CheClusterContainerRegistry{
|
||||
Hostname: "AirGapContainerRegistryHostname",
|
||||
Organization: "AirGapContainerRegistryOrganization",
|
||||
},
|
||||
},
|
||||
Status: chev2.CheClusterStatus{
|
||||
CheVersion: "CheVersion",
|
||||
CheURL: "CheURL",
|
||||
DevfileRegistryURL: "DevfileRegistryURL",
|
||||
PluginRegistryURL: "PluginRegistryURL",
|
||||
ChePhase: "Active",
|
||||
Message: "Message",
|
||||
Reason: "Reason",
|
||||
PostgresVersion: "PostgresVersion",
|
||||
},
|
||||
}
|
||||
|
||||
checlusterv1 := &chev1.CheCluster{}
|
||||
err := checlusterv1.ConvertFrom(checlusterv2)
|
||||
assert.Nil(t, err)
|
||||
|
||||
assert.Equal(t, checlusterv1.ObjectMeta.Name, "eclipse-che")
|
||||
assert.Equal(t, checlusterv1.ObjectMeta.Namespace, "eclipse-che")
|
||||
|
||||
assert.Equal(t, checlusterv1.Status.CheClusterRunning, "Available")
|
||||
assert.Equal(t, checlusterv1.Status.CheURL, "CheURL")
|
||||
assert.Equal(t, checlusterv1.Status.CheVersion, "CheVersion")
|
||||
assert.Equal(t, checlusterv1.Status.DevfileRegistryURL, "DevfileRegistryURL")
|
||||
assert.Equal(t, checlusterv1.Status.Message, "Message")
|
||||
assert.Equal(t, checlusterv1.Status.PluginRegistryURL, "PluginRegistryURL")
|
||||
assert.Equal(t, checlusterv1.Status.Reason, "Reason")
|
||||
assert.Equal(t, checlusterv1.Status.GitServerTLSCertificateConfigMapName, "che-git-self-signed-cert")
|
||||
|
||||
assert.Equal(t, checlusterv1.Spec.Auth.GatewayAuthenticationSidecarImage, "AuthenticationSidecarImage")
|
||||
assert.Equal(t, checlusterv1.Spec.Auth.GatewayAuthorizationSidecarImage, "AuthorizationSidecarImage")
|
||||
assert.Equal(t, checlusterv1.Spec.Auth.IdentityProviderURL, "IdentityProviderURL")
|
||||
assert.Equal(t, checlusterv1.Spec.Auth.OAuthClientName, "OAuthClientName")
|
||||
assert.Equal(t, checlusterv1.Spec.Auth.OAuthSecret, "OAuthSecret")
|
||||
|
||||
assert.Equal(t, checlusterv1.Spec.Database.ChePostgresContainerResources.Limits.Cpu, "2")
|
||||
assert.Equal(t, checlusterv1.Spec.Database.ChePostgresContainerResources.Limits.Memory, "228Mi")
|
||||
assert.Equal(t, checlusterv1.Spec.Database.ChePostgresContainerResources.Requests.Cpu, "1")
|
||||
assert.Equal(t, checlusterv1.Spec.Database.ChePostgresContainerResources.Requests.Memory, "128Mi")
|
||||
assert.Equal(t, checlusterv1.Spec.Database.ChePostgresDb, "PostgresDb")
|
||||
assert.Equal(t, checlusterv1.Spec.Database.ChePostgresHostName, "PostgresHostName")
|
||||
assert.Equal(t, checlusterv1.Spec.Database.ChePostgresPort, "PostgresPort")
|
||||
assert.Equal(t, checlusterv1.Spec.Database.ChePostgresSecret, "DatabaseCredentialsSecretName")
|
||||
assert.Equal(t, checlusterv1.Spec.Database.ExternalDb, true)
|
||||
assert.Equal(t, checlusterv1.Spec.Database.PostgresImage, "DatabaseImage")
|
||||
assert.Equal(t, checlusterv1.Spec.Database.PostgresImagePullPolicy, corev1.PullAlways)
|
||||
assert.Equal(t, checlusterv1.Spec.Database.PostgresVersion, "PostgresVersion")
|
||||
assert.Equal(t, checlusterv1.Spec.Database.PvcClaimSize, "DatabaseClaimSize")
|
||||
|
||||
assert.Equal(t, checlusterv1.Spec.DevWorkspace.ControllerImage, "DevWorkspaceImage")
|
||||
assert.Equal(t, checlusterv1.Spec.DevWorkspace.RunningLimit, "RunningLimit")
|
||||
assert.True(t, checlusterv1.Spec.DevWorkspace.Enable)
|
||||
|
||||
assert.Equal(t, checlusterv1.Spec.Dashboard.Warning, "DashboardWarning")
|
||||
|
||||
assert.Equal(t, checlusterv1.Spec.ImagePuller.Enable, true)
|
||||
assert.Equal(t, checlusterv1.Spec.Metrics.Enable, true)
|
||||
|
||||
assert.Equal(t, checlusterv1.Spec.Server.AirGapContainerRegistryHostname, "AirGapContainerRegistryHostname")
|
||||
assert.Equal(t, checlusterv1.Spec.Server.AirGapContainerRegistryOrganization, "AirGapContainerRegistryOrganization")
|
||||
assert.Equal(t, checlusterv1.Spec.Server.CheClusterRoles, "ClusterRoles_1,ClusterRoles_2")
|
||||
assert.Equal(t, checlusterv1.Spec.Server.CheDebug, "true")
|
||||
assert.Equal(t, checlusterv1.Spec.Server.CheImage, "ServerImage")
|
||||
assert.Equal(t, checlusterv1.Spec.Server.CheImagePullPolicy, corev1.PullPolicy("Always"))
|
||||
assert.Equal(t, checlusterv1.Spec.Server.CheImageTag, "ServerTag")
|
||||
assert.Equal(t, checlusterv1.Spec.Server.CheLogLevel, "LogLevel")
|
||||
assert.Equal(t, checlusterv1.Spec.Server.CustomCheProperties, map[string]string{"a": "b", "c": "d"})
|
||||
assert.Equal(t, checlusterv1.Spec.Server.DashboardCpuLimit, "2")
|
||||
assert.Equal(t, checlusterv1.Spec.Server.DashboardCpuRequest, "1")
|
||||
assert.Equal(t, checlusterv1.Spec.Server.DashboardImage, "DashboardImage")
|
||||
assert.Equal(t, checlusterv1.Spec.Server.DashboardImagePullPolicy, "Always")
|
||||
assert.Equal(t, checlusterv1.Spec.Server.DashboardMemoryLimit, "228Mi")
|
||||
assert.Equal(t, checlusterv1.Spec.Server.DashboardMemoryRequest, "128Mi")
|
||||
assert.Equal(t, checlusterv1.Spec.Server.DevfileRegistryCpuLimit, "2")
|
||||
assert.Equal(t, checlusterv1.Spec.Server.DevfileRegistryCpuRequest, "1")
|
||||
assert.Equal(t, checlusterv1.Spec.Server.DevfileRegistryImage, "DevfileRegistryImage")
|
||||
assert.Equal(t, checlusterv1.Spec.Server.DevfileRegistryMemoryLimit, "228Mi")
|
||||
assert.Equal(t, checlusterv1.Spec.Server.DevfileRegistryMemoryRequest, "128Mi")
|
||||
assert.Equal(t, checlusterv1.Spec.Server.DevfileRegistryPullPolicy, corev1.PullPolicy("Always"))
|
||||
assert.Equal(t, checlusterv1.Spec.Server.ExternalDevfileRegistries, []chev1.ExternalDevfileRegistries{{Url: "ExternalDevfileRegistries"}})
|
||||
assert.Equal(t, checlusterv1.Spec.Server.ExternalDevfileRegistry, true)
|
||||
assert.Equal(t, checlusterv1.Spec.Server.ExternalPluginRegistry, true)
|
||||
assert.Equal(t, checlusterv1.Spec.Server.GitSelfSignedCert, true)
|
||||
assert.Equal(t, checlusterv1.Spec.Server.NonProxyHosts, "NonProxyHosts_1|NonProxyHosts_2")
|
||||
assert.Equal(t, checlusterv1.Spec.Server.PluginRegistryCpuLimit, "2")
|
||||
assert.Equal(t, checlusterv1.Spec.Server.PluginRegistryCpuRequest, "1")
|
||||
assert.Equal(t, checlusterv1.Spec.Server.PluginRegistryImage, "PluginRegistryImage")
|
||||
assert.Equal(t, checlusterv1.Spec.Server.PluginRegistryMemoryLimit, "228Mi")
|
||||
assert.Equal(t, checlusterv1.Spec.Server.PluginRegistryMemoryRequest, "128Mi")
|
||||
assert.Equal(t, checlusterv1.Spec.Server.PluginRegistryPullPolicy, corev1.PullPolicy("Always"))
|
||||
assert.Equal(t, checlusterv1.Spec.Server.PluginRegistryUrl, "ExternalPluginRegistries_1")
|
||||
assert.Equal(t, checlusterv1.Spec.Server.ProxyPort, "ProxyPort")
|
||||
assert.Equal(t, checlusterv1.Spec.Server.ProxySecret, "ProxyCredentialsSecretName")
|
||||
assert.Equal(t, checlusterv1.Spec.Server.ProxyURL, "ProxyUrl")
|
||||
assert.Equal(t, checlusterv1.Spec.Server.ServerCpuLimit, "2")
|
||||
assert.Equal(t, checlusterv1.Spec.Server.ServerCpuRequest, "1")
|
||||
assert.Equal(t, checlusterv1.Spec.Server.ServerMemoryLimit, "228Mi")
|
||||
assert.Equal(t, checlusterv1.Spec.Server.ServerMemoryRequest, "128Mi")
|
||||
assert.Equal(t, checlusterv1.Spec.Server.SingleHostGatewayConfigMapLabels, labels.Set{"a": "b", "c": "d"})
|
||||
assert.Equal(t, checlusterv1.Spec.Server.SingleHostGatewayConfigSidecarImage, "ConfigSidecarImage")
|
||||
assert.Equal(t, checlusterv1.Spec.Server.SingleHostGatewayImage, "GatewayImage")
|
||||
assert.Equal(t, checlusterv1.Spec.Server.WorkspaceNamespaceDefault, "WorkspaceNamespaceName")
|
||||
assert.Equal(t, checlusterv1.Spec.Server.WorkspacePodNodeSelector, map[string]string{"a": "b", "c": "d"})
|
||||
assert.Equal(t, checlusterv1.Spec.Server.WorkspacePodTolerations, []corev1.Toleration{
|
||||
{
|
||||
Key: "Key",
|
||||
Operator: "Operator",
|
||||
Value: "Value",
|
||||
Effect: "Effect",
|
||||
},
|
||||
})
|
||||
assert.Equal(t, checlusterv1.Spec.Server.WorkspacesDefaultPlugins, []chev1.WorkspacesDefaultPlugins{{Editor: "Editor", Plugins: []string{"Plugins_1", "Plugins_2"}}})
|
||||
|
||||
assert.Equal(t, checlusterv1.Spec.Storage.PostgresPVCStorageClassName, "DatabaseStorageClass")
|
||||
assert.Equal(t, checlusterv1.Spec.Storage.PvcClaimSize, "StorageClaimSize")
|
||||
assert.Equal(t, checlusterv1.Spec.Storage.PvcStrategy, "PvcStrategy")
|
||||
assert.Equal(t, checlusterv1.Spec.Storage.WorkspacePVCStorageClassName, "StorageClass")
|
||||
}
|
||||
|
|
@ -0,0 +1,412 @@
|
|||
//
|
||||
// Copyright (c) 2019-2022 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
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"k8s.io/apimachinery/pkg/api/resource"
|
||||
|
||||
"github.com/devfile/devworkspace-operator/pkg/infrastructure"
|
||||
chev1 "github.com/eclipse-che/che-operator/api/v1"
|
||||
chev2 "github.com/eclipse-che/che-operator/api/v2"
|
||||
"github.com/eclipse-che/che-operator/pkg/common/constants"
|
||||
defaults "github.com/eclipse-che/che-operator/pkg/common/operator-defaults"
|
||||
"github.com/stretchr/testify/assert"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
)
|
||||
|
||||
func TestConvertToEmptyCheCluster(t *testing.T) {
|
||||
checlusterv1 := &chev1.CheCluster{}
|
||||
checlusterv2 := &chev2.CheCluster{}
|
||||
|
||||
err := checlusterv1.ConvertTo(checlusterv2)
|
||||
assert.Nil(t, err)
|
||||
}
|
||||
|
||||
func TestConvertToIngressOnOpenShift(t *testing.T) {
|
||||
infrastructure.InitializeForTesting(infrastructure.OpenShiftv4)
|
||||
|
||||
checlusterv1 := &chev1.CheCluster{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "eclipse-che",
|
||||
Namespace: "eclipse-che",
|
||||
},
|
||||
Spec: chev1.CheClusterSpec{
|
||||
Server: chev1.CheClusterSpecServer{
|
||||
CheHost: "CheHost",
|
||||
CheHostTLSSecret: "CheHostTLSSecret",
|
||||
CheServerIngress: chev1.IngressCustomSettings{
|
||||
Labels: "a=b,c=d",
|
||||
},
|
||||
CheServerRoute: chev1.RouteCustomSettings{
|
||||
Labels: "a=b,c=d",
|
||||
Annotations: map[string]string{"a": "b", "c": "d"},
|
||||
Domain: "CheServerRoute.Domain",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
checlusterv2 := &chev2.CheCluster{}
|
||||
err := checlusterv1.ConvertTo(checlusterv2)
|
||||
assert.Nil(t, err)
|
||||
|
||||
assert.Equal(t, map[string]string{"a": "b", "c": "d"}, checlusterv2.Spec.Networking.Annotations)
|
||||
assert.Equal(t, "CheServerRoute.Domain", checlusterv2.Spec.Networking.Domain)
|
||||
assert.Equal(t, "CheHost", checlusterv2.Spec.Networking.Hostname)
|
||||
assert.Equal(t, map[string]string{"a": "b", "c": "d"}, checlusterv2.Spec.Networking.Labels)
|
||||
assert.Equal(t, "CheHostTLSSecret", checlusterv2.Spec.Networking.TlsSecretName)
|
||||
}
|
||||
|
||||
func TestConvertToIngressOnK8s(t *testing.T) {
|
||||
infrastructure.InitializeForTesting(infrastructure.Kubernetes)
|
||||
|
||||
checlusterv1 := &chev1.CheCluster{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "eclipse-che",
|
||||
Namespace: "eclipse-che",
|
||||
},
|
||||
Spec: chev1.CheClusterSpec{
|
||||
Server: chev1.CheClusterSpecServer{
|
||||
CheHost: "CheHost",
|
||||
CheServerIngress: chev1.IngressCustomSettings{
|
||||
Labels: "a=b,c=d",
|
||||
Annotations: map[string]string{"a": "b", "c": "d"},
|
||||
},
|
||||
},
|
||||
K8s: chev1.CheClusterSpecK8SOnly{
|
||||
IngressDomain: "k8s.IngressDomain",
|
||||
IngressClass: "k8s.IngressClass",
|
||||
TlsSecretName: "k8s.TlsSecretName",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
checlusterv2 := &chev2.CheCluster{}
|
||||
err := checlusterv1.ConvertTo(checlusterv2)
|
||||
assert.Nil(t, err)
|
||||
|
||||
assert.Equal(t, map[string]string{"a": "b", "c": "d", "kubernetes.io/ingress.class": "k8s.IngressClass"}, checlusterv2.Spec.Networking.Annotations)
|
||||
assert.Equal(t, "k8s.IngressDomain", checlusterv2.Spec.Networking.Domain)
|
||||
assert.Equal(t, "CheHost", checlusterv2.Spec.Networking.Hostname)
|
||||
assert.Equal(t, map[string]string{"a": "b", "c": "d"}, checlusterv2.Spec.Networking.Labels)
|
||||
assert.Equal(t, "k8s.TlsSecretName", checlusterv2.Spec.Networking.TlsSecretName)
|
||||
}
|
||||
|
||||
func TestConvertToIngressOnK8sWithCheHostTLSSecret(t *testing.T) {
|
||||
infrastructure.InitializeForTesting(infrastructure.Kubernetes)
|
||||
|
||||
checlusterv1 := &chev1.CheCluster{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "eclipse-che",
|
||||
Namespace: "eclipse-che",
|
||||
},
|
||||
Spec: chev1.CheClusterSpec{
|
||||
Server: chev1.CheClusterSpecServer{
|
||||
CheHost: "CheHost",
|
||||
CheHostTLSSecret: "CheHostTLSSecret",
|
||||
CheServerIngress: chev1.IngressCustomSettings{
|
||||
Labels: "a=b,c=d",
|
||||
Annotations: map[string]string{"a": "b", "c": "d"},
|
||||
},
|
||||
},
|
||||
K8s: chev1.CheClusterSpecK8SOnly{
|
||||
IngressDomain: "k8s.IngressDomain",
|
||||
IngressClass: "k8s.IngressClass",
|
||||
TlsSecretName: "k8s.TlsSecretName",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
checlusterv2 := &chev2.CheCluster{}
|
||||
err := checlusterv1.ConvertTo(checlusterv2)
|
||||
assert.Nil(t, err)
|
||||
|
||||
assert.Equal(t, map[string]string{"a": "b", "c": "d", "kubernetes.io/ingress.class": "k8s.IngressClass"}, checlusterv2.Spec.Networking.Annotations)
|
||||
assert.Equal(t, "k8s.IngressDomain", checlusterv2.Spec.Networking.Domain)
|
||||
assert.Equal(t, "CheHost", checlusterv2.Spec.Networking.Hostname)
|
||||
assert.Equal(t, map[string]string{"a": "b", "c": "d"}, checlusterv2.Spec.Networking.Labels)
|
||||
assert.Equal(t, "CheHostTLSSecret", checlusterv2.Spec.Networking.TlsSecretName)
|
||||
}
|
||||
|
||||
func TestConvertTo(t *testing.T) {
|
||||
infrastructure.InitializeForTesting(infrastructure.Kubernetes)
|
||||
|
||||
checlusterv1 := &chev1.CheCluster{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "eclipse-che",
|
||||
Namespace: "eclipse-che",
|
||||
},
|
||||
Spec: chev1.CheClusterSpec{
|
||||
Server: chev1.CheClusterSpecServer{
|
||||
AirGapContainerRegistryHostname: "AirGapContainerRegistryHostname",
|
||||
AirGapContainerRegistryOrganization: "AirGapContainerRegistryOrganization",
|
||||
CheImage: "CheImage",
|
||||
CheImageTag: "CheImageTag",
|
||||
CheImagePullPolicy: "Always",
|
||||
CheLogLevel: "CheLogLevel",
|
||||
CheDebug: "true",
|
||||
CheClusterRoles: "CheClusterRoles_1,CheClusterRoles_2",
|
||||
CheWorkspaceClusterRole: "CheWorkspaceClusterRole",
|
||||
WorkspaceNamespaceDefault: "WorkspaceNamespaceDefault",
|
||||
ServerTrustStoreConfigMapName: "ServerTrustStoreConfigMapName",
|
||||
GitSelfSignedCert: true,
|
||||
DashboardImage: "DashboardImage",
|
||||
DashboardImagePullPolicy: "Always",
|
||||
DashboardMemoryLimit: "200Mi",
|
||||
DashboardMemoryRequest: "100Mi",
|
||||
DashboardCpuLimit: "2",
|
||||
DashboardCpuRequest: "1",
|
||||
DevfileRegistryImage: "DevfileRegistryImage",
|
||||
DevfileRegistryPullPolicy: "Always",
|
||||
DevfileRegistryMemoryLimit: "200Mi",
|
||||
DevfileRegistryMemoryRequest: "100Mi",
|
||||
DevfileRegistryCpuLimit: "2",
|
||||
DevfileRegistryCpuRequest: "1",
|
||||
ExternalDevfileRegistry: true,
|
||||
ExternalDevfileRegistries: []chev1.ExternalDevfileRegistries{
|
||||
{
|
||||
Url: "ExternalDevfileRegistries_1",
|
||||
},
|
||||
{
|
||||
Url: "ExternalDevfileRegistries_2",
|
||||
},
|
||||
},
|
||||
PluginRegistryUrl: "PluginRegistryUrl",
|
||||
PluginRegistryImage: "PluginRegistryImage",
|
||||
PluginRegistryPullPolicy: "Always",
|
||||
PluginRegistryMemoryLimit: "200Mi",
|
||||
PluginRegistryMemoryRequest: "100Mi",
|
||||
PluginRegistryCpuLimit: "2",
|
||||
PluginRegistryCpuRequest: "1",
|
||||
ExternalPluginRegistry: true,
|
||||
CustomCheProperties: map[string]string{"a": "b", "c": "d"},
|
||||
ProxyURL: "ProxyURL",
|
||||
ProxyPort: "ProxyPort",
|
||||
ProxySecret: "ProxySecret",
|
||||
NonProxyHosts: "NonProxyHosts_1|NonProxyHosts_2",
|
||||
ServerMemoryRequest: "100Mi",
|
||||
ServerMemoryLimit: "200Mi",
|
||||
ServerCpuLimit: "2",
|
||||
ServerCpuRequest: "1",
|
||||
SingleHostGatewayImage: "SingleHostGatewayImage",
|
||||
SingleHostGatewayConfigSidecarImage: "SingleHostGatewayConfigSidecarImage",
|
||||
SingleHostGatewayConfigMapLabels: map[string]string{"a": "b", "c": "d"},
|
||||
WorkspacesDefaultPlugins: []chev1.WorkspacesDefaultPlugins{
|
||||
{
|
||||
Editor: "Editor",
|
||||
Plugins: []string{"Plugin_1,Plugin_2"},
|
||||
},
|
||||
},
|
||||
WorkspacePodNodeSelector: map[string]string{"a": "b", "c": "d"},
|
||||
WorkspacePodTolerations: []corev1.Toleration{
|
||||
{
|
||||
Key: "Key",
|
||||
Operator: "Operator",
|
||||
Value: "Value",
|
||||
Effect: "Effect",
|
||||
},
|
||||
},
|
||||
},
|
||||
Database: chev1.CheClusterSpecDB{
|
||||
ExternalDb: true,
|
||||
ChePostgresHostName: "ChePostgresHostName",
|
||||
ChePostgresPort: "ChePostgresPort",
|
||||
ChePostgresDb: "ChePostgresDb",
|
||||
ChePostgresSecret: "ChePostgresSecret",
|
||||
PostgresImage: "PostgresImage",
|
||||
PostgresVersion: "PostgresVersion",
|
||||
PostgresImagePullPolicy: "Always",
|
||||
PvcClaimSize: "DatabasePvcClaimSize",
|
||||
ChePostgresContainerResources: chev1.ResourcesCustomSettings{
|
||||
Requests: chev1.Resources{
|
||||
Memory: "100Mi",
|
||||
Cpu: "1",
|
||||
},
|
||||
Limits: chev1.Resources{
|
||||
Memory: "200Mi",
|
||||
Cpu: "2",
|
||||
},
|
||||
},
|
||||
},
|
||||
Auth: chev1.CheClusterSpecAuth{
|
||||
IdentityProviderURL: "IdentityProviderURL",
|
||||
OAuthClientName: "OAuthClientName",
|
||||
OAuthSecret: "OAuthSecret",
|
||||
GatewayAuthenticationSidecarImage: "GatewayAuthenticationSidecarImage",
|
||||
GatewayAuthorizationSidecarImage: "GatewayAuthorizationSidecarImage",
|
||||
},
|
||||
Storage: chev1.CheClusterSpecStorage{
|
||||
PvcStrategy: "PvcStrategy",
|
||||
PvcClaimSize: "WorkspacePvcClaimSize",
|
||||
PostgresPVCStorageClassName: "PostgresPVCStorageClassName",
|
||||
WorkspacePVCStorageClassName: "WorkspacePVCStorageClassName",
|
||||
},
|
||||
Metrics: chev1.CheClusterSpecMetrics{
|
||||
Enable: true,
|
||||
},
|
||||
K8s: chev1.CheClusterSpecK8SOnly{
|
||||
SecurityContextFsGroup: "64",
|
||||
SecurityContextRunAsUser: "65",
|
||||
},
|
||||
ImagePuller: chev1.CheClusterSpecImagePuller{
|
||||
Enable: true,
|
||||
},
|
||||
DevWorkspace: chev1.CheClusterSpecDevWorkspace{
|
||||
Enable: true,
|
||||
ControllerImage: "ControllerImage",
|
||||
RunningLimit: "RunningLimit",
|
||||
},
|
||||
Dashboard: chev1.CheClusterSpecDashboard{
|
||||
Warning: "DashboardWarning",
|
||||
},
|
||||
},
|
||||
Status: chev1.CheClusterStatus{
|
||||
CheClusterRunning: "Available",
|
||||
CheVersion: "CheVersion",
|
||||
CheURL: "CheURL",
|
||||
Message: "Message",
|
||||
Reason: "Reason",
|
||||
HelpLink: "HelpLink",
|
||||
DevfileRegistryURL: "DevfileRegistryURL",
|
||||
PluginRegistryURL: "PluginRegistryURL",
|
||||
},
|
||||
}
|
||||
|
||||
checlusterv2 := &chev2.CheCluster{}
|
||||
err := checlusterv1.ConvertTo(checlusterv2)
|
||||
assert.Nil(t, err)
|
||||
|
||||
assert.Equal(t, checlusterv2.ObjectMeta.Name, "eclipse-che")
|
||||
assert.Equal(t, checlusterv2.ObjectMeta.Namespace, "eclipse-che")
|
||||
|
||||
assert.Equal(t, checlusterv2.Spec.Networking.Auth.Gateway.Deployment.Containers[0].Name, constants.GatewayContainerName)
|
||||
assert.Equal(t, checlusterv2.Spec.Networking.Auth.Gateway.Deployment.Containers[0].Image, "SingleHostGatewayImage")
|
||||
assert.Equal(t, checlusterv2.Spec.Networking.Auth.Gateway.Deployment.Containers[1].Name, constants.GatewayConfigSideCarContainerName)
|
||||
assert.Equal(t, checlusterv2.Spec.Networking.Auth.Gateway.Deployment.Containers[1].Image, "SingleHostGatewayConfigSidecarImage")
|
||||
assert.Equal(t, checlusterv2.Spec.Networking.Auth.Gateway.Deployment.Containers[2].Name, constants.GatewayAuthenticationContainerName)
|
||||
assert.Equal(t, checlusterv2.Spec.Networking.Auth.Gateway.Deployment.Containers[2].Image, "GatewayAuthenticationSidecarImage")
|
||||
assert.Equal(t, checlusterv2.Spec.Networking.Auth.Gateway.Deployment.Containers[3].Name, constants.GatewayAuthorizationContainerName)
|
||||
assert.Equal(t, checlusterv2.Spec.Networking.Auth.Gateway.Deployment.Containers[3].Image, "GatewayAuthorizationSidecarImage")
|
||||
assert.Equal(t, checlusterv2.Spec.Networking.Auth.Gateway.ConfigLabels, map[string]string{"a": "b", "c": "d"})
|
||||
assert.Equal(t, checlusterv2.Spec.Networking.Auth.IdentityProviderURL, "IdentityProviderURL")
|
||||
assert.Equal(t, checlusterv2.Spec.Networking.Auth.OAuthClientName, "OAuthClientName")
|
||||
assert.Equal(t, checlusterv2.Spec.Networking.Auth.OAuthSecret, "OAuthSecret")
|
||||
|
||||
assert.Equal(t, checlusterv2.Spec.ContainerRegistry.Hostname, "AirGapContainerRegistryHostname")
|
||||
assert.Equal(t, checlusterv2.Spec.ContainerRegistry.Organization, "AirGapContainerRegistryOrganization")
|
||||
assert.Equal(t, checlusterv2.Spec.Components.CheServer.ClusterRoles, []string{"CheClusterRoles_1", "CheClusterRoles_2"})
|
||||
assert.Equal(t, checlusterv2.Spec.Components.CheServer.ExtraProperties, map[string]string{"a": "b", "c": "d"})
|
||||
assert.True(t, *checlusterv2.Spec.Components.CheServer.Debug)
|
||||
assert.Equal(t, checlusterv2.Spec.Components.CheServer.Deployment.Containers[0].Image, "CheImage:CheImageTag")
|
||||
assert.Equal(t, checlusterv2.Spec.Components.CheServer.Deployment.Containers[0].Name, defaults.GetCheFlavor())
|
||||
assert.Equal(t, checlusterv2.Spec.Components.CheServer.Deployment.Containers[0].ImagePullPolicy, corev1.PullPolicy("Always"))
|
||||
assert.Equal(t, checlusterv2.Spec.Components.CheServer.Deployment.Containers[0].Resources.Limits.Cpu, resource.MustParse("2"))
|
||||
assert.Equal(t, checlusterv2.Spec.Components.CheServer.Deployment.Containers[0].Resources.Limits.Memory, resource.MustParse("200Mi"))
|
||||
assert.Equal(t, checlusterv2.Spec.Components.CheServer.Deployment.Containers[0].Resources.Requests.Cpu, resource.MustParse("1"))
|
||||
assert.Equal(t, checlusterv2.Spec.Components.CheServer.Deployment.Containers[0].Resources.Requests.Memory, resource.MustParse("100Mi"))
|
||||
assert.Equal(t, *checlusterv2.Spec.Components.CheServer.Deployment.SecurityContext.FsGroup, int64(64))
|
||||
assert.Equal(t, *checlusterv2.Spec.Components.CheServer.Deployment.SecurityContext.RunAsUser, int64(65))
|
||||
assert.Equal(t, checlusterv2.Spec.DevEnvironments.TrustedCerts.GitTrustedCertsConfigMapName, "che-git-self-signed-cert")
|
||||
assert.Equal(t, checlusterv2.Spec.Components.CheServer.LogLevel, "CheLogLevel")
|
||||
assert.Equal(t, checlusterv2.Spec.Components.CheServer.Proxy.CredentialsSecretName, "ProxySecret")
|
||||
assert.Equal(t, checlusterv2.Spec.Components.CheServer.Proxy.NonProxyHosts, []string{"NonProxyHosts_1", "NonProxyHosts_2"})
|
||||
assert.Equal(t, checlusterv2.Spec.Components.CheServer.Proxy.Port, "ProxyPort")
|
||||
assert.Equal(t, checlusterv2.Spec.Components.CheServer.Proxy.Url, "ProxyURL")
|
||||
assert.Equal(t, checlusterv2.Spec.DevEnvironments.DefaultNamespace.Template, "WorkspaceNamespaceDefault")
|
||||
assert.Equal(t, checlusterv2.Spec.DevEnvironments.NodeSelector, map[string]string{"a": "b", "c": "d"})
|
||||
assert.Equal(t, checlusterv2.Spec.DevEnvironments.Tolerations, []corev1.Toleration{{
|
||||
Key: "Key",
|
||||
Operator: "Operator",
|
||||
Value: "Value",
|
||||
Effect: "Effect",
|
||||
}})
|
||||
assert.Equal(t, checlusterv2.Spec.DevEnvironments.DefaultPlugins, []chev2.WorkspaceDefaultPlugins{{
|
||||
Editor: "Editor",
|
||||
Plugins: []string{"Plugin_1,Plugin_2"},
|
||||
}})
|
||||
|
||||
assert.Equal(t, checlusterv2.Spec.Components.Dashboard.Deployment.Containers[0].Name, defaults.GetCheFlavor()+"-dashboard")
|
||||
assert.Equal(t, checlusterv2.Spec.Components.Dashboard.Deployment.Containers[0].Image, "DashboardImage")
|
||||
assert.Equal(t, checlusterv2.Spec.Components.Dashboard.Deployment.Containers[0].ImagePullPolicy, corev1.PullPolicy("Always"))
|
||||
assert.Equal(t, checlusterv2.Spec.Components.Dashboard.Deployment.Containers[0].Resources.Limits.Cpu, resource.MustParse("2"))
|
||||
assert.Equal(t, checlusterv2.Spec.Components.Dashboard.Deployment.Containers[0].Resources.Limits.Memory, resource.MustParse("200Mi"))
|
||||
assert.Equal(t, checlusterv2.Spec.Components.Dashboard.Deployment.Containers[0].Resources.Requests.Cpu, resource.MustParse("1"))
|
||||
assert.Equal(t, checlusterv2.Spec.Components.Dashboard.Deployment.Containers[0].Resources.Requests.Memory, resource.MustParse("100Mi"))
|
||||
assert.Equal(t, *checlusterv2.Spec.Components.Dashboard.Deployment.SecurityContext.FsGroup, int64(64))
|
||||
assert.Equal(t, *checlusterv2.Spec.Components.Dashboard.Deployment.SecurityContext.RunAsUser, int64(65))
|
||||
assert.Equal(t, checlusterv2.Spec.Components.Dashboard.HeaderMessage.Text, "DashboardWarning")
|
||||
assert.True(t, checlusterv2.Spec.Components.Dashboard.HeaderMessage.Show)
|
||||
|
||||
assert.Equal(t, checlusterv2.Spec.Components.Database.CredentialsSecretName, "ChePostgresSecret")
|
||||
assert.Equal(t, checlusterv2.Spec.Components.Database.Deployment.Containers[0].Name, constants.PostgresName)
|
||||
assert.Equal(t, checlusterv2.Spec.Components.Database.Deployment.Containers[0].Image, "PostgresImage")
|
||||
assert.Equal(t, checlusterv2.Spec.Components.Database.Deployment.Containers[0].ImagePullPolicy, corev1.PullPolicy("Always"))
|
||||
assert.Equal(t, checlusterv2.Spec.Components.Database.Deployment.Containers[0].Resources.Limits.Cpu, resource.MustParse("2"))
|
||||
assert.Equal(t, checlusterv2.Spec.Components.Database.Deployment.Containers[0].Resources.Limits.Memory, resource.MustParse("200Mi"))
|
||||
assert.Equal(t, checlusterv2.Spec.Components.Database.Deployment.Containers[0].Resources.Requests.Cpu, resource.MustParse("1"))
|
||||
assert.Equal(t, checlusterv2.Spec.Components.Database.Deployment.Containers[0].Resources.Requests.Memory, resource.MustParse("100Mi"))
|
||||
assert.Equal(t, checlusterv2.Spec.Components.Database.ExternalDb, true)
|
||||
assert.Equal(t, checlusterv2.Spec.Components.Database.PostgresDb, "ChePostgresDb")
|
||||
assert.Equal(t, checlusterv2.Spec.Components.Database.PostgresHostName, "ChePostgresHostName")
|
||||
assert.Equal(t, checlusterv2.Spec.Components.Database.PostgresPort, "ChePostgresPort")
|
||||
assert.Equal(t, checlusterv2.Spec.Components.Database.Pvc.ClaimSize, "DatabasePvcClaimSize")
|
||||
assert.Equal(t, checlusterv2.Spec.Components.Database.Pvc.StorageClass, "PostgresPVCStorageClassName")
|
||||
|
||||
assert.Equal(t, checlusterv2.Spec.Components.DevWorkspace.Deployment.Containers[0].Image, "ControllerImage")
|
||||
assert.Equal(t, checlusterv2.Spec.Components.DevWorkspace.RunningLimit, "RunningLimit")
|
||||
|
||||
assert.Equal(t, checlusterv2.Spec.Components.ImagePuller.Enable, true)
|
||||
assert.Equal(t, checlusterv2.Spec.Components.Metrics.Enable, true)
|
||||
|
||||
assert.Equal(t, checlusterv2.Spec.Components.DevfileRegistry.Deployment.Containers[0].Name, constants.DevfileRegistryName)
|
||||
assert.Equal(t, checlusterv2.Spec.Components.DevfileRegistry.Deployment.Containers[0].Image, "DevfileRegistryImage")
|
||||
assert.Equal(t, checlusterv2.Spec.Components.DevfileRegistry.Deployment.Containers[0].ImagePullPolicy, corev1.PullPolicy("Always"))
|
||||
assert.Equal(t, checlusterv2.Spec.Components.DevfileRegistry.Deployment.Containers[0].Resources.Limits.Cpu, resource.MustParse("2"))
|
||||
assert.Equal(t, checlusterv2.Spec.Components.DevfileRegistry.Deployment.Containers[0].Resources.Limits.Memory, resource.MustParse("200Mi"))
|
||||
assert.Equal(t, checlusterv2.Spec.Components.DevfileRegistry.Deployment.Containers[0].Resources.Requests.Cpu, resource.MustParse("1"))
|
||||
assert.Equal(t, checlusterv2.Spec.Components.DevfileRegistry.Deployment.Containers[0].Resources.Requests.Memory, resource.MustParse("100Mi"))
|
||||
assert.Equal(t, checlusterv2.Spec.Components.DevfileRegistry.DisableInternalRegistry, true)
|
||||
assert.Equal(t, checlusterv2.Spec.Components.DevfileRegistry.ExternalDevfileRegistries, []chev2.ExternalDevfileRegistry{
|
||||
{
|
||||
Url: "ExternalDevfileRegistries_1",
|
||||
},
|
||||
{
|
||||
Url: "ExternalDevfileRegistries_2",
|
||||
}})
|
||||
|
||||
assert.Equal(t, checlusterv2.Spec.Components.PluginRegistry.Deployment.Containers[0].Name, constants.PluginRegistryName)
|
||||
assert.Equal(t, checlusterv2.Spec.Components.PluginRegistry.Deployment.Containers[0].Image, "PluginRegistryImage")
|
||||
assert.Equal(t, checlusterv2.Spec.Components.PluginRegistry.Deployment.Containers[0].ImagePullPolicy, corev1.PullPolicy("Always"))
|
||||
assert.Equal(t, checlusterv2.Spec.Components.PluginRegistry.Deployment.Containers[0].Resources.Limits.Cpu, resource.MustParse("2"))
|
||||
assert.Equal(t, checlusterv2.Spec.Components.PluginRegistry.Deployment.Containers[0].Resources.Limits.Memory, resource.MustParse("200Mi"))
|
||||
assert.Equal(t, checlusterv2.Spec.Components.PluginRegistry.Deployment.Containers[0].Resources.Requests.Cpu, resource.MustParse("1"))
|
||||
assert.Equal(t, checlusterv2.Spec.Components.PluginRegistry.Deployment.Containers[0].Resources.Requests.Memory, resource.MustParse("100Mi"))
|
||||
assert.Equal(t, checlusterv2.Spec.Components.PluginRegistry.DisableInternalRegistry, true)
|
||||
assert.Equal(t, checlusterv2.Spec.Components.PluginRegistry.ExternalPluginRegistries, []chev2.ExternalPluginRegistry{{Url: "PluginRegistryUrl"}})
|
||||
|
||||
assert.Equal(t, checlusterv2.Spec.DevEnvironments.Storage.Pvc.ClaimSize, "WorkspacePvcClaimSize")
|
||||
assert.Equal(t, checlusterv2.Spec.DevEnvironments.Storage.Pvc.StorageClass, "WorkspacePVCStorageClassName")
|
||||
assert.Equal(t, checlusterv2.Spec.DevEnvironments.Storage.PvcStrategy, "PvcStrategy")
|
||||
|
||||
assert.Equal(t, checlusterv2.Status.CheURL, "CheURL")
|
||||
assert.Equal(t, checlusterv2.Status.CheVersion, "CheVersion")
|
||||
assert.Equal(t, checlusterv2.Status.DevfileRegistryURL, "DevfileRegistryURL")
|
||||
assert.Equal(t, checlusterv2.Status.Message, "Message")
|
||||
assert.Equal(t, checlusterv2.Status.ChePhase, chev2.CheClusterPhase("Active"))
|
||||
assert.Equal(t, checlusterv2.Status.PluginRegistryURL, "PluginRegistryURL")
|
||||
assert.Equal(t, checlusterv2.Status.Reason, "Reason")
|
||||
assert.Equal(t, checlusterv2.Status.PostgresVersion, "PostgresVersion")
|
||||
}
|
||||
|
|
@ -0,0 +1,541 @@
|
|||
//
|
||||
// Copyright (c) 2019-2022 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
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/devfile/devworkspace-operator/pkg/infrastructure"
|
||||
"github.com/eclipse-che/che-operator/pkg/common/constants"
|
||||
k8shelper "github.com/eclipse-che/che-operator/pkg/common/k8s-helper"
|
||||
defaults "github.com/eclipse-che/che-operator/pkg/common/operator-defaults"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/api/resource"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/utils/pointer"
|
||||
|
||||
chev1 "github.com/eclipse-che/che-operator/api/v1"
|
||||
chev2 "github.com/eclipse-che/che-operator/api/v2"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestRoundConvertEmptyCheClusterV2(t *testing.T) {
|
||||
f := func() {
|
||||
checlusterv2Orignal := &chev2.CheCluster{}
|
||||
|
||||
checlusterv1 := &chev1.CheCluster{}
|
||||
checlusterv2 := &chev2.CheCluster{}
|
||||
|
||||
err := checlusterv1.ConvertFrom(checlusterv2Orignal)
|
||||
assert.Nil(t, err)
|
||||
|
||||
err = checlusterv1.ConvertTo(checlusterv2)
|
||||
assert.Nil(t, err)
|
||||
|
||||
assert.Equal(t, checlusterv2Orignal, checlusterv2)
|
||||
}
|
||||
|
||||
onKubernetes(f)
|
||||
onOpenShift(f)
|
||||
}
|
||||
|
||||
func TestRoundConvertEmptyCheClusterV1(t *testing.T) {
|
||||
f := func() {
|
||||
checlusterv1Orignal := &chev1.CheCluster{
|
||||
Spec: chev1.CheClusterSpec{
|
||||
DevWorkspace: chev1.CheClusterSpecDevWorkspace{
|
||||
Enable: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
checlusterv1 := &chev1.CheCluster{}
|
||||
checlusterv2 := &chev2.CheCluster{}
|
||||
|
||||
err := checlusterv1Orignal.ConvertTo(checlusterv2)
|
||||
assert.Nil(t, err)
|
||||
|
||||
err = checlusterv1.ConvertFrom(checlusterv2)
|
||||
assert.Nil(t, err)
|
||||
|
||||
assert.Equal(t, checlusterv1Orignal, checlusterv1)
|
||||
}
|
||||
|
||||
onKubernetes(f)
|
||||
onOpenShift(f)
|
||||
}
|
||||
|
||||
func TestRoundConvertCheClusterV2(t *testing.T) {
|
||||
f := func() {
|
||||
checlusterv2Original := &chev2.CheCluster{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "eclipse-che",
|
||||
Namespace: "eclipse-che",
|
||||
},
|
||||
Spec: chev2.CheClusterSpec{
|
||||
Components: chev2.CheClusterComponents{
|
||||
Metrics: chev2.ServerMetrics{
|
||||
Enable: true,
|
||||
},
|
||||
Database: chev2.Database{
|
||||
ExternalDb: true,
|
||||
Deployment: chev2.Deployment{
|
||||
Containers: []chev2.Container{
|
||||
{
|
||||
Name: "postgres",
|
||||
Image: "DatabaseImage",
|
||||
ImagePullPolicy: corev1.PullAlways,
|
||||
Resources: chev2.ResourceRequirements{
|
||||
Requests: chev2.ResourceList{
|
||||
Memory: resource.MustParse("148Mi"),
|
||||
Cpu: resource.MustParse("1"),
|
||||
},
|
||||
Limits: chev2.ResourceList{
|
||||
Memory: resource.MustParse("228Mi"),
|
||||
Cpu: resource.MustParse("2"),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
PostgresHostName: "PostgresHostName",
|
||||
PostgresPort: "PostgresPort",
|
||||
PostgresDb: "PostgresDb",
|
||||
CredentialsSecretName: "DatabaseCredentialsSecretName",
|
||||
Pvc: chev2.PVC{
|
||||
ClaimSize: "DatabaseClaimSize",
|
||||
StorageClass: "DatabaseStorageClass",
|
||||
},
|
||||
},
|
||||
PluginRegistry: chev2.PluginRegistry{
|
||||
Deployment: chev2.Deployment{
|
||||
Containers: []chev2.Container{
|
||||
{
|
||||
Name: "plugin-registry",
|
||||
Image: "PluginRegistryImage",
|
||||
ImagePullPolicy: corev1.PullAlways,
|
||||
Resources: chev2.ResourceRequirements{
|
||||
Requests: chev2.ResourceList{
|
||||
Memory: resource.MustParse("148Mi"),
|
||||
Cpu: resource.MustParse("1"),
|
||||
},
|
||||
Limits: chev2.ResourceList{
|
||||
Memory: resource.MustParse("228Mi"),
|
||||
Cpu: resource.MustParse("2"),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
DisableInternalRegistry: true,
|
||||
ExternalPluginRegistries: []chev2.ExternalPluginRegistry{
|
||||
{
|
||||
Url: "ExternalPluginRegistries_1",
|
||||
},
|
||||
},
|
||||
},
|
||||
DevfileRegistry: chev2.DevfileRegistry{
|
||||
Deployment: chev2.Deployment{
|
||||
Containers: []chev2.Container{
|
||||
{
|
||||
Name: "devfile-registry",
|
||||
Image: "DevfileRegistryImage",
|
||||
ImagePullPolicy: corev1.PullAlways,
|
||||
Resources: chev2.ResourceRequirements{
|
||||
Requests: chev2.ResourceList{
|
||||
Memory: resource.MustParse("148Mi"),
|
||||
Cpu: resource.MustParse("1"),
|
||||
},
|
||||
Limits: chev2.ResourceList{
|
||||
Memory: resource.MustParse("228Mi"),
|
||||
Cpu: resource.MustParse("2"),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
DisableInternalRegistry: true,
|
||||
ExternalDevfileRegistries: []chev2.ExternalDevfileRegistry{
|
||||
{
|
||||
Url: "ExternalDevfileRegistries",
|
||||
},
|
||||
},
|
||||
},
|
||||
Dashboard: chev2.Dashboard{
|
||||
Deployment: chev2.Deployment{
|
||||
Containers: []chev2.Container{
|
||||
{
|
||||
Name: defaults.GetCheFlavor() + "-dashboard",
|
||||
Image: "DashboardImage",
|
||||
ImagePullPolicy: corev1.PullAlways,
|
||||
Resources: chev2.ResourceRequirements{
|
||||
Requests: chev2.ResourceList{
|
||||
Memory: resource.MustParse("148Mi"),
|
||||
Cpu: resource.MustParse("1"),
|
||||
},
|
||||
Limits: chev2.ResourceList{
|
||||
Memory: resource.MustParse("228Mi"),
|
||||
Cpu: resource.MustParse("2"),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
SecurityContext: chev2.PodSecurityContext{
|
||||
RunAsUser: pointer.Int64Ptr(64),
|
||||
FsGroup: pointer.Int64Ptr(65),
|
||||
},
|
||||
},
|
||||
HeaderMessage: chev2.DashboardHeaderMessage{
|
||||
Show: true,
|
||||
Text: "DashboardWarning",
|
||||
},
|
||||
},
|
||||
ImagePuller: chev2.ImagePuller{
|
||||
Enable: true,
|
||||
},
|
||||
CheServer: chev2.CheServer{
|
||||
ExtraProperties: map[string]string{"a": "b", "c": "d"},
|
||||
Deployment: chev2.Deployment{
|
||||
Containers: []chev2.Container{
|
||||
{
|
||||
Name: defaults.GetCheFlavor(),
|
||||
Image: "ServerImage:ServerTag",
|
||||
ImagePullPolicy: corev1.PullAlways,
|
||||
Resources: chev2.ResourceRequirements{
|
||||
Requests: chev2.ResourceList{
|
||||
Memory: resource.MustParse("148Mi"),
|
||||
Cpu: resource.MustParse("1"),
|
||||
},
|
||||
Limits: chev2.ResourceList{
|
||||
Memory: resource.MustParse("228Mi"),
|
||||
Cpu: resource.MustParse("2"),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
SecurityContext: chev2.PodSecurityContext{
|
||||
RunAsUser: pointer.Int64Ptr(64),
|
||||
FsGroup: pointer.Int64Ptr(65),
|
||||
},
|
||||
},
|
||||
LogLevel: "LogLevel",
|
||||
Debug: pointer.BoolPtr(true),
|
||||
ClusterRoles: []string{"ClusterRoles_1", "ClusterRoles_2"},
|
||||
Proxy: chev2.Proxy{
|
||||
Url: "ProxyUrl",
|
||||
Port: "ProxyPort",
|
||||
NonProxyHosts: []string{"NonProxyHosts_1", "NonProxyHosts_2"},
|
||||
CredentialsSecretName: "ProxyCredentialsSecretName",
|
||||
},
|
||||
},
|
||||
DevWorkspace: chev2.DevWorkspace{
|
||||
Deployment: chev2.Deployment{
|
||||
Containers: []chev2.Container{
|
||||
{
|
||||
Name: "devworkspace-controller",
|
||||
Image: "DevWorkspaceImage",
|
||||
},
|
||||
},
|
||||
},
|
||||
RunningLimit: "RunningLimit",
|
||||
},
|
||||
},
|
||||
Networking: chev2.CheClusterSpecNetworking{
|
||||
TlsSecretName: "che-tls",
|
||||
Domain: "domain",
|
||||
Hostname: "hostname",
|
||||
Labels: map[string]string{
|
||||
"label": "value",
|
||||
},
|
||||
Annotations: map[string]string{
|
||||
"kubernetes.io/ingress.class": "nginx",
|
||||
},
|
||||
Auth: chev2.Auth{
|
||||
IdentityProviderURL: "IdentityProviderURL",
|
||||
OAuthClientName: "OAuthClientName",
|
||||
OAuthSecret: "OAuthSecret",
|
||||
Gateway: chev2.Gateway{
|
||||
Deployment: chev2.Deployment{
|
||||
Containers: []chev2.Container{
|
||||
{
|
||||
Name: "gateway",
|
||||
Image: "GatewayImage",
|
||||
},
|
||||
{
|
||||
Name: "configbump",
|
||||
Image: "ConfigSidecarImage",
|
||||
},
|
||||
{
|
||||
Name: "oauth-proxy",
|
||||
Image: "AuthenticationSidecarImage",
|
||||
},
|
||||
{
|
||||
Name: "kube-rbac-proxy",
|
||||
Image: "AuthorizationSidecarImage",
|
||||
},
|
||||
},
|
||||
},
|
||||
ConfigLabels: map[string]string{"a": "b", "c": "d"},
|
||||
},
|
||||
},
|
||||
},
|
||||
DevEnvironments: chev2.CheClusterDevEnvironments{
|
||||
DefaultNamespace: chev2.DefaultNamespace{
|
||||
Template: "WorkspaceNamespaceName",
|
||||
},
|
||||
TrustedCerts: chev2.TrustedCerts{
|
||||
GitTrustedCertsConfigMapName: "che-git-self-signed-cert",
|
||||
},
|
||||
Storage: chev2.WorkspaceStorage{
|
||||
Pvc: chev2.PVC{
|
||||
ClaimSize: "StorageClaimSize",
|
||||
StorageClass: "StorageClass",
|
||||
},
|
||||
PvcStrategy: "PvcStrategy",
|
||||
},
|
||||
DefaultPlugins: []chev2.WorkspaceDefaultPlugins{
|
||||
{
|
||||
Editor: "Editor",
|
||||
Plugins: []string{"Plugins_1", "Plugins_2"},
|
||||
},
|
||||
},
|
||||
NodeSelector: map[string]string{"a": "b", "c": "d"},
|
||||
Tolerations: []corev1.Toleration{{
|
||||
Key: "Key",
|
||||
Operator: "Operator",
|
||||
Value: "Value",
|
||||
Effect: "Effect",
|
||||
}},
|
||||
},
|
||||
ContainerRegistry: chev2.CheClusterContainerRegistry{
|
||||
Hostname: "AirGapContainerRegistryHostname",
|
||||
Organization: "AirGapContainerRegistryOrganization",
|
||||
},
|
||||
},
|
||||
Status: chev2.CheClusterStatus{
|
||||
CheVersion: "CheVersion",
|
||||
CheURL: "CheURL",
|
||||
DevfileRegistryURL: "DevfileRegistryURL",
|
||||
PluginRegistryURL: "PluginRegistryURL",
|
||||
ChePhase: "Active",
|
||||
Message: "Message",
|
||||
Reason: "Reason",
|
||||
PostgresVersion: "PostgresVersion",
|
||||
},
|
||||
}
|
||||
|
||||
checlusterv1 := &chev1.CheCluster{}
|
||||
checlusterv2 := &chev2.CheCluster{}
|
||||
|
||||
err := checlusterv1.ConvertFrom(checlusterv2Original)
|
||||
assert.Nil(t, err)
|
||||
|
||||
err = checlusterv1.ConvertTo(checlusterv2)
|
||||
assert.Nil(t, err)
|
||||
|
||||
assert.Equal(t, checlusterv2Original, checlusterv2)
|
||||
}
|
||||
onKubernetes(f)
|
||||
onOpenShift(f)
|
||||
}
|
||||
|
||||
func TestRoundConvertCheClusterV1(t *testing.T) {
|
||||
f := func() {
|
||||
truststoreConfigMap := &corev1.ConfigMap{
|
||||
TypeMeta: metav1.TypeMeta{
|
||||
Kind: "ConfigMap",
|
||||
APIVersion: "v1",
|
||||
},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: constants.DefaultServerTrustStoreConfigMapName,
|
||||
Namespace: "eclipse-che",
|
||||
},
|
||||
}
|
||||
|
||||
k8sHelper := k8shelper.New()
|
||||
_, err := k8sHelper.GetClientset().CoreV1().ConfigMaps("eclipse-che").Create(context.TODO(), truststoreConfigMap, metav1.CreateOptions{})
|
||||
|
||||
checlusterv1Orignal := &chev1.CheCluster{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "eclipse-che",
|
||||
Namespace: "eclipse-che",
|
||||
},
|
||||
Spec: chev1.CheClusterSpec{
|
||||
Server: chev1.CheClusterSpecServer{
|
||||
AirGapContainerRegistryHostname: "AirGapContainerRegistryHostname",
|
||||
AirGapContainerRegistryOrganization: "AirGapContainerRegistryOrganization",
|
||||
CheImage: "CheImage",
|
||||
CheImageTag: "CheImageTag",
|
||||
CheImagePullPolicy: "Always",
|
||||
CheLogLevel: "CheLogLevel",
|
||||
CheDebug: "true",
|
||||
CheClusterRoles: "CheClusterRoles_1,CheClusterRoles_2",
|
||||
WorkspaceNamespaceDefault: "WorkspaceNamespaceDefault",
|
||||
ServerTrustStoreConfigMapName: constants.DefaultServerTrustStoreConfigMapName,
|
||||
GitSelfSignedCert: true,
|
||||
DashboardImage: "DashboardImage",
|
||||
DashboardImagePullPolicy: "Always",
|
||||
DashboardMemoryLimit: "200Mi",
|
||||
DashboardMemoryRequest: "100Mi",
|
||||
DashboardCpuLimit: "2",
|
||||
DashboardCpuRequest: "1",
|
||||
DevfileRegistryImage: "DevfileRegistryImage",
|
||||
DevfileRegistryPullPolicy: "Always",
|
||||
DevfileRegistryMemoryLimit: "200Mi",
|
||||
DevfileRegistryMemoryRequest: "100Mi",
|
||||
DevfileRegistryCpuLimit: "2",
|
||||
DevfileRegistryCpuRequest: "1",
|
||||
ExternalDevfileRegistry: true,
|
||||
ExternalDevfileRegistries: []chev1.ExternalDevfileRegistries{
|
||||
{
|
||||
Url: "ExternalDevfileRegistries_1",
|
||||
},
|
||||
{
|
||||
Url: "ExternalDevfileRegistries_2",
|
||||
},
|
||||
},
|
||||
PluginRegistryUrl: "PluginRegistryUrl",
|
||||
PluginRegistryImage: "PluginRegistryImage",
|
||||
PluginRegistryPullPolicy: "Always",
|
||||
PluginRegistryMemoryLimit: "200Mi",
|
||||
PluginRegistryMemoryRequest: "100Mi",
|
||||
PluginRegistryCpuLimit: "2",
|
||||
PluginRegistryCpuRequest: "1",
|
||||
ExternalPluginRegistry: true,
|
||||
CustomCheProperties: map[string]string{"a": "b", "c": "d"},
|
||||
ProxyURL: "ProxyURL",
|
||||
ProxyPort: "ProxyPort",
|
||||
ProxySecret: "ProxySecret",
|
||||
NonProxyHosts: "NonProxyHosts_1|NonProxyHosts_2",
|
||||
ServerMemoryRequest: "100Mi",
|
||||
ServerMemoryLimit: "200Mi",
|
||||
ServerCpuLimit: "2",
|
||||
ServerCpuRequest: "1",
|
||||
SingleHostGatewayImage: "SingleHostGatewayImage",
|
||||
SingleHostGatewayConfigSidecarImage: "SingleHostGatewayConfigSidecarImage",
|
||||
SingleHostGatewayConfigMapLabels: map[string]string{"a": "b", "c": "d"},
|
||||
WorkspacesDefaultPlugins: []chev1.WorkspacesDefaultPlugins{
|
||||
{
|
||||
Editor: "Editor",
|
||||
Plugins: []string{"Plugin_1,Plugin_2"},
|
||||
},
|
||||
},
|
||||
WorkspacePodNodeSelector: map[string]string{"a": "b", "c": "d"},
|
||||
WorkspacePodTolerations: []corev1.Toleration{
|
||||
{
|
||||
Key: "Key",
|
||||
Operator: "Operator",
|
||||
Value: "Value",
|
||||
Effect: "Effect",
|
||||
},
|
||||
},
|
||||
},
|
||||
Database: chev1.CheClusterSpecDB{
|
||||
ExternalDb: true,
|
||||
ChePostgresHostName: "ChePostgresHostName",
|
||||
ChePostgresPort: "ChePostgresPort",
|
||||
ChePostgresDb: "ChePostgresDb",
|
||||
ChePostgresSecret: "ChePostgresSecret",
|
||||
PostgresImage: "PostgresImage",
|
||||
PostgresVersion: "PostgresVersion",
|
||||
PostgresImagePullPolicy: "Always",
|
||||
PvcClaimSize: "DatabasePvcClaimSize",
|
||||
ChePostgresContainerResources: chev1.ResourcesCustomSettings{
|
||||
Requests: chev1.Resources{
|
||||
Memory: "100Mi",
|
||||
Cpu: "1",
|
||||
},
|
||||
Limits: chev1.Resources{
|
||||
Memory: "200Mi",
|
||||
Cpu: "2",
|
||||
},
|
||||
},
|
||||
},
|
||||
Auth: chev1.CheClusterSpecAuth{
|
||||
IdentityProviderURL: "IdentityProviderURL",
|
||||
OAuthClientName: "OAuthClientName",
|
||||
OAuthSecret: "OAuthSecret",
|
||||
GatewayAuthenticationSidecarImage: "GatewayAuthenticationSidecarImage",
|
||||
GatewayAuthorizationSidecarImage: "GatewayAuthorizationSidecarImage",
|
||||
},
|
||||
Storage: chev1.CheClusterSpecStorage{
|
||||
PvcStrategy: "PvcStrategy",
|
||||
PvcClaimSize: "WorkspacePvcClaimSize",
|
||||
PostgresPVCStorageClassName: "PostgresPVCStorageClassName",
|
||||
WorkspacePVCStorageClassName: "WorkspacePVCStorageClassName",
|
||||
},
|
||||
Metrics: chev1.CheClusterSpecMetrics{
|
||||
Enable: true,
|
||||
},
|
||||
K8s: chev1.CheClusterSpecK8SOnly{
|
||||
SecurityContextFsGroup: "64",
|
||||
SecurityContextRunAsUser: "65",
|
||||
},
|
||||
ImagePuller: chev1.CheClusterSpecImagePuller{
|
||||
Enable: true,
|
||||
},
|
||||
DevWorkspace: chev1.CheClusterSpecDevWorkspace{
|
||||
Enable: true,
|
||||
ControllerImage: "ControllerImage",
|
||||
RunningLimit: "RunningLimit",
|
||||
},
|
||||
Dashboard: chev1.CheClusterSpecDashboard{
|
||||
Warning: "DashboardWarning",
|
||||
},
|
||||
},
|
||||
Status: chev1.CheClusterStatus{
|
||||
CheClusterRunning: "Available",
|
||||
CheVersion: "CheVersion",
|
||||
CheURL: "CheURL",
|
||||
Message: "Message",
|
||||
Reason: "Reason",
|
||||
DevfileRegistryURL: "DevfileRegistryURL",
|
||||
PluginRegistryURL: "PluginRegistryURL",
|
||||
GitServerTLSCertificateConfigMapName: "che-git-self-signed-cert",
|
||||
DevworkspaceStatus: chev1.LegacyDevworkspaceStatus{
|
||||
GatewayHost: "CheURL",
|
||||
Message: "Message",
|
||||
Reason: "Reason",
|
||||
Phase: chev1.ClusterPhaseActive,
|
||||
GatewayPhase: chev1.GatewayPhaseEstablished,
|
||||
WorkspaceBaseDomain: "Domain",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
checlusterv1 := &chev1.CheCluster{}
|
||||
checlusterv2 := &chev2.CheCluster{}
|
||||
|
||||
err = checlusterv1Orignal.ConvertTo(checlusterv2)
|
||||
assert.Nil(t, err)
|
||||
|
||||
err = checlusterv1.ConvertFrom(checlusterv2)
|
||||
assert.Nil(t, err)
|
||||
|
||||
assert.Equal(t, checlusterv1Orignal, checlusterv1)
|
||||
}
|
||||
|
||||
onKubernetes(f)
|
||||
onOpenShift(f)
|
||||
}
|
||||
|
||||
func onKubernetes(f func()) {
|
||||
infrastructure.InitializeForTesting(infrastructure.Kubernetes)
|
||||
f()
|
||||
}
|
||||
|
||||
func onOpenShift(f func()) {
|
||||
infrastructure.InitializeForTesting(infrastructure.OpenShiftv4)
|
||||
f()
|
||||
}
|
||||
|
|
@ -1,289 +0,0 @@
|
|||
//
|
||||
// Copyright (c) 2019-2021 Red Hat, Inc.
|
||||
// This program and the accompanying materials are made
|
||||
// available under the terms of the Eclipse Public License 2.0
|
||||
// which is available at https://www.eclipse.org/legal/epl-2.0/
|
||||
//
|
||||
// SPDX-License-Identifier: EPL-2.0
|
||||
//
|
||||
// Contributors:
|
||||
// Red Hat, Inc. - initial API and implementation
|
||||
//
|
||||
|
||||
package org
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"strings"
|
||||
|
||||
v1 "github.com/eclipse-che/che-operator/api/v1"
|
||||
"github.com/eclipse-che/che-operator/api/v2alpha1"
|
||||
"github.com/eclipse-che/che-operator/pkg/deploy"
|
||||
"github.com/eclipse-che/che-operator/pkg/util"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
"k8s.io/utils/pointer"
|
||||
"sigs.k8s.io/yaml"
|
||||
)
|
||||
|
||||
const (
|
||||
v1StorageAnnotation = "che.eclipse.org/cheClusterV1Spec"
|
||||
v2alpha1StorageAnnotation = "che.eclipse.org/cheClusterV2alpha1Spec"
|
||||
routeDomainSuffixPropertyKey = "CHE_INFRA_OPENSHIFT_ROUTE_HOST_DOMAIN__SUFFIX"
|
||||
defaultV2alpha1IngressClass = "nginx"
|
||||
defaultV1IngressClass = "nginx"
|
||||
)
|
||||
|
||||
func AsV1(v2 *v2alpha1.CheCluster) *v1.CheCluster {
|
||||
ret := &v1.CheCluster{}
|
||||
V2alpha1ToV1(v2, ret)
|
||||
return ret
|
||||
}
|
||||
|
||||
func AsV2alpha1(v1 *v1.CheCluster) *v2alpha1.CheCluster {
|
||||
ret := &v2alpha1.CheCluster{}
|
||||
V1ToV2alpha1(v1, ret)
|
||||
return ret
|
||||
}
|
||||
|
||||
func V1ToV2alpha1(v1 *v1.CheCluster, v2 *v2alpha1.CheCluster) error {
|
||||
v2Data := v1.Annotations[v2alpha1StorageAnnotation]
|
||||
v2Spec := v2alpha1.CheClusterSpec{}
|
||||
if v2Data != "" {
|
||||
err := yaml.Unmarshal([]byte(v2Data), &v2Spec)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
v2.ObjectMeta = *v1.ObjectMeta.DeepCopy()
|
||||
v2.Spec = v2Spec
|
||||
|
||||
v1Spec, err := yaml.Marshal(v1.Spec)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if v2.Annotations == nil {
|
||||
v2.Annotations = map[string]string{}
|
||||
}
|
||||
v2.Annotations[v1StorageAnnotation] = string(v1Spec)
|
||||
|
||||
v1ToV2alpha1_Enabled(v1, v2)
|
||||
v1ToV2alpha1_Host(v1, v2)
|
||||
v1ToV2alpha1_GatewayEnabled(v1, v2)
|
||||
v1ToV2alpha1_GatewayImage(v1, v2)
|
||||
v1ToV2alpha1_GatewayConfigurerImage(v1, v2)
|
||||
v1ToV2alpha1_GatewayTlsSecretName(v1, v2)
|
||||
v1toV2alpha1_GatewayConfigLabels(v1, v2)
|
||||
v1ToV2alpha1_WorkspaceDomainEndpointsBaseDomain(v1, v2)
|
||||
v1ToV2alpha1_WorkspaceDomainEndpointsTlsSecretName(v1, v2)
|
||||
v1ToV2alpha1_WorkspacePodNodeSelector(v1, v2)
|
||||
if err := v1ToV2alpha1_WorkspacePodTolerations(v1, v2); err != nil {
|
||||
return err
|
||||
}
|
||||
v1ToV2alpha1_K8sIngressAnnotations(v1, v2)
|
||||
|
||||
// we don't need to store the serialized v2 on a v2 object
|
||||
delete(v2.Annotations, v2alpha1StorageAnnotation)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func V2alpha1ToV1(v2 *v2alpha1.CheCluster, v1Obj *v1.CheCluster) error {
|
||||
v1Data := v2.Annotations[v1StorageAnnotation]
|
||||
v1Spec := v1.CheClusterSpec{}
|
||||
if v1Data != "" {
|
||||
err := yaml.Unmarshal([]byte(v1Data), &v1Spec)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
v1Obj.ObjectMeta = *v2.ObjectMeta.DeepCopy()
|
||||
v1Obj.Spec = v1Spec
|
||||
v1Obj.Status = v1.CheClusterStatus{}
|
||||
|
||||
v2Spec, err := yaml.Marshal(v2.Spec)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if v1Obj.Annotations == nil {
|
||||
v1Obj.Annotations = map[string]string{}
|
||||
}
|
||||
v1Obj.Annotations[v2alpha1StorageAnnotation] = string(v2Spec)
|
||||
|
||||
v2alpha1ToV1_Host(v1Obj, v2)
|
||||
v2alpha1ToV1_GatewayImage(v1Obj, v2)
|
||||
v2alpha1ToV1_GatewayConfigurerImage(v1Obj, v2)
|
||||
v2alpha1ToV1_GatewayTlsSecretName(v1Obj, v2)
|
||||
v2alpha1ToV1_GatewayConfigLabels(v1Obj, v2)
|
||||
v2alpha1ToV1_WorkspaceDomainEndpointsBaseDomain(v1Obj, v2)
|
||||
v2alpha1ToV1_WorkspaceDomainEndpointsTlsSecretName(v1Obj, v2)
|
||||
v2alpha1ToV1_WorkspacePodNodeSelector(v1Obj, v2)
|
||||
v2alpha1ToV1_WorkspacePodTolerations(v1Obj, v2)
|
||||
v2alpha1ToV1_K8sIngressAnnotations(v1Obj, v2)
|
||||
|
||||
// we don't need to store the serialized v1 on a v1 object
|
||||
delete(v1Obj.Annotations, v1StorageAnnotation)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func v1ToV2alpha1_Enabled(v1 *v1.CheCluster, v2 *v2alpha1.CheCluster) {
|
||||
v2.Spec.Enabled = pointer.BoolPtr(true)
|
||||
}
|
||||
|
||||
func v1ToV2alpha1_Host(v1 *v1.CheCluster, v2 *v2alpha1.CheCluster) {
|
||||
v2.Spec.Gateway.Host = v1.Spec.Server.CheHost
|
||||
}
|
||||
|
||||
func v1ToV2alpha1_WorkspaceDomainEndpointsBaseDomain(v1 *v1.CheCluster, v2 *v2alpha1.CheCluster) {
|
||||
if util.IsOpenShift {
|
||||
v2.Spec.Workspaces.DomainEndpoints.BaseDomain = v1.Spec.Server.CustomCheProperties[routeDomainSuffixPropertyKey]
|
||||
} else {
|
||||
v2.Spec.Workspaces.DomainEndpoints.BaseDomain = v1.Spec.K8s.IngressDomain
|
||||
}
|
||||
}
|
||||
|
||||
func v1ToV2alpha1_WorkspaceDomainEndpointsTlsSecretName(v1 *v1.CheCluster, v2 *v2alpha1.CheCluster) {
|
||||
// Che server always uses the default cluster certificate for subdomain workspace endpoints on OpenShift, and the K8s.TlsSecretName on K8s.
|
||||
// Because we're dealing with endpoints, let's try to use the secret on Kubernetes and nothing (e.g. the default cluster cert on OpenShift)
|
||||
// which is in line with the logic of the Che server.
|
||||
if !util.IsOpenShift {
|
||||
v2.Spec.Workspaces.DomainEndpoints.TlsSecretName = v1.Spec.K8s.TlsSecretName
|
||||
}
|
||||
}
|
||||
|
||||
func v1ToV2alpha1_WorkspacePodNodeSelector(v1 *v1.CheCluster, v2 *v2alpha1.CheCluster) {
|
||||
selector := v1.Spec.Server.WorkspacePodNodeSelector
|
||||
if len(selector) == 0 {
|
||||
prop := v1.Spec.Server.CustomCheProperties["CHE_WORKSPACE_POD_NODE__SELECTOR"]
|
||||
if prop != "" {
|
||||
selector = map[string]string{}
|
||||
kvs := strings.Split(prop, ",")
|
||||
for _, pair := range kvs {
|
||||
kv := strings.Split(pair, "=")
|
||||
if len(kv) == 2 {
|
||||
selector[kv[0]] = kv[1]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
v2.Spec.Workspaces.PodNodeSelector = selector
|
||||
}
|
||||
|
||||
func v1ToV2alpha1_WorkspacePodTolerations(v1 *v1.CheCluster, v2 *v2alpha1.CheCluster) error {
|
||||
tolerations := v1.Spec.Server.WorkspacePodTolerations
|
||||
|
||||
if len(tolerations) == 0 {
|
||||
prop := v1.Spec.Server.CustomCheProperties["CHE_WORKSPACE_POD_TOLERATIONS__JSON"]
|
||||
if prop != "" {
|
||||
tols := []corev1.Toleration{}
|
||||
if err := json.Unmarshal([]byte(prop), &tols); err != nil {
|
||||
return err
|
||||
}
|
||||
tolerations = tols
|
||||
}
|
||||
}
|
||||
|
||||
v2.Spec.Workspaces.PodTolerations = tolerations
|
||||
return nil
|
||||
}
|
||||
|
||||
func v1ToV2alpha1_GatewayEnabled(v1 *v1.CheCluster, v2 *v2alpha1.CheCluster) {
|
||||
// On Kubernetes, we can have single-host realized using ingresses (that use the same host but different paths).
|
||||
// This is actually not supported on DWCO where we always use the gateway for that. So here, we actually just
|
||||
// ignore the Spec.K8s.SingleHostExposureType, but we need to be aware of it when converting back.
|
||||
// Note that default-host is actually not supported on v2, but it is similar enough to default host that we
|
||||
// treat it as such for v2. The difference between default-host and single-host is that the default-host uses
|
||||
// the cluster domain itself as the base domain whereas single-host uses a configured domain. In v2 we always
|
||||
// need a domain configured.
|
||||
v2.Spec.Gateway.Enabled = pointer.BoolPtr(true)
|
||||
}
|
||||
|
||||
func v1ToV2alpha1_GatewayImage(v1 *v1.CheCluster, v2 *v2alpha1.CheCluster) {
|
||||
v2.Spec.Gateway.Image = util.GetValue(v1.Spec.Server.SingleHostGatewayImage, deploy.DefaultSingleHostGatewayImage(v1))
|
||||
}
|
||||
|
||||
func v1ToV2alpha1_GatewayConfigurerImage(v1 *v1.CheCluster, v2 *v2alpha1.CheCluster) {
|
||||
v2.Spec.Gateway.ConfigurerImage = v1.Spec.Server.SingleHostGatewayConfigSidecarImage
|
||||
}
|
||||
|
||||
func v1ToV2alpha1_GatewayTlsSecretName(v1 *v1.CheCluster, v2 *v2alpha1.CheCluster) {
|
||||
// v1.Spec.Server.CheHostTLSSecret is used specifically for Che Host - i.e. the host under which che server is deployed.
|
||||
// In DW we would only used that for subpath endpoints but wouldn't know what TLS to use for subdomain endpoints.
|
||||
|
||||
v2.Spec.Gateway.TlsSecretName = v1.Spec.Server.CheHostTLSSecret
|
||||
}
|
||||
|
||||
func v1toV2alpha1_GatewayConfigLabels(v1 *v1.CheCluster, v2 *v2alpha1.CheCluster) {
|
||||
v2.Spec.Gateway.ConfigLabels = v1.Spec.Server.SingleHostGatewayConfigMapLabels
|
||||
}
|
||||
|
||||
func v1ToV2alpha1_K8sIngressAnnotations(v1 *v1.CheCluster, v2 *v2alpha1.CheCluster) {
|
||||
// The only property in v1 spec that boils down to the ingress annotations is the K8s.IngressClass
|
||||
if v1.Spec.K8s.IngressClass != "" && v1.Spec.K8s.IngressClass != defaultV2alpha1IngressClass {
|
||||
if v2.Spec.K8s.IngressAnnotations == nil {
|
||||
v2.Spec.K8s.IngressAnnotations = map[string]string{}
|
||||
}
|
||||
v2.Spec.K8s.IngressAnnotations["kubernetes.io/ingress.class"] = v1.Spec.K8s.IngressClass
|
||||
}
|
||||
}
|
||||
|
||||
func v2alpha1ToV1_Host(v1 *v1.CheCluster, v2 *v2alpha1.CheCluster) {
|
||||
v1.Spec.Server.CheHost = v2.Spec.Gateway.Host
|
||||
}
|
||||
|
||||
func v2alpha1ToV1_WorkspaceDomainEndpointsBaseDomain(v1 *v1.CheCluster, v2 *v2alpha1.CheCluster) {
|
||||
if util.IsOpenShift {
|
||||
if v1.Spec.Server.CustomCheProperties == nil {
|
||||
v1.Spec.Server.CustomCheProperties = map[string]string{}
|
||||
}
|
||||
if len(v2.Spec.Workspaces.DomainEndpoints.BaseDomain) > 0 {
|
||||
v1.Spec.Server.CustomCheProperties[routeDomainSuffixPropertyKey] = v2.Spec.Workspaces.DomainEndpoints.BaseDomain
|
||||
}
|
||||
} else {
|
||||
v1.Spec.K8s.IngressDomain = v2.Spec.Workspaces.DomainEndpoints.BaseDomain
|
||||
}
|
||||
}
|
||||
|
||||
func v2alpha1ToV1_WorkspaceDomainEndpointsTlsSecretName(v1 *v1.CheCluster, v2 *v2alpha1.CheCluster) {
|
||||
// see the comments in the v1 to v2alpha1 conversion method
|
||||
if !util.IsOpenShift {
|
||||
v1.Spec.K8s.TlsSecretName = v2.Spec.Workspaces.DomainEndpoints.TlsSecretName
|
||||
}
|
||||
}
|
||||
|
||||
func v2alpha1ToV1_WorkspacePodNodeSelector(v1 *v1.CheCluster, v2 *v2alpha1.CheCluster) {
|
||||
v1.Spec.Server.WorkspacePodNodeSelector = v2.Spec.Workspaces.PodNodeSelector
|
||||
}
|
||||
|
||||
func v2alpha1ToV1_WorkspacePodTolerations(v1 *v1.CheCluster, v2 *v2alpha1.CheCluster) {
|
||||
v1.Spec.Server.WorkspacePodTolerations = v2.Spec.Workspaces.PodTolerations
|
||||
}
|
||||
|
||||
func v2alpha1ToV1_GatewayImage(v1 *v1.CheCluster, v2 *v2alpha1.CheCluster) {
|
||||
v1.Spec.Server.SingleHostGatewayImage = v2.Spec.Gateway.Image
|
||||
}
|
||||
|
||||
func v2alpha1ToV1_GatewayConfigurerImage(v1 *v1.CheCluster, v2 *v2alpha1.CheCluster) {
|
||||
v1.Spec.Server.SingleHostGatewayConfigSidecarImage = v2.Spec.Gateway.ConfigurerImage
|
||||
}
|
||||
|
||||
func v2alpha1ToV1_GatewayTlsSecretName(v1 *v1.CheCluster, v2 *v2alpha1.CheCluster) {
|
||||
// see the comments in the v1 to v2alpha1 conversion method
|
||||
v1.Spec.Server.CheHostTLSSecret = v2.Spec.Gateway.TlsSecretName
|
||||
}
|
||||
|
||||
func v2alpha1ToV1_GatewayConfigLabels(v1 *v1.CheCluster, v2 *v2alpha1.CheCluster) {
|
||||
v1.Spec.Server.SingleHostGatewayConfigMapLabels = v2.Spec.Gateway.ConfigLabels
|
||||
}
|
||||
|
||||
func v2alpha1ToV1_K8sIngressAnnotations(v1 *v1.CheCluster, v2 *v2alpha1.CheCluster) {
|
||||
ingressClass := v2.Spec.K8s.IngressAnnotations["kubernetes.io/ingress.class"]
|
||||
if ingressClass == "" {
|
||||
ingressClass = defaultV2alpha1IngressClass
|
||||
}
|
||||
if v1.Spec.K8s.IngressClass != "" || ingressClass != defaultV1IngressClass {
|
||||
v1.Spec.K8s.IngressClass = ingressClass
|
||||
}
|
||||
}
|
||||
|
|
@ -1,643 +0,0 @@
|
|||
//
|
||||
// Copyright (c) 2019-2021 Red Hat, Inc.
|
||||
// This program and the accompanying materials are made
|
||||
// available under the terms of the Eclipse Public License 2.0
|
||||
// which is available at https://www.eclipse.org/legal/epl-2.0/
|
||||
//
|
||||
// SPDX-License-Identifier: EPL-2.0
|
||||
//
|
||||
// Contributors:
|
||||
// Red Hat, Inc. - initial API and implementation
|
||||
//
|
||||
|
||||
package org
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"github.com/che-incubator/kubernetes-image-puller-operator/api/v1alpha1"
|
||||
v1 "github.com/eclipse-che/che-operator/api/v1"
|
||||
"github.com/eclipse-che/che-operator/api/v2alpha1"
|
||||
"github.com/eclipse-che/che-operator/pkg/util"
|
||||
"github.com/google/go-cmp/cmp"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"k8s.io/utils/pointer"
|
||||
"sigs.k8s.io/yaml"
|
||||
)
|
||||
|
||||
func TestV1ToV2alpha1(t *testing.T) {
|
||||
tolerations := []corev1.Toleration{
|
||||
{
|
||||
Key: "a",
|
||||
Operator: corev1.TolerationOpEqual,
|
||||
Value: "b",
|
||||
},
|
||||
}
|
||||
|
||||
tolBytes, err := json.Marshal(tolerations)
|
||||
assert.NoError(t, err)
|
||||
|
||||
tolerationStr := string(tolBytes)
|
||||
|
||||
v1Obj := v1.CheCluster{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "che-cluster",
|
||||
Annotations: map[string]string{
|
||||
"anno1": "annoValue1",
|
||||
"anno2": "annoValue2",
|
||||
},
|
||||
},
|
||||
Spec: v1.CheClusterSpec{
|
||||
Auth: v1.CheClusterSpecAuth{
|
||||
IdentityProviderURL: "kachny",
|
||||
},
|
||||
Database: v1.CheClusterSpecDB{
|
||||
ExternalDb: true,
|
||||
PostgresImage: "postgres:the-best-version",
|
||||
},
|
||||
DevWorkspace: v1.CheClusterSpecDevWorkspace{},
|
||||
ImagePuller: v1.CheClusterSpecImagePuller{
|
||||
Spec: v1alpha1.KubernetesImagePullerSpec{
|
||||
ConfigMapName: "pulled-kachna",
|
||||
},
|
||||
},
|
||||
K8s: v1.CheClusterSpecK8SOnly{
|
||||
IngressDomain: "ingressDomain",
|
||||
IngressClass: "traefik",
|
||||
TlsSecretName: "k8sSecret",
|
||||
},
|
||||
Metrics: v1.CheClusterSpecMetrics{
|
||||
Enable: true,
|
||||
},
|
||||
Server: v1.CheClusterSpecServer{
|
||||
CheHost: "cheHost",
|
||||
CheImage: "teh-che-severe",
|
||||
SingleHostGatewayImage: "single-host-image-of-the-year",
|
||||
CheHostTLSSecret: "cheSecret",
|
||||
SingleHostGatewayConfigMapLabels: labels.Set{
|
||||
"a": "b",
|
||||
"c": "d",
|
||||
},
|
||||
CustomCheProperties: map[string]string{
|
||||
"CHE_INFRA_OPENSHIFT_ROUTE_HOST_DOMAIN__SUFFIX": "routeDomain",
|
||||
"CHE_WORKSPACE_POD_TOLERATIONS__JSON": tolerationStr,
|
||||
"CHE_WORKSPACE_POD_NODE__SELECTOR": "a=b,c=d",
|
||||
},
|
||||
},
|
||||
Storage: v1.CheClusterSpecStorage{
|
||||
PvcStrategy: "common",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
t.Run("origInAnnos", func(t *testing.T) {
|
||||
v2 := &v2alpha1.CheCluster{}
|
||||
err := V1ToV2alpha1(&v1Obj, v2)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
anno1 := v2.Annotations["anno1"]
|
||||
anno2 := v2.Annotations["anno2"]
|
||||
storedV1 := v2.Annotations[v1StorageAnnotation]
|
||||
|
||||
if anno1 != "annoValue1" {
|
||||
t.Errorf("anno1 not copied")
|
||||
}
|
||||
|
||||
if anno2 != "annoValue2" {
|
||||
t.Errorf("anno2 not copied")
|
||||
}
|
||||
|
||||
if storedV1 == "" {
|
||||
t.Errorf("v2 should contain v1 data in annnotation")
|
||||
}
|
||||
|
||||
restoredV1Spec := v1.CheClusterSpec{}
|
||||
if err = yaml.Unmarshal([]byte(storedV1), &restoredV1Spec); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(&v1Obj.Spec, &restoredV1Spec) {
|
||||
t.Errorf("The spec should be restored verbatim from the annotations, but there's a diff %s", cmp.Diff(&v1Obj.Spec, &restoredV1Spec))
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("Enabled", func(t *testing.T) {
|
||||
v2 := &v2alpha1.CheCluster{}
|
||||
err := V1ToV2alpha1(&v1Obj, v2)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
if !*v2.Spec.Enabled {
|
||||
t.Errorf("Unexpected v2.Spec.Enabled: %t", *v2.Spec.Enabled)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("Host-k8s", func(t *testing.T) {
|
||||
v2 := &v2alpha1.CheCluster{}
|
||||
err := V1ToV2alpha1(&v1Obj, v2)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
if v2.Spec.Gateway.Host != "cheHost" {
|
||||
t.Errorf("Unexpected v2.Spec.Host: %s", v2.Spec.Gateway.Host)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("WorkspaceDomainEndpointsBaseDomain-k8s", func(t *testing.T) {
|
||||
onFakeKubernetes(func() {
|
||||
v2 := &v2alpha1.CheCluster{}
|
||||
err := V1ToV2alpha1(&v1Obj, v2)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
if v2.Spec.Workspaces.DomainEndpoints.BaseDomain != "ingressDomain" {
|
||||
t.Errorf("Unexpected v2.Spec.Workspaces.DomainEndpoints.BaseDomain: %s", v2.Spec.Workspaces.DomainEndpoints.BaseDomain)
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("WorkspaceDomainEndpointsBaseDomain-opensfhit", func(t *testing.T) {
|
||||
onFakeOpenShift(func() {
|
||||
v2 := &v2alpha1.CheCluster{}
|
||||
err := V1ToV2alpha1(&v1Obj, v2)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
if v2.Spec.Workspaces.DomainEndpoints.BaseDomain != "routeDomain" {
|
||||
t.Errorf("Unexpected v2.Spec.Workspaces.DomainEndpoints.BaseDomain: %s", v2.Spec.Workspaces.DomainEndpoints.BaseDomain)
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("WorkspaceDomainEndpointsTlsSecretName_k8s", func(t *testing.T) {
|
||||
onFakeKubernetes(func() {
|
||||
v2 := &v2alpha1.CheCluster{}
|
||||
err := V1ToV2alpha1(&v1Obj, v2)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
if v2.Spec.Workspaces.DomainEndpoints.TlsSecretName != "k8sSecret" {
|
||||
t.Errorf("Unexpected TlsSecretName")
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("WorkspaceDomainEndpointsTlsSecretName_OpenShift", func(t *testing.T) {
|
||||
onFakeOpenShift(func() {
|
||||
v2 := &v2alpha1.CheCluster{}
|
||||
err := V1ToV2alpha1(&v1Obj, v2)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
if v2.Spec.Workspaces.DomainEndpoints.TlsSecretName != "" {
|
||||
t.Errorf("Unexpected TlsSecretName")
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("GatewayEnabled", func(t *testing.T) {
|
||||
onFakeOpenShift(func() {
|
||||
v2 := &v2alpha1.CheCluster{}
|
||||
err := V1ToV2alpha1(&v1Obj, v2)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
if v2.Spec.Gateway.Enabled == nil {
|
||||
t.Logf("The gateway.enabled attribute should be set explicitly after the conversion.")
|
||||
t.FailNow()
|
||||
}
|
||||
|
||||
if !*v2.Spec.Gateway.Enabled {
|
||||
t.Errorf("The default for OpenShift is single")
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("GatewayImage", func(t *testing.T) {
|
||||
v2 := &v2alpha1.CheCluster{}
|
||||
err := V1ToV2alpha1(&v1Obj, v2)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
if v2.Spec.Gateway.Image != "single-host-image-of-the-year" {
|
||||
t.Errorf("Unexpected gateway image")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("GatewayTlsSecretName", func(t *testing.T) {
|
||||
v2 := &v2alpha1.CheCluster{}
|
||||
err := V1ToV2alpha1(&v1Obj, v2)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
if v2.Spec.Gateway.TlsSecretName != "cheSecret" {
|
||||
t.Errorf("Unexpected TlsSecretName")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("GatewayConfigLabels", func(t *testing.T) {
|
||||
v2 := &v2alpha1.CheCluster{}
|
||||
err := V1ToV2alpha1(&v1Obj, v2)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(v2.Spec.Gateway.ConfigLabels, v1Obj.Spec.Server.SingleHostGatewayConfigMapLabels) {
|
||||
t.Errorf("Unexpected Spec.Gateway.ConfigLabels: %v", cmp.Diff(v1Obj.Spec.Server.SingleHostGatewayConfigMapLabels, v2.Spec.Gateway.ConfigLabels))
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("WorkspacePodSelector", func(t *testing.T) {
|
||||
v2 := &v2alpha1.CheCluster{}
|
||||
assert.NoError(t, V1ToV2alpha1(&v1Obj, v2))
|
||||
assert.Equal(t, map[string]string{"a": "b", "c": "d"}, v2.Spec.Workspaces.PodNodeSelector)
|
||||
})
|
||||
|
||||
t.Run("WorkspacePodTolerations", func(t *testing.T) {
|
||||
v2 := &v2alpha1.CheCluster{}
|
||||
assert.NoError(t, V1ToV2alpha1(&v1Obj, v2))
|
||||
assert.Equal(t, tolerations, v2.Spec.Workspaces.PodTolerations)
|
||||
})
|
||||
}
|
||||
|
||||
func TestV2alpha1ToV1(t *testing.T) {
|
||||
v2Obj := v2alpha1.CheCluster{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "che-cluster",
|
||||
Annotations: map[string]string{
|
||||
"anno1": "annoValue1",
|
||||
"anno2": "annoValue2",
|
||||
},
|
||||
},
|
||||
Spec: v2alpha1.CheClusterSpec{
|
||||
Enabled: pointer.BoolPtr(true),
|
||||
Workspaces: v2alpha1.Workspaces{
|
||||
DomainEndpoints: v2alpha1.DomainEndpoints{
|
||||
BaseDomain: "baseDomain",
|
||||
TlsSecretName: "workspaceSecret",
|
||||
},
|
||||
PodNodeSelector: map[string]string{"a": "b", "c": "d"},
|
||||
PodTolerations: []corev1.Toleration{
|
||||
{
|
||||
Key: "a",
|
||||
Operator: corev1.TolerationOpEqual,
|
||||
Value: "b",
|
||||
},
|
||||
},
|
||||
},
|
||||
Gateway: v2alpha1.CheGatewaySpec{
|
||||
Host: "v2Host",
|
||||
Enabled: pointer.BoolPtr(true),
|
||||
Image: "gateway-image",
|
||||
ConfigurerImage: "configurer-image",
|
||||
TlsSecretName: "superSecret",
|
||||
ConfigLabels: labels.Set{
|
||||
"a": "b",
|
||||
},
|
||||
},
|
||||
K8s: v2alpha1.CheClusterSpecK8s{
|
||||
IngressAnnotations: map[string]string{
|
||||
"kubernetes.io/ingress.class": "some-other-ingress",
|
||||
"a": "b",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
t.Run("origInAnnos", func(t *testing.T) {
|
||||
v1 := &v1.CheCluster{}
|
||||
err := V2alpha1ToV1(&v2Obj, v1)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
anno1 := v1.Annotations["anno1"]
|
||||
anno2 := v1.Annotations["anno2"]
|
||||
storedV2 := v1.Annotations[v2alpha1StorageAnnotation]
|
||||
|
||||
if anno1 != "annoValue1" {
|
||||
t.Errorf("anno1 not copied")
|
||||
}
|
||||
|
||||
if anno2 != "annoValue2" {
|
||||
t.Errorf("anno2 not copied")
|
||||
}
|
||||
|
||||
if storedV2 == "" {
|
||||
t.Errorf("v1 should contain v2 data in annnotation")
|
||||
}
|
||||
|
||||
restoredV2Spec := v2alpha1.CheClusterSpec{}
|
||||
yaml.Unmarshal([]byte(storedV2), &restoredV2Spec)
|
||||
|
||||
if !reflect.DeepEqual(&v2Obj.Spec, &restoredV2Spec) {
|
||||
t.Errorf("The spec should be restored verbatim from the annotations, but there's a diff %s", cmp.Diff(&v2Obj.Spec, &restoredV2Spec))
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("Host", func(t *testing.T) {
|
||||
v1 := &v1.CheCluster{}
|
||||
err := V2alpha1ToV1(&v2Obj, v1)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
if v1.Spec.Server.CheHost != "v2Host" {
|
||||
t.Errorf("Unexpected v1.Spec.Server.CheHost: %s", v1.Spec.Server.CheHost)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("WorkspaceDomainEndpointsBaseDomain-k8s", func(t *testing.T) {
|
||||
onFakeKubernetes(func() {
|
||||
v1 := &v1.CheCluster{}
|
||||
err := V2alpha1ToV1(&v2Obj, v1)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
if v1.Spec.K8s.IngressDomain != "baseDomain" {
|
||||
t.Errorf("Unexpected v1.Spec.K8s.IngressDomain: %s", v1.Spec.K8s.IngressDomain)
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("WorkspaceDomainEndpointsBaseDomain-openshift", func(t *testing.T) {
|
||||
onFakeOpenShift(func() {
|
||||
v1 := &v1.CheCluster{}
|
||||
err := V2alpha1ToV1(&v2Obj, v1)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
if v1.Spec.Server.CustomCheProperties[routeDomainSuffixPropertyKey] != "baseDomain" {
|
||||
t.Errorf("Unexpected v1.Spec.Server.CustomCheProperties[%s]: %s", routeDomainSuffixPropertyKey, v1.Spec.Server.CustomCheProperties[routeDomainSuffixPropertyKey])
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("WorkspaceDomainEndpointsBaseDomain-openshift-should-not-be-set-empty-value", func(t *testing.T) {
|
||||
onFakeOpenShift(func() {
|
||||
v1 := &v1.CheCluster{}
|
||||
v2apha := v2Obj.DeepCopy()
|
||||
v2apha.Spec.Workspaces.DomainEndpoints.BaseDomain = ""
|
||||
err := V2alpha1ToV1(v2apha, v1)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
if _, ok := v1.Spec.Server.CustomCheProperties[routeDomainSuffixPropertyKey]; ok {
|
||||
t.Errorf("Unexpected value. We shouldn't set key with empty value for %s custom Che property", routeDomainSuffixPropertyKey)
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("WorkspaceDomainEndpointsTlsSecretName_k8s", func(t *testing.T) {
|
||||
onFakeKubernetes(func() {
|
||||
v1 := &v1.CheCluster{}
|
||||
err := V2alpha1ToV1(&v2Obj, v1)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
if v1.Spec.K8s.TlsSecretName != "workspaceSecret" {
|
||||
t.Errorf("Unexpected TlsSecretName: %s", v1.Spec.K8s.TlsSecretName)
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("WorkspaceDomainEndpointsTlsSecretName_OpenShift", func(t *testing.T) {
|
||||
onFakeOpenShift(func() {
|
||||
v1 := &v1.CheCluster{}
|
||||
err := V2alpha1ToV1(&v2Obj, v1)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
if v1.Spec.K8s.TlsSecretName != "" {
|
||||
t.Errorf("Unexpected TlsSecretName")
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("GatewayEnabled", func(t *testing.T) {
|
||||
onFakeOpenShift(func() {
|
||||
v1 := &v1.CheCluster{}
|
||||
err := V2alpha1ToV1(&v2Obj, v1)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("GatewayImage", func(t *testing.T) {
|
||||
v1 := &v1.CheCluster{}
|
||||
err := V2alpha1ToV1(&v2Obj, v1)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
if v1.Spec.Server.SingleHostGatewayImage != "gateway-image" {
|
||||
t.Errorf("Unexpected gateway image")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("GatewayTlsSecretName", func(t *testing.T) {
|
||||
v1 := &v1.CheCluster{}
|
||||
err := V2alpha1ToV1(&v2Obj, v1)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
if v1.Spec.Server.CheHostTLSSecret != "superSecret" {
|
||||
t.Errorf("Unexpected TlsSecretName: %s", v1.Spec.Server.CheHostTLSSecret)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("GatewayConfigLabels", func(t *testing.T) {
|
||||
v1 := &v1.CheCluster{}
|
||||
err := V2alpha1ToV1(&v2Obj, v1)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(v1.Spec.Server.SingleHostGatewayConfigMapLabels, v2Obj.Spec.Gateway.ConfigLabels) {
|
||||
t.Errorf("Unexpected SingleHostGatewayConfigMapLabels: %s", v1.Spec.Server.SingleHostGatewayConfigMapLabels)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("WorkspacePodNodeSelector", func(t *testing.T) {
|
||||
v1 := &v1.CheCluster{}
|
||||
assert.NoError(t, V2alpha1ToV1(&v2Obj, v1))
|
||||
assert.Equal(t, map[string]string{"a": "b", "c": "d"}, v1.Spec.Server.WorkspacePodNodeSelector)
|
||||
})
|
||||
|
||||
t.Run("WorkspacePodTolerations", func(t *testing.T) {
|
||||
v1 := &v1.CheCluster{}
|
||||
assert.NoError(t, V2alpha1ToV1(&v2Obj, v1))
|
||||
assert.Equal(t, []corev1.Toleration{{
|
||||
Key: "a",
|
||||
Operator: corev1.TolerationOpEqual,
|
||||
Value: "b",
|
||||
}}, v1.Spec.Server.WorkspacePodTolerations)
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
func TestFullCircleV1(t *testing.T) {
|
||||
v1Obj := v1.CheCluster{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "che-cluster",
|
||||
Annotations: map[string]string{
|
||||
"anno1": "annoValue1",
|
||||
"anno2": "annoValue2",
|
||||
},
|
||||
},
|
||||
Spec: v1.CheClusterSpec{
|
||||
Auth: v1.CheClusterSpecAuth{
|
||||
IdentityProviderURL: "kachny",
|
||||
},
|
||||
Database: v1.CheClusterSpecDB{
|
||||
ExternalDb: true,
|
||||
PostgresImage: "postgres:the-best-version",
|
||||
},
|
||||
DevWorkspace: v1.CheClusterSpecDevWorkspace{},
|
||||
ImagePuller: v1.CheClusterSpecImagePuller{
|
||||
Spec: v1alpha1.KubernetesImagePullerSpec{
|
||||
ConfigMapName: "pulled-kachna",
|
||||
},
|
||||
},
|
||||
K8s: v1.CheClusterSpecK8SOnly{
|
||||
IngressDomain: "ingressDomain",
|
||||
IngressClass: "traefik",
|
||||
TlsSecretName: "k8sSecret",
|
||||
},
|
||||
Metrics: v1.CheClusterSpecMetrics{
|
||||
Enable: true,
|
||||
},
|
||||
Server: v1.CheClusterSpecServer{
|
||||
CheHost: "cheHost",
|
||||
CheImage: "teh-che-severe",
|
||||
SingleHostGatewayImage: "single-host-image-of-the-year",
|
||||
CheHostTLSSecret: "cheSecret",
|
||||
SingleHostGatewayConfigMapLabels: labels.Set{
|
||||
"a": "b",
|
||||
},
|
||||
CustomCheProperties: map[string]string{
|
||||
"CHE_INFRA_OPENSHIFT_ROUTE_HOST_DOMAIN__SUFFIX": "routeDomain",
|
||||
},
|
||||
},
|
||||
Storage: v1.CheClusterSpecStorage{
|
||||
PvcStrategy: "common",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
v2Obj := v2alpha1.CheCluster{}
|
||||
assert.NoError(t, V1ToV2alpha1(&v1Obj, &v2Obj))
|
||||
|
||||
convertedV1 := v1.CheCluster{}
|
||||
assert.NoError(t, V2alpha1ToV1(&v2Obj, &convertedV1))
|
||||
|
||||
assert.Empty(t, convertedV1.Annotations[v1StorageAnnotation])
|
||||
assert.NotEmpty(t, convertedV1.Annotations[v2alpha1StorageAnnotation])
|
||||
|
||||
// remove v2 content annotation on the convertedV1 so that it doesn't interfere with the equality.
|
||||
delete(convertedV1.Annotations, v2alpha1StorageAnnotation)
|
||||
|
||||
assert.Equal(t, &v1Obj, &convertedV1)
|
||||
}
|
||||
|
||||
func TestFullCircleV2(t *testing.T) {
|
||||
v2Obj := v2alpha1.CheCluster{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "che-cluster",
|
||||
Annotations: map[string]string{
|
||||
"anno1": "annoValue1",
|
||||
"anno2": "annoValue2",
|
||||
},
|
||||
},
|
||||
Spec: v2alpha1.CheClusterSpec{
|
||||
Enabled: pointer.BoolPtr(true),
|
||||
Workspaces: v2alpha1.Workspaces{
|
||||
DomainEndpoints: v2alpha1.DomainEndpoints{
|
||||
BaseDomain: "baseDomain",
|
||||
TlsSecretName: "workspaceSecret",
|
||||
},
|
||||
},
|
||||
Gateway: v2alpha1.CheGatewaySpec{
|
||||
Host: "v2Host",
|
||||
Enabled: pointer.BoolPtr(true),
|
||||
Image: "gateway-image",
|
||||
ConfigurerImage: "configurer-image",
|
||||
TlsSecretName: "superSecret",
|
||||
ConfigLabels: labels.Set{
|
||||
"a": "b",
|
||||
},
|
||||
},
|
||||
K8s: v2alpha1.CheClusterSpecK8s{
|
||||
IngressAnnotations: map[string]string{
|
||||
"kubernetes.io/ingress.class": "some-other-ingress",
|
||||
"a": "b",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
v1Obj := v1.CheCluster{}
|
||||
assert.NoError(t, V2alpha1ToV1(&v2Obj, &v1Obj))
|
||||
|
||||
convertedV2 := v2alpha1.CheCluster{}
|
||||
assert.NoError(t, V1ToV2alpha1(&v1Obj, &convertedV2))
|
||||
|
||||
assert.Empty(t, convertedV2.Annotations[v2alpha1StorageAnnotation])
|
||||
assert.NotEmpty(t, convertedV2.Annotations[v1StorageAnnotation])
|
||||
|
||||
// remove v1 content annotation on the convertedV1 so that it doesn't interfere with the equality.
|
||||
delete(convertedV2.Annotations, v1StorageAnnotation)
|
||||
|
||||
assert.Equal(t, &v2Obj, &convertedV2)
|
||||
}
|
||||
|
||||
func onFakeOpenShift(f func()) {
|
||||
origOpenshift := util.IsOpenShift
|
||||
origOpenshift4 := util.IsOpenShift4
|
||||
|
||||
util.IsOpenShift = true
|
||||
util.IsOpenShift4 = true
|
||||
|
||||
f()
|
||||
|
||||
util.IsOpenShift = origOpenshift
|
||||
util.IsOpenShift4 = origOpenshift4
|
||||
}
|
||||
|
||||
func onFakeKubernetes(f func()) {
|
||||
origOpenshift := util.IsOpenShift
|
||||
origOpenshift4 := util.IsOpenShift4
|
||||
|
||||
util.IsOpenShift = false
|
||||
util.IsOpenShift4 = false
|
||||
|
||||
f()
|
||||
|
||||
util.IsOpenShift = origOpenshift
|
||||
util.IsOpenShift4 = origOpenshift4
|
||||
}
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
//
|
||||
// Copyright (c) 2019-2021 Red Hat, Inc.
|
||||
// This program and the accompanying materials are made
|
||||
// available under the terms of the Eclipse Public License 2.0
|
||||
// which is available at https://www.eclipse.org/legal/epl-2.0/
|
||||
//
|
||||
// SPDX-License-Identifier: EPL-2.0
|
||||
//
|
||||
// Contributors:
|
||||
// Red Hat, Inc. - initial API and implementation
|
||||
//
|
||||
package org
|
||||
|
||||
import (
|
||||
"github.com/devfile/devworkspace-operator/pkg/infrastructure"
|
||||
defaults "github.com/eclipse-che/che-operator/pkg/common/operator-defaults"
|
||||
"github.com/eclipse-che/che-operator/pkg/common/test"
|
||||
)
|
||||
|
||||
func init() {
|
||||
test.EnableTestMode()
|
||||
|
||||
infrastructure.InitializeForTesting(infrastructure.OpenShiftv4)
|
||||
defaults.Initialize("../config/manager/manager.yaml")
|
||||
}
|
||||
|
|
@ -0,0 +1,356 @@
|
|||
//
|
||||
// Copyright (c) 2019-2022 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 v1
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/eclipse-che/che-operator/pkg/common/utils"
|
||||
|
||||
"github.com/devfile/devworkspace-operator/pkg/infrastructure"
|
||||
chev2 "github.com/eclipse-che/che-operator/api/v2"
|
||||
"github.com/eclipse-che/che-operator/pkg/common/constants"
|
||||
k8shelper "github.com/eclipse-che/che-operator/pkg/common/k8s-helper"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"sigs.k8s.io/controller-runtime/pkg/conversion"
|
||||
)
|
||||
|
||||
func (dst *CheCluster) ConvertFrom(srcRaw conversion.Hub) error {
|
||||
src := srcRaw.(*chev2.CheCluster)
|
||||
dst.ObjectMeta = src.ObjectMeta
|
||||
|
||||
if err := dst.convertFrom_Server(src); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := dst.convertFrom_K8s(src); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := dst.convertFrom_Auth(src); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := dst.convertFrom_Database(src); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := dst.convertFrom_DevWorkspace(src); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := dst.convertFrom_Dashboard(src); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := dst.convertFrom_Metrics(src); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := dst.convertFrom_ImagePuller(src); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := dst.convertFrom_Storage(src); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := dst.convertFrom_Status(src); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (dst *CheCluster) convertFrom_Server(src *chev2.CheCluster) error {
|
||||
dst.Spec.Server.AirGapContainerRegistryHostname = src.Spec.ContainerRegistry.Hostname
|
||||
dst.Spec.Server.AirGapContainerRegistryOrganization = src.Spec.ContainerRegistry.Organization
|
||||
dst.Spec.Server.CheClusterRoles = strings.Join(src.Spec.Components.CheServer.ClusterRoles, ",")
|
||||
dst.Spec.Server.CustomCheProperties = utils.CloneMap(src.Spec.Components.CheServer.ExtraProperties)
|
||||
if src.Spec.Components.CheServer.Debug != nil {
|
||||
dst.Spec.Server.CheDebug = strconv.FormatBool(*src.Spec.Components.CheServer.Debug)
|
||||
}
|
||||
dst.Spec.Server.CheLogLevel = src.Spec.Components.CheServer.LogLevel
|
||||
dst.Spec.Server.ProxyURL = src.Spec.Components.CheServer.Proxy.Url
|
||||
dst.Spec.Server.ProxyPort = src.Spec.Components.CheServer.Proxy.Port
|
||||
dst.Spec.Server.NonProxyHosts = strings.Join(src.Spec.Components.CheServer.Proxy.NonProxyHosts, "|")
|
||||
dst.Spec.Server.ProxySecret = src.Spec.Components.CheServer.Proxy.CredentialsSecretName
|
||||
dst.Spec.Server.WorkspaceNamespaceDefault = src.Spec.DevEnvironments.DefaultNamespace.Template
|
||||
dst.Spec.Server.WorkspacePodNodeSelector = utils.CloneMap(src.Spec.DevEnvironments.NodeSelector)
|
||||
|
||||
for _, v := range src.Spec.DevEnvironments.Tolerations {
|
||||
dst.Spec.Server.WorkspacePodTolerations = append(dst.Spec.Server.WorkspacePodTolerations, v)
|
||||
}
|
||||
|
||||
for _, p := range src.Spec.DevEnvironments.DefaultPlugins {
|
||||
dst.Spec.Server.WorkspacesDefaultPlugins = append(dst.Spec.Server.WorkspacesDefaultPlugins,
|
||||
WorkspacesDefaultPlugins{
|
||||
Editor: p.Editor,
|
||||
Plugins: p.Plugins,
|
||||
})
|
||||
}
|
||||
|
||||
if len(src.Spec.Components.CheServer.Deployment.Containers) != 0 {
|
||||
cheServerImageAndTag := strings.Split(src.Spec.Components.CheServer.Deployment.Containers[0].Image, ":")
|
||||
dst.Spec.Server.CheImage = strings.Join(cheServerImageAndTag[0:len(cheServerImageAndTag)-1], ":")
|
||||
dst.Spec.Server.CheImageTag = cheServerImageAndTag[len(cheServerImageAndTag)-1]
|
||||
dst.Spec.Server.CheImagePullPolicy = src.Spec.Components.CheServer.Deployment.Containers[0].ImagePullPolicy
|
||||
dst.Spec.Server.ServerMemoryRequest = src.Spec.Components.CheServer.Deployment.Containers[0].Resources.Requests.Memory.String()
|
||||
dst.Spec.Server.ServerCpuRequest = src.Spec.Components.CheServer.Deployment.Containers[0].Resources.Requests.Cpu.String()
|
||||
dst.Spec.Server.ServerMemoryLimit = src.Spec.Components.CheServer.Deployment.Containers[0].Resources.Limits.Memory.String()
|
||||
dst.Spec.Server.ServerCpuLimit = src.Spec.Components.CheServer.Deployment.Containers[0].Resources.Limits.Cpu.String()
|
||||
}
|
||||
|
||||
if infrastructure.IsOpenShift() {
|
||||
dst.Spec.Server.CheHost = src.Spec.Networking.Hostname
|
||||
dst.Spec.Server.CheServerRoute.Labels = utils.FormatLabels(src.Spec.Networking.Labels)
|
||||
dst.Spec.Server.CheServerRoute.Annotations = utils.CloneMap(src.Spec.Networking.Annotations)
|
||||
dst.Spec.Server.CheServerRoute.Domain = src.Spec.Networking.Domain
|
||||
dst.Spec.Server.CheHostTLSSecret = src.Spec.Networking.TlsSecretName
|
||||
} else {
|
||||
dst.Spec.Server.CheHost = src.Spec.Networking.Hostname
|
||||
dst.Spec.Server.CheServerIngress.Labels = utils.FormatLabels(src.Spec.Networking.Labels)
|
||||
dst.Spec.Server.CheServerIngress.Annotations = utils.CloneMap(src.Spec.Networking.Annotations)
|
||||
delete(dst.Spec.Server.CheServerIngress.Annotations, "kubernetes.io/ingress.class")
|
||||
}
|
||||
|
||||
for _, c := range src.Spec.Networking.Auth.Gateway.Deployment.Containers {
|
||||
switch c.Name {
|
||||
case constants.GatewayContainerName:
|
||||
dst.Spec.Server.SingleHostGatewayImage = c.Image
|
||||
case constants.GatewayConfigSideCarContainerName:
|
||||
dst.Spec.Server.SingleHostGatewayConfigSidecarImage = c.Image
|
||||
}
|
||||
}
|
||||
|
||||
dst.Spec.Server.SingleHostGatewayConfigMapLabels = utils.CloneMap(src.Spec.Networking.Auth.Gateway.ConfigLabels)
|
||||
|
||||
trustStoreConfigMap, err := findTrustStoreConfigMap(src.Namespace)
|
||||
if err != nil {
|
||||
return err
|
||||
} else {
|
||||
dst.Spec.Server.ServerTrustStoreConfigMapName = trustStoreConfigMap
|
||||
}
|
||||
|
||||
if src.Spec.DevEnvironments.TrustedCerts.GitTrustedCertsConfigMapName != "" {
|
||||
dst.Spec.Server.GitSelfSignedCert = true
|
||||
}
|
||||
|
||||
if err := dst.convertFrom_Server_PluginRegistry(src); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := dst.convertFrom_Server_DevfileRegistry(src); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := dst.convertFrom_Server_Dashboard(src); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (dst *CheCluster) convertFrom_Server_PluginRegistry(src *chev2.CheCluster) error {
|
||||
dst.Spec.Server.ExternalPluginRegistry = src.Spec.Components.PluginRegistry.DisableInternalRegistry
|
||||
|
||||
if src.Spec.Components.PluginRegistry.DisableInternalRegistry {
|
||||
if len(src.Spec.Components.PluginRegistry.ExternalPluginRegistries) != 0 {
|
||||
dst.Spec.Server.PluginRegistryUrl = src.Spec.Components.PluginRegistry.ExternalPluginRegistries[0].Url
|
||||
}
|
||||
}
|
||||
|
||||
if len(src.Spec.Components.PluginRegistry.Deployment.Containers) != 0 {
|
||||
dst.Spec.Server.PluginRegistryImage = src.Spec.Components.PluginRegistry.Deployment.Containers[0].Image
|
||||
dst.Spec.Server.PluginRegistryPullPolicy = src.Spec.Components.PluginRegistry.Deployment.Containers[0].ImagePullPolicy
|
||||
dst.Spec.Server.PluginRegistryMemoryRequest = src.Spec.Components.PluginRegistry.Deployment.Containers[0].Resources.Requests.Memory.String()
|
||||
dst.Spec.Server.PluginRegistryCpuRequest = src.Spec.Components.PluginRegistry.Deployment.Containers[0].Resources.Requests.Cpu.String()
|
||||
dst.Spec.Server.PluginRegistryMemoryLimit = src.Spec.Components.PluginRegistry.Deployment.Containers[0].Resources.Limits.Memory.String()
|
||||
dst.Spec.Server.PluginRegistryCpuLimit = src.Spec.Components.PluginRegistry.Deployment.Containers[0].Resources.Limits.Cpu.String()
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (dst *CheCluster) convertFrom_Server_DevfileRegistry(src *chev2.CheCluster) error {
|
||||
dst.Spec.Server.ExternalDevfileRegistry = src.Spec.Components.DevfileRegistry.DisableInternalRegistry
|
||||
|
||||
for _, r := range src.Spec.Components.DevfileRegistry.ExternalDevfileRegistries {
|
||||
dst.Spec.Server.ExternalDevfileRegistries = append(dst.Spec.Server.ExternalDevfileRegistries,
|
||||
ExternalDevfileRegistries{
|
||||
Url: r.Url,
|
||||
})
|
||||
}
|
||||
|
||||
if len(src.Spec.Components.DevfileRegistry.Deployment.Containers) != 0 {
|
||||
dst.Spec.Server.DevfileRegistryImage = src.Spec.Components.DevfileRegistry.Deployment.Containers[0].Image
|
||||
dst.Spec.Server.DevfileRegistryPullPolicy = src.Spec.Components.DevfileRegistry.Deployment.Containers[0].ImagePullPolicy
|
||||
dst.Spec.Server.DevfileRegistryMemoryRequest = src.Spec.Components.DevfileRegistry.Deployment.Containers[0].Resources.Requests.Memory.String()
|
||||
dst.Spec.Server.DevfileRegistryCpuRequest = src.Spec.Components.DevfileRegistry.Deployment.Containers[0].Resources.Requests.Cpu.String()
|
||||
dst.Spec.Server.DevfileRegistryMemoryLimit = src.Spec.Components.DevfileRegistry.Deployment.Containers[0].Resources.Limits.Memory.String()
|
||||
dst.Spec.Server.DevfileRegistryCpuLimit = src.Spec.Components.DevfileRegistry.Deployment.Containers[0].Resources.Limits.Cpu.String()
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (dst *CheCluster) convertFrom_Server_Dashboard(src *chev2.CheCluster) error {
|
||||
if len(src.Spec.Components.Dashboard.Deployment.Containers) != 0 {
|
||||
dst.Spec.Server.DashboardImage = src.Spec.Components.Dashboard.Deployment.Containers[0].Image
|
||||
dst.Spec.Server.DashboardImagePullPolicy = string(src.Spec.Components.Dashboard.Deployment.Containers[0].ImagePullPolicy)
|
||||
dst.Spec.Server.DashboardMemoryRequest = src.Spec.Components.Dashboard.Deployment.Containers[0].Resources.Requests.Memory.String()
|
||||
dst.Spec.Server.DashboardCpuRequest = src.Spec.Components.Dashboard.Deployment.Containers[0].Resources.Requests.Cpu.String()
|
||||
dst.Spec.Server.DashboardMemoryLimit = src.Spec.Components.Dashboard.Deployment.Containers[0].Resources.Limits.Memory.String()
|
||||
dst.Spec.Server.DashboardCpuLimit = src.Spec.Components.Dashboard.Deployment.Containers[0].Resources.Limits.Cpu.String()
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (dst *CheCluster) convertFrom_K8s(src *chev2.CheCluster) error {
|
||||
if src.Spec.Components.CheServer.Deployment.SecurityContext.RunAsUser != nil {
|
||||
dst.Spec.K8s.SecurityContextRunAsUser = strconv.FormatInt(*src.Spec.Components.CheServer.Deployment.SecurityContext.RunAsUser, 10)
|
||||
}
|
||||
|
||||
if src.Spec.Components.CheServer.Deployment.SecurityContext.FsGroup != nil {
|
||||
dst.Spec.K8s.SecurityContextFsGroup = strconv.FormatInt(*src.Spec.Components.CheServer.Deployment.SecurityContext.FsGroup, 10)
|
||||
}
|
||||
|
||||
if !infrastructure.IsOpenShift() {
|
||||
dst.Spec.K8s.IngressDomain = src.Spec.Networking.Domain
|
||||
dst.Spec.K8s.TlsSecretName = src.Spec.Networking.TlsSecretName
|
||||
dst.Spec.K8s.IngressClass = src.Spec.Networking.Annotations["kubernetes.io/ingress.class"]
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (dst *CheCluster) convertFrom_Auth(src *chev2.CheCluster) error {
|
||||
dst.Spec.Auth.IdentityProviderURL = src.Spec.Networking.Auth.IdentityProviderURL
|
||||
dst.Spec.Auth.OAuthClientName = src.Spec.Networking.Auth.OAuthClientName
|
||||
dst.Spec.Auth.OAuthSecret = src.Spec.Networking.Auth.OAuthSecret
|
||||
|
||||
for _, c := range src.Spec.Networking.Auth.Gateway.Deployment.Containers {
|
||||
switch c.Name {
|
||||
case constants.GatewayAuthenticationContainerName:
|
||||
dst.Spec.Auth.GatewayAuthenticationSidecarImage = c.Image
|
||||
case constants.GatewayAuthorizationContainerName:
|
||||
dst.Spec.Auth.GatewayAuthorizationSidecarImage = c.Image
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (dst *CheCluster) convertFrom_Database(src *chev2.CheCluster) error {
|
||||
dst.Spec.Database.ExternalDb = src.Spec.Components.Database.ExternalDb
|
||||
dst.Spec.Database.ChePostgresDb = src.Spec.Components.Database.PostgresDb
|
||||
dst.Spec.Database.ChePostgresHostName = src.Spec.Components.Database.PostgresHostName
|
||||
dst.Spec.Database.ChePostgresPort = src.Spec.Components.Database.PostgresPort
|
||||
dst.Spec.Database.PostgresVersion = src.Status.PostgresVersion
|
||||
dst.Spec.Database.PvcClaimSize = src.Spec.Components.Database.Pvc.ClaimSize
|
||||
dst.Spec.Database.ChePostgresSecret = src.Spec.Components.Database.CredentialsSecretName
|
||||
|
||||
if len(src.Spec.Components.Database.Deployment.Containers) != 0 {
|
||||
dst.Spec.Database.PostgresImage = src.Spec.Components.Database.Deployment.Containers[0].Image
|
||||
dst.Spec.Database.PostgresImagePullPolicy = src.Spec.Components.Database.Deployment.Containers[0].ImagePullPolicy
|
||||
dst.Spec.Database.ChePostgresContainerResources.Requests.Memory = src.Spec.Components.Database.Deployment.Containers[0].Resources.Requests.Memory.String()
|
||||
dst.Spec.Database.ChePostgresContainerResources.Requests.Cpu = src.Spec.Components.Database.Deployment.Containers[0].Resources.Requests.Cpu.String()
|
||||
dst.Spec.Database.ChePostgresContainerResources.Limits.Memory = src.Spec.Components.Database.Deployment.Containers[0].Resources.Limits.Memory.String()
|
||||
dst.Spec.Database.ChePostgresContainerResources.Limits.Cpu = src.Spec.Components.Database.Deployment.Containers[0].Resources.Limits.Cpu.String()
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (dst *CheCluster) convertFrom_DevWorkspace(src *chev2.CheCluster) error {
|
||||
if len(src.Spec.Components.DevWorkspace.Deployment.Containers) != 0 {
|
||||
dst.Spec.DevWorkspace.ControllerImage = src.Spec.Components.DevWorkspace.Deployment.Containers[0].Image
|
||||
}
|
||||
dst.Spec.DevWorkspace.RunningLimit = src.Spec.Components.DevWorkspace.RunningLimit
|
||||
dst.Spec.DevWorkspace.Enable = true
|
||||
return nil
|
||||
}
|
||||
|
||||
func (dst *CheCluster) convertFrom_ImagePuller(src *chev2.CheCluster) error {
|
||||
dst.Spec.ImagePuller.Enable = src.Spec.Components.ImagePuller.Enable
|
||||
dst.Spec.ImagePuller.Spec = src.Spec.Components.ImagePuller.Spec
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (dst *CheCluster) convertFrom_Metrics(src *chev2.CheCluster) error {
|
||||
dst.Spec.Metrics.Enable = src.Spec.Components.Metrics.Enable
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (dst *CheCluster) convertFrom_Dashboard(src *chev2.CheCluster) error {
|
||||
dst.Spec.Dashboard.Warning = src.Spec.Components.Dashboard.HeaderMessage.Text
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (dst *CheCluster) convertFrom_Status(src *chev2.CheCluster) error {
|
||||
dst.Status.CheURL = src.Status.CheURL
|
||||
dst.Status.CheVersion = src.Status.CheVersion
|
||||
dst.Status.DevfileRegistryURL = src.Status.DevfileRegistryURL
|
||||
dst.Status.PluginRegistryURL = src.Status.PluginRegistryURL
|
||||
dst.Status.Message = src.Status.Message
|
||||
dst.Status.Reason = src.Status.Reason
|
||||
dst.Status.DevworkspaceStatus.GatewayPhase = GatewayPhase(src.Status.GatewayPhase)
|
||||
dst.Status.DevworkspaceStatus.GatewayHost = src.GetCheHost()
|
||||
dst.Status.DevworkspaceStatus.WorkspaceBaseDomain = src.Status.WorkspaceBaseDomain
|
||||
dst.Status.DevworkspaceStatus.Message = src.Status.Message
|
||||
dst.Status.DevworkspaceStatus.Phase = ClusterPhase(src.Status.ChePhase)
|
||||
dst.Status.DevworkspaceStatus.Reason = src.Status.Reason
|
||||
|
||||
switch src.Status.ChePhase {
|
||||
case chev2.ClusterPhaseActive:
|
||||
dst.Status.CheClusterRunning = "Available"
|
||||
case chev2.ClusterPhaseInactive:
|
||||
dst.Status.CheClusterRunning = "Unavailable"
|
||||
case chev2.RollingUpdate:
|
||||
dst.Status.CheClusterRunning = "Available, Rolling Update in Progress"
|
||||
}
|
||||
|
||||
if src.Spec.DevEnvironments.TrustedCerts.GitTrustedCertsConfigMapName != "" {
|
||||
dst.Status.GitServerTLSCertificateConfigMapName = src.Spec.DevEnvironments.TrustedCerts.GitTrustedCertsConfigMapName
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (dst *CheCluster) convertFrom_Storage(src *chev2.CheCluster) error {
|
||||
dst.Spec.Storage.PostgresPVCStorageClassName = src.Spec.Components.Database.Pvc.StorageClass
|
||||
dst.Spec.Storage.PvcClaimSize = src.Spec.DevEnvironments.Storage.Pvc.ClaimSize
|
||||
dst.Spec.Storage.WorkspacePVCStorageClassName = src.Spec.DevEnvironments.Storage.Pvc.StorageClass
|
||||
dst.Spec.Storage.PvcStrategy = src.Spec.DevEnvironments.Storage.PvcStrategy
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Finds TrustStore ConfigMap.
|
||||
func findTrustStoreConfigMap(namespace string) (string, error) {
|
||||
k8sHelper := k8shelper.New()
|
||||
|
||||
_, err := k8sHelper.GetClientset().CoreV1().ConfigMaps(namespace).Get(context.TODO(), constants.DefaultServerTrustStoreConfigMapName, metav1.GetOptions{})
|
||||
if err == nil {
|
||||
// TrustStore ConfigMap with a default name exists
|
||||
return constants.DefaultServerTrustStoreConfigMapName, nil
|
||||
}
|
||||
|
||||
return "", nil
|
||||
}
|
||||
|
|
@ -0,0 +1,634 @@
|
|||
//
|
||||
// Copyright (c) 2019-2022 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 v1
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"k8s.io/apimachinery/pkg/api/resource"
|
||||
|
||||
"github.com/eclipse-che/che-operator/pkg/common/utils"
|
||||
ctrl "sigs.k8s.io/controller-runtime"
|
||||
|
||||
"github.com/devfile/devworkspace-operator/pkg/infrastructure"
|
||||
chev2 "github.com/eclipse-che/che-operator/api/v2"
|
||||
"github.com/eclipse-che/che-operator/pkg/common/constants"
|
||||
k8shelper "github.com/eclipse-che/che-operator/pkg/common/k8s-helper"
|
||||
defaults "github.com/eclipse-che/che-operator/pkg/common/operator-defaults"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"k8s.io/utils/pointer"
|
||||
"sigs.k8s.io/controller-runtime/pkg/conversion"
|
||||
)
|
||||
|
||||
var (
|
||||
logger = ctrl.Log.WithName("conversion")
|
||||
)
|
||||
|
||||
func (src *CheCluster) ConvertTo(dstRaw conversion.Hub) error {
|
||||
dst := dstRaw.(*chev2.CheCluster)
|
||||
dst.ObjectMeta = src.ObjectMeta
|
||||
|
||||
if err := src.convertTo_Components(dst); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := src.convertTo_Networking(dst); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := src.convertTo_DevEnvironments(dst); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := src.convertTo_ContainerRegistry(dst); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := src.convertTo_Status(dst); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (src *CheCluster) convertTo_Status(dst *chev2.CheCluster) error {
|
||||
dst.Status.PostgresVersion = src.Spec.Database.PostgresVersion
|
||||
dst.Status.CheURL = src.Status.CheURL
|
||||
dst.Status.CheVersion = src.Status.CheVersion
|
||||
dst.Status.DevfileRegistryURL = src.Status.DevfileRegistryURL
|
||||
dst.Status.PluginRegistryURL = src.Status.PluginRegistryURL
|
||||
dst.Status.Message = src.Status.Message
|
||||
dst.Status.Reason = src.Status.Reason
|
||||
dst.Status.GatewayPhase = chev2.GatewayPhase(src.Status.DevworkspaceStatus.GatewayPhase)
|
||||
dst.Status.WorkspaceBaseDomain = src.Status.DevworkspaceStatus.WorkspaceBaseDomain
|
||||
|
||||
switch src.Status.CheClusterRunning {
|
||||
case "Available":
|
||||
dst.Status.ChePhase = chev2.ClusterPhaseActive
|
||||
case "Unavailable":
|
||||
dst.Status.ChePhase = chev2.ClusterPhaseInactive
|
||||
case "Available, Rolling Update in Progress":
|
||||
dst.Status.ChePhase = chev2.RollingUpdate
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (src *CheCluster) convertTo_ContainerRegistry(dst *chev2.CheCluster) error {
|
||||
dst.Spec.ContainerRegistry.Hostname = src.Spec.Server.AirGapContainerRegistryHostname
|
||||
dst.Spec.ContainerRegistry.Organization = src.Spec.Server.AirGapContainerRegistryOrganization
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (src *CheCluster) convertTo_DevEnvironments(dst *chev2.CheCluster) error {
|
||||
if src.Spec.Server.GitSelfSignedCert {
|
||||
if src.Status.GitServerTLSCertificateConfigMapName != "" {
|
||||
dst.Spec.DevEnvironments.TrustedCerts.GitTrustedCertsConfigMapName = src.Status.GitServerTLSCertificateConfigMapName
|
||||
} else {
|
||||
dst.Spec.DevEnvironments.TrustedCerts.GitTrustedCertsConfigMapName = constants.DefaultGitSelfSignedCertsConfigMapName
|
||||
}
|
||||
}
|
||||
|
||||
dst.Spec.DevEnvironments.DefaultNamespace.Template = src.Spec.Server.WorkspaceNamespaceDefault
|
||||
dst.Spec.DevEnvironments.NodeSelector = utils.CloneMap(src.Spec.Server.WorkspacePodNodeSelector)
|
||||
|
||||
for _, v := range src.Spec.Server.WorkspacePodTolerations {
|
||||
dst.Spec.DevEnvironments.Tolerations = append(dst.Spec.DevEnvironments.Tolerations, v)
|
||||
}
|
||||
|
||||
for _, p := range src.Spec.Server.WorkspacesDefaultPlugins {
|
||||
dst.Spec.DevEnvironments.DefaultPlugins = append(dst.Spec.DevEnvironments.DefaultPlugins,
|
||||
chev2.WorkspaceDefaultPlugins{
|
||||
Editor: p.Editor,
|
||||
Plugins: p.Plugins,
|
||||
})
|
||||
}
|
||||
|
||||
if err := src.convertTo_Workspaces_Storage(dst); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (src *CheCluster) convertTo_Workspaces_Storage(dst *chev2.CheCluster) error {
|
||||
dst.Spec.DevEnvironments.Storage.Pvc = chev2.PVC{
|
||||
ClaimSize: src.Spec.Storage.PvcClaimSize,
|
||||
StorageClass: src.Spec.Storage.WorkspacePVCStorageClassName,
|
||||
}
|
||||
dst.Spec.DevEnvironments.Storage.PvcStrategy = src.Spec.Storage.PvcStrategy
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (src *CheCluster) convertTo_Networking(dst *chev2.CheCluster) error {
|
||||
if infrastructure.IsOpenShift() {
|
||||
dst.Spec.Networking = chev2.CheClusterSpecNetworking{
|
||||
Labels: utils.ParseMap(src.Spec.Server.CheServerRoute.Labels),
|
||||
Annotations: utils.CloneMap(src.Spec.Server.CheServerRoute.Annotations),
|
||||
Hostname: src.Spec.Server.CheHost,
|
||||
Domain: src.Spec.Server.CheServerRoute.Domain,
|
||||
TlsSecretName: src.Spec.Server.CheHostTLSSecret,
|
||||
}
|
||||
} else {
|
||||
dst.Spec.Networking = chev2.CheClusterSpecNetworking{
|
||||
Labels: utils.ParseMap(src.Spec.Server.CheServerIngress.Labels),
|
||||
Domain: src.Spec.K8s.IngressDomain,
|
||||
Hostname: src.Spec.Server.CheHost,
|
||||
}
|
||||
|
||||
if src.Spec.Server.CheHostTLSSecret != "" {
|
||||
dst.Spec.Networking.TlsSecretName = src.Spec.Server.CheHostTLSSecret
|
||||
} else {
|
||||
dst.Spec.Networking.TlsSecretName = src.Spec.K8s.TlsSecretName
|
||||
}
|
||||
|
||||
if src.Spec.K8s.IngressClass != "" {
|
||||
dst.Spec.Networking.Annotations = map[string]string{"kubernetes.io/ingress.class": src.Spec.K8s.IngressClass}
|
||||
}
|
||||
|
||||
if len(dst.Spec.Networking.Annotations) > 0 || len(src.Spec.Server.CheServerIngress.Annotations) > 0 {
|
||||
dst.Spec.Networking.Annotations = labels.Merge(dst.Spec.Networking.Annotations, src.Spec.Server.CheServerIngress.Annotations)
|
||||
}
|
||||
}
|
||||
|
||||
if err := src.convertTo_Networking_Auth(dst); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (src *CheCluster) convertTo_Networking_Auth(dst *chev2.CheCluster) error {
|
||||
dst.Spec.Networking.Auth.IdentityProviderURL = src.Spec.Auth.IdentityProviderURL
|
||||
dst.Spec.Networking.Auth.OAuthClientName = src.Spec.Auth.OAuthClientName
|
||||
dst.Spec.Networking.Auth.OAuthSecret = src.Spec.Auth.OAuthSecret
|
||||
|
||||
if err := src.convertTo_Networking_Auth_Gateway(dst); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (src *CheCluster) convertTo_Networking_Auth_Gateway(dst *chev2.CheCluster) error {
|
||||
dst.Spec.Networking.Auth.Gateway.ConfigLabels = utils.CloneMap(src.Spec.Server.SingleHostGatewayConfigMapLabels)
|
||||
|
||||
if src.Spec.Server.SingleHostGatewayImage != "" {
|
||||
dst.Spec.Networking.Auth.Gateway.Deployment.Containers = append(
|
||||
dst.Spec.Networking.Auth.Gateway.Deployment.Containers,
|
||||
chev2.Container{
|
||||
Name: constants.GatewayContainerName,
|
||||
Image: src.Spec.Server.SingleHostGatewayImage,
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
if src.Spec.Server.SingleHostGatewayConfigSidecarImage != "" {
|
||||
dst.Spec.Networking.Auth.Gateway.Deployment.Containers = append(
|
||||
dst.Spec.Networking.Auth.Gateway.Deployment.Containers,
|
||||
chev2.Container{
|
||||
Name: constants.GatewayConfigSideCarContainerName,
|
||||
Image: src.Spec.Server.SingleHostGatewayConfigSidecarImage,
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
if src.Spec.Auth.GatewayAuthenticationSidecarImage != "" {
|
||||
dst.Spec.Networking.Auth.Gateway.Deployment.Containers = append(
|
||||
dst.Spec.Networking.Auth.Gateway.Deployment.Containers,
|
||||
chev2.Container{
|
||||
Name: constants.GatewayAuthenticationContainerName,
|
||||
Image: src.Spec.Auth.GatewayAuthenticationSidecarImage,
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
if src.Spec.Auth.GatewayAuthorizationSidecarImage != "" {
|
||||
dst.Spec.Networking.Auth.Gateway.Deployment.Containers = append(
|
||||
dst.Spec.Networking.Auth.Gateway.Deployment.Containers,
|
||||
chev2.Container{
|
||||
Name: constants.GatewayAuthorizationContainerName,
|
||||
Image: src.Spec.Auth.GatewayAuthorizationSidecarImage,
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (src *CheCluster) convertTo_Components(dst *chev2.CheCluster) error {
|
||||
if err := src.convertTo_Components_Dashboard(dst); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := src.convertTo_Components_DevfileRegistry(dst); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := src.convertTo_Components_PluginRegistry(dst); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := src.convertTo_Components_CheServer(dst); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := src.convertTo_Components_Database(dst); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := src.convertTo_Components_Metrics(dst); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := src.convertTo_Components_ImagePuller(dst); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := src.convertTo_Components_DevWorkspace(dst); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (src *CheCluster) convertTo_Components_DevWorkspace(dst *chev2.CheCluster) error {
|
||||
if src.Spec.DevWorkspace.ControllerImage != "" {
|
||||
dst.Spec.Components.DevWorkspace.Deployment = chev2.Deployment{
|
||||
Containers: []chev2.Container{
|
||||
{
|
||||
Name: constants.DevWorkspaceController,
|
||||
Image: src.Spec.DevWorkspace.ControllerImage,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
dst.Spec.Components.DevWorkspace.RunningLimit = src.Spec.DevWorkspace.RunningLimit
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (src *CheCluster) convertTo_Components_ImagePuller(dst *chev2.CheCluster) error {
|
||||
dst.Spec.Components.ImagePuller.Enable = src.Spec.ImagePuller.Enable
|
||||
dst.Spec.Components.ImagePuller.Spec = src.Spec.ImagePuller.Spec
|
||||
return nil
|
||||
}
|
||||
|
||||
func (src *CheCluster) convertTo_Components_Metrics(dst *chev2.CheCluster) error {
|
||||
dst.Spec.Components.Metrics.Enable = src.Spec.Metrics.Enable
|
||||
return nil
|
||||
}
|
||||
|
||||
func (src *CheCluster) convertTo_Components_CheServer(dst *chev2.CheCluster) error {
|
||||
dst.Spec.Components.CheServer.ExtraProperties = utils.CloneMap(src.Spec.Server.CustomCheProperties)
|
||||
dst.Spec.Components.CheServer.LogLevel = src.Spec.Server.CheLogLevel
|
||||
if src.Spec.Server.CheClusterRoles != "" {
|
||||
dst.Spec.Components.CheServer.ClusterRoles = strings.Split(src.Spec.Server.CheClusterRoles, ",")
|
||||
}
|
||||
|
||||
if src.Spec.Server.CheDebug != "" {
|
||||
debug, err := strconv.ParseBool(src.Spec.Server.CheDebug)
|
||||
if err != nil {
|
||||
return err
|
||||
} else {
|
||||
dst.Spec.Components.CheServer.Debug = pointer.BoolPtr(debug)
|
||||
}
|
||||
}
|
||||
|
||||
dst.Spec.Components.CheServer.Proxy = chev2.Proxy{
|
||||
Url: src.Spec.Server.ProxyURL,
|
||||
Port: src.Spec.Server.ProxyPort,
|
||||
CredentialsSecretName: src.Spec.Server.ProxySecret,
|
||||
}
|
||||
if src.Spec.Server.NonProxyHosts != "" {
|
||||
dst.Spec.Components.CheServer.Proxy.NonProxyHosts = strings.Split(src.Spec.Server.NonProxyHosts, "|")
|
||||
}
|
||||
|
||||
if src.Spec.Server.ProxySecret == "" && src.Spec.Server.ProxyUser != "" && src.Spec.Server.ProxyPassword != "" {
|
||||
if err := createCredentialsSecret(
|
||||
src.Spec.Server.ProxyUser,
|
||||
src.Spec.Server.ProxyPassword,
|
||||
constants.DefaultProxyCredentialsSecret,
|
||||
src.ObjectMeta.Namespace); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
dst.Spec.Components.CheServer.Proxy.CredentialsSecretName = constants.DefaultProxyCredentialsSecret
|
||||
}
|
||||
|
||||
runAsUser, fsGroup, err := parseSecurityContext(src)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
dst.Spec.Components.CheServer.Deployment = toCheV2Deployment(
|
||||
defaults.GetCheFlavor(),
|
||||
map[bool]string{true: src.Spec.Server.CheImage + ":" + src.Spec.Server.CheImageTag, false: ""}[src.Spec.Server.CheImage != ""],
|
||||
src.Spec.Server.CheImagePullPolicy,
|
||||
src.Spec.Server.ServerMemoryRequest,
|
||||
src.Spec.Server.ServerMemoryLimit,
|
||||
src.Spec.Server.ServerCpuRequest,
|
||||
src.Spec.Server.ServerCpuLimit,
|
||||
fsGroup,
|
||||
runAsUser,
|
||||
)
|
||||
|
||||
if src.Spec.Server.ServerTrustStoreConfigMapName != "" {
|
||||
if err := renameTrustStoreConfigMapToDefault(src.Spec.Server.ServerTrustStoreConfigMapName, src.Namespace); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (src *CheCluster) convertTo_Components_PluginRegistry(dst *chev2.CheCluster) error {
|
||||
dst.Spec.Components.PluginRegistry.DisableInternalRegistry = src.Spec.Server.ExternalPluginRegistry
|
||||
|
||||
if dst.Spec.Components.PluginRegistry.DisableInternalRegistry {
|
||||
dst.Spec.Components.PluginRegistry.ExternalPluginRegistries = []chev2.ExternalPluginRegistry{
|
||||
{
|
||||
Url: src.Spec.Server.PluginRegistryUrl,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
dst.Spec.Components.PluginRegistry.Deployment = toCheV2Deployment(
|
||||
constants.PluginRegistryName,
|
||||
src.Spec.Server.PluginRegistryImage,
|
||||
src.Spec.Server.PluginRegistryPullPolicy,
|
||||
src.Spec.Server.PluginRegistryMemoryRequest,
|
||||
src.Spec.Server.PluginRegistryMemoryLimit,
|
||||
src.Spec.Server.PluginRegistryCpuRequest,
|
||||
src.Spec.Server.PluginRegistryCpuLimit,
|
||||
nil,
|
||||
nil,
|
||||
)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (src *CheCluster) convertTo_Components_DevfileRegistry(dst *chev2.CheCluster) error {
|
||||
dst.Spec.Components.DevfileRegistry.DisableInternalRegistry = src.Spec.Server.ExternalDevfileRegistry
|
||||
|
||||
for _, r := range src.Spec.Server.ExternalDevfileRegistries {
|
||||
dst.Spec.Components.DevfileRegistry.ExternalDevfileRegistries = append(dst.Spec.Components.DevfileRegistry.ExternalDevfileRegistries,
|
||||
chev2.ExternalDevfileRegistry{
|
||||
Url: r.Url,
|
||||
})
|
||||
}
|
||||
|
||||
dst.Spec.Components.DevfileRegistry.Deployment = toCheV2Deployment(
|
||||
constants.DevfileRegistryName,
|
||||
src.Spec.Server.DevfileRegistryImage,
|
||||
src.Spec.Server.DevfileRegistryPullPolicy,
|
||||
src.Spec.Server.DevfileRegistryMemoryRequest,
|
||||
src.Spec.Server.DevfileRegistryMemoryLimit,
|
||||
src.Spec.Server.DevfileRegistryCpuRequest,
|
||||
src.Spec.Server.DevfileRegistryCpuLimit,
|
||||
nil,
|
||||
nil,
|
||||
)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (src *CheCluster) convertTo_Components_Database(dst *chev2.CheCluster) error {
|
||||
dst.Spec.Components.Database.CredentialsSecretName = src.Spec.Database.ChePostgresSecret
|
||||
|
||||
if src.Spec.Database.ChePostgresSecret == "" && src.Spec.Database.ChePostgresUser != "" && src.Spec.Database.ChePostgresPassword != "" {
|
||||
if err := createCredentialsSecret(
|
||||
src.Spec.Database.ChePostgresUser,
|
||||
src.Spec.Database.ChePostgresPassword,
|
||||
constants.DefaultPostgresCredentialsSecret,
|
||||
src.ObjectMeta.Namespace); err != nil {
|
||||
return err
|
||||
}
|
||||
dst.Spec.Components.Database.CredentialsSecretName = constants.DefaultPostgresCredentialsSecret
|
||||
}
|
||||
|
||||
dst.Spec.Components.Database.Deployment = toCheV2Deployment(
|
||||
constants.PostgresName,
|
||||
src.Spec.Database.PostgresImage,
|
||||
src.Spec.Database.PostgresImagePullPolicy,
|
||||
src.Spec.Database.ChePostgresContainerResources.Requests.Memory,
|
||||
src.Spec.Database.ChePostgresContainerResources.Limits.Memory,
|
||||
src.Spec.Database.ChePostgresContainerResources.Requests.Cpu,
|
||||
src.Spec.Database.ChePostgresContainerResources.Limits.Cpu,
|
||||
nil,
|
||||
nil,
|
||||
)
|
||||
|
||||
dst.Spec.Components.Database.ExternalDb = src.Spec.Database.ExternalDb
|
||||
dst.Spec.Components.Database.PostgresDb = src.Spec.Database.ChePostgresDb
|
||||
dst.Spec.Components.Database.PostgresHostName = src.Spec.Database.ChePostgresHostName
|
||||
dst.Spec.Components.Database.PostgresPort = src.Spec.Database.ChePostgresPort
|
||||
dst.Spec.Components.Database.Pvc = chev2.PVC{
|
||||
ClaimSize: src.Spec.Database.PvcClaimSize,
|
||||
StorageClass: src.Spec.Storage.PostgresPVCStorageClassName,
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (src *CheCluster) convertTo_Components_Dashboard(dst *chev2.CheCluster) error {
|
||||
runAsUser, fsGroup, err := parseSecurityContext(src)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
dst.Spec.Components.Dashboard.Deployment = toCheV2Deployment(
|
||||
defaults.GetCheFlavor()+"-dashboard",
|
||||
src.Spec.Server.DashboardImage,
|
||||
corev1.PullPolicy(src.Spec.Server.DashboardImagePullPolicy),
|
||||
src.Spec.Server.DashboardMemoryRequest,
|
||||
src.Spec.Server.DashboardMemoryLimit,
|
||||
src.Spec.Server.DashboardCpuRequest,
|
||||
src.Spec.Server.DashboardCpuLimit,
|
||||
fsGroup,
|
||||
runAsUser,
|
||||
)
|
||||
|
||||
dst.Spec.Components.Dashboard.HeaderMessage.Text = src.Spec.Dashboard.Warning
|
||||
dst.Spec.Components.Dashboard.HeaderMessage.Show = src.Spec.Dashboard.Warning != ""
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func parseSecurityContext(cheClusterV1 *CheCluster) (*int64, *int64, error) {
|
||||
var runAsUser *int64 = nil
|
||||
if cheClusterV1.Spec.K8s.SecurityContextRunAsUser != "" {
|
||||
intValue, err := strconv.ParseInt(cheClusterV1.Spec.K8s.SecurityContextRunAsUser, 10, 64)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
runAsUser = pointer.Int64Ptr(intValue)
|
||||
}
|
||||
|
||||
var fsGroup *int64 = nil
|
||||
if cheClusterV1.Spec.K8s.SecurityContextFsGroup != "" {
|
||||
intValue, err := strconv.ParseInt(cheClusterV1.Spec.K8s.SecurityContextFsGroup, 10, 64)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
fsGroup = pointer.Int64Ptr(intValue)
|
||||
}
|
||||
|
||||
return runAsUser, fsGroup, nil
|
||||
}
|
||||
|
||||
// Create a secret with a user's credentials
|
||||
// Username and password are stored in `user` and `password` fields correspondingly.
|
||||
func createCredentialsSecret(username string, password string, secretName string, namespace string) error {
|
||||
k8sHelper := k8shelper.New()
|
||||
|
||||
_, err := k8sHelper.GetClientset().CoreV1().Secrets(namespace).Get(context.TODO(), secretName, metav1.GetOptions{})
|
||||
if err == nil {
|
||||
// Credentials secret already exists, we can't proceed
|
||||
return fmt.Errorf("secret %s already exists", secretName)
|
||||
}
|
||||
|
||||
secret := &corev1.Secret{
|
||||
ObjectMeta: v1.ObjectMeta{
|
||||
Name: secretName,
|
||||
Namespace: namespace,
|
||||
Labels: map[string]string{
|
||||
"app.kubernetes.io/part-of": "che.eclipse.org",
|
||||
},
|
||||
},
|
||||
Data: map[string][]byte{
|
||||
"user": []byte(username),
|
||||
"password": []byte(password),
|
||||
},
|
||||
}
|
||||
|
||||
if _, err := k8sHelper.GetClientset().CoreV1().Secrets(namespace).Create(context.TODO(), secret, metav1.CreateOptions{}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
logger.Info("Credentials secret '" + secretName + "' with created.")
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert `server.ServerTrustStoreConfigMapName` field from API V1 to API V2
|
||||
// Since we API V2 does not have `server.ServerTrustStoreConfigMapName` field, we need to create
|
||||
// the same ConfigMap but with a default name to be correctly handled by a controller.
|
||||
func renameTrustStoreConfigMapToDefault(trustStoreConfigMapName string, namespace string) error {
|
||||
if trustStoreConfigMapName == constants.DefaultServerTrustStoreConfigMapName {
|
||||
// Already in default name
|
||||
return nil
|
||||
}
|
||||
|
||||
k8sHelper := k8shelper.New()
|
||||
|
||||
_, err := k8sHelper.GetClientset().CoreV1().ConfigMaps(namespace).Get(context.TODO(), constants.DefaultServerTrustStoreConfigMapName, metav1.GetOptions{})
|
||||
if err == nil {
|
||||
// ConfigMap with a default name already exists, we can't proceed
|
||||
return fmt.Errorf("TrustStore ConfigMap %s already exists", constants.DefaultServerTrustStoreConfigMapName)
|
||||
}
|
||||
|
||||
existedTrustStoreConfigMap, err := k8sHelper.GetClientset().CoreV1().ConfigMaps(namespace).Get(context.TODO(), trustStoreConfigMapName, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
if errors.IsNotFound(err) {
|
||||
// ConfigMap not found, nothing to rename
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// must have labels
|
||||
newTrustStoreConfigMapLabels := map[string]string{
|
||||
"app.kubernetes.io/part-of": "che.eclipse.org",
|
||||
"app.kubernetes.io/component": "ca-bundle",
|
||||
}
|
||||
|
||||
newTrustStoreConfigMap := &corev1.ConfigMap{
|
||||
TypeMeta: metav1.TypeMeta{
|
||||
Kind: "ConfigMap",
|
||||
APIVersion: "v1",
|
||||
},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: constants.DefaultServerTrustStoreConfigMapName,
|
||||
Namespace: namespace,
|
||||
Labels: labels.Merge(newTrustStoreConfigMapLabels, existedTrustStoreConfigMap.Labels),
|
||||
},
|
||||
Data: existedTrustStoreConfigMap.Data,
|
||||
}
|
||||
|
||||
// Create TrustStore ConfigMap with a default name
|
||||
if _, err = k8sHelper.GetClientset().CoreV1().ConfigMaps(namespace).Create(context.TODO(), newTrustStoreConfigMap, metav1.CreateOptions{}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Delete legacy TrustStore ConfigMap
|
||||
if err = k8sHelper.GetClientset().CoreV1().ConfigMaps(namespace).Delete(context.TODO(), trustStoreConfigMapName, metav1.DeleteOptions{}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
logger.Info("TrustStore ConfigMap '" + constants.DefaultServerTrustStoreConfigMapName + "' created.")
|
||||
return nil
|
||||
}
|
||||
|
||||
func toCheV2Deployment(
|
||||
name string,
|
||||
image string,
|
||||
imagePullPolicy corev1.PullPolicy,
|
||||
memoryRequest string,
|
||||
memoryLimit string,
|
||||
cpuRequest string,
|
||||
cpuLimit string,
|
||||
fsGroup *int64,
|
||||
runAsUser *int64) chev2.Deployment {
|
||||
|
||||
deployment := chev2.Deployment{}
|
||||
|
||||
container := chev2.Container{}
|
||||
if image != "" {
|
||||
container.Image = image
|
||||
}
|
||||
if imagePullPolicy != "" {
|
||||
container.ImagePullPolicy = imagePullPolicy
|
||||
}
|
||||
if memoryRequest != "" {
|
||||
container.Resources.Requests.Memory = resource.MustParse(memoryRequest)
|
||||
}
|
||||
if memoryLimit != "" {
|
||||
container.Resources.Limits.Memory = resource.MustParse(memoryLimit)
|
||||
}
|
||||
if cpuRequest != "" {
|
||||
container.Resources.Requests.Cpu = resource.MustParse(cpuRequest)
|
||||
}
|
||||
if cpuLimit != "" {
|
||||
container.Resources.Limits.Cpu = resource.MustParse(cpuLimit)
|
||||
}
|
||||
if !reflect.DeepEqual(container, chev2.Container{}) {
|
||||
container.Name = name
|
||||
deployment.Containers = []chev2.Container{container}
|
||||
}
|
||||
|
||||
deployment.SecurityContext.RunAsUser = runAsUser
|
||||
deployment.SecurityContext.FsGroup = fsGroup
|
||||
|
||||
return deployment
|
||||
}
|
||||
|
|
@ -12,16 +12,12 @@
|
|||
|
||||
package v1
|
||||
|
||||
// Important: You must regenerate some generated code after modifying this file. At the root of the project:
|
||||
// Run `make generate`. It will perform required changes:
|
||||
// - update `api/v1/zz_generatedxxx` files;
|
||||
// - update `config/crd/bases/org_v1_checluster_crd.yaml` file;
|
||||
// Important: Don't modify this file.
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
chev1alpha1 "github.com/che-incubator/kubernetes-image-puller-operator/api/v1alpha1"
|
||||
v2alpha1 "github.com/eclipse-che/che-operator/api/v2alpha1"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
|
|
@ -719,6 +715,50 @@ type ExternalDevfileRegistries struct {
|
|||
Url string `json:"url,omitempty"`
|
||||
}
|
||||
|
||||
// GatewayPhase describes the different phases of the Che gateway lifecycle
|
||||
type GatewayPhase string
|
||||
|
||||
const (
|
||||
GatewayPhaseInitializing = "Initializing"
|
||||
GatewayPhaseEstablished = "Established"
|
||||
GatewayPhaseInactive = "Inactive"
|
||||
)
|
||||
|
||||
// ClusterPhase describes the different phases of the Che cluster lifecycle
|
||||
type ClusterPhase string
|
||||
|
||||
const (
|
||||
ClusterPhaseActive = "Active"
|
||||
ClusterPhaseInactive = "Inactive"
|
||||
ClusterPhasePendingDeletion = "PendingDeletion"
|
||||
)
|
||||
|
||||
// LegacyDevworkspaceStatus contains the status of the CheCluster object
|
||||
// +k8s:openapi-gen=true
|
||||
type LegacyDevworkspaceStatus struct {
|
||||
// GatewayPhase specifies the phase in which the gateway deployment currently is.
|
||||
// If the gateway is disabled, the phase is "Inactive".
|
||||
GatewayPhase GatewayPhase `json:"gatewayPhase,omitempty"`
|
||||
|
||||
// GatewayHost is the resolved host of the ingress/route. This is equal to the Host in the spec
|
||||
// on Kubernetes but contains the actual host name of the route if Host is unspecified on OpenShift.
|
||||
GatewayHost string `json:"gatewayHost,omitempty"`
|
||||
|
||||
// Phase is the phase in which the Che cluster as a whole finds itself in.
|
||||
Phase ClusterPhase `json:"phase,omitempty"`
|
||||
|
||||
// A brief CamelCase message indicating details about why the Che cluster is in this state.
|
||||
Reason string `json:"reason,omitempty"`
|
||||
|
||||
// Message contains further human-readable info for why the Che cluster is in the phase it currently is.
|
||||
Message string `json:"message,omitempty"`
|
||||
|
||||
// The resolved workspace base domain. This is either the copy of the explicitly defined property of the
|
||||
// same name in the spec or, if it is undefined in the spec and we're running on OpenShift, the automatically
|
||||
// resolved basedomain for routes.
|
||||
WorkspaceBaseDomain string `json:"workspaceBaseDomain,omitempty"`
|
||||
}
|
||||
|
||||
// CheClusterStatus defines the observed state of Che installation
|
||||
type CheClusterStatus struct {
|
||||
// OpenShift OAuth secret in `openshift-config` namespace that contains user credentials for HTPasswd identity provider.
|
||||
|
|
@ -738,6 +778,12 @@ type CheClusterStatus struct {
|
|||
// Indicates whether an Identity Provider instance, Keycloak or RH-SSO, has been configured to integrate with the GitHub OAuth.
|
||||
// +optional
|
||||
GitHubOAuthProvisioned bool `json:"gitHubOAuthProvisioned"`
|
||||
// The ConfigMap containing certificates to propagate to the Che components and to provide particular configuration for Git.
|
||||
// +optional
|
||||
// +operator-sdk:csv:customresourcedefinitions:type=status
|
||||
// +operator-sdk:csv:customresourcedefinitions:type=status,displayName="Git certificates"
|
||||
// +operator-sdk:csv:customresourcedefinitions:type=status,xDescriptors="urn:alm:descriptor:text"
|
||||
GitServerTLSCertificateConfigMapName string `json:"gitServerTLSCertificateConfigMapName"`
|
||||
// Status of a Che installation. Can be `Available`, `Unavailable`, or `Available, Rolling Update in Progress`.
|
||||
// +optional
|
||||
// +operator-sdk:csv:customresourcedefinitions:type=status
|
||||
|
|
@ -794,7 +840,7 @@ type CheClusterStatus struct {
|
|||
HelpLink string `json:"helpLink,omitempty"`
|
||||
// The status of the Devworkspace subsystem
|
||||
// +optional
|
||||
DevworkspaceStatus v2alpha1.CheClusterStatusV2Alpha1 `json:"devworkspaceStatus,omitempty"`
|
||||
DevworkspaceStatus LegacyDevworkspaceStatus `json:"devworkspaceStatus,omitempty"`
|
||||
}
|
||||
|
||||
// The `CheCluster` custom resource allows defining and managing a Che server installation
|
||||
|
|
@ -803,9 +849,8 @@ type CheClusterStatus struct {
|
|||
// +kubebuilder:subresource:status
|
||||
// +k8s:openapi-gen=true
|
||||
// +operator-sdk:csv:customresourcedefinitions:displayName="Eclipse Che instance Specification"
|
||||
// +operator-sdk:csv:customresourcedefinitions:order=0
|
||||
// +operator-sdk:csv:customresourcedefinitions:order=1
|
||||
// +operator-sdk:csv:customresourcedefinitions:resources={{Ingress,v1},{Route,v1},{ConfigMap,v1},{Service,v1},{Secret,v1},{Deployment,apps/v1},{Role,v1},{RoleBinding,v1},{ClusterRole,v1},{ClusterRoleBinding,v1}}
|
||||
// +kubebuilder:storageversion
|
||||
type CheCluster struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
metav1.ObjectMeta `json:"metadata,omitempty"`
|
||||
|
|
|
|||
|
|
@ -366,6 +366,21 @@ func (in *IngressCustomSettings) DeepCopy() *IngressCustomSettings {
|
|||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *LegacyDevworkspaceStatus) DeepCopyInto(out *LegacyDevworkspaceStatus) {
|
||||
*out = *in
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LegacyDevworkspaceStatus.
|
||||
func (in *LegacyDevworkspaceStatus) DeepCopy() *LegacyDevworkspaceStatus {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(LegacyDevworkspaceStatus)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *Resources) DeepCopyInto(out *Resources) {
|
||||
*out = *in
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
//
|
||||
// Copyright (c) 2019-2021 Red Hat, Inc.
|
||||
// Copyright (c) 2019-2022 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/
|
||||
|
|
@ -10,10 +10,6 @@
|
|||
// Red Hat, Inc. - initial API and implementation
|
||||
//
|
||||
|
||||
package v1
|
||||
package v2
|
||||
|
||||
const (
|
||||
STATE_IN_PROGRESS = "InProgress"
|
||||
STATE_SUCCEEDED = "Succeeded"
|
||||
STATE_FAILED = "Failed"
|
||||
)
|
||||
func (*CheCluster) Hub() {}
|
||||
|
|
@ -0,0 +1,633 @@
|
|||
//
|
||||
// Copyright (c) 2019-2021 Red Hat, Inc.
|
||||
// This program and the accompanying materials are made
|
||||
// available under the terms of the Eclipse Public License 2.0
|
||||
// which is available at https://www.eclipse.org/legal/epl-2.0/
|
||||
//
|
||||
// SPDX-License-Identifier: EPL-2.0
|
||||
//
|
||||
// Contributors:
|
||||
// Red Hat, Inc. - initial API and implementation
|
||||
//
|
||||
|
||||
package v2
|
||||
|
||||
// Important: Run `make generate` at the root directory of the project
|
||||
// to regenerate `api/v2/zz_generatedxxx` code after modifying this file.
|
||||
|
||||
import (
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"k8s.io/apimachinery/pkg/api/resource"
|
||||
|
||||
imagepullerv1alpha1 "github.com/che-incubator/kubernetes-image-puller-operator/api/v1alpha1"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
)
|
||||
|
||||
// +k8s:openapi-gen=true
|
||||
// Desired configuration of Eclipse Che installation.
|
||||
type CheClusterSpec struct {
|
||||
// Development environment default configuration options.
|
||||
// +optional
|
||||
// +operator-sdk:csv:customresourcedefinitions:type=spec,order=1
|
||||
// +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Development environments"
|
||||
DevEnvironments CheClusterDevEnvironments `json:"devEnvironments"`
|
||||
// Che components configuration.
|
||||
// +optional
|
||||
// +operator-sdk:csv:customresourcedefinitions:type=spec,order=2
|
||||
// +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Components"
|
||||
Components CheClusterComponents `json:"components"`
|
||||
// Networking, Che authentication and TLS configuration.
|
||||
// +optional
|
||||
// +operator-sdk:csv:customresourcedefinitions:type=spec,order=3
|
||||
// +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Networking"
|
||||
Networking CheClusterSpecNetworking `json:"networking,omitempty"`
|
||||
// Configuration of an alternative registry that stores Che images.
|
||||
// +optional
|
||||
// +operator-sdk:csv:customresourcedefinitions:type=spec,order=4
|
||||
// +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Container registry"
|
||||
ContainerRegistry CheClusterContainerRegistry `json:"containerRegistry"`
|
||||
}
|
||||
|
||||
// Development environment configuration.
|
||||
// +k8s:openapi-gen=true
|
||||
type CheClusterDevEnvironments struct {
|
||||
// Workspaces persistent storage.
|
||||
// +optional
|
||||
Storage WorkspaceStorage `json:"storage"`
|
||||
// Default plug-ins applied to Dev Workspaces.
|
||||
// +optional
|
||||
DefaultPlugins []WorkspaceDefaultPlugins `json:"defaultPlugins,omitempty"`
|
||||
// The node selector limits the nodes that can run the workspace pods.
|
||||
// +optional
|
||||
NodeSelector map[string]string `json:"nodeSelector,omitempty"`
|
||||
// The pod tolerations of the workspace pods limit where the workspace pods can run.
|
||||
// +optional
|
||||
Tolerations []corev1.Toleration `json:"tolerations,omitempty"`
|
||||
// User's default namespace.
|
||||
// +optional
|
||||
DefaultNamespace DefaultNamespace `json:"defaultNamespace,omitempty"`
|
||||
// Trusted certificate settings.
|
||||
// +optional
|
||||
TrustedCerts TrustedCerts `json:"trustedCerts,omitempty"`
|
||||
}
|
||||
|
||||
// Che components configuration.
|
||||
// +k8s:openapi-gen=true
|
||||
type CheClusterComponents struct {
|
||||
// DevWorkspace operator configuration.
|
||||
// +optional
|
||||
DevWorkspace DevWorkspace `json:"devWorkspace"`
|
||||
// General configuration settings related to the Che server.
|
||||
// +optional
|
||||
CheServer CheServer `json:"cheServer"`
|
||||
// Configuration settings related to the plug-in registry used by the Che installation.
|
||||
// +optional
|
||||
PluginRegistry PluginRegistry `json:"pluginRegistry"`
|
||||
// Configuration settings related to the Devfile registry used by the Che installation.
|
||||
// +optional
|
||||
DevfileRegistry DevfileRegistry `json:"devfileRegistry"`
|
||||
// Configuration settings related to the database used by the Che installation.
|
||||
// +optional
|
||||
Database Database `json:"database"`
|
||||
// Configuration settings related to the Dashboard used by the Che installation.
|
||||
// +optional
|
||||
Dashboard Dashboard `json:"dashboard"`
|
||||
// Kubernetes Image Puller configuration.
|
||||
// +optional
|
||||
ImagePuller ImagePuller `json:"imagePuller"`
|
||||
// Che server metrics configuration.
|
||||
// +optional
|
||||
Metrics ServerMetrics `json:"metrics"`
|
||||
}
|
||||
|
||||
// Configuration settings related to the Networking used by the Che installation.
|
||||
// +k8s:openapi-gen=true
|
||||
type CheClusterSpecNetworking struct {
|
||||
// Defines labels which will be set to an ingress (a route for OpenShift platform).
|
||||
// +optional
|
||||
Labels map[string]string `json:"labels,omitempty"`
|
||||
// Defines annotations which will be set to an ingress (a route for OpenShift platform).
|
||||
// The defaults for kubernetes platforms are:
|
||||
// kubernetes.io/ingress.class: "nginx"
|
||||
// nginx.ingress.kubernetes.io/proxy-read-timeout: "3600",
|
||||
// nginx.ingress.kubernetes.io/proxy-connect-timeout: "3600",
|
||||
// nginx.ingress.kubernetes.io/ssl-redirect: "true"
|
||||
// +optional
|
||||
Annotations map[string]string `json:"annotations,omitempty"`
|
||||
// For an OpenShift cluster, the Operator uses the domain to generate a hostname for a route.
|
||||
// The generated hostname follows this pattern: che-<che-namespace>.<domain>. The <che-namespace> is the namespace where the CheCluster CRD is created.
|
||||
// In a conjunction with labels it creates a route, which is served by a non-default Ingress controller.
|
||||
// For Kubernetes cluster it contains a global ingress domain. This MUST be explicitly specified: there are no defaults.
|
||||
// +optional
|
||||
Domain string `json:"domain,omitempty"`
|
||||
// The public hostname of the installed Che server.
|
||||
// +optional
|
||||
Hostname string `json:"hostname,omitempty"`
|
||||
// The name of the secret used to set up Ingress TLS termination.
|
||||
// If the field is an empty string, the default cluster certificate is used.
|
||||
// The secret must have a `app.kubernetes.io/part-of=che.eclipse.org` label.
|
||||
// +optional
|
||||
TlsSecretName string `json:"tlsSecretName,omitempty"`
|
||||
// Authentication settings.
|
||||
// +optional
|
||||
Auth Auth `json:"auth"`
|
||||
}
|
||||
|
||||
// Container registry configuration.
|
||||
// +k8s:openapi-gen=true
|
||||
type CheClusterContainerRegistry struct {
|
||||
// An optional hostname or URL of an alternative container registry to pull images from.
|
||||
// This value overrides the container registry hostname defined in all the default container images involved in a Che deployment.
|
||||
// This is particularly useful for installing Che in a restricted environment.
|
||||
// +optional
|
||||
Hostname string `json:"hostname,omitempty"`
|
||||
// An optional repository name of an alternative registry to pull images from.
|
||||
// This value overrides the container registry organization defined in all the default container images involved in a Che deployment.
|
||||
// This is particularly useful for installing Eclipse Che in a restricted environment.
|
||||
// +optional
|
||||
Organization string `json:"organization,omitempty"`
|
||||
}
|
||||
|
||||
// +k8s:openapi-gen=true
|
||||
// General configuration settings related to the Che server.
|
||||
type CheServer struct {
|
||||
// Deployment override options.
|
||||
// +optional
|
||||
Deployment Deployment `json:"deployment,omitempty"`
|
||||
// The log level for the Che server: `INFO` or `DEBUG`.
|
||||
// +optional
|
||||
// +kubebuilder:default:="INFO"
|
||||
LogLevel string `json:"logLevel,omitempty"`
|
||||
// Enables the debug mode for Che server.
|
||||
// +optional
|
||||
Debug *bool `json:"debug,omitempty"`
|
||||
// ClusterRoles assigned to Che ServiceAccount.
|
||||
// The defaults roles are:
|
||||
// - `<che-namespace>-cheworkspaces-namespaces-clusterrole`
|
||||
// - `<che-namespace>-cheworkspaces-clusterrole`
|
||||
// - `<che-namespace>-cheworkspaces-devworkspace-clusterrole`
|
||||
// where the <che-namespace> is the namespace where the CheCluster CRD is created.
|
||||
// Each role must have a `app.kubernetes.io/part-of=che.eclipse.org` label.
|
||||
// The Che Operator must already have all permissions in these ClusterRoles to grant them.
|
||||
// +optional
|
||||
ClusterRoles []string `json:"clusterRoles,omitempty"`
|
||||
// Proxy server settings for Kubernetes cluster. No additional configuration is required for OpenShift cluster.
|
||||
// By specifying these settings for the OpenShift cluster, you override the OpenShift proxy configuration.
|
||||
// +optional
|
||||
Proxy Proxy `json:"proxy"`
|
||||
// A map of additional environment variables applied in the generated `che` ConfigMap to be used by the Che server,
|
||||
// in addition to the values already generated from other fields of the `CheCluster` custom resource (CR).
|
||||
// If the `extraProperties` fields contains a property normally generated in `che` ConfigMap from other CR fields,
|
||||
// the value defined in the `extraProperties` is used instead.
|
||||
// +optional
|
||||
ExtraProperties map[string]string `json:"extraProperties,omitempty"`
|
||||
}
|
||||
|
||||
// Configuration settings related to the Dashaboard used by the Che installation.
|
||||
// +k8s:openapi-gen=true
|
||||
type Dashboard struct {
|
||||
// Deployment override options.
|
||||
// +optional
|
||||
Deployment Deployment `json:"deployment,omitempty"`
|
||||
// Dashboard header message.
|
||||
// +optional
|
||||
HeaderMessage DashboardHeaderMessage `json:"HeaderMessage,omitempty"`
|
||||
}
|
||||
|
||||
// Configuration settings related to the plug-in registry used by the Che installation.
|
||||
// +k8s:openapi-gen=true
|
||||
type PluginRegistry struct {
|
||||
// Deployment override options.
|
||||
// +optional
|
||||
Deployment Deployment `json:"deployment,omitempty"`
|
||||
// Disables internal plug-in registry.
|
||||
// +optional
|
||||
DisableInternalRegistry bool `json:"disableInternalRegistry,omitempty"`
|
||||
// External plugin registries.
|
||||
// +optional
|
||||
ExternalPluginRegistries []ExternalPluginRegistry `json:"externalPluginRegistries,omitempty"`
|
||||
}
|
||||
|
||||
// Configuration settings related to the devfile Registry used by the Che installation.
|
||||
// +k8s:openapi-gen=true
|
||||
type DevfileRegistry struct {
|
||||
// Deployment override options.
|
||||
// +optional
|
||||
Deployment Deployment `json:"deployment,omitempty"`
|
||||
// Disables internal devfile registry.
|
||||
// +optional
|
||||
DisableInternalRegistry bool `json:"disableInternalRegistry,omitempty"`
|
||||
// External devfile registries serving sample ready-to-use devfiles.
|
||||
// +optional
|
||||
ExternalDevfileRegistries []ExternalDevfileRegistry `json:"externalDevfileRegistries,omitempty"`
|
||||
}
|
||||
|
||||
// Configuration settings related to the database used by the Che installation.
|
||||
// +k8s:openapi-gen=true
|
||||
type Database struct {
|
||||
// Instructs the Operator to deploy a dedicated database.
|
||||
// By default, a dedicated PostgreSQL database is deployed as part of the Che installation.
|
||||
// When `externalDb` is set as `true`, no dedicated database is deployed by the
|
||||
// Operator and you need to provide connection details to the external DB you want to use.
|
||||
// +optional
|
||||
ExternalDb bool `json:"externalDb"`
|
||||
// Deployment override options.
|
||||
// +optional
|
||||
Deployment Deployment `json:"deployment,omitempty"`
|
||||
// PostgreSQL database hostname that the Che server connects to.
|
||||
// Override this value only when using an external database. See field `externalDb`.
|
||||
// +kubebuilder:default:="postgres"
|
||||
// +optional
|
||||
PostgresHostName string `json:"postgresHostName,omitempty"`
|
||||
// PostgreSQL Database port the Che server connects to.
|
||||
// Override this value only when using an external database. See field `externalDb`.
|
||||
// +optional
|
||||
// +kubebuilder:default:="5432"
|
||||
PostgresPort string `json:"postgresPort,omitempty"`
|
||||
// PostgreSQL database name that the Che server uses to connect to the DB.
|
||||
// +optional
|
||||
// +kubebuilder:default:="dbche"
|
||||
PostgresDb string `json:"postgresDb,omitempty"`
|
||||
// The secret that contains PostgreSQL `user` and `password` that the Che server uses to connect to the DB.
|
||||
// The secret must have a `app.kubernetes.io/part-of=che.eclipse.org` label.
|
||||
// +optional
|
||||
// +kubebuilder:default:="postgres-credentials"
|
||||
CredentialsSecretName string `json:"credentialsSecretName,omitempty"`
|
||||
// PVC settings for PostgreSQL database.
|
||||
// +optional
|
||||
Pvc PVC `json:"pvc,omitempty"`
|
||||
}
|
||||
|
||||
// Che server metrics configuration
|
||||
type ServerMetrics struct {
|
||||
// Enables `metrics` for the Che server endpoint.
|
||||
// +kubebuilder:default:=true
|
||||
// +optional
|
||||
Enable bool `json:"enable"`
|
||||
}
|
||||
|
||||
// Configuration settings for installation and configuration of the Kubernetes Image Puller
|
||||
// See https://github.com/che-incubator/kubernetes-image-puller-operator
|
||||
// +k8s:openapi-gen=true
|
||||
type ImagePuller struct {
|
||||
// Install and configure the community supported Kubernetes Image Puller Operator. When you set the value to `true` without providing any specs,
|
||||
// it creates a default Kubernetes Image Puller object managed by the Operator.
|
||||
// When you set the value to `false`, the Kubernetes Image Puller object is deleted, and the Operator uninstalled,
|
||||
// regardless of whether a spec is provided.
|
||||
// If you leave the `spec.images` field empty, a set of recommended workspace-related images is automatically detected and
|
||||
// pre-pulled after installation.
|
||||
// Note that while this Operator and its behavior is community-supported, its payload may be commercially-supported
|
||||
// for pulling commercially-supported images.
|
||||
Enable bool `json:"enable"`
|
||||
// A Kubernetes Image Puller spec to configure the image puller in the CheCluster
|
||||
// +optional
|
||||
Spec imagepullerv1alpha1.KubernetesImagePullerSpec `json:"spec"`
|
||||
}
|
||||
|
||||
// Settings for installation and configuration of the DevWorkspace operator
|
||||
// See https://github.com/devfile/devworkspace-operator
|
||||
// +k8s:openapi-gen=true
|
||||
type DevWorkspace struct {
|
||||
// Deployment override options.
|
||||
// +optional
|
||||
Deployment Deployment `json:"deployment,omitempty"`
|
||||
// The maximum number of running workspaces per user.
|
||||
// +optional
|
||||
RunningLimit string `json:"runningLimit,omitempty"`
|
||||
}
|
||||
|
||||
type DefaultNamespace struct {
|
||||
// If you don't create user namespaces in advance, this field defines the Kubernetes namespace created when you start your first workspace.
|
||||
// You can use `<username>`, `<userid>` and `<workspaceid>` placeholders, such as che-workspace-<username>.
|
||||
// +optional
|
||||
Template string `json:"template,omitempty"`
|
||||
}
|
||||
|
||||
type DashboardHeaderMessage struct {
|
||||
// Instructs dashboard to show the message.
|
||||
// +optional
|
||||
Show bool `json:"show,omitempty"`
|
||||
// Warning message displayed on the user dashboard.
|
||||
// +optional
|
||||
Text string `json:"warning,text"`
|
||||
}
|
||||
|
||||
type TrustedCerts struct {
|
||||
// The ConfigMap contains certificates to propagate to the Che components and to provide a particular configuration for Git.
|
||||
// See the following page: https://www.eclipse.org/che/docs/stable/administration-guide/deploying-che-with-support-for-git-repositories-with-self-signed-certificates/
|
||||
// The ConfigMap must have a `app.kubernetes.io/part-of=che.eclipse.org` label.
|
||||
// +optional
|
||||
GitTrustedCertsConfigMapName string `json:"gitTrustedCertsConfigMapName,omitempty"`
|
||||
}
|
||||
|
||||
// Configuration settings related to the workspaces persistent storage.
|
||||
type WorkspaceStorage struct {
|
||||
// PVC settings.
|
||||
// +optional
|
||||
Pvc PVC `json:"pvc,omitempty"`
|
||||
// Persistent volume claim strategy for the Che server.
|
||||
// Only the `common` strategy is supported (all workspaces PVCs in one volume).
|
||||
// For details, see https://github.com/eclipse/che/issues/21185.
|
||||
// +optional
|
||||
// +kubebuilder:default:="common"
|
||||
PvcStrategy string `json:"pvcStrategy,omitempty"`
|
||||
}
|
||||
|
||||
type WorkspaceDefaultPlugins struct {
|
||||
// The editor id to specify default plug-ins for.
|
||||
Editor string `json:"editor,omitempty"`
|
||||
// Default plug-in URIs for the specified editor.
|
||||
Plugins []string `json:"plugins,omitempty"`
|
||||
}
|
||||
|
||||
// Authentication settings.
|
||||
type Auth struct {
|
||||
// Public URL of the Identity Provider server.
|
||||
IdentityProviderURL string `json:"identityProviderURL,omitempty"`
|
||||
// Name of the OpenShift `OAuthClient` resource used to set up identity federation on the OpenShift side.
|
||||
OAuthClientName string `json:"oAuthClientName,omitempty"`
|
||||
// Name of the secret set in the OpenShift `OAuthClient` resource used to set up identity federation on the OpenShift side.
|
||||
OAuthSecret string `json:"oAuthSecret,omitempty"`
|
||||
// Gateway settings.
|
||||
// +optional
|
||||
Gateway Gateway `json:"gateway,omitempty"`
|
||||
}
|
||||
|
||||
// Gateway settings.
|
||||
type Gateway struct {
|
||||
// Deployment override options.
|
||||
// Since gateway deployment consists of several containers, they must be distinguished in the configuration by their names:
|
||||
// - `gateway`
|
||||
// - `configbump`
|
||||
// - `oauth-proxy`
|
||||
// - `kube-rbac-proxy`
|
||||
// +optional
|
||||
Deployment Deployment `json:"deployment,omitempty"`
|
||||
// Gate configuration labels.
|
||||
// +optional
|
||||
ConfigLabels map[string]string `json:"configLabels,omitempty"`
|
||||
}
|
||||
|
||||
// Proxy server configuration.
|
||||
type Proxy struct {
|
||||
// URL (protocol+hostname) of the proxy server.
|
||||
// Use only when a proxy configuration is required. Operator respects OpenShift cluster-wide proxy configuration,
|
||||
// defining `url` in a custom resource leads to overriding the cluster proxy configuration.
|
||||
// See the following page: https://docs.openshift.com/container-platform/4.4/networking/enable-cluster-wide-proxy.html. See also the `proxyPort` and `nonProxyHosts` fields.
|
||||
// +optional
|
||||
Url string `json:"url,omitempty"`
|
||||
// Proxy server port.
|
||||
// +optional
|
||||
Port string `json:"port,omitempty"`
|
||||
// A list of hosts that can be reached directly, bypassing the proxy.
|
||||
// Specify wild card domain use the following form `.<DOMAIN>`, for example:
|
||||
// - localhost
|
||||
// - my.host.com
|
||||
// - 123.42.12.32
|
||||
// Use only when a proxy configuration is required. Operator respects OpenShift cluster-wide proxy configuration,
|
||||
// defining `nonProxyHosts` in a custom resource leads to merging non-proxy hosts lists from the cluster proxy configuration, and the ones defined in the custom resources.
|
||||
// See the following page: https://docs.openshift.com/container-platform/4.4/networking/enable-cluster-wide-proxy.html. See also the `proxyURL` fields.
|
||||
NonProxyHosts []string `json:"nonProxyHosts,omitempty"`
|
||||
// The secret name that contains `user` and `password` for a proxy server.
|
||||
// The secret must have a `app.kubernetes.io/part-of=che.eclipse.org` label.
|
||||
// +optional
|
||||
CredentialsSecretName string `json:"credentialsSecretName,omitempty"`
|
||||
}
|
||||
|
||||
// PersistentVolumeClaim custom settings.
|
||||
type PVC struct {
|
||||
// Persistent Volume Claim size. To update the claim size, Storage class that provisions it must support resize.
|
||||
// +optional
|
||||
ClaimSize string `json:"claimSize,omitempty"`
|
||||
// Storage class for the Persistent Volume Claim. When omitted or left blank, a default storage class is used.
|
||||
// +optional
|
||||
StorageClass string `json:"storageClass,omitempty"`
|
||||
}
|
||||
|
||||
// External devfile registries configuration.
|
||||
type ExternalDevfileRegistry struct {
|
||||
// The public UR of the devfile registry that serves sample ready-to-use devfiles.
|
||||
// +optional
|
||||
Url string `json:"url,omitempty"`
|
||||
}
|
||||
|
||||
// External plug-in registries configuration.
|
||||
type ExternalPluginRegistry struct {
|
||||
// Public URL of the plug-in registry.
|
||||
// +optional
|
||||
Url string `json:"url,omitempty"`
|
||||
}
|
||||
|
||||
// Deployment custom settings.
|
||||
type Deployment struct {
|
||||
// A single application container.
|
||||
// +optional
|
||||
Containers []Container `json:"container,omitempty"`
|
||||
// Security options the pod should run with.
|
||||
// +optional
|
||||
SecurityContext PodSecurityContext `json:"securityContext,omitempty"`
|
||||
}
|
||||
|
||||
// Container custom settings.
|
||||
type Container struct {
|
||||
// Container name.
|
||||
// +optional
|
||||
Name string `json:"name,omitempty"`
|
||||
// Container image. Omit it or leave it empty to use the default container image provided by the Operator.
|
||||
// +optional
|
||||
Image string `json:"image,omitempty"`
|
||||
// Image pull policy. Default value is `Always` for `nightly`, `next` or `latest` images, and `IfNotPresent` in other cases.
|
||||
// +optional
|
||||
ImagePullPolicy corev1.PullPolicy `json:"imagePullPolicy,omitempty"`
|
||||
// Compute resources required by this container.
|
||||
// +optional
|
||||
Resources ResourceRequirements `json:"resources,omitempty"`
|
||||
}
|
||||
|
||||
// Describes the compute resource requirements.
|
||||
type ResourceRequirements struct {
|
||||
// Request describes the minimum amount of compute resources required.
|
||||
// +optional
|
||||
Requests ResourceList `json:"request,omitempty"`
|
||||
// Limits describe the maximum amount of compute resources allowed.
|
||||
// +optional
|
||||
Limits ResourceList `json:"limits,omitempty"`
|
||||
}
|
||||
|
||||
// List of resources.
|
||||
type ResourceList struct {
|
||||
// Memory, in bytes. (500Gi = 500GiB = 500 * 1024 * 1024 * 1024)
|
||||
// +optional
|
||||
Memory resource.Quantity `json:"memory,omitempty"`
|
||||
// CPU, in cores. (500m = .5 cores)
|
||||
// +optional
|
||||
Cpu resource.Quantity `json:"cpu,omitempty"`
|
||||
}
|
||||
|
||||
// PodSecurityContext holds pod-level security attributes and common container settings.
|
||||
type PodSecurityContext struct {
|
||||
// The UID to run the entrypoint of the container process. The default value is `1724`.
|
||||
// +optional
|
||||
RunAsUser *int64 `json:"runAsUser,omitempty"`
|
||||
// A special supplemental group that applies to all containers in a pod. The default value is `1724`.
|
||||
// +optional
|
||||
FsGroup *int64 `json:"fsGroup,omitempty"`
|
||||
}
|
||||
|
||||
// GatewayPhase describes the different phases of the Che gateway lifecycle.
|
||||
type GatewayPhase string
|
||||
|
||||
const (
|
||||
GatewayPhaseInitializing = "Initializing"
|
||||
GatewayPhaseEstablished = "Established"
|
||||
GatewayPhaseInactive = "Inactive"
|
||||
)
|
||||
|
||||
// CheClusterPhase describes the different phases of the Che cluster lifecycle.
|
||||
type CheClusterPhase string
|
||||
|
||||
const (
|
||||
ClusterPhaseActive = "Active"
|
||||
ClusterPhaseInactive = "Inactive"
|
||||
ClusterPhasePendingDeletion = "PendingDeletion"
|
||||
RollingUpdate = "RollingUpdate"
|
||||
)
|
||||
|
||||
// CheClusterStatus defines the observed state of Che installation.
|
||||
type CheClusterStatus struct {
|
||||
// Specifies the current phase of the gateway deployment.
|
||||
// +optional
|
||||
// +operator-sdk:csv:customresourcedefinitions:type=status
|
||||
// +operator-sdk:csv:customresourcedefinitions:type=status,displayName="Gateway phase"
|
||||
// +operator-sdk:csv:customresourcedefinitions:type=status,xDescriptors="urn:alm:descriptor:text"
|
||||
GatewayPhase GatewayPhase `json:"gatewayPhase,omitempty"`
|
||||
// Current installed Che version.
|
||||
// +optional
|
||||
// +operator-sdk:csv:customresourcedefinitions:type=status
|
||||
// +operator-sdk:csv:customresourcedefinitions:type=status,displayName="displayName: Eclipse Che version"
|
||||
// +operator-sdk:csv:customresourcedefinitions:type=status,xDescriptors="urn:alm:descriptor:text"
|
||||
CheVersion string `json:"cheVersion"`
|
||||
// Public URL to the Che server.
|
||||
// +optional
|
||||
// +operator-sdk:csv:customresourcedefinitions:type=status
|
||||
// +operator-sdk:csv:customresourcedefinitions:type=status,displayName="Eclipse Che URL"
|
||||
// +operator-sdk:csv:customresourcedefinitions:type=status,xDescriptors="urn:alm:descriptor:org.w3:link"
|
||||
CheURL string `json:"cheURL"`
|
||||
// Specifies the current phase of the Che deployment.
|
||||
// +optional
|
||||
// +operator-sdk:csv:customresourcedefinitions:type=status
|
||||
// +operator-sdk:csv:customresourcedefinitions:type=status,displayName="ChePhase"
|
||||
// +operator-sdk:csv:customresourcedefinitions:type=status,xDescriptors="urn:alm:descriptor:text"
|
||||
ChePhase CheClusterPhase `json:"chePhase,omitempty"`
|
||||
// The public URL to the internal devfile registry.
|
||||
// +optional
|
||||
// +operator-sdk:csv:customresourcedefinitions:type=status
|
||||
// +operator-sdk:csv:customresourcedefinitions:type=status,displayName="Devfile registry URL"
|
||||
// +operator-sdk:csv:customresourcedefinitions:type=status,xDescriptors="urn:alm:descriptor:org.w3:link"
|
||||
DevfileRegistryURL string `json:"devfileRegistryURL"`
|
||||
// The public URL to the internal plug-in registry.
|
||||
// +optional
|
||||
// +operator-sdk:csv:customresourcedefinitions:type=status
|
||||
// +operator-sdk:csv:customresourcedefinitions:type=status,displayName="Plugin registry URL"
|
||||
// +operator-sdk:csv:customresourcedefinitions:type=status,xDescriptors="urn:alm:descriptor:org.w3:link"
|
||||
PluginRegistryURL string `json:"pluginRegistryURL"`
|
||||
// A human readable message indicating details about why the Che deployment is in current phase.
|
||||
// +optional
|
||||
// +operator-sdk:csv:customresourcedefinitions:type=status
|
||||
// +operator-sdk:csv:customresourcedefinitions:type=status,displayName="Message"
|
||||
// +operator-sdk:csv:customresourcedefinitions:type=status,xDescriptors="urn:alm:descriptor:text"
|
||||
Message string `json:"message,omitempty"`
|
||||
// A brief CamelCase message indicating details about why the Che deployment is in current phase.
|
||||
// +optional
|
||||
// +operator-sdk:csv:customresourcedefinitions:type=status
|
||||
// +operator-sdk:csv:customresourcedefinitions:type=status,displayName="Reason"
|
||||
// +operator-sdk:csv:customresourcedefinitions:type=status,xDescriptors="urn:alm:descriptor:text"
|
||||
Reason string `json:"reason,omitempty"`
|
||||
// The PostgreSQL version of the image in use.
|
||||
// +optional
|
||||
// +operator-sdk:csv:customresourcedefinitions:type=status
|
||||
// +operator-sdk:csv:customresourcedefinitions:type=status,displayName="PostgreSQL version"
|
||||
// +operator-sdk:csv:customresourcedefinitions:type=status,xDescriptors="urn:alm:descriptor:text"
|
||||
PostgresVersion string `json:"postgresVersion,omitempty"`
|
||||
// The resolved workspace base domain. This is either the copy of the explicitly defined property of the
|
||||
// same name in the spec or, if it is undefined in the spec and we're running on OpenShift, the automatically
|
||||
// resolved basedomain for routes.
|
||||
// +optional
|
||||
// +operator-sdk:csv:customresourcedefinitions:type=status
|
||||
// +operator-sdk:csv:customresourcedefinitions:type=status,displayName="Workspace base domain"
|
||||
// +operator-sdk:csv:customresourcedefinitions:type=status,xDescriptors="urn:alm:descriptor:text"
|
||||
WorkspaceBaseDomain string `json:"workspaceBaseDomain,omitempty"`
|
||||
}
|
||||
|
||||
// The `CheCluster` custom resource allows defining and managing Eclipse Che server installation.
|
||||
// Based on these settings, the Operator automatically creates and maintains several ConfigMaps:
|
||||
// `che`, `plugin-registry`, `devfile-registry` that will contain the appropriate environment variables
|
||||
// of the various components of the installation. These generated ConfigMaps must NOT be updated manually.
|
||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||
// +kubebuilder:object:root=true
|
||||
// +kubebuilder:subresource:status
|
||||
// +k8s:openapi-gen=true
|
||||
// +operator-sdk:csv:customresourcedefinitions:displayName="Eclipse Che instance Specification"
|
||||
// +operator-sdk:csv:customresourcedefinitions:order=0
|
||||
// +operator-sdk:csv:customresourcedefinitions:resources={{Ingress,v1},{Route,v1},{ConfigMap,v1},{Service,v1},{Secret,v1},{Deployment,apps/v1},{Role,v1},{RoleBinding,v1},{ClusterRole,v1},{ClusterRoleBinding,v1}}
|
||||
// +kubebuilder:storageversion
|
||||
type CheCluster struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
metav1.ObjectMeta `json:"metadata,omitempty"`
|
||||
|
||||
// Desired configuration of Eclipse Che installation.
|
||||
Spec CheClusterSpec `json:"spec,omitempty"`
|
||||
|
||||
// CheClusterStatus defines the observed state of Che installation.
|
||||
Status CheClusterStatus `json:"status,omitempty"`
|
||||
}
|
||||
|
||||
//+kubebuilder:object:root=true
|
||||
// The CheClusterList contains a list of CheClusters.
|
||||
type CheClusterList struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
metav1.ListMeta `json:"metadata,omitempty"`
|
||||
Items []CheCluster `json:"items"`
|
||||
}
|
||||
|
||||
func init() {
|
||||
SchemeBuilder.Register(&CheCluster{}, &CheClusterList{})
|
||||
}
|
||||
|
||||
func (c *CheCluster) IsAirGapMode() bool {
|
||||
return c.Spec.ContainerRegistry.Hostname != "" || c.Spec.ContainerRegistry.Organization != ""
|
||||
}
|
||||
|
||||
func (c *CheCluster) IsImagePullerSpecEmpty() bool {
|
||||
return c.Spec.Components.ImagePuller.Spec == (imagepullerv1alpha1.KubernetesImagePullerSpec{})
|
||||
}
|
||||
|
||||
func (c *CheCluster) IsImagePullerImagesEmpty() bool {
|
||||
return len(c.Spec.Components.ImagePuller.Spec.Images) == 0
|
||||
}
|
||||
|
||||
func (c *CheCluster) GetCheHost() string {
|
||||
if c.Status.CheURL != "" {
|
||||
return strings.TrimPrefix(c.Status.CheURL, "https://")
|
||||
}
|
||||
|
||||
return c.Spec.Networking.Hostname
|
||||
}
|
||||
|
||||
func (c *CheCluster) GetDefaultNamespace() string {
|
||||
if c.Spec.Components.CheServer.ExtraProperties != nil {
|
||||
k8sDefaultNamespace := c.Spec.Components.CheServer.ExtraProperties["CHE_INFRA_KUBERNETES_NAMESPACE_DEFAULT"]
|
||||
if k8sDefaultNamespace != "" {
|
||||
return k8sDefaultNamespace
|
||||
}
|
||||
}
|
||||
|
||||
if c.Spec.DevEnvironments.DefaultNamespace.Template != "" {
|
||||
return c.Spec.DevEnvironments.DefaultNamespace.Template
|
||||
}
|
||||
|
||||
return "<username>-" + os.Getenv("CHE_FLAVOR")
|
||||
}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
//
|
||||
// Copyright (c) 2019-2022 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 v2
|
||||
|
||||
import (
|
||||
ctrl "sigs.k8s.io/controller-runtime"
|
||||
logf "sigs.k8s.io/controller-runtime/pkg/log"
|
||||
)
|
||||
|
||||
// log is for logging in this package.
|
||||
var checlusterlog = logf.Log.WithName("checluster-resource")
|
||||
|
||||
func (r *CheCluster) SetupWebhookWithManager(mgr ctrl.Manager) error {
|
||||
return ctrl.NewWebhookManagedBy(mgr).
|
||||
For(r).
|
||||
Complete()
|
||||
}
|
||||
|
||||
// EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN!
|
||||
|
|
@ -10,21 +10,10 @@
|
|||
// Red Hat, Inc. - initial API and implementation
|
||||
//
|
||||
|
||||
// NOTE: Boilerplate only. Ignore this file.
|
||||
|
||||
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
// NOTE THAT THIS IS CURRENTLY INTENTIONALLY NOT PART OF THE GENERATED API
|
||||
//
|
||||
// (the generator comments are switched off by using a '\' instead of a '+')
|
||||
//
|
||||
// This is so that we can start using this spec in the code before we are
|
||||
// actually ready to start deploying it in the cluster.
|
||||
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
|
||||
// Package v2alpha1 contains API Schema definitions for the org v2alpha1 API group
|
||||
// Package v2 contains API Schema definitions for the org v2 API group
|
||||
//+kubebuilder:object:generate=true
|
||||
//+groupName=org.eclipse.che
|
||||
package v2alpha1
|
||||
package v2
|
||||
|
||||
import (
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
|
|
@ -33,7 +22,7 @@ import (
|
|||
|
||||
var (
|
||||
// GroupVersion is group version used to register these objects
|
||||
GroupVersion = schema.GroupVersion{Group: "org.eclipse.che", Version: "v2alpha1"}
|
||||
GroupVersion = schema.GroupVersion{Group: "org.eclipse.che", Version: "v2"}
|
||||
|
||||
// SchemeBuilder is used to add go types to the GroupVersionKind scheme
|
||||
SchemeBuilder = &scheme.Builder{GroupVersion: GroupVersion}
|
||||
|
|
@ -0,0 +1,662 @@
|
|||
// +build !ignore_autogenerated
|
||||
|
||||
//
|
||||
// Copyright (c) 2019-2021 Red Hat, Inc.
|
||||
// This program and the accompanying materials are made
|
||||
// available under the terms of the Eclipse Public License 2.0
|
||||
// which is available at https://www.eclipse.org/legal/epl-2.0/
|
||||
//
|
||||
// SPDX-License-Identifier: EPL-2.0
|
||||
//
|
||||
// Contributors:
|
||||
// Red Hat, Inc. - initial API and implementation
|
||||
//
|
||||
|
||||
// Code generated by controller-gen. DO NOT EDIT.
|
||||
|
||||
package v2
|
||||
|
||||
import (
|
||||
v1 "k8s.io/api/core/v1"
|
||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||
)
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *Auth) DeepCopyInto(out *Auth) {
|
||||
*out = *in
|
||||
in.Gateway.DeepCopyInto(&out.Gateway)
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Auth.
|
||||
func (in *Auth) DeepCopy() *Auth {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(Auth)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *CheCluster) DeepCopyInto(out *CheCluster) {
|
||||
*out = *in
|
||||
out.TypeMeta = in.TypeMeta
|
||||
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
|
||||
in.Spec.DeepCopyInto(&out.Spec)
|
||||
out.Status = in.Status
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CheCluster.
|
||||
func (in *CheCluster) DeepCopy() *CheCluster {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(CheCluster)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||
func (in *CheCluster) DeepCopyObject() runtime.Object {
|
||||
if c := in.DeepCopy(); c != nil {
|
||||
return c
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *CheClusterComponents) DeepCopyInto(out *CheClusterComponents) {
|
||||
*out = *in
|
||||
in.DevWorkspace.DeepCopyInto(&out.DevWorkspace)
|
||||
in.CheServer.DeepCopyInto(&out.CheServer)
|
||||
in.PluginRegistry.DeepCopyInto(&out.PluginRegistry)
|
||||
in.DevfileRegistry.DeepCopyInto(&out.DevfileRegistry)
|
||||
in.Database.DeepCopyInto(&out.Database)
|
||||
in.Dashboard.DeepCopyInto(&out.Dashboard)
|
||||
out.ImagePuller = in.ImagePuller
|
||||
out.Metrics = in.Metrics
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CheClusterComponents.
|
||||
func (in *CheClusterComponents) DeepCopy() *CheClusterComponents {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(CheClusterComponents)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *CheClusterContainerRegistry) DeepCopyInto(out *CheClusterContainerRegistry) {
|
||||
*out = *in
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CheClusterContainerRegistry.
|
||||
func (in *CheClusterContainerRegistry) DeepCopy() *CheClusterContainerRegistry {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(CheClusterContainerRegistry)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *CheClusterDevEnvironments) DeepCopyInto(out *CheClusterDevEnvironments) {
|
||||
*out = *in
|
||||
out.Storage = in.Storage
|
||||
if in.DefaultPlugins != nil {
|
||||
in, out := &in.DefaultPlugins, &out.DefaultPlugins
|
||||
*out = make([]WorkspaceDefaultPlugins, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
if in.NodeSelector != nil {
|
||||
in, out := &in.NodeSelector, &out.NodeSelector
|
||||
*out = make(map[string]string, len(*in))
|
||||
for key, val := range *in {
|
||||
(*out)[key] = val
|
||||
}
|
||||
}
|
||||
if in.Tolerations != nil {
|
||||
in, out := &in.Tolerations, &out.Tolerations
|
||||
*out = make([]v1.Toleration, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
out.DefaultNamespace = in.DefaultNamespace
|
||||
out.TrustedCerts = in.TrustedCerts
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CheClusterDevEnvironments.
|
||||
func (in *CheClusterDevEnvironments) DeepCopy() *CheClusterDevEnvironments {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(CheClusterDevEnvironments)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *CheClusterList) DeepCopyInto(out *CheClusterList) {
|
||||
*out = *in
|
||||
out.TypeMeta = in.TypeMeta
|
||||
in.ListMeta.DeepCopyInto(&out.ListMeta)
|
||||
if in.Items != nil {
|
||||
in, out := &in.Items, &out.Items
|
||||
*out = make([]CheCluster, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CheClusterList.
|
||||
func (in *CheClusterList) DeepCopy() *CheClusterList {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(CheClusterList)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||
func (in *CheClusterList) DeepCopyObject() runtime.Object {
|
||||
if c := in.DeepCopy(); c != nil {
|
||||
return c
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *CheClusterSpec) DeepCopyInto(out *CheClusterSpec) {
|
||||
*out = *in
|
||||
in.DevEnvironments.DeepCopyInto(&out.DevEnvironments)
|
||||
in.Components.DeepCopyInto(&out.Components)
|
||||
in.Networking.DeepCopyInto(&out.Networking)
|
||||
out.ContainerRegistry = in.ContainerRegistry
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CheClusterSpec.
|
||||
func (in *CheClusterSpec) DeepCopy() *CheClusterSpec {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(CheClusterSpec)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *CheClusterSpecNetworking) DeepCopyInto(out *CheClusterSpecNetworking) {
|
||||
*out = *in
|
||||
if in.Labels != nil {
|
||||
in, out := &in.Labels, &out.Labels
|
||||
*out = make(map[string]string, len(*in))
|
||||
for key, val := range *in {
|
||||
(*out)[key] = val
|
||||
}
|
||||
}
|
||||
if in.Annotations != nil {
|
||||
in, out := &in.Annotations, &out.Annotations
|
||||
*out = make(map[string]string, len(*in))
|
||||
for key, val := range *in {
|
||||
(*out)[key] = val
|
||||
}
|
||||
}
|
||||
in.Auth.DeepCopyInto(&out.Auth)
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CheClusterSpecNetworking.
|
||||
func (in *CheClusterSpecNetworking) DeepCopy() *CheClusterSpecNetworking {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(CheClusterSpecNetworking)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *CheClusterStatus) DeepCopyInto(out *CheClusterStatus) {
|
||||
*out = *in
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CheClusterStatus.
|
||||
func (in *CheClusterStatus) DeepCopy() *CheClusterStatus {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(CheClusterStatus)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *CheServer) DeepCopyInto(out *CheServer) {
|
||||
*out = *in
|
||||
in.Deployment.DeepCopyInto(&out.Deployment)
|
||||
if in.Debug != nil {
|
||||
in, out := &in.Debug, &out.Debug
|
||||
*out = new(bool)
|
||||
**out = **in
|
||||
}
|
||||
if in.ClusterRoles != nil {
|
||||
in, out := &in.ClusterRoles, &out.ClusterRoles
|
||||
*out = make([]string, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
in.Proxy.DeepCopyInto(&out.Proxy)
|
||||
if in.ExtraProperties != nil {
|
||||
in, out := &in.ExtraProperties, &out.ExtraProperties
|
||||
*out = make(map[string]string, len(*in))
|
||||
for key, val := range *in {
|
||||
(*out)[key] = val
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CheServer.
|
||||
func (in *CheServer) DeepCopy() *CheServer {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(CheServer)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *Container) DeepCopyInto(out *Container) {
|
||||
*out = *in
|
||||
in.Resources.DeepCopyInto(&out.Resources)
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Container.
|
||||
func (in *Container) DeepCopy() *Container {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(Container)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *Dashboard) DeepCopyInto(out *Dashboard) {
|
||||
*out = *in
|
||||
in.Deployment.DeepCopyInto(&out.Deployment)
|
||||
out.HeaderMessage = in.HeaderMessage
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Dashboard.
|
||||
func (in *Dashboard) DeepCopy() *Dashboard {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(Dashboard)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *DashboardHeaderMessage) DeepCopyInto(out *DashboardHeaderMessage) {
|
||||
*out = *in
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DashboardHeaderMessage.
|
||||
func (in *DashboardHeaderMessage) DeepCopy() *DashboardHeaderMessage {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(DashboardHeaderMessage)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *Database) DeepCopyInto(out *Database) {
|
||||
*out = *in
|
||||
in.Deployment.DeepCopyInto(&out.Deployment)
|
||||
out.Pvc = in.Pvc
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Database.
|
||||
func (in *Database) DeepCopy() *Database {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(Database)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *DefaultNamespace) DeepCopyInto(out *DefaultNamespace) {
|
||||
*out = *in
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DefaultNamespace.
|
||||
func (in *DefaultNamespace) DeepCopy() *DefaultNamespace {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(DefaultNamespace)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *Deployment) DeepCopyInto(out *Deployment) {
|
||||
*out = *in
|
||||
if in.Containers != nil {
|
||||
in, out := &in.Containers, &out.Containers
|
||||
*out = make([]Container, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
in.SecurityContext.DeepCopyInto(&out.SecurityContext)
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Deployment.
|
||||
func (in *Deployment) DeepCopy() *Deployment {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(Deployment)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *DevWorkspace) DeepCopyInto(out *DevWorkspace) {
|
||||
*out = *in
|
||||
in.Deployment.DeepCopyInto(&out.Deployment)
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DevWorkspace.
|
||||
func (in *DevWorkspace) DeepCopy() *DevWorkspace {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(DevWorkspace)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *DevfileRegistry) DeepCopyInto(out *DevfileRegistry) {
|
||||
*out = *in
|
||||
in.Deployment.DeepCopyInto(&out.Deployment)
|
||||
if in.ExternalDevfileRegistries != nil {
|
||||
in, out := &in.ExternalDevfileRegistries, &out.ExternalDevfileRegistries
|
||||
*out = make([]ExternalDevfileRegistry, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DevfileRegistry.
|
||||
func (in *DevfileRegistry) DeepCopy() *DevfileRegistry {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(DevfileRegistry)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *ExternalDevfileRegistry) DeepCopyInto(out *ExternalDevfileRegistry) {
|
||||
*out = *in
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExternalDevfileRegistry.
|
||||
func (in *ExternalDevfileRegistry) DeepCopy() *ExternalDevfileRegistry {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(ExternalDevfileRegistry)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *ExternalPluginRegistry) DeepCopyInto(out *ExternalPluginRegistry) {
|
||||
*out = *in
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExternalPluginRegistry.
|
||||
func (in *ExternalPluginRegistry) DeepCopy() *ExternalPluginRegistry {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(ExternalPluginRegistry)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *Gateway) DeepCopyInto(out *Gateway) {
|
||||
*out = *in
|
||||
in.Deployment.DeepCopyInto(&out.Deployment)
|
||||
if in.ConfigLabels != nil {
|
||||
in, out := &in.ConfigLabels, &out.ConfigLabels
|
||||
*out = make(map[string]string, len(*in))
|
||||
for key, val := range *in {
|
||||
(*out)[key] = val
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Gateway.
|
||||
func (in *Gateway) DeepCopy() *Gateway {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(Gateway)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *ImagePuller) DeepCopyInto(out *ImagePuller) {
|
||||
*out = *in
|
||||
out.Spec = in.Spec
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ImagePuller.
|
||||
func (in *ImagePuller) DeepCopy() *ImagePuller {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(ImagePuller)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *PVC) DeepCopyInto(out *PVC) {
|
||||
*out = *in
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PVC.
|
||||
func (in *PVC) DeepCopy() *PVC {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(PVC)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *PluginRegistry) DeepCopyInto(out *PluginRegistry) {
|
||||
*out = *in
|
||||
in.Deployment.DeepCopyInto(&out.Deployment)
|
||||
if in.ExternalPluginRegistries != nil {
|
||||
in, out := &in.ExternalPluginRegistries, &out.ExternalPluginRegistries
|
||||
*out = make([]ExternalPluginRegistry, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PluginRegistry.
|
||||
func (in *PluginRegistry) DeepCopy() *PluginRegistry {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(PluginRegistry)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *PodSecurityContext) DeepCopyInto(out *PodSecurityContext) {
|
||||
*out = *in
|
||||
if in.RunAsUser != nil {
|
||||
in, out := &in.RunAsUser, &out.RunAsUser
|
||||
*out = new(int64)
|
||||
**out = **in
|
||||
}
|
||||
if in.FsGroup != nil {
|
||||
in, out := &in.FsGroup, &out.FsGroup
|
||||
*out = new(int64)
|
||||
**out = **in
|
||||
}
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PodSecurityContext.
|
||||
func (in *PodSecurityContext) DeepCopy() *PodSecurityContext {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(PodSecurityContext)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *Proxy) DeepCopyInto(out *Proxy) {
|
||||
*out = *in
|
||||
if in.NonProxyHosts != nil {
|
||||
in, out := &in.NonProxyHosts, &out.NonProxyHosts
|
||||
*out = make([]string, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Proxy.
|
||||
func (in *Proxy) DeepCopy() *Proxy {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(Proxy)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *ResourceList) DeepCopyInto(out *ResourceList) {
|
||||
*out = *in
|
||||
out.Memory = in.Memory.DeepCopy()
|
||||
out.Cpu = in.Cpu.DeepCopy()
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ResourceList.
|
||||
func (in *ResourceList) DeepCopy() *ResourceList {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(ResourceList)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *ResourceRequirements) DeepCopyInto(out *ResourceRequirements) {
|
||||
*out = *in
|
||||
in.Requests.DeepCopyInto(&out.Requests)
|
||||
in.Limits.DeepCopyInto(&out.Limits)
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ResourceRequirements.
|
||||
func (in *ResourceRequirements) DeepCopy() *ResourceRequirements {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(ResourceRequirements)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *ServerMetrics) DeepCopyInto(out *ServerMetrics) {
|
||||
*out = *in
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServerMetrics.
|
||||
func (in *ServerMetrics) DeepCopy() *ServerMetrics {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(ServerMetrics)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *TrustedCerts) DeepCopyInto(out *TrustedCerts) {
|
||||
*out = *in
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TrustedCerts.
|
||||
func (in *TrustedCerts) DeepCopy() *TrustedCerts {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(TrustedCerts)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *WorkspaceDefaultPlugins) DeepCopyInto(out *WorkspaceDefaultPlugins) {
|
||||
*out = *in
|
||||
if in.Plugins != nil {
|
||||
in, out := &in.Plugins, &out.Plugins
|
||||
*out = make([]string, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WorkspaceDefaultPlugins.
|
||||
func (in *WorkspaceDefaultPlugins) DeepCopy() *WorkspaceDefaultPlugins {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(WorkspaceDefaultPlugins)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *WorkspaceStorage) DeepCopyInto(out *WorkspaceStorage) {
|
||||
*out = *in
|
||||
out.Pvc = in.Pvc
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WorkspaceStorage.
|
||||
func (in *WorkspaceStorage) DeepCopy() *WorkspaceStorage {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(WorkspaceStorage)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
|
@ -1,213 +0,0 @@
|
|||
//
|
||||
// Copyright (c) 2019-2021 Red Hat, Inc.
|
||||
// This program and the accompanying materials are made
|
||||
// available under the terms of the Eclipse Public License 2.0
|
||||
// which is available at https://www.eclipse.org/legal/epl-2.0/
|
||||
//
|
||||
// SPDX-License-Identifier: EPL-2.0
|
||||
//
|
||||
// Contributors:
|
||||
// Red Hat, Inc. - initial API and implementation
|
||||
//
|
||||
|
||||
package v2alpha1
|
||||
|
||||
import (
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
)
|
||||
|
||||
// CheClusterSpec holds the configuration of the Che controller.
|
||||
// +k8s:openapi-gen=true
|
||||
type CheClusterSpec struct {
|
||||
// If false, Che is disabled and does not resolve the devworkspaces with the che routingClass.
|
||||
Enabled *bool `json:"enabled,omitempty"`
|
||||
|
||||
// Workspaces contains configuration affecting the behavior of workspaces.
|
||||
Workspaces Workspaces `json:"workspaces"`
|
||||
|
||||
// Gateway contains the configuration of the gateway used for workspace endpoint routing.
|
||||
Gateway CheGatewaySpec `json:"gateway,omitempty"`
|
||||
|
||||
// K8s contains the configuration specific only to Kubernetes
|
||||
K8s CheClusterSpecK8s `json:"k8s,omitempty"`
|
||||
}
|
||||
|
||||
type Workspaces struct {
|
||||
// Configuration of the workspace endpoints that are exposed on separate domains, as opposed to the subpaths
|
||||
// of the gateway.
|
||||
DomainEndpoints DomainEndpoints `json:"domainEndpoints,omitempty"`
|
||||
|
||||
// The node selector that limits the nodes that can run the workspace pods.
|
||||
PodNodeSelector map[string]string `json:"podNodeSelector,omitempty"`
|
||||
|
||||
// The pod tolerations put on the workspace pods to limit where the workspace pods can run.
|
||||
PodTolerations []corev1.Toleration `json:"podTolerations,omitempty"`
|
||||
}
|
||||
|
||||
type DomainEndpoints struct {
|
||||
// The workspace endpoints that need to be deployed on a subdomain will be deployed on subdomains of this base domain.
|
||||
// This is mandatory on Kubernetes. On OpenShift, an attempt is made to automatically figure out the base domain of
|
||||
// the routes. The resolved value of this property is written to the status.
|
||||
BaseDomain string `json:"baseDomain,omitempty"`
|
||||
|
||||
// Name of a secret that will be used to setup ingress/route TLS certificate for the workspace endpoints. The endpoints
|
||||
// will be on randomly named subdomains of the `BaseDomain` and therefore the TLS certificate should a wildcard certificate.
|
||||
//
|
||||
// When the field is empty string, the endpoints are served over unecrypted HTTP. This might be OK because the workspace endpoints
|
||||
// generally only expose applications in debugging sessions during development.
|
||||
//
|
||||
// The secret is assumed to exist in the same namespace as the CheCluster CR is copied to the namespace of the devworkspace on
|
||||
// devworkspace start (so that the ingresses on Kubernetes can reference it).
|
||||
//
|
||||
// The secret has to be of type "tls".
|
||||
//
|
||||
// +optional
|
||||
TlsSecretName string `json:"tlsSecretName,omitempty"`
|
||||
}
|
||||
|
||||
type CheGatewaySpec struct {
|
||||
// Enabled enables or disables routing of the url rewrite supporting devworkspace endpoints
|
||||
// through a common gateway (the hostname of which is defined by the Host).
|
||||
//
|
||||
// Default value is "true" meaning that the gateway is enabled.
|
||||
//
|
||||
// If set to true (i.e. the gateway is enabled), endpoints marked using the "urlRewriteSupported" attribute
|
||||
// are exposed on unique subpaths of the Host, while the rest of the devworkspace endpoints are exposed
|
||||
// on subdomains of the Host.
|
||||
//
|
||||
// If set to false (i.e. the gateway is disabled), all endpoints are deployed on subdomains of
|
||||
// the Host.
|
||||
Enabled *bool `json:"enabled,omitempty"`
|
||||
|
||||
// Host is the full host name used to expose devworkspace endpoints that support url rewriting reverse proxy.
|
||||
// See the gateway.enabled attribute for a more detailed description of where and how are devworkspace endpoints
|
||||
// exposed in various configurations.
|
||||
//
|
||||
// This attribute is mandatory on Kubernetes, optional on OpenShift.
|
||||
Host string `json:"host,omitempty"`
|
||||
|
||||
// Name of a secret that will be used to setup ingress/route TLS certificate for the gateway host.
|
||||
// When the field is empty string, the default cluster certificate will be used.
|
||||
// The secret is assumed to exist in the same namespace as the CheCluster CR.
|
||||
//
|
||||
// The secret has to be of type "tls".
|
||||
//
|
||||
// +optional
|
||||
TlsSecretName string `json:"tlsSecretName,omitempty"`
|
||||
|
||||
// Image is the docker image to use for the Che gateway. This is only used if Enabled is true.
|
||||
// If not defined in the CR, it is taken from
|
||||
// the `RELATED_IMAGE_gateway` environment variable of the operator deployment/pod. If not defined there,
|
||||
// it defaults to a hardcoded value.
|
||||
Image string `json:"image,omitempty"`
|
||||
|
||||
// ConfigurerImage is the docker image to use for the sidecar of the Che gateway that is
|
||||
// used to configure it. This is only used when Enabled is true. If not defined in the CR,
|
||||
// it is taken from the `RELATED_IMAGE_gateway_configurer` environment variable of the operator
|
||||
// deployment/pod. If not defined there, it defaults to a hardcoded value.
|
||||
ConfigurerImage string `json:"configurerImage,omitempty"`
|
||||
|
||||
// ConfigLabels are labels that are put on the gateway configuration configmaps so that they are picked up
|
||||
// by the gateway configurer. The default value are labels: app=che,component=che-gateway-config
|
||||
// +optional
|
||||
ConfigLabels labels.Set `json:"configLabels,omitempty"`
|
||||
}
|
||||
|
||||
// CheClusterSpecK8s contains the configuration options specific to Kubernetes only.
|
||||
type CheClusterSpecK8s struct {
|
||||
// IngressAnnotations are the annotations to be put on the generated ingresses. This can be used to
|
||||
// configure the ingress class and the ingress-controller-specific behavior for both the gateway
|
||||
// and the ingresses created to expose the Devworkspace component endpoints.
|
||||
// When not specified, this defaults to:
|
||||
//
|
||||
// kubernetes.io/ingress.class: "nginx"
|
||||
// nginx.ingress.kubernetes.io/proxy-read-timeout: "3600",
|
||||
// nginx.ingress.kubernetes.io/proxy-connect-timeout: "3600",
|
||||
// nginx.ingress.kubernetes.io/ssl-redirect: "true"
|
||||
//
|
||||
// +optional
|
||||
IngressAnnotations map[string]string `json:"ingressAnnotations,omitempty"`
|
||||
}
|
||||
|
||||
// GatewayPhase describes the different phases of the Che gateway lifecycle
|
||||
type GatewayPhase string
|
||||
|
||||
const (
|
||||
GatewayPhaseInitializing = "Initializing"
|
||||
GatewayPhaseEstablished = "Established"
|
||||
GatewayPhaseInactive = "Inactive"
|
||||
)
|
||||
|
||||
// ClusterPhase describes the different phases of the Che cluster lifecycle
|
||||
type ClusterPhase string
|
||||
|
||||
const (
|
||||
ClusterPhaseActive = "Active"
|
||||
ClusterPhaseInactive = "Inactive"
|
||||
ClusterPhasePendingDeletion = "PendingDeletion"
|
||||
)
|
||||
|
||||
// CheClusterStatusV2Alpha1 contains the status of the CheCluster object
|
||||
// +k8s:openapi-gen=true
|
||||
type CheClusterStatusV2Alpha1 struct {
|
||||
// GatewayPhase specifies the phase in which the gateway deployment currently is.
|
||||
// If the gateway is disabled, the phase is "Inactive".
|
||||
GatewayPhase GatewayPhase `json:"gatewayPhase,omitempty"`
|
||||
|
||||
// GatewayHost is the resolved host of the ingress/route. This is equal to the Host in the spec
|
||||
// on Kubernetes but contains the actual host name of the route if Host is unspecified on OpenShift.
|
||||
GatewayHost string `json:"gatewayHost,omitempty"`
|
||||
|
||||
// Phase is the phase in which the Che cluster as a whole finds itself in.
|
||||
Phase ClusterPhase `json:"phase,omitempty"`
|
||||
|
||||
// A brief CamelCase message indicating details about why the Che cluster is in this state.
|
||||
Reason string `json:"reason,omitempty"`
|
||||
|
||||
// Message contains further human-readable info for why the Che cluster is in the phase it currently is.
|
||||
Message string `json:"message,omitempty"`
|
||||
|
||||
// The resolved workspace base domain. This is either the copy of the explicitly defined property of the
|
||||
// same name in the spec or, if it is undefined in the spec and we're running on OpenShift, the automatically
|
||||
// resolved basedomain for routes.
|
||||
WorkspaceBaseDomain string `json:"workspaceBaseDomain,omitempty"`
|
||||
}
|
||||
|
||||
// CheCluster is the configuration of the CheCluster layer of Devworkspace.
|
||||
// +k8s:openapi-gen=true
|
||||
// +kubebuilder:subresource:status
|
||||
// +kubebuilder:resource:path=checlusters,scope=Namespaced
|
||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||
// +operator-sdk:csv:customresourcedefinitions:displayName="Eclipse Che Cluster"
|
||||
type CheCluster struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
metav1.ObjectMeta `json:"metadata,omitempty"`
|
||||
|
||||
Spec CheClusterSpec `json:"spec,omitempty"`
|
||||
Status CheClusterStatusV2Alpha1 `json:"status,omitempty"`
|
||||
}
|
||||
|
||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||
|
||||
// CheClusterList is the list type for CheCluster
|
||||
type CheClusterList struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
metav1.ListMeta `json:"metadata,omitempty"`
|
||||
Items []CheCluster `json:"items"`
|
||||
}
|
||||
|
||||
func init() {
|
||||
SchemeBuilder.Register(&CheCluster{}, &CheClusterList{})
|
||||
}
|
||||
|
||||
// IsEnabled is a utility method checking the `Enabled` property using its optional value or the default.
|
||||
func (s *CheClusterSpec) IsEnabled() bool {
|
||||
return s.Enabled == nil || *s.Enabled
|
||||
}
|
||||
|
||||
// IsEnabled is a utility method checking the `Enabled` property using its optional value or the default.
|
||||
func (s *CheGatewaySpec) IsEnabled() bool {
|
||||
return s.Enabled == nil || *s.Enabled
|
||||
}
|
||||
|
|
@ -1,16 +0,0 @@
|
|||
//
|
||||
// Copyright (c) 2019-2021 Red Hat, Inc.
|
||||
// This program and the accompanying materials are made
|
||||
// available under the terms of the Eclipse Public License 2.0
|
||||
// which is available at https://www.eclipse.org/legal/epl-2.0/
|
||||
//
|
||||
// SPDX-License-Identifier: EPL-2.0
|
||||
//
|
||||
// Contributors:
|
||||
// Red Hat, Inc. - initial API and implementation
|
||||
//
|
||||
|
||||
// Package v2alpha1 contains API Schema definitions for the org v2alpha1 API group
|
||||
// +k8s:deepcopy-gen=package,register
|
||||
// +groupName=org.eclipse.che
|
||||
package v2alpha1
|
||||
|
|
@ -1,214 +0,0 @@
|
|||
// +build !ignore_autogenerated
|
||||
|
||||
//
|
||||
// Copyright (c) 2019-2021 Red Hat, Inc.
|
||||
// This program and the accompanying materials are made
|
||||
// available under the terms of the Eclipse Public License 2.0
|
||||
// which is available at https://www.eclipse.org/legal/epl-2.0/
|
||||
//
|
||||
// SPDX-License-Identifier: EPL-2.0
|
||||
//
|
||||
// Contributors:
|
||||
// Red Hat, Inc. - initial API and implementation
|
||||
//
|
||||
|
||||
// Code generated by controller-gen. DO NOT EDIT.
|
||||
|
||||
package v2alpha1
|
||||
|
||||
import (
|
||||
v1 "k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||
)
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *CheCluster) DeepCopyInto(out *CheCluster) {
|
||||
*out = *in
|
||||
out.TypeMeta = in.TypeMeta
|
||||
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
|
||||
in.Spec.DeepCopyInto(&out.Spec)
|
||||
out.Status = in.Status
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CheCluster.
|
||||
func (in *CheCluster) DeepCopy() *CheCluster {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(CheCluster)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||
func (in *CheCluster) DeepCopyObject() runtime.Object {
|
||||
if c := in.DeepCopy(); c != nil {
|
||||
return c
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *CheClusterList) DeepCopyInto(out *CheClusterList) {
|
||||
*out = *in
|
||||
out.TypeMeta = in.TypeMeta
|
||||
in.ListMeta.DeepCopyInto(&out.ListMeta)
|
||||
if in.Items != nil {
|
||||
in, out := &in.Items, &out.Items
|
||||
*out = make([]CheCluster, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CheClusterList.
|
||||
func (in *CheClusterList) DeepCopy() *CheClusterList {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(CheClusterList)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||
func (in *CheClusterList) DeepCopyObject() runtime.Object {
|
||||
if c := in.DeepCopy(); c != nil {
|
||||
return c
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *CheClusterSpec) DeepCopyInto(out *CheClusterSpec) {
|
||||
*out = *in
|
||||
if in.Enabled != nil {
|
||||
in, out := &in.Enabled, &out.Enabled
|
||||
*out = new(bool)
|
||||
**out = **in
|
||||
}
|
||||
in.Workspaces.DeepCopyInto(&out.Workspaces)
|
||||
in.Gateway.DeepCopyInto(&out.Gateway)
|
||||
in.K8s.DeepCopyInto(&out.K8s)
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CheClusterSpec.
|
||||
func (in *CheClusterSpec) DeepCopy() *CheClusterSpec {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(CheClusterSpec)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *CheClusterSpecK8s) DeepCopyInto(out *CheClusterSpecK8s) {
|
||||
*out = *in
|
||||
if in.IngressAnnotations != nil {
|
||||
in, out := &in.IngressAnnotations, &out.IngressAnnotations
|
||||
*out = make(map[string]string, len(*in))
|
||||
for key, val := range *in {
|
||||
(*out)[key] = val
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CheClusterSpecK8s.
|
||||
func (in *CheClusterSpecK8s) DeepCopy() *CheClusterSpecK8s {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(CheClusterSpecK8s)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *CheClusterStatusV2Alpha1) DeepCopyInto(out *CheClusterStatusV2Alpha1) {
|
||||
*out = *in
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CheClusterStatusV2Alpha1.
|
||||
func (in *CheClusterStatusV2Alpha1) DeepCopy() *CheClusterStatusV2Alpha1 {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(CheClusterStatusV2Alpha1)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *CheGatewaySpec) DeepCopyInto(out *CheGatewaySpec) {
|
||||
*out = *in
|
||||
if in.Enabled != nil {
|
||||
in, out := &in.Enabled, &out.Enabled
|
||||
*out = new(bool)
|
||||
**out = **in
|
||||
}
|
||||
if in.ConfigLabels != nil {
|
||||
in, out := &in.ConfigLabels, &out.ConfigLabels
|
||||
*out = make(labels.Set, len(*in))
|
||||
for key, val := range *in {
|
||||
(*out)[key] = val
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CheGatewaySpec.
|
||||
func (in *CheGatewaySpec) DeepCopy() *CheGatewaySpec {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(CheGatewaySpec)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *DomainEndpoints) DeepCopyInto(out *DomainEndpoints) {
|
||||
*out = *in
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DomainEndpoints.
|
||||
func (in *DomainEndpoints) DeepCopy() *DomainEndpoints {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(DomainEndpoints)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *Workspaces) DeepCopyInto(out *Workspaces) {
|
||||
*out = *in
|
||||
out.DomainEndpoints = in.DomainEndpoints
|
||||
if in.PodNodeSelector != nil {
|
||||
in, out := &in.PodNodeSelector, &out.PodNodeSelector
|
||||
*out = make(map[string]string, len(*in))
|
||||
for key, val := range *in {
|
||||
(*out)[key] = val
|
||||
}
|
||||
}
|
||||
if in.PodTolerations != nil {
|
||||
in, out := &in.PodTolerations, &out.PodTolerations
|
||||
*out = make([]v1.Toleration, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Workspaces.
|
||||
func (in *Workspaces) DeepCopy() *Workspaces {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(Workspaces)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
|
@ -20,7 +20,8 @@ metadata:
|
|||
"apiVersion": "org.eclipse.che/v1",
|
||||
"kind": "CheCluster",
|
||||
"metadata": {
|
||||
"name": "eclipse-che"
|
||||
"name": "eclipse-che",
|
||||
"namespace": "eclipse-che"
|
||||
},
|
||||
"spec": {
|
||||
"auth": {
|
||||
|
|
@ -29,34 +30,55 @@ metadata:
|
|||
"oAuthSecret": ""
|
||||
},
|
||||
"database": {
|
||||
"chePostgresDb": "",
|
||||
"chePostgresHostName": "",
|
||||
"chePostgresPort": "",
|
||||
"chePostgresSecret": "",
|
||||
"externalDb": false
|
||||
},
|
||||
"devWorkspace": {
|
||||
"enable": true
|
||||
"k8s": {
|
||||
"ingressDomain": null,
|
||||
"tlsSecretName": null
|
||||
},
|
||||
"metrics": {
|
||||
"enable": true
|
||||
},
|
||||
"server": {
|
||||
"cheClusterRoles": "",
|
||||
"cheWorkspaceClusterRole": "",
|
||||
"gitSelfSignedCert": false,
|
||||
"nonProxyHosts": "",
|
||||
"proxyPort": "",
|
||||
"proxySecret": "",
|
||||
"proxyURL": "",
|
||||
"workspaceNamespaceDefault": "<username>-che"
|
||||
},
|
||||
"storage": {
|
||||
"postgresPVCStorageClassName": "",
|
||||
"preCreateSubPaths": true,
|
||||
"pvcClaimSize": "10Gi",
|
||||
"pvcStrategy": "common",
|
||||
"workspacePVCStorageClassName": ""
|
||||
"pvcStrategy": "common"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"apiVersion": "org.eclipse.che/v2",
|
||||
"kind": "CheCluster",
|
||||
"metadata": {
|
||||
"name": "eclipse-che",
|
||||
"namespace": "eclipse-che"
|
||||
},
|
||||
"spec": {
|
||||
"components": {
|
||||
"database": {
|
||||
"externalDb": false
|
||||
},
|
||||
"metrics": {
|
||||
"enable": true
|
||||
}
|
||||
},
|
||||
"devEnvironments": {
|
||||
"defaultNamespace": {
|
||||
"template": "<username>-che"
|
||||
},
|
||||
"storage": {
|
||||
"pvcStrategy": "common"
|
||||
}
|
||||
},
|
||||
"networking": {
|
||||
"auth": {
|
||||
"identityProviderURL": "",
|
||||
"oAuthClientName": "",
|
||||
"oAuthSecret": ""
|
||||
},
|
||||
"domain": "",
|
||||
"tlsSecretName": ""
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -75,12 +97,123 @@ metadata:
|
|||
operators.operatorframework.io/project_layout: go.kubebuilder.io/v3
|
||||
repository: https://github.com/eclipse-che/che-operator
|
||||
support: Eclipse Foundation
|
||||
name: eclipse-che-preview-openshift.v7.48.0-445.next
|
||||
name: eclipse-che-preview-openshift.v7.49.0-565.next
|
||||
namespace: placeholder
|
||||
spec:
|
||||
apiservicedefinitions: {}
|
||||
customresourcedefinitions:
|
||||
owned:
|
||||
- description: 'The `CheCluster` custom resource allows defining and managing
|
||||
Eclipse Che server installation. Based on these settings, the Operator
|
||||
automatically creates and maintains several ConfigMaps: `che`, `plugin-registry`,
|
||||
`devfile-registry` that will contain the appropriate environment variables
|
||||
of the various components of the installation. These generated ConfigMaps
|
||||
must NOT be updated manually.'
|
||||
displayName: Eclipse Che instance Specification
|
||||
kind: CheCluster
|
||||
name: checlusters.org.eclipse.che
|
||||
resources:
|
||||
- kind: ClusterRole
|
||||
name: ''
|
||||
version: v1
|
||||
- kind: ClusterRoleBinding
|
||||
name: ''
|
||||
version: v1
|
||||
- kind: ConfigMap
|
||||
name: ''
|
||||
version: v1
|
||||
- kind: Deployment
|
||||
name: ''
|
||||
version: apps/v1
|
||||
- kind: Ingress
|
||||
name: ''
|
||||
version: v1
|
||||
- kind: Role
|
||||
name: ''
|
||||
version: v1
|
||||
- kind: RoleBinding
|
||||
name: ''
|
||||
version: v1
|
||||
- kind: Route
|
||||
name: ''
|
||||
version: v1
|
||||
- kind: Secret
|
||||
name: ''
|
||||
version: v1
|
||||
- kind: Service
|
||||
name: ''
|
||||
version: v1
|
||||
specDescriptors:
|
||||
- description: Development environment default configuration options.
|
||||
displayName: Development environments
|
||||
path: devEnvironments
|
||||
- description: Che components configuration.
|
||||
displayName: Components
|
||||
path: components
|
||||
- description: Networking, Che authentication and TLS configuration.
|
||||
displayName: Networking
|
||||
path: networking
|
||||
- description: Configuration of an alternative registry that stores Che
|
||||
images.
|
||||
displayName: Container registry
|
||||
path: containerRegistry
|
||||
statusDescriptors:
|
||||
- description: Specifies the current phase of the Che deployment.
|
||||
displayName: ChePhase
|
||||
path: chePhase
|
||||
x-descriptors:
|
||||
- urn:alm:descriptor:text
|
||||
- description: Public URL to the Che server.
|
||||
displayName: Eclipse Che URL
|
||||
path: cheURL
|
||||
x-descriptors:
|
||||
- urn:alm:descriptor:org.w3:link
|
||||
- description: Current installed Che version.
|
||||
displayName: 'displayName: Eclipse Che version'
|
||||
path: cheVersion
|
||||
x-descriptors:
|
||||
- urn:alm:descriptor:text
|
||||
- description: The public URL to the internal devfile registry.
|
||||
displayName: Devfile registry URL
|
||||
path: devfileRegistryURL
|
||||
x-descriptors:
|
||||
- urn:alm:descriptor:org.w3:link
|
||||
- description: Specifies the current phase of the gateway deployment.
|
||||
displayName: Gateway phase
|
||||
path: gatewayPhase
|
||||
x-descriptors:
|
||||
- urn:alm:descriptor:text
|
||||
- description: A human readable message indicating details about why the
|
||||
Che deployment is in current phase.
|
||||
displayName: Message
|
||||
path: message
|
||||
x-descriptors:
|
||||
- urn:alm:descriptor:text
|
||||
- description: The public URL to the internal plug-in registry.
|
||||
displayName: Plugin registry URL
|
||||
path: pluginRegistryURL
|
||||
x-descriptors:
|
||||
- urn:alm:descriptor:org.w3:link
|
||||
- description: The PostgreSQL version of the image in use.
|
||||
displayName: PostgreSQL version
|
||||
path: postgresVersion
|
||||
x-descriptors:
|
||||
- urn:alm:descriptor:text
|
||||
- description: A brief CamelCase message indicating details about why the
|
||||
Che deployment is in current phase.
|
||||
displayName: Reason
|
||||
path: reason
|
||||
x-descriptors:
|
||||
- urn:alm:descriptor:text
|
||||
- description: The resolved workspace base domain. This is either the copy
|
||||
of the explicitly defined property of the same name in the spec or,
|
||||
if it is undefined in the spec and we're running on OpenShift, the automatically
|
||||
resolved basedomain for routes.
|
||||
displayName: Workspace base domain
|
||||
path: workspaceBaseDomain
|
||||
x-descriptors:
|
||||
- urn:alm:descriptor:text
|
||||
version: v2
|
||||
- description: The `CheCluster` custom resource allows defining and managing
|
||||
a Che server installation
|
||||
displayName: Eclipse Che instance Specification
|
||||
|
|
@ -220,6 +353,12 @@ spec:
|
|||
path: devfileRegistryURL
|
||||
x-descriptors:
|
||||
- urn:alm:descriptor:org.w3:link
|
||||
- description: The ConfigMap containing certificates to propagate to the
|
||||
Che components and to provide particular configuration for Git.
|
||||
displayName: Git certificates
|
||||
path: gitServerTLSCertificateConfigMapName
|
||||
x-descriptors:
|
||||
- urn:alm:descriptor:text
|
||||
- description: A URL that points to some URL where to find help related
|
||||
to the current Operator status.
|
||||
displayName: Help link
|
||||
|
|
@ -540,6 +679,16 @@ spec:
|
|||
- get
|
||||
- list
|
||||
- watch
|
||||
- apiGroups:
|
||||
- cert-manager.io
|
||||
resources:
|
||||
- issuers
|
||||
- certificates
|
||||
verbs:
|
||||
- create
|
||||
- get
|
||||
- list
|
||||
- update
|
||||
- apiGroups:
|
||||
- ""
|
||||
resources:
|
||||
|
|
@ -971,8 +1120,8 @@ spec:
|
|||
value: quay.io/eclipse/che-plugin-registry:next
|
||||
- name: RELATED_IMAGE_devfile_registry
|
||||
value: quay.io/eclipse/che-devfile-registry:next
|
||||
- name: RELATED_IMAGE_pvc_jobs
|
||||
value: registry.access.redhat.com/ubi8-minimal:8.6-751
|
||||
- name: RELATED_IMAGE_che_tls_secrets_creation_job
|
||||
value: quay.io/eclipse/che-tls-secret-creator:alpine-01a4c34
|
||||
- name: RELATED_IMAGE_postgres
|
||||
value: quay.io/eclipse/che--centos--postgresql-96-centos7:9.6-b681d78125361519180a6ac05242c296f8906c11eab7e207b5ca9a89b6344392
|
||||
- name: RELATED_IMAGE_postgres_13_3
|
||||
|
|
@ -1020,6 +1169,9 @@ spec:
|
|||
timeoutSeconds: 5
|
||||
name: che-operator
|
||||
ports:
|
||||
- containerPort: 9443
|
||||
name: webhook-server
|
||||
protocol: TCP
|
||||
- containerPort: 60000
|
||||
name: metrics
|
||||
readinessProbe:
|
||||
|
|
@ -1046,12 +1198,21 @@ spec:
|
|||
privileged: false
|
||||
readOnlyRootFilesystem: false
|
||||
runAsNonRoot: true
|
||||
volumeMounts:
|
||||
- mountPath: /tmp/k8s-webhook-server/serving-certs
|
||||
name: webhook-tls-certs
|
||||
readOnly: true
|
||||
hostIPC: false
|
||||
hostNetwork: false
|
||||
hostPID: false
|
||||
restartPolicy: Always
|
||||
serviceAccountName: che-operator
|
||||
terminationGracePeriodSeconds: 20
|
||||
volumes:
|
||||
- name: webhook-tls-certs
|
||||
secret:
|
||||
defaultMode: 420
|
||||
secretName: che-operator-webhook-server-cert
|
||||
permissions:
|
||||
- rules:
|
||||
- apiGroups:
|
||||
|
|
@ -1216,37 +1377,6 @@ spec:
|
|||
- patch
|
||||
- update
|
||||
- watch
|
||||
- apiGroups:
|
||||
- ""
|
||||
resources:
|
||||
- configmaps
|
||||
verbs:
|
||||
- get
|
||||
- list
|
||||
- watch
|
||||
- create
|
||||
- update
|
||||
- patch
|
||||
- delete
|
||||
- apiGroups:
|
||||
- coordination.k8s.io
|
||||
resources:
|
||||
- leases
|
||||
verbs:
|
||||
- get
|
||||
- list
|
||||
- watch
|
||||
- create
|
||||
- update
|
||||
- patch
|
||||
- delete
|
||||
- apiGroups:
|
||||
- ""
|
||||
resources:
|
||||
- events
|
||||
verbs:
|
||||
- create
|
||||
- patch
|
||||
serviceAccountName: che-operator
|
||||
strategy: deployment
|
||||
installModes:
|
||||
|
|
@ -1273,9 +1403,22 @@ spec:
|
|||
- name: Operator GitHub Repo
|
||||
url: https://github.com/eclipse-che/che-operator
|
||||
maintainers:
|
||||
- email: dfestal@redhat.com
|
||||
name: David Festal
|
||||
- email: abazko@redhat.com
|
||||
name: Anatolii Bazko
|
||||
maturity: stable
|
||||
provider:
|
||||
name: Eclipse Foundation
|
||||
version: 7.48.0-445.next
|
||||
version: 7.49.0-565.next
|
||||
webhookdefinitions:
|
||||
- admissionReviewVersions:
|
||||
- v1
|
||||
- v2
|
||||
containerPort: 443
|
||||
conversionCRDs:
|
||||
- checlusters.org.eclipse.che
|
||||
deploymentName: che-operator
|
||||
generateName: ccheclusters.kb.io
|
||||
sideEffects: None
|
||||
targetPort: 9443
|
||||
type: ConversionWebhook
|
||||
webhookPath: /convert
|
||||
|
|
|
|||
|
|
@ -1,29 +0,0 @@
|
|||
#
|
||||
# Copyright (c) 2019-2021 Red Hat, Inc.
|
||||
# This program and the accompanying materials are made
|
||||
# available under the terms of the Eclipse Public License 2.0
|
||||
# which is available at https://www.eclipse.org/legal/epl-2.0/
|
||||
#
|
||||
# SPDX-License-Identifier: EPL-2.0
|
||||
#
|
||||
# Contributors:
|
||||
# Red Hat, Inc. - initial API and implementation
|
||||
#
|
||||
|
||||
apiVersion: v1
|
||||
data:
|
||||
controller_manager_config.yaml: |
|
||||
apiVersion: controller-runtime.sigs.k8s.io/v1alpha1
|
||||
kind: ControllerManagerConfig
|
||||
health:
|
||||
healthProbeBindAddress: :6789
|
||||
metrics:
|
||||
bindAddress: 127.0.0.1:60000
|
||||
webhook:
|
||||
port: 9443
|
||||
leaderElection:
|
||||
leaderElect: true
|
||||
resourceName: e79b08a4.org.eclipse.che
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: manager-config
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -1,142 +0,0 @@
|
|||
#
|
||||
# Copyright (c) 2019-2021 Red Hat, Inc.
|
||||
# This program and the accompanying materials are made
|
||||
# available under the terms of the Eclipse Public License 2.0
|
||||
# which is available at https://www.eclipse.org/legal/epl-2.0/
|
||||
#
|
||||
# SPDX-License-Identifier: EPL-2.0
|
||||
#
|
||||
# Contributors:
|
||||
# Red Hat, Inc. - initial API and implementation
|
||||
#
|
||||
|
||||
apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
annotations:
|
||||
controller-gen.kubebuilder.io/version: v0.4.1
|
||||
creationTimestamp: null
|
||||
labels:
|
||||
app.kubernetes.io/instance: che
|
||||
app.kubernetes.io/managed-by: olm
|
||||
app.kubernetes.io/name: che
|
||||
name: chebackupserverconfigurations.org.eclipse.che
|
||||
spec:
|
||||
group: org.eclipse.che
|
||||
names:
|
||||
kind: CheBackupServerConfiguration
|
||||
listKind: CheBackupServerConfigurationList
|
||||
plural: chebackupserverconfigurations
|
||||
singular: chebackupserverconfiguration
|
||||
scope: Namespaced
|
||||
versions:
|
||||
- name: v1
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
description: The `CheBackupServerConfiguration` custom resource allows defining and managing Eclipse Che Backup Server Configurations
|
||||
properties:
|
||||
apiVersion:
|
||||
description: 'APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
|
||||
type: string
|
||||
kind:
|
||||
description: 'Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
|
||||
type: string
|
||||
metadata:
|
||||
type: object
|
||||
spec:
|
||||
description: CheBackupServerConfigurationSpec defines the desired state of CheBackupServerConfiguration Only one type of backup server is allowed to be configured per CR.
|
||||
properties:
|
||||
awss3:
|
||||
description: Amazon S3 or compatible alternatives.
|
||||
properties:
|
||||
awsAccessKeySecretRef:
|
||||
description: Reference to secret that contains awsAccessKeyId and awsSecretAccessKey keys.
|
||||
type: string
|
||||
hostname:
|
||||
description: Server hostname, defaults to 's3.amazonaws.com'. Might be customized in case of alternative server.
|
||||
type: string
|
||||
port:
|
||||
description: Backup server port. Usually default value is used. Might be customized in case of alternative server.
|
||||
type: integer
|
||||
protocol:
|
||||
description: Protocol to use when connection to the server. Might be customized in case of alternative server.
|
||||
type: string
|
||||
repositoryPasswordSecretRef:
|
||||
description: Holds reference to a secret with restic repository password under 'repo-password' field to encrypt / decrypt its content.
|
||||
type: string
|
||||
repositoryPath:
|
||||
description: Bucket name and repository, e.g. bucket/repo
|
||||
type: string
|
||||
required:
|
||||
- awsAccessKeySecretRef
|
||||
- repositoryPasswordSecretRef
|
||||
- repositoryPath
|
||||
type: object
|
||||
rest:
|
||||
description: Rest backup server configuration.
|
||||
properties:
|
||||
credentialsSecretRef:
|
||||
description: Secret that contains username and password fields to login into restic server. Note, each repository is encrypted with own password. See ResticRepoPasswordSecretRef field.
|
||||
type: string
|
||||
hostname:
|
||||
description: Backup server host
|
||||
type: string
|
||||
port:
|
||||
description: Backup server port
|
||||
type: integer
|
||||
protocol:
|
||||
description: Protocol to use when connection to the server Defaults to https.
|
||||
type: string
|
||||
repositoryPasswordSecretRef:
|
||||
description: Holds reference to a secret with restic repository password under 'repo-password' field to encrypt / decrypt its content.
|
||||
type: string
|
||||
repositoryPath:
|
||||
description: Restic repository path
|
||||
type: string
|
||||
required:
|
||||
- hostname
|
||||
- repositoryPasswordSecretRef
|
||||
type: object
|
||||
sftp:
|
||||
description: Sftp backup server configuration.
|
||||
properties:
|
||||
hostname:
|
||||
description: Backup server host
|
||||
type: string
|
||||
port:
|
||||
description: Backup server port
|
||||
type: integer
|
||||
repositoryPasswordSecretRef:
|
||||
description: Holds reference to a secret with restic repository password under 'repo-password' field to encrypt / decrypt its content.
|
||||
type: string
|
||||
repositoryPath:
|
||||
description: Restic repository path, relative or absolute, e.g. /srv/repo
|
||||
type: string
|
||||
sshKeySecretRef:
|
||||
description: Private ssh key under 'ssh-privatekey' field for passwordless login
|
||||
type: string
|
||||
username:
|
||||
description: User login on the remote server
|
||||
type: string
|
||||
required:
|
||||
- hostname
|
||||
- repositoryPasswordSecretRef
|
||||
- repositoryPath
|
||||
- sshKeySecretRef
|
||||
- username
|
||||
type: object
|
||||
type: object
|
||||
status:
|
||||
description: CheBackupServerConfigurationStatus defines the observed state of CheBackupServerConfiguration
|
||||
type: object
|
||||
type: object
|
||||
served: true
|
||||
storage: true
|
||||
subresources:
|
||||
status: {}
|
||||
status:
|
||||
acceptedNames:
|
||||
kind: ""
|
||||
plural: ""
|
||||
conditions: []
|
||||
storedVersions: []
|
||||
|
|
@ -1,85 +0,0 @@
|
|||
#
|
||||
# Copyright (c) 2019-2021 Red Hat, Inc.
|
||||
# This program and the accompanying materials are made
|
||||
# available under the terms of the Eclipse Public License 2.0
|
||||
# which is available at https://www.eclipse.org/legal/epl-2.0/
|
||||
#
|
||||
# SPDX-License-Identifier: EPL-2.0
|
||||
#
|
||||
# Contributors:
|
||||
# Red Hat, Inc. - initial API and implementation
|
||||
#
|
||||
|
||||
apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
annotations:
|
||||
controller-gen.kubebuilder.io/version: v0.4.1
|
||||
creationTimestamp: null
|
||||
labels:
|
||||
app.kubernetes.io/instance: che
|
||||
app.kubernetes.io/managed-by: olm
|
||||
app.kubernetes.io/name: che
|
||||
name: checlusterbackups.org.eclipse.che
|
||||
spec:
|
||||
group: org.eclipse.che
|
||||
names:
|
||||
kind: CheClusterBackup
|
||||
listKind: CheClusterBackupList
|
||||
plural: checlusterbackups
|
||||
singular: checlusterbackup
|
||||
scope: Namespaced
|
||||
versions:
|
||||
- name: v1
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
description: The `CheClusterBackup` custom resource allows defining and managing Eclipse Che backup
|
||||
properties:
|
||||
apiVersion:
|
||||
description: 'APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
|
||||
type: string
|
||||
kind:
|
||||
description: 'Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
|
||||
type: string
|
||||
metadata:
|
||||
type: object
|
||||
spec:
|
||||
description: CheClusterBackupSpec defines the desired state of CheClusterBackup
|
||||
properties:
|
||||
backupServerConfigRef:
|
||||
description: Name of custom resource with a backup server configuration to use for this backup. Note, UseInternalBackupServer field can configure internal backup server automatically.
|
||||
type: string
|
||||
useInternalBackupServer:
|
||||
description: Automatically setup pod with REST backup server and use the server in this configuration. Note, this flag takes precedence and will overwrite existing backup server configuration.
|
||||
type: boolean
|
||||
type: object
|
||||
status:
|
||||
description: CheClusterBackupStatus defines the observed state of CheClusterBackup
|
||||
properties:
|
||||
cheVersion:
|
||||
description: Version that was backed up
|
||||
type: string
|
||||
message:
|
||||
description: Message explaining the state of the backup or an error message
|
||||
type: string
|
||||
snapshotId:
|
||||
description: Last backup snapshot ID
|
||||
type: string
|
||||
stage:
|
||||
description: Describes backup progress
|
||||
type: string
|
||||
state:
|
||||
description: 'Backup progress state: InProgress, Failed, Succeeded'
|
||||
type: string
|
||||
type: object
|
||||
type: object
|
||||
served: true
|
||||
storage: true
|
||||
subresources:
|
||||
status: {}
|
||||
status:
|
||||
acceptedNames:
|
||||
kind: ""
|
||||
plural: ""
|
||||
conditions: []
|
||||
storedVersions: []
|
||||
|
|
@ -1,79 +0,0 @@
|
|||
#
|
||||
# Copyright (c) 2019-2021 Red Hat, Inc.
|
||||
# This program and the accompanying materials are made
|
||||
# available under the terms of the Eclipse Public License 2.0
|
||||
# which is available at https://www.eclipse.org/legal/epl-2.0/
|
||||
#
|
||||
# SPDX-License-Identifier: EPL-2.0
|
||||
#
|
||||
# Contributors:
|
||||
# Red Hat, Inc. - initial API and implementation
|
||||
#
|
||||
|
||||
apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
annotations:
|
||||
controller-gen.kubebuilder.io/version: v0.4.1
|
||||
creationTimestamp: null
|
||||
labels:
|
||||
app.kubernetes.io/instance: che
|
||||
app.kubernetes.io/managed-by: olm
|
||||
app.kubernetes.io/name: che
|
||||
name: checlusterrestores.org.eclipse.che
|
||||
spec:
|
||||
group: org.eclipse.che
|
||||
names:
|
||||
kind: CheClusterRestore
|
||||
listKind: CheClusterRestoreList
|
||||
plural: checlusterrestores
|
||||
singular: checlusterrestore
|
||||
scope: Namespaced
|
||||
versions:
|
||||
- name: v1
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
description: The `CheClusterRestore` custom resource allows defining and managing Eclipse Che restore
|
||||
properties:
|
||||
apiVersion:
|
||||
description: 'APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
|
||||
type: string
|
||||
kind:
|
||||
description: 'Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
|
||||
type: string
|
||||
metadata:
|
||||
type: object
|
||||
spec:
|
||||
description: CheClusterRestoreSpec defines the desired state of CheClusterRestore
|
||||
properties:
|
||||
backupServerConfigRef:
|
||||
description: Name of custom resource with a backup server configuration to use for this restore. Can be omitted if only one server configuration object exists within the namespace.
|
||||
type: string
|
||||
snapshotId:
|
||||
description: If omitted, latest snapshot will be used.
|
||||
type: string
|
||||
type: object
|
||||
status:
|
||||
description: CheClusterRestoreStatus defines the observed state of CheClusterRestore
|
||||
properties:
|
||||
message:
|
||||
description: Restore result or error message
|
||||
type: string
|
||||
stage:
|
||||
description: Describes phase of restore progress
|
||||
type: string
|
||||
state:
|
||||
description: 'Restore progress state: InProgress, Failed, Succeeded'
|
||||
type: string
|
||||
type: object
|
||||
type: object
|
||||
served: true
|
||||
storage: true
|
||||
subresources:
|
||||
status: {}
|
||||
status:
|
||||
acceptedNames:
|
||||
kind: ""
|
||||
plural: ""
|
||||
conditions: []
|
||||
storedVersions: []
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
#
|
||||
# Copyright (c) 2019-2022 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
|
||||
#
|
||||
|
||||
# The following manifests contain a self-signed issuer CR and a certificate CR.
|
||||
# More document can be found at https://docs.cert-manager.io
|
||||
# WARNING: Targets CertManager v1.0. Check https://cert-manager.io/docs/installation/upgrading/ for breaking changes.
|
||||
apiVersion: cert-manager.io/v1
|
||||
kind: Issuer
|
||||
metadata:
|
||||
name: che-operator-selfsigned-issuer
|
||||
namespace: eclipse-che
|
||||
labels:
|
||||
app.kubernetes.io/name: che
|
||||
app.kubernetes.io/instance: che
|
||||
app.kubernetes.io/part-of: che.eclipse.org
|
||||
app.kubernetes.io/component: che-operator
|
||||
spec:
|
||||
selfSigned: {}
|
||||
---
|
||||
apiVersion: cert-manager.io/v1
|
||||
kind: Certificate
|
||||
metadata:
|
||||
name: che-operator-serving-cert # this name should match the one appeared in kustomizeconfig.yaml
|
||||
namespace: eclipse-che
|
||||
labels:
|
||||
app.kubernetes.io/name: che
|
||||
app.kubernetes.io/instance: che
|
||||
app.kubernetes.io/part-of: che.eclipse.org
|
||||
app.kubernetes.io/component: che-operator
|
||||
spec:
|
||||
# $(SERVICE_NAME) and $(SERVICE_NAMESPACE) will be substituted by kustomize
|
||||
dnsNames:
|
||||
- $(SERVICE_NAME).$(SERVICE_NAMESPACE).svc
|
||||
- $(SERVICE_NAME).$(SERVICE_NAMESPACE).svc.cluster.local
|
||||
issuerRef:
|
||||
kind: Issuer
|
||||
name: che-operator-selfsigned-issuer
|
||||
secretName: che-operator-webhook-server-cert # this secret will not be prefixed, since it's not managed by kustomize
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
#
|
||||
# Copyright (c) 2019-2022 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
|
||||
#
|
||||
|
||||
resources:
|
||||
- certificate.yaml
|
||||
|
||||
configurations:
|
||||
- kustomizeconfig.yaml
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
#
|
||||
# Copyright (c) 2019-2022 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
|
||||
#
|
||||
|
||||
# This configuration is for teaching kustomize how to update name ref and var substitution
|
||||
nameReference:
|
||||
- kind: Issuer
|
||||
group: cert-manager.io
|
||||
fieldSpecs:
|
||||
- kind: Certificate
|
||||
group: cert-manager.io
|
||||
path: spec/issuerRef/name
|
||||
|
||||
varReference:
|
||||
- kind: Certificate
|
||||
group: cert-manager.io
|
||||
path: spec/commonName
|
||||
- kind: Certificate
|
||||
group: cert-manager.io
|
||||
path: spec/dnsNames
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -14,25 +14,12 @@
|
|||
# since it depends on service name and namespace that are out of this kustomize package.
|
||||
# It should be run by config/default
|
||||
resources:
|
||||
- bases/org_v1_che_crd.yaml
|
||||
# - bases/org.eclipse.che_checlusters.yaml
|
||||
#+kubebuilder:scaffold:crdkustomizeresource
|
||||
- bases/org.eclipse.che_checlusters.yaml
|
||||
|
||||
patchesStrategicMerge:
|
||||
# [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix.
|
||||
# patches here are for enabling the conversion webhook for each CRD
|
||||
#- patches/webhook_in_checlusters.yaml
|
||||
#+kubebuilder:scaffold:crdkustomizewebhookpatch
|
||||
|
||||
# [CERTMANAGER] To enable webhook, uncomment all the sections with [CERTMANAGER] prefix.
|
||||
# patches here are for enabling the CA injection for each CRD
|
||||
#- patches/cainjection_in_checlusters.yaml
|
||||
#+kubebuilder:scaffold:crdkustomizecainjectionpatch
|
||||
|
||||
# [LABELS] extra labels patches
|
||||
- patches/webhook_in_checlusters.yaml
|
||||
- patches/extralabels_in_checlusters.yaml
|
||||
# +kubebuilder:scaffold:crdkustomizeextralabelspatch
|
||||
|
||||
# the following config is for teaching kustomize how to do kustomization for CRDs.
|
||||
configurations:
|
||||
- kustomizeconfig.yaml
|
||||
|
||||
|
|
|
|||
|
|
@ -17,5 +17,5 @@ metadata:
|
|||
labels:
|
||||
app.kubernetes.io/name: che
|
||||
app.kubernetes.io/instance: che
|
||||
app.kubernetes.io/managed-by: olm
|
||||
app.kubernetes.io/part-of: che.eclipse.org
|
||||
name: checlusters.org.eclipse.che
|
||||
|
|
|
|||
|
|
@ -19,8 +19,11 @@ spec:
|
|||
conversion:
|
||||
strategy: Webhook
|
||||
webhook:
|
||||
conversionReviewVersions: ["v1", "v2"]
|
||||
clientConfig:
|
||||
service:
|
||||
namespace: system
|
||||
name: webhook-service
|
||||
namespace: eclipse-che
|
||||
name: che-operator-service
|
||||
path: /convert
|
||||
# caBundle will be filled on creation
|
||||
# caBundle: Cg==
|
||||
|
|
|
|||
|
|
@ -1,87 +0,0 @@
|
|||
#
|
||||
# Copyright (c) 2019-2021 Red Hat, Inc.
|
||||
# This program and the accompanying materials are made
|
||||
# available under the terms of the Eclipse Public License 2.0
|
||||
# which is available at https://www.eclipse.org/legal/epl-2.0/
|
||||
#
|
||||
# SPDX-License-Identifier: EPL-2.0
|
||||
#
|
||||
# Contributors:
|
||||
# Red Hat, Inc. - initial API and implementation
|
||||
#
|
||||
|
||||
# Adds namespace to all resources.
|
||||
namespace: eclipse-che
|
||||
|
||||
# Value of this field is prepended to the
|
||||
# names of all resources, e.g. a deployment named
|
||||
# "wordpress" becomes "alices-wordpress".
|
||||
# Note that it should also match with the prefix (text before '-') of the namespace
|
||||
# field above.
|
||||
# namePrefix: che-operator-
|
||||
|
||||
# Labels to add to all resources and selectors.
|
||||
#commonLabels:
|
||||
# someName: someValue
|
||||
|
||||
bases:
|
||||
- ../crd
|
||||
- ../rbac
|
||||
- ../manager
|
||||
# [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix including the one in
|
||||
# crd/kustomization.yaml
|
||||
#- ../webhook
|
||||
# [CERTMANAGER] To enable cert-manager, uncomment all sections with 'CERTMANAGER'. 'WEBHOOK' components are required.
|
||||
#- ../certmanager
|
||||
# [PROMETHEUS] To enable prometheus monitor, uncomment all sections with 'PROMETHEUS'.
|
||||
#- ../prometheus
|
||||
|
||||
patchesStrategicMerge:
|
||||
# Protect the /metrics endpoint by putting it behind auth.
|
||||
# If you want your che-operator to expose the /metrics
|
||||
# endpoint w/o any authn/z, please comment the following line.
|
||||
# Todo "metrics proxy"
|
||||
# - manager_auth_proxy_patch.yaml
|
||||
|
||||
# Mount the controller config file for loading che-operator configurations
|
||||
# through a ComponentConfig type
|
||||
#- manager_config_patch.yaml
|
||||
|
||||
# [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix including the one in
|
||||
# crd/kustomization.yaml
|
||||
#- manager_webhook_patch.yaml
|
||||
|
||||
# [CERTMANAGER] To enable cert-manager, uncomment all sections with 'CERTMANAGER'.
|
||||
# Uncomment 'CERTMANAGER' sections in crd/kustomization.yaml to enable the CA injection in the admission webhooks.
|
||||
# 'CERTMANAGER' needs to be enabled to use ca injection
|
||||
#- webhookcainjection_patch.yaml
|
||||
|
||||
# the following config is for teaching kustomize how to do var substitution
|
||||
vars:
|
||||
# [CERTMANAGER] To enable cert-manager, uncomment all sections with 'CERTMANAGER' prefix.
|
||||
#- name: CERTIFICATE_NAMESPACE # namespace of the certificate CR
|
||||
# objref:
|
||||
# kind: Certificate
|
||||
# group: cert-manager.io
|
||||
# version: v1
|
||||
# name: serving-cert # this name should match the one in certificate.yaml
|
||||
# fieldref:
|
||||
# fieldpath: metadata.namespace
|
||||
#- name: CERTIFICATE_NAME
|
||||
# objref:
|
||||
# kind: Certificate
|
||||
# group: cert-manager.io
|
||||
# version: v1
|
||||
# name: serving-cert # this name should match the one in certificate.yaml
|
||||
#- name: SERVICE_NAMESPACE # namespace of the service
|
||||
# objref:
|
||||
# kind: Service
|
||||
# version: v1
|
||||
# name: webhook-service
|
||||
# fieldref:
|
||||
# fieldpath: metadata.namespace
|
||||
#- name: SERVICE_NAME
|
||||
# objref:
|
||||
# kind: Service
|
||||
# version: v1
|
||||
# name: webhook-service
|
||||
|
|
@ -1,39 +0,0 @@
|
|||
#
|
||||
# Copyright (c) 2019-2021 Red Hat, Inc.
|
||||
# This program and the accompanying materials are made
|
||||
# available under the terms of the Eclipse Public License 2.0
|
||||
# which is available at https://www.eclipse.org/legal/epl-2.0/
|
||||
#
|
||||
# SPDX-License-Identifier: EPL-2.0
|
||||
#
|
||||
# Contributors:
|
||||
# Red Hat, Inc. - initial API and implementation
|
||||
#
|
||||
|
||||
# This patch inject a sidecar container which is a HTTP proxy for the
|
||||
# controller che-operator, it performs RBAC authorization against the Kubernetes API using SubjectAccessReviews.
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: che-operator
|
||||
namespace: system
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: kube-rbac-proxy
|
||||
image: gcr.io/kubebuilder/kube-rbac-proxy:v0.8.0
|
||||
imagePullPolicy: Always
|
||||
args:
|
||||
- "--secure-listen-address=0.0.0.0:8443"
|
||||
- "--upstream=http://127.0.0.1:60000/"
|
||||
- "--logtostderr=true"
|
||||
- "--v=10"
|
||||
ports:
|
||||
- containerPort: 8443
|
||||
name: https
|
||||
- name: che-operator
|
||||
args:
|
||||
- "--health-probe-bind-address=:6789"
|
||||
- "--metrics-bind-address=127.0.0.1:60000"
|
||||
- "--leader-elect"
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
#
|
||||
# Copyright (c) 2019-2021 Red Hat, Inc.
|
||||
# This program and the accompanying materials are made
|
||||
# available under the terms of the Eclipse Public License 2.0
|
||||
# which is available at https://www.eclipse.org/legal/epl-2.0/
|
||||
#
|
||||
# SPDX-License-Identifier: EPL-2.0
|
||||
#
|
||||
# Contributors:
|
||||
# Red Hat, Inc. - initial API and implementation
|
||||
#
|
||||
|
||||
resources:
|
||||
- ../crd
|
||||
- ../rbac
|
||||
- ../manager
|
||||
- ../namespace
|
||||
- ../webhook
|
||||
- ../certmanager
|
||||
|
||||
# Kubernetes platform specific patches
|
||||
patchesStrategicMerge:
|
||||
- patches/cainjection_in_checlusters.yaml
|
||||
|
||||
vars:
|
||||
- name: CERTIFICATE_NAMESPACE # namespace of the certificate CR
|
||||
objref:
|
||||
kind: Certificate
|
||||
group: cert-manager.io
|
||||
version: v1
|
||||
name: che-operator-serving-cert # this name should match the one in certificate.yaml
|
||||
fieldref:
|
||||
fieldpath: metadata.namespace
|
||||
- name: CERTIFICATE_NAME
|
||||
objref:
|
||||
kind: Certificate
|
||||
group: cert-manager.io
|
||||
version: v1
|
||||
name: che-operator-serving-cert # this name should match the one in certificate.yaml
|
||||
- name: SERVICE_NAMESPACE # namespace of the service
|
||||
objref:
|
||||
kind: Service
|
||||
version: v1
|
||||
name: che-operator-service
|
||||
fieldref:
|
||||
fieldpath: metadata.namespace
|
||||
- name: SERVICE_NAME
|
||||
objref:
|
||||
kind: Service
|
||||
version: v1
|
||||
name: che-operator-service
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
apiVersion: controller-runtime.sigs.k8s.io/v1alpha1
|
||||
kind: ControllerManagerConfig
|
||||
health:
|
||||
healthProbeBindAddress: :6789
|
||||
metrics:
|
||||
bindAddress: 127.0.0.1:60000
|
||||
webhook:
|
||||
port: 9443
|
||||
leaderElection:
|
||||
leaderElect: true
|
||||
resourceName: e79b08a4.org.eclipse.che
|
||||
|
|
@ -12,17 +12,15 @@
|
|||
|
||||
resources:
|
||||
- manager.yaml
|
||||
- controller-namespace.yaml
|
||||
|
||||
patchesStrategicMerge:
|
||||
- patches/manager_webhook_patch.yaml
|
||||
|
||||
generatorOptions:
|
||||
disableNameSuffixHash: true
|
||||
|
||||
configMapGenerator:
|
||||
- files:
|
||||
- controller_manager_config.yaml
|
||||
name: manager-config
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
images:
|
||||
- name: quay.io/eclipse/che-operator:next
|
||||
newName: quay.io/eclipse/che-operator
|
||||
|
|
|
|||
|
|
@ -71,8 +71,6 @@ spec:
|
|||
value: quay.io/eclipse/che-devfile-registry:next
|
||||
- name: RELATED_IMAGE_che_tls_secrets_creation_job
|
||||
value: quay.io/eclipse/che-tls-secret-creator:alpine-01a4c34
|
||||
- name: RELATED_IMAGE_pvc_jobs
|
||||
value: registry.access.redhat.com/ubi8-minimal:8.6-751
|
||||
- name: RELATED_IMAGE_postgres
|
||||
value: quay.io/eclipse/che--centos--postgresql-96-centos7:9.6-b681d78125361519180a6ac05242c296f8906c11eab7e207b5ca9a89b6344392
|
||||
- name: RELATED_IMAGE_postgres_13_3
|
||||
|
|
|
|||
|
|
@ -14,20 +14,22 @@ apiVersion: apps/v1
|
|||
kind: Deployment
|
||||
metadata:
|
||||
name: che-operator
|
||||
namespace: system
|
||||
namespace: eclipse-che
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: che-operator
|
||||
imagePullPolicy: Always
|
||||
args:
|
||||
- "--config=controller_manager_config.yaml"
|
||||
ports:
|
||||
- containerPort: 9443
|
||||
name: webhook-server
|
||||
protocol: TCP
|
||||
volumeMounts:
|
||||
- name: manager-config
|
||||
mountPath: /controller_manager_config.yaml
|
||||
subPath: controller_manager_config.yaml
|
||||
- mountPath: /tmp/k8s-webhook-server/serving-certs
|
||||
name: webhook-tls-certs
|
||||
readOnly: true
|
||||
volumes:
|
||||
- name: manager-config
|
||||
configMap:
|
||||
name: manager-config
|
||||
- name: webhook-tls-certs
|
||||
secret:
|
||||
defaultMode: 420
|
||||
secretName: che-operator-webhook-server-cert
|
||||
File diff suppressed because one or more lines are too long
|
|
@ -14,26 +14,3 @@
|
|||
# used to generate the 'manifests/' directory in a bundle.
|
||||
resources:
|
||||
- bases/che-operator.clusterserviceversion.yaml
|
||||
- ../default
|
||||
- ../samples
|
||||
- ../scorecard
|
||||
|
||||
# [WEBHOOK] To enable webhooks, uncomment all the sections with [WEBHOOK] prefix.
|
||||
# Do NOT uncomment sections with prefix [CERTMANAGER], as OLM does not support cert-manager.
|
||||
# These patches remove the unnecessary "cert" volume and its che-operator container volumeMount.
|
||||
#patchesJson6902:
|
||||
#- target:
|
||||
# group: apps
|
||||
# version: v1
|
||||
# kind: Deployment
|
||||
# name: che-operator
|
||||
# namespace: system
|
||||
# patch: |-
|
||||
# # Remove the che-operator container's "cert" volumeMount, since OLM will create and mount a set of certs.
|
||||
# # Update the indices in this path if adding or removing containers/volumeMounts in the che-operator's Deployment.
|
||||
# - op: remove
|
||||
# path: /spec/template/spec/containers/1/volumeMounts/0
|
||||
# # Remove the "cert" volume, since OLM will create and mount a set of certs.
|
||||
# # Update the indices in this path if adding or removing volumes in the che-operator's Deployment.
|
||||
# - op: remove
|
||||
# path: /spec/template/spec/volumes/0
|
||||
|
|
|
|||
|
|
@ -10,12 +10,5 @@
|
|||
# Red Hat, Inc. - initial API and implementation
|
||||
#
|
||||
|
||||
bases:
|
||||
- ../../manifests
|
||||
patchesJson6902:
|
||||
- path: che-operator.clusterserviceversion-description-patch.yaml
|
||||
target:
|
||||
group: operators.coreos.com
|
||||
version: v1alpha1
|
||||
kind: ClusterServiceVersion
|
||||
name: eclipse-che-preview-openshift.v0.0.0
|
||||
resources:
|
||||
- namespace.yaml
|
||||
|
|
@ -13,6 +13,4 @@
|
|||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
labels:
|
||||
app: che-operator
|
||||
name: eclipse-che
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
#
|
||||
# Copyright (c) 2019-2021 Red Hat, Inc.
|
||||
# This program and the accompanying materials are made
|
||||
# available under the terms of the Eclipse Public License 2.0
|
||||
# which is available at https://www.eclipse.org/legal/epl-2.0/
|
||||
#
|
||||
# SPDX-License-Identifier: EPL-2.0
|
||||
#
|
||||
# Contributors:
|
||||
# Red Hat, Inc. - initial API and implementation
|
||||
#
|
||||
|
||||
resources:
|
||||
- ../crd
|
||||
- ../rbac
|
||||
- ../manager
|
||||
- ../namespace
|
||||
- ../webhook
|
||||
|
||||
patchesStrategicMerge:
|
||||
- patches/cainjection_in_checlusters.yaml
|
||||
- patches/service_cert_patch.yaml
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
#
|
||||
# Copyright (c) 2019-2021 Red Hat, Inc.
|
||||
# This program and the accompanying materials are made
|
||||
# available under the terms of the Eclipse Public License 2.0
|
||||
# which is available at https://www.eclipse.org/legal/epl-2.0/
|
||||
#
|
||||
# SPDX-License-Identifier: EPL-2.0
|
||||
#
|
||||
# Contributors:
|
||||
# Red Hat, Inc. - initial API and implementation
|
||||
#
|
||||
|
||||
resources:
|
||||
- ../../manifests
|
||||
- ../../crd
|
||||
- ../../rbac
|
||||
- ../../manager
|
||||
- ../../webhook
|
||||
- ../../samples
|
||||
- ../../scorecard
|
||||
|
||||
patchesStrategicMerge:
|
||||
- patches/extralabels_in_checlusters.yaml
|
||||
|
||||
patchesJson6902:
|
||||
- target:
|
||||
group: apps
|
||||
version: v1
|
||||
kind: Deployment
|
||||
name: che-operator
|
||||
patch: |-
|
||||
- op: replace
|
||||
path: /spec/template/metadata/labels
|
||||
value:
|
||||
app: che-operator
|
||||
app.kubernetes.io/name: che
|
||||
app.kubernetes.io/instance: che
|
||||
app.kubernetes.io/part-of: che.eclipse.org
|
||||
app.kubernetes.io/component: che-operator
|
||||
app.kubernetes.io/managed-by: olm
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
#
|
||||
# Copyright (c) 2019-2021 Red Hat, Inc.
|
||||
# This program and the accompanying materials are made
|
||||
# available under the terms of the Eclipse Public License 2.0
|
||||
# which is available at https://www.eclipse.org/legal/epl-2.0/
|
||||
#
|
||||
# SPDX-License-Identifier: EPL-2.0
|
||||
#
|
||||
# Contributors:
|
||||
# Red Hat, Inc. - initial API and implementation
|
||||
#
|
||||
|
||||
# The following patch adds extra labels to CRD
|
||||
apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
labels:
|
||||
app.kubernetes.io/managed-by: olm
|
||||
name: checlusters.org.eclipse.che
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
#
|
||||
# Copyright (c) 2019-2021 Red Hat, Inc.
|
||||
# This program and the accompanying materials are made
|
||||
# available under the terms of the Eclipse Public License 2.0
|
||||
# which is available at https://www.eclipse.org/legal/epl-2.0/
|
||||
#
|
||||
# SPDX-License-Identifier: EPL-2.0
|
||||
#
|
||||
# Contributors:
|
||||
# Red Hat, Inc. - initial API and implementation
|
||||
#
|
||||
|
||||
# The following patch adds a directive for certmanager to inject CA into the CRD
|
||||
apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
annotations:
|
||||
service.beta.openshift.io/inject-cabundle: "true"
|
||||
name: checlusters.org.eclipse.che
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
#
|
||||
# Copyright (c) 2019-2021 Red Hat, Inc.
|
||||
# This program and the accompanying materials are made
|
||||
# available under the terms of the Eclipse Public License 2.0
|
||||
# which is available at https://www.eclipse.org/legal/epl-2.0/
|
||||
#
|
||||
# SPDX-License-Identifier: EPL-2.0
|
||||
#
|
||||
# Contributors:
|
||||
# Red Hat, Inc. - initial API and implementation
|
||||
#
|
||||
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: che-operator-service
|
||||
namespace: eclipse-che
|
||||
annotations:
|
||||
service.beta.openshift.io/serving-cert-secret-name: che-operator-webhook-server-cert
|
||||
|
|
@ -1,39 +0,0 @@
|
|||
#
|
||||
# Copyright (c) 2019-2021 Red Hat, Inc.
|
||||
# This program and the accompanying materials are made
|
||||
# available under the terms of the Eclipse Public License 2.0
|
||||
# which is available at https://www.eclipse.org/legal/epl-2.0/
|
||||
#
|
||||
# SPDX-License-Identifier: EPL-2.0
|
||||
#
|
||||
# Contributors:
|
||||
# Red Hat, Inc. - initial API and implementation
|
||||
#
|
||||
|
||||
- op: replace
|
||||
path: /spec/description
|
||||
value: |
|
||||
A collaborative Kubernetes-native development solution that delivers OpenShift workspaces and in-browser IDE for rapid cloud application development.
|
||||
This operator installs PostgreSQL, Plugin and Devfile registries, Dashboard, Gateway and the Eclipse Che server, as well as configures all these services.
|
||||
OpenShift OAuth is used directly for authentication. TLS mode is on.
|
||||
|
||||
## How to Install
|
||||
Press the **Install** button, choose the channel and the upgrade strategy, and wait for the **Installed** Operator status.
|
||||
When the operator is installed, create a new Custom Resource (CR) of Kind CheCluster (click the **Create New** button).
|
||||
The CR spec contains all defaults. You can start using Eclipse Che when the CR status is set to **Available**, and you see a URL to Eclipse Che.
|
||||
|
||||
## Defaults
|
||||
By default, the operator deploys Eclipse Che with:
|
||||
* 10Gi storage
|
||||
* Auto-generated passwords
|
||||
* Bundled PostgreSQL
|
||||
* Bundled Plugin and Devfile registries
|
||||
|
||||
Use `oc edit checluster/eclipse-che -n eclipse-che` to update Eclipse Che default installation options.
|
||||
See more in the [Installation guide](https://www.eclipse.org/che/docs/che-7/installation-guide/configuring-the-che-installation/).
|
||||
|
||||
### Certificates
|
||||
Operator uses a default router certificate to secure Eclipse Che routes.
|
||||
Follow the [guide](https://www.eclipse.org/che/docs/che-7/installation-guide/importing-untrusted-tls-certificates/)
|
||||
to import certificates into Eclipse Che.
|
||||
|
||||
|
|
@ -21,13 +21,3 @@ resources:
|
|||
- role_binding.yaml
|
||||
- cluster_role.yaml
|
||||
- cluster_rolebinding.yaml
|
||||
- leader_election_role.yaml
|
||||
- leader_election_role_binding.yaml
|
||||
# Comment the following 4 lines if you want to disable
|
||||
# the auth proxy (https://github.com/brancz/kube-rbac-proxy)
|
||||
# which protects your /metrics endpoint.
|
||||
# Todo "metrics proxy"
|
||||
# - auth_proxy_service.yaml
|
||||
# - auth_proxy_role.yaml
|
||||
# - auth_proxy_role_binding.yaml
|
||||
# - auth_proxy_client_clusterrole.yaml
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ apiVersion: v1
|
|||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: che-operator
|
||||
namespace: eclipse-che
|
||||
labels:
|
||||
app.kubernetes.io/name: che
|
||||
app.kubernetes.io/instance: che
|
||||
|
|
|
|||
|
|
@ -10,11 +10,6 @@
|
|||
# Red Hat, Inc. - initial API and implementation
|
||||
#
|
||||
|
||||
## Append samples you want in your CSV to this file as resources ##
|
||||
resources:
|
||||
- org.eclipse.che_v1_checluster.yaml
|
||||
# Uncomment it to enable sample for CheCluster with version v2alphav1
|
||||
# - org_v2alpha1_checluster.yaml
|
||||
# Uncomment to enable a devworkspace sample
|
||||
# - devworkspace_flattened_theia-nodejs.yaml
|
||||
#+kubebuilder:scaffold:manifestskustomizesamples
|
||||
- org_v1_checluster.yaml
|
||||
- org_v2_checluster.yaml
|
||||
|
|
|
|||
|
|
@ -1,105 +0,0 @@
|
|||
#
|
||||
# Copyright (c) 2019-2021 Red Hat, Inc.
|
||||
# This program and the accompanying materials are made
|
||||
# available under the terms of the Eclipse Public License 2.0
|
||||
# which is available at https://www.eclipse.org/legal/epl-2.0/
|
||||
#
|
||||
# SPDX-License-Identifier: EPL-2.0
|
||||
#
|
||||
# Contributors:
|
||||
# Red Hat, Inc. - initial API and implementation
|
||||
#
|
||||
|
||||
apiVersion: org.eclipse.che/v1
|
||||
kind: CheCluster
|
||||
metadata:
|
||||
name: eclipse-che
|
||||
spec:
|
||||
server:
|
||||
# A comma-separated list of ClusterRoles that will be assigned to Che ServiceAccount.
|
||||
# Be aware that the Che Operator has to already have all permissions in these ClusterRoles to grant them.
|
||||
cheClusterRoles: ''
|
||||
# Custom cluster role bound to the user for the Che workspaces.
|
||||
# The default roles are used when omitted or left blank.
|
||||
cheWorkspaceClusterRole: ''
|
||||
# When enabled, the certificate from `che-git-self-signed-cert` ConfigMap will be propagated to the Che components and provide particular configuration for Git.
|
||||
gitSelfSignedCert: false
|
||||
# URL (protocol+host name) of the proxy server. This drives the appropriate changes in the `JAVA_OPTS` and `https(s)_proxy` variables
|
||||
# in the Che server and workspaces containers.
|
||||
# Only use when configuring a proxy is required. Operator respects OpenShift cluster wide proxy configuration
|
||||
# and no additional configuration is required, but defining `proxyUrl` in a custom resource leads to overrides the cluster proxy configuration
|
||||
# with fields `proxyUrl`, `proxyPort`, `proxyUser` and `proxyPassword` from the custom resource.
|
||||
# See the doc https://docs.openshift.com/container-platform/4.4/networking/enable-cluster-wide-proxy.html. See also the `proxyPort` and `nonProxyHosts` fields.
|
||||
proxyURL: ''
|
||||
# Port of the proxy server. Only use when configuring a proxy is required. See also the `proxyURL` and `nonProxyHosts` fields.
|
||||
proxyPort: ''
|
||||
# The secret that contains `user` and `password` for a proxy server.
|
||||
# The secret must have `app.kubernetes.io/part-of=che.eclipse.org` label.
|
||||
proxySecret: ''
|
||||
# List of hosts that will be reached directly, bypassing the proxy.
|
||||
# Specify wild card domain use the following form `.<DOMAIN>` and `|` as delimiter, for example: `localhost|.my.host.com|123.42.12.32`
|
||||
# Only use when configuring a proxy is required. Operator respects OpenShift cluster wide proxy configuration and no additional configuration is required,
|
||||
# but defining `nonProxyHosts` in a custom resource leads to merging non proxy hosts lists from the cluster proxy configuration and ones defined in the custom resources.
|
||||
# See the doc https://docs.openshift.com/container-platform/4.4/networking/enable-cluster-wide-proxy.html. See also the `proxyURL` fields.
|
||||
nonProxyHosts: ''
|
||||
# Defines Kubernetes default namespace in which user's workspaces are created for a case when a user does not override it.
|
||||
# It's possible to use `<username>`, `<userid>` and `<workspaceid>` placeholders, such as che-workspace-<username>.
|
||||
# In that case, a new namespace will be created for each user or workspace.
|
||||
workspaceNamespaceDefault: "<username>-che"
|
||||
database:
|
||||
# Instructs the Operator on whether to deploy a dedicated database.
|
||||
# By default, a dedicated PostgreSQL database is deployed as part of the Che installation. When `externalDb` is `true`, no dedicated database will be deployed by the
|
||||
# Operator and you will need to provide connection details to the external DB you are about to use. See also all the fields starting with: `chePostgres`.
|
||||
externalDb: false
|
||||
# PostgreSQL Database host name that the Che server uses to connect to.
|
||||
# Defaults is `postgres`. Override this value ONLY when using an external database. See field `externalDb`.
|
||||
# In the default case it will be automatically set by the Operator.
|
||||
chePostgresHostName: ''
|
||||
# PostgreSQL Database port that the Che server uses to connect to. Defaults to 5432.
|
||||
# Override this value ONLY when using an external database. See field `externalDb`. In the default case it will be automatically set by the Operator.
|
||||
chePostgresPort: ''
|
||||
# The secret that contains PostgreSQL `user` and `password` that the Che server uses to connect to the DB.
|
||||
# The secret must have `app.kubernetes.io/part-of=che.eclipse.org` label.
|
||||
chePostgresSecret: ''
|
||||
# PostgreSQL database name that the Che server uses to connect to the DB. Defaults to `dbche`.
|
||||
chePostgresDb: ''
|
||||
storage:
|
||||
# Persistent volume claim strategy for the Che server. This Can be:`common` (all workspaces PVCs in one volume),
|
||||
# `per-workspace` (one PVC per workspace for all declared volumes) and `unique` (one PVC per declared volume).
|
||||
pvcStrategy: 'common'
|
||||
# Size of the persistent volume claim for workspaces.
|
||||
pvcClaimSize: '10Gi'
|
||||
# Instructs the Che server to start a special Pod to pre-create a sub-path in the Persistent Volumes.
|
||||
preCreateSubPaths: true
|
||||
# Storage class for the Persistent Volume Claim dedicated to the PostgreSQL database. When omitted or left blank, a default storage class is used.
|
||||
postgresPVCStorageClassName: ''
|
||||
# Storage class for the Persistent Volume Claims dedicated to the Che workspaces. When omitted or left blank, a default storage class is used.
|
||||
workspacePVCStorageClassName: ''
|
||||
auth:
|
||||
# Public URL of the Identity Provider server (Keycloak / RH-SSO server).
|
||||
identityProviderURL: ''
|
||||
# Name of the OpenShift `OAuthClient` resource used to setup identity federation on the OpenShift side. Auto-generated when left blank. See also the `OpenShiftoAuth` field.
|
||||
oAuthClientName: ''
|
||||
# Name of the secret set in the OpenShift `OAuthClient` resource used to setup identity federation on the OpenShift side. Auto-generated when left blank. See also the `OAuthClientName` field.
|
||||
oAuthSecret: ''
|
||||
k8s:
|
||||
# Global ingress domain for a Kubernetes cluster.
|
||||
ingressDomain: '192.168.99.101.nip.io'
|
||||
# Ingress class that will define the which controller will manage ingresses. Defaults to `nginx`.
|
||||
# NB: This drives the `kubernetes.io/ingress.class` annotation on Che-related ingresses.
|
||||
ingressClass: ''
|
||||
# Name of a secret that will be used to setup ingress TLS termination when TLS is enabled.
|
||||
# When the field is empty string, the default cluster certificate will be used.
|
||||
tlsSecretName: 'che-tls'
|
||||
# The FSGroup in which the Che Pod and workspace Pods containers runs in. Default value is `1724`.
|
||||
securityContextFsGroup: ''
|
||||
# ID of the user the Che Pod and workspace Pods containers run as. Default value is `1724`.
|
||||
securityContextRunAsUser: ''
|
||||
metrics:
|
||||
# Enables `metrics` the Che server endpoint.
|
||||
enable: true
|
||||
devWorkspace:
|
||||
# Deploys the DevWorkspace Operator in the cluster.
|
||||
# Does nothing when a matching version of the Operator is already installed.
|
||||
# Fails when a non-matching version of the Operator is already installed.
|
||||
enable: true
|
||||
|
|
@ -17,37 +17,17 @@ metadata:
|
|||
namespace: eclipse-che
|
||||
spec:
|
||||
server:
|
||||
cheClusterRoles: ''
|
||||
cheWorkspaceClusterRole: ''
|
||||
gitSelfSignedCert: false
|
||||
proxyURL: ''
|
||||
proxyPort: ''
|
||||
proxySecret: ''
|
||||
nonProxyHosts: ''
|
||||
workspaceNamespaceDefault: "<username>-che"
|
||||
database:
|
||||
externalDb: false
|
||||
chePostgresHostName: ''
|
||||
chePostgresPort: ''
|
||||
chePostgresSecret: ''
|
||||
chePostgresDb: ''
|
||||
storage:
|
||||
pvcStrategy: 'common'
|
||||
pvcClaimSize: '10Gi'
|
||||
preCreateSubPaths: true
|
||||
postgresPVCStorageClassName: ''
|
||||
workspacePVCStorageClassName: ''
|
||||
auth:
|
||||
identityProviderURL: ''
|
||||
oAuthClientName: ''
|
||||
oAuthSecret: ''
|
||||
k8s:
|
||||
ingressDomain: '{{ .Values.k8s.ingressDomain }}'
|
||||
ingressClass: ''
|
||||
tlsSecretName: 'che-tls'
|
||||
securityContextFsGroup: ''
|
||||
securityContextRunAsUser: ''
|
||||
ingressDomain:
|
||||
tlsSecretName:
|
||||
metrics:
|
||||
enable: true
|
||||
devWorkspace:
|
||||
enable: true
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
#
|
||||
# Copyright (c) 2019-2021 Red Hat, Inc.
|
||||
# This program and the accompanying materials are made
|
||||
# available under the terms of the Eclipse Public License 2.0
|
||||
# which is available at https://www.eclipse.org/legal/epl-2.0/
|
||||
#
|
||||
# SPDX-License-Identifier: EPL-2.0
|
||||
#
|
||||
# Contributors:
|
||||
# Red Hat, Inc. - initial API and implementation
|
||||
#
|
||||
|
||||
apiVersion: org.eclipse.che/v2
|
||||
kind: CheCluster
|
||||
metadata:
|
||||
name: eclipse-che
|
||||
namespace: eclipse-che
|
||||
spec:
|
||||
devEnvironments:
|
||||
defaultNamespace:
|
||||
template: '<username>-che'
|
||||
storage:
|
||||
pvcStrategy: 'common'
|
||||
components:
|
||||
database:
|
||||
externalDb: false
|
||||
metrics:
|
||||
enable: true
|
||||
networking:
|
||||
domain: ''
|
||||
tlsSecretName: ''
|
||||
auth:
|
||||
identityProviderURL: ''
|
||||
oAuthClientName: ''
|
||||
oAuthSecret: ''
|
||||
|
|
@ -12,6 +12,7 @@
|
|||
|
||||
resources:
|
||||
- bases/config.yaml
|
||||
|
||||
patchesJson6902:
|
||||
- path: patches/basic.config.yaml
|
||||
target:
|
||||
|
|
@ -25,4 +26,3 @@ patchesJson6902:
|
|||
version: v1alpha3
|
||||
kind: Configuration
|
||||
name: config
|
||||
#+kubebuilder:scaffold:patchesJson6902
|
||||
|
|
|
|||
|
|
@ -0,0 +1,17 @@
|
|||
#
|
||||
# Copyright (c) 2019-2021 Red Hat, Inc.
|
||||
# This program and the accompanying materials are made
|
||||
# available under the terms of the Eclipse Public License 2.0
|
||||
# which is available at https://www.eclipse.org/legal/epl-2.0/
|
||||
#
|
||||
# SPDX-License-Identifier: EPL-2.0
|
||||
#
|
||||
# Contributors:
|
||||
# Red Hat, Inc. - initial API and implementation
|
||||
#
|
||||
|
||||
resources:
|
||||
- service.yaml
|
||||
|
||||
configurations:
|
||||
- kustomizeconfig.yaml
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
#
|
||||
# Copyright (c) 2019-2021 Red Hat, Inc.
|
||||
# This program and the accompanying materials are made
|
||||
# available under the terms of the Eclipse Public License 2.0
|
||||
# which is available at https://www.eclipse.org/legal/epl-2.0/
|
||||
#
|
||||
# SPDX-License-Identifier: EPL-2.0
|
||||
#
|
||||
# Contributors:
|
||||
# Red Hat, Inc. - initial API and implementation
|
||||
#
|
||||
|
||||
# the following config is for teaching kustomize where to look at when substituting vars.
|
||||
# It requires kustomize v2.1.0 or newer to work properly.
|
||||
nameReference:
|
||||
- kind: Service
|
||||
version: v1
|
||||
fieldSpecs:
|
||||
- kind: MutatingWebhookConfiguration
|
||||
group: admissionregistration.k8s.io
|
||||
path: webhooks/clientConfig/service/name
|
||||
- kind: ValidatingWebhookConfiguration
|
||||
group: admissionregistration.k8s.io
|
||||
path: webhooks/clientConfig/service/name
|
||||
|
||||
namespace:
|
||||
- kind: MutatingWebhookConfiguration
|
||||
group: admissionregistration.k8s.io
|
||||
path: webhooks/clientConfig/service/namespace
|
||||
create: true
|
||||
- kind: ValidatingWebhookConfiguration
|
||||
group: admissionregistration.k8s.io
|
||||
path: webhooks/clientConfig/service/namespace
|
||||
create: true
|
||||
|
||||
varReference:
|
||||
- path: metadata/annotations
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
#
|
||||
# Copyright (c) 2019-2022 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
|
||||
#
|
||||
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: che-operator-service
|
||||
namespace: eclipse-che
|
||||
labels:
|
||||
app.kubernetes.io/name: che
|
||||
app.kubernetes.io/instance: che
|
||||
app.kubernetes.io/part-of: che.eclipse.org
|
||||
app.kubernetes.io/component: che-operator
|
||||
spec:
|
||||
ports:
|
||||
- port: 443
|
||||
targetPort: 9443
|
||||
selector:
|
||||
app: che-operator
|
||||
|
|
@ -15,6 +15,10 @@ package che
|
|||
import (
|
||||
"context"
|
||||
|
||||
"github.com/devfile/devworkspace-operator/pkg/infrastructure"
|
||||
"github.com/eclipse-che/che-operator/pkg/common/chetypes"
|
||||
"github.com/eclipse-che/che-operator/pkg/common/test"
|
||||
"github.com/eclipse-che/che-operator/pkg/common/utils"
|
||||
"github.com/eclipse-che/che-operator/pkg/deploy"
|
||||
"github.com/eclipse-che/che-operator/pkg/deploy/consolelink"
|
||||
"github.com/eclipse-che/che-operator/pkg/deploy/dashboard"
|
||||
|
|
@ -30,7 +34,6 @@ import (
|
|||
"github.com/eclipse-che/che-operator/pkg/deploy/server"
|
||||
"github.com/eclipse-che/che-operator/pkg/deploy/tls"
|
||||
|
||||
"github.com/eclipse-che/che-operator/pkg/util"
|
||||
"github.com/go-logr/logr"
|
||||
routev1 "github.com/openshift/api/route/v1"
|
||||
"github.com/sirupsen/logrus"
|
||||
|
|
@ -47,7 +50,7 @@ import (
|
|||
"sigs.k8s.io/controller-runtime/pkg/predicate"
|
||||
"sigs.k8s.io/controller-runtime/pkg/source"
|
||||
|
||||
orgv1 "github.com/eclipse-che/che-operator/api/v1"
|
||||
chev2 "github.com/eclipse-che/che-operator/api/v2"
|
||||
networking "k8s.io/api/networking/v1"
|
||||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
)
|
||||
|
|
@ -85,7 +88,7 @@ func NewReconciler(
|
|||
reconcileManager := deploy.NewReconcileManager()
|
||||
|
||||
// order does matter
|
||||
if !util.IsTestMode() {
|
||||
if !test.IsTestMode() {
|
||||
reconcileManager.RegisterReconciler(migration.NewMigrator())
|
||||
reconcileManager.RegisterReconciler(NewCheClusterValidator())
|
||||
}
|
||||
|
|
@ -102,7 +105,7 @@ func NewReconciler(
|
|||
// resources since che host is used for dashboard deployment and che config map
|
||||
reconcileManager.RegisterReconciler(server.NewCheHostReconciler())
|
||||
reconcileManager.RegisterReconciler(postgres.NewPostgresReconciler())
|
||||
if util.IsOpenShift {
|
||||
if infrastructure.IsOpenShift() {
|
||||
reconcileManager.RegisterReconciler(identityprovider.NewIdentityProviderReconciler())
|
||||
}
|
||||
reconcileManager.RegisterReconciler(devfileregistry.NewDevfileRegistryReconciler())
|
||||
|
|
@ -111,7 +114,7 @@ func NewReconciler(
|
|||
reconcileManager.RegisterReconciler(gateway.NewGatewayReconciler())
|
||||
reconcileManager.RegisterReconciler(server.NewCheServerReconciler())
|
||||
|
||||
if util.IsOpenShift4 {
|
||||
if infrastructure.IsOpenShift() {
|
||||
reconcileManager.RegisterReconciler(consolelink.NewConsoleLinkReconciler())
|
||||
}
|
||||
|
||||
|
|
@ -129,8 +132,6 @@ func NewReconciler(
|
|||
|
||||
// SetupWithManager sets up the controller with the Manager.
|
||||
func (r *CheClusterReconciler) SetupWithManager(mgr ctrl.Manager) error {
|
||||
isOpenShift := util.IsOpenShift
|
||||
|
||||
onAllExceptGenericEventsPredicate := predicate.Funcs{
|
||||
UpdateFunc: func(evt event.UpdateEvent) bool {
|
||||
return true
|
||||
|
|
@ -164,39 +165,39 @@ func (r *CheClusterReconciler) SetupWithManager(mgr ctrl.Manager) error {
|
|||
|
||||
controllerBuilder := ctrl.NewControllerManagedBy(mgr).
|
||||
// Watch for changes to primary resource CheCluster
|
||||
Watches(&source.Kind{Type: &orgv1.CheCluster{}}, &handler.EnqueueRequestForObject{}).
|
||||
Watches(&source.Kind{Type: &chev2.CheCluster{}}, &handler.EnqueueRequestForObject{}).
|
||||
// Watch for changes to secondary resources and requeue the owner CheCluster
|
||||
Watches(&source.Kind{Type: &corev1.Service{}}, &handler.EnqueueRequestForOwner{
|
||||
IsController: true,
|
||||
OwnerType: &orgv1.CheCluster{},
|
||||
OwnerType: &chev2.CheCluster{},
|
||||
}).
|
||||
Watches(&source.Kind{Type: &corev1.Secret{}}, &handler.EnqueueRequestForOwner{
|
||||
IsController: true,
|
||||
OwnerType: &orgv1.CheCluster{},
|
||||
OwnerType: &chev2.CheCluster{},
|
||||
}).
|
||||
Watches(&source.Kind{Type: &corev1.ConfigMap{}}, &handler.EnqueueRequestForOwner{
|
||||
IsController: true,
|
||||
OwnerType: &orgv1.CheCluster{},
|
||||
OwnerType: &chev2.CheCluster{},
|
||||
}).
|
||||
Watches(&source.Kind{Type: &rbacv1.Role{}}, &handler.EnqueueRequestForOwner{
|
||||
IsController: true,
|
||||
OwnerType: &orgv1.CheCluster{},
|
||||
OwnerType: &chev2.CheCluster{},
|
||||
}).
|
||||
Watches(&source.Kind{Type: &rbacv1.RoleBinding{}}, &handler.EnqueueRequestForOwner{
|
||||
IsController: true,
|
||||
OwnerType: &orgv1.CheCluster{},
|
||||
OwnerType: &chev2.CheCluster{},
|
||||
}).
|
||||
Watches(&source.Kind{Type: &corev1.ServiceAccount{}}, &handler.EnqueueRequestForOwner{
|
||||
IsController: true,
|
||||
OwnerType: &orgv1.CheCluster{},
|
||||
OwnerType: &chev2.CheCluster{},
|
||||
}).
|
||||
Watches(&source.Kind{Type: &appsv1.Deployment{}}, &handler.EnqueueRequestForOwner{
|
||||
IsController: true,
|
||||
OwnerType: &orgv1.CheCluster{},
|
||||
OwnerType: &chev2.CheCluster{},
|
||||
}).
|
||||
Watches(&source.Kind{Type: &corev1.PersistentVolumeClaim{}}, &handler.EnqueueRequestForOwner{
|
||||
IsController: true,
|
||||
OwnerType: &orgv1.CheCluster{},
|
||||
OwnerType: &chev2.CheCluster{},
|
||||
}).
|
||||
Watches(&source.Kind{Type: &corev1.ConfigMap{}},
|
||||
handler.EnqueueRequestsFromMapFunc(toTrustedBundleConfigMapRequestMapper),
|
||||
|
|
@ -211,24 +212,24 @@ func (r *CheClusterReconciler) SetupWithManager(mgr ctrl.Manager) error {
|
|||
builder.WithPredicates(onAllExceptGenericEventsPredicate),
|
||||
)
|
||||
|
||||
if isOpenShift {
|
||||
if infrastructure.IsOpenShift() {
|
||||
controllerBuilder = controllerBuilder.Watches(&source.Kind{Type: &routev1.Route{}}, &handler.EnqueueRequestForOwner{
|
||||
IsController: true,
|
||||
OwnerType: &orgv1.CheCluster{},
|
||||
OwnerType: &chev2.CheCluster{},
|
||||
})
|
||||
} else {
|
||||
controllerBuilder = controllerBuilder.Watches(&source.Kind{Type: &networking.Ingress{}}, &handler.EnqueueRequestForOwner{
|
||||
IsController: true,
|
||||
OwnerType: &orgv1.CheCluster{},
|
||||
OwnerType: &chev2.CheCluster{},
|
||||
})
|
||||
}
|
||||
|
||||
if r.namespace != "" {
|
||||
controllerBuilder = controllerBuilder.WithEventFilter(util.InNamespaceEventFilter(r.namespace))
|
||||
controllerBuilder = controllerBuilder.WithEventFilter(utils.InNamespaceEventFilter(r.namespace))
|
||||
}
|
||||
|
||||
return controllerBuilder.
|
||||
For(&orgv1.CheCluster{}).
|
||||
For(&chev2.CheCluster{}).
|
||||
Complete(r)
|
||||
}
|
||||
|
||||
|
|
@ -240,7 +241,7 @@ func (r *CheClusterReconciler) SetupWithManager(mgr ctrl.Manager) error {
|
|||
func (r *CheClusterReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
|
||||
_ = r.Log.WithValues("checluster", req.NamespacedName)
|
||||
|
||||
clusterAPI := deploy.ClusterAPI{
|
||||
clusterAPI := chetypes.ClusterAPI{
|
||||
Client: r.client,
|
||||
NonCachingClient: r.nonCachedClient,
|
||||
DiscoveryClient: r.discoveryClient,
|
||||
|
|
@ -262,7 +263,7 @@ func (r *CheClusterReconciler) Reconcile(ctx context.Context, req ctrl.Request)
|
|||
return ctrl.Result{}, err
|
||||
}
|
||||
|
||||
deployContext := &deploy.DeployContext{
|
||||
deployContext := &chetypes.DeployContext{
|
||||
ClusterAPI: clusterAPI,
|
||||
CheCluster: checluster,
|
||||
}
|
||||
|
|
@ -292,13 +293,16 @@ func (r *CheClusterReconciler) Reconcile(ctx context.Context, req ctrl.Request)
|
|||
return ctrl.Result{}, nil
|
||||
}
|
||||
} else {
|
||||
deployContext.CheCluster.Status.ChePhase = chev2.ClusterPhasePendingDeletion
|
||||
_ = deploy.UpdateCheCRStatus(deployContext, "ChePhase", chev2.ClusterPhasePendingDeletion)
|
||||
|
||||
done := r.reconcileManager.FinalizeAll(deployContext)
|
||||
return ctrl.Result{Requeue: !done}, nil
|
||||
}
|
||||
}
|
||||
|
||||
func (r *CheClusterReconciler) GetCR(request ctrl.Request) (*orgv1.CheCluster, error) {
|
||||
checluster := &orgv1.CheCluster{}
|
||||
func (r *CheClusterReconciler) GetCR(request ctrl.Request) (*chev2.CheCluster, error) {
|
||||
checluster := &chev2.CheCluster{}
|
||||
err := r.client.Get(context.TODO(), request.NamespacedName, checluster)
|
||||
return checluster, err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,14 +16,14 @@ import (
|
|||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/devfile/devworkspace-operator/pkg/infrastructure"
|
||||
"github.com/eclipse-che/che-operator/pkg/common/chetypes"
|
||||
"github.com/eclipse-che/che-operator/pkg/deploy"
|
||||
"github.com/eclipse-che/che-operator/pkg/util"
|
||||
"sigs.k8s.io/controller-runtime/pkg/reconcile"
|
||||
)
|
||||
|
||||
const (
|
||||
NamespaceStrategyErrorMessage = "Namespace strategies other than 'per user' is not supported anymore. Using the <username> or <userid> placeholder is required in the 'spec.server.workspaceNamespaceDefault' field. The current value is: %s"
|
||||
AuthenticationModeErrorMessage = "Single user authentication mode is not supported anymore. To backup your data you can commit workspace configuration to an SCM server and use factories to restore it in multi user mode. To switch to multi user authentication mode set 'spec.server.customCheProperties.CHE_MULTIUSER' to 'true' in %s CheCluster custom resource. Switching to multi user authentication mode without backing up your data will cause data loss."
|
||||
NamespaceStrategyErrorMessage = "Namespace strategies other than 'per user' is not supported anymore. Using the <username> or <userid> placeholder is required in the 'spec.server.workspaceNamespaceDefault' field. The current value is: %s"
|
||||
)
|
||||
|
||||
// CheClusterValidator checks CheCluster CR configuration.
|
||||
|
|
@ -39,25 +39,21 @@ func NewCheClusterValidator() *CheClusterValidator {
|
|||
return &CheClusterValidator{}
|
||||
}
|
||||
|
||||
func (v *CheClusterValidator) Reconcile(ctx *deploy.DeployContext) (reconcile.Result, bool, error) {
|
||||
if !util.IsOpenShift {
|
||||
if ctx.CheCluster.Spec.K8s.IngressDomain == "" {
|
||||
return reconcile.Result{}, false, fmt.Errorf("Required field \"spec.K8s.IngressDomain\" is not set")
|
||||
func (v *CheClusterValidator) Reconcile(ctx *chetypes.DeployContext) (reconcile.Result, bool, error) {
|
||||
if !infrastructure.IsOpenShift() {
|
||||
if ctx.CheCluster.Spec.Networking.Domain == "" {
|
||||
return reconcile.Result{}, false, fmt.Errorf("Required field \"spec.networking.domain\" is not set")
|
||||
}
|
||||
}
|
||||
|
||||
workspaceNamespaceDefault := deploy.GetWorkspaceNamespaceDefault(ctx.CheCluster)
|
||||
workspaceNamespaceDefault := ctx.CheCluster.GetDefaultNamespace()
|
||||
if strings.Index(workspaceNamespaceDefault, "<username>") == -1 && strings.Index(workspaceNamespaceDefault, "<userid>") == -1 {
|
||||
return reconcile.Result{}, false, fmt.Errorf(NamespaceStrategyErrorMessage, workspaceNamespaceDefault)
|
||||
}
|
||||
|
||||
if !util.IsCheMultiUser(ctx.CheCluster) {
|
||||
return reconcile.Result{}, false, fmt.Errorf(AuthenticationModeErrorMessage, ctx.CheCluster.Name)
|
||||
}
|
||||
|
||||
return reconcile.Result{}, true, nil
|
||||
}
|
||||
|
||||
func (v *CheClusterValidator) Finalize(ctx *deploy.DeployContext) bool {
|
||||
func (v *CheClusterValidator) Finalize(ctx *chetypes.DeployContext) bool {
|
||||
return true
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,9 +13,9 @@
|
|||
package che
|
||||
|
||||
import (
|
||||
"github.com/eclipse-che/che-operator/pkg/common/constants"
|
||||
"github.com/eclipse-che/che-operator/pkg/deploy"
|
||||
"github.com/eclipse-che/che-operator/pkg/deploy/tls"
|
||||
"github.com/eclipse-che/che-operator/pkg/util"
|
||||
"github.com/sirupsen/logrus"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
ctrl "sigs.k8s.io/controller-runtime"
|
||||
|
|
@ -29,7 +29,7 @@ func IsTrustedBundleConfigMap(cl client.Client, watchNamespace string, obj clien
|
|||
return false, ctrl.Request{}
|
||||
}
|
||||
|
||||
checluster, num, _ := util.FindCheClusterCRInNamespace(cl, watchNamespace)
|
||||
checluster, num, _ := deploy.FindCheClusterCRInNamespace(cl, watchNamespace)
|
||||
if num != 1 {
|
||||
if num > 1 {
|
||||
logrus.Warn("More than one checluster Custom Resource found.")
|
||||
|
|
@ -42,22 +42,16 @@ func IsTrustedBundleConfigMap(cl client.Client, watchNamespace string, obj clien
|
|||
return false, ctrl.Request{}
|
||||
}
|
||||
|
||||
// Check if config map is the config map from CR
|
||||
trustStoreConfigMap := util.GetValue(checluster.Spec.Server.ServerTrustStoreConfigMapName, deploy.DefaultServerTrustStoreConfigMapName)
|
||||
if trustStoreConfigMap != obj.GetName() {
|
||||
// No, it is not form CR
|
||||
// Check for component
|
||||
if value, exists := obj.GetLabels()[constants.KubernetesComponentLabelKey]; !exists || value != tls.CheCACertsConfigMapLabelValue {
|
||||
// Labels do not match
|
||||
return false, ctrl.Request{}
|
||||
}
|
||||
|
||||
// Check for component
|
||||
if value, exists := obj.GetLabels()[deploy.KubernetesComponentLabelKey]; !exists || value != tls.CheCACertsConfigMapLabelValue {
|
||||
// Labels do not match
|
||||
return false, ctrl.Request{}
|
||||
}
|
||||
|
||||
// Check for part-of
|
||||
if value, exists := obj.GetLabels()[deploy.KubernetesPartOfLabelKey]; !exists || value != deploy.CheEclipseOrg {
|
||||
// ignore not matched labels
|
||||
return false, ctrl.Request{}
|
||||
}
|
||||
// Check for part-of
|
||||
if value, exists := obj.GetLabels()[constants.KubernetesPartOfLabelKey]; !exists || value != constants.CheEclipseOrg {
|
||||
// ignore not matched labels
|
||||
return false, ctrl.Request{}
|
||||
}
|
||||
|
||||
return true, ctrl.Request{
|
||||
|
|
@ -77,7 +71,7 @@ func IsEclipseCheRelatedObj(cl client.Client, watchNamespace string, obj client.
|
|||
return false, ctrl.Request{}
|
||||
}
|
||||
|
||||
checluster, num, _ := util.FindCheClusterCRInNamespace(cl, watchNamespace)
|
||||
checluster, num, _ := deploy.FindCheClusterCRInNamespace(cl, watchNamespace)
|
||||
if num != 1 {
|
||||
if num > 1 {
|
||||
logrus.Warn("More than one checluster Custom Resource found.")
|
||||
|
|
@ -91,7 +85,7 @@ func IsEclipseCheRelatedObj(cl client.Client, watchNamespace string, obj client.
|
|||
}
|
||||
|
||||
// Check for part-of label
|
||||
if value, exists := obj.GetLabels()[deploy.KubernetesPartOfLabelKey]; !exists || value != deploy.CheEclipseOrg {
|
||||
if value, exists := obj.GetLabels()[constants.KubernetesPartOfLabelKey]; !exists || value != constants.CheEclipseOrg {
|
||||
return false, ctrl.Request{}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -13,11 +13,11 @@
|
|||
package che
|
||||
|
||||
import (
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
orgv1 "github.com/eclipse-che/che-operator/api/v1"
|
||||
"github.com/eclipse-che/che-operator/pkg/deploy"
|
||||
chev2 "github.com/eclipse-che/che-operator/api/v2"
|
||||
defaults "github.com/eclipse-che/che-operator/pkg/common/operator-defaults"
|
||||
"github.com/eclipse-che/che-operator/pkg/common/test"
|
||||
"github.com/stretchr/testify/assert"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
|
|
@ -28,7 +28,7 @@ func TestIsTrustedBundleConfigMap(t *testing.T) {
|
|||
type testCase struct {
|
||||
name string
|
||||
initObjects []runtime.Object
|
||||
checluster *orgv1.CheCluster
|
||||
checluster *chev2.CheCluster
|
||||
objNamespace string
|
||||
objLabels map[string]string
|
||||
watchNamespace string
|
||||
|
|
@ -45,7 +45,7 @@ func TestIsTrustedBundleConfigMap(t *testing.T) {
|
|||
Labels: map[string]string{
|
||||
"app.kubernetes.io/part-of": "che.eclipse.org",
|
||||
"app.kubernetes.io/component": "ca-bundle",
|
||||
"app.kubernetes.io/instance": os.Getenv("CHE_FLAVOR"),
|
||||
"app.kubernetes.io/instance": defaults.GetCheFlavor(),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
|
@ -73,22 +73,6 @@ func TestIsTrustedBundleConfigMap(t *testing.T) {
|
|||
watchNamespace: "eclipse-che",
|
||||
expectedIsEclipseCheObj: false,
|
||||
},
|
||||
{
|
||||
name: "Object in 'eclipse-che' namespace, not ca-bundle component, but trusted configmap",
|
||||
initObjects: []runtime.Object{},
|
||||
checluster: &orgv1.CheCluster{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "eclipse-che", Namespace: "eclipse-che"},
|
||||
Spec: orgv1.CheClusterSpec{
|
||||
Server: orgv1.CheClusterSpecServer{
|
||||
ServerTrustStoreConfigMapName: "test",
|
||||
},
|
||||
},
|
||||
},
|
||||
objLabels: map[string]string{},
|
||||
objNamespace: "eclipse-che",
|
||||
watchNamespace: "eclipse-che",
|
||||
expectedIsEclipseCheObj: true,
|
||||
},
|
||||
{
|
||||
name: "Object in another namespace than 'eclipse-che'",
|
||||
initObjects: []runtime.Object{},
|
||||
|
|
@ -100,7 +84,7 @@ func TestIsTrustedBundleConfigMap(t *testing.T) {
|
|||
name: "Object in 'eclipse-che' namespace, several checluster CR",
|
||||
initObjects: []runtime.Object{
|
||||
// checluster CR in `default` namespace
|
||||
&orgv1.CheCluster{ObjectMeta: metav1.ObjectMeta{Name: "eclipse-che", Namespace: "default"}},
|
||||
&chev2.CheCluster{ObjectMeta: metav1.ObjectMeta{Name: "eclipse-che", Namespace: "default"}},
|
||||
},
|
||||
objNamespace: "eclipse-che",
|
||||
watchNamespace: "eclipse-che",
|
||||
|
|
@ -131,7 +115,7 @@ func TestIsTrustedBundleConfigMap(t *testing.T) {
|
|||
|
||||
for _, testCase := range testCases {
|
||||
t.Run(testCase.name, func(t *testing.T) {
|
||||
deployContext := deploy.GetTestDeployContext(testCase.checluster, testCase.initObjects)
|
||||
deployContext := test.GetDeployContext(testCase.checluster, testCase.initObjects)
|
||||
|
||||
newTestObject := testObject.DeepCopy()
|
||||
newTestObject.ObjectMeta.Namespace = testCase.objNamespace
|
||||
|
|
@ -168,7 +152,7 @@ func TestIsEclipseCheRelatedObj(t *testing.T) {
|
|||
Name: "test",
|
||||
Labels: map[string]string{
|
||||
"app.kubernetes.io/part-of": "che.eclipse.org",
|
||||
"app.kubernetes.io/instance": os.Getenv("CHE_FLAVOR"),
|
||||
"app.kubernetes.io/instance": defaults.GetCheFlavor(),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
|
@ -199,7 +183,7 @@ func TestIsEclipseCheRelatedObj(t *testing.T) {
|
|||
name: "Object in 'eclipse-che' namespace, several checluster CR",
|
||||
initObjects: []runtime.Object{
|
||||
// checluster CR in `default` namespace
|
||||
&orgv1.CheCluster{ObjectMeta: metav1.ObjectMeta{Name: "eclipse-che", Namespace: "default"}},
|
||||
&chev2.CheCluster{ObjectMeta: metav1.ObjectMeta{Name: "eclipse-che", Namespace: "default"}},
|
||||
},
|
||||
objNamespace: "eclipse-che",
|
||||
watchNamespace: "eclipse-che",
|
||||
|
|
@ -230,7 +214,7 @@ func TestIsEclipseCheRelatedObj(t *testing.T) {
|
|||
|
||||
for _, testCase := range testCases {
|
||||
t.Run(testCase.name, func(t *testing.T) {
|
||||
deployContext := deploy.GetTestDeployContext(nil, testCase.initObjects)
|
||||
deployContext := test.GetDeployContext(nil, testCase.initObjects)
|
||||
|
||||
testObject.ObjectMeta.Namespace = testCase.objNamespace
|
||||
isEclipseCheObj, req := IsEclipseCheRelatedObj(deployContext.ClusterAPI.NonCachingClient, testCase.watchNamespace, testObject)
|
||||
|
|
|
|||
|
|
@ -12,12 +12,14 @@
|
|||
package che
|
||||
|
||||
import (
|
||||
"github.com/eclipse-che/che-operator/pkg/deploy"
|
||||
"github.com/devfile/devworkspace-operator/pkg/infrastructure"
|
||||
defaults "github.com/eclipse-che/che-operator/pkg/common/operator-defaults"
|
||||
"github.com/eclipse-che/che-operator/pkg/common/test"
|
||||
)
|
||||
|
||||
func init() {
|
||||
err := deploy.InitTestDefaultsFromDeployment("../../config/manager/manager.yaml")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
test.EnableTestMode()
|
||||
|
||||
infrastructure.InitializeForTesting(infrastructure.OpenShiftv4)
|
||||
defaults.Initialize("../../config/manager/manager.yaml")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,61 +0,0 @@
|
|||
//
|
||||
// Copyright (c) 2019-2021 Red Hat, Inc.
|
||||
// This program and the accompanying materials are made
|
||||
// available under the terms of the Eclipse Public License 2.0
|
||||
// which is available at https://www.eclipse.org/legal/epl-2.0/
|
||||
//
|
||||
// SPDX-License-Identifier: EPL-2.0
|
||||
//
|
||||
// Contributors:
|
||||
// Red Hat, Inc. - initial API and implementation
|
||||
//
|
||||
|
||||
package che
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/eclipse-che/che-operator/pkg/util"
|
||||
authorizationv1 "k8s.io/api/authorization/v1"
|
||||
rbac "k8s.io/api/rbac/v1"
|
||||
)
|
||||
|
||||
type PermissionChecker interface {
|
||||
GetNotPermittedPolicyRules(policies []rbac.PolicyRule, namespace string) ([]rbac.PolicyRule, error)
|
||||
}
|
||||
|
||||
type K8sApiPermissionChecker struct {
|
||||
}
|
||||
|
||||
func (pc *K8sApiPermissionChecker) GetNotPermittedPolicyRules(policies []rbac.PolicyRule, namespace string) ([]rbac.PolicyRule, error) {
|
||||
var notPermittedPolicyRules []rbac.PolicyRule = []rbac.PolicyRule{}
|
||||
for _, policy := range policies {
|
||||
for _, apiGroup := range policy.APIGroups {
|
||||
for _, verb := range policy.Verbs {
|
||||
for _, resource := range policy.Resources {
|
||||
resourceAttribute := &authorizationv1.ResourceAttributes{
|
||||
Namespace: namespace,
|
||||
Verb: verb,
|
||||
Group: apiGroup,
|
||||
Resource: resource,
|
||||
}
|
||||
ok, err := util.K8sclient.IsResourceOperationPermitted(resourceAttribute)
|
||||
if err != nil {
|
||||
return notPermittedPolicyRules, fmt.Errorf("failed to check policy rule: %v", policy)
|
||||
}
|
||||
if !ok {
|
||||
if len(notPermittedPolicyRules) == 0 {
|
||||
notPermittedPolicyRules = append(notPermittedPolicyRules, policy)
|
||||
} else {
|
||||
lastNotPermittedRule := notPermittedPolicyRules[len(notPermittedPolicyRules)-1]
|
||||
if lastNotPermittedRule.Resources[0] != policy.Resources[0] && lastNotPermittedRule.APIGroups[0] != policy.APIGroups[0] {
|
||||
notPermittedPolicyRules = append(notPermittedPolicyRules, policy)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return notPermittedPolicyRules, nil
|
||||
}
|
||||
|
|
@ -12,21 +12,21 @@
|
|||
package che
|
||||
|
||||
import (
|
||||
"github.com/devfile/devworkspace-operator/pkg/infrastructure"
|
||||
"github.com/eclipse-che/che-operator/pkg/common/chetypes"
|
||||
"github.com/eclipse-che/che-operator/pkg/deploy"
|
||||
"github.com/eclipse-che/che-operator/pkg/util"
|
||||
configv1 "github.com/openshift/api/config/v1"
|
||||
)
|
||||
|
||||
func GetProxyConfiguration(deployContext *deploy.DeployContext) (*deploy.Proxy, error) {
|
||||
// OpenShift 4.x
|
||||
if util.IsOpenShift4 {
|
||||
func GetProxyConfiguration(deployContext *chetypes.DeployContext) (*chetypes.Proxy, error) {
|
||||
if infrastructure.IsOpenShift() {
|
||||
clusterProxy := &configv1.Proxy{}
|
||||
exists, err := deploy.GetClusterObject(deployContext, "cluster", clusterProxy)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
clusterWideProxyConf := &deploy.Proxy{}
|
||||
clusterWideProxyConf := &chetypes.Proxy{}
|
||||
if exists {
|
||||
clusterWideProxyConf, err = deploy.ReadClusterWideProxyConfiguration(clusterProxy)
|
||||
if err != nil {
|
||||
|
|
@ -34,7 +34,7 @@ func GetProxyConfiguration(deployContext *deploy.DeployContext) (*deploy.Proxy,
|
|||
}
|
||||
}
|
||||
|
||||
cheClusterProxyConf, err := deploy.ReadCheClusterProxyConfiguration(deployContext.CheCluster)
|
||||
cheClusterProxyConf, err := deploy.ReadCheClusterProxyConfiguration(deployContext)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -57,7 +57,7 @@ func GetProxyConfiguration(deployContext *deploy.DeployContext) (*deploy.Proxy,
|
|||
}
|
||||
|
||||
// OpenShift 3.x and k8s
|
||||
cheClusterProxyConf, err := deploy.ReadCheClusterProxyConfiguration(deployContext.CheCluster)
|
||||
cheClusterProxyConf, err := deploy.ReadCheClusterProxyConfiguration(deployContext)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,9 +16,9 @@ import (
|
|||
"reflect"
|
||||
"testing"
|
||||
|
||||
orgv1 "github.com/eclipse-che/che-operator/api/v1"
|
||||
"github.com/eclipse-che/che-operator/pkg/deploy"
|
||||
"github.com/eclipse-che/che-operator/pkg/util"
|
||||
"github.com/devfile/devworkspace-operator/pkg/infrastructure"
|
||||
chev2 "github.com/eclipse-che/che-operator/api/v2"
|
||||
"github.com/eclipse-che/che-operator/pkg/common/chetypes"
|
||||
"github.com/google/go-cmp/cmp"
|
||||
configv1 "github.com/openshift/api/config/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
|
|
@ -34,52 +34,56 @@ import (
|
|||
func TestReadProxyConfiguration(t *testing.T) {
|
||||
type testCase struct {
|
||||
name string
|
||||
openShiftVersion string
|
||||
cheCluster *orgv1.CheCluster
|
||||
isOpenShift bool
|
||||
cheCluster *chev2.CheCluster
|
||||
clusterProxy *configv1.Proxy
|
||||
initObjects []runtime.Object
|
||||
expectedProxyConf *deploy.Proxy
|
||||
expectedProxyConf *chetypes.Proxy
|
||||
}
|
||||
|
||||
testCases := []testCase{
|
||||
{
|
||||
name: "Test no proxy configured",
|
||||
openShiftVersion: "4",
|
||||
name: "Test no proxy configured",
|
||||
isOpenShift: true,
|
||||
clusterProxy: &configv1.Proxy{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "cluster",
|
||||
},
|
||||
},
|
||||
cheCluster: &orgv1.CheCluster{
|
||||
cheCluster: &chev2.CheCluster{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Namespace: "eclipse-che",
|
||||
},
|
||||
},
|
||||
initObjects: []runtime.Object{},
|
||||
expectedProxyConf: &deploy.Proxy{},
|
||||
expectedProxyConf: &chetypes.Proxy{},
|
||||
},
|
||||
{
|
||||
name: "Test checluster proxy configured, OpenShift 4.x",
|
||||
openShiftVersion: "4",
|
||||
name: "Test checluster proxy configured, OpenShift 4.x",
|
||||
isOpenShift: true,
|
||||
clusterProxy: &configv1.Proxy{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "cluster",
|
||||
},
|
||||
},
|
||||
cheCluster: &orgv1.CheCluster{
|
||||
cheCluster: &chev2.CheCluster{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Namespace: "eclipse-che",
|
||||
},
|
||||
Spec: orgv1.CheClusterSpec{
|
||||
Server: orgv1.CheClusterSpecServer{
|
||||
ProxyURL: "http://proxy",
|
||||
ProxyPort: "3128",
|
||||
NonProxyHosts: "host1",
|
||||
Spec: chev2.CheClusterSpec{
|
||||
Components: chev2.CheClusterComponents{
|
||||
CheServer: chev2.CheServer{
|
||||
Proxy: chev2.Proxy{
|
||||
Url: "http://proxy",
|
||||
Port: "3128",
|
||||
NonProxyHosts: []string{"host1"},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
initObjects: []runtime.Object{},
|
||||
expectedProxyConf: &deploy.Proxy{
|
||||
expectedProxyConf: &chetypes.Proxy{
|
||||
HttpProxy: "http://proxy:3128",
|
||||
HttpUser: "",
|
||||
HttpPassword: "",
|
||||
|
|
@ -95,8 +99,8 @@ func TestReadProxyConfiguration(t *testing.T) {
|
|||
},
|
||||
},
|
||||
{
|
||||
name: "Test checluster proxy configured, nonProxy merged, OpenShift 4.x",
|
||||
openShiftVersion: "4",
|
||||
name: "Test checluster proxy configured, nonProxy merged, OpenShift 4.x",
|
||||
isOpenShift: true,
|
||||
clusterProxy: &configv1.Proxy{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "cluster",
|
||||
|
|
@ -107,20 +111,24 @@ func TestReadProxyConfiguration(t *testing.T) {
|
|||
NoProxy: "host2",
|
||||
},
|
||||
},
|
||||
cheCluster: &orgv1.CheCluster{
|
||||
cheCluster: &chev2.CheCluster{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Namespace: "eclipse-che",
|
||||
},
|
||||
Spec: orgv1.CheClusterSpec{
|
||||
Server: orgv1.CheClusterSpecServer{
|
||||
ProxyURL: "http://proxy",
|
||||
ProxyPort: "3128",
|
||||
NonProxyHosts: "host1",
|
||||
Spec: chev2.CheClusterSpec{
|
||||
Components: chev2.CheClusterComponents{
|
||||
CheServer: chev2.CheServer{
|
||||
Proxy: chev2.Proxy{
|
||||
Url: "http://proxy",
|
||||
Port: "3128",
|
||||
NonProxyHosts: []string{"host1"},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
initObjects: []runtime.Object{},
|
||||
expectedProxyConf: &deploy.Proxy{
|
||||
expectedProxyConf: &chetypes.Proxy{
|
||||
HttpProxy: "http://proxy:3128",
|
||||
HttpUser: "",
|
||||
HttpPassword: "",
|
||||
|
|
@ -136,8 +144,8 @@ func TestReadProxyConfiguration(t *testing.T) {
|
|||
},
|
||||
},
|
||||
{
|
||||
name: "Test cluster wide proxy configured, OpenShift 4.x",
|
||||
openShiftVersion: "4",
|
||||
name: "Test cluster wide proxy configured, OpenShift 4.x",
|
||||
isOpenShift: true,
|
||||
clusterProxy: &configv1.Proxy{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "cluster",
|
||||
|
|
@ -153,16 +161,13 @@ func TestReadProxyConfiguration(t *testing.T) {
|
|||
NoProxy: "host1",
|
||||
},
|
||||
},
|
||||
cheCluster: &orgv1.CheCluster{
|
||||
cheCluster: &chev2.CheCluster{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Namespace: "eclipse-che",
|
||||
},
|
||||
Spec: orgv1.CheClusterSpec{
|
||||
Server: orgv1.CheClusterSpecServer{},
|
||||
},
|
||||
},
|
||||
initObjects: []runtime.Object{},
|
||||
expectedProxyConf: &deploy.Proxy{
|
||||
expectedProxyConf: &chetypes.Proxy{
|
||||
HttpProxy: "http://proxy:3128",
|
||||
HttpUser: "",
|
||||
HttpPassword: "",
|
||||
|
|
@ -178,8 +183,8 @@ func TestReadProxyConfiguration(t *testing.T) {
|
|||
},
|
||||
},
|
||||
{
|
||||
name: "Test cluster wide proxy is not configured, but cluster wide CA certs added, OpenShift 4.x",
|
||||
openShiftVersion: "4",
|
||||
name: "Test cluster wide proxy is not configured, but cluster wide CA certs added, OpenShift 4.x",
|
||||
isOpenShift: true,
|
||||
clusterProxy: &configv1.Proxy{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "cluster",
|
||||
|
|
@ -190,19 +195,19 @@ func TestReadProxyConfiguration(t *testing.T) {
|
|||
},
|
||||
},
|
||||
},
|
||||
cheCluster: &orgv1.CheCluster{
|
||||
cheCluster: &chev2.CheCluster{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Namespace: "eclipse-che",
|
||||
},
|
||||
},
|
||||
initObjects: []runtime.Object{},
|
||||
expectedProxyConf: &deploy.Proxy{
|
||||
expectedProxyConf: &chetypes.Proxy{
|
||||
TrustedCAMapName: "additional-cluster-ca-bundle",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Test cluster wide proxy configured, nonProxy merged, OpenShift 4.x",
|
||||
openShiftVersion: "4",
|
||||
name: "Test cluster wide proxy configured, nonProxy merged, OpenShift 4.x",
|
||||
isOpenShift: true,
|
||||
clusterProxy: &configv1.Proxy{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "cluster",
|
||||
|
|
@ -213,18 +218,22 @@ func TestReadProxyConfiguration(t *testing.T) {
|
|||
NoProxy: "host1",
|
||||
},
|
||||
},
|
||||
cheCluster: &orgv1.CheCluster{
|
||||
cheCluster: &chev2.CheCluster{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Namespace: "eclipse-che",
|
||||
},
|
||||
Spec: orgv1.CheClusterSpec{
|
||||
Server: orgv1.CheClusterSpecServer{
|
||||
NonProxyHosts: "host2",
|
||||
Spec: chev2.CheClusterSpec{
|
||||
Components: chev2.CheClusterComponents{
|
||||
CheServer: chev2.CheServer{
|
||||
Proxy: chev2.Proxy{
|
||||
NonProxyHosts: []string{"host2"},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
initObjects: []runtime.Object{},
|
||||
expectedProxyConf: &deploy.Proxy{
|
||||
expectedProxyConf: &chetypes.Proxy{
|
||||
HttpProxy: "http://proxy:3128",
|
||||
HttpUser: "",
|
||||
HttpPassword: "",
|
||||
|
|
@ -240,23 +249,27 @@ func TestReadProxyConfiguration(t *testing.T) {
|
|||
},
|
||||
},
|
||||
{
|
||||
name: "Test checluster proxy configured, OpenShift 3.x",
|
||||
openShiftVersion: "3",
|
||||
clusterProxy: &configv1.Proxy{},
|
||||
cheCluster: &orgv1.CheCluster{
|
||||
name: "Test checluster proxy configured, Kubernetes",
|
||||
isOpenShift: false,
|
||||
clusterProxy: &configv1.Proxy{},
|
||||
cheCluster: &chev2.CheCluster{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Namespace: "eclipse-che",
|
||||
},
|
||||
Spec: orgv1.CheClusterSpec{
|
||||
Server: orgv1.CheClusterSpecServer{
|
||||
ProxyURL: "http://proxy",
|
||||
ProxyPort: "3128",
|
||||
NonProxyHosts: "host1",
|
||||
Spec: chev2.CheClusterSpec{
|
||||
Components: chev2.CheClusterComponents{
|
||||
CheServer: chev2.CheServer{
|
||||
Proxy: chev2.Proxy{
|
||||
Url: "http://proxy",
|
||||
Port: "3128",
|
||||
NonProxyHosts: []string{"host1"},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
initObjects: []runtime.Object{},
|
||||
expectedProxyConf: &deploy.Proxy{
|
||||
expectedProxyConf: &chetypes.Proxy{
|
||||
HttpProxy: "http://proxy:3128",
|
||||
HttpUser: "",
|
||||
HttpPassword: "",
|
||||
|
|
@ -272,23 +285,27 @@ func TestReadProxyConfiguration(t *testing.T) {
|
|||
},
|
||||
},
|
||||
{
|
||||
name: "Test checluster proxy configured, OpenShift 3.x and k8s, svc usage",
|
||||
openShiftVersion: "3",
|
||||
clusterProxy: &configv1.Proxy{},
|
||||
cheCluster: &orgv1.CheCluster{
|
||||
name: "Test checluster proxy configured, Kubernetes",
|
||||
isOpenShift: true,
|
||||
clusterProxy: &configv1.Proxy{},
|
||||
cheCluster: &chev2.CheCluster{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Namespace: "eclipse-che",
|
||||
},
|
||||
Spec: orgv1.CheClusterSpec{
|
||||
Server: orgv1.CheClusterSpecServer{
|
||||
ProxyURL: "http://proxy",
|
||||
ProxyPort: "3128",
|
||||
NonProxyHosts: "host1",
|
||||
Spec: chev2.CheClusterSpec{
|
||||
Components: chev2.CheClusterComponents{
|
||||
CheServer: chev2.CheServer{
|
||||
Proxy: chev2.Proxy{
|
||||
Url: "http://proxy",
|
||||
Port: "3128",
|
||||
NonProxyHosts: []string{"host1"},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
initObjects: []runtime.Object{},
|
||||
expectedProxyConf: &deploy.Proxy{
|
||||
expectedProxyConf: &chetypes.Proxy{
|
||||
HttpProxy: "http://proxy:3128",
|
||||
HttpUser: "",
|
||||
HttpPassword: "",
|
||||
|
|
@ -308,11 +325,11 @@ func TestReadProxyConfiguration(t *testing.T) {
|
|||
for _, testCase := range testCases {
|
||||
t.Run(testCase.name, func(t *testing.T) {
|
||||
logf.SetLogger(zap.New(zap.WriteTo(os.Stdout), zap.UseDevMode(true)))
|
||||
orgv1.SchemeBuilder.AddToScheme(scheme.Scheme)
|
||||
chev2.SchemeBuilder.AddToScheme(scheme.Scheme)
|
||||
testCase.initObjects = append(testCase.initObjects, testCase.clusterProxy, testCase.cheCluster)
|
||||
|
||||
scheme := scheme.Scheme
|
||||
orgv1.SchemeBuilder.AddToScheme(scheme)
|
||||
chev2.SchemeBuilder.AddToScheme(scheme)
|
||||
scheme.AddKnownTypes(configv1.SchemeGroupVersion, &configv1.Proxy{})
|
||||
|
||||
cli := fake.NewFakeClientWithScheme(scheme, testCase.initObjects...)
|
||||
|
|
@ -320,12 +337,11 @@ func TestReadProxyConfiguration(t *testing.T) {
|
|||
fakeDiscovery, _ := clientSet.Discovery().(*fakeDiscovery.FakeDiscovery)
|
||||
fakeDiscovery.Fake.Resources = []*metav1.APIResourceList{}
|
||||
|
||||
os.Setenv("OPENSHIFT_VERSION", testCase.openShiftVersion)
|
||||
util.IsOpenShift, util.IsOpenShift4, _ = util.DetectOpenShift()
|
||||
infrastructure.InitializeForTesting(infrastructure.OpenShiftv4)
|
||||
|
||||
deployContext := &deploy.DeployContext{
|
||||
deployContext := &chetypes.DeployContext{
|
||||
CheCluster: testCase.cheCluster,
|
||||
ClusterAPI: deploy.ClusterAPI{
|
||||
ClusterAPI: chetypes.ClusterAPI{
|
||||
Client: cli,
|
||||
NonCachingClient: cli,
|
||||
Scheme: scheme,
|
||||
|
|
|
|||
|
|
@ -18,18 +18,14 @@ import (
|
|||
stdErrors "errors"
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"reflect"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
checluster "github.com/eclipse-che/che-operator/api"
|
||||
checlusterv1 "github.com/eclipse-che/che-operator/api/v1"
|
||||
"github.com/eclipse-che/che-operator/api/v2alpha1"
|
||||
"github.com/devfile/devworkspace-operator/pkg/infrastructure"
|
||||
chev2 "github.com/eclipse-che/che-operator/api/v2"
|
||||
"github.com/eclipse-che/che-operator/controllers/devworkspace/defaults"
|
||||
datasync "github.com/eclipse-che/che-operator/controllers/devworkspace/sync"
|
||||
"github.com/eclipse-che/che-operator/pkg/deploy"
|
||||
"github.com/eclipse-che/che-operator/pkg/util"
|
||||
routev1 "github.com/openshift/api/route/v1"
|
||||
appsv1 "k8s.io/api/apps/v1"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
|
|
@ -45,7 +41,7 @@ import (
|
|||
|
||||
var (
|
||||
log = ctrl.Log.WithName("devworkspace-che")
|
||||
currentCheInstances = map[client.ObjectKey]v2alpha1.CheCluster{}
|
||||
currentCheInstances = map[client.ObjectKey]chev2.CheCluster{}
|
||||
cheInstancesAccess = sync.Mutex{}
|
||||
)
|
||||
|
||||
|
|
@ -73,11 +69,11 @@ type CheClusterReconciler struct {
|
|||
//
|
||||
// If need be, this method can be replaced by a simply calling client.List to get all the che
|
||||
// managers in the cluster.
|
||||
func GetCurrentCheClusterInstances() map[client.ObjectKey]v2alpha1.CheCluster {
|
||||
func GetCurrentCheClusterInstances() map[client.ObjectKey]chev2.CheCluster {
|
||||
cheInstancesAccess.Lock()
|
||||
defer cheInstancesAccess.Unlock()
|
||||
|
||||
ret := map[client.ObjectKey]v2alpha1.CheCluster{}
|
||||
ret := map[client.ObjectKey]chev2.CheCluster{}
|
||||
|
||||
for k, v := range currentCheInstances {
|
||||
ret[k] = v
|
||||
|
|
@ -92,7 +88,7 @@ func CleanCheClusterInstancesForTest() {
|
|||
cheInstancesAccess.Lock()
|
||||
defer cheInstancesAccess.Unlock()
|
||||
|
||||
currentCheInstances = map[client.ObjectKey]v2alpha1.CheCluster{}
|
||||
currentCheInstances = map[client.ObjectKey]chev2.CheCluster{}
|
||||
}
|
||||
|
||||
// New returns a new instance of the Che manager reconciler. This is mainly useful for
|
||||
|
|
@ -111,7 +107,7 @@ func (r *CheClusterReconciler) SetupWithManager(mgr ctrl.Manager) error {
|
|||
r.syncer = datasync.New(r.client, r.scheme)
|
||||
|
||||
bld := ctrl.NewControllerManagedBy(mgr).
|
||||
For(&checlusterv1.CheCluster{}).
|
||||
For(&chev2.CheCluster{}).
|
||||
Owns(&corev1.Service{}).
|
||||
Owns(&corev1.ConfigMap{}).
|
||||
Owns(&appsv1.Deployment{}).
|
||||
|
|
@ -119,7 +115,7 @@ func (r *CheClusterReconciler) SetupWithManager(mgr ctrl.Manager) error {
|
|||
Owns(&corev1.ServiceAccount{}).
|
||||
Owns(&rbac.Role{}).
|
||||
Owns(&rbac.RoleBinding{})
|
||||
if util.IsOpenShift {
|
||||
if infrastructure.IsOpenShift() {
|
||||
bld.Owns(&routev1.Route{})
|
||||
} else {
|
||||
bld.Owns(&networkingv1.Ingress{})
|
||||
|
|
@ -138,8 +134,8 @@ func (r *CheClusterReconciler) Reconcile(ctx context.Context, req ctrl.Request)
|
|||
delete(currentCheInstances, req.NamespacedName)
|
||||
|
||||
// make sure we've checked we're in a valid state
|
||||
currentV1 := &checlusterv1.CheCluster{}
|
||||
err := r.client.Get(ctx, req.NamespacedName, currentV1)
|
||||
cluster := &chev2.CheCluster{}
|
||||
err := r.client.Get(ctx, req.NamespacedName, cluster)
|
||||
if err != nil {
|
||||
if errors.IsNotFound(err) {
|
||||
// Ok, our current router disappeared...
|
||||
|
|
@ -149,14 +145,12 @@ func (r *CheClusterReconciler) Reconcile(ctx context.Context, req ctrl.Request)
|
|||
return ctrl.Result{}, err
|
||||
}
|
||||
|
||||
current := checluster.AsV2alpha1(currentV1)
|
||||
|
||||
if current.GetDeletionTimestamp() != nil {
|
||||
return ctrl.Result{}, r.finalize(ctx, current, currentV1)
|
||||
if cluster.GetDeletionTimestamp() != nil {
|
||||
return ctrl.Result{}, r.finalize(ctx, cluster)
|
||||
}
|
||||
|
||||
disabledMessage := ""
|
||||
switch GetDevWorkspaceState(r.scheme, current) {
|
||||
switch GetDevWorkspaceState(r.scheme, cluster) {
|
||||
case APINotPresentState:
|
||||
disabledMessage = "DevWorkspace CRDs are not installed"
|
||||
case DisabledState:
|
||||
|
|
@ -164,14 +158,14 @@ func (r *CheClusterReconciler) Reconcile(ctx context.Context, req ctrl.Request)
|
|||
}
|
||||
|
||||
if disabledMessage != "" {
|
||||
res, err := r.updateStatus(ctx, current, currentV1, nil, current.Status.GatewayHost, current.Status.WorkspaceBaseDomain, v2alpha1.ClusterPhaseInactive, disabledMessage)
|
||||
res, err := r.updateStatus(ctx, cluster, nil, cluster.Status.WorkspaceBaseDomain, chev2.ClusterPhaseInactive, disabledMessage)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
return res, nil
|
||||
}
|
||||
|
||||
finalizerUpdated, err := r.ensureFinalizer(ctx, current)
|
||||
finalizerUpdated, err := r.ensureFinalizer(ctx, cluster)
|
||||
if err != nil {
|
||||
log.Info("Failed to set a finalizer", "object", req.String())
|
||||
return ctrl.Result{}, err
|
||||
|
|
@ -182,10 +176,10 @@ func (r *CheClusterReconciler) Reconcile(ctx context.Context, req ctrl.Request)
|
|||
}
|
||||
|
||||
// validate the CR
|
||||
err = r.validate(current)
|
||||
err = r.validate(cluster)
|
||||
if err != nil {
|
||||
log.Info("validation errors", "errors", err.Error())
|
||||
res, err := r.updateStatus(ctx, current, currentV1, nil, current.Status.GatewayHost, current.Status.WorkspaceBaseDomain, v2alpha1.ClusterPhaseInactive, err.Error())
|
||||
res, err := r.updateStatus(ctx, cluster, nil, cluster.Status.WorkspaceBaseDomain, chev2.ClusterPhaseInactive, err.Error())
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
|
|
@ -195,12 +189,10 @@ func (r *CheClusterReconciler) Reconcile(ctx context.Context, req ctrl.Request)
|
|||
|
||||
// now, finally, the actual reconciliation
|
||||
var changed bool
|
||||
var host string
|
||||
|
||||
// We are no longer in charge of the gateway, leaving the responsibility for managing it on the che-operator.
|
||||
// But we need to detect the hostname on which the gateway is exposed so that the rest of our subsystems work.
|
||||
host, err = r.detectCheHost(ctx, currentV1)
|
||||
if err != nil {
|
||||
if cluster.GetCheHost() == "" {
|
||||
// Wait some time in case the route is not ready yet
|
||||
return ctrl.Result{RequeueAfter: 2 * time.Second}, err
|
||||
}
|
||||
|
|
@ -209,16 +201,22 @@ func (r *CheClusterReconciler) Reconcile(ctx context.Context, req ctrl.Request)
|
|||
// control of gateway creation
|
||||
changed = false
|
||||
|
||||
workspaceBaseDomain := current.Spec.Workspaces.DomainEndpoints.BaseDomain
|
||||
workspaceBaseDomain := cluster.Spec.Networking.Domain
|
||||
|
||||
// to be compatible with CheCluster API v1
|
||||
routeDomain := cluster.Spec.Components.CheServer.ExtraProperties["CHE_INFRA_OPENSHIFT_ROUTE_HOST_DOMAIN__SUFFIX"]
|
||||
if routeDomain != "" {
|
||||
workspaceBaseDomain = routeDomain
|
||||
}
|
||||
|
||||
if workspaceBaseDomain == "" {
|
||||
workspaceBaseDomain, err = r.detectOpenShiftRouteBaseDomain(current)
|
||||
workspaceBaseDomain, err = r.detectOpenShiftRouteBaseDomain(cluster)
|
||||
if err != nil {
|
||||
return ctrl.Result{}, err
|
||||
}
|
||||
|
||||
if workspaceBaseDomain == "" {
|
||||
res, err := r.updateStatus(ctx, current, currentV1, nil, current.Status.GatewayHost, current.Status.WorkspaceBaseDomain, v2alpha1.ClusterPhaseInactive, "Could not auto-detect the workspaceBaseDomain. Please set it explicitly in the spec.")
|
||||
res, err := r.updateStatus(ctx, cluster, nil, cluster.Status.WorkspaceBaseDomain, chev2.ClusterPhaseInactive, "Could not auto-detect the workspaceBaseDomain. Please set it explicitly in the spec.")
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
|
|
@ -227,58 +225,42 @@ func (r *CheClusterReconciler) Reconcile(ctx context.Context, req ctrl.Request)
|
|||
}
|
||||
}
|
||||
|
||||
res, err := r.updateStatus(ctx, current, currentV1, &changed, host, workspaceBaseDomain, v2alpha1.ClusterPhaseActive, "")
|
||||
res, err := r.updateStatus(ctx, cluster, &changed, workspaceBaseDomain, chev2.ClusterPhaseActive, "")
|
||||
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
|
||||
// everything went fine and the manager exists, put it back in the shared map
|
||||
currentCheInstances[req.NamespacedName] = *current
|
||||
currentCheInstances[req.NamespacedName] = *cluster
|
||||
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (r *CheClusterReconciler) updateStatus(ctx context.Context, cluster *v2alpha1.CheCluster, v1Cluster *checlusterv1.CheCluster, changed *bool, host string, workspaceDomain string, phase v2alpha1.ClusterPhase, phaseMessage string) (ctrl.Result, error) {
|
||||
func (r *CheClusterReconciler) updateStatus(ctx context.Context, cluster *chev2.CheCluster, changed *bool, workspaceDomain string, phase chev2.CheClusterPhase, phaseMessage string) (ctrl.Result, error) {
|
||||
currentPhase := cluster.Status.GatewayPhase
|
||||
|
||||
if changed != nil {
|
||||
if !cluster.Spec.Gateway.IsEnabled() {
|
||||
cluster.Status.GatewayPhase = v2alpha1.GatewayPhaseInactive
|
||||
} else if *changed {
|
||||
cluster.Status.GatewayPhase = v2alpha1.GatewayPhaseInitializing
|
||||
if *changed {
|
||||
cluster.Status.GatewayPhase = chev2.GatewayPhaseInitializing
|
||||
} else {
|
||||
cluster.Status.GatewayPhase = v2alpha1.GatewayPhaseEstablished
|
||||
cluster.Status.GatewayPhase = chev2.GatewayPhaseEstablished
|
||||
}
|
||||
}
|
||||
|
||||
cluster.Status.GatewayHost = host
|
||||
cluster.Status.WorkspaceBaseDomain = workspaceDomain
|
||||
err := r.client.Status().Update(ctx, cluster)
|
||||
|
||||
// set this unconditionally, because the only other value is set using the finalizer
|
||||
cluster.Status.Phase = phase
|
||||
cluster.Status.Message = phaseMessage
|
||||
|
||||
var err error
|
||||
if !reflect.DeepEqual(v1Cluster.Status.DevworkspaceStatus, cluster.Status) {
|
||||
v1Cluster.Status.DevworkspaceStatus = cluster.Status
|
||||
err = r.client.Status().Update(ctx, v1Cluster)
|
||||
}
|
||||
|
||||
requeue := cluster.Spec.IsEnabled() && (currentPhase == v2alpha1.GatewayPhaseInitializing ||
|
||||
cluster.Status.Phase != v2alpha1.ClusterPhaseActive)
|
||||
|
||||
requeue := currentPhase == chev2.GatewayPhaseInitializing
|
||||
return ctrl.Result{Requeue: requeue}, err
|
||||
}
|
||||
|
||||
func (r *CheClusterReconciler) validate(cluster *v2alpha1.CheCluster) error {
|
||||
func (r *CheClusterReconciler) validate(cluster *chev2.CheCluster) error {
|
||||
validationErrors := []string{}
|
||||
|
||||
if !util.IsOpenShift {
|
||||
// The validation error messages must correspond to the storage version of the resource, which is currently
|
||||
// v1...
|
||||
if cluster.Spec.Workspaces.DomainEndpoints.BaseDomain == "" {
|
||||
validationErrors = append(validationErrors, "spec.k8s.ingressDomain must be specified")
|
||||
if !infrastructure.IsOpenShift() {
|
||||
if cluster.Spec.Networking.Domain == "" {
|
||||
validationErrors = append(validationErrors, "spec.networking.domain must be specified")
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -294,7 +276,7 @@ func (r *CheClusterReconciler) validate(cluster *v2alpha1.CheCluster) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (r *CheClusterReconciler) finalize(ctx context.Context, cluster *v2alpha1.CheCluster, v1Cluster *checlusterv1.CheCluster) (err error) {
|
||||
func (r *CheClusterReconciler) finalize(ctx context.Context, cluster *chev2.CheCluster) (err error) {
|
||||
err = r.gatewayConfigFinalize(ctx, cluster)
|
||||
|
||||
if err == nil {
|
||||
|
|
@ -307,19 +289,17 @@ func (r *CheClusterReconciler) finalize(ctx context.Context, cluster *v2alpha1.C
|
|||
|
||||
cluster.Finalizers = finalizers
|
||||
|
||||
err = r.client.Update(ctx, checluster.AsV1(cluster))
|
||||
err = r.client.Update(ctx, cluster)
|
||||
} else {
|
||||
cluster.Status.Phase = v2alpha1.ClusterPhasePendingDeletion
|
||||
cluster.Status.ChePhase = chev2.ClusterPhasePendingDeletion
|
||||
cluster.Status.Message = fmt.Sprintf("Finalization has failed: %s", err.Error())
|
||||
|
||||
v1Cluster.Status.DevworkspaceStatus = cluster.Status
|
||||
err = r.client.Status().Update(ctx, v1Cluster)
|
||||
err = r.client.Status().Update(ctx, cluster)
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func (r *CheClusterReconciler) ensureFinalizer(ctx context.Context, cluster *v2alpha1.CheCluster) (updated bool, err error) {
|
||||
func (r *CheClusterReconciler) ensureFinalizer(ctx context.Context, cluster *chev2.CheCluster) (updated bool, err error) {
|
||||
|
||||
needsUpdate := true
|
||||
if cluster.Finalizers != nil {
|
||||
|
|
@ -335,15 +315,15 @@ func (r *CheClusterReconciler) ensureFinalizer(ctx context.Context, cluster *v2a
|
|||
|
||||
if needsUpdate {
|
||||
cluster.Finalizers = append(cluster.Finalizers, FinalizerName)
|
||||
err = r.client.Update(ctx, checluster.AsV1(cluster))
|
||||
err = r.client.Update(ctx, cluster)
|
||||
}
|
||||
|
||||
return needsUpdate, err
|
||||
}
|
||||
|
||||
// Tries to autodetect the route base domain.
|
||||
func (r *CheClusterReconciler) detectOpenShiftRouteBaseDomain(cluster *v2alpha1.CheCluster) (string, error) {
|
||||
if !util.IsOpenShift {
|
||||
func (r *CheClusterReconciler) detectOpenShiftRouteBaseDomain(cluster *chev2.CheCluster) (string, error) {
|
||||
if !infrastructure.IsOpenShift() {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
|
|
@ -381,58 +361,9 @@ func randomSuffix(length int) string {
|
|||
return hex.EncodeToString(arr)
|
||||
}
|
||||
|
||||
func (r *CheClusterReconciler) detectCheHost(ctx context.Context, cluster *checlusterv1.CheCluster) (string, error) {
|
||||
host := strings.TrimPrefix(cluster.Status.CheURL, "https://")
|
||||
|
||||
if host == "" {
|
||||
expectedLabels := deploy.GetLabels(cluster, deploy.DefaultCheFlavor(cluster))
|
||||
lbls := labels.SelectorFromSet(expectedLabels)
|
||||
|
||||
if util.IsOpenShift {
|
||||
list := routev1.RouteList{}
|
||||
err := r.client.List(ctx, &list, &client.ListOptions{
|
||||
Namespace: cluster.Namespace,
|
||||
LabelSelector: lbls,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if len(list.Items) == 0 {
|
||||
return "", fmt.Errorf("expecting exactly 1 route to match Che gateway labels but found %d", len(list.Items))
|
||||
}
|
||||
|
||||
host = list.Items[0].Spec.Host
|
||||
} else {
|
||||
list := networkingv1.IngressList{}
|
||||
err := r.client.List(ctx, &list, &client.ListOptions{
|
||||
Namespace: cluster.Namespace,
|
||||
LabelSelector: lbls,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if len(list.Items) == 0 {
|
||||
return "", fmt.Errorf("expecting exactly 1 ingress to match Che gateway labels but found %d", len(list.Items))
|
||||
}
|
||||
|
||||
if len(list.Items[0].Spec.Rules) != 1 {
|
||||
return "", fmt.Errorf("expecting exactly 1 rule on the Che gateway ingress but found %d. This is a bug", len(list.Items[0].Spec.Rules))
|
||||
}
|
||||
|
||||
host = list.Items[0].Spec.Rules[0].Host
|
||||
}
|
||||
}
|
||||
|
||||
return host, nil
|
||||
}
|
||||
|
||||
// Checks that there are no devworkspace configurations for the gateway (which would mean running devworkspaces).
|
||||
// If there are some, an error is returned.
|
||||
func (r *CheClusterReconciler) gatewayConfigFinalize(ctx context.Context, cluster *v2alpha1.CheCluster) error {
|
||||
func (r *CheClusterReconciler) gatewayConfigFinalize(ctx context.Context, cluster *chev2.CheCluster) error {
|
||||
// we need to stop the reconcile if there are devworkspaces handled by it.
|
||||
// we detect that by the presence of the gateway configmaps in the namespace of the manager
|
||||
list := corev1.ConfigMapList{}
|
||||
|
|
|
|||
|
|
@ -20,13 +20,9 @@ import (
|
|||
|
||||
dwo "github.com/devfile/devworkspace-operator/apis/controller/v1alpha1"
|
||||
"github.com/devfile/devworkspace-operator/pkg/infrastructure"
|
||||
checluster "github.com/eclipse-che/che-operator/api"
|
||||
v1 "github.com/eclipse-che/che-operator/api/v1"
|
||||
"github.com/eclipse-che/che-operator/api/v2alpha1"
|
||||
chev2 "github.com/eclipse-che/che-operator/api/v2"
|
||||
"github.com/eclipse-che/che-operator/controllers/devworkspace/defaults"
|
||||
"github.com/eclipse-che/che-operator/controllers/devworkspace/sync"
|
||||
"github.com/eclipse-che/che-operator/pkg/deploy"
|
||||
"github.com/eclipse-che/che-operator/pkg/util"
|
||||
|
||||
routev1 "github.com/openshift/api/route/v1"
|
||||
appsv1 "k8s.io/api/apps/v1"
|
||||
|
|
@ -34,7 +30,6 @@ import (
|
|||
networkingv1 "k8s.io/api/networking/v1"
|
||||
"k8s.io/api/node/v1alpha1"
|
||||
rbac "k8s.io/api/rbac/v1"
|
||||
"k8s.io/utils/pointer"
|
||||
|
||||
k8sErrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
|
|
@ -56,13 +51,15 @@ func createTestScheme() *runtime.Scheme {
|
|||
utilruntime.Must(appsv1.AddToScheme(scheme))
|
||||
utilruntime.Must(rbac.AddToScheme(scheme))
|
||||
utilruntime.Must(routev1.AddToScheme(scheme))
|
||||
utilruntime.Must(v1.AddToScheme(scheme))
|
||||
utilruntime.Must(chev2.AddToScheme(scheme))
|
||||
utilruntime.Must(dwo.AddToScheme(scheme))
|
||||
|
||||
return scheme
|
||||
}
|
||||
|
||||
func TestNoCustomResourceSharedWhenReconcilingNonExistent(t *testing.T) {
|
||||
infrastructure.InitializeForTesting(infrastructure.Kubernetes)
|
||||
|
||||
// clear the map before the test
|
||||
for k := range currentCheInstances {
|
||||
delete(currentCheInstances, k)
|
||||
|
|
@ -89,24 +86,21 @@ func TestNoCustomResourceSharedWhenReconcilingNonExistent(t *testing.T) {
|
|||
}
|
||||
|
||||
// now add some manager and reconcile a non-existent one
|
||||
cl.Create(ctx, asV1(&v2alpha1.CheCluster{
|
||||
cl.Create(ctx, &chev2.CheCluster{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: managerName + "-not-me",
|
||||
Namespace: ns,
|
||||
Finalizers: []string{FinalizerName},
|
||||
},
|
||||
Spec: v2alpha1.CheClusterSpec{
|
||||
Gateway: v2alpha1.CheGatewaySpec{
|
||||
Host: "over.the.rainbow",
|
||||
Enabled: pointer.BoolPtr(false),
|
||||
},
|
||||
Workspaces: v2alpha1.Workspaces{
|
||||
DomainEndpoints: v2alpha1.DomainEndpoints{
|
||||
BaseDomain: "down.on.earth",
|
||||
},
|
||||
Spec: chev2.CheClusterSpec{
|
||||
Networking: chev2.CheClusterSpecNetworking{
|
||||
Hostname: "over.the.rainbow",
|
||||
},
|
||||
},
|
||||
}))
|
||||
Status: chev2.CheClusterStatus{
|
||||
WorkspaceBaseDomain: "down.on.earth",
|
||||
},
|
||||
})
|
||||
|
||||
_, err = reconciler.Reconcile(context.TODO(), reconcile.Request{NamespacedName: types.NamespacedName{Name: managerName, Namespace: ns}})
|
||||
if err != nil {
|
||||
|
|
@ -120,6 +114,8 @@ func TestNoCustomResourceSharedWhenReconcilingNonExistent(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestAddsCustomResourceToSharedMapOnCreate(t *testing.T) {
|
||||
infrastructure.InitializeForTesting(infrastructure.Kubernetes)
|
||||
|
||||
// clear the map before the test
|
||||
for k := range currentCheInstances {
|
||||
delete(currentCheInstances, k)
|
||||
|
|
@ -128,24 +124,19 @@ func TestAddsCustomResourceToSharedMapOnCreate(t *testing.T) {
|
|||
managerName := "che"
|
||||
ns := "default"
|
||||
scheme := createTestScheme()
|
||||
cl := fake.NewFakeClientWithScheme(scheme, asV1(&v2alpha1.CheCluster{
|
||||
cl := fake.NewFakeClientWithScheme(scheme, &chev2.CheCluster{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: managerName,
|
||||
Namespace: ns,
|
||||
Finalizers: []string{FinalizerName},
|
||||
},
|
||||
Spec: v2alpha1.CheClusterSpec{
|
||||
Gateway: v2alpha1.CheGatewaySpec{
|
||||
Host: "over.the.rainbow",
|
||||
Enabled: pointer.BoolPtr(false),
|
||||
},
|
||||
Workspaces: v2alpha1.Workspaces{
|
||||
DomainEndpoints: v2alpha1.DomainEndpoints{
|
||||
BaseDomain: "down.on.earth",
|
||||
},
|
||||
Spec: chev2.CheClusterSpec{
|
||||
Networking: chev2.CheClusterSpecNetworking{
|
||||
Hostname: "over.the.rainbow",
|
||||
Domain: "down.on.earth",
|
||||
},
|
||||
},
|
||||
}))
|
||||
})
|
||||
|
||||
reconciler := CheClusterReconciler{client: cl, scheme: scheme, syncer: sync.New(cl, scheme)}
|
||||
|
||||
|
|
@ -170,6 +161,8 @@ func TestAddsCustomResourceToSharedMapOnCreate(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestUpdatesCustomResourceInSharedMapOnUpdate(t *testing.T) {
|
||||
infrastructure.InitializeForTesting(infrastructure.Kubernetes)
|
||||
|
||||
// clear the map before the test
|
||||
for k := range currentCheInstances {
|
||||
delete(currentCheInstances, k)
|
||||
|
|
@ -179,24 +172,19 @@ func TestUpdatesCustomResourceInSharedMapOnUpdate(t *testing.T) {
|
|||
ns := "default"
|
||||
scheme := createTestScheme()
|
||||
|
||||
cl := fake.NewFakeClientWithScheme(scheme, asV1(&v2alpha1.CheCluster{
|
||||
cl := fake.NewFakeClientWithScheme(scheme, &chev2.CheCluster{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: managerName,
|
||||
Namespace: ns,
|
||||
Finalizers: []string{FinalizerName},
|
||||
},
|
||||
Spec: v2alpha1.CheClusterSpec{
|
||||
Gateway: v2alpha1.CheGatewaySpec{
|
||||
Enabled: pointer.BoolPtr(false),
|
||||
Host: "over.the.rainbow",
|
||||
},
|
||||
Workspaces: v2alpha1.Workspaces{
|
||||
DomainEndpoints: v2alpha1.DomainEndpoints{
|
||||
BaseDomain: "down.on.earth",
|
||||
},
|
||||
Spec: chev2.CheClusterSpec{
|
||||
Networking: chev2.CheClusterSpecNetworking{
|
||||
Hostname: "over.the.rainbow",
|
||||
Domain: "down.on.earth",
|
||||
},
|
||||
},
|
||||
}))
|
||||
})
|
||||
|
||||
reconciler := CheClusterReconciler{client: cl, scheme: scheme, syncer: sync.New(cl, scheme)}
|
||||
|
||||
|
|
@ -219,19 +207,19 @@ func TestUpdatesCustomResourceInSharedMapOnUpdate(t *testing.T) {
|
|||
t.Fatalf("Found a manager that we didn't reconcile. Curious (and buggy). We found %s but should have found %s", mgr.Name, managerName)
|
||||
}
|
||||
|
||||
if mgr.Spec.Gateway.Host != "over.the.rainbow" {
|
||||
t.Fatalf("Unexpected host value: expected: over.the.rainbow, actual: %s", mgr.Spec.Gateway.Host)
|
||||
if mgr.GetCheHost() != "over.the.rainbow" {
|
||||
t.Fatalf("Unexpected host value: expected: over.the.rainbow, actual: %s", mgr.GetCheHost())
|
||||
}
|
||||
|
||||
// now update the manager and reconcile again. See that the map contains the updated value
|
||||
mgrInCluster := v1.CheCluster{}
|
||||
mgrInCluster := chev2.CheCluster{}
|
||||
cl.Get(context.TODO(), client.ObjectKey{Name: managerName, Namespace: ns}, &mgrInCluster)
|
||||
|
||||
// to be able to update, we need to set the resource version
|
||||
mgr.SetResourceVersion(mgrInCluster.GetResourceVersion())
|
||||
|
||||
mgr.Spec.Gateway.Host = "over.the.shoulder"
|
||||
err = cl.Update(context.TODO(), asV1(&mgr))
|
||||
mgr.Spec.Networking.Hostname = "over.the.shoulder"
|
||||
err = cl.Update(context.TODO(), &mgr)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to update. Wat? %s", err)
|
||||
}
|
||||
|
|
@ -247,8 +235,8 @@ func TestUpdatesCustomResourceInSharedMapOnUpdate(t *testing.T) {
|
|||
t.Fatalf("Found a manager that we didn't reconcile. Curious (and buggy). We found %s but should have found %s", mgr.Name, managerName)
|
||||
}
|
||||
|
||||
if mgr.Spec.Gateway.Host != "over.the.rainbow" {
|
||||
t.Fatalf("Unexpected host value: expected: over.the.rainbow, actual: %s", mgr.Spec.Gateway.Host)
|
||||
if mgr.Spec.Networking.Hostname != "over.the.rainbow" {
|
||||
t.Fatalf("Unexpected host value: expected: over.the.rainbow, actual: %s", mgr.Spec.Networking.Hostname)
|
||||
}
|
||||
|
||||
// now reconcile and see that the value in the map is now updated
|
||||
|
|
@ -268,12 +256,14 @@ func TestUpdatesCustomResourceInSharedMapOnUpdate(t *testing.T) {
|
|||
t.Fatalf("Found a manager that we didn't reconcile. Curious (and buggy). We found %s but should have found %s", mgr.Name, managerName)
|
||||
}
|
||||
|
||||
if mgr.Spec.Gateway.Host != "over.the.shoulder" {
|
||||
t.Fatalf("Unexpected host value: expected: over.the.shoulder, actual: %s", mgr.Spec.Gateway.Host)
|
||||
if mgr.Spec.Networking.Hostname != "over.the.shoulder" {
|
||||
t.Fatalf("Unexpected host value: expected: over.the.shoulder, actual: %s", mgr.Spec.Networking.Hostname)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRemovesCustomResourceFromSharedMapOnDelete(t *testing.T) {
|
||||
infrastructure.InitializeForTesting(infrastructure.Kubernetes)
|
||||
|
||||
// clear the map before the test
|
||||
for k := range currentCheInstances {
|
||||
delete(currentCheInstances, k)
|
||||
|
|
@ -283,24 +273,19 @@ func TestRemovesCustomResourceFromSharedMapOnDelete(t *testing.T) {
|
|||
ns := "default"
|
||||
scheme := createTestScheme()
|
||||
|
||||
cl := fake.NewFakeClientWithScheme(scheme, asV1(&v2alpha1.CheCluster{
|
||||
cl := fake.NewFakeClientWithScheme(scheme, &chev2.CheCluster{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: managerName,
|
||||
Namespace: ns,
|
||||
Finalizers: []string{FinalizerName},
|
||||
},
|
||||
Spec: v2alpha1.CheClusterSpec{
|
||||
Gateway: v2alpha1.CheGatewaySpec{
|
||||
Host: "over.the.rainbow",
|
||||
Enabled: pointer.BoolPtr(false),
|
||||
},
|
||||
Workspaces: v2alpha1.Workspaces{
|
||||
DomainEndpoints: v2alpha1.DomainEndpoints{
|
||||
BaseDomain: "down.on.earth",
|
||||
},
|
||||
Spec: chev2.CheClusterSpec{
|
||||
Networking: chev2.CheClusterSpecNetworking{
|
||||
Hostname: "over.the.rainbow",
|
||||
Domain: "down.on.earth",
|
||||
},
|
||||
},
|
||||
}))
|
||||
})
|
||||
|
||||
reconciler := CheClusterReconciler{client: cl, scheme: scheme, syncer: sync.New(cl, scheme)}
|
||||
|
||||
|
|
@ -323,7 +308,7 @@ func TestRemovesCustomResourceFromSharedMapOnDelete(t *testing.T) {
|
|||
t.Fatalf("Found a manager that we didn't reconcile. Curious (and buggy). We found %s but should have found %s", mgr.Name, managerName)
|
||||
}
|
||||
|
||||
cl.Delete(context.TODO(), asV1(&mgr))
|
||||
cl.Delete(context.TODO(), &mgr)
|
||||
|
||||
// now reconcile and see that the value is no longer in the map
|
||||
|
||||
|
|
@ -340,28 +325,26 @@ func TestRemovesCustomResourceFromSharedMapOnDelete(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestCustomResourceFinalization(t *testing.T) {
|
||||
infrastructure.InitializeForTesting(infrastructure.Kubernetes)
|
||||
|
||||
managerName := "che"
|
||||
ns := "default"
|
||||
scheme := createTestScheme()
|
||||
ctx := context.TODO()
|
||||
cl := fake.NewFakeClientWithScheme(scheme,
|
||||
asV1(&v2alpha1.CheCluster{
|
||||
&chev2.CheCluster{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: managerName,
|
||||
Namespace: ns,
|
||||
Finalizers: []string{FinalizerName},
|
||||
},
|
||||
Spec: v2alpha1.CheClusterSpec{
|
||||
Gateway: v2alpha1.CheGatewaySpec{
|
||||
Host: "over.the.rainbow",
|
||||
},
|
||||
Workspaces: v2alpha1.Workspaces{
|
||||
DomainEndpoints: v2alpha1.DomainEndpoints{
|
||||
BaseDomain: "down.on.earth",
|
||||
},
|
||||
Spec: chev2.CheClusterSpec{
|
||||
Networking: chev2.CheClusterSpecNetworking{
|
||||
Hostname: "over.the.rainbow",
|
||||
Domain: "down.on.earth",
|
||||
},
|
||||
},
|
||||
}),
|
||||
},
|
||||
&corev1.ConfigMap{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "ws1",
|
||||
|
|
@ -382,7 +365,7 @@ func TestCustomResourceFinalization(t *testing.T) {
|
|||
}
|
||||
|
||||
// check that the reconcile loop added the finalizer
|
||||
manager := v1.CheCluster{}
|
||||
manager := chev2.CheCluster{}
|
||||
err = cl.Get(ctx, client.ObjectKey{Name: managerName, Namespace: ns}, &manager)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to obtain the manager from the fake client: %s", err)
|
||||
|
|
@ -407,7 +390,7 @@ func TestCustomResourceFinalization(t *testing.T) {
|
|||
t.Fatalf("Failed to reconcile che manager with error: %s", err)
|
||||
}
|
||||
|
||||
manager = v1.CheCluster{}
|
||||
manager = chev2.CheCluster{}
|
||||
err = cl.Get(ctx, client.ObjectKey{Name: managerName, Namespace: ns}, &manager)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to obtain the manager from the fake client: %s", err)
|
||||
|
|
@ -417,10 +400,10 @@ func TestCustomResourceFinalization(t *testing.T) {
|
|||
t.Fatalf("There should have been a finalizer on the manager after a failed finalization attempt")
|
||||
}
|
||||
|
||||
if manager.Status.DevworkspaceStatus.Phase != v2alpha1.ClusterPhasePendingDeletion {
|
||||
t.Fatalf("Expected the manager to be in the pending deletion phase but it is: %s", manager.Status.DevworkspaceStatus.Phase)
|
||||
if manager.Status.ChePhase != chev2.ClusterPhasePendingDeletion {
|
||||
t.Fatalf("Expected the manager to be in the pending deletion phase but it is: %s", manager.Status.ChePhase)
|
||||
}
|
||||
if len(manager.Status.DevworkspaceStatus.Message) == 0 {
|
||||
if len(manager.Status.Message) == 0 {
|
||||
t.Fatalf("Expected an non-empty message about the failed finalization in the manager status")
|
||||
}
|
||||
|
||||
|
|
@ -440,7 +423,7 @@ func TestCustomResourceFinalization(t *testing.T) {
|
|||
t.Fatalf("Failed to reconcile che manager with error: %s", err)
|
||||
}
|
||||
|
||||
manager = v1.CheCluster{}
|
||||
manager = chev2.CheCluster{}
|
||||
err = cl.Get(ctx, client.ObjectKey{Name: managerName, Namespace: ns}, &manager)
|
||||
if err == nil || !k8sErrors.IsNotFound(err) {
|
||||
t.Fatalf("Failed to obtain the manager from the fake client: %s", err)
|
||||
|
|
@ -461,40 +444,19 @@ func TestExternalGatewayDetection(t *testing.T) {
|
|||
clusterName := "eclipse-che"
|
||||
ns := "default"
|
||||
|
||||
v2cluster := &v2alpha1.CheCluster{
|
||||
cluster := &chev2.CheCluster{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: clusterName,
|
||||
Namespace: ns,
|
||||
},
|
||||
Spec: v2alpha1.CheClusterSpec{
|
||||
Workspaces: v2alpha1.Workspaces{
|
||||
DomainEndpoints: v2alpha1.DomainEndpoints{
|
||||
BaseDomain: "down.on.earth",
|
||||
},
|
||||
},
|
||||
Status: chev2.CheClusterStatus{
|
||||
WorkspaceBaseDomain: "down.on.earth",
|
||||
CheURL: "https://host",
|
||||
},
|
||||
}
|
||||
|
||||
onKubernetes(func() {
|
||||
v1Cluster := asV1(v2cluster)
|
||||
|
||||
cl := fake.NewFakeClientWithScheme(scheme,
|
||||
v1Cluster,
|
||||
&networkingv1.Ingress{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "ingress",
|
||||
Namespace: ns,
|
||||
Labels: deploy.GetLabels(v1Cluster, "test-che"),
|
||||
},
|
||||
Spec: networkingv1.IngressSpec{
|
||||
Rules: []networkingv1.IngressRule{
|
||||
{
|
||||
Host: "ingress.host",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
)
|
||||
cl := fake.NewFakeClientWithScheme(scheme, cluster)
|
||||
|
||||
reconciler := CheClusterReconciler{client: cl, scheme: scheme, syncer: sync.New(cl, scheme)}
|
||||
|
||||
|
|
@ -508,36 +470,18 @@ func TestExternalGatewayDetection(t *testing.T) {
|
|||
t.Fatalf("Failed to reconcile che manager with error: %s", err)
|
||||
}
|
||||
|
||||
persisted := v1.CheCluster{}
|
||||
persisted := chev2.CheCluster{}
|
||||
if err := cl.Get(context.TODO(), types.NamespacedName{Name: clusterName, Namespace: ns}, &persisted); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if persisted.Status.DevworkspaceStatus.Phase != v2alpha1.ClusterPhaseActive {
|
||||
t.Fatalf("Unexpected cluster state: %v", persisted.Status.DevworkspaceStatus.Phase)
|
||||
}
|
||||
|
||||
if persisted.Status.DevworkspaceStatus.GatewayHost != "ingress.host" {
|
||||
t.Fatalf("Unexpected gateway host: %v", persisted.Status.DevworkspaceStatus.GatewayHost)
|
||||
if persisted.GetCheHost() != "host" {
|
||||
t.Fatalf("Unexpected gateway host: %v", persisted.GetCheHost())
|
||||
}
|
||||
})
|
||||
|
||||
onOpenShift(func() {
|
||||
v1Cluster := asV1(v2cluster)
|
||||
|
||||
cl := fake.NewFakeClientWithScheme(scheme,
|
||||
v1Cluster,
|
||||
&routev1.Route{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "route",
|
||||
Namespace: ns,
|
||||
Labels: deploy.GetLabels(v1Cluster, "test-che"),
|
||||
},
|
||||
Spec: routev1.RouteSpec{
|
||||
Host: "route.host",
|
||||
},
|
||||
},
|
||||
)
|
||||
cl := fake.NewFakeClientWithScheme(scheme, cluster)
|
||||
|
||||
reconciler := CheClusterReconciler{client: cl, scheme: scheme, syncer: sync.New(cl, scheme)}
|
||||
|
||||
|
|
@ -551,49 +495,23 @@ func TestExternalGatewayDetection(t *testing.T) {
|
|||
t.Fatalf("Failed to reconcile che manager with error: %s", err)
|
||||
}
|
||||
|
||||
persisted := v1.CheCluster{}
|
||||
persisted := chev2.CheCluster{}
|
||||
if err := cl.Get(context.TODO(), types.NamespacedName{Name: clusterName, Namespace: ns}, &persisted); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if persisted.Status.DevworkspaceStatus.Phase != v2alpha1.ClusterPhaseActive {
|
||||
t.Fatalf("Unexpected cluster state: %v", persisted.Status.DevworkspaceStatus.Phase)
|
||||
}
|
||||
|
||||
if persisted.Status.DevworkspaceStatus.GatewayHost != "route.host" {
|
||||
t.Fatalf("Unexpected gateway host: %v", persisted.Status.DevworkspaceStatus.GatewayHost)
|
||||
if persisted.GetCheHost() != "host" {
|
||||
t.Fatalf("Unexpected gateway host: %v", persisted.GetCheHost())
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func asV1(v2Obj *v2alpha1.CheCluster) *v1.CheCluster {
|
||||
v1 := checluster.AsV1(v2Obj)
|
||||
v1.Status.CheURL = "https://" + v1.Spec.Server.CheHost
|
||||
return v1
|
||||
}
|
||||
|
||||
func onKubernetes(f func()) {
|
||||
isOpenShift := util.IsOpenShift
|
||||
isOpenShift4 := util.IsOpenShift4
|
||||
|
||||
util.IsOpenShift = false
|
||||
util.IsOpenShift4 = false
|
||||
|
||||
infrastructure.InitializeForTesting(infrastructure.Kubernetes)
|
||||
f()
|
||||
|
||||
util.IsOpenShift = isOpenShift
|
||||
util.IsOpenShift4 = isOpenShift4
|
||||
}
|
||||
|
||||
func onOpenShift(f func()) {
|
||||
isOpenShift := util.IsOpenShift
|
||||
isOpenShift4 := util.IsOpenShift4
|
||||
|
||||
util.IsOpenShift = true
|
||||
util.IsOpenShift4 = true
|
||||
|
||||
infrastructure.InitializeForTesting(infrastructure.OpenShiftv4)
|
||||
f()
|
||||
|
||||
util.IsOpenShift = isOpenShift
|
||||
util.IsOpenShift4 = isOpenShift4
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,21 +13,13 @@
|
|||
package defaults
|
||||
|
||||
import (
|
||||
"os"
|
||||
"runtime"
|
||||
|
||||
"github.com/eclipse-che/che-operator/api/v2alpha1"
|
||||
chev2 "github.com/eclipse-che/che-operator/api/v2"
|
||||
"github.com/eclipse-che/che-operator/pkg/common/constants"
|
||||
"github.com/eclipse-che/che-operator/pkg/deploy"
|
||||
ctrl "sigs.k8s.io/controller-runtime"
|
||||
)
|
||||
|
||||
const (
|
||||
gatewayImageEnvVarName = "RELATED_IMAGE_gateway"
|
||||
gatewayConfigurerImageEnvVarName = "RELATED_IMAGE_gateway_configurer"
|
||||
|
||||
defaultGatewayImage = "quay.io/eclipse/che--traefik:v2.5.0-eb30f9f09a65cee1fab5ef9c64cb4ec91b800dc3fdd738d62a9d4334f0114683"
|
||||
defaultGatewayConfigurerImage = "quay.io/che-incubator/configbump:0.1.4"
|
||||
|
||||
configAnnotationPrefix = "che.routing.controller.devfile.io/"
|
||||
ConfigAnnotationCheManagerName = configAnnotationPrefix + "che-name"
|
||||
ConfigAnnotationCheManagerNamespace = configAnnotationPrefix + "che-namespace"
|
||||
|
|
@ -40,13 +32,6 @@ const (
|
|||
var (
|
||||
log = ctrl.Log.WithName("defaults")
|
||||
|
||||
DefaultIngressAnnotations = map[string]string{
|
||||
"kubernetes.io/ingress.class": "nginx",
|
||||
"nginx.ingress.kubernetes.io/proxy-read-timeout": "3600",
|
||||
"nginx.ingress.kubernetes.io/proxy-connect-timeout": "3600",
|
||||
"nginx.ingress.kubernetes.io/ssl-redirect": "true",
|
||||
}
|
||||
|
||||
// If this looks weirdly out of place to you from all other labels, then you're completely right!
|
||||
// These labels are the default ones used by che-operator and Che7. Let's keep the defaults
|
||||
// the same for the ease of translation...
|
||||
|
|
@ -60,7 +45,7 @@ func GetGatewayWorkspaceConfigMapName(workspaceID string) string {
|
|||
return workspaceID + "-route"
|
||||
}
|
||||
|
||||
func GetLabelsForComponent(cluster *v2alpha1.CheCluster, component string) map[string]string {
|
||||
func GetLabelsForComponent(cluster *chev2.CheCluster, component string) map[string]string {
|
||||
return GetLabelsFromNames(cluster.Name, component)
|
||||
}
|
||||
|
||||
|
|
@ -68,53 +53,27 @@ func GetLabelsFromNames(appName string, component string) map[string]string {
|
|||
return AddStandardLabelsFromNames(appName, component, map[string]string{})
|
||||
}
|
||||
|
||||
func AddStandardLabelsForComponent(cluster *v2alpha1.CheCluster, component string, labels map[string]string) map[string]string {
|
||||
func AddStandardLabelsForComponent(cluster *chev2.CheCluster, component string, labels map[string]string) map[string]string {
|
||||
return AddStandardLabelsFromNames(cluster.Name, component, labels)
|
||||
}
|
||||
|
||||
func AddStandardLabelsFromNames(appName string, component string, labels map[string]string) map[string]string {
|
||||
labels["app.kubernetes.io/name"] = appName
|
||||
labels["app.kubernetes.io/part-of"] = deploy.CheEclipseOrg
|
||||
labels["app.kubernetes.io/part-of"] = constants.CheEclipseOrg
|
||||
labels["app.kubernetes.io/component"] = component
|
||||
return labels
|
||||
}
|
||||
|
||||
func GetGatewayImage() string {
|
||||
return read(gatewayImageEnvVarName, defaultGatewayImage)
|
||||
}
|
||||
|
||||
func GetGatewayConfigurerImage() string {
|
||||
return read(gatewayConfigurerImageEnvVarName, defaultGatewayConfigurerImage)
|
||||
}
|
||||
|
||||
func GetIngressAnnotations(cluster *v2alpha1.CheCluster) map[string]string {
|
||||
if len(cluster.Spec.K8s.IngressAnnotations) > 0 {
|
||||
return cluster.Spec.K8s.IngressAnnotations
|
||||
func GetIngressAnnotations(cluster *chev2.CheCluster) map[string]string {
|
||||
if len(cluster.Spec.Networking.Annotations) > 0 {
|
||||
return cluster.Spec.Networking.Annotations
|
||||
}
|
||||
return DefaultIngressAnnotations
|
||||
return deploy.DefaultIngressAnnotations
|
||||
}
|
||||
|
||||
func GetGatewayWorkspaceConfigMapLabels(cluster *v2alpha1.CheCluster) map[string]string {
|
||||
if len(cluster.Spec.Gateway.ConfigLabels) > 0 {
|
||||
return cluster.Spec.Gateway.ConfigLabels
|
||||
func GetGatewayWorkspaceConfigMapLabels(cluster *chev2.CheCluster) map[string]string {
|
||||
if len(cluster.Spec.Networking.Auth.Gateway.ConfigLabels) > 0 {
|
||||
return cluster.Spec.Networking.Auth.Gateway.ConfigLabels
|
||||
}
|
||||
return defaultGatewayConfigLabels
|
||||
}
|
||||
|
||||
func read(varName string, fallback string) string {
|
||||
ret := os.Getenv(varName)
|
||||
|
||||
if len(ret) == 0 {
|
||||
ret = os.Getenv(archDependent(varName))
|
||||
if len(ret) == 0 {
|
||||
log.Info("Failed to read the default value from the environment. Will use the hardcoded default value.", "envvar", varName, "value", fallback)
|
||||
ret = fallback
|
||||
}
|
||||
}
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
func archDependent(envVarName string) string {
|
||||
return envVarName + "_" + runtime.GOARCH
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,25 @@
|
|||
//
|
||||
// Copyright (c) 2019-2021 Red Hat, Inc.
|
||||
// This program and the accompanying materials are made
|
||||
// available under the terms of the Eclipse Public License 2.0
|
||||
// which is available at https://www.eclipse.org/legal/epl-2.0/
|
||||
//
|
||||
// SPDX-License-Identifier: EPL-2.0
|
||||
//
|
||||
// Contributors:
|
||||
// Red Hat, Inc. - initial API and implementation
|
||||
//
|
||||
package devworkspace
|
||||
|
||||
import (
|
||||
"github.com/devfile/devworkspace-operator/pkg/infrastructure"
|
||||
defaults "github.com/eclipse-che/che-operator/pkg/common/operator-defaults"
|
||||
"github.com/eclipse-che/che-operator/pkg/common/test"
|
||||
)
|
||||
|
||||
func init() {
|
||||
test.EnableTestMode()
|
||||
|
||||
infrastructure.InitializeForTesting(infrastructure.OpenShiftv4)
|
||||
defaults.Initialize("../../config/manager/manager.yaml")
|
||||
}
|
||||
|
|
@ -21,7 +21,9 @@ import (
|
|||
|
||||
dw "github.com/devfile/api/v2/pkg/apis/workspaces/v1alpha2"
|
||||
|
||||
"github.com/eclipse-che/che-operator/pkg/util"
|
||||
"github.com/eclipse-che/che-operator/pkg/common/constants"
|
||||
defaults "github.com/eclipse-che/che-operator/pkg/common/operator-defaults"
|
||||
"github.com/eclipse-che/che-operator/pkg/common/utils"
|
||||
|
||||
"github.com/eclipse-che/che-operator/pkg/deploy/gateway"
|
||||
"k8s.io/apimachinery/pkg/api/resource"
|
||||
|
|
@ -30,11 +32,11 @@ import (
|
|||
dwo "github.com/devfile/devworkspace-operator/apis/controller/v1alpha1"
|
||||
"github.com/devfile/devworkspace-operator/controllers/controller/devworkspacerouting/solvers"
|
||||
"github.com/devfile/devworkspace-operator/pkg/common"
|
||||
"github.com/devfile/devworkspace-operator/pkg/constants"
|
||||
"github.com/eclipse-che/che-operator/api/v2alpha1"
|
||||
"github.com/eclipse-che/che-operator/controllers/devworkspace/defaults"
|
||||
dwconstants "github.com/devfile/devworkspace-operator/pkg/constants"
|
||||
"github.com/devfile/devworkspace-operator/pkg/infrastructure"
|
||||
chev2 "github.com/eclipse-che/che-operator/api/v2"
|
||||
dwdefaults "github.com/eclipse-che/che-operator/controllers/devworkspace/defaults"
|
||||
"github.com/eclipse-che/che-operator/controllers/devworkspace/sync"
|
||||
"github.com/eclipse-che/che-operator/pkg/deploy"
|
||||
"github.com/google/go-cmp/cmp/cmpopts"
|
||||
routeV1 "github.com/openshift/api/route/v1"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
|
|
@ -59,7 +61,7 @@ var (
|
|||
configMapDiffOpts = cmpopts.IgnoreFields(corev1.ConfigMap{}, "TypeMeta", "ObjectMeta")
|
||||
)
|
||||
|
||||
func (c *CheRoutingSolver) cheSpecObjects(cheCluster *v2alpha1.CheCluster, routing *dwo.DevWorkspaceRouting, workspaceMeta solvers.DevWorkspaceMetadata) (solvers.RoutingObjects, error) {
|
||||
func (c *CheRoutingSolver) cheSpecObjects(cheCluster *chev2.CheCluster, routing *dwo.DevWorkspaceRouting, workspaceMeta solvers.DevWorkspaceMetadata) (solvers.RoutingObjects, error) {
|
||||
objs := solvers.RoutingObjects{}
|
||||
|
||||
if err := c.provisionServices(&objs, cheCluster, routing, workspaceMeta); err != nil {
|
||||
|
|
@ -77,7 +79,7 @@ func (c *CheRoutingSolver) cheSpecObjects(cheCluster *v2alpha1.CheCluster, routi
|
|||
return objs, nil
|
||||
}
|
||||
|
||||
func (c *CheRoutingSolver) provisionServices(objs *solvers.RoutingObjects, cheCluster *v2alpha1.CheCluster, routing *dwo.DevWorkspaceRouting, workspaceMeta solvers.DevWorkspaceMetadata) error {
|
||||
func (c *CheRoutingSolver) provisionServices(objs *solvers.RoutingObjects, cheCluster *chev2.CheCluster, routing *dwo.DevWorkspaceRouting, workspaceMeta solvers.DevWorkspaceMetadata) error {
|
||||
objs.Services = solvers.GetDiscoverableServicesForEndpoints(routing.Spec.Endpoints, workspaceMeta)
|
||||
|
||||
commonService := &corev1.Service{
|
||||
|
|
@ -85,8 +87,8 @@ func (c *CheRoutingSolver) provisionServices(objs *solvers.RoutingObjects, cheCl
|
|||
Name: common.ServiceName(routing.Spec.DevWorkspaceId),
|
||||
Namespace: routing.Namespace,
|
||||
Labels: map[string]string{
|
||||
constants.DevWorkspaceIDLabel: routing.Spec.DevWorkspaceId,
|
||||
deploy.KubernetesPartOfLabelKey: deploy.CheEclipseOrg,
|
||||
dwconstants.DevWorkspaceIDLabel: routing.Spec.DevWorkspaceId,
|
||||
constants.KubernetesPartOfLabelKey: constants.CheEclipseOrg,
|
||||
},
|
||||
},
|
||||
Spec: corev1.ServiceSpec{
|
||||
|
|
@ -105,10 +107,10 @@ func (c *CheRoutingSolver) provisionServices(objs *solvers.RoutingObjects, cheCl
|
|||
objs.Services = append(objs.Services, *commonService)
|
||||
|
||||
annos := map[string]string{}
|
||||
annos[defaults.ConfigAnnotationCheManagerName] = cheCluster.Name
|
||||
annos[defaults.ConfigAnnotationCheManagerNamespace] = cheCluster.Namespace
|
||||
annos[dwdefaults.ConfigAnnotationCheManagerName] = cheCluster.Name
|
||||
annos[dwdefaults.ConfigAnnotationCheManagerNamespace] = cheCluster.Namespace
|
||||
|
||||
additionalLabels := defaults.GetLabelsForComponent(cheCluster, "exposure")
|
||||
additionalLabels := dwdefaults.GetLabelsForComponent(cheCluster, "exposure")
|
||||
|
||||
for i := range objs.Services {
|
||||
// need to use a ref otherwise s would be a copy
|
||||
|
|
@ -140,7 +142,7 @@ func (c *CheRoutingSolver) provisionServices(objs *solvers.RoutingObjects, cheCl
|
|||
return nil
|
||||
}
|
||||
|
||||
func (c *CheRoutingSolver) provisionRouting(objs *solvers.RoutingObjects, cheCluster *v2alpha1.CheCluster, routing *dwo.DevWorkspaceRouting, workspaceMeta solvers.DevWorkspaceMetadata) error {
|
||||
func (c *CheRoutingSolver) provisionRouting(objs *solvers.RoutingObjects, cheCluster *chev2.CheCluster, routing *dwo.DevWorkspaceRouting, workspaceMeta solvers.DevWorkspaceMetadata) error {
|
||||
// k, now we have to create our own objects for configuring the gateway
|
||||
configMaps, err := c.getGatewayConfigsAndFillRoutingObjects(cheCluster, workspaceMeta.DevWorkspaceId, routing, objs)
|
||||
if err != nil {
|
||||
|
|
@ -159,15 +161,23 @@ func (c *CheRoutingSolver) provisionRouting(objs *solvers.RoutingObjects, cheClu
|
|||
return nil
|
||||
}
|
||||
|
||||
func (c *CheRoutingSolver) provisionPodAdditions(objs *solvers.RoutingObjects, cheCluster *v2alpha1.CheCluster, routing *dwo.DevWorkspaceRouting) error {
|
||||
func (c *CheRoutingSolver) provisionPodAdditions(objs *solvers.RoutingObjects, cheCluster *chev2.CheCluster, routing *dwo.DevWorkspaceRouting) error {
|
||||
objs.PodAdditions = &dwo.PodAdditions{
|
||||
Containers: []corev1.Container{},
|
||||
Volumes: []corev1.Volume{},
|
||||
}
|
||||
|
||||
image := defaults.GetGatewayImage(cheCluster)
|
||||
for _, c := range cheCluster.Spec.Networking.Auth.Gateway.Deployment.Containers {
|
||||
if c.Name == constants.GatewayContainerName {
|
||||
image = c.Image
|
||||
}
|
||||
}
|
||||
|
||||
objs.PodAdditions.Containers = append(objs.PodAdditions.Containers, corev1.Container{
|
||||
Name: wsGatewayName,
|
||||
Image: cheCluster.Spec.Gateway.Image,
|
||||
ImagePullPolicy: corev1.PullPolicy(deploy.DefaultPullPolicyFromDockerImage(cheCluster.Spec.Gateway.Image)),
|
||||
Image: image,
|
||||
ImagePullPolicy: corev1.PullPolicy(utils.GetPullPolicyFromDockerImage(image)),
|
||||
VolumeMounts: []corev1.VolumeMount{
|
||||
{
|
||||
Name: wsGatewayName,
|
||||
|
|
@ -194,7 +204,7 @@ func (c *CheRoutingSolver) provisionPodAdditions(objs *solvers.RoutingObjects, c
|
|||
VolumeSource: corev1.VolumeSource{
|
||||
ConfigMap: &corev1.ConfigMapVolumeSource{
|
||||
LocalObjectReference: corev1.LocalObjectReference{
|
||||
Name: defaults.GetGatewayWorkspaceConfigMapName(routing.Spec.DevWorkspaceId),
|
||||
Name: dwdefaults.GetGatewayWorkspaceConfigMapName(routing.Spec.DevWorkspaceId),
|
||||
},
|
||||
DefaultMode: &defaultMode,
|
||||
},
|
||||
|
|
@ -204,14 +214,14 @@ func (c *CheRoutingSolver) provisionPodAdditions(objs *solvers.RoutingObjects, c
|
|||
return nil
|
||||
}
|
||||
|
||||
func (c *CheRoutingSolver) cheExposedEndpoints(cheCluster *v2alpha1.CheCluster, workspaceID string, componentEndpoints map[string]dwo.EndpointList, routingObj solvers.RoutingObjects) (exposedEndpoints map[string]dwo.ExposedEndpointList, ready bool, err error) {
|
||||
if cheCluster.Status.GatewayPhase == v2alpha1.GatewayPhaseInitializing {
|
||||
func (c *CheRoutingSolver) cheExposedEndpoints(cheCluster *chev2.CheCluster, workspaceID string, componentEndpoints map[string]dwo.EndpointList, routingObj solvers.RoutingObjects) (exposedEndpoints map[string]dwo.ExposedEndpointList, ready bool, err error) {
|
||||
if cheCluster.Status.GatewayPhase == chev2.GatewayPhaseInitializing {
|
||||
return nil, false, nil
|
||||
}
|
||||
|
||||
exposedEndpoints = map[string]dwo.ExposedEndpointList{}
|
||||
|
||||
gatewayHost := cheCluster.Status.GatewayHost
|
||||
gatewayHost := cheCluster.GetCheHost()
|
||||
|
||||
for component, endpoints := range componentEndpoints {
|
||||
for _, endpoint := range endpoints {
|
||||
|
|
@ -242,7 +252,7 @@ func (c *CheRoutingSolver) cheExposedEndpoints(cheCluster *v2alpha1.CheCluster,
|
|||
// try to find the endpoint in the ingresses/routes first. If it is there, it is exposed on a subdomain
|
||||
// otherwise it is exposed through the gateway
|
||||
var endpointURL string
|
||||
if util.IsOpenShift4 {
|
||||
if infrastructure.IsOpenShift() {
|
||||
route := findRouteForEndpoint(component, endpoint, &routingObj, workspaceID)
|
||||
if route != nil {
|
||||
endpointURL = path.Join(route.Spec.Host, endpoint.Path)
|
||||
|
|
@ -300,13 +310,13 @@ func isSecureScheme(scheme string) bool {
|
|||
return scheme == "https" || scheme == "wss"
|
||||
}
|
||||
|
||||
func (c *CheRoutingSolver) getGatewayConfigsAndFillRoutingObjects(cheCluster *v2alpha1.CheCluster, workspaceID string, routing *dwo.DevWorkspaceRouting, objs *solvers.RoutingObjects) ([]corev1.ConfigMap, error) {
|
||||
restrictedAnno, setRestrictedAnno := routing.Annotations[constants.DevWorkspaceRestrictedAccessAnnotation]
|
||||
func (c *CheRoutingSolver) getGatewayConfigsAndFillRoutingObjects(cheCluster *chev2.CheCluster, workspaceID string, routing *dwo.DevWorkspaceRouting, objs *solvers.RoutingObjects) ([]corev1.ConfigMap, error) {
|
||||
restrictedAnno, setRestrictedAnno := routing.Annotations[dwconstants.DevWorkspaceRestrictedAccessAnnotation]
|
||||
|
||||
cmLabels := defaults.AddStandardLabelsForComponent(cheCluster, "gateway-config", defaults.GetGatewayWorkspaceConfigMapLabels(cheCluster))
|
||||
cmLabels[constants.DevWorkspaceIDLabel] = workspaceID
|
||||
cmLabels := dwdefaults.AddStandardLabelsForComponent(cheCluster, "gateway-config", dwdefaults.GetGatewayWorkspaceConfigMapLabels(cheCluster))
|
||||
cmLabels[dwconstants.DevWorkspaceIDLabel] = workspaceID
|
||||
if setRestrictedAnno {
|
||||
cmLabels[constants.DevWorkspaceRestrictedAccessAnnotation] = restrictedAnno
|
||||
cmLabels[dwconstants.DevWorkspaceRestrictedAccessAnnotation] = restrictedAnno
|
||||
}
|
||||
|
||||
configs := make([]corev1.ConfigMap, 0)
|
||||
|
|
@ -330,8 +340,8 @@ func (c *CheRoutingSolver) getGatewayConfigsAndFillRoutingObjects(cheCluster *v2
|
|||
return configs, nil
|
||||
}
|
||||
|
||||
func (c *CheRoutingSolver) getInfraSpecificExposer(cheCluster *v2alpha1.CheCluster, routing *dwo.DevWorkspaceRouting, objs *solvers.RoutingObjects) (func(info *EndpointInfo), error) {
|
||||
if util.IsOpenShift4 {
|
||||
func (c *CheRoutingSolver) getInfraSpecificExposer(cheCluster *chev2.CheCluster, routing *dwo.DevWorkspaceRouting, objs *solvers.RoutingObjects) (func(info *EndpointInfo), error) {
|
||||
if infrastructure.IsOpenShift() {
|
||||
exposer := &RouteExposer{}
|
||||
if err := exposer.initFrom(context.TODO(), c.client, cheCluster, routing); err != nil {
|
||||
return nil, err
|
||||
|
|
@ -342,7 +352,7 @@ func (c *CheRoutingSolver) getInfraSpecificExposer(cheCluster *v2alpha1.CheClust
|
|||
}, nil
|
||||
} else {
|
||||
exposer := &IngressExposer{}
|
||||
if err := exposer.initFrom(context.TODO(), c.client, cheCluster, routing, defaults.GetIngressAnnotations(cheCluster)); err != nil {
|
||||
if err := exposer.initFrom(context.TODO(), c.client, cheCluster, routing, dwdefaults.GetIngressAnnotations(cheCluster)); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return func(info *EndpointInfo) {
|
||||
|
|
@ -362,7 +372,7 @@ func getCommonService(objs *solvers.RoutingObjects, dwId string) *corev1.Service
|
|||
return nil
|
||||
}
|
||||
|
||||
func exposeAllEndpoints(cheCluster *v2alpha1.CheCluster, routing *dwo.DevWorkspaceRouting, objs *solvers.RoutingObjects, ingressExpose func(*EndpointInfo)) *corev1.ConfigMap {
|
||||
func exposeAllEndpoints(cheCluster *chev2.CheCluster, routing *dwo.DevWorkspaceRouting, objs *solvers.RoutingObjects, ingressExpose func(*EndpointInfo)) *corev1.ConfigMap {
|
||||
wsRouteConfig := gateway.CreateEmptyTraefikConfig()
|
||||
|
||||
commonService := getCommonService(objs, routing.Spec.DevWorkspaceId)
|
||||
|
|
@ -415,11 +425,11 @@ func exposeAllEndpoints(cheCluster *v2alpha1.CheCluster, routing *dwo.DevWorkspa
|
|||
|
||||
wsConfigMap := &corev1.ConfigMap{
|
||||
ObjectMeta: v1.ObjectMeta{
|
||||
Name: defaults.GetGatewayWorkspaceConfigMapName(routing.Spec.DevWorkspaceId),
|
||||
Name: dwdefaults.GetGatewayWorkspaceConfigMapName(routing.Spec.DevWorkspaceId),
|
||||
Namespace: routing.Namespace,
|
||||
Labels: map[string]string{
|
||||
constants.DevWorkspaceIDLabel: routing.Spec.DevWorkspaceId,
|
||||
deploy.KubernetesPartOfLabelKey: deploy.CheEclipseOrg,
|
||||
dwconstants.DevWorkspaceIDLabel: routing.Spec.DevWorkspaceId,
|
||||
constants.KubernetesPartOfLabelKey: constants.CheEclipseOrg,
|
||||
},
|
||||
},
|
||||
Data: map[string]string{},
|
||||
|
|
@ -454,7 +464,7 @@ func containPort(service *corev1.Service, port int32) bool {
|
|||
return false
|
||||
}
|
||||
|
||||
func provisionMainWorkspaceRoute(cheCluster *v2alpha1.CheCluster, routing *dwo.DevWorkspaceRouting, cmLabels map[string]string) (*corev1.ConfigMap, error) {
|
||||
func provisionMainWorkspaceRoute(cheCluster *chev2.CheCluster, routing *dwo.DevWorkspaceRouting, cmLabels map[string]string) (*corev1.ConfigMap, error) {
|
||||
dwId := routing.Spec.DevWorkspaceId
|
||||
dwNamespace := routing.Namespace
|
||||
|
||||
|
|
@ -465,7 +475,7 @@ func provisionMainWorkspaceRoute(cheCluster *v2alpha1.CheCluster, routing *dwo.D
|
|||
getServiceURL(wsGatewayPort, dwId, dwNamespace),
|
||||
[]string{"/" + dwId})
|
||||
|
||||
if util.IsOpenShift4 {
|
||||
if infrastructure.IsOpenShift() {
|
||||
// on OpenShift, we need to set authorization header.
|
||||
// This MUST come before Auth, because Auth needs Authorization header to be properly set.
|
||||
cfg.AddAuthHeaderRewrite(dwId)
|
||||
|
|
@ -482,12 +492,12 @@ func provisionMainWorkspaceRoute(cheCluster *v2alpha1.CheCluster, routing *dwo.D
|
|||
} else {
|
||||
return &corev1.ConfigMap{
|
||||
ObjectMeta: v1.ObjectMeta{
|
||||
Name: defaults.GetGatewayWorkspaceConfigMapName(dwId),
|
||||
Name: dwdefaults.GetGatewayWorkspaceConfigMapName(dwId),
|
||||
Namespace: cheCluster.Namespace,
|
||||
Labels: cmLabels,
|
||||
Annotations: map[string]string{
|
||||
defaults.ConfigAnnotationDevWorkspaceRoutingName: routing.Name,
|
||||
defaults.ConfigAnnotationDevWorkspaceRoutingNamespace: routing.Namespace,
|
||||
dwdefaults.ConfigAnnotationDevWorkspaceRoutingName: routing.Name,
|
||||
dwdefaults.ConfigAnnotationDevWorkspaceRoutingNamespace: routing.Namespace,
|
||||
},
|
||||
},
|
||||
Data: map[string]string{dwId + ".yml": string(contents)},
|
||||
|
|
@ -501,7 +511,7 @@ func routeForHealthzEndpoint(cfg *gateway.TraefikConfig, dwId string, endpoints
|
|||
for _, e := range endpoints {
|
||||
if e.Attributes.GetString(string(dwo.TypeEndpointAttribute), nil) == string(dwo.MainEndpointType) {
|
||||
middlewares := []string{dwId + gateway.StripPrefixMiddlewareSuffix}
|
||||
if util.IsOpenShift4 {
|
||||
if infrastructure.IsOpenShift() {
|
||||
middlewares = append(middlewares, dwId+gateway.HeaderRewriteMiddlewareSuffix)
|
||||
}
|
||||
routeName, endpointPath := createEndpointPath(&e, componentName)
|
||||
|
|
@ -517,7 +527,7 @@ func routeForHealthzEndpoint(cfg *gateway.TraefikConfig, dwId string, endpoints
|
|||
}
|
||||
}
|
||||
|
||||
func addEndpointToTraefikConfig(componentName string, e dwo.Endpoint, cfg *gateway.TraefikConfig, cheCluster *v2alpha1.CheCluster, routing *dwo.DevWorkspaceRouting) {
|
||||
func addEndpointToTraefikConfig(componentName string, e dwo.Endpoint, cfg *gateway.TraefikConfig, cheCluster *chev2.CheCluster, routing *dwo.DevWorkspaceRouting) {
|
||||
routeName, prefix := createEndpointPath(&e, componentName)
|
||||
rulePrefix := fmt.Sprintf("PathPrefix(`%s`)", prefix)
|
||||
|
||||
|
|
@ -580,8 +590,8 @@ func findIngressForEndpoint(componentName string, endpoint dwo.Endpoint, objs *s
|
|||
for i := range objs.Ingresses {
|
||||
ingress := &objs.Ingresses[i]
|
||||
|
||||
if ingress.Annotations[defaults.ConfigAnnotationComponentName] != componentName ||
|
||||
ingress.Annotations[defaults.ConfigAnnotationEndpointName] != endpoint.Name {
|
||||
if ingress.Annotations[dwdefaults.ConfigAnnotationComponentName] != componentName ||
|
||||
ingress.Annotations[dwdefaults.ConfigAnnotationEndpointName] != endpoint.Name {
|
||||
continue
|
||||
}
|
||||
|
||||
|
|
@ -610,8 +620,8 @@ func findRouteForEndpoint(componentName string, endpoint dwo.Endpoint, objs *sol
|
|||
|
||||
for r := range objs.Routes {
|
||||
route := &objs.Routes[r]
|
||||
if route.Annotations[defaults.ConfigAnnotationComponentName] == componentName &&
|
||||
route.Annotations[defaults.ConfigAnnotationEndpointName] == endpoint.Name &&
|
||||
if route.Annotations[dwdefaults.ConfigAnnotationComponentName] == componentName &&
|
||||
route.Annotations[dwdefaults.ConfigAnnotationEndpointName] == endpoint.Name &&
|
||||
route.Spec.To.Kind == "Service" &&
|
||||
route.Spec.To.Name == service.Name &&
|
||||
route.Spec.Port.TargetPort.IntValue() == endpoint.TargetPort {
|
||||
|
|
@ -622,8 +632,8 @@ func findRouteForEndpoint(componentName string, endpoint dwo.Endpoint, objs *sol
|
|||
return nil
|
||||
}
|
||||
|
||||
func (c *CheRoutingSolver) cheRoutingFinalize(cheManager *v2alpha1.CheCluster, routing *dwo.DevWorkspaceRouting) error {
|
||||
selector, err := labels.Parse(fmt.Sprintf("%s=%s", constants.DevWorkspaceIDLabel, routing.Spec.DevWorkspaceId))
|
||||
func (c *CheRoutingSolver) cheRoutingFinalize(cheManager *chev2.CheCluster, routing *dwo.DevWorkspaceRouting) error {
|
||||
selector, err := labels.Parse(fmt.Sprintf("%s=%s", dwconstants.DevWorkspaceIDLabel, routing.Spec.DevWorkspaceId))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue