Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feature: recharge gift by configmap #3542

Closed
wants to merge 16 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion controllers/account/api/v1/debt_webhook.go
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ func checkOption(ctx context.Context, logger logr.Logger, c client.Client, nsNam
return admission.Allowed("namespace not found")
}
// Check if it is a user namespace
user, ok := ns.Annotations[userv1.UserAnnotationOwnerKey]
user, ok := ns.Annotations[userv1.UserAnnotationCreatorKey]
logger.V(1).Info("check user namespace", "ns.name", ns.Name, "ns", ns)
if !ok {
return admission.ValidationResponse(true, fmt.Sprintf("this namespace is not user namespace %s,or have not create", ns.Name))
Expand Down
12 changes: 12 additions & 0 deletions controllers/account/config/rbac/role.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,18 @@ metadata:
creationTimestamp: null
name: manager-role
rules:
- apiGroups:
- ""
resources:
- configmaps
verbs:
- create
- delete
- get
- list
- patch
- update
- watch
- apiGroups:
- account.sealos.io
resources:
Expand Down
66 changes: 36 additions & 30 deletions controllers/account/controllers/account_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,10 @@ import (
"fmt"
"os"
"strconv"
"strings"
"time"

"k8s.io/apimachinery/pkg/types"
"sigs.k8s.io/controller-runtime/pkg/event"
"sigs.k8s.io/controller-runtime/pkg/predicate"

Expand Down Expand Up @@ -85,6 +87,7 @@ type AccountReconciler struct {
//+kubebuilder:rbac:groups=account.sealos.io,resources=accountbalances/status,verbs=get;list;watch;create;update;patch;delete
//+kubebuilder:rbac:groups=rbac.authorization.k8s.io,resources=rolebindings,verbs=get;list;watch;create;update;patch;delete
//+kubebuilder:rbac:groups=rbac.authorization.k8s.io,resources=roles,verbs=get;list;watch;create;update;patch;delete
//+kubebuilder:rbac:groups="",resources=configmaps,verbs=get;list;watch;create;update;patch;delete

func (r *AccountReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
//It should not stop the normal process for the failure to delete the payment
Expand All @@ -100,6 +103,11 @@ func (r *AccountReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ct
return ctrl.Result{}, err
}

configMap := &corev1.ConfigMap{}
if err := r.Client.Get(ctx, types.NamespacedName{Name: "recharge-gift", Namespace: "sealos"}, configMap); err != nil {
r.Logger.Error(err, "get recharge-gift ConfigMap failed")
}

accountBalance := accountv1.AccountBalance{}
if err := r.Get(ctx, req.NamespacedName, &accountBalance); err == nil {
err = retry2.RetryOnConflict(retry2.DefaultBackoff, func() error {
Expand Down Expand Up @@ -153,7 +161,11 @@ func (r *AccountReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ct
now := time.Now().UTC()
payAmount := *orderResp.Amount.Total * 10000
//1¥ = 100WechatPayAmount; 1 WechatPayAmount = 10000 SealosAmount
err = crypto.RechargeBalance(account.Status.EncryptBalance, giveGift(payAmount))
gift, err := giveGift(payAmount, configMap)
if err != nil {
r.Logger.Error(err, "get gift error")
}
err = crypto.RechargeBalance(account.Status.EncryptBalance, gift)
if err != nil {
return ctrl.Result{}, fmt.Errorf("recharge encrypt balance failed: %v", err)
}
Expand Down Expand Up @@ -493,36 +505,30 @@ func (p *NamespaceFilterPredicate) Generic(e event.GenericEvent) bool {
return e.Object.GetNamespace() == p.Namespace
}

const (
BaseUnit = 1_000_000
Threshold1 = 299 * BaseUnit
Threshold2 = 599 * BaseUnit
Threshold3 = 1999 * BaseUnit
Threshold4 = 4999 * BaseUnit
Threshold5 = 19999 * BaseUnit
Ratio0 int64 = 0
Ratio1 int64 = 10
Ratio2 int64 = 15
Ratio3 int64 = 20
Ratio4 int64 = 25
Ratio5 int64 = 30
)
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")
}
stepsStr := strings.Split(configMap.Data["steps"], ",")
ratiosStr := strings.Split(configMap.Data["ratios"], ",")

func giveGift(amount int64) int64 {
var ratio int64
switch {
case amount < Threshold1:
ratio = Ratio0
case amount < Threshold2:
ratio = Ratio1
case amount < Threshold3:
ratio = Ratio2
case amount < Threshold4:
ratio = Ratio3
case amount < Threshold5:
ratio = Ratio4
default:
ratio = Ratio5

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.ParseInt(ratiosStr[i], 10, 64)
if err != nil {
return amount, fmt.Errorf("ratios format error :%s", err)
}
} else {
break
}
}
return (amount * ratio / 100) + amount
return (amount * ratio / 100) + amount, nil
}
14 changes: 12 additions & 2 deletions controllers/account/controllers/account_controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,11 @@ limitations under the License.

package controllers

import "testing"
import (
"testing"

corev1 "k8s.io/api/core/v1"
)

func Test_giveGift(t *testing.T) {
type args struct {
Expand All @@ -43,9 +47,15 @@ func Test_giveGift(t *testing.T) {
{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,15,20,25,30"

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := giveGift(tt.args.amount); got != tt.want {
if got, _ := giveGift(tt.args.amount, configMap); got != tt.want {
t.Errorf("giveGift() = %v, want %v", got, tt.want)
}
})
Expand Down
6 changes: 3 additions & 3 deletions controllers/account/controllers/billing_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ func (r *BillingReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ct
return ctrl.Result{}, nil
}

own := ns.Annotations[v1.UserAnnotationOwnerKey]
own := ns.Annotations[v1.UserAnnotationCreatorKey]
if own == "" {
r.Logger.V(1).Info("billing namespace not found owner annotation", "namespace", ns.Name)
return ctrl.Result{}, nil
Expand All @@ -119,7 +119,7 @@ func (r *BillingReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ct
// return ctrl.Result{}, err
//}
//for _, namespace := range nsList.Items {
// if namespace.Annotations[v1.UserAnnotationOwnerKey] != own {
// if namespace.Annotations[v1.UserAnnotationCreatorKey] != own {
// continue
// }
// if err = r.syncResourceQuota(ctx, namespace.Name); err != nil {
Expand Down Expand Up @@ -270,7 +270,7 @@ func (r *BillingReconciler) SetupWithManager(mgr ctrl.Manager, rateOpts controll
return ctrl.NewControllerManagedBy(mgr).
For(&corev1.Namespace{}, builder.WithPredicates(predicate.Funcs{
CreateFunc: func(createEvent event.CreateEvent) bool {
_, ok := createEvent.Object.GetAnnotations()[v1.UserAnnotationOwnerKey]
_, ok := createEvent.Object.GetAnnotations()[v1.UserAnnotationCreatorKey]
return ok
},
UpdateFunc: func(updateEvent event.UpdateEvent) bool {
Expand Down
12 changes: 12 additions & 0 deletions controllers/account/deploy/manifests/deploy.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -636,6 +636,18 @@ metadata:
creationTimestamp: null
name: account-manager-role
rules:
- apiGroups:
- ""
resources:
- configmaps
verbs:
- create
- delete
- get
- list
- patch
- update
- watch
- apiGroups:
- account.sealos.io
resources:
Expand Down
2 changes: 1 addition & 1 deletion controllers/resources/controllers/monitor_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -272,7 +272,7 @@ func (r *MonitorReconciler) podResourceUsage(ctx context.Context, dbClient datab
if client.IgnoreNotFound(err) != nil {
return err
}
if _, ok := namespace.GetAnnotations()[v1.UserAnnotationOwnerKey]; ok {
if _, ok := namespace.GetAnnotations()[v1.UserAnnotationCreatorKey]; ok {
//+kubebuilder:rbac:groups=rbac.authorization.k8s.io,resources=rolebindings,verbs=get;list;watch;create;update;patch;delete
//+kubebuilder:rbac:groups=rbac.authorization.k8s.io,resources=roles,verbs=get;list;watch;create;update;patch;delete
//if err = r.syncResourceQuota(ctx, namespace.Name); err != nil {
Expand Down
6 changes: 5 additions & 1 deletion controllers/user/api/v1/groupversion_info.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,11 @@ var (
)

const (
UserAnnotationOwnerKey = "user.sealos.io/creator"
// UserAnnotationCreatorKey refers to the user who created the resource
UserAnnotationCreatorKey = "user.sealos.io/creator"
// UserAnnotationOwnerKey refers to the user who owns the resource
UserAnnotationOwnerKey = "user.sealos.io/owner"
UserLabelOwnerKey = "user.sealos.io/owner"
UserAnnotationDisplayKey = "user.sealos.io/display-name"
)

Expand Down
3 changes: 3 additions & 0 deletions controllers/user/api/v1/user_webhook.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,9 @@ func (r *User) Default() {
if r.Annotations[UserAnnotationDisplayKey] == "" {
r.Annotations[UserAnnotationDisplayKey] = r.Name
}
if r.Annotations[UserAnnotationOwnerKey] == "" {
r.Annotations[UserAnnotationOwnerKey] = r.Name
}
}

// TODO(user): change verbs to "verbs=create;update;delete" if you want to enable deletion validation.
Expand Down
26 changes: 21 additions & 5 deletions controllers/user/controllers/user_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,9 @@ import (
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
)

var userAnnotationCreatorKey = userv1.UserAnnotationCreatorKey
var userAnnotationOwnerKey = userv1.UserAnnotationOwnerKey
var userLabelOwnerKey = userv1.UserLabelOwnerKey

// UserReconciler reconciles a User object
type UserReconciler struct {
Expand Down Expand Up @@ -134,7 +136,7 @@ func (r *UserReconciler) SetupWithManager(mgr ctrl.Manager, opts utilcontroller.
owner := &handler.EnqueueRequestForOwner{OwnerType: &userv1.User{}, IsController: true}
return ctrl.NewControllerManagedBy(mgr).
For(&userv1.User{}, builder.WithPredicates(
predicate.Or(predicate.GenerationChangedPredicate{}))).
predicate.Or(predicate.GenerationChangedPredicate{}, predicate.AnnotationChangedPredicate{}))).
Watches(&source.Kind{Type: &v1.ServiceAccount{}}, owner).
Watches(&source.Kind{Type: &v12.Role{}}, owner).
Watches(&source.Kind{Type: &v12.RoleBinding{}}, owner).
Expand Down Expand Up @@ -233,8 +235,13 @@ func (r *UserReconciler) syncNamespace(ctx context.Context, user *userv1.User) c
r.Logger.V(1).Info("define namespace User namespace is created", "isCreated", isCreated, "namespace", ns.Name)
}
if change, err = controllerutil.CreateOrUpdate(ctx, r.Client, ns, func() error {
ns.Annotations = map[string]string{userAnnotationOwnerKey: user.Name}
ns.Annotations = map[string]string{
userAnnotationCreatorKey: user.Name,
userAnnotationOwnerKey: user.Annotations[userAnnotationOwnerKey],
}
ns.Labels = config.SetPodSecurity(ns.Labels)
// add label for namespace to filter
ns.Labels[userLabelOwnerKey] = user.Annotations[userAnnotationOwnerKey]
ns.SetOwnerReferences([]metav1.OwnerReference{})
return controllerutil.SetControllerReference(user, ns, r.Scheme)
}); err != nil {
Expand Down Expand Up @@ -274,7 +281,10 @@ func (r *UserReconciler) syncRole(ctx context.Context, user *userv1.User) contex
role.Namespace = config.GetUsersNamespace(user.Name)
role.Labels = map[string]string{}
if change, err = controllerutil.CreateOrUpdate(ctx, r.Client, role, func() error {
role.Annotations = map[string]string{userAnnotationOwnerKey: user.Name}
role.Annotations = map[string]string{
userAnnotationCreatorKey: user.Name,
userAnnotationOwnerKey: user.Annotations[userAnnotationOwnerKey],
}
role.Rules = config.GetUserRole()
return controllerutil.SetControllerReference(user, role, r.Scheme)
}); err != nil {
Expand Down Expand Up @@ -313,7 +323,10 @@ func (r *UserReconciler) syncRoleBinding(ctx context.Context, user *userv1.User)
roleBinding.Namespace = config.GetUsersNamespace(user.Name)
roleBinding.Labels = map[string]string{}
if change, err = controllerutil.CreateOrUpdate(ctx, r.Client, roleBinding, func() error {
roleBinding.Annotations = map[string]string{userAnnotationOwnerKey: user.Name}
roleBinding.Annotations = map[string]string{
userAnnotationCreatorKey: user.Name,
userAnnotationOwnerKey: user.Annotations[userAnnotationOwnerKey],
}
roleBinding.RoleRef = v12.RoleRef{
APIGroup: v12.GroupName,
Kind: "Role",
Expand Down Expand Up @@ -379,7 +392,10 @@ func (r *UserReconciler) syncServiceAccount(ctx context.Context, user *userv1.Us
}
secretName := kubeconfig.SecretName(user.Name)
if change, err = controllerutil.CreateOrUpdate(ctx, r.Client, sa, func() error {
sa.Annotations = map[string]string{userAnnotationOwnerKey: user.Name}
sa.Annotations = map[string]string{
userAnnotationCreatorKey: user.Name,
userAnnotationOwnerKey: user.Annotations[userAnnotationOwnerKey],
}
if len(sa.Secrets) == 0 {
sa.Secrets = []v1.ObjectReference{
{
Expand Down
31 changes: 0 additions & 31 deletions deploy/cloud-deprecated/README.md

This file was deleted.

12 changes: 10 additions & 2 deletions deploy/cloud/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,13 +46,15 @@ sealos gen labring/kubernetes:v1.25.6\
labring/zot:v1.4.3\
labring/kubeblocks:v0.5.3\
--env policy=anonymousPolicy\
--masters 10.140.0.16 > Clusterfile
--masters 10.140.0.16 \
--nodes 10.140.0.17, 10.140.0.18 > Clusterfile

sealos apply -f Clusterfile
```

Note: if you want to change pod cidr, please edit the `Clusterfile` before run `sealos apply`


### Ingress-nginx setup
We use ingress-nginx to expose our services. You can install ingress-nginx by using sealos:

Expand Down Expand Up @@ -82,10 +84,16 @@ Install ingress-nginx and switch to NodePort mode
sealos run docker.io/labring/ingress-nginx:v1.5.1 --config-file ingress-nginx-config.yaml
```

Note: if your domain is resolved to the master ip, you may need patch ingress-nginx DaemonSet to run on master node:

```shell
kubectl -n ingress-nginx patch ds ingress-nginx-controller -p '{"spec":{"template":{"spec":{"tolerations":[{"key":"node-role.kubernetes.io/master","operator":"Exists","effect":"NoSchedule"}]}}}}'
````

## run sealos cloud cluster image

### Generate TLS config file
You can skip this step if you use the self-signed cert that we provide by default.
You can skip this step if you use the self-signed cert which we provided by default.

Please make sure `spec.match` is the same as the image you want to run and the registry name such as ghcr.io/docker.io can

Expand Down
Loading
Loading