// Copyright 2020-2023 Project Capsule Authors.
// SPDX-License-Identifier: Apache-2.0

package e2e

import (
	"context"

	. "github.com/onsi/ginkgo/v2"
	. "github.com/onsi/gomega"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/types"
	"k8s.io/utils/ptr"
	"sigs.k8s.io/controller-runtime/pkg/client"

	capsulev1beta2 "github.com/projectcapsule/capsule/api/v1beta2"
	"github.com/projectcapsule/capsule/pkg/api/meta"
	"github.com/projectcapsule/capsule/pkg/api/rbac"
)

var _ = Describe("Owners", Ordered, Label("config", "tenantowner", "tenant", "permissions", "owners"), func() {
	originConfig := &capsulev1beta2.CapsuleConfiguration{}

	tnt1 := &capsulev1beta2.Tenant{
		ObjectMeta: metav1.ObjectMeta{
			Name: "e2e-owners-1",
			Labels: map[string]string{
				"env": "e2e",
			},
		},
		Spec: capsulev1beta2.TenantSpec{
			Permissions: capsulev1beta2.Permissions{
				MatchOwners: []*metav1.LabelSelector{
					{
						MatchLabels: map[string]string{
							"customer":               "x",
							"e2e.suite.capsule/name": "owner_test",
						},
					},
					{
						MatchLabels: map[string]string{
							"team":                   "devops",
							"e2e.suite.capsule/name": "owner_test",
						},
					},
				},
			},
			Owners: rbac.OwnerListSpec{
				{
					CoreOwnerSpec: rbac.CoreOwnerSpec{
						UserSpec: rbac.UserSpec{
							Name: "e2e-owners-1",
							Kind: "User",
						},
					},
				},
				{
					CoreOwnerSpec: rbac.CoreOwnerSpec{
						UserSpec: rbac.UserSpec{
							Name: "e2e-owners-1-group",
							Kind: "Group",
						},
					},
				},
				{
					CoreOwnerSpec: rbac.CoreOwnerSpec{
						UserSpec: rbac.UserSpec{
							Name: "system:serviceaccount:capsule-system:capsule",
							Kind: "ServiceAccount",
						},
					},
				},
			},
		},
	}

	tnt2 := &capsulev1beta2.Tenant{
		ObjectMeta: metav1.ObjectMeta{
			Name: "e2e-owners-2",
			Labels: map[string]string{
				"env": "e2e",
			},
		},
		Spec: capsulev1beta2.TenantSpec{
			Permissions: capsulev1beta2.Permissions{
				MatchOwners: []*metav1.LabelSelector{
					{
						MatchLabels: map[string]string{
							"customer":               "x",
							"e2e.suite.capsule/name": "owner_test",
						},
					},
					{
						MatchLabels: map[string]string{
							"team":                   "infrastructure",
							"e2e.suite.capsule/name": "owner_test",
						},
					},
				},
			},
			Owners: rbac.OwnerListSpec{
				{
					CoreOwnerSpec: rbac.CoreOwnerSpec{
						UserSpec: rbac.UserSpec{
							Name: "e2e-owners-2",
							Kind: "User",
						},
					},
				},
				{
					CoreOwnerSpec: rbac.CoreOwnerSpec{
						UserSpec: rbac.UserSpec{
							Name: "e2e-owners-2-group",
							Kind: "Group",
						},
					},
				},
				{
					CoreOwnerSpec: rbac.CoreOwnerSpec{
						UserSpec: rbac.UserSpec{
							Name: "system:serviceaccount:capsule-system:capsule",
							Kind: "ServiceAccount",
						},
					},
				},
			},
		},
	}

	ownersInfra := &capsulev1beta2.TenantOwner{
		ObjectMeta: metav1.ObjectMeta{
			Name: "e2e-owners-infra",
			Labels: map[string]string{
				"team":                   "infrastructure",
				"e2e.suite.capsule/name": "owner_test",
			},
		},
		Spec: capsulev1beta2.TenantOwnerSpec{
			Aggregate: ptr.To(true),
			CoreOwnerSpec: rbac.CoreOwnerSpec{
				UserSpec: rbac.UserSpec{
					Kind: rbac.GroupOwner,
					Name: "oidc:comp:administrators",
				},
				ClusterRoles: []string{
					"admin",
				},
			},
		},
	}

	ownersDevops := &capsulev1beta2.TenantOwner{
		ObjectMeta: metav1.ObjectMeta{
			Name: "e2e-owners-devops",
			Labels: map[string]string{
				"team":                   "devops",
				"e2e.suite.capsule/name": "owner_test",
			},
		},
		Spec: capsulev1beta2.TenantOwnerSpec{
			Aggregate: ptr.To(true),
			CoreOwnerSpec: rbac.CoreOwnerSpec{
				UserSpec: rbac.UserSpec{
					Kind: rbac.GroupOwner,
					Name: "oidc:comp:devops",
				},
				ClusterRoles: []string{
					"view",
				},
			},
		},
	}

	ownersCommon := &capsulev1beta2.TenantOwner{
		ObjectMeta: metav1.ObjectMeta{
			Name: "e2e-owners-common",
			Labels: map[string]string{
				"team":                   "infrastructure",
				"customer":               "x",
				"e2e.suite.capsule/name": "owner_test",
			},
		},
		Spec: capsulev1beta2.TenantOwnerSpec{
			Aggregate: ptr.To(true),
			CoreOwnerSpec: rbac.CoreOwnerSpec{
				UserSpec: rbac.UserSpec{
					Kind: rbac.ServiceAccountOwner,
					Name: "system:serviceaccount:capsule-system:capsule",
				},
				ClusterRoles: []string{
					"edit",
				},
			},
		},
	}

	tnt1Owner := &capsulev1beta2.TenantOwner{
		ObjectMeta: metav1.ObjectMeta{
			Name: "e2e-owners-tnt",
			Labels: map[string]string{
				meta.NewTenantLabel: tnt1.GetName(),
			},
		},
		Spec: capsulev1beta2.TenantOwnerSpec{
			Aggregate: ptr.To(true),
			CoreOwnerSpec: rbac.CoreOwnerSpec{
				UserSpec: rbac.UserSpec{
					Kind: rbac.UserOwner,
					Name: "tnt-1-user",
				},
				ClusterRoles: []string{
					"edit",
				},
			},
		},
	}

	userOwnersCommon := &capsulev1beta2.TenantOwner{
		ObjectMeta: metav1.ObjectMeta{
			Name: "e2e-owners-common-user",
			Labels: map[string]string{
				"team":                   "infrastructure",
				"customer":               "x",
				"e2e.suite.capsule/name": "owner_test",
			},
		},
		Spec: capsulev1beta2.TenantOwnerSpec{
			Aggregate: ptr.To(false),
			CoreOwnerSpec: rbac.CoreOwnerSpec{
				UserSpec: rbac.UserSpec{
					Kind: rbac.UserOwner,
					Name: "some-user",
				},
				ClusterRoles: []string{
					"view",
				},
			},
		},
	}

	JustBeforeEach(func() {
		Expect(k8sClient.Get(context.Background(), client.ObjectKey{Name: defaultConfigurationName}, originConfig)).To(Succeed())

		for _, tnt := range []*capsulev1beta2.Tenant{tnt1, tnt2} {
			EventuallyCreation(func() error {
				tnt.ResourceVersion = ""

				return k8sClient.Create(context.TODO(), tnt)
			}).Should(Succeed())

			TenantReady(tnt, metav1.ConditionTrue, defaultTimeoutInterval)
		}

		for _, tnt := range []*capsulev1beta2.TenantOwner{ownersInfra, ownersDevops, ownersCommon, userOwnersCommon, tnt1Owner} {
			EventuallyCreation(func() error {
				tnt.ResourceVersion = ""

				return k8sClient.Create(context.TODO(), tnt)
			}).Should(Succeed())
		}
	})

	JustAfterEach(func() {
		for _, tnt := range []*capsulev1beta2.Tenant{tnt1, tnt2} {
			EventuallyDeletion(tnt)
		}

		for _, owners := range []*capsulev1beta2.TenantOwner{ownersInfra, ownersDevops, ownersCommon, userOwnersCommon, tnt1Owner} {
			EventuallyDeletion(owners)
		}
	})

	It("Verify owners for", func() {
		By("checking configuration", func() {
			Eventually(func(g Gomega) {
				cfg := &capsulev1beta2.CapsuleConfiguration{}
				err := k8sClient.Get(
					context.Background(),
					client.ObjectKey{Name: defaultConfigurationName},
					cfg,
				)
				g.Expect(err).ToNot(HaveOccurred())

				expected := rbac.UserListSpec{
					{Kind: ownersInfra.Spec.Kind, Name: ownersInfra.Spec.Name},
					{Kind: ownersDevops.Spec.Kind, Name: ownersDevops.Spec.Name},
					{Kind: ownersCommon.Spec.Kind, Name: ownersCommon.Spec.Name},
					{Kind: tnt1Owner.Spec.Kind, Name: tnt1Owner.Spec.Name},
					{Kind: rbac.GroupOwner, Name: "projectcapsule.dev"},
				}

				g.Expect(cfg.Status.Users).To(ConsistOf(expected))

				g.Expect(cfg.Status.Users).NotTo(ContainElement(
					rbac.UserSpec{Kind: userOwnersCommon.Spec.Kind, Name: userOwnersCommon.Spec.Name},
				))
			}, defaultTimeoutInterval, defaultPollInterval).Should(Succeed())
		})

		By("checking owners (e2e-owners-1)", func() {
			expectedOwners := rbac.OwnerStatusListSpec{
				{
					UserSpec: rbac.UserSpec{
						Kind: rbac.GroupOwner,
						Name: "e2e-owners-1-group",
					},
					ClusterRoles: []string{"admin", "capsule-namespace-deleter"},
				},
				{
					UserSpec: rbac.UserSpec{
						Kind: rbac.GroupOwner,
						Name: "oidc:comp:devops",
					},
					ClusterRoles: []string{"view"},
				},
				{
					UserSpec: rbac.UserSpec{
						Kind: rbac.ServiceAccountOwner,
						Name: "system:serviceaccount:capsule-system:capsule",
					},
					ClusterRoles: []string{"admin", "capsule-namespace-deleter", "edit"},
				},
				{
					UserSpec: rbac.UserSpec{
						Kind: rbac.UserOwner,
						Name: "e2e-owners-1",
					},
					ClusterRoles: []string{"admin", "capsule-namespace-deleter"},
				},
				{
					UserSpec: rbac.UserSpec{
						Kind: userOwnersCommon.Spec.Kind,
						Name: userOwnersCommon.Spec.Name,
					},
					ClusterRoles: []string{"view"},
				},
				{
					UserSpec: rbac.UserSpec{
						Kind: tnt1Owner.Spec.Kind,
						Name: tnt1Owner.Spec.Name,
					},
					ClusterRoles: []string{"edit"},
				},
			}

			t := &capsulev1beta2.Tenant{}
			Expect(k8sClient.Get(context.TODO(), types.NamespacedName{Name: tnt1.GetName()}, t)).Should(Succeed())

			t = ExpectTenantOwnersEventually(tnt1.GetName(), expectedOwners)
			VerifyTenantRoleBindings(t)
		})

		By("creating namespaces (e2e-owners-1)", func() {
			for _, u := range []rbac.UserSpec{
				rbac.UserSpec{
					Kind: rbac.GroupOwner,
					Name: "e2e-owners-1-group",
				},
				rbac.UserSpec{
					Kind: rbac.GroupOwner,
					Name: "oidc:comp:devops",
				},
				rbac.UserSpec{
					Kind: rbac.ServiceAccountOwner,
					Name: "system:serviceaccount:capsule-system:capsule",
				},
				rbac.UserSpec{
					Kind: rbac.UserOwner,
					Name: "e2e-owners-1",
				},
				rbac.UserSpec{
					Kind: userOwnersCommon.Spec.Kind,
					Name: userOwnersCommon.Spec.Name,
				},
				rbac.UserSpec{
					Kind: tnt1Owner.Spec.Kind,
					Name: tnt1Owner.Spec.Name,
				},
			} {
				ns := NewNamespace("", map[string]string{
					meta.TenantLabel: tnt1.GetName(),
				})
				NamespaceCreation(ns, u, defaultTimeoutInterval).Should(Succeed())
				NamespaceIsPartOfTenant(tnt1, ns).Should(Succeed())
			}
		})

		By("checking owners (e2e-owners-2)", func() {
			t := &capsulev1beta2.Tenant{}
			Expect(k8sClient.Get(context.TODO(), types.NamespacedName{Name: tnt2.GetName()}, t)).Should(Succeed())

			expectedOwners := rbac.OwnerStatusListSpec{
				{
					UserSpec: rbac.UserSpec{
						Kind: rbac.GroupOwner,
						Name: "e2e-owners-2-group",
					},
					ClusterRoles: []string{"admin", "capsule-namespace-deleter"},
				},
				{
					UserSpec: rbac.UserSpec{
						Kind: rbac.GroupOwner,
						Name: "oidc:comp:administrators",
					},
					ClusterRoles: []string{"admin"},
				},
				{
					UserSpec: rbac.UserSpec{
						Kind: rbac.ServiceAccountOwner,
						Name: "system:serviceaccount:capsule-system:capsule",
					},
					ClusterRoles: []string{"admin", "capsule-namespace-deleter", "edit"},
				},
				{
					UserSpec: rbac.UserSpec{
						Kind: rbac.UserOwner,
						Name: "e2e-owners-2",
					},
					ClusterRoles: []string{"admin", "capsule-namespace-deleter"},
				},

				{
					UserSpec: rbac.UserSpec{
						Kind: userOwnersCommon.Spec.Kind,
						Name: userOwnersCommon.Spec.Name,
					},
					ClusterRoles: []string{"view"},
				},
			}

			t = ExpectTenantOwnersEventually(tnt2.GetName(), expectedOwners)
			VerifyTenantRoleBindings(t)
		})

		By("creating namespaces (e2e-owners-2)", func() {
			for _, u := range []rbac.UserSpec{
				rbac.UserSpec{
					Kind: rbac.GroupOwner,
					Name: "e2e-owners-2-group",
				},
				rbac.UserSpec{
					Kind: rbac.GroupOwner,
					Name: "oidc:comp:administrators",
				},
				rbac.UserSpec{
					Kind: rbac.ServiceAccountOwner,
					Name: "system:serviceaccount:capsule-system:capsule",
				},
				rbac.UserSpec{
					Kind: rbac.UserOwner,
					Name: "e2e-owners-2",
				},
				rbac.UserSpec{
					Kind: userOwnersCommon.Spec.Kind,
					Name: userOwnersCommon.Spec.Name,
				},
			} {
				ns := NewNamespace("", map[string]string{
					meta.TenantLabel: tnt2.GetName(),
				})
				NamespaceCreation(ns, u, defaultTimeoutInterval).Should(Succeed())
				NamespaceIsPartOfTenant(tnt2, ns).Should(Succeed())
			}
		})

		By("remove common tenant-owners", func() {
			EventuallyDeletion(ownersCommon)
		})

		By("checking configuration", func() {
			Eventually(func(g Gomega) {
				cfg := &capsulev1beta2.CapsuleConfiguration{}
				err := k8sClient.Get(
					context.Background(),
					client.ObjectKey{Name: defaultConfigurationName},
					cfg,
				)
				g.Expect(err).ToNot(HaveOccurred())

				expected := rbac.UserListSpec{
					{Kind: ownersInfra.Spec.Kind, Name: ownersInfra.Spec.Name},
					{Kind: ownersDevops.Spec.Kind, Name: ownersDevops.Spec.Name},
					{Kind: tnt1Owner.Spec.Kind, Name: tnt1Owner.Spec.Name},
					{Kind: rbac.GroupOwner, Name: "projectcapsule.dev"},
				}

				g.Expect(cfg.Status.Users).To(ConsistOf(expected))
			}, defaultTimeoutInterval, defaultPollInterval).Should(Succeed())
		})

		By("checking owners (e2e-owners-1)", func() {
			t := &capsulev1beta2.Tenant{}
			Expect(k8sClient.Get(context.TODO(), types.NamespacedName{Name: tnt1.GetName()}, t)).Should(Succeed())

			expectedOwners := rbac.OwnerStatusListSpec{
				{
					UserSpec: rbac.UserSpec{
						Kind: rbac.GroupOwner,
						Name: "e2e-owners-1-group",
					},
					ClusterRoles: []string{"admin", "capsule-namespace-deleter"},
				},
				{
					UserSpec: rbac.UserSpec{
						Kind: rbac.GroupOwner,
						Name: "oidc:comp:devops",
					},
					ClusterRoles: []string{"view"},
				},
				{
					UserSpec: rbac.UserSpec{
						Kind: rbac.ServiceAccountOwner,
						Name: "system:serviceaccount:capsule-system:capsule",
					},
					ClusterRoles: []string{"admin", "capsule-namespace-deleter"},
				},
				{
					UserSpec: rbac.UserSpec{
						Kind: rbac.UserOwner,
						Name: "e2e-owners-1",
					},
					ClusterRoles: []string{"admin", "capsule-namespace-deleter"},
				},
				{
					UserSpec: rbac.UserSpec{
						Kind: userOwnersCommon.Spec.Kind,
						Name: userOwnersCommon.Spec.Name,
					},
					ClusterRoles: []string{"view"},
				},
				{
					UserSpec: rbac.UserSpec{
						Kind: tnt1Owner.Spec.Kind,
						Name: tnt1Owner.Spec.Name,
					},
					ClusterRoles: []string{"edit"},
				},
			}

			t = ExpectTenantOwnersEventually(tnt1.GetName(), expectedOwners)
			VerifyTenantRoleBindings(t)
		})

		By("checking owners (e2e-owners-2)", func() {
			t := &capsulev1beta2.Tenant{}
			Expect(k8sClient.Get(context.TODO(), types.NamespacedName{Name: tnt2.GetName()}, t)).Should(Succeed())

			expectedOwners := rbac.OwnerStatusListSpec{
				{
					UserSpec: rbac.UserSpec{
						Kind: rbac.GroupOwner,
						Name: "e2e-owners-2-group",
					},
					ClusterRoles: []string{"admin", "capsule-namespace-deleter"},
				},
				{
					UserSpec: rbac.UserSpec{
						Kind: rbac.GroupOwner,
						Name: "oidc:comp:administrators",
					},
					ClusterRoles: []string{"admin"},
				},
				{
					UserSpec: rbac.UserSpec{
						Kind: rbac.ServiceAccountOwner,
						Name: "system:serviceaccount:capsule-system:capsule",
					},
					ClusterRoles: []string{"admin", "capsule-namespace-deleter"},
				},
				{
					UserSpec: rbac.UserSpec{
						Kind: rbac.UserOwner,
						Name: "e2e-owners-2",
					},
					ClusterRoles: []string{"admin", "capsule-namespace-deleter"},
				},
				{
					UserSpec: rbac.UserSpec{
						Kind: userOwnersCommon.Spec.Kind,
						Name: userOwnersCommon.Spec.Name,
					},
					ClusterRoles: []string{"view"},
				},
			}

			t = ExpectTenantOwnersEventually(tnt2.GetName(), expectedOwners)
			VerifyTenantRoleBindings(t)
		})

		By("remove admin tenant-owners", func() {
			Expect(k8sClient.Delete(context.TODO(), ownersInfra)).Should(Succeed())
		})

		By("checking configuration", func() {
			Eventually(func(g Gomega) {
				cfg := &capsulev1beta2.CapsuleConfiguration{}
				err := k8sClient.Get(
					context.Background(),
					client.ObjectKey{Name: defaultConfigurationName},
					cfg,
				)
				g.Expect(err).ToNot(HaveOccurred())

				expected := rbac.UserListSpec{
					{Kind: ownersDevops.Spec.Kind, Name: ownersDevops.Spec.Name},
					{Kind: tnt1Owner.Spec.Kind, Name: tnt1Owner.Spec.Name},
					{Kind: rbac.GroupOwner, Name: "projectcapsule.dev"},
				}

				g.Expect(cfg.Status.Users).To(ConsistOf(expected))
			}, defaultTimeoutInterval, defaultPollInterval).Should(Succeed())
		})

		By("checking owners (e2e-owners-1)", func() {
			t := &capsulev1beta2.Tenant{}
			Expect(k8sClient.Get(context.TODO(), types.NamespacedName{Name: tnt1.GetName()}, t)).Should(Succeed())

			expectedOwners := rbac.OwnerStatusListSpec{
				{
					UserSpec: rbac.UserSpec{
						Kind: rbac.GroupOwner,
						Name: "e2e-owners-1-group",
					},
					ClusterRoles: []string{"admin", "capsule-namespace-deleter"},
				},
				{
					UserSpec: rbac.UserSpec{
						Kind: rbac.GroupOwner,
						Name: "oidc:comp:devops",
					},
					ClusterRoles: []string{"view"},
				},
				{
					UserSpec: rbac.UserSpec{
						Kind: rbac.ServiceAccountOwner,
						Name: "system:serviceaccount:capsule-system:capsule",
					},
					ClusterRoles: []string{"admin", "capsule-namespace-deleter"},
				},
				{
					UserSpec: rbac.UserSpec{
						Kind: rbac.UserOwner,
						Name: "e2e-owners-1",
					},
					ClusterRoles: []string{"admin", "capsule-namespace-deleter"},
				},
				{
					UserSpec: rbac.UserSpec{
						Kind: userOwnersCommon.Spec.Kind,
						Name: userOwnersCommon.Spec.Name,
					},
					ClusterRoles: []string{"view"},
				},
				{
					UserSpec: rbac.UserSpec{
						Kind: tnt1Owner.Spec.Kind,
						Name: tnt1Owner.Spec.Name,
					},
					ClusterRoles: []string{"edit"},
				},
			}

			t = ExpectTenantOwnersEventually(tnt1.GetName(), expectedOwners)
			VerifyTenantRoleBindings(t)
		})

		By("checking owners (e2e-owners-2)", func() {
			t := &capsulev1beta2.Tenant{}
			Expect(k8sClient.Get(context.TODO(), types.NamespacedName{Name: tnt2.GetName()}, t)).Should(Succeed())

			expectedOwners := rbac.OwnerStatusListSpec{
				{
					UserSpec: rbac.UserSpec{
						Kind: rbac.GroupOwner,
						Name: "e2e-owners-2-group",
					},
					ClusterRoles: []string{"admin", "capsule-namespace-deleter"},
				},
				{
					UserSpec: rbac.UserSpec{
						Kind: rbac.ServiceAccountOwner,
						Name: "system:serviceaccount:capsule-system:capsule",
					},
					ClusterRoles: []string{"admin", "capsule-namespace-deleter"},
				},
				{
					UserSpec: rbac.UserSpec{
						Kind: rbac.UserOwner,
						Name: "e2e-owners-2",
					},
					ClusterRoles: []string{"admin", "capsule-namespace-deleter"},
				},
				{
					UserSpec: rbac.UserSpec{
						Kind: userOwnersCommon.Spec.Kind,
						Name: userOwnersCommon.Spec.Name,
					},
					ClusterRoles: []string{"view"},
				},
			}

			t = ExpectTenantOwnersEventually(tnt2.GetName(), expectedOwners)
			VerifyTenantRoleBindings(t)
		})

		By("remove admin tenant-owners", func() {
			EventuallyDeletion(ownersDevops)
		})

		By("checking configuration", func() {
			Eventually(func(g Gomega) {
				cfg := &capsulev1beta2.CapsuleConfiguration{}
				err := k8sClient.Get(
					context.Background(),
					client.ObjectKey{Name: defaultConfigurationName},
					cfg,
				)
				g.Expect(err).ToNot(HaveOccurred())

				expected := rbac.UserListSpec{
					{Kind: tnt1Owner.Spec.Kind, Name: tnt1Owner.Spec.Name},
					{Kind: rbac.GroupOwner, Name: "projectcapsule.dev"},
				}

				g.Expect(cfg.Status.Users).To(ConsistOf(expected))
			}, defaultTimeoutInterval, defaultPollInterval).Should(Succeed())
		})

		By("checking owners (e2e-owners-1)", func() {
			t := &capsulev1beta2.Tenant{}
			Expect(k8sClient.Get(context.TODO(), types.NamespacedName{Name: tnt1.GetName()}, t)).Should(Succeed())

			expectedOwners := rbac.OwnerStatusListSpec{
				{
					UserSpec: rbac.UserSpec{
						Kind: rbac.GroupOwner,
						Name: "e2e-owners-1-group",
					},
					ClusterRoles: []string{"admin", "capsule-namespace-deleter"},
				},
				{
					UserSpec: rbac.UserSpec{
						Kind: rbac.ServiceAccountOwner,
						Name: "system:serviceaccount:capsule-system:capsule",
					},
					ClusterRoles: []string{"admin", "capsule-namespace-deleter"},
				},
				{
					UserSpec: rbac.UserSpec{
						Kind: rbac.UserOwner,
						Name: "e2e-owners-1",
					},
					ClusterRoles: []string{"admin", "capsule-namespace-deleter"},
				},
				{
					UserSpec: rbac.UserSpec{
						Kind: userOwnersCommon.Spec.Kind,
						Name: userOwnersCommon.Spec.Name,
					},
					ClusterRoles: []string{"view"},
				},
				{
					UserSpec: rbac.UserSpec{
						Kind: tnt1Owner.Spec.Kind,
						Name: tnt1Owner.Spec.Name,
					},
					ClusterRoles: []string{"edit"},
				},
			}

			t = ExpectTenantOwnersEventually(tnt1.GetName(), expectedOwners)
			VerifyTenantRoleBindings(t)
		})

		By("checking owners (e2e-owners-2)", func() {
			t := &capsulev1beta2.Tenant{}
			Expect(k8sClient.Get(context.TODO(), types.NamespacedName{Name: tnt2.GetName()}, t)).Should(Succeed())

			expectedOwners := rbac.OwnerStatusListSpec{
				{
					UserSpec: rbac.UserSpec{
						Kind: rbac.GroupOwner,
						Name: "e2e-owners-2-group",
					},
					ClusterRoles: []string{"admin", "capsule-namespace-deleter"},
				},
				{
					UserSpec: rbac.UserSpec{
						Kind: rbac.ServiceAccountOwner,
						Name: "system:serviceaccount:capsule-system:capsule",
					},
					ClusterRoles: []string{"admin", "capsule-namespace-deleter"},
				},
				{
					UserSpec: rbac.UserSpec{
						Kind: rbac.UserOwner,
						Name: "e2e-owners-2",
					},
					ClusterRoles: []string{"admin", "capsule-namespace-deleter"},
				},
				{
					UserSpec: rbac.UserSpec{
						Kind: userOwnersCommon.Spec.Kind,
						Name: userOwnersCommon.Spec.Name,
					},
					ClusterRoles: []string{"view"},
				},
			}

			t = ExpectTenantOwnersEventually(tnt2.GetName(), expectedOwners)
			VerifyTenantRoleBindings(t)
		})
	})
})

func ExpectTenantOwnersEventually(
	tenantName string,
	expected rbac.OwnerStatusListSpec,
) *capsulev1beta2.Tenant {
	var current *capsulev1beta2.Tenant

	Eventually(func(g Gomega) {
		current = &capsulev1beta2.Tenant{}

		g.Expect(k8sClient.Get(
			context.TODO(),
			types.NamespacedName{Name: tenantName},
			current,
		)).To(Succeed())

		g.Expect(normalizeOwners(current.Status.Owners)).
			To(Equal(normalizeOwners(expected)))
	}, defaultTimeoutInterval, defaultPollInterval).Should(Succeed())

	return current
}
