Skip to content

Commit

Permalink
Unified account (#4576)
Browse files Browse the repository at this point in the history
* accountv2 interface implementation:
use the cockroach distributed database as a multi-region unified account data storage source to replace the old CRD interaction format;
temporarily turn off account functions such as transfers and activities.

* create account v2 with cockroachdb

* add get account api service;
  • Loading branch information
bxy4543 authored Mar 11, 2024
1 parent 295e6a5 commit 0350700
Show file tree
Hide file tree
Showing 52 changed files with 2,840 additions and 1,173 deletions.
1 change: 1 addition & 0 deletions .github/workflows/services.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ env:
# Common versions
GO_VERSION: "1.20"
DEFAULT_OWNER: "labring"
CRYPTOKEY: ${{ secrets.CONTROLLER_BUILD_CRYPTOKEY }}

jobs:
resolve-modules:
Expand Down
12 changes: 10 additions & 2 deletions controllers/account/api/v1/debt_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,16 @@ type DebtSpec struct {

// DebtStatus defines the observed state of Debt
type DebtStatus struct {
LastUpdateTimestamp int64 `json:"lastUpdateTimestamp,omitempty"`
AccountDebtStatus DebtStatusType `json:"status,omitempty"`
LastUpdateTimestamp int64 `json:"lastUpdateTimestamp,omitempty"`
DebtStatusRecords []DebtStatusRecord `json:"debtStatusRecords,omitempty"`
AccountDebtStatus DebtStatusType `json:"status,omitempty"`
}

// DebtStatusRecord defines the observed state of Debt
type DebtStatusRecord struct {
LastStatus DebtStatusType `json:"lastDebtStatus,omitempty"`
CurrentStatus DebtStatusType `json:"currentStatus,omitempty"`
UpdateTime int64 `json:"updateTime,omitempty"`
}

//+kubebuilder:object:root=true
Expand Down
29 changes: 17 additions & 12 deletions controllers/account/api/v1/debt_webhook.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,11 @@ import (
"os"
"strings"

"github.com/labring/sealos/controllers/pkg/database/cockroach"

account2 "github.com/labring/sealos/controllers/pkg/account"
"github.com/labring/sealos/controllers/pkg/code"
pkgtype "github.com/labring/sealos/controllers/pkg/types"
userv1 "github.com/labring/sealos/controllers/user/api/v1"

admissionv1 "k8s.io/api/admission/v1"
Expand Down Expand Up @@ -55,15 +58,16 @@ var logger = logf.Log.WithName("debt-resource")
// +kubebuilder:object:generate=false

type DebtValidate struct {
Client client.Client
Client client.Client
AccountV2 *cockroach.Cockroach
}

var kubeSystemGroup string

func init() {
kubeSystemGroup = fmt.Sprintf("%s:%s", saPrefix, kubeSystemNamespace)
}
func (d DebtValidate) Handle(ctx context.Context, req admission.Request) admission.Response {
func (d *DebtValidate) Handle(ctx context.Context, req admission.Request) admission.Response {
logger.V(1).Info("checking user", "userInfo", req.UserInfo, "req.Namespace", req.Namespace, "req.Name", req.Name, "req.gvrk", getGVRK(req), "req.Operation", req.Operation)
// skip delete request (删除quota资源除外)
if req.Operation == admissionv1.Delete && !strings.Contains(getGVRK(req), "quotas") {
Expand Down Expand Up @@ -99,7 +103,7 @@ func (d DebtValidate) Handle(ctx context.Context, req admission.Request) admissi
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)
return d.checkOption(ctx, logger, d.Client, req.Namespace)
}
logger.V(1).Info("pass ", "req.Namespace", req.Namespace)
return admission.ValidationResponse(true, "")
Expand Down Expand Up @@ -127,11 +131,10 @@ func isWhiteList(req admission.Request) bool {
return true
}
}

return false
}

func checkOption(ctx context.Context, logger logr.Logger, c client.Client, nsName string) admission.Response {
func (d *DebtValidate) checkOption(ctx context.Context, logger logr.Logger, c client.Client, nsName string) admission.Response {
if nsName == "" {
return admission.Allowed("")
}
Expand All @@ -150,11 +153,13 @@ func checkOption(ctx context.Context, logger logr.Logger, c client.Client, nsNam
logger.Error(err, "get account error", "user", user)
return admission.ValidationResponse(true, err.Error())
}

for _, account := range accountList.Items {
if account.Status.Balance < account.Status.DeductionBalance {
return admission.ValidationResponse(false, fmt.Sprintf(code.MessageFormat, code.InsufficientBalance, fmt.Sprintf("account balance less than 0,now account is %.2f¥. Please recharge the user %s.", GetAccountDebtBalance(account), user)))
}
account, err := d.AccountV2.GetAccount(&pkgtype.UserQueryOpts{Owner: user})
if err != nil {
logger.Error(err, "get account error", "user", user)
return admission.ValidationResponse(false, err.Error())
}
if account.Balance < account.DeductionBalance {
return admission.ValidationResponse(false, fmt.Sprintf(code.MessageFormat, code.InsufficientBalance, fmt.Sprintf("account balance less than 0,now account is %.2f¥. Please recharge the user %s.", GetAccountDebtBalance(*account), user)))
}
return admission.Allowed(fmt.Sprintf("pass user %s , namespace %s", user, ns.Name))
}
Expand All @@ -163,8 +168,8 @@ func isDefaultQuotaName(name string) bool {
return strings.HasPrefix(name, "quota-") || name == debtLimit0QuotaName
}

func GetAccountDebtBalance(account Account) float64 {
return account2.GetCurrencyBalance(account.Status.Balance - account.Status.DeductionBalance)
func GetAccountDebtBalance(account pkgtype.Account) float64 {
return account2.GetCurrencyBalance(account.Balance - account.DeductionBalance)
}

const debtLimit0QuotaName = "debt-limit0"
Loading

0 comments on commit 0350700

Please sign in to comment.