Add field for workspace cluster role to operator (#29)

* Add field for workspace cluster role to operator
* Update Che controller test to verify custom role.

Signed-off-by: John Collier <John.J.Collier@ibm.com>
pull/36/head
John Collier 2019-06-04 05:44:52 -04:00 committed by David Festal
parent cbfb771f07
commit 30740e8154
4 changed files with 38 additions and 11 deletions

View File

@ -1,3 +1,4 @@
#
# Copyright (c) 2012-2019 Red Hat, Inc.
# This program and the accompanying materials are made
@ -22,6 +23,9 @@ spec:
# defaults to `che`. When set to `codeready`, CodeReady Workspaces is deployed
# the difference is in images, labels, exec commands
cheFlavor: ''
# specifies a custom cluster role to user for the Che workspaces
# Uses the default roles if left blank.
cheWorkspaceClusterRole: ''
# when set to true the operator will attempt to get a secret in OpenShift router namespace
# to add it to Java trust store of Che server. Requires cluster-admin privileges for operator service account
selfSignedCert:

View File

@ -22,11 +22,11 @@ import (
type CheClusterSpec struct {
// INSERT ADDITIONAL SPEC FIELDS - desired state of cluster
// Important: Run "operator-sdk generate k8s" to regenerate code after modifying this file
Server CheClusterSpecServer `json:"server"`
Database CheClusterSpecDB `json:"database"`
Auth CheClusterSpecAuth `json:"auth"`
Storage CheClusterSpecStorage `json:"storage"`
K8SOnly CheClusterSpecK8SOnly `json:"k8s"`
Server CheClusterSpecServer `json:"server"`
Database CheClusterSpecDB `json:"database"`
Auth CheClusterSpecAuth `json:"auth"`
Storage CheClusterSpecStorage `json:"storage"`
K8SOnly CheClusterSpecK8SOnly `json:"k8s"`
}
type CheClusterSpecServer struct {
@ -42,6 +42,9 @@ type CheClusterSpecServer struct {
CheLogLevel string `json:"cheLogLevel"`
// CheDebug is debug mode for Che server. Defaults to false
CheDebug string `json:"cheDebug"`
// CustomClusterRoleName specifies a custom cluster role to user for the Che workspaces
// The default roles are used if this is left blank.
CheWorkspaceClusterRole string `json:"cheWorkspaceClusterRole"`
// SelfSignedCert signal about the necessity to get OpenShift router tls secret
// and extract certificate to add it to Java trust store for Che server
SelfSignedCert bool `json:"selfSignedCert"`

View File

@ -281,6 +281,17 @@ func (r *ReconcileChe) Reconcile(request reconcile.Request) (reconcile.Result, e
if err := r.CreateNewRoleBinding(instance, viewRoleBinding); err != nil {
return reconcile.Result{}, err
}
// If the user specified an additional cluster role to use for the Che workspace, create a role binding for it
// Use a role binding instead of a cluster role binding to keep the additional access scoped to the workspace's namespace
workspaceClusterRole := instance.Spec.Server.CheWorkspaceClusterRole
if workspaceClusterRole != "" {
customRoleBinding := deploy.NewRoleBinding(instance, "che-workspace-custom", workspaceServiceAccount.Name, workspaceClusterRole, "ClusterRole")
if err = r.CreateNewRoleBinding(instance, customRoleBinding); err != nil {
return reconcile.Result{}, err
}
}
if err := r.GenerateAndSaveFields(instance, request); err != nil {
instance, _ = r.GetCR(request)
return reconcile.Result{Requeue: true, RequeueAfter: time.Second * 1}, err
@ -474,7 +485,7 @@ func (r *ReconcileChe) Reconcile(request reconcile.Request) (reconcile.Result, e
if deployment.Spec.Template.Spec.Containers[0].Image != instance.Spec.Auth.KeycloakImage {
keycloakDeployment := deploy.NewKeycloakDeployment(instance, keycloakPostgresPassword, keycloakAdminPassword, cheFlavor)
logrus.Infof("Updating Keycloak deployment with an image %s", instance.Spec.Auth.KeycloakImage)
if err := r.client.Update(context.TODO(),keycloakDeployment); err!= nil {
if err := r.client.Update(context.TODO(), keycloakDeployment); err != nil {
logrus.Errorf("Failed to update Keycloak deployment: %s", err)
}
@ -487,8 +498,6 @@ func (r *ReconcileChe) Reconcile(request reconcile.Request) (reconcile.Result, e
}
}
if isOpenShift {
doInstallOpenShiftoAuthProvider := instance.Spec.Auth.OpenShiftOauth
if doInstallOpenShiftoAuthProvider {
@ -685,7 +694,7 @@ func (r *ReconcileChe) Reconcile(request reconcile.Request) (reconcile.Result, e
if err := controllerutil.SetControllerReference(instance, cheDeployment, r.scheme); err != nil {
logrus.Errorf("An error occurred: %s", err)
}
logrus.Infof("Updating deployment %s with new memory settings. Request: %s, limit: %s",cheDeployment.Name, desiredRequest, desiredLimit)
logrus.Infof("Updating deployment %s with new memory settings. Request: %s, limit: %s", cheDeployment.Name, desiredRequest, desiredLimit)
if err := r.client.Update(context.TODO(), cheDeployment); err != nil {
logrus.Errorf("Failed to update deployment: %s", err)
return reconcile.Result{}, err

View File

@ -13,12 +13,15 @@ package che
import (
"context"
"time"
orgv1 "github.com/eclipse/che-operator/pkg/apis/org/v1"
oauth "github.com/openshift/api/oauth/v1"
routev1 "github.com/openshift/api/route/v1"
"github.com/sirupsen/logrus"
appsv1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
rbacapi "k8s.io/api/rbac/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/types"
@ -26,7 +29,6 @@ import (
"sigs.k8s.io/controller-runtime/pkg/client/fake"
"sigs.k8s.io/controller-runtime/pkg/reconcile"
logf "sigs.k8s.io/controller-runtime/pkg/runtime/log"
"time"
"testing"
)
@ -63,6 +65,9 @@ func TestCheController(t *testing.T) {
},
Spec: orgv1.CheClusterSpec{
// todo add some spec to check controller ifs like external db, ssl etc
Server: orgv1.CheClusterSpecServer{
CheWorkspaceClusterRole: "cluster-admin",
},
},
}
// Objects to track in the fake client.
@ -121,6 +126,12 @@ func TestCheController(t *testing.T) {
t.Errorf("ConfigMap %s not found: %s", cm.Name, err)
}
// Get the custom role binding that should have been created for the role we passed in
rb := &rbacapi.RoleBinding{}
if err := cl.Get(context.TODO(), types.NamespacedName{Name: "che-workspace-custom", Namespace: cheCR.Namespace}, rb); err != nil {
t.Errorf("Custom role binding %s not found: %s", rb.Name, err)
}
// run a few checks to make sure the operator reconciled tls routes and updated configmap
if cm.Data["CHE_INFRA_OPENSHIFT_TLS__ENABLED"] != "true" {
t.Errorf("ConfigMap wasn't updated. Extecting true, got: %s", cm.Data["CHE_INFRA_OPENSHIFT_TLS__ENABLED"])
@ -207,7 +218,7 @@ func TestCheController(t *testing.T) {
}
actualStorageClassName := pvc.Spec.StorageClassName
if len(*actualStorageClassName) != len(fakeStorageClassName) {
t.Fatalf("Expecting %s storageClassName, got %s", fakeStorageClassName, *actualStorageClassName )
t.Fatalf("Expecting %s storageClassName, got %s", fakeStorageClassName, *actualStorageClassName)
}
// check if oAuthClient is deleted after CR is deleted (finalizer logic)