diff --git a/controllers/account/api/v1/account_types.go b/controllers/account/api/v1/account_types.go index 1a037ea4b..41d5d66f1 100644 --- a/controllers/account/api/v1/account_types.go +++ b/controllers/account/api/v1/account_types.go @@ -36,6 +36,7 @@ const ( Recharge TransferIn TransferOut + ActivityGiving ) const QueryAllType Type = -1 @@ -92,6 +93,8 @@ type AccountStatus struct { EncryptBalance *string `json:"encryptBalance,omitempty"` // Recharge amount Balance int64 `json:"balance,omitempty"` + // ActivityBonus: for demonstration purposes only and does not participate in calculation + ActivityBonus int64 `json:"activityBonus,omitempty"` //Deduction amount DeductionBalance int64 `json:"deductionBalance,omitempty"` // EncryptDeductionBalance is to encrypt DeductionBalance diff --git a/controllers/account/api/v1/billinginfoquery_types.go b/controllers/account/api/v1/billinginfoquery_types.go index 073ab6595..05721066c 100644 --- a/controllers/account/api/v1/billinginfoquery_types.go +++ b/controllers/account/api/v1/billinginfoquery_types.go @@ -27,6 +27,7 @@ const ( QueryTypeNamespacesHistory = "NamespacesHistory" QueryTypeProperties = "Properties" QueryTypeAppType = "AppType" + QueryTypeRecharge = "Recharge" ) // BillingInfoQuerySpec defines the desired state of BillingInfoQuery diff --git a/controllers/account/config/crd/bases/account.sealos.io_accounts.yaml b/controllers/account/config/crd/bases/account.sealos.io_accounts.yaml index 588e3916c..ab6de6f2f 100644 --- a/controllers/account/config/crd/bases/account.sealos.io_accounts.yaml +++ b/controllers/account/config/crd/bases/account.sealos.io_accounts.yaml @@ -52,6 +52,11 @@ spec: status: description: AccountStatus defines the observed state of Account properties: + activityBonus: + description: 'ActivityBonus: for demonstration purposes only and does + not participate in calculation' + format: int64 + type: integer balance: description: Recharge amount format: int64 diff --git a/controllers/account/controllers/account_controller.go b/controllers/account/controllers/account_controller.go index 5ac690a60..d32f6f608 100644 --- a/controllers/account/controllers/account_controller.go +++ b/controllers/account/controllers/account_controller.go @@ -18,6 +18,7 @@ package controllers import ( "context" + "encoding/json" "fmt" "math" "os" @@ -25,6 +26,10 @@ import ( "strings" "time" + "k8s.io/client-go/rest" + + "k8s.io/client-go/kubernetes" + "github.com/go-logr/logr" gonanoid "github.com/matoous/go-nanoid/v2" @@ -33,15 +38,14 @@ import ( "github.com/labring/sealos/controllers/pkg/database" "github.com/labring/sealos/controllers/pkg/pay" "github.com/labring/sealos/controllers/pkg/resources" + pkgtypes "github.com/labring/sealos/controllers/pkg/types" "github.com/labring/sealos/controllers/pkg/utils/env" "github.com/labring/sealos/controllers/pkg/utils/retry" userv1 "github.com/labring/sealos/controllers/user/api/v1" - corev1 "k8s.io/api/core/v1" rbacv1 "k8s.io/api/rbac/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/types" cretry "k8s.io/client-go/util/retry" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/builder" @@ -73,6 +77,9 @@ type AccountReconciler struct { AccountSystemNamespace string DBClient database.Account MongoDBURI string + Activities pkgtypes.Activities + RechargeStep []int64 + RechargeRatio []float64 } //+kubebuilder:rbac:groups=account.sealos.io,resources=accounts,verbs=get;list;watch;create;update;patch;delete @@ -143,12 +150,7 @@ func (r *AccountReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ct now := time.Now().UTC() //1¥ = 100WechatPayAmount; 1 WechatPayAmount = 10000 SealosAmount payAmount := orderAmount * 10000 - // get recharge-gift configmap - configMap := &corev1.ConfigMap{} - if err := r.Client.Get(ctx, types.NamespacedName{Name: RECHARGEGIFT, Namespace: SEALOS}, configMap); err != nil { - r.Logger.Error(err, "get recharge-gift ConfigMap failed") - } - gift, err := giveGift(payAmount, configMap) + updateAnno, gift, err := r.getAmountWithRates(payAmount, account) if err != nil { r.Logger.Error(err, "get gift error") } @@ -157,12 +159,18 @@ func (r *AccountReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ct return ctrl.Result{}, fmt.Errorf("recharge encrypt balance failed: %v", err) } if err := SyncAccountStatus(ctx, r.Client, account); err != nil { - return ctrl.Result{}, fmt.Errorf("update account failed: %v", err) + return ctrl.Result{}, fmt.Errorf("update account status failed: %v", err) } payment.Status.Status = pay.PaymentSuccess if err := r.Status().Update(ctx, payment); err != nil { return ctrl.Result{}, fmt.Errorf("update payment failed: %v", err) } + if len(updateAnno) > 0 { + account.Annotations = updateAnno + if err := r.Update(ctx, account); err != nil { + return ctrl.Result{}, fmt.Errorf("update account failed: %v", err) + } + } id, err := gonanoid.New(12) if err != nil { @@ -436,6 +444,62 @@ func (r *AccountReconciler) SetupWithManager(mgr ctrl.Manager, rateOpts controll Complete(r) } +func RawParseRechargeConfig() (activities pkgtypes.Activities, discountsteps []int64, discountratios []float64, returnErr error) { + // local test + //config, err := clientcmd.BuildConfigFromFlags("", os.Getenv("KUBECONFIG")) + //if err != nil { + // fmt.Printf("Error building kubeconfig: %v\n", err) + // os.Exit(1) + //} + config, err := rest.InClusterConfig() + if err != nil { + returnErr = fmt.Errorf("get in cluster config failed: %v", err) + return + } + clientset, err := kubernetes.NewForConfig(config) + if err != nil { + returnErr = fmt.Errorf("get clientset failed: %v", err) + return + } + configMap, err := clientset.CoreV1().ConfigMaps(SEALOS).Get(context.TODO(), RECHARGEGIFT, metav1.GetOptions{}) + if err != nil { + returnErr = fmt.Errorf("get configmap failed: %v", err) + return + } + if returnErr = parseConfigList(configMap.Data["steps"], &discountsteps, "steps"); returnErr != nil { + return + } + + if returnErr = parseConfigList(configMap.Data["ratios"], &discountratios, "ratios"); returnErr != nil { + return + } + + if activityStr := configMap.Data["activities"]; activityStr != "" { + returnErr = json.Unmarshal([]byte(activityStr), &activities) + } + return +} + +func parseConfigList(s string, list interface{}, configName string) error { + for _, v := range strings.Split(s, ",") { + switch list := list.(type) { + case *[]int64: + i, err := strconv.ParseInt(v, 10, 64) + if err != nil { + return fmt.Errorf("%s format error: %v", configName, err) + } + *list = append(*list, i) + case *[]float64: + f, err := strconv.ParseFloat(v, 64) + if err != nil { + return fmt.Errorf("%s format error: %v", configName, err) + } + *list = append(*list, f) + } + } + return nil +} + func GetUserOwner(user *userv1.User) string { own := user.Annotations[userv1.UserAnnotationOwnerKey] if own == "" { @@ -467,28 +531,42 @@ func (p *NamespaceFilterPredicate) Generic(e event.GenericEvent) bool { const BaseUnit = 1_000_000 -func giveGift(amount int64, configMap *corev1.ConfigMap) (int64, error) { - if configMap.Data == nil { - return amount, fmt.Errorf("configMap's data is nil") +func (r *AccountReconciler) getAmountWithRates(amount int64, account *accountv1.Account) (anno map[string]string, amt int64, err error) { + userActivities, err := pkgtypes.ParseUserActivities(account.Annotations) + if err != nil { + return nil, 0, fmt.Errorf("parse user activities failed: %w", err) } - stepsStr := strings.Split(configMap.Data["steps"], ",") - ratiosStr := strings.Split(configMap.Data["ratios"], ",") - var ratio float64 - - for i, stepStr := range stepsStr { - step, err := strconv.ParseInt(stepStr, 10, 64) - if err != nil { - return amount, fmt.Errorf("steps format error :%s", err) - } - if amount >= step*BaseUnit { - ratio, err = strconv.ParseFloat(ratiosStr[i], 32) - if err != nil { - return amount, fmt.Errorf("ratios format error :%s", err) + rechargeDiscount := pkgtypes.RechargeDiscount{ + DiscountSteps: r.RechargeStep, + DiscountRates: r.RechargeRatio, + } + if len(userActivities) > 0 { + if activityType, phase, _ := pkgtypes.GetUserActivityDiscount(r.Activities, &userActivities); phase != nil { + if len(phase.RechargeDiscount.DiscountSteps) > 0 { + rechargeDiscount.DiscountSteps = phase.RechargeDiscount.DiscountSteps + rechargeDiscount.DiscountRates = phase.RechargeDiscount.DiscountRates } + rechargeDiscount.SpecialDiscount = phase.RechargeDiscount.SpecialDiscount + rechargeDiscount = phase.RechargeDiscount + currentPhase := userActivities[activityType].Phases[userActivities[activityType].CurrentPhase] + anno = pkgtypes.SetUserPhaseRechargeTimes(account.Annotations, activityType, currentPhase.Name, currentPhase.RechargeNums+1) + } + } + return anno, getAmountWithDiscount(amount, rechargeDiscount), nil +} + +func getAmountWithDiscount(amount int64, discount pkgtypes.RechargeDiscount) int64 { + if discount.SpecialDiscount != nil && discount.SpecialDiscount[amount/BaseUnit] != 0 { + return amount + discount.SpecialDiscount[amount/BaseUnit]*BaseUnit + } + var r float64 + for i, s := range discount.DiscountSteps { + if amount >= s*BaseUnit { + r = discount.DiscountRates[i] } else { break } } - return int64(math.Ceil(float64(amount)*ratio/100)) + amount, nil + return int64(math.Ceil(float64(amount)*r)) + amount } diff --git a/controllers/account/controllers/account_controller_test.go b/controllers/account/controllers/account_controller_test.go index 8803a1d22..53ff77be9 100644 --- a/controllers/account/controllers/account_controller_test.go +++ b/controllers/account/controllers/account_controller_test.go @@ -19,44 +19,65 @@ package controllers import ( "testing" - corev1 "k8s.io/api/core/v1" + "github.com/labring/sealos/controllers/pkg/types" ) -func Test_giveGift(t *testing.T) { +//func Test_giveGift(t *testing.T) { +// type args struct { +// amount int64 +// } +// const BaseUnit = 1_000_000 +// tests := []struct { +// name string +// args args +// want int64 +// }{ +// // [1-298] -> 0%, [299-598] -> 10%, [599-1998] -> 15%, [1999-4998] -> 20%, [4999-19998] -> 25%, [19999+] -> 30% +// {name: "0% less than 299", args: args{amount: 100 * BaseUnit}, want: 0 + 100*BaseUnit}, +// {name: "10% between 299 and 599", args: args{amount: 299 * BaseUnit}, want: 29_900_000 + 299*BaseUnit}, +// {name: "10% between 299 and 599", args: args{amount: 300 * BaseUnit}, want: 30_000_000 + 300*BaseUnit}, +// {name: "15% between 599 and 1999", args: args{amount: 599 * BaseUnit}, want: 89_850_000 + 599*BaseUnit}, +// {name: "15% between 599 and 1999", args: args{amount: 600 * BaseUnit}, want: 90_000_000 + 600*BaseUnit}, +// {name: "20% between 1999 and 4999", args: args{amount: 1999 * BaseUnit}, want: 399_800_000 + 1999*BaseUnit}, +// {name: "20% between 1999 and 4999", args: args{amount: 2000 * BaseUnit}, want: 400_000_000 + 2000*BaseUnit}, +// {name: "25% between 4999 and 19999", args: args{amount: 4999 * BaseUnit}, want: 1249_750_000 + 4999*BaseUnit}, +// {name: "25% between 4999 and 19999", args: args{amount: 5000 * BaseUnit}, want: 1250_000_000 + 5000*BaseUnit}, +// {name: "30% more than 19999", args: args{amount: 19999 * BaseUnit}, want: 5999_700_000 + 19999*BaseUnit}, +// {name: "30% more than 19999", args: args{amount: 20000 * BaseUnit}, want: 6000_000_000 + 20000*BaseUnit}, +// {name: "30% more than 19999", args: args{amount: 99999 * BaseUnit}, want: 29999_700_000 + 99999*BaseUnit}, +// {"0% less than 299", args{amount: 1 * BaseUnit}, 1 * BaseUnit}, +// } +// +// configMap := &corev1.ConfigMap{} +// configMap.Data = make(map[string]string) +// configMap.Data["steps"] = "299,599,1999,4999,19999" +// configMap.Data["ratios"] = "10.0,15.0,20.0,25.0,30.0" +// +// for _, tt := range tests { +// t.Run(tt.name, func(t *testing.T) { +// if got, _ := giveGift(tt.args.amount, configMap); got != tt.want { +// t.Errorf("giveGift() = %v, want %v", got, tt.want) +// } +// }) +// } +//} + +func Test_getAmountWithDiscount(t *testing.T) { type args struct { - amount int64 + amount int64 + discount types.RechargeDiscount } - const BaseUnit = 1_000_000 tests := []struct { name string args args want int64 }{ - // [1-298] -> 0%, [299-598] -> 10%, [599-1998] -> 15%, [1999-4998] -> 20%, [4999-19998] -> 25%, [19999+] -> 30% - {name: "0% less than 299", args: args{amount: 100 * BaseUnit}, want: 0 + 100*BaseUnit}, - {name: "10% between 299 and 599", args: args{amount: 299 * BaseUnit}, want: 29_900_000 + 299*BaseUnit}, - {name: "10% between 299 and 599", args: args{amount: 300 * BaseUnit}, want: 30_000_000 + 300*BaseUnit}, - {name: "15% between 599 and 1999", args: args{amount: 599 * BaseUnit}, want: 89_850_000 + 599*BaseUnit}, - {name: "15% between 599 and 1999", args: args{amount: 600 * BaseUnit}, want: 90_000_000 + 600*BaseUnit}, - {name: "20% between 1999 and 4999", args: args{amount: 1999 * BaseUnit}, want: 399_800_000 + 1999*BaseUnit}, - {name: "20% between 1999 and 4999", args: args{amount: 2000 * BaseUnit}, want: 400_000_000 + 2000*BaseUnit}, - {name: "25% between 4999 and 19999", args: args{amount: 4999 * BaseUnit}, want: 1249_750_000 + 4999*BaseUnit}, - {name: "25% between 4999 and 19999", args: args{amount: 5000 * BaseUnit}, want: 1250_000_000 + 5000*BaseUnit}, - {name: "30% more than 19999", args: args{amount: 19999 * BaseUnit}, want: 5999_700_000 + 19999*BaseUnit}, - {name: "30% more than 19999", args: args{amount: 20000 * BaseUnit}, want: 6000_000_000 + 20000*BaseUnit}, - {name: "30% more than 19999", args: args{amount: 99999 * BaseUnit}, want: 29999_700_000 + 99999*BaseUnit}, - {"0% less than 299", args{amount: 1 * BaseUnit}, 1 * BaseUnit}, + // TODO: Add test cases. } - - configMap := &corev1.ConfigMap{} - configMap.Data = make(map[string]string) - configMap.Data["steps"] = "299,599,1999,4999,19999" - configMap.Data["ratios"] = "10.0,15.0,20.0,25.0,30.0" - for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - if got, _ := giveGift(tt.args.amount, configMap); got != tt.want { - t.Errorf("giveGift() = %v, want %v", got, tt.want) + if got := getAmountWithDiscount(tt.args.amount, tt.args.discount); got != tt.want { + t.Errorf("getAmountWithDiscount() = %v, want %v", got, tt.want) } }) } diff --git a/controllers/account/controllers/activity_controller.go b/controllers/account/controllers/activity_controller.go new file mode 100644 index 000000000..c76a1948e --- /dev/null +++ b/controllers/account/controllers/activity_controller.go @@ -0,0 +1,174 @@ +/* +Copyright 2022 labring. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package controllers + +import ( + "context" + "fmt" + "reflect" + "time" + + gonanoid "github.com/matoous/go-nanoid/v2" + + "github.com/labring/sealos/controllers/pkg/resources" + + "github.com/labring/sealos/controllers/pkg/database" + + "github.com/labring/sealos/controllers/pkg/crypto" + + "sigs.k8s.io/controller-runtime/pkg/event" + "sigs.k8s.io/controller-runtime/pkg/predicate" + + "sigs.k8s.io/controller-runtime/pkg/controller" + + "github.com/go-logr/logr" + "k8s.io/apimachinery/pkg/runtime" + + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/log" + + accountv1 "github.com/labring/sealos/controllers/account/api/v1" + "github.com/labring/sealos/controllers/pkg/types" +) + +type ActivityReconciler struct { + client.Client + Scheme *runtime.Scheme + Logger logr.Logger + Activity types.Activities + DBClient database.Account +} + +//+kubebuilder:rbac:groups=account.sealos.io,resources=accounts,verbs=get;list;watch;create;update;patch;delete +//+kubebuilder:rbac:groups=account.sealos.io,resources=accounts/status,verbs=get;update;patch +//+kubebuilder:rbac:groups=account.sealos.io,resources=accounts/finalizers,verbs=update + +// Reconcile is part of the main kubernetes reconciliation loop which aims to +// move the current state of the cluster closer to the desired state. +// TODO(user): Modify the Reconcile function to compare the state specified by +// the Payment object against the actual cluster state, and then +// perform operations to make the cluster state reflect the state specified by +// the user. +// +// For more details, check Reconcile and its Result here: +// - https://pkg.go.dev/sigs.k8s.io/controller-runtime@v0.12.2/pkg/reconcile +func (r *ActivityReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { + r.Logger = log.FromContext(ctx) + + account := &accountv1.Account{} + if err := r.Get(ctx, req.NamespacedName, account); err != nil { + r.Logger.Error(err, "get account failed") + return ctrl.Result{}, client.IgnoreNotFound(err) + } + userActivities, err := types.ParseUserActivities(account.Annotations) + if err != nil { + r.Logger.Error(err, "parse user activities failed") + return ctrl.Result{}, err + } + anno, amount, err := r.giveAmount(userActivities, account) + if err != nil { + return ctrl.Result{}, err + } + if anno != nil { + if err := r.handleBonus(account, anno, amount); err != nil { + return ctrl.Result{}, fmt.Errorf("handle bonus failed: %v", err) + } + } + return ctrl.Result{}, nil +} + +func (r *ActivityReconciler) handleBonus(account *accountv1.Account, annotations map[string]string, amount int64) error { + if err := SyncAccountStatus(context.Background(), r.Client, account); err != nil { + return fmt.Errorf("update account status failed: %v", err) + } + + account.Annotations = annotations + if err := r.Update(context.Background(), account); err != nil { + return fmt.Errorf("update account failed: %v", err) + } + id, err := gonanoid.New(12) + if err != nil { + return fmt.Errorf("create id failed: %v", err) + } + + if err = r.DBClient.SaveBillings(&resources.Billing{ + Time: time.Now().UTC(), + OrderID: id, + Amount: amount, + Namespace: GetUserNamespace(account.Name), + Owner: getUsername(account.Name), + Type: accountv1.ActivityGiving, + }); err != nil { + return fmt.Errorf("save billing failed: %v", err) + } + r.Logger.Info("update account success", "account", account.Name, "bonus amount", amount, "balance", account.Status.Balance) + return nil +} + +func (r *ActivityReconciler) giveAmount(userActivities types.UserActivities, account *accountv1.Account) (annotations map[string]string, amount int64, err error) { + for activityType, userActivity := range userActivities { + activity, exist := r.Activity[activityType] + if !exist { + r.Logger.Error(nil, "activity not exist", "activity", activity) + continue + } + userPhase, exist := userActivity.Phases[userActivity.CurrentPhase] + if !exist { + r.Logger.Error(nil, "userPhase not exist", "activity", activityType, "phase", userActivity.CurrentPhase) + continue + } + if userPhase.EndTime.IsZero() { + continue + } + giveAmount := activity.Phases[userActivity.CurrentPhase].GiveAmount + if giveAmount != 0 && userPhase.GiveAmount == 0 { + err := crypto.RechargeBalance(account.Status.EncryptBalance, giveAmount) + if err != nil { + return nil, 0, fmt.Errorf("give account %s amount failed: %w", account.Name, err) + } + account.Status.Balance += giveAmount + account.Status.ActivityBonus += giveAmount + return types.SetUserPhaseGiveAmount(account.Annotations, activityType, userActivity.CurrentPhase, giveAmount), giveAmount, nil + } + } + return nil, 0, nil +} + +// SetupWithManager sets up the controller with the Manager. +func (r *ActivityReconciler) SetupWithManager(mgr ctrl.Manager, rateOpts controller.Options) error { + const controllerName = "activity_controller" + r.Logger = ctrl.Log.WithName(controllerName) + return ctrl.NewControllerManagedBy(mgr). + For(&accountv1.Account{}). + WithEventFilter(predicate.Funcs{ + CreateFunc: func(e event.CreateEvent) bool { + return len(e.Object.GetAnnotations()) > 1 + }, + UpdateFunc: func(e event.UpdateEvent) bool { + accountOld := e.ObjectOld.(*accountv1.Account) + accountNew := e.ObjectNew.(*accountv1.Account) + if len(accountNew.Annotations) == 0 { + return false + } + return !reflect.DeepEqual(accountOld.Annotations, accountNew.Annotations) + }, + DeleteFunc: func(e event.DeleteEvent) bool { + return false + }, + }).WithOptions(rateOpts).Complete(r) +} diff --git a/controllers/account/controllers/activity_controller_test.go b/controllers/account/controllers/activity_controller_test.go new file mode 100644 index 000000000..7afa462e7 --- /dev/null +++ b/controllers/account/controllers/activity_controller_test.go @@ -0,0 +1,74 @@ +// Copyright © 2023 sealos. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package controllers + +import ( + "testing" + "time" + + "github.com/labring/sealos/controllers/pkg/types" +) + +func Test_parseUserActivitiesAnnotation(t *testing.T) { + annotations := map[string]string{ + "activity.beginner-guide.launchpad.startTime": "2016-03-04T15:04:05Z", + "activity.beginner-guide.launchpad.rechargeNums": "1", + "activity.beginner-guide.launchpad.giveAmount": "10000", + "activity.beginner-guide.current-phase": "launchpad", + } + + userActivities, err := types.ParseUserActivities(annotations) + if err != nil { + t.Errorf("Unexpected error: %v", err) + } + + if len(userActivities) != 1 { + t.Errorf("Expected 1 activity type, got %d", len(userActivities)) + } + + activity, exists := userActivities["beginner-guide"] + if !exists { + t.Errorf("Expected activity type 'beginner-guide' not found") + } + + if activity.CurrentPhase != "launchpad" { + t.Errorf("Expected current phase 'launchpad', got %s", activity.CurrentPhase) + } + + if len(activity.Phases) != 1 { + t.Errorf("Expected 1 phase, got %d", len(activity.Phases)) + } + + phase, exists := activity.Phases["launchpad"] + if !exists { + t.Errorf("Expected phase 'launchpad' not found") + } + + if phase.Name != "launchpad" { + t.Errorf("Expected phase name 'launchpad', got %s", phase.Name) + } + tmpTime, _ := time.Parse(time.RFC3339, "2006-01-02T15:04:05Z") + if phase.StartTime.Equal(tmpTime) { + t.Errorf("Expected phase start time '$time', got %s", phase.StartTime) + } + + if phase.RechargeNums != 1 { + t.Errorf("Expected recharge nums 1, got %d", phase.RechargeNums) + } + + if phase.GiveAmount != 10000 { + t.Errorf("Expected give amount 10000, got %d", phase.GiveAmount) + } +} diff --git a/controllers/account/controllers/billinginfoquery_controller.go b/controllers/account/controllers/billinginfoquery_controller.go index 86156c30e..4b4949baa 100644 --- a/controllers/account/controllers/billinginfoquery_controller.go +++ b/controllers/account/controllers/billinginfoquery_controller.go @@ -23,6 +23,8 @@ import ( "strings" "time" + "github.com/labring/sealos/controllers/pkg/types" + userv1 "github.com/labring/sealos/controllers/user/api/v1" "github.com/go-logr/logr" @@ -42,11 +44,15 @@ import ( type BillingInfoQueryReconciler struct { client.Client logr.Logger - Scheme *runtime.Scheme - DBClient database.Account - Properties *resources.PropertyTypeLS - propertiesQuery []accountv1.PropertyQuery - QueryFuncMap map[string]func(context.Context, ctrl.Request, *accountv1.BillingInfoQuery) (string, error) + Scheme *runtime.Scheme + DBClient database.Account + AccountSystemNamespace string + Properties *resources.PropertyTypeLS + propertiesQuery []accountv1.PropertyQuery + Activities types.Activities + RechargeStep []int64 + RechargeRatio []float64 + QueryFuncMap map[string]func(context.Context, ctrl.Request, *accountv1.BillingInfoQuery) (string, error) } //+kubebuilder:rbac:groups=account.sealos.io,resources=billinginfoqueries,verbs=get;list;watch;create;update;patch;delete @@ -141,6 +147,40 @@ func (r *BillingInfoQueryReconciler) AppTypeQuery(_ context.Context, _ ctrl.Requ return string(data), nil } +func (r *BillingInfoQueryReconciler) RechargeQuery(ctx context.Context, req ctrl.Request, _ *accountv1.BillingInfoQuery) (result string, err error) { + account := &accountv1.Account{} + if err := r.Get(ctx, client.ObjectKey{Namespace: r.AccountSystemNamespace, Name: getUsername(req.Namespace)}, account); err != nil { + return "", fmt.Errorf("get account failed: %w", err) + } + + userActivities, err := types.ParseUserActivities(account.Annotations) + if err != nil { + return "", fmt.Errorf("parse user activities failed: %w", err) + } + + rechargeDiscount := types.RechargeDiscount{ + DiscountSteps: r.RechargeStep, + DiscountRates: r.RechargeRatio, + } + + if len(userActivities) > 0 { + if _, phase, _ := types.GetUserActivityDiscount(r.Activities, &userActivities); phase != nil { + if len(phase.RechargeDiscount.DiscountSteps) > 0 { + rechargeDiscount.DiscountSteps = phase.RechargeDiscount.DiscountSteps + rechargeDiscount.DiscountRates = phase.RechargeDiscount.DiscountRates + } + rechargeDiscount.SpecialDiscount = phase.RechargeDiscount.SpecialDiscount + } + } + + data, err := json.Marshal(rechargeDiscount) + if err != nil { + return "", fmt.Errorf("marshal recharge discount failed: %w", err) + } + + return string(data), nil +} + func (r *BillingInfoQueryReconciler) ConvertPropertiesToQuery() error { r.propertiesQuery = make([]accountv1.PropertyQuery, 0) for _, types := range r.Properties.Types { @@ -165,6 +205,7 @@ func (r *BillingInfoQueryReconciler) SetupWithManager(mgr ctrl.Manager) error { r.QueryFuncMap[strings.ToLower(accountv1.QueryTypeNamespacesHistory)] = r.NamespacesHistoryQuery r.QueryFuncMap[strings.ToLower(accountv1.QueryTypeProperties)] = r.PropertiesQuery r.QueryFuncMap[strings.ToLower(accountv1.QueryTypeAppType)] = r.AppTypeQuery + r.QueryFuncMap[strings.ToLower(accountv1.QueryTypeRecharge)] = r.RechargeQuery return ctrl.NewControllerManagedBy(mgr). For(&accountv1.BillingInfoQuery{}). Complete(r) diff --git a/controllers/account/controllers/transfer_controller.go b/controllers/account/controllers/transfer_controller.go index ef05f79a3..e83cb4624 100644 --- a/controllers/account/controllers/transfer_controller.go +++ b/controllers/account/controllers/transfer_controller.go @@ -177,7 +177,8 @@ func (r *TransferReconciler) transferAccount(ctx context.Context, transfer *acco } balance, _ := crypto.DecryptInt64(*fromAccount.Status.EncryptBalance) deductionBalance, _ := crypto.DecryptInt64(*fromAccount.Status.EncryptDeductionBalance) - if balance < deductionBalance+transfer.Spec.Amount+MinBalance { + // check balance is enough ( balance - deductionBalance - transferAmount - MinBalance - ActivityBonus) activity give amount not included + if balance < deductionBalance+transfer.Spec.Amount+MinBalance+fromAccount.Status.ActivityBonus { return fmt.Errorf("balance not enough") } if r.Get(ctx, client.ObjectKey{Namespace: r.AccountSystemNamespace, Name: getUsername(to)}, &accountv1.Account{}) != nil { diff --git a/controllers/account/deploy/manifests/deploy.yaml.tmpl b/controllers/account/deploy/manifests/deploy.yaml.tmpl index 492fbe805..bb5c75570 100644 --- a/controllers/account/deploy/manifests/deploy.yaml.tmpl +++ b/controllers/account/deploy/manifests/deploy.yaml.tmpl @@ -44,6 +44,11 @@ spec: status: description: AccountStatus defines the observed state of Account properties: + activityBonus: + description: 'ActivityBonus: for demonstration purposes only and does + not participate in calculation' + format: int64 + type: integer balance: description: Recharge amount format: int64 diff --git a/controllers/account/go.mod b/controllers/account/go.mod index a872a5dc4..e95cc31c6 100644 --- a/controllers/account/go.mod +++ b/controllers/account/go.mod @@ -11,6 +11,7 @@ require ( github.com/labring/sealos/controllers/pkg v0.0.0-00010101000000-000000000000 github.com/labring/sealos/controllers/user v0.0.0 github.com/matoous/go-nanoid/v2 v2.0.0 + github.com/minio/madmin-go/v3 v3.0.35 github.com/onsi/ginkgo v1.16.5 github.com/onsi/gomega v1.27.8 k8s.io/api v0.27.4 @@ -32,14 +33,17 @@ require ( github.com/clbanning/mxj/v2 v2.5.5 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/dinoallo/sealos-networkmanager-protoapi v0.0.0-20230928031328-cf9649d6af49 // indirect + github.com/dustin/go-humanize v1.0.1 // indirect github.com/emicklei/go-restful/v3 v3.10.1 // indirect github.com/evanphx/json-patch/v5 v5.6.0 // indirect github.com/fsnotify/fsnotify v1.6.0 // indirect github.com/go-logr/zapr v1.2.4 // indirect + github.com/go-ole/go-ole v1.2.6 // indirect github.com/go-openapi/jsonpointer v0.19.6 // indirect github.com/go-openapi/jsonreference v0.20.1 // indirect github.com/go-openapi/swag v0.22.3 // indirect github.com/gogo/protobuf v1.3.2 // indirect + github.com/golang-jwt/jwt/v4 v4.5.0 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/protobuf v1.5.3 // indirect github.com/golang/snappy v0.0.4 // indirect @@ -52,28 +56,43 @@ require ( github.com/josharian/intern v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect github.com/klauspost/compress v1.16.7 // indirect + github.com/klauspost/cpuid/v2 v2.2.5 // indirect + github.com/lufia/plan9stats v0.0.0-20230110061619-bbe2e5e100de // indirect github.com/mailru/easyjson v0.7.7 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect + github.com/minio/md5-simd v1.1.2 // indirect + github.com/minio/minio-go/v7 v7.0.64 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/nxadm/tail v1.4.8 // indirect github.com/onsi/ginkgo/v2 v2.10.0 // indirect + github.com/philhofer/fwd v1.1.2 // indirect github.com/pkg/errors v0.9.1 // indirect + github.com/power-devops/perfstat v0.0.0-20221212215047-62379fc7944b // indirect github.com/prometheus/client_golang v1.15.1 // indirect github.com/prometheus/client_model v0.4.0 // indirect - github.com/prometheus/common v0.42.0 // indirect + github.com/prometheus/common v0.44.0 // indirect github.com/prometheus/procfs v0.9.0 // indirect + github.com/prometheus/prom2json v1.3.3 // indirect + github.com/rs/xid v1.5.0 // indirect + github.com/safchain/ethtool v0.3.0 // indirect + github.com/secure-io/sio-go v0.3.1 // indirect + github.com/shirou/gopsutil/v3 v3.23.1 // indirect github.com/spf13/pflag v1.0.5 // indirect github.com/stretchr/testify v1.8.4 // indirect github.com/stripe/stripe-go/v74 v74.30.0 // indirect + github.com/tinylib/msgp v1.1.8 // indirect github.com/tjfoc/gmsm v1.3.2 // indirect + github.com/tklauser/go-sysconf v0.3.11 // indirect + github.com/tklauser/numcpus v0.6.0 // indirect github.com/wechatpay-apiv3/wechatpay-go v0.2.17 // indirect github.com/xdg-go/pbkdf2 v1.0.0 // indirect github.com/xdg-go/scram v1.1.2 // indirect github.com/xdg-go/stringprep v1.0.4 // indirect github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d // indirect + github.com/yusufpapurcu/wmi v1.2.2 // indirect go.mongodb.org/mongo-driver v1.12.1 // indirect go.uber.org/multierr v1.11.0 // indirect go.uber.org/zap v1.26.0 // indirect diff --git a/controllers/account/go.sum b/controllers/account/go.sum index 570ed7492..89ca98272 100644 --- a/controllers/account/go.sum +++ b/controllers/account/go.sum @@ -62,6 +62,7 @@ github.com/dinoallo/sealos-networkmanager-protoapi v0.0.0-20230928031328-cf9649d github.com/dinoallo/sealos-networkmanager-protoapi v0.0.0-20230928031328-cf9649d6af49/go.mod h1:sbm1DAsayX+XsXCOC2CFAAU9JZhX0SPKwnybDjSd0Ls= github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= +github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= github.com/emicklei/go-restful/v3 v3.10.1 h1:rc42Y5YTp7Am7CS630D7JmhRjq4UlEUuEKfrDac4bSQ= github.com/emicklei/go-restful/v3 v3.10.1/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= @@ -84,6 +85,8 @@ github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/zapr v1.2.4 h1:QHVo+6stLbfJmYGkQ7uGHUCu5hnAFAj6mDe6Ea0SeOo= github.com/go-logr/zapr v1.2.4/go.mod h1:FyHWQIzQORZ0QVE1BtVHv3cKtNLuXsbNLtpuhNapBOA= +github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= +github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= github.com/go-openapi/jsonpointer v0.19.6 h1:eCs3fxoIi3Wh6vtgmLTOjdhSpiqphQ+DaPn38N2ZdrE= github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs= github.com/go-openapi/jsonreference v0.20.1 h1:FBLnyygC4/IZZr893oiomc9XaghoveYTrLC1F86HID8= @@ -94,6 +97,8 @@ github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg78 github.com/go-task/slim-sprig v2.20.0+incompatible h1:4Xh3bDzO29j4TWNOI+24ubc0vbVFMg2PMnXKxK54/CA= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= +github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg= +github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -126,6 +131,7 @@ github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= @@ -155,6 +161,9 @@ github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+o github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= github.com/klauspost/compress v1.16.7 h1:2mk3MPGNzKyxErAw8YaohYh69+pa4sIQSC0fPGCFR9I= github.com/klauspost/compress v1.16.7/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= +github.com/klauspost/cpuid/v2 v2.0.1/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= +github.com/klauspost/cpuid/v2 v2.2.5 h1:0E5MSMDEoAulmXNFquVs//DdoomxaoTY1kUhbc/qbZg= +github.com/klauspost/cpuid/v2 v2.2.5/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= @@ -163,6 +172,9 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= +github.com/lufia/plan9stats v0.0.0-20230110061619-bbe2e5e100de h1:V53FWzU6KAZVi1tPp5UIsMoUWJ2/PNwYIDXnu7QuBCE= +github.com/lufia/plan9stats v0.0.0-20230110061619-bbe2e5e100de/go.mod h1:JKx41uQRwqlTZabZc+kILPrO/3jlKnQ2Z8b7YiVw5cE= github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/matoous/go-nanoid v1.5.0/go.mod h1:zyD2a71IubI24efhpvkJz+ZwfwagzgSO6UNiFsZKN7U= @@ -170,6 +182,13 @@ github.com/matoous/go-nanoid/v2 v2.0.0 h1:d19kur2QuLeHmJBkvYkFdhFBzLoo1XVm2GgTpL github.com/matoous/go-nanoid/v2 v2.0.0/go.mod h1:FtS4aGPVfEkxKxhdWPAspZpZSh1cOjtM7Ej/So3hR0g= github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= +github.com/minio/madmin-go/v3 v3.0.35 h1:cCo5ZZpHA+rlBQbsAcwFwiuh/uHJmjVoDDx1G4+zaho= +github.com/minio/madmin-go/v3 v3.0.35/go.mod h1:4QN2NftLSV7MdlT50dkrenOMmNVHluxTvlqJou3hte8= +github.com/minio/md5-simd v1.1.2 h1:Gdi1DZK69+ZVMoNHRXJyNcxrMA4dSxoYHZSQbirFg34= +github.com/minio/md5-simd v1.1.2/go.mod h1:MzdKDxYpY2BT9XQFocsiZf/NKVtR7nkE4RoEpN+20RM= +github.com/minio/minio-go/v7 v7.0.64 h1:Zdza8HwOzkld0ZG/og50w56fKi6AAyfqfifmasD9n2Q= +github.com/minio/minio-go/v7 v7.0.64/go.mod h1:R4WVUR6ZTedlCcGwZRauLMIKjgyaWxhs4Mqi/OMPmEc= +github.com/minio/sha256-simd v1.0.1 h1:6kaan5IFmwTNynnKKpDHe6FWHohJOHhCPchzK49dzMM= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= @@ -195,22 +214,37 @@ github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7J github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/onsi/gomega v1.27.8 h1:gegWiwZjBsf2DgiSbf5hpokZ98JVDMcWkUiigk6/KXc= github.com/onsi/gomega v1.27.8/go.mod h1:2J8vzI/s+2shY9XHRApDkdgPo1TKT7P2u6fXeJKFnNQ= +github.com/philhofer/fwd v1.1.2 h1:bnDivRJ1EWPjUIRXV5KfORO897HTbpFAQddBdE8t7Gw= +github.com/philhofer/fwd v1.1.2/go.mod h1:qkPdfjR2SIEbspLqpe1tO4n5yICnr2DY7mqEx2tUTP0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= +github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= +github.com/power-devops/perfstat v0.0.0-20221212215047-62379fc7944b h1:0LFwY6Q3gMACTjAbMZBjXAqTOzOwFaj2Ld6cjeQ7Rig= +github.com/power-devops/perfstat v0.0.0-20221212215047-62379fc7944b/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= github.com/prometheus/client_golang v1.15.1 h1:8tXpTmJbyH5lydzFPoxSIJ0J46jdh3tylbvM1xCv0LI= github.com/prometheus/client_golang v1.15.1/go.mod h1:e9yaBhRPU2pPNsZwE+JdQl0KEt1N9XgF6zxWmaC0xOk= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.4.0 h1:5lQXD3cAg1OXBf4Wq03gTrXHeaV0TQvGfUooCfx1yqY= github.com/prometheus/client_model v0.4.0/go.mod h1:oMQmHW1/JoDwqLtg57MGgP/Fb1CJEYF2imWWhWtMkYU= -github.com/prometheus/common v0.42.0 h1:EKsfXEYo4JpWMHH5cg+KOUWeuJSov1Id8zGR8eeI1YM= -github.com/prometheus/common v0.42.0/go.mod h1:xBwqVerjNdUDjgODMpudtOMwlOwf2SaTr1yjz4b7Zbc= +github.com/prometheus/common v0.44.0 h1:+5BrQJwiBB9xsMygAB3TNvpQKOwlkc25LbISbrdOOfY= +github.com/prometheus/common v0.44.0/go.mod h1:ofAIvZbQ1e/nugmZGz4/qCb9Ap1VoSTIO7x0VV9VvuY= github.com/prometheus/procfs v0.9.0 h1:wzCHvIvM5SxWqYvwgVL7yJY8Lz3PKn49KQtpgMYJfhI= github.com/prometheus/procfs v0.9.0/go.mod h1:+pB4zwohETzFnmlpe6yd2lSc+0/46IYZRB/chUwxUZY= +github.com/prometheus/prom2json v1.3.3 h1:IYfSMiZ7sSOfliBoo89PcufjWO4eAR0gznGcETyaUgo= +github.com/prometheus/prom2json v1.3.3/go.mod h1:Pv4yIPktEkK7btWsrUTWDDDrnpUrAELaOCj+oFwlgmc= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= +github.com/rs/xid v1.5.0 h1:mKX4bl4iPYJtEIxp6CYiUuLQ/8DYMoz0PUdtGgMFRVc= +github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= +github.com/safchain/ethtool v0.3.0 h1:gimQJpsI6sc1yIqP/y8GYgiXn/NjgvpM0RNoWLVVmP0= +github.com/safchain/ethtool v0.3.0/go.mod h1:SA9BwrgyAqNo7M+uaL6IYbxpm5wk3L7Mm6ocLW+CJUs= +github.com/secure-io/sio-go v0.3.1 h1:dNvY9awjabXTYGsTF1PiCySl9Ltofk9GA3VdWlo7rRc= +github.com/secure-io/sio-go v0.3.1/go.mod h1:+xbkjDzPjwh4Axd07pRKSNriS9SCiYksWnZqdnfpQxs= +github.com/shirou/gopsutil/v3 v3.23.1 h1:a9KKO+kGLKEvcPIs4W62v0nu3sciVDOOOPUD0Hz7z/4= +github.com/shirou/gopsutil/v3 v3.23.1/go.mod h1:NN6mnm5/0k8jw4cBfCnJtr5L7ErOTg18tMNpgFkn0hA= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/assertions v1.1.0/go.mod h1:tcbTF8ujkAEcZ8TElKY+i30BzYlVhC/LOxJk7iOWnoo= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= @@ -233,8 +267,14 @@ github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcU github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/stripe/stripe-go/v74 v74.30.0 h1:0Kf0KkeFnY7iRhOwvTerX0Ia1BRw+eV1CVJ51mGYAUY= github.com/stripe/stripe-go/v74 v74.30.0/go.mod h1:f9L6LvaXa35ja7eyvP6GQswoaIPaBRvGAimAO+udbBw= +github.com/tinylib/msgp v1.1.8 h1:FCXC1xanKO4I8plpHGH2P7koL/RzZs12l/+r7vakfm0= +github.com/tinylib/msgp v1.1.8/go.mod h1:qkpG+2ldGg4xRFmx+jfTvZPxfGFhi64BcnL9vkCm/Tw= github.com/tjfoc/gmsm v1.3.2 h1:7JVkAn5bvUJ7HtU08iW6UiD+UTmJTIToHCfeFzkcCxM= github.com/tjfoc/gmsm v1.3.2/go.mod h1:HaUcFuY0auTiaHB9MHFGCPx5IaLhTUd2atbCFBQXn9w= +github.com/tklauser/go-sysconf v0.3.11 h1:89WgdJhk5SNwJfu+GKyYveZ4IaJ7xAkecBo+KdJV0CM= +github.com/tklauser/go-sysconf v0.3.11/go.mod h1:GqXfhXY3kiPa0nAXPDIQIWzJbMCB7AmcWpGR8lSZfqI= +github.com/tklauser/numcpus v0.6.0 h1:kebhY2Qt+3U6RNK7UqpYNA+tJ23IBEGKkB7JQBfDYms= +github.com/tklauser/numcpus v0.6.0/go.mod h1:FEZLMke0lhOUG6w2JadTzp0a+Nl8PF/GFkQ5UVIcaL4= github.com/wechatpay-apiv3/wechatpay-go v0.2.17 h1:i4YJA/6BqAbi2YfyPZBjpeEeO/+oa4UbKP4gSTRhhQg= github.com/wechatpay-apiv3/wechatpay-go v0.2.17/go.mod h1:A254AUBVB6R+EqQFo3yTgeh7HtyqRRtN2w9hQSOrd4Q= github.com/xdg-go/pbkdf2 v1.0.0 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c= @@ -253,6 +293,8 @@ github.com/yuin/goldmark v1.1.30/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +github.com/yusufpapurcu/wmi v1.2.2 h1:KBNDSne4vP5mbSWnJbO+51IMOXJB67QiYCSBrubbPRg= +github.com/yusufpapurcu/wmi v1.2.2/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= go.mongodb.org/mongo-driver v1.12.1 h1:nLkghSU8fQNaK7oUmDhQFsnrtcoNy7Z6LVFKsEecqgE= go.mongodb.org/mongo-driver v1.12.1/go.mod h1:/rGBTebI3XYboVmgz+Wv3Bcbl3aD0QF9zl6kDDw18rQ= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= @@ -268,6 +310,7 @@ go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191219195013-becbf705a915/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= @@ -284,6 +327,7 @@ golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -305,6 +349,7 @@ golang.org/x/net v0.0.0-20210520170846-37e1c6afe023/go.mod h1:9nx3DQGgdP8bBQD5qx golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.3.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= @@ -332,12 +377,15 @@ golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200509044756-6aff5f38e54f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -346,13 +394,18 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/term v0.9.0/go.mod h1:M6DEAAIenWoTxdKrOltXcmDY3rSplQUkrvaDU5FcQyo= @@ -365,6 +418,7 @@ golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= +golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.10.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= @@ -385,6 +439,7 @@ golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.4.0/go.mod h1:UE5sM2OK9E/d67R0ANs2xJizIymRP5gJU295PvKXxjQ= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/tools v0.9.3 h1:Gn1I8+64MsuTb/HpH+LmQtNas23LhUVr3rYZ0eKuaMM= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/controllers/account/main.go b/controllers/account/main.go index e118ecaf3..16c869f68 100644 --- a/controllers/account/main.go +++ b/controllers/account/main.go @@ -22,6 +22,11 @@ import ( "os" "time" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/webhook" + + "github.com/labring/sealos/controllers/account/controllers/cache" + "github.com/labring/sealos/controllers/pkg/database/mongo" "github.com/labring/sealos/controllers/pkg/resources" @@ -32,20 +37,17 @@ import ( rate "github.com/labring/sealos/controllers/pkg/utils/rate" userv1 "github.com/labring/sealos/controllers/user/api/v1" - accountv1 "github.com/labring/sealos/controllers/account/api/v1" - "github.com/labring/sealos/controllers/account/controllers" - "github.com/labring/sealos/controllers/account/controllers/cache" - "k8s.io/apimachinery/pkg/runtime" utilruntime "k8s.io/apimachinery/pkg/util/runtime" clientgoscheme "k8s.io/client-go/kubernetes/scheme" _ "k8s.io/client-go/plugin/pkg/client/auth" ctrl "sigs.k8s.io/controller-runtime" - "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/controller" "sigs.k8s.io/controller-runtime/pkg/healthz" "sigs.k8s.io/controller-runtime/pkg/log/zap" - "sigs.k8s.io/controller-runtime/pkg/webhook" + + accountv1 "github.com/labring/sealos/controllers/account/api/v1" + "github.com/labring/sealos/controllers/account/controllers" //+kubebuilder:scaffold:imports ) @@ -91,6 +93,11 @@ func main() { flag.Parse() ctrl.SetLogger(zap.New(zap.UseFlagOptions(&opts))) + // local test env + //err := godotenv.Load() + //if err != nil { + // setupLog.Error(err, "unable to load .env file") + //} mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{ Scheme: scheme, @@ -131,28 +138,57 @@ func main() { setupLog.Error(err, "unable to disconnect from mongo") } }() - if err = (&controllers.AccountReconciler{ + accountReconciler := &controllers.AccountReconciler{ Client: mgr.GetClient(), Scheme: mgr.GetScheme(), DBClient: dbClient, - }).SetupWithManager(mgr, rateOpts); err != nil { - setupLog.Error(err, "unable to create controller", "controller", "Account") + } + billingInfoQueryReconciler := &controllers.BillingInfoQueryReconciler{ + Client: mgr.GetClient(), + Scheme: mgr.GetScheme(), + DBClient: dbClient, + Properties: resources.DefaultPropertyTypeLS, + } + activityReconciler := &controllers.ActivityReconciler{ + Client: mgr.GetClient(), + Scheme: mgr.GetScheme(), + DBClient: dbClient, + } + activities, discountSteps, discountRatios, err := controllers.RawParseRechargeConfig() + if err != nil { + setupLog.Error(err, "parse recharge config failed") + } else { + setupLog.Info("parse recharge config success", "activities", activities, "discountSteps", discountSteps, "discountRatios", discountRatios) + accountReconciler.Activities = activities + accountReconciler.RechargeStep = discountSteps + accountReconciler.RechargeRatio = discountRatios + billingInfoQueryReconciler.Activities = activities + billingInfoQueryReconciler.RechargeStep = discountSteps + billingInfoQueryReconciler.RechargeRatio = discountRatios + activityReconciler.Activity = activities + } + setupManagerError := func(err error, controller string) { + setupLog.Error(err, "unable to create controller", "controller", controller) os.Exit(1) } + if err = (activityReconciler).SetupWithManager(mgr, rateOpts); err != nil { + setupManagerError(err, "Activity") + } + if err = (accountReconciler).SetupWithManager(mgr, rateOpts); err != nil { + setupManagerError(err, "Account") + } if err = (&controllers.PaymentReconciler{ Client: mgr.GetClient(), Scheme: mgr.GetScheme(), }).SetupWithManager(mgr, rateOpts); err != nil { - setupLog.Error(err, "unable to create controller", "controller", "Payment") - os.Exit(1) + setupManagerError(err, "Payment") } if err = (&controllers.DebtReconciler{ Client: mgr.GetClient(), Scheme: mgr.GetScheme(), DBClient: dbClient, }).SetupWithManager(mgr, rateOpts); err != nil { - setupLog.Error(err, "unable to create controller", "controller", "Debt") - os.Exit(1) + setupManagerError(err, "Debt") } if err = cache.SetupCache(mgr); err != nil { @@ -175,8 +211,7 @@ func main() { Client: mgr.GetClient(), Scheme: mgr.GetScheme(), }).SetupWithManager(mgr, rateOpts); err != nil { - setupLog.Error(err, "unable to create controller", "controller", "BillingRecordQuery") - os.Exit(1) + setupManagerError(err, "BillingRecordQuery") } if err = (&controllers.BillingReconciler{ DBClient: dbClient, @@ -184,47 +219,37 @@ func main() { Client: mgr.GetClient(), Scheme: mgr.GetScheme(), }).SetupWithManager(mgr, rateOpts); err != nil { - setupLog.Error(err, "unable to create controller", "controller", "Billing") - os.Exit(1) + setupManagerError(err, "Billing") } if err = (&controllers.PodReconciler{ Client: mgr.GetClient(), Scheme: mgr.GetScheme(), }).SetupWithManager(mgr); err != nil { - setupLog.Error(err, "unable to create controller", "controller", "Pod") - os.Exit(1) + setupManagerError(err, "Pod") } if err = (&controllers.NamespaceReconciler{ Client: watchClient, Scheme: mgr.GetScheme(), }).SetupWithManager(mgr); err != nil { - setupLog.Error(err, "unable to create controller", "controller", "Namespace") - os.Exit(1) + setupManagerError(err, "Namespace") } if err = (&controllers.TransferReconciler{ Client: mgr.GetClient(), Scheme: mgr.GetScheme(), DBClient: dbClient, }).SetupWithManager(mgr); err != nil { - setupLog.Error(err, "unable to create controller", "controller", "Transfer") - os.Exit(1) + setupManagerError(err, "Transfer") } if err = (&controllers.NamespaceBillingHistoryReconciler{ Client: mgr.GetClient(), Scheme: mgr.GetScheme(), }).SetupWithManager(mgr); err != nil { - setupLog.Error(err, "unable to create controller", "controller", "NamespaceBillingHistory") - os.Exit(1) + setupManagerError(err, "NamespaceBillingHistory") } - if err = (&controllers.BillingInfoQueryReconciler{ - Client: mgr.GetClient(), - Scheme: mgr.GetScheme(), - DBClient: dbClient, - Properties: resources.DefaultPropertyTypeLS, - }).SetupWithManager(mgr); err != nil { - setupLog.Error(err, "unable to create controller", "controller", "BillingInfoQuery") - os.Exit(1) + billingInfoQueryReconciler.AccountSystemNamespace = accountReconciler.AccountSystemNamespace + if err = (billingInfoQueryReconciler).SetupWithManager(mgr); err != nil { + setupManagerError(err, "BillingInfoQuery") } //+kubebuilder:scaffold:builder diff --git a/controllers/go.work.sum b/controllers/go.work.sum index 831692612..3cb8c8140 100644 --- a/controllers/go.work.sum +++ b/controllers/go.work.sum @@ -273,6 +273,7 @@ github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310 h1:BUAU3CGlLvorLI26 github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a h1:idn718Q4B6AGu/h5Sxe66HYVdqdGu2l9Iebqhi/AEoA= github.com/bgentry/speakeasy v0.1.0 h1:ByYyxL9InA1OWqxJqqp2A5pYHUrCiAL6K3J+LKSsQkY= +github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c h1:+0HFd5KSZ/mm3JmhmrDukiId5iR6w4+BdFtfSy4yWIc= github.com/bketelsen/crypt v0.0.4 h1:w/jqZtC9YD4DS/Vp9GhWfWcCpuAL58oTnLoI8vE9YHU= github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM= github.com/buger/jsonparser v1.1.1 h1:2PnMjfWD7wBILjqQbt530v576A/cAbQvEW9gGIpYMUs= @@ -319,7 +320,9 @@ github.com/envoyproxy/go-control-plane v0.11.1-0.20230524094728-9239064ad72f h1: github.com/envoyproxy/go-control-plane v0.11.1-0.20230524094728-9239064ad72f/go.mod h1:sfYdkwUW4BA3PbKjySwjJy+O4Pu0h62rlqCMHNk+K+Q= github.com/envoyproxy/protoc-gen-validate v0.10.1 h1:c0g45+xCJhdgFGw7a5QAfdS4byAbud7miNWJ1WwEVf8= github.com/envoyproxy/protoc-gen-validate v0.10.1/go.mod h1:DRjgyB0I43LtJapqN6NiRwroiAU2PaFuvk/vjgh61ss= +github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys= github.com/fatih/color v1.12.0 h1:mRhaKNwANqRgUBGKmnI5ZxEk7QXmjQeCcuYFMX2bfcc= +github.com/felixge/httpsnoop v1.0.1 h1:lvB5Jl89CsZtGIWuTcDM1E/vkVs49/Ml7JJe07l8SPQ= github.com/felixge/httpsnoop v1.0.2 h1:+nS9g82KMXccJ/wp0zyRW9ZBHFETmMGtkk+2CTTrW4o= github.com/flowstack/go-jsonschema v0.1.1 h1:dCrjGJRXIlbDsLAgTJZTjhwUJnnxVWl1OgNyYh5nyDc= github.com/form3tech-oss/jwt-go v3.2.3+incompatible h1:7ZaBxOI7TMoYBfyA3cQHErNNyAWIKUMIwqxEtgHOs5c= @@ -359,6 +362,7 @@ github.com/googleapis/gax-go/v2 v2.7.1/go.mod h1:4orTrqY6hXxxaUL4LHIPl6lGo8vAE38 github.com/googleapis/gnostic v0.5.5 h1:9fHAtK0uDfpveeqqo1hkEZJcFvYXAiCN3UutL8F9xHw= github.com/googleapis/go-type-adapters v1.0.0 h1:9XdMn+d/G57qq1s8dNc5IesGCXHf6V2HZ2JwRxfA2tA= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8= +github.com/gopherjs/gopherjs v0.0.0-20200217142428-fce0ec30dd00 h1:l5lAOZEym3oK3SQ2HBHWsJUfbNBiTXJDeW2QDxw9AQ0= github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7 h1:pdN6V1QBWetyv/0+wjACpqVH+eVULgEjkurDLq3goeM= @@ -372,6 +376,7 @@ github.com/hashicorp/consul/api v1.1.0 h1:BNQPM9ytxj6jbjjdRPioQ94T6YXriSopn0i8CO github.com/hashicorp/consul/sdk v0.1.1 h1:LnuDWGNsoajlhGyHJvuWW6FVqRl8JOTPqS6CPTsYjhY= github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= github.com/hashicorp/go-cleanhttp v0.5.1 h1:dH3aiDG9Jvb5r5+bYHsikaOUIpcM0xvgMXVoDkXMzJM= +github.com/hashicorp/go-immutable-radix v1.0.0 h1:AKDB1HM5PWEA7i4nhcpwOrO2byshxBjXVn/J/3+z5/0= github.com/hashicorp/go-immutable-radix v1.3.0 h1:8exGP7ego3OmkfksihtSouGMZ+hQrhxx+FVELeXpVPE= github.com/hashicorp/go-memdb v1.3.2 h1:RBKHOsnSszpU6vxq80LzC2BaQjuuvoyaQbkLTf7V7g8= github.com/hashicorp/go-msgpack v0.5.3 h1:zKjpN5BK/P5lMYrLmBHdBULWbJ0XpYR+7NGzqkZzoD4= @@ -381,6 +386,7 @@ github.com/hashicorp/go-sockaddr v1.0.0 h1:GeH6tui99pF4NJgfnhp+L6+FfobzVW3Ah46sL github.com/hashicorp/go-syslog v1.0.0 h1:KaodqZuhUoZereWVIYmpUgZysurB1kBLX2j0MwMrUAE= github.com/hashicorp/go-uuid v1.0.1 h1:fv1ep09latC32wFoVwnqcnKJGnMSdBanPczbHAYm1BE= github.com/hashicorp/go.net v0.0.1 h1:sNCoNyDEvN1xa+X0baata4RdcpKwcMS6DH+xwfqPgjw= +github.com/hashicorp/golang-lru v0.5.1 h1:0hERBMJE1eitiLkihrMvRVBYAkpHzc/J3QdDN+dAcgU= github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/logutils v1.0.0 h1:dLEQVugN8vlakKOUE3ihGLTZJRB4j+M2cdTm/ORI65Y= @@ -394,8 +400,8 @@ github.com/ianlancetaylor/demangle v0.0.0-20220517205856-0058ec4f073c/go.mod h1: github.com/imdario/mergo v0.3.6/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= github.com/jessevdk/go-flags v1.4.0 h1:4IU2WS7AumrZ/40jfhf4QVDMsQwqA7VEHozFRrGARJA= github.com/jonboulle/clockwork v0.2.2 h1:UOGuzwb1PwsrDAObMuhUnj0p5ULPj8V/xJ7Kx9qUBdQ= -github.com/jpillora/backoff v1.0.0 h1:uvFg412JmmHBHw7iwprIxkPMI+sGQ4kzOWsMeHnm2EA= github.com/jstemmer/go-junit-report v0.9.1 h1:6QPYqodiu3GuPL+7mfx+NwDdp2eTkp9IfEUpgAwUN0o= +github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= github.com/julienschmidt/httprouter v1.3.0 h1:U0609e9tgbseu3rBINet9P48AI/D3oJs4dN7jwJOQ1U= github.com/kisielk/errcheck v1.5.0 h1:e8esj/e4R+SAOwFwN+n3zr0nYeCyeweozKfO23MvHzY= github.com/kisielk/gotool v1.0.0 h1:AV2c/EiW3KqPNT9ZKl07ehoAGi4C5/01Cfbblndcapg= @@ -408,15 +414,15 @@ github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3x github.com/kr/pty v1.1.1 h1:VkoXIwSboBpnk99O/KFauAEILuNHv5DVFKZMBN/gUgw= github.com/lithammer/dedent v1.1.0 h1:VNzHMVCBNG1j0fh3OrsFRkVUwStdDArbgBWoPAffktY= github.com/lyft/protoc-gen-star/v2 v2.0.1 h1:keaAo8hRuAT0O3DfJ/wM3rufbAjGeJ1lAtWZHDjKGB0= +github.com/magiconair/properties v1.8.1 h1:ZC2Vc7/ZFkGmsVC9KvOjumD+G5lXy2RtTKyzRKO2BQ4= github.com/magiconair/properties v1.8.5 h1:b6kJs+EmPFMYGkow9GiUyCyOvIwYetYJ3fSaWak/Gls= github.com/matoous/go-nanoid v1.5.0 h1:VRorl6uCngneC4oUQqOYtO3S0H5QKFtKuKycFG3euek= +github.com/mattn/go-colorable v0.0.9 h1:UVL0vNpWh04HeJXV0KLcaT7r06gOH2l4OW6ddYRUIY4= github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8= github.com/mattn/go-shellwords v1.0.12 h1:M2zGm7EW6UQJvDeQxo4T51eKPurbeFbe8WtebGE2xrk= github.com/miekg/dns v1.0.14 h1:9jZdLNd/P4+SfEJ0TNyxYpsK8N4GtfylBLqtbYN1sbA= github.com/minio/asm2plan9s v0.0.0-20200509001527-cdd76441f9d8 h1:AMFGa4R4MiIpspGNG7Z948v4n35fFGB3RR3G/ry4FWs= github.com/minio/c2goasm v0.0.0-20190812172519-36a3d3bbc4f3 h1:+n/aFZefKZp7spd8DFdX7uMikMLXX4oubIzJF4kv/wI= -github.com/minio/minio-go/v7 v7.0.64 h1:Zdza8HwOzkld0ZG/og50w56fKi6AAyfqfifmasD9n2Q= -github.com/minio/minio-go/v7 v7.0.64/go.mod h1:R4WVUR6ZTedlCcGwZRauLMIKjgyaWxhs4Mqi/OMPmEc= github.com/mistifyio/go-zfs/v3 v3.0.1 h1:YaoXgBePoMA12+S1u/ddkv+QqxcfiZK4prI6HPnkFiU= github.com/mitchellh/cli v1.0.0 h1:iGBIsUe3+HZ/AD/Vd7DErOt5sU9fa8Uj7A2s1aggv1Y= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= @@ -426,7 +432,6 @@ github.com/mitchellh/iochan v1.0.0 h1:C+X3KsSTLFVBr/tK1eYN/vs4rJcvsiLU338UhYPJWe github.com/moby/spdystream v0.2.0 h1:cjW1zVyyoiM0T7b6UoySUFqzXMoqRckQtXwGPiBhOM8= github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6 h1:dcztxKSvZ4Id8iPpHERQBbIJfabdt4wUm5qy3wOL2Zc= github.com/mrunalp/fileutils v0.5.0 h1:NKzVxiH7eSk+OQ4M+ZYW1K6h27RUV3MI6NUTsHhU6Z4= -github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f h1:KUppIJq7/+SVif2QVs3tOP0zanoHgBEVAwHxUSIzRqU= github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f h1:y5//uYreIhSUg3J1GEMiLbxo1LJaP8RfCpH6pymGZus= github.com/oklog/ulid v1.3.1 h1:EGfNDEx6MqHz8B3uNV6QAib1UR2Lm97sHi3ocA6ESJ4= github.com/onsi/ginkgo/v2 v2.1.3/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c= @@ -460,11 +465,16 @@ github.com/seccomp/libseccomp-golang v0.9.2-0.20220502022130-f33da4d89646 h1:Rpf github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo= github.com/slok/kubewebhook/v2 v2.2.0 h1:pOrFBTp6hnO0zakRfR9rd5WDRGiUimerNfR/JoNg1uI= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM= +github.com/smartystreets/assertions v1.1.0 h1:MkTeG1DMwsrdH7QtLXy5W+fUxWq+vmb6cLmyJ7aRtF0= +github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s= github.com/soheilhy/cmux v0.1.5 h1:jjzc5WVemNEDTLwv9tlmemhC73tI08BNOIGwBOo10Js= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72 h1:qLC7fQah7D6K1B0ujays3HV9gkFtllcxhzImRR7ArPQ= github.com/spf13/afero v1.6.0 h1:xoax2sJ2DT8S8xA2paPFjDCScCNeWsg75VG0DLRreiY= +github.com/spf13/cast v1.3.0 h1:oget//CVOEoFewqQxwr0Ej5yjygnqGkvggSE/gB35Q8= github.com/spf13/cast v1.3.1 h1:nFm6S0SMdyzrzcmThSipiEubIDy8WEXKNZ0UOgiRpng= +github.com/spf13/jwalterweatherman v1.0.0 h1:XHEdyB+EcvlqZamSM4ZOMGlc93t6AcsBEu9Gc1vn7yk= github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk= +github.com/spf13/viper v1.7.0 h1:xVKxvI7ouOI5I+U9s2eeiUfMaWBVoXA3AWskkrqK0VM= github.com/spf13/viper v1.8.1 h1:Kq1fyeebqsBfbjZj4EL7gj2IO0mMaiyjYUWcUsl2O44= github.com/stoewer/go-strcase v1.2.0 h1:Z2iHWqGXH00XYgqDmNgQbIBxf3wrNq0F3feEy0ainaU= github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c= @@ -504,16 +514,21 @@ go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= go.opentelemetry.io/contrib v0.20.0 h1:ubFQUn0VCZ0gPwIoJfBJVpeBlyRMxu8Mm/huKWYd9p0= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.20.0 h1:sO4WKdPAudZGKPcpZT4MJn6JaDmpyLrMPDGGyA1SttE= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.20.0 h1:Q3C9yzW6I9jqEc8sawxzxZmY48fs9u220KXq6d5s3XU= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.27.0 h1:0BgiNWjN7rUWO9HdjF4L12r8OW86QkVQcYmCjnayJLo= +go.opentelemetry.io/otel v0.20.0 h1:eaP0Fqu7SXHwvjiqDq83zImeehOHX8doTvU9AwXON8g= go.opentelemetry.io/otel v1.2.0 h1:YOQDvxO1FayUcT9MIhJhgMyNO1WqoduiyvQHzGN0kUQ= go.opentelemetry.io/otel/exporters/otlp v0.20.0 h1:PTNgq9MRmQqqJY0REVbZFvwkYOA85vbdQU/nVfxDyqg= go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.2.0 h1:OiYdrCq1Ctwnovp6EofSPwlp5aGy4LgKNbkg7PtEUw8= go.opentelemetry.io/otel/internal/metric v0.25.0 h1:w/7RXe16WdPylaIXDgcYM6t/q0K5lXgSdZOEbIEyliE= +go.opentelemetry.io/otel/metric v0.20.0 h1:4kzhXFP+btKm4jwxpjIqjs41A7MakRFUS86bqLHTIw8= go.opentelemetry.io/otel/metric v0.25.0 h1:7cXOnCADUsR3+EOqxPaSKwhEuNu0gz/56dRN1hpIdKw= go.opentelemetry.io/otel/oteltest v0.20.0 h1:HiITxCawalo5vQzdHfKeZurV8x7ljcqAgiWzF6Vaeaw= +go.opentelemetry.io/otel/sdk v0.20.0 h1:JsxtGXd06J8jrnya7fdI/U/MR6yXA5DtbZy+qoHQlr8= go.opentelemetry.io/otel/sdk v1.2.0 h1:wKN260u4DesJYhyjxDa7LRFkuhH7ncEVKU37LWcyNIo= go.opentelemetry.io/otel/sdk/export/metric v0.20.0 h1:c5VRjxCXdQlx1HjzwGdQHzZaVI82b5EbBgOu2ljD92g= go.opentelemetry.io/otel/sdk/metric v0.20.0 h1:7ao1wpzHRVKf0OQ7GIxiQJA6X7DLX9o14gmVon7mMK8= +go.opentelemetry.io/otel/trace v0.20.0 h1:1DL6EXUdcg95gukhuRRvLDO/4X5THh/5dIV52lqtnbw= go.opentelemetry.io/otel/trace v1.2.0 h1:Ys3iqbqZhcf28hHzrm5WAquMkDHNZTUkw7KHbuNjej0= go.opentelemetry.io/proto/otlp v0.19.0 h1:IVN6GR+mhC4s5yfcTbmzHYODqvWAp3ZedA2SJPI1Nnw= go.opentelemetry.io/proto/otlp v0.19.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U= diff --git a/controllers/license/go.mod b/controllers/license/go.mod index bf7b7e988..74c1e1fe5 100644 --- a/controllers/license/go.mod +++ b/controllers/license/go.mod @@ -71,7 +71,7 @@ require ( github.com/pkg/errors v0.9.1 // indirect github.com/prometheus/client_golang v1.15.1 // indirect github.com/prometheus/client_model v0.4.0 // indirect - github.com/prometheus/common v0.42.0 // indirect + github.com/prometheus/common v0.44.0 // indirect github.com/prometheus/procfs v0.9.0 // indirect github.com/spf13/pflag v1.0.5 // indirect github.com/xdg-go/pbkdf2 v1.0.0 // indirect diff --git a/controllers/license/go.sum b/controllers/license/go.sum index 9375c86d4..fc4f6db4b 100644 --- a/controllers/license/go.sum +++ b/controllers/license/go.sum @@ -177,8 +177,8 @@ github.com/prometheus/client_golang v1.15.1/go.mod h1:e9yaBhRPU2pPNsZwE+JdQl0KEt github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.4.0 h1:5lQXD3cAg1OXBf4Wq03gTrXHeaV0TQvGfUooCfx1yqY= github.com/prometheus/client_model v0.4.0/go.mod h1:oMQmHW1/JoDwqLtg57MGgP/Fb1CJEYF2imWWhWtMkYU= -github.com/prometheus/common v0.42.0 h1:EKsfXEYo4JpWMHH5cg+KOUWeuJSov1Id8zGR8eeI1YM= -github.com/prometheus/common v0.42.0/go.mod h1:xBwqVerjNdUDjgODMpudtOMwlOwf2SaTr1yjz4b7Zbc= +github.com/prometheus/common v0.44.0 h1:+5BrQJwiBB9xsMygAB3TNvpQKOwlkc25LbISbrdOOfY= +github.com/prometheus/common v0.44.0/go.mod h1:ofAIvZbQ1e/nugmZGz4/qCb9Ap1VoSTIO7x0VV9VvuY= github.com/prometheus/procfs v0.9.0 h1:wzCHvIvM5SxWqYvwgVL7yJY8Lz3PKn49KQtpgMYJfhI= github.com/prometheus/procfs v0.9.0/go.mod h1:+pB4zwohETzFnmlpe6yd2lSc+0/46IYZRB/chUwxUZY= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= diff --git a/controllers/pkg/go.mod b/controllers/pkg/go.mod index 3a6a1082e..87730f6fe 100644 --- a/controllers/pkg/go.mod +++ b/controllers/pkg/go.mod @@ -95,7 +95,7 @@ require ( github.com/pelletier/go-toml/v2 v2.0.8 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/prometheus/client_model v0.4.0 // indirect - github.com/prometheus/common v0.42.0 // indirect + github.com/prometheus/common v0.44.0 // indirect github.com/prometheus/procfs v0.9.0 // indirect github.com/rogpeppe/go-internal v1.11.0 // indirect github.com/rs/xid v1.5.0 // indirect diff --git a/controllers/pkg/go.sum b/controllers/pkg/go.sum index 870662d0e..6567ac2ba 100644 --- a/controllers/pkg/go.sum +++ b/controllers/pkg/go.sum @@ -202,8 +202,8 @@ github.com/prometheus/client_golang v1.15.1/go.mod h1:e9yaBhRPU2pPNsZwE+JdQl0KEt github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.4.0 h1:5lQXD3cAg1OXBf4Wq03gTrXHeaV0TQvGfUooCfx1yqY= github.com/prometheus/client_model v0.4.0/go.mod h1:oMQmHW1/JoDwqLtg57MGgP/Fb1CJEYF2imWWhWtMkYU= -github.com/prometheus/common v0.42.0 h1:EKsfXEYo4JpWMHH5cg+KOUWeuJSov1Id8zGR8eeI1YM= -github.com/prometheus/common v0.42.0/go.mod h1:xBwqVerjNdUDjgODMpudtOMwlOwf2SaTr1yjz4b7Zbc= +github.com/prometheus/common v0.44.0 h1:+5BrQJwiBB9xsMygAB3TNvpQKOwlkc25LbISbrdOOfY= +github.com/prometheus/common v0.44.0/go.mod h1:ofAIvZbQ1e/nugmZGz4/qCb9Ap1VoSTIO7x0VV9VvuY= github.com/prometheus/procfs v0.9.0 h1:wzCHvIvM5SxWqYvwgVL7yJY8Lz3PKn49KQtpgMYJfhI= github.com/prometheus/procfs v0.9.0/go.mod h1:+pB4zwohETzFnmlpe6yd2lSc+0/46IYZRB/chUwxUZY= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= diff --git a/controllers/pkg/types/activity.go b/controllers/pkg/types/activity.go new file mode 100644 index 000000000..92c68b23e --- /dev/null +++ b/controllers/pkg/types/activity.go @@ -0,0 +1,159 @@ +// Copyright © 2023 sealos. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package types + +import ( + "fmt" + "strconv" + "strings" + "time" +) + +type RechargeDiscount struct { + LimitTimes int64 `json:"limitTimes,omitempty"` + LimitDuration string `json:"limitDuration,omitempty"` + DiscountRates []float64 `json:"discountRates,omitempty"` + DiscountSteps []int64 `json:"discountSteps,omitempty"` + SpecialDiscount map[int64]int64 `json:"specialDiscount,omitempty"` +} + +type Phase struct { + Name string `json:"name"` + GiveAmount int64 `json:"giveAmount"` + RechargeDiscount RechargeDiscount `json:",inline"` +} + +type Activity struct { + ActivityType string `json:"activityType"` + Phases map[string]Phase `json:"phases"` + PhaseOrder string `json:"phaseOrder"` +} + +type Activities map[string]*Activity + +type UserActivities map[string]*UserActivity + +type UserPhase struct { + Name string `json:"name"` + //RFC339 time format + StartTime time.Time `json:"startTime"` + EndTime time.Time `json:"endTime"` + RechargeNums int64 `json:"rechargeNums"` + GiveAmount int64 `json:"giveAmount"` +} + +type UserActivity struct { + CurrentPhase string `json:"currentPhase"` + Phases map[string]*UserPhase +} + +func ParseUserActivities(annotations map[string]string) (UserActivities, error) { + userActivities := make(map[string]*UserActivity) + + for key, value := range annotations { + parts := strings.Split(key, ".") + + if len(parts) == 3 && parts[0] == "activity" && parts[2] == "current-phase" { + if _, exists := userActivities[parts[1]]; !exists { + userActivities[parts[1]] = &UserActivity{ + Phases: make(map[string]*UserPhase), + } + } + userActivities[parts[1]].CurrentPhase = value + } + + if len(parts) == 4 && parts[0] == "activity" { + activityType := parts[1] + phase := parts[2] + + if _, exists := userActivities[activityType]; !exists { + userActivities[activityType] = &UserActivity{ + Phases: make(map[string]*UserPhase), + } + } + + if _, exists := userActivities[activityType].Phases[phase]; !exists { + userActivities[activityType].Phases[phase] = &UserPhase{Name: phase} + } + var err error + switch parts[3] { + case "startTime": + fmt.Println(value) + userActivities[activityType].Phases[phase].StartTime, err = time.Parse(time.RFC3339, value) + if err != nil { + return nil, fmt.Errorf("parse start time failed: %w", err) + } + case "endTime": + userActivities[activityType].Phases[phase].EndTime, err = time.Parse(time.RFC3339, value) + if err != nil { + return nil, fmt.Errorf("parse end time failed: %w", err) + } + case "rechargeNums": + userActivities[activityType].Phases[phase].RechargeNums, err = strconv.ParseInt(value, 10, 64) + if err != nil { + return nil, fmt.Errorf("parse %s to recharge nums failed: %w", value, err) + } + case "giveAmount": + userActivities[activityType].Phases[phase].GiveAmount, err = strconv.ParseInt(value, 10, 64) + if err != nil { + return nil, fmt.Errorf("parse %s to give amount failed: %w", value, err) + } + } + } + } + return userActivities, nil +} + +func SetUserPhaseRechargeTimes(annotations map[string]string, activityType string, phase string, rechargeNums int64) map[string]string { + annotations[fmt.Sprintf("activity.%s.%s.rechargeNums", activityType, phase)] = fmt.Sprintf("%d", rechargeNums) + return annotations +} + +func SetUserPhaseGiveAmount(annotations map[string]string, activityType string, phase string, giveAmount int64) map[string]string { + annotations[fmt.Sprintf("activity.%s.%s.giveAmount", activityType, phase)] = fmt.Sprintf("%d", giveAmount) + return annotations +} + +func GetUserActivityDiscount(activities Activities, userActivities *UserActivities) (activityType string, returnPhase *Phase, returnErr error) { + if activities == nil || userActivities == nil { + returnErr = fmt.Errorf("activities is nil") + return + } + for aType, userActivity := range *userActivities { + activity := activities[aType] + phase, exists := activity.Phases[userActivity.CurrentPhase] + if !exists { + returnErr = fmt.Errorf("phase %s not exist", userActivity.CurrentPhase) + return + } + + if phase.RechargeDiscount.LimitTimes > 0 && userActivity.Phases[userActivity.CurrentPhase].RechargeNums >= phase.RechargeDiscount.LimitTimes { + return + } + if phase.RechargeDiscount.LimitDuration != "" { + duration, err := time.ParseDuration(phase.RechargeDiscount.LimitDuration) + if err != nil { + returnErr = fmt.Errorf("parse duration failed: %w", err) + return + } + if time.Now().After(userActivity.Phases[userActivity.CurrentPhase].EndTime.Add(duration)) { + return + } + } + return aType, &phase, nil + } + returnErr = fmt.Errorf("user activity not exist") + return +}