mirror of
https://github.com/labring/sealos.git
synced 2026-10-30 18:09:56 +08:00
add namespace billinghistory query for costcenter (#3902)
* add namespace billinghistory query for costcenter
This commit is contained in:
@@ -83,4 +83,13 @@ resources:
|
||||
kind: Transfer
|
||||
path: github.com/labring/sealos/controllers/account/api/v1
|
||||
version: v1
|
||||
- api:
|
||||
crdVersion: v1
|
||||
namespaced: true
|
||||
controller: true
|
||||
domain: sealos.io
|
||||
group: account
|
||||
kind: NamespaceBillingHistory
|
||||
path: github.com/labring/sealos/controllers/account/api/v1
|
||||
version: v1
|
||||
version: "3"
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
Copyright 2023.
|
||||
|
||||
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 v1
|
||||
|
||||
import (
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
)
|
||||
|
||||
// EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN!
|
||||
// NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized.
|
||||
|
||||
// NamespaceBillingHistorySpec defines the desired state of NamespaceBillingHistory
|
||||
type NamespaceBillingHistorySpec struct {
|
||||
StartTime metav1.Time `json:"startTime,omitempty"`
|
||||
EndTime metav1.Time `json:"endTime,omitempty"`
|
||||
Type Type `json:"type"`
|
||||
}
|
||||
|
||||
// NamespaceBillingHistoryStatus defines the observed state of NamespaceBillingHistory
|
||||
type NamespaceBillingHistoryStatus struct {
|
||||
// INSERT ADDITIONAL STATUS FIELD - define observed state of cluster
|
||||
// Important: Run "make" to regenerate code after modifying this file
|
||||
NamespaceList []string `json:"namespaceList,omitempty"`
|
||||
Status Status `json:"status,omitempty"`
|
||||
Detail string `json:"detail,omitempty"`
|
||||
}
|
||||
|
||||
//+kubebuilder:object:root=true
|
||||
//+kubebuilder:subresource:status
|
||||
|
||||
// NamespaceBillingHistory is the Schema for the namespacebillinghistories API
|
||||
type NamespaceBillingHistory struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
metav1.ObjectMeta `json:"metadata,omitempty"`
|
||||
|
||||
Spec NamespaceBillingHistorySpec `json:"spec,omitempty"`
|
||||
Status NamespaceBillingHistoryStatus `json:"status,omitempty"`
|
||||
}
|
||||
|
||||
//+kubebuilder:object:root=true
|
||||
|
||||
// NamespaceBillingHistoryList contains a list of NamespaceBillingHistory
|
||||
type NamespaceBillingHistoryList struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
metav1.ListMeta `json:"metadata,omitempty"`
|
||||
Items []NamespaceBillingHistory `json:"items"`
|
||||
}
|
||||
|
||||
func init() {
|
||||
SchemeBuilder.Register(&NamespaceBillingHistory{}, &NamespaceBillingHistoryList{})
|
||||
}
|
||||
@@ -199,6 +199,16 @@ func (in *AccountSpec) DeepCopy() *AccountSpec {
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *AccountStatus) DeepCopyInto(out *AccountStatus) {
|
||||
*out = *in
|
||||
if in.EncryptBalance != nil {
|
||||
in, out := &in.EncryptBalance, &out.EncryptBalance
|
||||
*out = new(string)
|
||||
**out = **in
|
||||
}
|
||||
if in.EncryptDeductionBalance != nil {
|
||||
in, out := &in.EncryptDeductionBalance, &out.EncryptDeductionBalance
|
||||
*out = new(string)
|
||||
**out = **in
|
||||
}
|
||||
if in.ChargeList != nil {
|
||||
in, out := &in.ChargeList, &out.ChargeList
|
||||
*out = make([]Charge, len(*in))
|
||||
@@ -464,6 +474,95 @@ func (in *DebtStatus) DeepCopy() *DebtStatus {
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *NamespaceBillingHistory) DeepCopyInto(out *NamespaceBillingHistory) {
|
||||
*out = *in
|
||||
out.TypeMeta = in.TypeMeta
|
||||
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
|
||||
out.Spec = in.Spec
|
||||
out.Status = in.Status
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NamespaceBillingHistory.
|
||||
func (in *NamespaceBillingHistory) DeepCopy() *NamespaceBillingHistory {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(NamespaceBillingHistory)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||
func (in *NamespaceBillingHistory) DeepCopyObject() runtime.Object {
|
||||
if c := in.DeepCopy(); c != nil {
|
||||
return c
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *NamespaceBillingHistoryList) DeepCopyInto(out *NamespaceBillingHistoryList) {
|
||||
*out = *in
|
||||
out.TypeMeta = in.TypeMeta
|
||||
in.ListMeta.DeepCopyInto(&out.ListMeta)
|
||||
if in.Items != nil {
|
||||
in, out := &in.Items, &out.Items
|
||||
*out = make([]NamespaceBillingHistory, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NamespaceBillingHistoryList.
|
||||
func (in *NamespaceBillingHistoryList) DeepCopy() *NamespaceBillingHistoryList {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(NamespaceBillingHistoryList)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||
func (in *NamespaceBillingHistoryList) DeepCopyObject() runtime.Object {
|
||||
if c := in.DeepCopy(); c != nil {
|
||||
return c
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *NamespaceBillingHistorySpec) DeepCopyInto(out *NamespaceBillingHistorySpec) {
|
||||
*out = *in
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NamespaceBillingHistorySpec.
|
||||
func (in *NamespaceBillingHistorySpec) DeepCopy() *NamespaceBillingHistorySpec {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(NamespaceBillingHistorySpec)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *NamespaceBillingHistoryStatus) DeepCopyInto(out *NamespaceBillingHistoryStatus) {
|
||||
*out = *in
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NamespaceBillingHistoryStatus.
|
||||
func (in *NamespaceBillingHistoryStatus) DeepCopy() *NamespaceBillingHistoryStatus {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(NamespaceBillingHistoryStatus)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *Payment) DeepCopyInto(out *Payment) {
|
||||
*out = *in
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
---
|
||||
apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
annotations:
|
||||
controller-gen.kubebuilder.io/version: v0.8.0
|
||||
creationTimestamp: null
|
||||
name: namespacebillinghistories.account.sealos.io
|
||||
spec:
|
||||
group: account.sealos.io
|
||||
names:
|
||||
kind: NamespaceBillingHistory
|
||||
listKind: NamespaceBillingHistoryList
|
||||
plural: namespacebillinghistories
|
||||
singular: namespacebillinghistory
|
||||
scope: Namespaced
|
||||
versions:
|
||||
- name: v1
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
description: NamespaceBillingHistory is the Schema for the namespacebillinghistories
|
||||
API
|
||||
properties:
|
||||
apiVersion:
|
||||
description: 'APIVersion defines the versioned schema of this representation
|
||||
of an object. Servers should convert recognized schemas to the latest
|
||||
internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
|
||||
type: string
|
||||
kind:
|
||||
description: 'Kind is a string value representing the REST resource this
|
||||
object represents. Servers may infer this from the endpoint the client
|
||||
submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
|
||||
type: string
|
||||
metadata:
|
||||
type: object
|
||||
spec:
|
||||
description: NamespaceBillingHistorySpec defines the desired state of
|
||||
NamespaceBillingHistory
|
||||
properties:
|
||||
endTime:
|
||||
format: date-time
|
||||
type: string
|
||||
startTime:
|
||||
format: date-time
|
||||
type: string
|
||||
type:
|
||||
type: integer
|
||||
required:
|
||||
- type
|
||||
type: object
|
||||
status:
|
||||
description: NamespaceBillingHistoryStatus defines the observed state
|
||||
of NamespaceBillingHistory
|
||||
properties:
|
||||
detail:
|
||||
type: string
|
||||
namespaceList:
|
||||
description: 'INSERT ADDITIONAL STATUS FIELD - define observed state
|
||||
of cluster Important: Run "make" to regenerate code after modifying
|
||||
this file'
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
status:
|
||||
type: string
|
||||
type: object
|
||||
type: object
|
||||
served: true
|
||||
storage: true
|
||||
subresources:
|
||||
status: {}
|
||||
status:
|
||||
acceptedNames:
|
||||
kind: ""
|
||||
plural: ""
|
||||
conditions: []
|
||||
storedVersions: []
|
||||
@@ -9,6 +9,7 @@ resources:
|
||||
- bases/account.sealos.io_billingrecordqueries.yaml
|
||||
- bases/account.sealos.io_pricequeries.yaml
|
||||
- bases/account.sealos.io_transfers.yaml
|
||||
- bases/account.sealos.io_namespacebillinghistories.yaml
|
||||
#+kubebuilder:scaffold:crdkustomizeresource
|
||||
|
||||
patchesStrategicMerge:
|
||||
@@ -21,6 +22,7 @@ patchesStrategicMerge:
|
||||
#- patches/webhook_in_billingrecordqueries.yaml
|
||||
#- patches/webhook_in_pricequeries.yaml
|
||||
#- patches/webhook_in_transfers.yaml
|
||||
#- patches/webhook_in_namespacebillinghistories.yaml
|
||||
#+kubebuilder:scaffold:crdkustomizewebhookpatch
|
||||
|
||||
# [CERTMANAGER] To enable cert-manager, uncomment all the sections with [CERTMANAGER] prefix.
|
||||
@@ -32,6 +34,7 @@ patchesStrategicMerge:
|
||||
#- patches/cainjection_in_billingrecordqueries.yaml
|
||||
#- patches/cainjection_in_pricequeries.yaml
|
||||
#- patches/cainjection_in_transfers.yaml
|
||||
#- patches/cainjection_in_namespacebillinghistories.yaml
|
||||
#+kubebuilder:scaffold:crdkustomizecainjectionpatch
|
||||
|
||||
# the following config is for teaching kustomize how to do kustomization for CRDs.
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
# The following patch adds a directive for certmanager to inject CA into the CRD
|
||||
apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
annotations:
|
||||
cert-manager.io/inject-ca-from: $(CERTIFICATE_NAMESPACE)/$(CERTIFICATE_NAME)
|
||||
name: namespacebillinghistories.account.sealos.io
|
||||
@@ -0,0 +1,16 @@
|
||||
# The following patch enables a conversion webhook for the CRD
|
||||
apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
name: namespacebillinghistories.account.sealos.io
|
||||
spec:
|
||||
conversion:
|
||||
strategy: Webhook
|
||||
webhook:
|
||||
clientConfig:
|
||||
service:
|
||||
namespace: system
|
||||
name: webhook-service
|
||||
path: /convert
|
||||
conversionReviewVersions:
|
||||
- v1
|
||||
@@ -0,0 +1,24 @@
|
||||
# permissions for end users to edit namespacebillinghistories.
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRole
|
||||
metadata:
|
||||
name: namespacebillinghistory-editor-role
|
||||
rules:
|
||||
- apiGroups:
|
||||
- account.sealos.io
|
||||
resources:
|
||||
- namespacebillinghistories
|
||||
verbs:
|
||||
- create
|
||||
- delete
|
||||
- get
|
||||
- list
|
||||
- patch
|
||||
- update
|
||||
- watch
|
||||
- apiGroups:
|
||||
- account.sealos.io
|
||||
resources:
|
||||
- namespacebillinghistories/status
|
||||
verbs:
|
||||
- get
|
||||
@@ -0,0 +1,20 @@
|
||||
# permissions for end users to view namespacebillinghistories.
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRole
|
||||
metadata:
|
||||
name: namespacebillinghistory-viewer-role
|
||||
rules:
|
||||
- apiGroups:
|
||||
- account.sealos.io
|
||||
resources:
|
||||
- namespacebillinghistories
|
||||
verbs:
|
||||
- get
|
||||
- list
|
||||
- watch
|
||||
- apiGroups:
|
||||
- account.sealos.io
|
||||
resources:
|
||||
- namespacebillinghistories/status
|
||||
verbs:
|
||||
- get
|
||||
@@ -125,6 +125,32 @@ rules:
|
||||
- get
|
||||
- patch
|
||||
- update
|
||||
- apiGroups:
|
||||
- account.sealos.io
|
||||
resources:
|
||||
- namespacebillinghistories
|
||||
verbs:
|
||||
- create
|
||||
- delete
|
||||
- get
|
||||
- list
|
||||
- patch
|
||||
- update
|
||||
- watch
|
||||
- apiGroups:
|
||||
- account.sealos.io
|
||||
resources:
|
||||
- namespacebillinghistories/finalizers
|
||||
verbs:
|
||||
- update
|
||||
- apiGroups:
|
||||
- account.sealos.io
|
||||
resources:
|
||||
- namespacebillinghistories/status
|
||||
verbs:
|
||||
- get
|
||||
- patch
|
||||
- update
|
||||
- apiGroups:
|
||||
- account.sealos.io
|
||||
resources:
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
apiVersion: account.sealos.io/v1
|
||||
kind: NamespaceBillingHistory
|
||||
metadata:
|
||||
name: namespacebillinghistory-sample
|
||||
spec:
|
||||
# TODO(user): Add fields here
|
||||
@@ -12,7 +12,6 @@ webhooks:
|
||||
name: webhook-service
|
||||
namespace: system
|
||||
path: /validate-v1-sealos-cloud
|
||||
timeoutSeconds: 10
|
||||
failurePolicy: Ignore
|
||||
name: debt.sealos.io
|
||||
rules:
|
||||
|
||||
@@ -0,0 +1,119 @@
|
||||
/*
|
||||
Copyright 2023.
|
||||
|
||||
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"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
userv1 "github.com/labring/sealos/controllers/user/api/v1"
|
||||
|
||||
"github.com/go-logr/logr"
|
||||
"github.com/labring/sealos/controllers/pkg/database"
|
||||
"sigs.k8s.io/controller-runtime/pkg/log"
|
||||
|
||||
accountv1 "github.com/labring/sealos/controllers/account/api/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
ctrl "sigs.k8s.io/controller-runtime"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
)
|
||||
|
||||
// NamespaceBillingHistoryReconciler reconciles a NamespaceBillingHistory object
|
||||
type NamespaceBillingHistoryReconciler struct {
|
||||
client.Client
|
||||
Scheme *runtime.Scheme
|
||||
Logger logr.Logger
|
||||
MongoDBURI string
|
||||
}
|
||||
|
||||
//+kubebuilder:rbac:groups=account.sealos.io,resources=namespacebillinghistories,verbs=get;list;watch;create;update;patch;delete
|
||||
//+kubebuilder:rbac:groups=account.sealos.io,resources=namespacebillinghistories/status,verbs=get;update;patch
|
||||
//+kubebuilder:rbac:groups=account.sealos.io,resources=namespacebillinghistories/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 NamespaceBillingHistory 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.11.2/pkg/reconcile
|
||||
func (r *NamespaceBillingHistoryReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
|
||||
dbCtx := context.Background()
|
||||
dbClient, err := database.NewMongoDB(dbCtx, r.MongoDBURI)
|
||||
if err != nil {
|
||||
r.Logger.Error(err, "connect mongo client failed")
|
||||
return ctrl.Result{Requeue: true}, err
|
||||
}
|
||||
defer func() {
|
||||
err := dbClient.Disconnect(ctx)
|
||||
if err != nil {
|
||||
r.Logger.V(5).Info("disconnect mongo client failed", "err", err)
|
||||
}
|
||||
}()
|
||||
|
||||
nsHistory := &accountv1.NamespaceBillingHistory{}
|
||||
err = r.Get(ctx, req.NamespacedName, nsHistory)
|
||||
if err == nil {
|
||||
// delete after 3 minutes
|
||||
if time.Since(nsHistory.CreationTimestamp.Time) > 3*time.Minute {
|
||||
return ctrl.Result{}, r.Delete(ctx, nsHistory)
|
||||
}
|
||||
if err = r.reconcile(ctx, req, dbClient, nsHistory); err != nil {
|
||||
r.Logger.Error(err, "reconcile failed")
|
||||
nsHistory.Status.Status = accountv1.Failed
|
||||
}
|
||||
if err = r.Status().Update(ctx, nsHistory); err == nil {
|
||||
// return after 4 minutes
|
||||
return ctrl.Result{RequeueAfter: 4 * time.Minute}, nil
|
||||
}
|
||||
}
|
||||
|
||||
return ctrl.Result{}, client.IgnoreNotFound(err)
|
||||
}
|
||||
|
||||
func (r *NamespaceBillingHistoryReconciler) reconcile(ctx context.Context, req ctrl.Request, dbClient database.Interface, nsHistory *accountv1.NamespaceBillingHistory) error {
|
||||
user := &userv1.User{}
|
||||
if err := r.Get(ctx, client.ObjectKey{Namespace: req.Namespace, Name: getUsername(req.Namespace)}, user); err != nil {
|
||||
return fmt.Errorf("get user failed: %w", err)
|
||||
}
|
||||
owner, ok := user.GetAnnotations()[userv1.UserAnnotationOwnerKey]
|
||||
if !ok {
|
||||
return fmt.Errorf("user %s has no annotations %s", user.Name, userv1.UserLabelOwnerKey)
|
||||
}
|
||||
nsList, err := dbClient.GetBillingHistoryNamespaceList(&nsHistory.Spec, owner)
|
||||
if err != nil {
|
||||
return fmt.Errorf("get billing history namespace list failed: %w", err)
|
||||
}
|
||||
nsHistory.Status.NamespaceList = nsList
|
||||
nsHistory.Status.Status = accountv1.Completed
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetupWithManager sets up the controller with the Manager.
|
||||
func (r *NamespaceBillingHistoryReconciler) SetupWithManager(mgr ctrl.Manager) error {
|
||||
if r.MongoDBURI = os.Getenv(database.MongoURI); r.MongoDBURI == "" {
|
||||
return fmt.Errorf("env %s is empty", database.MongoURI)
|
||||
}
|
||||
r.Logger = log.Log.WithName("namespacebillinghistories-controller")
|
||||
return ctrl.NewControllerManagedBy(mgr).
|
||||
For(&accountv1.NamespaceBillingHistory{}).
|
||||
Complete(r)
|
||||
}
|
||||
@@ -388,6 +388,83 @@ status:
|
||||
---
|
||||
apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
annotations:
|
||||
controller-gen.kubebuilder.io/version: v0.8.0
|
||||
creationTimestamp: null
|
||||
name: namespacebillinghistories.account.sealos.io
|
||||
spec:
|
||||
group: account.sealos.io
|
||||
names:
|
||||
kind: NamespaceBillingHistory
|
||||
listKind: NamespaceBillingHistoryList
|
||||
plural: namespacebillinghistories
|
||||
singular: namespacebillinghistory
|
||||
scope: Namespaced
|
||||
versions:
|
||||
- name: v1
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
description: NamespaceBillingHistory is the Schema for the namespacebillinghistories
|
||||
API
|
||||
properties:
|
||||
apiVersion:
|
||||
description: 'APIVersion defines the versioned schema of this representation
|
||||
of an object. Servers should convert recognized schemas to the latest
|
||||
internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
|
||||
type: string
|
||||
kind:
|
||||
description: 'Kind is a string value representing the REST resource this
|
||||
object represents. Servers may infer this from the endpoint the client
|
||||
submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
|
||||
type: string
|
||||
metadata:
|
||||
type: object
|
||||
spec:
|
||||
description: NamespaceBillingHistorySpec defines the desired state of
|
||||
NamespaceBillingHistory
|
||||
properties:
|
||||
endTime:
|
||||
format: date-time
|
||||
type: string
|
||||
startTime:
|
||||
format: date-time
|
||||
type: string
|
||||
type:
|
||||
type: integer
|
||||
required:
|
||||
- type
|
||||
type: object
|
||||
status:
|
||||
description: NamespaceBillingHistoryStatus defines the observed state
|
||||
of NamespaceBillingHistory
|
||||
properties:
|
||||
detail:
|
||||
type: string
|
||||
namespaceList:
|
||||
description: 'INSERT ADDITIONAL STATUS FIELD - define observed state
|
||||
of cluster Important: Run "make" to regenerate code after modifying
|
||||
this file'
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
status:
|
||||
type: string
|
||||
type: object
|
||||
type: object
|
||||
served: true
|
||||
storage: true
|
||||
subresources:
|
||||
status: {}
|
||||
status:
|
||||
acceptedNames:
|
||||
kind: ""
|
||||
plural: ""
|
||||
conditions: []
|
||||
storedVersions: []
|
||||
---
|
||||
apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
annotations:
|
||||
controller-gen.kubebuilder.io/version: v0.8.0
|
||||
@@ -765,6 +842,32 @@ rules:
|
||||
- get
|
||||
- patch
|
||||
- update
|
||||
- apiGroups:
|
||||
- account.sealos.io
|
||||
resources:
|
||||
- namespacebillinghistories
|
||||
verbs:
|
||||
- create
|
||||
- delete
|
||||
- get
|
||||
- list
|
||||
- patch
|
||||
- update
|
||||
- watch
|
||||
- apiGroups:
|
||||
- account.sealos.io
|
||||
resources:
|
||||
- namespacebillinghistories/finalizers
|
||||
verbs:
|
||||
- update
|
||||
- apiGroups:
|
||||
- account.sealos.io
|
||||
resources:
|
||||
- namespacebillinghistories/status
|
||||
verbs:
|
||||
- get
|
||||
- patch
|
||||
- update
|
||||
- apiGroups:
|
||||
- account.sealos.io
|
||||
resources:
|
||||
|
||||
@@ -46,8 +46,9 @@ import (
|
||||
"sigs.k8s.io/controller-runtime/pkg/healthz"
|
||||
"sigs.k8s.io/controller-runtime/pkg/log/zap"
|
||||
|
||||
accountv1 "github.com/labring/sealos/controllers/account/api/v1"
|
||||
userv1 "github.com/labring/sealos/controllers/user/api/v1"
|
||||
|
||||
accountv1 "github.com/labring/sealos/controllers/account/api/v1"
|
||||
//+kubebuilder:scaffold:imports
|
||||
)
|
||||
|
||||
@@ -190,6 +191,13 @@ func main() {
|
||||
setupLog.Error(err, "unable to create controller", "controller", "Transfer")
|
||||
os.Exit(1)
|
||||
}
|
||||
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)
|
||||
}
|
||||
//+kubebuilder:scaffold:builder
|
||||
|
||||
if err := mgr.AddHealthzCheck("healthz", healthz.Ping); err != nil {
|
||||
|
||||
@@ -26,6 +26,7 @@ type Interface interface {
|
||||
//InitDB() error
|
||||
GetMeteringOwnerTimeResult(queryTime time.Time, queryCategories, queryProperties []string) (*MeteringOwnerTimeResult, error)
|
||||
GetBillingLastUpdateTime(owner string, _type accountv1.Type) (bool, time.Time, error)
|
||||
GetBillingHistoryNamespaceList(ns *accountv1.NamespaceBillingHistorySpec, owner string) ([]string, error)
|
||||
SaveBillingsWithAccountBalance(accountBalanceSpec *accountv1.AccountBalanceSpec) error
|
||||
QueryBillingRecords(billingRecordQuery *accountv1.BillingRecordQuery, owner string) error
|
||||
GetUpdateTimeForCategoryAndPropertyFromMetering(category string, property string) (time.Time, error)
|
||||
|
||||
@@ -100,6 +100,44 @@ func (m *MongoDB) GetBillingLastUpdateTime(owner string, _type accountv1.Type) (
|
||||
return false, time.Time{}, fmt.Errorf("failed to convert time field to primitive.DateTime: %v", result["time"])
|
||||
}
|
||||
|
||||
func (m *MongoDB) GetBillingHistoryNamespaceList(nsHistorySpec *accountv1.NamespaceBillingHistorySpec, owner string) ([]string, error) {
|
||||
filter := bson.M{
|
||||
"owner": owner,
|
||||
}
|
||||
if nsHistorySpec.StartTime != nsHistorySpec.EndTime {
|
||||
filter["time"] = bson.M{
|
||||
"$gte": nsHistorySpec.StartTime.Time.UTC(),
|
||||
"$lte": nsHistorySpec.EndTime.Time.UTC(),
|
||||
}
|
||||
}
|
||||
if nsHistorySpec.Type != -1 {
|
||||
filter["type"] = nsHistorySpec.Type
|
||||
}
|
||||
|
||||
pipeline := mongo.Pipeline{
|
||||
{{"$match", filter}},
|
||||
{{"$group", bson.D{{"_id", nil}, {"namespaces", bson.D{{"$addToSet", "$namespace"}}}}}},
|
||||
}
|
||||
|
||||
cur, err := m.getBillingCollection().Aggregate(context.Background(), pipeline)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer cur.Close(context.Background())
|
||||
|
||||
if !cur.Next(context.Background()) {
|
||||
return []string{}, nil
|
||||
}
|
||||
|
||||
var result struct {
|
||||
Namespaces []string `bson:"namespaces"`
|
||||
}
|
||||
if err := cur.Decode(&result); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return result.Namespaces, nil
|
||||
}
|
||||
|
||||
func (m *MongoDB) SaveBillingsWithAccountBalance(accountBalanceSpec *accountv1.AccountBalanceSpec) error {
|
||||
accountBalanceDoc := AccountBalanceSpecBSON{
|
||||
Time: accountBalanceSpec.Time.Time.UTC(),
|
||||
|
||||
@@ -417,3 +417,27 @@ func TestMongoDB_DropMonitorCollectionsOlderThan(t *testing.T) {
|
||||
t.Fatalf("failed to drop monitor collections older than 30 days: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMongoDB_GetBillingHistoryNamespaceList(t *testing.T) {
|
||||
dbCTX := context.Background()
|
||||
m, err := NewMongoDB(dbCTX, os.Getenv("MONGODB_URI"))
|
||||
if err != nil {
|
||||
t.Errorf("failed to connect mongo: error = %v", err)
|
||||
}
|
||||
defer func() {
|
||||
if err = m.Disconnect(dbCTX); err != nil {
|
||||
t.Errorf("failed to disconnect mongo: error = %v", err)
|
||||
}
|
||||
}()
|
||||
queryTime := time.Now().UTC()
|
||||
billRecord := &accountv1.NamespaceBillingHistorySpec{
|
||||
StartTime: metav1.Time{Time: queryTime.Add(-time.Hour * 24 * 30)},
|
||||
EndTime: metav1.Time{Time: queryTime},
|
||||
Type: -1,
|
||||
}
|
||||
namespaceList, err := m.GetBillingHistoryNamespaceList(billRecord, "")
|
||||
if err != nil {
|
||||
t.Fatalf("failed to get billing history namespace list: %v", err)
|
||||
}
|
||||
t.Logf("namespaceList: %v", namespaceList)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user