diff --git a/controllers/che/checluster_controller.go b/controllers/che/checluster_controller.go index d79a76e60..3ff76ca2d 100644 --- a/controllers/che/checluster_controller.go +++ b/controllers/che/checluster_controller.go @@ -573,7 +573,7 @@ func (r *CheClusterReconciler) Reconcile(req ctrl.Request) (ctrl.Result, error) } d := dashboard.NewDashboard(deployContext) - done, err = d.SyncAll() + done, err = d.Reconcile() if !done { if err != nil { logrus.Errorf("Error provisioning '%s' to cluster: %v", d.GetComponentName(), err) @@ -794,12 +794,15 @@ func (r *CheClusterReconciler) reconcileFinalizers(deployContext *deploy.DeployC logrus.Error(err) } - if err := deploy.ReconcileClusterRoleBindingFinalizer(deployContext, dashboard.DashboardSAClusterRoleBinding); err != nil { + if err := deploy.ReconcileConsoleLinkFinalizer(deployContext); err != nil { logrus.Error(err) } - if err := deploy.ReconcileConsoleLinkFinalizer(deployContext); err != nil { - logrus.Error(err) + if !deployContext.CheCluster.ObjectMeta.DeletionTimestamp.IsZero() { + done, err := dashboard.NewDashboard(deployContext).Finalize() + if !done { + logrus.Error(err) + } } if len(deployContext.CheCluster.Spec.Server.CheClusterRoles) > 0 { diff --git a/pkg/deploy/dashboard/dashboard.go b/pkg/deploy/dashboard/dashboard.go index ec9dd9eb4..b2311bb28 100644 --- a/pkg/deploy/dashboard/dashboard.go +++ b/pkg/deploy/dashboard/dashboard.go @@ -15,6 +15,8 @@ import ( "github.com/eclipse-che/che-operator/pkg/deploy" "github.com/eclipse-che/che-operator/pkg/deploy/expose" "github.com/eclipse-che/che-operator/pkg/util" + rbacv1 "k8s.io/api/rbac/v1" + "k8s.io/apimachinery/pkg/types" ) type Dashboard struct { @@ -29,7 +31,11 @@ func NewDashboard(deployContext *deploy.DeployContext) *Dashboard { } } -func (d *Dashboard) SyncAll() (done bool, err error) { +func (d *Dashboard) GetComponentName() string { + return d.component +} + +func (d *Dashboard) Reconcile() (done bool, err error) { // Create a new dashboard service done, err = deploy.SyncServiceToCluster(d.deployContext, d.component, []string{"http"}, []int32{8080}, d.component) if !done { @@ -54,15 +60,20 @@ func (d *Dashboard) SyncAll() (done bool, err error) { // on Kubernetes Dashboard needs privileged SA to work with user's objects // for time being until Kubernetes did not get authentication if !util.IsOpenShift { - done, err = deploy.SyncClusterRoleToCluster(d.deployContext, DashboardSAClusterRole, GetPrivilegedPoliciesRulesForKubernetes()) + done, err = deploy.SyncClusterRoleToCluster(d.deployContext, d.getClusterRoleName(), GetPrivilegedPoliciesRulesForKubernetes()) if !done { return false, err } - done, err = deploy.SyncClusterRoleBindingAndAddFinalizerToCluster(d.deployContext, DashboardSAClusterRoleBinding, DashboardSA, DashboardSAClusterRole) + done, err = deploy.SyncClusterRoleBindingToCluster(d.deployContext, d.getClusterRoleBindingName(), DashboardSA, d.getClusterRoleName()) if !done { return false, err } + + err = deploy.AppendFinalizer(d.deployContext, ClusterPermissionsDashboardFinalizer) + if err != nil { + return false, err + } } // Deploy dashboard @@ -73,6 +84,17 @@ func (d *Dashboard) SyncAll() (done bool, err error) { return deploy.SyncDeploymentSpecToCluster(d.deployContext, spec, deploy.DefaultDeploymentDiffOpts) } -func (d *Dashboard) GetComponentName() string { - return d.component +func (d *Dashboard) Finalize() (done bool, err error) { + done, err = deploy.Delete(d.deployContext, types.NamespacedName{Name: d.getClusterRoleName()}, &rbacv1.ClusterRole{}) + if !done { + return false, err + } + + done, err = deploy.Delete(d.deployContext, types.NamespacedName{Name: d.getClusterRoleBindingName()}, &rbacv1.ClusterRoleBinding{}) + if !done { + return false, err + } + + err = deploy.DeleteFinalizer(d.deployContext, ClusterPermissionsDashboardFinalizer) + return err == nil, err } diff --git a/pkg/deploy/dashboard/dashboard_test.go b/pkg/deploy/dashboard/dashboard_test.go index 30930df4e..e71b9610f 100644 --- a/pkg/deploy/dashboard/dashboard_test.go +++ b/pkg/deploy/dashboard/dashboard_test.go @@ -13,6 +13,7 @@ package dashboard import ( "context" + "fmt" "github.com/eclipse-che/che-operator/pkg/deploy" "github.com/eclipse-che/che-operator/pkg/util" @@ -32,10 +33,12 @@ import ( "testing" ) +const Namespace = "eclipse-che" + func TestDashboardOpenShift(t *testing.T) { cheCluster := &orgv1.CheCluster{ ObjectMeta: metav1.ObjectMeta{ - Namespace: "eclipse-che", + Namespace: Namespace, Name: "eclipse-che", }, } @@ -56,7 +59,7 @@ func TestDashboardOpenShift(t *testing.T) { util.IsOpenShift = true dashboard := NewDashboard(deployContext) - done, err := dashboard.SyncAll() + done, err := dashboard.Reconcile() if !done || err != nil { t.Fatalf("Failed to sync Dashboard: %v", err) } @@ -88,12 +91,12 @@ func TestDashboardOpenShift(t *testing.T) { t.Fatalf("Service account not found: %v", err) } - err = cli.Get(context.TODO(), types.NamespacedName{Name: DashboardSAClusterRole}, &rbacv1.ClusterRole{}) + err = cli.Get(context.TODO(), types.NamespacedName{Name: fmt.Sprintf(DashboardSAClusterRoleTemplate, Namespace)}, &rbacv1.ClusterRole{}) if err == nil || !errors.IsNotFound(err) { t.Fatalf("ClusterRole is created or failed to check on OpenShift: %v", err) } - err = cli.Get(context.TODO(), types.NamespacedName{Name: DashboardSAClusterRoleBinding}, &rbacv1.ClusterRoleBinding{}) + err = cli.Get(context.TODO(), types.NamespacedName{Name: fmt.Sprintf(DashboardSAClusterRoleBindingTemplate, Namespace)}, &rbacv1.ClusterRoleBinding{}) if err == nil || !errors.IsNotFound(err) { t.Fatalf("ClusterRoleBinding is created or failed to check on OpenShift: %v", err) } @@ -102,7 +105,7 @@ func TestDashboardOpenShift(t *testing.T) { func TestDashboardKubernetes(t *testing.T) { cheCluster := &orgv1.CheCluster{ ObjectMeta: metav1.ObjectMeta{ - Namespace: "eclipse-che", + Namespace: Namespace, Name: "eclipse-che", }, } @@ -123,7 +126,7 @@ func TestDashboardKubernetes(t *testing.T) { util.IsOpenShift = false dashboard := NewDashboard(deployContext) - done, err := dashboard.SyncAll() + done, err := dashboard.Reconcile() if !done || err != nil { t.Fatalf("Failed to sync Dashboard: %v", err) } @@ -156,13 +159,13 @@ func TestDashboardKubernetes(t *testing.T) { } clusterRole := &rbacv1.ClusterRole{} - err = cli.Get(context.TODO(), types.NamespacedName{Name: DashboardSAClusterRole}, clusterRole) + err = cli.Get(context.TODO(), types.NamespacedName{Name: fmt.Sprintf(DashboardSAClusterRoleTemplate, Namespace)}, clusterRole) if err != nil { t.Fatalf("ClusterRole is not found on K8s: %v", err) } clusterRoleBinding := &rbacv1.ClusterRoleBinding{} - err = cli.Get(context.TODO(), types.NamespacedName{Name: DashboardSAClusterRoleBinding}, clusterRoleBinding) + err = cli.Get(context.TODO(), types.NamespacedName{Name: fmt.Sprintf(DashboardSAClusterRoleBindingTemplate, Namespace)}, clusterRoleBinding) if err != nil { t.Fatalf("ClusterRoleBinding is not found on k8s: %v", err) } diff --git a/pkg/deploy/dashboard/rbac.go b/pkg/deploy/dashboard/rbac.go index 2b9203b4e..c14123c11 100644 --- a/pkg/deploy/dashboard/rbac.go +++ b/pkg/deploy/dashboard/rbac.go @@ -12,12 +12,16 @@ package dashboard import ( + "fmt" + rbacv1 "k8s.io/api/rbac/v1" ) +const ClusterPermissionsDashboardFinalizer = "dashboard.clusterpermissions.finalizers.che.eclipse.org" + const DashboardSA = "che-dashboard" -const DashboardSAClusterRole = "che-dashboard" -const DashboardSAClusterRoleBinding = "che-dashboard" +const DashboardSAClusterRoleTemplate = "%s-che-dashboard" +const DashboardSAClusterRoleBindingTemplate = "%s-che-dashboard" func GetPrivilegedPoliciesRulesForKubernetes() []rbacv1.PolicyRule { return []rbacv1.PolicyRule{ @@ -38,3 +42,11 @@ func GetPrivilegedPoliciesRulesForKubernetes() []rbacv1.PolicyRule { }, } } + +func (d *Dashboard) getClusterRoleName() string { + return fmt.Sprintf(DashboardSAClusterRoleTemplate, d.deployContext.CheCluster.Namespace) +} + +func (d *Dashboard) getClusterRoleBindingName() string { + return fmt.Sprintf(DashboardSAClusterRoleBindingTemplate, d.deployContext.CheCluster.Namespace) +}