diff --git a/.ci/oci-nightly-olm.sh b/.ci/oci-nightly-olm.sh index a07f57bab..6a031497f 100755 --- a/.ci/oci-nightly-olm.sh +++ b/.ci/oci-nightly-olm.sh @@ -45,7 +45,11 @@ runTests() { waitDevWorkspaceControllerStarted sleep 10s - createWorksaceDevWorkspaceController + createWorkspaceDevWorkspaceController + waitWorkspaceStartedDevWorkspaceController + + sleep 10s + createWorkspaceDevWorkspaceCheOperator waitWorkspaceStartedDevWorkspaceController } diff --git a/.github/bin/common.sh b/.github/bin/common.sh index 5da9150dd..bb5887ee2 100755 --- a/.github/bin/common.sh +++ b/.github/bin/common.sh @@ -380,7 +380,7 @@ waitDevWorkspaceControllerStarted() { exit 1 } -createWorksaceDevWorkspaceController () { +createWorkspaceDevWorkspaceController () { oc apply -f https://raw.githubusercontent.com/devfile/devworkspace-operator/main/samples/flattened_theia-next.yaml -n ${NAMESPACE} } @@ -390,7 +390,7 @@ waitWorkspaceStartedDevWorkspaceController() { do pods=$(oc get pods -n ${NAMESPACE}) if [[ $pods =~ .*Running.* ]]; then - echo "[INFO] Wokrspace started succesfully" + echo "[INFO] Workspace started succesfully" return fi @@ -401,3 +401,7 @@ waitWorkspaceStartedDevWorkspaceController() { echo "Failed to start a workspace" exit 1 } + +createWorkspaceDevWorkspaceCheOperator() { + oc apply -f https://raw.githubusercontent.com/che-incubator/devworkspace-che-operator/main/samples/flattened_theia-nodejs.yaml -n ${NAMESPACE} +} diff --git a/Dockerfile b/Dockerfile index 54b59db9e..79fb8db4e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -13,7 +13,8 @@ # NOTE: using registry.redhat.io/rhel8/go-toolset requires login, which complicates automation # NOTE: since updateBaseImages.sh does not support other registries than RHCC, update to RHEL8 # https://access.redhat.com/containers/?tab=tags#/registry.access.redhat.com/devtools/go-toolset-rhel7 -ARG DEV_WORKSPACE_CONTROLLER_VERSION="master" +ARG DEV_WORKSPACE_CONTROLLER_VERSION="main" +ARG DEV_WORKSPACE_CHE_OPERATOR_VERSION="main" FROM registry.access.redhat.com/devtools/go-toolset-rhel7:1.13.15-4 as builder ENV PATH=/opt/rh/go-toolset-1.13/root/usr/bin:${PATH} \ @@ -33,6 +34,10 @@ RUN export ARCH="$(uname -m)" && if [[ ${ARCH} == "x86_64" ]]; then export ARCH= RUN curl -L https://api.github.com/repos/devfile/devworkspace-operator/zipball/${DEV_WORKSPACE_CONTROLLER_VERSION} > /tmp/devworkspace-operator.zip && \ unzip /tmp/devworkspace-operator.zip */deploy/deployment/* -d /tmp +# download devworkspace-che-operator templates +RUN curl -L https://api.github.com/repos/che-incubator/devworkspace-che-operator/zipball/${DEV_WORKSPACE_CHE_OPERATOR_VERSION} > /tmp/devworkspace-che-operator.zip && \ + unzip /tmp/devworkspace-che-operator.zip */deploy/deployment/* -d /tmp + # https://access.redhat.com/containers/?tab=tags#/registry.access.redhat.com/ubi8-minimal FROM registry.access.redhat.com/ubi8-minimal:8.3-291 @@ -43,6 +48,7 @@ COPY --from=builder /che-operator/templates/oauth-provision.sh /tmp/oauth-provis COPY --from=builder /che-operator/templates/delete-identity-provider.sh /tmp/delete-identity-provider.sh COPY --from=builder /che-operator/templates/create-github-identity-provider.sh /tmp/create-github-identity-provider.sh COPY --from=builder /tmp/devfile-devworkspace-operator-*/deploy /tmp/devworkspace-operator/templates +COPY --from=builder /tmp/che-incubator-devworkspace-che-operator-*/deploy /tmp/devworkspace-che-operator/templates # apply CVE fixes, if required RUN microdnf update -y librepo libnghttp2 && microdnf install httpd-tools && microdnf clean all && rm -rf /var/cache/yum && echo "Installed Packages" && rpm -qa | sort -V && echo "End Of Installed Packages" diff --git a/deploy/cluster_role.yaml b/deploy/cluster_role.yaml index b5a8653a9..54a7441a0 100644 --- a/deploy/cluster_role.yaml +++ b/deploy/cluster_role.yaml @@ -310,3 +310,74 @@ rules: verbs: - list - watch +# devworkspace-che requirements + - apiGroups: + - che.eclipse.org + resources: + - '*' + verbs: + - '*' + - apiGroups: + - che.eclipse.org + resources: + - chemanagers + verbs: + - '*' + - apiGroups: + - che.eclipse.org + resources: + - chemanagers/status + verbs: + - get + - patch + - update + - apiGroups: + - che.eclipse.org + resources: + - chemanagers/finalizers + verbs: + - update + - apiGroups: + - controller.devfile.io + resources: + - workspaceroutings + verbs: + - '*' + - apiGroups: + - controller.devfile.io + resources: + - workspaceroutings/finalizers + verbs: + - update + - apiGroups: + - controller.devfile.io + resources: + - workspaceroutings/status + verbs: + - get + - patch + - update + - apiGroups: + - '' + resources: + - configmap + verbs: + - create + - delete + - get + - list + - patch + - update + - watch + - apiGroups: + - apps + resources: + - deployments/finalizers + resourceNames: + - devworkspace-che-operator + verbs: + - update + - nonResourceURLs: + - /metrics + verbs: + - get diff --git a/deploy/olm-catalog/nightly/eclipse-che-preview-kubernetes/manifests/che-operator.clusterserviceversion.yaml b/deploy/olm-catalog/nightly/eclipse-che-preview-kubernetes/manifests/che-operator.clusterserviceversion.yaml index d88c6985d..23eedbb78 100644 --- a/deploy/olm-catalog/nightly/eclipse-che-preview-kubernetes/manifests/che-operator.clusterserviceversion.yaml +++ b/deploy/olm-catalog/nightly/eclipse-che-preview-kubernetes/manifests/che-operator.clusterserviceversion.yaml @@ -76,13 +76,13 @@ metadata: categories: Developer Tools certified: "false" containerImage: quay.io/eclipse/che-operator:nightly - createdAt: "2021-03-05T16:30:06Z" + createdAt: "2021-03-10T11:28:00Z" description: A Kube-native development solution that delivers portable and collaborative developer workspaces. operatorframework.io/suggested-namespace: eclipse-che repository: https://github.com/eclipse/che-operator support: Eclipse Foundation - name: eclipse-che-preview-kubernetes.v7.27.0-122.nightly + name: eclipse-che-preview-kubernetes.v7.28.0-124.nightly namespace: placeholder spec: apiservicedefinitions: {} @@ -461,6 +461,76 @@ spec: verbs: - list - watch + - apiGroups: + - che.eclipse.org + resources: + - '*' + verbs: + - '*' + - apiGroups: + - che.eclipse.org + resources: + - chemanagers + verbs: + - '*' + - apiGroups: + - che.eclipse.org + resources: + - chemanagers/status + verbs: + - get + - patch + - update + - apiGroups: + - che.eclipse.org + resources: + - chemanagers/finalizers + verbs: + - update + - apiGroups: + - controller.devfile.io + resources: + - workspaceroutings + verbs: + - '*' + - apiGroups: + - controller.devfile.io + resources: + - workspaceroutings/finalizers + verbs: + - update + - apiGroups: + - controller.devfile.io + resources: + - workspaceroutings/status + verbs: + - get + - patch + - update + - apiGroups: + - "" + resources: + - configmap + verbs: + - create + - delete + - get + - list + - patch + - update + - watch + - apiGroups: + - apps + resourceNames: + - devworkspace-che-operator + resources: + - deployments/finalizers + verbs: + - update + - nonResourceURLs: + - /metrics + verbs: + - get serviceAccountName: che-operator - rules: - apiGroups: @@ -719,4 +789,4 @@ spec: maturity: stable provider: name: Eclipse Foundation - version: 7.27.0-122.nightly + version: 7.28.0-124.nightly diff --git a/deploy/olm-catalog/nightly/eclipse-che-preview-openshift/manifests/che-operator.clusterserviceversion.yaml b/deploy/olm-catalog/nightly/eclipse-che-preview-openshift/manifests/che-operator.clusterserviceversion.yaml index 5527970df..08e411438 100644 --- a/deploy/olm-catalog/nightly/eclipse-che-preview-openshift/manifests/che-operator.clusterserviceversion.yaml +++ b/deploy/olm-catalog/nightly/eclipse-che-preview-openshift/manifests/che-operator.clusterserviceversion.yaml @@ -67,13 +67,13 @@ metadata: categories: Developer Tools, OpenShift Optional certified: "false" containerImage: quay.io/eclipse/che-operator:nightly - createdAt: "2021-03-05T16:30:13Z" + createdAt: "2021-03-10T11:28:09Z" description: A Kube-native development solution that delivers portable and collaborative developer workspaces in OpenShift. operatorframework.io/suggested-namespace: eclipse-che repository: https://github.com/eclipse/che-operator support: Eclipse Foundation - name: eclipse-che-preview-openshift.v7.27.0-112.nightly + name: eclipse-che-preview-openshift.v7.28.0-114.nightly namespace: placeholder spec: apiservicedefinitions: {} @@ -534,6 +534,76 @@ spec: verbs: - list - watch + - apiGroups: + - che.eclipse.org + resources: + - '*' + verbs: + - '*' + - apiGroups: + - che.eclipse.org + resources: + - chemanagers + verbs: + - '*' + - apiGroups: + - che.eclipse.org + resources: + - chemanagers/status + verbs: + - get + - patch + - update + - apiGroups: + - che.eclipse.org + resources: + - chemanagers/finalizers + verbs: + - update + - apiGroups: + - controller.devfile.io + resources: + - workspaceroutings + verbs: + - '*' + - apiGroups: + - controller.devfile.io + resources: + - workspaceroutings/finalizers + verbs: + - update + - apiGroups: + - controller.devfile.io + resources: + - workspaceroutings/status + verbs: + - get + - patch + - update + - apiGroups: + - "" + resources: + - configmap + verbs: + - create + - delete + - get + - list + - patch + - update + - watch + - apiGroups: + - apps + resourceNames: + - devworkspace-che-operator + resources: + - deployments/finalizers + verbs: + - update + - nonResourceURLs: + - /metrics + verbs: + - get serviceAccountName: che-operator - rules: - apiGroups: @@ -796,4 +866,4 @@ spec: maturity: stable provider: name: Eclipse Foundation - version: 7.27.0-112.nightly + version: 7.28.0-114.nightly diff --git a/local-debug.sh b/local-debug.sh index 8d2e449aa..b57a5e041 100755 --- a/local-debug.sh +++ b/local-debug.sh @@ -18,7 +18,8 @@ command -v operator-sdk >/dev/null 2>&1 || { echo "operator-sdk is not installed ECLIPSE_CHE_NAMESPACE="eclipse-che" ECLIPSE_CHE_CR="./deploy/crds/org_v1_che_cr.yaml" ECLIPSE_CHE_CRD="./deploy/crds/org_v1_che_crd.yaml" -DEV_WORKSPACE_CONTROLLER_VERSION="master" +DEV_WORKSPACE_CONTROLLER_VERSION="main" +DEV_WORKSPACE_CHE_OPERATOR_VERSION="main" # Stop execution on any error trap "catchFinish" EXIT SIGINT @@ -60,9 +61,22 @@ prepareTemplates() { curl -sL https://api.github.com/repos/devfile/devworkspace-operator/zipball/${DEV_WORKSPACE_CONTROLLER_VERSION} > /tmp/devworkspace-operator.zip - unzip /tmp/devworkspace-operator.zip */deploy/deployment/* -d /tmp + unzip /tmp/devworkspace-operator.zip '*/deploy/deployment/*' -d /tmp cp -r /tmp/devfile-devworkspace-operator*/deploy/* /tmp/devworkspace-operator/templates echo "[INFO] Downloading Dev Workspace operator templates completed." + + # Download Dev Workspace Che operator templates + echo "[INFO] Downloading Dev Workspace Che operator templates ..." + rm /tmp/devworkspace-che-operator.zip + rm -rf /tmp/che-incubator-devworkspace-che-operator-* + rm -rf /tmp/devworkspace-che-operator/ + mkdir -p /tmp/devworkspace-che-operator/templates + + curl -sL https://api.github.com/repos/che-incubator/devworkspace-che-operator/zipball/${DEV_WORKSPACE_CHE_OPERATOR_VERSION} > /tmp/devworkspace-che-operator.zip + + unzip /tmp/devworkspace-che-operator.zip '*/deploy/deployment/*' -d /tmp + cp -r /tmp/che-incubator-devworkspace-che-operator*/deploy/* /tmp/devworkspace-che-operator/templates + echo "[INFO] Downloading Dev Workspace Che operator templates completed." } createNamespace() { diff --git a/make-release.sh b/make-release.sh index 05f66b746..ad24d2430 100755 --- a/make-release.sh +++ b/make-release.sh @@ -28,6 +28,7 @@ init() { FORCE_UPDATE="" BUILDX_PLATFORMS="linux/amd64,linux/ppc64le" DEV_WORKSPACE_CONTROLLER_VERSION="master" + DEV_WORKSPACE_CHE_OPERATOR_VERSION="main" if [[ $# -lt 1 ]]; then usage; exit; fi @@ -41,6 +42,7 @@ init() { '--update-nightly-olm-files') UPDATE_NIGHTLY_OLM_FILES=true; shift 0;; '--prepare-community-operators-update') PREPARE_COMMUNITY_OPERATORS_UPDATE=true; shift 0;; '--dev-workspace-controller-version') DEV_WORKSPACE_CONTROLLER_VERSION=$2; shift 1;; + '--dev-workspace-che-operator-version') DEV_WORKSPACE_CHE_OPERATOR_VERSION=$2; shift 1;; '--force') FORCE_UPDATE="--force"; shift 0;; '--help'|'-h') usage; exit;; esac @@ -161,7 +163,7 @@ releaseOperatorCode() { docker login quay.io -u "${QUAY_ECLIPSE_CHE_USERNAME}" -p "${QUAY_ECLIPSE_CHE_PASSWORD}" echo "[INFO] releaseOperatorCode :: Build operator image in platforms: $BUILDX_PLATFORMS" - docker buildx build --build-arg DEV_WORKSPACE_CONTROLLER_VERSION=${DEV_WORKSPACE_CONTROLLER_VERSION} --platform "$BUILDX_PLATFORMS" --push -t "quay.io/eclipse/che-operator:${RELEASE}" . + docker buildx build --build-arg DEV_WORKSPACE_CONTROLLER_VERSION=${DEV_WORKSPACE_CONTROLLER_VERSION} --build-arg DEV_WORKSPACE_CHE_OPERATOR_VERSION=${DEV_WORKSPACE_CHE_OPERATOR_VERSION} --platform "$BUILDX_PLATFORMS" --push -t "quay.io/eclipse/che-operator:${RELEASE}" . } updateNightlyOlmFiles() { diff --git a/pkg/deploy/dev-workspace/dev_workspace.go b/pkg/deploy/dev-workspace/dev_workspace.go index 0ef6a8485..adf6af11d 100644 --- a/pkg/deploy/dev-workspace/dev_workspace.go +++ b/pkg/deploy/dev-workspace/dev_workspace.go @@ -25,17 +25,22 @@ import ( apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/types" "sigs.k8s.io/controller-runtime/pkg/client" ) const ( DevWorkspaceNamespace = "devworkspace-controller" + DevWorkspaceCheNamespace = "devworkspace-che" DevWorkspaceWebhookName = "controller.devfile.io" DevWorkspaceServiceAccount = "devworkspace-controller-serviceaccount" DevWorkspaceDeploymentName = "devworkspace-controller-manager" - DevWorkspaceTemplates = "/tmp/devworkspace-operator/templates/deployment/openshift/objects" + DevWorkspaceTemplates = "/tmp/devworkspace-operator/templates/deployment/openshift/objects" + DevWorkspaceCheTemplates = "/tmp/devworkspace-che-operator/templates/deployment/openshift/objects/" + DevWorkspaceServiceAccountFile = DevWorkspaceTemplates + "/devworkspace-controller-serviceaccount.ServiceAccount.yaml" DevWorkspaceRoleFile = DevWorkspaceTemplates + "/devworkspace-controller-leader-election-role.Role.yaml" DevWorkspaceClusterRoleFile = DevWorkspaceTemplates + "/devworkspace-controller-role.ClusterRole.yaml" @@ -52,6 +57,19 @@ const ( DevWorkspaceConfigMapFile = DevWorkspaceTemplates + "/devworkspace-controller-configmap.ConfigMap.yaml" DevWorkspaceDeploymentFile = DevWorkspaceTemplates + "/devworkspace-controller-manager.Deployment.yaml" + DevWorkspaceCheServiceAccountFile = DevWorkspaceCheTemplates + "/devworkspace-che-serviceaccount.ServiceAccount.yaml" + DevWorkspaceCheRoleFile = DevWorkspaceCheTemplates + "/devworkspace-che-leader-election-role.Role.yaml" + DevWorkspaceCheClusterRoleFile = DevWorkspaceCheTemplates + "/devworkspace-che-role.ClusterRole.yaml" + DevWorkspaceCheProxyClusterRoleFile = DevWorkspaceCheTemplates + "/devworkspace-che-proxy-role.ClusterRole.yaml" + DevWorkspaceCheMetricsReaderClusterRoleFile = DevWorkspaceCheTemplates + "/devworkspace-che-metrics-reader.ClusterRole.yaml" + DevWorkspaceCheRoleBindingFile = DevWorkspaceCheTemplates + "/devworkspace-che-leader-election-rolebinding.RoleBinding.yaml" + DevWorkspaceCheClusterRoleBindingFile = DevWorkspaceCheTemplates + "/devworkspace-che-rolebinding.ClusterRoleBinding.yaml" + DevWorkspaceCheProxyClusterRoleBindingFile = DevWorkspaceCheTemplates + "/devworkspace-che-proxy-rolebinding.ClusterRoleBinding.yaml" + DevWorkspaceCheManagersCRDFile = DevWorkspaceCheTemplates + "/chemanagers.che.eclipse.org.CustomResourceDefinition.yaml" + DevWorkspaceCheConfigMapFile = DevWorkspaceCheTemplates + "/devworkspace-che-configmap.ConfigMap.yaml" + DevWorkspaceCheDeploymentFile = DevWorkspaceCheTemplates + "/devworkspace-che-manager.Deployment.yaml" + DevWorkspaceCheMetricsServiceFile = DevWorkspaceCheTemplates + "/devworkspace-che-controller-manager-metrics-service.Service.yaml" + WebTerminalOperatorSubscriptionName = "web-terminal" WebTerminalOperatorNamespace = "openshift-operators" ) @@ -60,22 +78,39 @@ var ( // cachedObjects cachedObj = make(map[string]metav1.Object) syncItems = []func(*deploy.DeployContext) (bool, error){ - createNamespace, - syncServiceAccount, - syncClusterRole, - syncProxyClusterRole, - syncEditWorkspacesClusterRole, - syncViewWorkspacesClusterRole, - syncRole, - syncRoleBinding, - syncClusterRoleBinding, - syncProxyClusterRoleBinding, - syncCRD, - syncComponentsCRD, - syncTemplatesCRD, - syncWorkspaceRoutingCRD, - syncConfigMap, - syncDeployment, + createDwNamespace, + syncDwServiceAccount, + syncDwClusterRole, + syncDwProxyClusterRole, + syncDwEditWorkspacesClusterRole, + syncDwViewWorkspacesClusterRole, + syncDwRole, + syncDwRoleBinding, + syncDwClusterRoleBinding, + syncDwProxyClusterRoleBinding, + syncDwCRD, + syncDwComponentsCRD, + syncDwTemplatesCRD, + syncDwWorkspaceRoutingCRD, + syncDwConfigMap, + syncDwDeployment, + } + + syncDwCheItems = []func(*deploy.DeployContext) (bool, error){ + createDwCheNamespace, + syncDwCheServiceAccount, + syncDwCheClusterRole, + syncDwCheProxyClusterRole, + syncDwCheMetricsClusterRole, + syncDwCheLeaderRole, + syncDwCheLeaderRoleBinding, + syncDwCheProxyRoleBinding, + syncDwCheRoleBinding, + syncDwCheCRD, + synDwCheCR, + syncDwCheConfigMap, + syncDwCheMetricsService, + synDwCheDeployment, } ) @@ -112,6 +147,15 @@ func ReconcileDevWorkspace(deployContext *deploy.DeployContext) (bool, error) { } } + for _, syncItem := range syncDwCheItems { + done, err := syncItem(deployContext) + if !util.IsTestMode() { + if !done { + return false, err + } + } + } + return true, nil } @@ -134,7 +178,7 @@ func checkWebTerminalSubscription(deployContext *deploy.DeployContext) error { return errors.New("A non matching version of the Dev Workspace operator is already installed") } -func createNamespace(deployContext *deploy.DeployContext) (bool, error) { +func createDwNamespace(deployContext *deploy.DeployContext) (bool, error) { namespace := &corev1.Namespace{ TypeMeta: metav1.TypeMeta{ Kind: "Namespace", @@ -149,66 +193,167 @@ func createNamespace(deployContext *deploy.DeployContext) (bool, error) { return deploy.CreateIfNotExists(deployContext, namespace) } -func syncServiceAccount(deployContext *deploy.DeployContext) (bool, error) { +func syncDwServiceAccount(deployContext *deploy.DeployContext) (bool, error) { return syncObject(deployContext, DevWorkspaceServiceAccountFile, &corev1.ServiceAccount{}) } -func syncRole(deployContext *deploy.DeployContext) (bool, error) { +func syncDwRole(deployContext *deploy.DeployContext) (bool, error) { return syncObject(deployContext, DevWorkspaceRoleFile, &rbacv1.Role{}) } -func syncRoleBinding(deployContext *deploy.DeployContext) (bool, error) { +func syncDwRoleBinding(deployContext *deploy.DeployContext) (bool, error) { return syncObject(deployContext, DevWorkspaceRoleBindingFile, &rbacv1.RoleBinding{}) } -func syncClusterRoleBinding(deployContext *deploy.DeployContext) (bool, error) { +func syncDwClusterRoleBinding(deployContext *deploy.DeployContext) (bool, error) { return syncObject(deployContext, DevWorkspaceClusterRoleBindingFile, &rbacv1.ClusterRoleBinding{}) } -func syncProxyClusterRoleBinding(deployContext *deploy.DeployContext) (bool, error) { +func syncDwProxyClusterRoleBinding(deployContext *deploy.DeployContext) (bool, error) { return syncObject(deployContext, DevWorkspaceProxyClusterRoleBindingFile, &rbacv1.ClusterRoleBinding{}) } -func syncClusterRole(deployContext *deploy.DeployContext) (bool, error) { +func syncDwClusterRole(deployContext *deploy.DeployContext) (bool, error) { return syncObject(deployContext, DevWorkspaceClusterRoleFile, &rbacv1.ClusterRole{}) } -func syncProxyClusterRole(deployContext *deploy.DeployContext) (bool, error) { +func syncDwProxyClusterRole(deployContext *deploy.DeployContext) (bool, error) { return syncObject(deployContext, DevWorkspaceProxyClusterRoleFile, &rbacv1.ClusterRole{}) } -func syncViewWorkspacesClusterRole(deployContext *deploy.DeployContext) (bool, error) { +func syncDwViewWorkspacesClusterRole(deployContext *deploy.DeployContext) (bool, error) { return syncObject(deployContext, DevWorkspaceViewWorkspacesClusterRoleFile, &rbacv1.ClusterRole{}) } -func syncEditWorkspacesClusterRole(deployContext *deploy.DeployContext) (bool, error) { +func syncDwEditWorkspacesClusterRole(deployContext *deploy.DeployContext) (bool, error) { return syncObject(deployContext, DevWorkspaceEditWorkspacesClusterRoleFile, &rbacv1.ClusterRole{}) } -func syncWorkspaceRoutingCRD(deployContext *deploy.DeployContext) (bool, error) { +func syncDwWorkspaceRoutingCRD(deployContext *deploy.DeployContext) (bool, error) { return syncObject(deployContext, DevWorkspaceWorkspaceRoutingCRDFile, &apiextensionsv1.CustomResourceDefinition{}) } -func syncTemplatesCRD(deployContext *deploy.DeployContext) (bool, error) { +func syncDwTemplatesCRD(deployContext *deploy.DeployContext) (bool, error) { return syncObject(deployContext, DevWorkspaceTemplatesCRDFile, &apiextensionsv1.CustomResourceDefinition{}) } -func syncComponentsCRD(deployContext *deploy.DeployContext) (bool, error) { +func syncDwComponentsCRD(deployContext *deploy.DeployContext) (bool, error) { return syncObject(deployContext, DevWorkspaceComponentsCRDFile, &apiextensionsv1.CustomResourceDefinition{}) } -func syncCRD(deployContext *deploy.DeployContext) (bool, error) { +func syncDwCRD(deployContext *deploy.DeployContext) (bool, error) { return syncObject(deployContext, DevWorkspaceCRDFile, &apiextensionsv1.CustomResourceDefinition{}) } -func syncConfigMap(deployContext *deploy.DeployContext) (bool, error) { +func syncDwConfigMap(deployContext *deploy.DeployContext) (bool, error) { return syncObject(deployContext, DevWorkspaceConfigMapFile, &corev1.ConfigMap{}) } -func syncDeployment(deployContext *deploy.DeployContext) (bool, error) { +func syncDwDeployment(deployContext *deploy.DeployContext) (bool, error) { return syncObject(deployContext, DevWorkspaceDeploymentFile, &appsv1.Deployment{}) } +func createDwCheNamespace(deployContext *deploy.DeployContext) (bool, error) { + namespace := &corev1.Namespace{ + TypeMeta: metav1.TypeMeta{ + Kind: "Namespace", + APIVersion: corev1.SchemeGroupVersion.String(), + }, + ObjectMeta: metav1.ObjectMeta{ + Name: DevWorkspaceCheNamespace, + }, + Spec: corev1.NamespaceSpec{}, + } + + return deploy.CreateIfNotExists(deployContext, namespace) +} + +func syncDwCheServiceAccount(deployContext *deploy.DeployContext) (bool, error) { + return syncObject(deployContext, DevWorkspaceCheServiceAccountFile, &corev1.ServiceAccount{}) +} + +func syncDwCheClusterRole(deployContext *deploy.DeployContext) (bool, error) { + return syncObject(deployContext, DevWorkspaceCheClusterRoleFile, &rbacv1.ClusterRole{}) +} + +func syncDwCheProxyClusterRole(deployContext *deploy.DeployContext) (bool, error) { + return syncObject(deployContext, DevWorkspaceCheProxyClusterRoleFile, &rbacv1.ClusterRole{}) +} + +func syncDwCheMetricsClusterRole(deployContext *deploy.DeployContext) (bool, error) { + return syncObject(deployContext, DevWorkspaceCheMetricsReaderClusterRoleFile, &rbacv1.ClusterRole{}) +} + +func syncDwCheLeaderRole(deployContext *deploy.DeployContext) (bool, error) { + return syncObject(deployContext, DevWorkspaceCheRoleFile, &rbacv1.Role{}) +} + +func syncDwCheLeaderRoleBinding(deployContext *deploy.DeployContext) (bool, error) { + return syncObject(deployContext, DevWorkspaceCheRoleBindingFile, &rbacv1.RoleBinding{}) +} + +func syncDwCheProxyRoleBinding(deployContext *deploy.DeployContext) (bool, error) { + return syncObject(deployContext, DevWorkspaceCheProxyClusterRoleBindingFile, &rbacv1.ClusterRoleBinding{}) +} + +func syncDwCheRoleBinding(deployContext *deploy.DeployContext) (bool, error) { + return syncObject(deployContext, DevWorkspaceCheClusterRoleBindingFile, &rbacv1.ClusterRoleBinding{}) +} + +func syncDwCheCRD(deployContext *deploy.DeployContext) (bool, error) { + return syncObject(deployContext, DevWorkspaceCheManagersCRDFile, &apiextensionsv1.CustomResourceDefinition{}) +} + +func syncDwCheConfigMap(deployContext *deploy.DeployContext) (bool, error) { + return syncObject(deployContext, DevWorkspaceCheConfigMapFile, &corev1.ConfigMap{}) +} + +func syncDwCheMetricsService(deployContext *deploy.DeployContext) (bool, error) { + return syncObject(deployContext, DevWorkspaceCheMetricsServiceFile, &corev1.Service{}) +} + +func synDwCheCR(deployContext *deploy.DeployContext) (bool, error) { + // We want to create a default CheManager instance to be able to configure the che-specific + // parts of the installation, but at the same time we don't want to add a dependency on + // devworkspace-che-operator. Note that this way of initializing will probably see changes + // once we figure out https://github.com/eclipse/che/issues/19220 + obj := &unstructured.Unstructured{} + obj.SetGroupVersionKind(schema.GroupVersionKind{Group: "che.eclipse.org", Version: "v1alpha1", Kind: "CheManager"}) + err := deployContext.ClusterAPI.Client.Get(context.TODO(), client.ObjectKey{Name: "devworkspace-che", Namespace: DevWorkspaceNamespace}, obj) + if err != nil { + if apierrors.IsNotFound(err) { + obj = nil + } else { + return false, err + } + } + + if obj == nil { + obj := &unstructured.Unstructured{} + obj.SetGroupVersionKind(schema.GroupVersionKind{ + Group: "che.eclipse.org", + Version: "v1alpha1", + Kind: "CheManager", + }) + obj.SetName("devworkspace-che") + obj.SetNamespace(DevWorkspaceCheNamespace) + + err = deployContext.ClusterAPI.Client.Create(context.TODO(), obj) + if err != nil { + if apierrors.IsAlreadyExists(err) { + return false, nil + } + return false, err + } + } + + return true, nil +} + +func synDwCheDeployment(deployContext *deploy.DeployContext) (bool, error) { + return syncObject(deployContext, DevWorkspaceCheDeploymentFile, &appsv1.Deployment{}) +} + func syncObject(deployContext *deploy.DeployContext, yamlFile string, obj interface{}) (bool, error) { _, exists := cachedObj[yamlFile] if !exists { diff --git a/pkg/deploy/dev-workspace/dev_workspace_test.go b/pkg/deploy/dev-workspace/dev_workspace_test.go index cfc6cc1bc..7c3e63844 100644 --- a/pkg/deploy/dev-workspace/dev_workspace_test.go +++ b/pkg/deploy/dev-workspace/dev_workspace_test.go @@ -12,13 +12,18 @@ package devworkspace import ( + "context" + orgv1 "github.com/eclipse/che-operator/pkg/apis/org/v1" "github.com/eclipse/che-operator/pkg/deploy" "github.com/eclipse/che-operator/pkg/util" operatorsv1alpha1 "github.com/operator-framework/api/pkg/operators/v1alpha1" admissionregistrationv1 "k8s.io/api/admissionregistration/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/client-go/kubernetes/scheme" + "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/client/fake" "testing" @@ -62,6 +67,19 @@ func TestReconcileDevWorkspace(t *testing.T) { if !done { t.Fatalf("Dev Workspace operator has not been provisioned") } + + t.Run("defaultCheManagerDeployed", func(t *testing.T) { + obj := &unstructured.Unstructured{} + obj.SetGroupVersionKind(schema.GroupVersionKind{Group: "che.eclipse.org", Version: "v1alpha1", Kind: "CheManager"}) + err := cli.Get(context.TODO(), client.ObjectKey{Name: "devworkspace-che", Namespace: DevWorkspaceCheNamespace}, obj) + if err != nil { + t.Fatalf("Should have found a CheManager with default config but got an error: %s", err) + } + + if obj.GetName() != "devworkspace-che" { + t.Fatalf("Should have found a CheManager with default config but found: %s", obj.GetName()) + } + }) } func TestReconcileDevWorkspaceShouldThrowErrorIfWebTerminalSubscriptionExists(t *testing.T) {