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
parent
cbfb771f07
commit
30740e8154
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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"`
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
Loading…
Reference in New Issue