Skip to content

Commit

Permalink
fix multi ns debt
Browse files Browse the repository at this point in the history
  • Loading branch information
bxy4543 committed Sep 22, 2023
1 parent 4809993 commit c2a3d21
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 51 deletions.
58 changes: 22 additions & 36 deletions controllers/account/api/v1/debt_webhook.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,32 +84,28 @@ func (d DebtValidate) Handle(ctx context.Context, req admission.Request) admissi
case kubeSystemGroup:
logger.V(1).Info("pass for kube-system")
return admission.ValidationResponse(true, "")
case fmt.Sprintf("%s:%s", saPrefix, req.Namespace):
if !isUserNamespace(req.Namespace) || isWhiteList(req) {
return admission.ValidationResponse(true, "")
}
logger.V(1).Info("check for user", "user", req.UserInfo.Username, "ns: ", req.Namespace, "name", req.Name, "Operation", req.Operation)
// Check if the request is for resourcequota resource
if req.Kind.Kind == "ResourceQuota" {
// Check if the operation is UPDATE or DELETE
switch req.Name {
case getDefaultQuotaName(req.Namespace), debtLimit0QuotaName:
return admission.Denied(fmt.Sprintf("ns %s request %s %s permission denied", req.Namespace, req.Kind.Kind, req.Operation))
}
}
if req.Kind.Kind == "Namespace" && req.Name == req.Namespace {
return admission.Denied(fmt.Sprintf("ns %s request %s %s permission denied", req.Namespace, req.Kind.Kind, req.Operation))
}
if req.Kind.Kind == "Payment" && req.Operation == admissionV1.Update {
return admission.Denied(fmt.Sprintf("ns %s request %s %s permission denied", req.Namespace, req.Kind.Kind, req.Operation))
}
return checkOption(ctx, logger, d.Client, req.Namespace)
default:
// continue to check other groups
}
// is user sa
if !strings.HasPrefix(g, saPrefix+":ns-") {
continue
}
if isWhiteList(req) {
return admission.ValidationResponse(true, "")
}
logger.V(1).Info("check for user", "user", req.UserInfo.Username, "ns: ", req.Namespace, "name", req.Name, "Operation", req.Operation)
// Check if the request is for resourcequota resource
if req.Kind.Kind == "ResourceQuota" && isDefaultQuotaName(req.Name) {
// Check if the operation is UPDATE or DELETE
return admission.Denied(fmt.Sprintf("ns %s request %s %s permission denied", req.Namespace, req.Kind.Kind, req.Operation))
}
if req.Kind.Kind == "Namespace" {
return admission.Denied(fmt.Sprintf("ns %s request %s %s permission denied", req.Namespace, req.Kind.Kind, req.Operation))
}
if req.Kind.Kind == "Payment" && req.Operation == admissionV1.Update {
return admission.Denied(fmt.Sprintf("ns %s request %s %s permission denied", req.Namespace, req.Kind.Kind, req.Operation))
}
return checkOption(ctx, logger, d.Client, req.Namespace)
}

logger.V(1).Info("pass ", "req.Namespace", req.Namespace)
return admission.ValidationResponse(true, "")
}
Expand Down Expand Up @@ -140,17 +136,7 @@ func isWhiteList(req admission.Request) bool {
return false
}

func isUserNamespace(namespace string) bool {
return strings.HasPrefix(namespace, "ns-")
}

func checkOption(ctx context.Context, logger logr.Logger, c client.Client, nsName string) admission.Response {
//nsList := &corev1.NamespaceList{}
//if err := c.List(ctx, nsList, client.MatchingFields{"name": nsName}); err != nil {
// logger.Error(err, "list ns error", "naName", nsName, "nsList", nsList)
// return admission.ValidationResponse(true, nsName)
//}
// skip check if nsName is empty or equal to user system namespace
if nsName == "" {
return admission.Allowed("")
}
Expand All @@ -161,7 +147,7 @@ func checkOption(ctx context.Context, logger logr.Logger, c client.Client, nsNam
// Check if it is a user namespace
user, ok := ns.Labels[userV1.UserLabelOwnerKey]
if !ok {
return admission.ValidationResponse(true, fmt.Sprintf("this namespace is not user namespace %s,or have not create", ns.Name))
return admission.ValidationResponse(false, fmt.Sprintf("this namespace is not user namespace %s,or have not create", ns.Name))
}
logger.V(1).Info("check user namespace", "ns", ns.Name, "user", user)
accountList := AccountList{}
Expand All @@ -178,8 +164,8 @@ func checkOption(ctx context.Context, logger logr.Logger, c client.Client, nsNam
return admission.Allowed(fmt.Sprintf("pass user %s , namespace %s", user, ns.Name))
}

func getDefaultQuotaName(namespace string) string {
return fmt.Sprintf("quota-%s", namespace)
func isDefaultQuotaName(name string) bool {
return strings.HasPrefix(name, "quota-") || name == debtLimit0QuotaName
}

func GetAccountDebtBalance(account Account) float64 {
Expand Down
35 changes: 20 additions & 15 deletions controllers/account/controllers/account_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,8 +92,12 @@ func (r *AccountReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ct
r.Logger.Error(err, "delete payment failed")
}
user := &userv1.User{}
owner := ""
if err := r.Get(ctx, client.ObjectKey{Namespace: req.Namespace, Name: req.Name}, user); err == nil {
_, err = r.syncAccount(ctx, GetUserOwner(user), r.AccountSystemNamespace, "ns-"+user.Name)
if owner = user.Annotations[userv1.UserAnnotationOwnerKey]; owner == "" {
return ctrl.Result{}, fmt.Errorf("user owner is empty")
}
_, err = r.syncAccount(ctx, owner, r.AccountSystemNamespace, "ns-"+user.Name)
return ctrl.Result{}, err
} else if client.IgnoreNotFound(err) != nil {
return ctrl.Result{}, err
Expand All @@ -113,7 +117,7 @@ func (r *AccountReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ct
return ctrl.Result{}, nil
}

account, err := r.syncAccount(ctx, payment.Spec.UserID, r.AccountSystemNamespace, payment.Namespace)
account, err := r.syncAccount(ctx, owner, r.AccountSystemNamespace, payment.Namespace)
if err != nil {
return ctrl.Result{}, fmt.Errorf("get account failed: %v", err)
}
Expand Down Expand Up @@ -194,10 +198,18 @@ func (r *AccountReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ct
return ctrl.Result{}, nil
}

func (r *AccountReconciler) syncAccount(ctx context.Context, name, accountNamespace string, userNamespace string) (*accountv1.Account, error) {
func (r *AccountReconciler) syncAccount(ctx context.Context, owner, accountNamespace string, userNamespace string) (*accountv1.Account, error) {
if err := r.syncResourceQuotaAndLimitRange(ctx, userNamespace); err != nil {
//return nil, fmt.Errorf("sync resource resourceQuota and limitRange failed: %v", err)
r.Logger.Error(err, "sync resource resourceQuota and limitRange failed")
}
//TODO delete after nodeport count quota already in resource-quota
if err := r.adaptNodePortCountQuota(ctx, userNamespace); err != nil {
r.Logger.Error(err, "adapt nodeport count quota failed")
}
account := accountv1.Account{
ObjectMeta: metav1.ObjectMeta{
Name: name,
Name: owner,
Namespace: accountNamespace,
},
}
Expand All @@ -209,24 +221,17 @@ func (r *AccountReconciler) syncAccount(ctx context.Context, name, accountNamesp
}); err != nil {
return nil, err
}
if owner != getUsername(userNamespace) {
return &account, nil
}
// add role get account permission
if err := r.syncRoleAndRoleBinding(ctx, name, userNamespace); err != nil {
if err := r.syncRoleAndRoleBinding(ctx, owner, userNamespace); err != nil {
return nil, fmt.Errorf("sync role and rolebinding failed: %v", err)
}
err := r.initBalance(&account)
if err != nil {
return nil, fmt.Errorf("sync init balance failed: %v", err)
}
if account.GetAnnotations()[AccountAnnotationIgnoreQuota] != "true" {
if err := r.syncResourceQuotaAndLimitRange(ctx, userNamespace); err != nil {
//return nil, fmt.Errorf("sync resource resourceQuota and limitRange failed: %v", err)
r.Logger.Error(err, "sync resource resourceQuota and limitRange failed")
}
//TODO delete after nodeport count quota already in resource-quota
if err := r.adaptNodePortCountQuota(ctx, userNamespace); err != nil {
r.Logger.Error(err, "adapt nodeport count quota failed")
}
}
// add account balance when account is new user
stringAmount := os.Getenv(NEWACCOUNTAMOUNTENV)
if stringAmount == "" {
Expand Down

0 comments on commit c2a3d21

Please sign in to comment.