package utils
import (
"context"
"fmt"
authenticationv1 "k8s.io/api/authentication/v1"
corev1 "k8s.io/api/core/v1"
rbacv1 "k8s.io/api/rbac/v1"
apierrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"gitcode.com/openFuyao/e2e-auto-test/e2e/framework/k8s"
)
const (
tenantSAName = "sdb-e2e-tenant"
tenantRoleName = "sdb-e2e-tenant-role"
norbacSAName = "sdb-e2e-norbac"
)
var tenantRules = []rbacv1.PolicyRule{
{APIGroups: []string{GroupName}, Resources: []string{ResDBInsts}, Verbs: []string{"get", "list", "patch", "delete"}},
{APIGroups: []string{GroupName}, Resources: []string{ResDBInsts + "/status"}, Verbs: []string{"patch"}},
{APIGroups: []string{""}, Resources: []string{"pods"}, Verbs: []string{"get", "patch"}},
{APIGroups: []string{""}, Resources: []string{"services"}, Verbs: []string{"get", "create", "delete"}},
}
func CreateTenantSA(ctx context.Context, k8sClient *k8s.K8SClient, ns string) (string, error) {
saClient := k8sClient.Clientset.CoreV1().ServiceAccounts(ns)
_, err := saClient.Get(ctx, tenantSAName, metav1.GetOptions{})
if apierrors.IsNotFound(err) {
_, err = saClient.Create(ctx, &corev1.ServiceAccount{
ObjectMeta: metav1.ObjectMeta{Name: tenantSAName, Namespace: ns},
}, metav1.CreateOptions{})
if err != nil {
return "", fmt.Errorf("create tenant SA: %w", err)
}
} else if err != nil {
return "", fmt.Errorf("get tenant SA: %w", err)
}
roleClient := k8sClient.Clientset.RbacV1().Roles(ns)
_, err = roleClient.Get(ctx, tenantRoleName, metav1.GetOptions{})
if apierrors.IsNotFound(err) {
_, err = roleClient.Create(ctx, &rbacv1.Role{
ObjectMeta: metav1.ObjectMeta{Name: tenantRoleName, Namespace: ns},
Rules: tenantRules,
}, metav1.CreateOptions{})
if err != nil {
return "", fmt.Errorf("create tenant Role: %w", err)
}
} else if err != nil {
return "", fmt.Errorf("get tenant Role: %w", err)
}
rbClient := k8sClient.Clientset.RbacV1().RoleBindings(ns)
_, err = rbClient.Get(ctx, tenantRoleName, metav1.GetOptions{})
if apierrors.IsNotFound(err) {
_, err = rbClient.Create(ctx, &rbacv1.RoleBinding{
ObjectMeta: metav1.ObjectMeta{Name: tenantRoleName, Namespace: ns},
Subjects: []rbacv1.Subject{{Kind: "ServiceAccount", Name: tenantSAName, Namespace: ns}},
RoleRef: rbacv1.RoleRef{Kind: "Role", Name: tenantRoleName, APIGroup: "rbac.authorization.k8s.io"},
}, metav1.CreateOptions{})
if err != nil {
return "", fmt.Errorf("create tenant RoleBinding: %w", err)
}
} else if err != nil {
return "", fmt.Errorf("get tenant RoleBinding: %w", err)
}
return requestSAToken(ctx, k8sClient, ns, tenantSAName)
}
func CreateNoRBACSA(ctx context.Context, k8sClient *k8s.K8SClient, ns string) (string, error) {
saClient := k8sClient.Clientset.CoreV1().ServiceAccounts(ns)
_, err := saClient.Get(ctx, norbacSAName, metav1.GetOptions{})
if apierrors.IsNotFound(err) {
_, err = saClient.Create(ctx, &corev1.ServiceAccount{
ObjectMeta: metav1.ObjectMeta{Name: norbacSAName, Namespace: ns},
}, metav1.CreateOptions{})
if err != nil {
return "", fmt.Errorf("create norbac SA: %w", err)
}
} else if err != nil {
return "", fmt.Errorf("get norbac SA: %w", err)
}
return requestSAToken(ctx, k8sClient, ns, norbacSAName)
}
func requestSAToken(ctx context.Context, k8sClient *k8s.K8SClient, ns, saName string) (string, error) {
tr := &authenticationv1.TokenRequest{
Spec: authenticationv1.TokenRequestSpec{
ExpirationSeconds: ptrInt64(7200),
},
}
resp, err := k8sClient.Clientset.CoreV1().ServiceAccounts(ns).CreateToken(ctx, saName, tr, metav1.CreateOptions{})
if err != nil {
return "", fmt.Errorf("create token for SA %s: %w", saName, err)
}
return resp.Status.Token, nil
}
func ptrInt64(v int64) *int64 { return &v }