From abf3b93806f94e0e952431dc8037d6259d38ed79 Mon Sep 17 00:00:00 2001 From: Powerfool Date: Thu, 21 Mar 2024 16:44:53 +0800 Subject: [PATCH] Some optimizations for dashboard handlers (#251) --- internal/assets/metric_zh_CN.yaml | 1 + internal/{oceanbase => clients}/clients.go | 4 +- .../{oceanbase => clients}/clients_test.go | 2 +- internal/{oceanbase => clients}/obcluster.go | 5 +- internal/{oceanbase => clients}/obtenant.go | 4 +- .../oceanbase_suite_test.go | 2 +- .../schema/groupversion.go | 0 .../schema/obcluster.go | 0 .../schema/obresourcerescue.go | 0 .../{oceanbase => clients}/schema/observer.go | 0 .../{oceanbase => clients}/schema/obtenant.go | 0 .../schema/obtenantbackup.go | 0 .../schema/obtenantbackuppolicy.go | 0 .../schema/obtenantoperation.go | 0 .../{oceanbase => clients}/schema/obzone.go | 0 internal/dashboard/business/k8s/k8s.go | 17 +++--- internal/dashboard/business/metric/metric.go | 35 +++++++++++- .../dashboard/business/oceanbase/obcluster.go | 37 ++++++------ .../business/oceanbase/obcluster_usage.go | 8 +-- .../dashboard/business/oceanbase/obtenant.go | 38 ++++++------- .../business/oceanbase/obtenant_pool.go | 16 +++--- .../business/oceanbase/obtenantbackup.go | 56 ++++++++++++++----- .../dashboard/generated/bindata/bindata.go | 20 +++---- internal/dashboard/generated/swagger/docs.go | 21 ++++--- .../dashboard/generated/swagger/swagger.json | 21 ++++--- .../dashboard/generated/swagger/swagger.yaml | 19 +++++-- internal/dashboard/handler/info_handler.go | 15 ++--- internal/dashboard/handler/k8s_handler.go | 8 ++- internal/dashboard/handler/metric_handler.go | 4 ++ .../dashboard/handler/obcluster_handler.go | 22 ++++++-- .../dashboard/handler/obtenant_handler.go | 25 ++++++++- internal/dashboard/middleware/logging.go | 6 +- internal/dashboard/model/response/backup.go | 7 ++- internal/dashboard/model/response/k8s.go | 18 +++--- .../dashboard/router/v1/obcluster_router.go | 2 +- ui/README.md | 3 - 36 files changed, 270 insertions(+), 146 deletions(-) rename internal/{oceanbase => clients}/clients.go (95%) rename internal/{oceanbase => clients}/clients_test.go (99%) rename internal/{oceanbase => clients}/obcluster.go (97%) rename internal/{oceanbase => clients}/obtenant.go (97%) rename internal/{oceanbase => clients}/oceanbase_suite_test.go (96%) rename internal/{oceanbase => clients}/schema/groupversion.go (100%) rename internal/{oceanbase => clients}/schema/obcluster.go (100%) rename internal/{oceanbase => clients}/schema/obresourcerescue.go (100%) rename internal/{oceanbase => clients}/schema/observer.go (100%) rename internal/{oceanbase => clients}/schema/obtenant.go (100%) rename internal/{oceanbase => clients}/schema/obtenantbackup.go (100%) rename internal/{oceanbase => clients}/schema/obtenantbackuppolicy.go (100%) rename internal/{oceanbase => clients}/schema/obtenantoperation.go (100%) rename internal/{oceanbase => clients}/schema/obzone.go (100%) delete mode 100644 ui/README.md diff --git a/internal/assets/metric_zh_CN.yaml b/internal/assets/metric_zh_CN.yaml index 0d717f9d8..c554ad0da 100644 --- a/internal/assets/metric_zh_CN.yaml +++ b/internal/assets/metric_zh_CN.yaml @@ -648,6 +648,7 @@ OBTENANT: name: "\u5B58\u50A8\u4E0E\u7F13\u5B58" OBCLUSTER_OVERVIEW: - description: Cluster Overview + name: "\u96c6\u7fa4\u6027\u80fd\u6982\u89c8" metricGroups: - description: "\u5E73\u5747\u6BCF\u79D2\u5904\u7406 SQL \u8BED\u53E5\u6570" metrics: diff --git a/internal/oceanbase/clients.go b/internal/clients/clients.go similarity index 95% rename from internal/oceanbase/clients.go rename to internal/clients/clients.go index 6a9d0620b..ca621a36a 100644 --- a/internal/oceanbase/clients.go +++ b/internal/clients/clients.go @@ -10,11 +10,11 @@ MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. See the Mulan PSL v2 for more details. */ -package oceanbase +package clients import ( "github.com/oceanbase/ob-operator/api/v1alpha1" - "github.com/oceanbase/ob-operator/internal/oceanbase/schema" + "github.com/oceanbase/ob-operator/internal/clients/schema" "github.com/oceanbase/ob-operator/pkg/k8s/client" ) diff --git a/internal/oceanbase/clients_test.go b/internal/clients/clients_test.go similarity index 99% rename from internal/oceanbase/clients_test.go rename to internal/clients/clients_test.go index 26ea6ef9c..02da4c9af 100644 --- a/internal/oceanbase/clients_test.go +++ b/internal/clients/clients_test.go @@ -10,7 +10,7 @@ MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. See the Mulan PSL v2 for more details. */ -package oceanbase +package clients import ( "context" diff --git a/internal/oceanbase/obcluster.go b/internal/clients/obcluster.go similarity index 97% rename from internal/oceanbase/obcluster.go rename to internal/clients/obcluster.go index a977c3d6b..70c219896 100644 --- a/internal/oceanbase/obcluster.go +++ b/internal/clients/obcluster.go @@ -10,7 +10,7 @@ MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. See the Mulan PSL v2 for more details. */ -package oceanbase +package clients import ( "context" @@ -24,8 +24,8 @@ import ( "k8s.io/apimachinery/pkg/runtime" "github.com/oceanbase/ob-operator/api/v1alpha1" + "github.com/oceanbase/ob-operator/internal/clients/schema" oceanbaseconst "github.com/oceanbase/ob-operator/internal/const/oceanbase" - "github.com/oceanbase/ob-operator/internal/oceanbase/schema" "github.com/oceanbase/ob-operator/pkg/k8s/client" ) @@ -156,7 +156,6 @@ func ListOBZonesOfOBCluster(ctx context.Context, obcluster *v1alpha1.OBCluster) func ListOBServersOfOBZone(ctx context.Context, obzone *v1alpha1.OBZone) (*v1alpha1.OBServerList, error) { client := client.GetClient() var observerList v1alpha1.OBServerList - logger.Infof("get observer list of obzone %s", obzone.Name) obj, err := client.DynamicClient.Resource(schema.OBServerRes).Namespace(obzone.Namespace).List(ctx, metav1.ListOptions{ LabelSelector: fmt.Sprintf("%s=%s", oceanbaseconst.LabelRefOBZone, obzone.Name), }) diff --git a/internal/oceanbase/obtenant.go b/internal/clients/obtenant.go similarity index 97% rename from internal/oceanbase/obtenant.go rename to internal/clients/obtenant.go index 3dd490a9e..8473fab72 100644 --- a/internal/oceanbase/obtenant.go +++ b/internal/clients/obtenant.go @@ -10,7 +10,7 @@ MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. See the Mulan PSL v2 for more details. */ -package oceanbase +package clients import ( "context" @@ -20,8 +20,8 @@ import ( "k8s.io/apimachinery/pkg/types" "github.com/oceanbase/ob-operator/api/v1alpha1" + "github.com/oceanbase/ob-operator/internal/clients/schema" oceanbaseconst "github.com/oceanbase/ob-operator/internal/const/oceanbase" - "github.com/oceanbase/ob-operator/internal/oceanbase/schema" ) func CreateOBTenant(ctx context.Context, tenant *v1alpha1.OBTenant) (*v1alpha1.OBTenant, error) { diff --git a/internal/oceanbase/oceanbase_suite_test.go b/internal/clients/oceanbase_suite_test.go similarity index 96% rename from internal/oceanbase/oceanbase_suite_test.go rename to internal/clients/oceanbase_suite_test.go index 97bde804b..64ac22a3b 100644 --- a/internal/oceanbase/oceanbase_suite_test.go +++ b/internal/clients/oceanbase_suite_test.go @@ -10,7 +10,7 @@ MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. See the Mulan PSL v2 for more details. */ -package oceanbase_test +package clients import ( "testing" diff --git a/internal/oceanbase/schema/groupversion.go b/internal/clients/schema/groupversion.go similarity index 100% rename from internal/oceanbase/schema/groupversion.go rename to internal/clients/schema/groupversion.go diff --git a/internal/oceanbase/schema/obcluster.go b/internal/clients/schema/obcluster.go similarity index 100% rename from internal/oceanbase/schema/obcluster.go rename to internal/clients/schema/obcluster.go diff --git a/internal/oceanbase/schema/obresourcerescue.go b/internal/clients/schema/obresourcerescue.go similarity index 100% rename from internal/oceanbase/schema/obresourcerescue.go rename to internal/clients/schema/obresourcerescue.go diff --git a/internal/oceanbase/schema/observer.go b/internal/clients/schema/observer.go similarity index 100% rename from internal/oceanbase/schema/observer.go rename to internal/clients/schema/observer.go diff --git a/internal/oceanbase/schema/obtenant.go b/internal/clients/schema/obtenant.go similarity index 100% rename from internal/oceanbase/schema/obtenant.go rename to internal/clients/schema/obtenant.go diff --git a/internal/oceanbase/schema/obtenantbackup.go b/internal/clients/schema/obtenantbackup.go similarity index 100% rename from internal/oceanbase/schema/obtenantbackup.go rename to internal/clients/schema/obtenantbackup.go diff --git a/internal/oceanbase/schema/obtenantbackuppolicy.go b/internal/clients/schema/obtenantbackuppolicy.go similarity index 100% rename from internal/oceanbase/schema/obtenantbackuppolicy.go rename to internal/clients/schema/obtenantbackuppolicy.go diff --git a/internal/oceanbase/schema/obtenantoperation.go b/internal/clients/schema/obtenantoperation.go similarity index 100% rename from internal/oceanbase/schema/obtenantoperation.go rename to internal/clients/schema/obtenantoperation.go diff --git a/internal/oceanbase/schema/obzone.go b/internal/clients/schema/obzone.go similarity index 100% rename from internal/oceanbase/schema/obzone.go rename to internal/clients/schema/obzone.go diff --git a/internal/dashboard/business/k8s/k8s.go b/internal/dashboard/business/k8s/k8s.go index 5fe5ab05e..c71542e24 100644 --- a/internal/dashboard/business/k8s/k8s.go +++ b/internal/dashboard/business/k8s/k8s.go @@ -17,16 +17,15 @@ import ( "strings" logger "github.com/sirupsen/logrus" + corev1 "k8s.io/api/core/v1" + storagev1 "k8s.io/api/storage/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "github.com/oceanbase/ob-operator/internal/dashboard/business/common" "github.com/oceanbase/ob-operator/internal/dashboard/business/constant" "github.com/oceanbase/ob-operator/internal/dashboard/model/param" "github.com/oceanbase/ob-operator/internal/dashboard/model/response" "github.com/oceanbase/ob-operator/pkg/k8s/resource" - - corev1 "k8s.io/api/core/v1" - storagev1 "k8s.io/api/storage/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) const ( @@ -147,6 +146,8 @@ func ListEvents(queryEventParam *param.QueryEventParam) ([]response.K8sEvent, er kind = "OBCluster" case "OBTENANT": kind = "OBTenant" + case "OBBACKUPPOLICY": + kind = "OBTenantBackupPolicy" default: kind = queryEventParam.ObjectType } @@ -170,15 +171,15 @@ func ListEvents(queryEventParam *param.QueryEventParam) ([]response.K8sEvent, er listOptions.FieldSelector = strings.Join(selectors, ",") } eventList, err := resource.ListEvents(ns, listOptions) - logger.Infof("query events with param: %v", queryEventParam) + logger.Infof("Query events with param: %+v", queryEventParam) if err == nil { for _, event := range eventList.Items { events = append(events, response.K8sEvent{ Namespace: event.Namespace, Type: event.Type, Count: event.Count, - FirstOccur: float64(event.FirstTimestamp.UnixMilli()) / 1000, - LastSeen: float64(event.LastTimestamp.UnixMilli()) / 1000, + FirstOccur: event.FirstTimestamp.Unix(), + LastSeen: event.LastTimestamp.Unix(), Reason: event.Reason, Message: event.Message, Object: fmt.Sprintf("%s/%s", event.InvolvedObject.Kind, event.InvolvedObject.Name), @@ -200,7 +201,7 @@ func ListNodes() ([]response.K8sNode, error) { Roles: extractNodeRoles(&node), Labels: common.MapToKVs(node.Labels), Conditions: extractNodeConditions(&node), - Uptime: float64(node.CreationTimestamp.UnixMilli()) / 1000, + Uptime: node.CreationTimestamp.Unix(), InternalIP: internalAddress, ExternalIP: externalAddress, Version: node.Status.NodeInfo.KubeletVersion, diff --git a/internal/dashboard/business/metric/metric.go b/internal/dashboard/business/metric/metric.go index cf804a5d9..869bb59e3 100644 --- a/internal/dashboard/business/metric/metric.go +++ b/internal/dashboard/business/metric/metric.go @@ -68,6 +68,7 @@ func ListMetricClasses(scope, language string) ([]response.MetricClass, error) { } logger.Debugf("metric configs contents: %s", string(metricConfigContent)) metricConfigMap := make(map[string][]response.MetricClass) + // TODO: Do not unmarshal the file every time, cache the result err = yaml.Unmarshal(metricConfigContent, &metricConfigMap) if err != nil { return metricClasses, err @@ -99,20 +100,52 @@ func extractMetricData(name string, resp *external.PrometheusQueryRangeResponse) Name: name, Labels: bizcommon.MapToKVs(result.Metric), } + lastValid := math.NaN() + invalidTimestamps := make([]float64, 0) + // one loop to handle invalid timestamps interpolation for _, value := range result.Values { t := value[0].(float64) v, err := strconv.ParseFloat(value[1].(string), 64) if err != nil { logger.Warnf("failed to parse value %v", value) + invalidTimestamps = append(invalidTimestamps, t) } else if math.IsNaN(v) { - logger.Debugf("skip NaN value at timestamp %f", t) + logger.Debugf("value at timestamp %f is NaN", t) + invalidTimestamps = append(invalidTimestamps, t) } else { + // if there are invalid timestamps, interpolate them + if len(invalidTimestamps) > 0 { + var interpolated float64 + if math.IsNaN(lastValid) { + interpolated = v + } else { + interpolated = (lastValid + v) / 2 + } + // interpolate invalid slots with last valid value + for _, it := range invalidTimestamps { + values = append(values, response.MetricValue{ + Timestamp: it, + Value: interpolated, + }) + } + invalidTimestamps = invalidTimestamps[:0] + } values = append(values, response.MetricValue{ Timestamp: t, Value: v, }) + lastValid = v } } + if math.IsNaN(lastValid) { + lastValid = 0.0 + } + for _, it := range invalidTimestamps { + values = append(values, response.MetricValue{ + Timestamp: it, + Value: lastValid, + }) + } metricDatas = append(metricDatas, response.MetricData{ Metric: metric, Values: values, diff --git a/internal/dashboard/business/oceanbase/obcluster.go b/internal/dashboard/business/oceanbase/obcluster.go index 23d126ec0..cd33ad7a4 100644 --- a/internal/dashboard/business/oceanbase/obcluster.go +++ b/internal/dashboard/business/oceanbase/obcluster.go @@ -26,6 +26,7 @@ import ( apitypes "github.com/oceanbase/ob-operator/api/types" "github.com/oceanbase/ob-operator/api/v1alpha1" + "github.com/oceanbase/ob-operator/internal/clients" oceanbaseconst "github.com/oceanbase/ob-operator/internal/const/oceanbase" clusterstatus "github.com/oceanbase/ob-operator/internal/const/status/obcluster" "github.com/oceanbase/ob-operator/internal/dashboard/business/common" @@ -33,7 +34,6 @@ import ( modelcommon "github.com/oceanbase/ob-operator/internal/dashboard/model/common" "github.com/oceanbase/ob-operator/internal/dashboard/model/param" "github.com/oceanbase/ob-operator/internal/dashboard/model/response" - "github.com/oceanbase/ob-operator/internal/oceanbase" ) const ( @@ -158,20 +158,19 @@ func buildOBClusterResponse(ctx context.Context, obcluster *v1alpha1.OBCluster) } func buildOBClusterTopologyResp(ctx context.Context, obcluster *v1alpha1.OBCluster) ([]response.OBZone, error) { - obzoneList, err := oceanbase.ListOBZonesOfOBCluster(ctx, obcluster) + obzoneList, err := clients.ListOBZonesOfOBCluster(ctx, obcluster) if err != nil { return nil, errors.Wrapf(err, "List obzone of obcluster %s %s", obcluster.Namespace, obcluster.Name) } topology := make([]response.OBZone, 0, len(obzoneList.Items)) for _, obzone := range obzoneList.Items { observers := make([]response.OBServer, 0) - observerList, err := oceanbase.ListOBServersOfOBZone(ctx, &obzone) + observerList, err := clients.ListOBServersOfOBZone(ctx, &obzone) if err != nil { return nil, errors.Wrapf(err, "List observers of obzone %s %s", obzone.Namespace, obzone.Name) } - logger.Infof("found %d observer", len(observerList.Items)) for _, observer := range observerList.Items { - logger.Infof("add observer %s to result", observer.Name) + logger.Debugf("add observer %s to result", observer.Name) observers = append(observers, response.OBServer{ Namespace: observer.Namespace, Name: observer.Name, @@ -266,7 +265,7 @@ func buildOBClusterTopologyResp(ctx context.Context, obcluster *v1alpha1.OBClust func ListOBClusters(ctx context.Context) ([]response.OBClusterOverview, error) { obclusters := make([]response.OBClusterOverview, 0) - obclusterList, err := oceanbase.ListAllOBClusters(ctx) + obclusterList, err := clients.ListAllOBClusters(ctx) if err != nil { return obclusters, errors.Wrap(err, "failed to list obclusters") } @@ -481,16 +480,16 @@ func generateOBClusterInstance(param *param.CreateOBClusterParam) *v1alpha1.OBCl func CreateOBCluster(ctx context.Context, param *param.CreateOBClusterParam) error { obcluster := generateOBClusterInstance(param) - err := oceanbase.CreateSecretsForOBCluster(ctx, obcluster, param.RootPassword) + err := clients.CreateSecretsForOBCluster(ctx, obcluster, param.RootPassword) if err != nil { return errors.Wrap(err, "Create secrets for obcluster") } logger.Infof("Generated obcluster instance:%v", obcluster) - return oceanbase.CreateOBCluster(ctx, obcluster) + return clients.CreateOBCluster(ctx, obcluster) } func UpgradeObCluster(ctx context.Context, obclusterIdentity *param.K8sObjectIdentity, updateParam *param.UpgradeOBClusterParam) error { - obcluster, err := oceanbase.GetOBCluster(ctx, obclusterIdentity.Namespace, obclusterIdentity.Name) + obcluster, err := clients.GetOBCluster(ctx, obclusterIdentity.Namespace, obclusterIdentity.Name) if err != nil { return errors.Wrapf(err, "Get obcluster %s %s", obclusterIdentity.Namespace, obclusterIdentity.Name) } @@ -498,11 +497,11 @@ func UpgradeObCluster(ctx context.Context, obclusterIdentity *param.K8sObjectIde return errors.Errorf("Obcluster status invalid %s", obcluster.Status.Status) } obcluster.Spec.OBServerTemplate.Image = updateParam.Image - return oceanbase.UpdateOBCluster(ctx, obcluster) + return clients.UpdateOBCluster(ctx, obcluster) } func ScaleOBServer(ctx context.Context, obzoneIdentity *param.OBZoneIdentity, scaleParam *param.ScaleOBServerParam) error { - obcluster, err := oceanbase.GetOBCluster(ctx, obzoneIdentity.Namespace, obzoneIdentity.Name) + obcluster, err := clients.GetOBCluster(ctx, obzoneIdentity.Namespace, obzoneIdentity.Name) if err != nil { return errors.Wrapf(err, "Get obcluster %s %s", obzoneIdentity.Namespace, obzoneIdentity.Name) } @@ -527,11 +526,11 @@ func ScaleOBServer(ctx context.Context, obzoneIdentity *param.OBZoneIdentity, sc if !replicaChanged { return errors.Errorf("obzone %s replica already satisfied in obcluster %s %s", obzoneIdentity.OBZoneName, obzoneIdentity.Namespace, obzoneIdentity.Name) } - return oceanbase.UpdateOBCluster(ctx, obcluster) + return clients.UpdateOBCluster(ctx, obcluster) } func DeleteOBZone(ctx context.Context, obzoneIdentity *param.OBZoneIdentity) error { - obcluster, err := oceanbase.GetOBCluster(ctx, obzoneIdentity.Namespace, obzoneIdentity.Name) + obcluster, err := clients.GetOBCluster(ctx, obzoneIdentity.Namespace, obzoneIdentity.Name) if err != nil { return errors.Wrapf(err, "Get obcluster %s %s", obzoneIdentity.Namespace, obzoneIdentity.Name) } @@ -551,11 +550,11 @@ func DeleteOBZone(ctx context.Context, obzoneIdentity *param.OBZoneIdentity) err return errors.Errorf("obzone %s not found in obcluster %s %s", obzoneIdentity.OBZoneName, obzoneIdentity.Namespace, obzoneIdentity.Name) } obcluster.Spec.Topology = newTopology - return oceanbase.UpdateOBCluster(ctx, obcluster) + return clients.UpdateOBCluster(ctx, obcluster) } func AddOBZone(ctx context.Context, obclusterIdentity *param.K8sObjectIdentity, zone *param.ZoneTopology) error { - obcluster, err := oceanbase.GetOBCluster(ctx, obclusterIdentity.Namespace, obclusterIdentity.Name) + obcluster, err := clients.GetOBCluster(ctx, obclusterIdentity.Namespace, obclusterIdentity.Name) if err != nil { return errors.Wrapf(err, "Get obcluster %s %s", obclusterIdentity.Namespace, obclusterIdentity.Name) } @@ -572,11 +571,11 @@ func AddOBZone(ctx context.Context, obclusterIdentity *param.K8sObjectIdentity, NodeSelector: common.KVsToMap(zone.NodeSelector), Replica: zone.Replicas, }) - return oceanbase.UpdateOBCluster(ctx, obcluster) + return clients.UpdateOBCluster(ctx, obcluster) } func GetOBCluster(ctx context.Context, obclusterIdentity *param.K8sObjectIdentity) (*response.OBCluster, error) { - obcluster, err := oceanbase.GetOBCluster(ctx, obclusterIdentity.Namespace, obclusterIdentity.Name) + obcluster, err := clients.GetOBCluster(ctx, obclusterIdentity.Namespace, obclusterIdentity.Name) if err != nil { return nil, errors.Wrapf(err, "Get obcluster %s %s", obclusterIdentity.Namespace, obclusterIdentity.Name) } @@ -584,12 +583,12 @@ func GetOBCluster(ctx context.Context, obclusterIdentity *param.K8sObjectIdentit } func DeleteOBCluster(ctx context.Context, obclusterIdentity *param.K8sObjectIdentity) error { - return oceanbase.DeleteOBCluster(ctx, obclusterIdentity.Namespace, obclusterIdentity.Name) + return clients.DeleteOBCluster(ctx, obclusterIdentity.Namespace, obclusterIdentity.Name) } func GetOBClusterStatistic(ctx context.Context) ([]response.OBClusterStastistic, error) { statisticResult := make([]response.OBClusterStastistic, 0) - obclusterList, err := oceanbase.ListAllOBClusters(ctx) + obclusterList, err := clients.ListAllOBClusters(ctx) if err != nil { return statisticResult, errors.Wrap(err, "failed to list obclusters") } diff --git a/internal/dashboard/business/oceanbase/obcluster_usage.go b/internal/dashboard/business/oceanbase/obcluster_usage.go index 4ea2c83a0..03448dd96 100644 --- a/internal/dashboard/business/oceanbase/obcluster_usage.go +++ b/internal/dashboard/business/oceanbase/obcluster_usage.go @@ -19,10 +19,10 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "github.com/oceanbase/ob-operator/api/v1alpha1" + "github.com/oceanbase/ob-operator/internal/clients" oceanbaseconst "github.com/oceanbase/ob-operator/internal/const/oceanbase" "github.com/oceanbase/ob-operator/internal/dashboard/model/param" "github.com/oceanbase/ob-operator/internal/dashboard/model/response" - "github.com/oceanbase/ob-operator/internal/oceanbase" httpErr "github.com/oceanbase/ob-operator/pkg/errors" "github.com/oceanbase/ob-operator/pkg/k8s/client" "github.com/oceanbase/ob-operator/pkg/oceanbase-sdk/connector" @@ -30,14 +30,14 @@ import ( "github.com/oceanbase/ob-operator/pkg/oceanbase-sdk/operation" ) -func GetOBClusterEssentialParameters(ctx context.Context, nn *param.K8sObjectIdentity) (*response.OBClusterResources, error) { - obcluster, err := oceanbase.GetOBCluster(ctx, nn.Namespace, nn.Name) +func GetOBClusterUsages(ctx context.Context, nn *param.K8sObjectIdentity) (*response.OBClusterResources, error) { + obcluster, err := clients.GetOBCluster(ctx, nn.Namespace, nn.Name) if err != nil { return nil, err } clt := client.GetClient() serverList := &v1alpha1.OBServerList{} - err = oceanbase.ServerClient.List(ctx, nn.Namespace, serverList, metav1.ListOptions{}) + err = clients.ServerClient.List(ctx, nn.Namespace, serverList, metav1.ListOptions{}) if err != nil { return nil, httpErr.NewInternal(err.Error()) } diff --git a/internal/dashboard/business/oceanbase/obtenant.go b/internal/dashboard/business/oceanbase/obtenant.go index a09893c03..f49c821ba 100644 --- a/internal/dashboard/business/oceanbase/obtenant.go +++ b/internal/dashboard/business/oceanbase/obtenant.go @@ -25,11 +25,11 @@ import ( apiconst "github.com/oceanbase/ob-operator/api/constants" apitypes "github.com/oceanbase/ob-operator/api/types" "github.com/oceanbase/ob-operator/api/v1alpha1" + "github.com/oceanbase/ob-operator/internal/clients" + "github.com/oceanbase/ob-operator/internal/clients/schema" "github.com/oceanbase/ob-operator/internal/const/status/tenantstatus" "github.com/oceanbase/ob-operator/internal/dashboard/model/param" "github.com/oceanbase/ob-operator/internal/dashboard/model/response" - "github.com/oceanbase/ob-operator/internal/oceanbase" - "github.com/oceanbase/ob-operator/internal/oceanbase/schema" oberr "github.com/oceanbase/ob-operator/pkg/errors" "github.com/oceanbase/ob-operator/pkg/k8s/client" ) @@ -195,7 +195,7 @@ func buildOverviewFromApiType(t *v1alpha1.OBTenant) *response.OBTenantOverview { func updateOBTenant(ctx context.Context, nn types.NamespacedName, p *param.CreateOBTenantParam) (*response.OBTenantDetail, error) { var err error - tenant, err := oceanbase.GetOBTenant(ctx, nn) + tenant, err := clients.GetOBTenant(ctx, nn) if err != nil { return nil, err } @@ -205,7 +205,7 @@ func updateOBTenant(ctx context.Context, nn types.NamespacedName, p *param.Creat } tenant.Spec = t.Spec - tenant, err = oceanbase.UpdateOBTenant(ctx, tenant) + tenant, err = clients.UpdateOBTenant(ctx, tenant) if err != nil { return nil, err } @@ -289,7 +289,7 @@ func CreateOBTenant(ctx context.Context, nn types.NamespacedName, p *param.Creat } } - tenant, err := oceanbase.CreateOBTenant(ctx, t) + tenant, err := clients.CreateOBTenant(ctx, t) if err != nil { return nil, err } @@ -297,7 +297,7 @@ func CreateOBTenant(ctx context.Context, nn types.NamespacedName, p *param.Creat } func ListAllOBTenants(ctx context.Context, listOptions v1.ListOptions) ([]*response.OBTenantOverview, error) { - tenantList, err := oceanbase.ListAllOBTenants(ctx, listOptions) + tenantList, err := clients.ListAllOBTenants(ctx, listOptions) if err != nil { return nil, err } @@ -309,7 +309,7 @@ func ListAllOBTenants(ctx context.Context, listOptions v1.ListOptions) ([]*respo } func GetOBTenant(ctx context.Context, nn types.NamespacedName) (*response.OBTenantDetail, error) { - tenant, err := oceanbase.GetOBTenant(ctx, nn) + tenant, err := clients.GetOBTenant(ctx, nn) if err != nil { return nil, err } @@ -317,12 +317,12 @@ func GetOBTenant(ctx context.Context, nn types.NamespacedName) (*response.OBTena } func DeleteOBTenant(ctx context.Context, nn types.NamespacedName) error { - return oceanbase.DeleteOBTenant(ctx, nn) + return clients.DeleteOBTenant(ctx, nn) } func ModifyOBTenantRootPassword(ctx context.Context, nn types.NamespacedName, rootPassword string) (*response.OBTenantDetail, error) { var err error - tenant, err := oceanbase.GetOBTenant(ctx, nn) + tenant, err := clients.GetOBTenant(ctx, nn) if err != nil { return nil, err } @@ -355,7 +355,7 @@ func ModifyOBTenantRootPassword(ctx context.Context, nn types.NamespacedName, ro }, }, } - _, err = oceanbase.CreateOBTenantOperation(ctx, &changePwdOp) + _, err = clients.CreateOBTenantOperation(ctx, &changePwdOp) if err != nil { return nil, err } @@ -364,7 +364,7 @@ func ModifyOBTenantRootPassword(ctx context.Context, nn types.NamespacedName, ro func ReplayStandbyLog(ctx context.Context, nn types.NamespacedName, param *param.ReplayStandbyLog) (*response.OBTenantDetail, error) { var err error - tenant, err := oceanbase.GetOBTenant(ctx, nn) + tenant, err := clients.GetOBTenant(ctx, nn) if err != nil { return nil, err } @@ -385,7 +385,7 @@ func ReplayStandbyLog(ctx context.Context, nn types.NamespacedName, param *param TargetTenant: &nn.Name, }, } - _, err = oceanbase.CreateOBTenantOperation(ctx, &replayLogOp) + _, err = clients.CreateOBTenantOperation(ctx, &replayLogOp) if err != nil { return nil, err } @@ -394,7 +394,7 @@ func ReplayStandbyLog(ctx context.Context, nn types.NamespacedName, param *param func UpgradeTenantVersion(ctx context.Context, nn types.NamespacedName) (*response.OBTenantDetail, error) { var err error - tenant, err := oceanbase.GetOBTenant(ctx, nn) + tenant, err := clients.GetOBTenant(ctx, nn) if err != nil { return nil, err } @@ -411,7 +411,7 @@ func UpgradeTenantVersion(ctx context.Context, nn types.NamespacedName) (*respon TargetTenant: &nn.Name, }, } - _, err = oceanbase.CreateOBTenantOperation(ctx, &upgradeOp) + _, err = clients.CreateOBTenantOperation(ctx, &upgradeOp) if err != nil { return nil, err } @@ -420,7 +420,7 @@ func UpgradeTenantVersion(ctx context.Context, nn types.NamespacedName) (*respon func ChangeTenantRole(ctx context.Context, nn types.NamespacedName, p *param.ChangeTenantRole) (*response.OBTenantDetail, error) { var err error - tenant, err := oceanbase.GetOBTenant(ctx, nn) + tenant, err := clients.GetOBTenant(ctx, nn) if err != nil { return nil, err } @@ -449,7 +449,7 @@ func ChangeTenantRole(ctx context.Context, nn types.NamespacedName, p *param.Cha StandbyTenant: nn.Name, } } - _, err = oceanbase.CreateOBTenantOperation(ctx, &changeRoleOp) + _, err = clients.CreateOBTenantOperation(ctx, &changeRoleOp) if err != nil { return nil, err } @@ -458,7 +458,7 @@ func ChangeTenantRole(ctx context.Context, nn types.NamespacedName, p *param.Cha func PatchTenant(ctx context.Context, nn types.NamespacedName, p *param.PatchTenant) (*response.OBTenantDetail, error) { var err error - tenant, err := oceanbase.GetOBTenant(ctx, nn) + tenant, err := clients.GetOBTenant(ctx, nn) if err != nil { return nil, err } @@ -497,7 +497,7 @@ func PatchTenant(ctx context.Context, nn types.NamespacedName, p *param.PatchTen } } } - tenant, err = oceanbase.UpdateOBTenant(ctx, tenant) + tenant, err = clients.UpdateOBTenant(ctx, tenant) if err != nil { return nil, err } @@ -508,7 +508,7 @@ func PatchTenant(ctx context.Context, nn types.NamespacedName, p *param.PatchTen // Including the number of tenants in four status: running, deleting, operating, failed func GetOBTenantStatistics(ctx context.Context) ([]response.OBTenantStatistic, error) { stats := []response.OBTenantStatistic{} - tenantList, err := oceanbase.ListAllOBTenants(ctx, v1.ListOptions{}) + tenantList, err := clients.ListAllOBTenants(ctx, v1.ListOptions{}) if err != nil { return nil, oberr.Wrap(err, oberr.ErrInternal, "failed to list tenants") } diff --git a/internal/dashboard/business/oceanbase/obtenant_pool.go b/internal/dashboard/business/oceanbase/obtenant_pool.go index 7336662f6..ceec5da6b 100644 --- a/internal/dashboard/business/oceanbase/obtenant_pool.go +++ b/internal/dashboard/business/oceanbase/obtenant_pool.go @@ -19,8 +19,8 @@ import ( "k8s.io/apimachinery/pkg/types" "github.com/oceanbase/ob-operator/api/v1alpha1" + "github.com/oceanbase/ob-operator/internal/clients" "github.com/oceanbase/ob-operator/internal/dashboard/model/param" - "github.com/oceanbase/ob-operator/internal/oceanbase" oberr "github.com/oceanbase/ob-operator/pkg/errors" ) @@ -38,7 +38,7 @@ func CreateTenantPool(ctx context.Context, nn param.TenantPoolName, p *param.Ten return false, oberr.NewBadRequest("invalid log disk size: " + err.Error()) } - tenantCR, err := oceanbase.GetOBTenant(ctx, types.NamespacedName{ + tenantCR, err := clients.GetOBTenant(ctx, types.NamespacedName{ Namespace: nn.Namespace, Name: nn.Name, }) @@ -50,7 +50,7 @@ func CreateTenantPool(ctx context.Context, nn param.TenantPoolName, p *param.Ten return false, oberr.NewBadRequest("pool already exists") } } - clusterCR, err := oceanbase.GetOBCluster(ctx, nn.Namespace, tenantCR.Spec.ClusterName) + clusterCR, err := clients.GetOBCluster(ctx, nn.Namespace, tenantCR.Spec.ClusterName) if err != nil { return false, err } @@ -74,7 +74,7 @@ func CreateTenantPool(ctx context.Context, nn param.TenantPoolName, p *param.Ten LogDiskSize: logDiskSize, }, }) - _, err = oceanbase.UpdateOBTenant(ctx, tenantCR) + _, err = clients.UpdateOBTenant(ctx, tenantCR) if err != nil { return false, err } @@ -85,7 +85,7 @@ func CreateTenantPool(ctx context.Context, nn param.TenantPoolName, p *param.Ten } func DeleteTenantPool(ctx context.Context, nn param.TenantPoolName) (bool, error) { - tenantCR, err := oceanbase.GetOBTenant(ctx, types.NamespacedName{ + tenantCR, err := clients.GetOBTenant(ctx, types.NamespacedName{ Namespace: nn.Namespace, Name: nn.Name, }) @@ -110,7 +110,7 @@ func DeleteTenantPool(ctx context.Context, nn param.TenantPoolName) (bool, error } tenantCR.Spec.Pools = remainPools - _, err = oceanbase.UpdateOBTenant(ctx, tenantCR) + _, err = clients.UpdateOBTenant(ctx, tenantCR) if err != nil { return false, err } @@ -118,7 +118,7 @@ func DeleteTenantPool(ctx context.Context, nn param.TenantPoolName) (bool, error } func PatchTenantPool(ctx context.Context, nn param.TenantPoolName, p *param.TenantPoolSpec) (bool, error) { - tenantCR, err := oceanbase.GetOBTenant(ctx, types.NamespacedName{ + tenantCR, err := clients.GetOBTenant(ctx, types.NamespacedName{ Namespace: nn.Namespace, Name: nn.Name, }) @@ -149,7 +149,7 @@ func PatchTenantPool(ctx context.Context, nn param.TenantPoolName, p *param.Tena tenantCR.Spec.Pools[i].UnitConfig.IopsWeight = p.UnitConfig.IopsWeight } } - _, err = oceanbase.UpdateOBTenant(ctx, tenantCR) + _, err = clients.UpdateOBTenant(ctx, tenantCR) if err != nil { return false, err } diff --git a/internal/dashboard/business/oceanbase/obtenantbackup.go b/internal/dashboard/business/oceanbase/obtenantbackup.go index 6d2dee3af..79f4fd3ea 100644 --- a/internal/dashboard/business/oceanbase/obtenantbackup.go +++ b/internal/dashboard/business/oceanbase/obtenantbackup.go @@ -27,10 +27,10 @@ import ( apiconst "github.com/oceanbase/ob-operator/api/constants" apitypes "github.com/oceanbase/ob-operator/api/types" "github.com/oceanbase/ob-operator/api/v1alpha1" + "github.com/oceanbase/ob-operator/internal/clients" oceanbaseconst "github.com/oceanbase/ob-operator/internal/const/oceanbase" "github.com/oceanbase/ob-operator/internal/dashboard/model/param" "github.com/oceanbase/ob-operator/internal/dashboard/model/response" - "github.com/oceanbase/ob-operator/internal/oceanbase" oberr "github.com/oceanbase/ob-operator/pkg/errors" "github.com/oceanbase/ob-operator/pkg/k8s/client" ) @@ -237,6 +237,7 @@ func buildBackupPolicyModelType(p *v1alpha1.OBTenantBackupPolicy) *response.Back OSSAccessSecret: p.Spec.LogArchive.Destination.OSSAccessSecret, BakEncryptionSecret: p.Spec.DataBackup.EncryptionSecret, CreateTime: p.CreationTimestamp.Format("2006-01-02 15:04:05"), + Events: []response.K8sEvent{}, } res.ScheduleBase = getScheduleDatesFromPolicy(p) return res @@ -282,25 +283,52 @@ func buildBackupJobModelType(p *v1alpha1.OBTenantBackup) *response.BackupJob { } func GetTenantBackupPolicy(ctx context.Context, nn types.NamespacedName) (*response.BackupPolicy, error) { - _, err := oceanbase.GetOBTenant(ctx, nn) + _, err := clients.GetOBTenant(ctx, nn) if err != nil { if kubeerrors.IsNotFound(err) { return nil, oberr.NewNotFound("Tenant not found") } return nil, oberr.NewInternal(err.Error()) } - policy, err := oceanbase.GetTenantBackupPolicy(ctx, nn) + policy, err := clients.GetTenantBackupPolicy(ctx, nn) if err != nil { return nil, oberr.NewInternal(err.Error()) } if policy == nil { return nil, nil } - return buildBackupPolicyModelType(policy), nil + respPolicy := buildBackupPolicyModelType(policy) + events, err := client.GetClient().ClientSet.CoreV1().Events(nn.Namespace).List(ctx, metav1.ListOptions{ + FieldSelector: "involvedObject.name=" + policy.Name + ",involvedObject.kind=OBTenantBackupPolicy", + }) + if err != nil { + return nil, oberr.NewInternal(err.Error()) + } + jobEvents, err := client.GetClient().ClientSet.CoreV1().Events(nn.Namespace).List(ctx, metav1.ListOptions{ + LabelSelector: oceanbaseconst.LabelRefBackupPolicy + "=" + policy.Name, + FieldSelector: "involvedObject.kind=OBTenantBackup", + }) + if err != nil { + return nil, oberr.NewInternal(err.Error()) + } + events.Items = append(events.Items, jobEvents.Items...) + for _, event := range events.Items { + respPolicy.Events = append(respPolicy.Events, response.K8sEvent{ + Namespace: event.Namespace, + Type: event.Type, + Count: event.Count, + FirstOccur: event.FirstTimestamp.Unix(), + LastSeen: event.LastTimestamp.Unix(), + Reason: event.Reason, + Message: event.Message, + Object: fmt.Sprintf("%s/%s", event.InvolvedObject.Kind, event.InvolvedObject.Name), + }) + } + return respPolicy, nil } func CreateTenantBackupPolicy(ctx context.Context, nn types.NamespacedName, p *param.CreateBackupPolicy) (*response.BackupPolicy, error) { - tenant, err := oceanbase.GetOBTenant(ctx, nn) + tenant, err := clients.GetOBTenant(ctx, nn) if err != nil { if kubeerrors.IsNotFound(err) { return nil, oberr.NewNotFound("Tenant not found") @@ -361,7 +389,7 @@ func CreateTenantBackupPolicy(ctx context.Context, nn types.NamespacedName, p *p } } - policy, err := oceanbase.CreateTenantBackupPolicy(ctx, backupPolicy) + policy, err := clients.CreateTenantBackupPolicy(ctx, backupPolicy) if err != nil { return nil, oberr.NewInternal(err.Error()) } @@ -369,7 +397,7 @@ func CreateTenantBackupPolicy(ctx context.Context, nn types.NamespacedName, p *p } func UpdateTenantBackupPolicy(ctx context.Context, nn types.NamespacedName, p *param.UpdateBackupPolicy) (*response.BackupPolicy, error) { - tenant, err := oceanbase.GetOBTenant(ctx, nn) + tenant, err := clients.GetOBTenant(ctx, nn) if err != nil { if kubeerrors.IsNotFound(err) { return nil, oberr.NewNotFound("Tenant not found") @@ -379,7 +407,7 @@ func UpdateTenantBackupPolicy(ctx context.Context, nn types.NamespacedName, p *p if tenant.Status.Status != "running" { return nil, oberr.NewBadRequest("Tenant is not running") } - policy, err := oceanbase.GetTenantBackupPolicy(ctx, nn) + policy, err := clients.GetTenantBackupPolicy(ctx, nn) if err != nil { return nil, oberr.NewBadRequest(err.Error()) } @@ -417,7 +445,7 @@ func UpdateTenantBackupPolicy(ctx context.Context, nn types.NamespacedName, p *p } } - np, err := oceanbase.UpdateTenantBackupPolicy(ctx, policy) + np, err := clients.UpdateTenantBackupPolicy(ctx, policy) if err != nil { return nil, oberr.NewInternal(err.Error()) } @@ -425,18 +453,18 @@ func UpdateTenantBackupPolicy(ctx context.Context, nn types.NamespacedName, p *p } func DeleteTenantBackupPolicy(ctx context.Context, nn types.NamespacedName, force bool) error { - policy, err := oceanbase.GetTenantBackupPolicy(ctx, nn) + policy, err := clients.GetTenantBackupPolicy(ctx, nn) if err != nil { return oberr.NewBadRequest(err.Error()) } if force { - return oceanbase.ForceDeleteTenantBackupPolicy(ctx, types.NamespacedName{Name: policy.Name, Namespace: policy.Namespace}) + return clients.ForceDeleteTenantBackupPolicy(ctx, types.NamespacedName{Name: policy.Name, Namespace: policy.Namespace}) } - return oceanbase.DeleteTenantBackupPolicy(ctx, types.NamespacedName{Name: policy.Name, Namespace: policy.Namespace}) + return clients.DeleteTenantBackupPolicy(ctx, types.NamespacedName{Name: policy.Name, Namespace: policy.Namespace}) } func ListBackupJobs(ctx context.Context, nn types.NamespacedName, jobType string, limit int) ([]*response.BackupJob, error) { - policy, err := oceanbase.GetTenantBackupPolicy(ctx, nn) + policy, err := clients.GetTenantBackupPolicy(ctx, nn) if err != nil { return nil, oberr.NewInternal(err.Error()) } @@ -450,7 +478,7 @@ func ListBackupJobs(ctx context.Context, nn types.NamespacedName, jobType string listOption.LabelSelector = oceanbaseconst.LabelRefBackupPolicy + "=" + policy.Name } listOption.Limit = int64(limit) - jobs, err := oceanbase.ListBackupJobs(ctx, listOption) + jobs, err := clients.ListBackupJobs(ctx, listOption) if err != nil { return nil, oberr.NewInternal(err.Error()) } diff --git a/internal/dashboard/generated/bindata/bindata.go b/internal/dashboard/generated/bindata/bindata.go index d6122a1b5..c1a063e45 100644 --- a/internal/dashboard/generated/bindata/bindata.go +++ b/internal/dashboard/generated/bindata/bindata.go @@ -94,7 +94,7 @@ func internalAssetsMetric_en_usYaml() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "internal/assets/metric_en_US.yaml", size: 21510, mode: os.FileMode(420), modTime: time.Unix(1708935041, 0)} + info := bindataFileInfo{name: "internal/assets/metric_en_US.yaml", size: 21510, mode: os.FileMode(420), modTime: time.Unix(1709022970, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -114,12 +114,12 @@ func internalAssetsMetric_exprYaml() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "internal/assets/metric_expr.yaml", size: 31556, mode: os.FileMode(420), modTime: time.Unix(1708935041, 0)} + info := bindataFileInfo{name: "internal/assets/metric_expr.yaml", size: 31556, mode: os.FileMode(420), modTime: time.Unix(1709022970, 0)} a := &asset{bytes: bytes, info: info} return a, nil } -var _internalAssetsMetric_zh_cnYaml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\x5c\x5b\x6f\xdb\x3a\x12\x7e\xef\xaf\x10\x02\x2c\xfa\xb2\x8b\x95\x75\xb5\xf3\x16\xdd\x16\x05\xda\x93\xb6\x69\xcf\xbe\x08\x30\x14\x85\x4d\xb5\x95\x2d\x57\x12\x5b\xe4\xfc\xfa\x05\x49\xc9\xba\x0d\x29\xd2\xca\x1e\x6c\x7a\xf4\x62\x24\x22\xcd\xf9\x38\xe2\x7c\x33\x1c\x0e\x7d\xeb\xf9\x6f\x3f\xdf\x7d\x0a\x3f\x5e\xbf\xfa\x87\xf6\x80\xaa\xb4\xcc\x4e\x75\x56\x1c\xaf\xb5\xab\x18\x3b\xb6\xab\xc7\xd8\x31\x9d\x30\xc6\x76\xb8\x33\x63\xec\xe8\x86\x1b\xe3\xad\x1e\x05\x57\xaf\x34\xed\x80\xea\x32\x4b\xff\x55\x16\xf8\x54\x5d\xbf\xd2\xb4\xe9\x08\x76\xe8\x9a\x31\xb6\x5d\xcb\x8d\xb1\xe3\xf9\x51\x8c\xdd\x5d\x60\xc4\xd8\xde\xe9\x56\x8c\x5d\x4b\x77\xb4\xbb\x0f\x6f\xb5\x18\x6f\xbd\x30\x88\xb1\x6d\x86\x36\x13\x4b\x86\x6f\x05\xd0\xb1\xa1\xd1\x2f\x18\x51\xd3\xbe\xa1\xa7\x6b\xad\xfa\x9e\xef\x93\x3c\xdf\xa7\x05\x3e\xd6\x4d\xc3\x31\x39\xa0\x6b\x2d\xc9\xf3\xe6\x7f\x7c\xcc\xea\x6b\xad\xce\x0e\xa8\xfa\x67\xa5\x88\x00\xe5\x28\xad\x65\x40\x54\xb4\x27\x80\x83\x35\x2c\x87\xf2\xe6\x58\xa1\x52\x0a\x4a\x46\x7b\x02\x50\x58\xc3\x72\x28\x9f\x4f\x0f\x49\x8d\x64\xa0\x60\xda\x13\x80\xc2\x1a\x96\x43\xf9\x88\x4e\x79\x92\x4a\x61\x29\x59\x57\x00\x4c\xd3\xb2\x1c\x4d\x80\x72\x24\xa7\x98\x07\xda\x13\xc0\xc2\x1a\xa4\xa1\x04\xc1\xdb\xbf\x6b\x81\x4f\x3e\x3e\x11\x63\x71\x3d\x6b\x17\x63\x7b\xe3\x3a\x31\xb6\xc2\xc0\x91\x80\x52\xd4\x5f\x51\x09\x20\xa1\xcf\xb9\x40\x58\x9f\x0f\xef\xef\x40\xba\x70\x5c\x9d\x08\x35\x6e\x36\x31\x76\x6f\xc2\xa8\xd5\x98\xe3\x3a\x1b\xc0\xac\x3b\x15\x36\x4c\xd3\x88\x6d\x19\x67\xab\x6f\x08\xef\xd8\x91\x23\x41\x27\xc0\xf0\x3d\xf2\xea\x8b\x1a\x0f\x3b\xe2\x94\x52\x4c\x28\x57\x31\xd6\x4d\xcf\xaf\xae\x60\x14\x10\x73\x5c\x00\xa4\xe1\x95\x72\x96\x54\xc4\x70\x40\xf6\xb8\x00\x4e\xc3\x2d\xe5\x2c\xb1\x88\xe1\x80\x0c\x72\x01\x9c\x86\x5f\xca\x59\x72\x11\xc3\x81\x59\xe4\x02\x3c\x2d\xc7\x94\xf3\x04\x23\x46\x04\x32\xc9\x05\x80\x1a\x9e\x29\x67\x49\x66\x06\x8e\x12\xcd\x4c\x70\x36\x92\x88\x41\xcf\x22\x66\x74\x54\xce\x71\xd1\x10\x2f\xeb\x45\x89\x87\x00\xd8\x7a\x21\x21\x66\xcb\x0f\x68\xbc\x63\x31\x51\x31\xde\xd9\x91\x75\x75\x61\x7c\x43\x26\xba\xf5\x5a\x52\x5b\x18\xda\xf0\x06\x6b\xf4\x50\x9f\xaa\x67\x8a\x65\x1c\x33\xd0\x89\xb0\x1b\x6b\x4e\x64\x99\x1c\xab\x24\x25\x83\xec\xd3\xe2\x70\xc8\xa0\x00\x82\x76\x82\x9a\x95\x7d\xa6\x13\x84\x31\x76\xc2\xe0\x46\x01\x56\x59\xe4\xf9\x7d\x92\x7e\xe3\x02\x03\x3b\xa8\x42\xdb\x06\x5b\xbb\x5d\x2f\xd2\xd0\xc8\xf0\x05\xe6\xab\x0c\x6a\xe7\xf9\xd4\x4f\x8a\x3e\xd5\x0a\x8d\x91\x16\x39\x3c\x71\x76\xaa\x43\x63\x98\x5d\xc2\x12\x43\xf3\x0c\xba\x3e\x55\xcb\xdc\x28\x5f\x7a\x7f\x65\xf3\xa4\x4f\xd7\x74\x29\x58\xd0\x4a\x1e\x4c\xa0\x96\xde\xda\x96\x00\x76\x5e\xb4\x20\xb4\x69\xab\x90\xfe\x06\x98\x14\xe8\xcf\x8a\x36\x04\xad\x17\x04\x0a\xd4\x66\x47\x36\x99\xb4\x61\x91\x2f\x05\xa6\x47\x6c\xc7\x37\x79\x83\x35\x53\x27\xb3\xfe\x81\xf6\x15\xaa\xaa\xac\x38\x0e\x57\x06\xd4\xc4\xa6\xfb\xfa\xb5\x04\x06\xb1\xdc\x3c\x87\x85\x4e\x9e\x0f\x24\x76\x9a\x05\x06\xe7\x45\x9e\x11\x79\xe7\xbe\x45\x78\xce\x35\xb6\x67\x6f\x19\x11\x62\xd9\x39\x9b\x88\x00\x26\xeb\xc2\x0a\x8d\x20\xc6\xae\xb3\xb5\x9a\x3e\x5d\xd8\x4b\xfb\x5e\x10\xf6\x4a\x09\xec\xb5\x72\x16\x68\x89\xbe\x63\x54\xd5\xfb\xef\x18\x61\x44\xd9\x6b\xa0\xb4\xc9\x63\xe1\xa2\xec\x2b\x84\x87\x6c\x88\x43\xde\xa7\x31\xe5\x0d\x79\x9a\x86\x20\x51\xe0\x5e\xe8\xa5\x2f\x19\xbe\x6f\xd7\x2d\x9d\xe4\xc5\x23\xe0\x0f\xc6\x4f\x79\x5e\xe0\x6a\x5e\xec\x73\x4d\xc3\xde\x19\xe4\xd3\xd7\xa3\xff\xa1\xae\xc6\x42\x1a\x8d\xa5\x44\x1f\x4c\x6d\xf4\xaf\xa2\x4e\xf2\x7d\x95\xfd\x81\x26\x4a\xeb\x3d\x64\x3a\xbb\x7f\x6a\x42\xd8\x59\x85\xed\x36\x7e\xc4\x51\xd8\xc4\xa7\xf2\x63\xb4\x6e\x3c\x36\xd3\xc5\x1b\xd5\xf3\xa6\xd8\x33\x36\x02\xc5\x6d\x76\x3b\x22\x32\xd8\x0e\xdd\x0c\x15\xd5\x0b\xac\x27\x36\x4c\x55\xfb\xb3\xcc\x6a\xb4\x7f\xc8\xaa\x89\x7f\xe9\x5a\x94\xbc\x9e\x0c\x64\x37\xb2\x89\x3e\xc3\xc0\x27\x5e\x48\xf7\x49\x7f\xc7\x1e\x6a\x8c\xaf\x33\x9e\x2d\x55\x4f\xc7\x74\xb2\x0f\x26\xcf\x64\x79\x88\x07\x77\x8e\x7b\xe0\xbd\x81\xf6\xe6\x56\x6b\x15\x21\xc9\x33\x77\x77\x77\x75\x51\x22\x6d\x14\x70\x7a\x91\x37\x1d\xa8\xd1\x42\x56\xec\x4b\x94\x3c\x80\x49\xab\xe4\x41\x3a\xc4\x85\x25\xb3\xa5\xc5\x97\xcc\x96\xc8\x54\x34\x7d\x3e\xc3\x5f\x6f\x6e\x39\x61\xec\x54\x9b\x04\x00\xd3\xa6\x9a\xc3\x1b\xcd\x89\xcd\x83\x69\xd3\x36\x03\x07\x30\x97\xe9\x2a\x6b\xf5\x3b\xd9\xb0\x8f\x94\x3b\x93\xec\x01\xa1\x30\xf5\xda\x1b\xc7\x96\x85\xc2\x14\x0e\x19\xea\xfc\xfa\x06\x14\xa8\xb8\x94\x7b\x87\x04\x2d\x63\x2e\x58\xd0\xec\x15\xc0\x83\x8e\x94\x3f\xe1\xfb\x89\xfa\xcf\x5c\xaf\xb2\xb0\x99\xe6\xe7\x10\x30\x9d\x4f\x20\x4c\xb5\x3e\xf6\x37\x54\x69\xb6\xb5\x09\xe9\xa7\x2e\x72\x33\xbc\xec\x82\x63\xea\x84\xe1\xbd\xdd\x4d\x8c\x5d\xdf\x25\x5a\x73\x09\x47\x2d\xce\x34\x38\x0e\x9d\xae\xbe\x51\xd9\x5f\x57\xd9\xf1\x31\x47\xfb\x53\x52\xd6\x59\xb3\x67\x82\x77\xb3\xc2\x8e\xca\xa9\x00\x83\x65\x7d\x75\xa2\xa1\x48\x8f\x14\x00\x1f\x70\x5e\x67\x12\x78\x45\xfd\xa4\xe3\x2f\xb7\xf7\x86\xbb\x74\x93\xf0\x60\xed\xd6\xfb\x14\xfe\x76\xf3\xdb\x27\xf0\x48\xee\xdc\x8f\x08\xd2\xc3\xbb\x0f\x6f\xd7\x93\xb8\xf5\x24\x6e\x3d\x89\x5b\x4f\xe2\x9e\xf5\x24\x8e\x9f\x05\x5a\x8f\xd1\xd6\x63\xb4\xf5\x18\x6d\x3d\x46\x83\xb6\xca\x6b\xee\x78\x20\xf7\x4f\xcb\x1d\x3b\x86\x43\xa2\xc2\xad\xe5\x93\xfe\x34\x8b\x6f\x6c\x8c\xf3\xe6\xc0\x30\xbc\x45\x87\x8e\x8e\x6b\xf8\x64\x45\x99\xfa\x50\x14\xe8\x8d\xf2\x22\x4d\xa0\x70\x8e\x3e\x5f\xec\xa1\x63\xbc\x8d\x02\x3f\xc6\xee\x8d\xee\xf1\xe7\xcd\x09\x1f\x0e\x05\xe8\xb1\x59\xc3\x33\x40\x9b\xee\x49\x38\x00\x7b\x16\x09\x07\x17\x59\x55\x97\xd9\x3d\xae\x11\x94\xc2\xe9\xb5\xce\xed\x46\x54\x96\x87\x78\x9e\xfd\x0c\x3c\xdb\xe1\x58\x21\x31\x70\xa5\x4c\xd6\x65\x43\x36\x8a\xf9\x99\x64\xf5\x1e\xfd\x40\x47\x28\x32\x5e\xb0\x59\xd8\xd0\x43\x05\x3d\xdc\x2a\x23\xaa\x9e\xaa\x1a\x1d\x1a\x4c\xd9\xb1\x46\xe5\x31\xc9\x9b\x64\x34\x41\x5b\x8d\xdc\x74\xd3\x81\x34\x5d\x0a\xf6\x9c\x16\xd5\x3e\xbe\xf7\xb5\x65\x88\x59\x66\xf4\x94\x72\x11\x9f\x3b\x2c\x40\xbc\xb3\xf5\xcd\x32\x98\x65\xf1\x93\x90\xca\x37\x8a\x82\x8b\x75\xd0\xeb\x22\xac\x2c\x9d\xb5\x68\x09\x14\xfc\x97\x5f\x2c\x00\x96\x27\x75\xfa\x75\x21\x36\x3a\x06\x17\x1e\x6b\x5d\xb2\x30\x7b\xc1\xc8\x12\x98\x2c\xfe\xe0\xc1\x64\xad\x42\x98\x67\xef\x09\xa3\x80\x89\x8e\x87\x58\x94\x7e\x9d\x21\xba\x4b\x86\x9c\x12\xdd\xc2\x22\x08\x19\x6e\x93\x00\xc4\xe1\xb9\xec\x80\xe8\xbb\x38\xbb\xa1\x39\x9e\x9b\x85\x2b\xcb\x6e\xaa\x98\x3b\xa6\xe3\x60\xe6\x33\xdd\x1c\xe6\x29\xbf\x75\x81\xaf\x3a\xd0\x11\xd7\x71\xd0\xf2\xb9\x6e\x66\x1b\x2a\x22\x38\xe5\x75\x50\xf0\x57\x00\x40\x76\x62\x64\x73\x0c\xa7\x0a\xae\x61\x3b\x0e\x3e\x0e\xdb\xcd\x5b\xd3\x3c\xc7\xa9\x02\x6d\xf8\x8e\x03\x94\xc3\x77\x9c\xdd\x17\x0f\x93\x7c\x91\x44\x9b\xb0\x8d\x02\xaf\x3d\x07\x11\xd4\x84\xdc\x28\xc4\x7d\xfd\x21\xfb\x21\x73\x7f\x48\x76\x3e\xde\x2f\xfb\x18\xa6\xcf\xb5\x71\x99\x09\x3a\xb2\x8a\x12\x28\xa4\xe7\xf7\x90\x71\x6d\x56\xe8\x87\x7c\xa0\xf6\x26\xba\x69\x9f\x70\x40\xf7\x22\x7c\x2e\xfc\x07\x34\x07\x1f\xea\x21\x70\x79\xf3\x15\x33\x6b\xf9\xd1\x9f\x58\x7e\xe4\xbf\xff\x4c\x36\xf1\x2e\x59\x25\x36\x9d\xa0\xb9\x75\x25\x74\x22\xf8\x5e\x33\xd1\xe2\x7e\x9f\x9e\xf0\xfe\x84\xca\x14\x8d\x96\x0e\x79\x5e\x8e\xf3\x6f\xaf\xff\x36\x48\x2d\x70\x05\x00\x61\xcc\x2e\xa0\xdb\x58\xd3\x6d\xa3\x09\xdb\xb3\xb7\xa3\x6f\x3b\x6e\xd8\x6e\x7e\x1d\x2f\x90\xab\x0e\xe5\x0d\x6c\x07\x91\x21\x33\x7c\xa7\x89\x03\x3a\x14\xe5\x13\xa8\x8c\xa6\x09\x57\xc9\xa3\x50\x21\x82\xb9\x71\x34\xf3\x2e\x7c\x47\x4f\x90\x17\x6b\x42\x65\xa0\x66\xce\x07\x74\xa8\xc8\x57\xc0\x29\xb7\xe3\x8d\x1a\xc1\x69\xcb\xcb\x9e\xa4\x6c\x4f\x29\xcd\x5d\x98\x4e\x8c\x4d\x9d\x44\x40\xb6\x19\xd0\x4f\x5d\x95\x01\xfa\x43\xb1\xaf\x4b\xf8\x50\x12\xaa\x9d\x92\xf4\x1b\x22\xf1\xe8\x34\x1f\xae\xe0\xd6\x99\xf8\x3e\x7a\x35\xf1\x05\x9e\x44\xe9\x05\x96\x70\xd7\xad\xdc\xa9\xbe\x80\xc0\xc3\xb4\x89\x4b\x8f\x68\xd6\xb3\x1f\x5d\x6e\xb6\xb6\xe8\x4d\xdc\x3f\xd5\x68\xe8\x8f\x14\x0b\x35\x80\x77\x03\x14\x2e\xc0\x6f\x45\xf4\x4a\xb8\x75\x19\xc0\xdb\x90\x14\xd8\x29\x1d\x7e\x09\xe3\x32\x8c\xbe\xfe\xe5\xaa\x31\x1c\xc3\x66\x79\x3d\xbd\xf5\x7e\x4e\x68\x6e\x63\xec\x6c\x75\xa5\x9a\x51\xc9\x61\x5a\x82\x3b\xa1\x23\x7a\xd8\xa7\xb8\xac\x8a\xb2\x82\x4e\xf9\x4e\xe8\xd8\x36\x0f\x8d\x7d\x44\x71\x72\x82\xbb\xee\x50\xa5\x81\xa8\x9c\xfd\xb9\xea\x10\xd6\x1b\x33\xeb\x8d\x19\x2e\xb4\xf5\xc6\xcc\x7a\x63\xe6\x25\xdf\x98\x59\x2f\x24\xac\x17\x12\xfe\x9a\x17\x12\xfe\xbf\xaa\xfb\x5f\xe0\xa5\x8a\xc5\x17\x12\xfa\x0b\xbe\x3f\x06\x90\xc2\x56\x3b\xd4\x65\x6a\x01\x86\x31\x48\x44\x6d\x1b\xbb\x88\x7b\xf8\x73\xde\xcb\x32\x15\xd0\xac\x76\x85\xd3\x14\xaa\xc3\xc4\x69\x8a\xaa\x4a\x21\xda\xe0\xe1\xb2\x77\xe6\x86\xc4\x1f\x06\x30\x55\x01\xae\x2f\x49\x06\x15\x36\x90\xc7\x6a\x24\x38\xa7\x70\xde\xab\x9b\x06\x20\xc0\xdc\x2e\x3f\xb2\xea\xab\xab\x3f\x8c\x44\xe6\x0d\x52\xd7\xf9\x08\x63\xb8\xd4\x47\x4f\xa5\x57\xba\x18\xd7\xa5\x17\xf5\xd7\x52\xfa\x17\x5e\x4a\xdf\xdf\x7f\x02\xaf\x9d\xe5\x14\xf5\x9b\x2d\xdb\xc4\x12\x37\xb4\x31\xd9\x73\x99\xfd\xea\xad\x47\x93\x04\xd4\xa1\x72\x2e\x87\x74\x99\x43\x85\x6c\x1f\xf1\x11\xba\xe9\x71\xc3\x09\x16\x3f\x9c\xad\x0a\x57\xa3\x83\x21\xda\x3e\xd0\xdf\x3b\x8f\xf7\xa6\xcf\x65\x72\x5a\x4f\x3a\x47\x6e\x53\x0f\xc7\x17\xcc\x3a\xc8\x49\xde\xee\x42\xe7\x9c\xcc\xb1\x74\xe6\x33\xe9\x51\x0a\xfd\x5b\x37\xfd\x21\x87\x24\xff\x29\xca\xfd\x97\x12\xa1\x3f\xd0\xbe\x2e\xb3\xc7\xc7\x73\xd1\x61\xbb\x94\xfa\xcf\x84\xc2\xbb\xcc\x26\x89\x71\xf2\xec\x90\xd5\x30\x5f\xd1\xa6\x61\x8c\xd6\x7b\x32\x90\x31\xcc\xaf\xae\x57\xfe\xb4\xf5\xca\xdf\x7a\xe5\x6f\xbd\xf2\xf7\xbc\x57\xfe\x3a\xf7\xa4\xbc\x9f\xb5\x5d\xdb\x15\x0f\xd0\x4c\xe5\x9e\x86\x67\x69\x92\x7e\x65\xb3\xd9\x1f\xee\x07\x13\xea\xb5\x4b\x12\x3d\xad\x2c\x95\x90\x5c\x16\x3f\x05\x72\xcf\xad\x92\x8e\x8d\x57\xd5\x3a\x8f\xe3\x94\x27\x47\x01\x90\xae\x59\x06\x89\x9f\x17\x8f\x9a\x94\x58\xba\x0b\xe4\x8b\xed\x9a\x65\xc4\xde\xe7\x45\x71\xd0\xbe\x64\x79\x8d\x4a\x39\xf1\xf4\x1b\x7b\xf6\x0d\xf1\xeb\x1f\x75\x93\x81\x93\x17\x69\x42\xfe\x94\x83\xd2\xf6\x16\xc0\x18\x76\xe1\x3b\x64\xa1\xd1\xcc\x18\x98\xe5\x06\xe7\xf2\x02\xb9\xb3\x79\xd0\xcc\xc0\x61\x00\x63\xfb\x9a\xd5\xfb\x92\x4c\x4a\xca\xdc\xda\xc3\x5a\x29\x7b\x13\x41\xe8\xac\x0e\x06\x00\xdb\x1d\x5f\xbc\x94\xe1\x89\x00\xf5\xcc\x0f\x46\xc4\x31\x40\x1e\x24\xc8\x02\x45\xf2\x7b\x76\x08\xcb\xe7\x58\x22\x4f\xbe\xc8\x14\x67\xd6\xc6\xd8\x20\xb9\x4b\x44\x64\x92\x3c\x5c\x3c\x9b\x14\x61\x1a\x59\x26\x8c\x47\x60\x9b\x93\xca\x8a\x39\xc9\x62\x13\x1d\x14\x56\x29\x66\xa5\x26\x86\x2a\x1a\x0c\x30\xd7\x12\x7d\xdf\xf7\x37\x5a\x33\xe6\x2a\x6f\xad\x12\x38\x3a\x9b\x85\x51\x70\x6c\x56\xda\x3e\x24\x20\xf4\xac\x04\xc6\xc0\xb3\x12\x65\x23\x91\x7b\x2f\x63\x53\xe1\xbe\x1e\xa1\xa9\x28\x59\x8a\x04\xb0\x91\xbd\xc0\xa0\x44\xf6\x22\x30\x17\xbe\xf8\xae\x6e\x49\x98\xe0\x38\xff\xba\xf7\xfe\xf6\xf7\xf0\xe3\xef\x6f\xc2\x7f\x4f\x7e\x53\xc0\xcf\x71\x45\xde\xc8\xed\x0f\x54\xfe\xc8\xd0\xcf\x5f\xf4\xc7\x04\xbe\x63\x54\x3e\x49\xa5\x9d\x5e\xcc\x8d\x68\x36\x25\xd9\x54\xea\xaf\xf3\xab\xa6\xed\x19\xd0\x5f\xfe\x80\xbf\xab\x78\x90\x59\x00\xbf\xf8\x6f\x3c\x2a\xdd\x9a\x7d\x39\x37\x7e\x94\x8e\x4b\x64\x2e\x00\xfc\x37\x00\x00\xff\xff\x11\x20\x69\xf9\xf1\x61\x00\x00") +var _internalAssetsMetric_zh_cnYaml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\x5c\xdd\x6f\xdb\x38\x12\x7f\xdf\xbf\x42\x08\x70\xe8\xcb\x1d\x4e\xb6\x3e\x9d\xb7\xe8\xeb\x50\xa0\xdd\xb4\x4d\xbb\xf7\x22\xc0\x50\x14\x36\xd5\x55\xb6\x5c\x49\x6c\x90\xfd\xeb\x0f\x24\x25\xeb\x6b\x48\x91\x56\x6e\x71\xd9\xd5\x8b\x91\x88\x34\xe7\xc7\x11\xe7\x37\xc3\xe1\xd0\xb7\x9e\xff\xee\xcb\xdd\xe7\xf0\xd3\xf5\x2f\xff\xd0\x1e\x50\x95\x96\xd9\xa9\xce\x8a\xe3\xb5\x76\x15\x63\xdb\x72\xf4\x18\xdb\x86\x1d\xc6\xd8\x0a\x77\x46\x8c\x6d\x7d\xeb\xc4\xd8\xd5\xa3\xe0\xea\x17\x4d\x3b\xa0\xba\xcc\xd2\x7f\x95\x05\x3e\x55\xd7\xbf\x68\xda\x74\x04\x2b\x74\x8c\x18\x5b\x8e\xe9\xc4\xd8\xf6\xfc\x28\xc6\xce\x2e\xd8\xc6\xd8\xda\xe9\x66\x8c\x1d\x53\xb7\xb5\xbb\x8f\xef\xb4\x18\xbb\x5e\x18\xc4\xd8\x32\x42\x8b\x89\x25\xc3\xb7\x02\xe8\xd8\xd0\xe8\x17\x8c\xa8\x69\xdf\xd1\xf3\xb5\x56\xfd\xc8\xf7\x49\x9e\xef\xd3\x02\x1f\xeb\xa6\xe1\x98\x1c\xd0\xb5\x96\xe4\x79\xf3\x3f\x3e\x66\xf5\xb5\x56\x67\x07\x54\xfd\xb3\x52\x44\x80\x72\x94\xd6\x32\x20\x2a\xda\x13\xc0\xc1\x1a\x96\x43\x79\x7b\xac\x50\x29\x05\x25\xa3\x3d\x01\x28\xac\x61\x39\x94\x2f\xa7\x87\xa4\x46\x32\x50\x30\xed\x09\x40\x61\x0d\xcb\xa1\x7c\x42\xa7\x3c\x49\xa5\xb0\x94\xac\x2b\x00\xa6\x69\x59\x8e\x26\x40\x39\x92\x53\xcc\x03\xed\x09\x60\x61\x0d\xd2\x50\x82\xe0\xdd\xdf\xb5\xc0\x27\x1f\x9f\x89\xb1\x38\x9e\xb9\x8b\xb1\xb5\x71\xec\x18\x9b\x61\x60\x4b\x40\x29\xea\x6f\xa8\x04\x90\xd0\xe7\x5c\x20\xac\xcf\xc7\x0f\x77\x20\x5d\xd8\x8e\x4e\x84\x6e\x6f\x36\x31\x76\x6e\xc2\xa8\xd5\x98\xed\xd8\x1b\xc0\xac\x3b\x15\x36\x4c\xd3\x88\x6d\x19\xc7\xd5\x37\x84\x77\xac\xc8\x96\xa0\x13\x60\xf8\x1e\x79\xf5\x45\x8d\x87\x1d\x71\x4a\x29\x26\x94\xab\x18\xeb\x86\xe7\x57\x57\x30\x0a\x88\x39\x2e\x00\xd2\xf0\x4a\x39\x4b\x2a\x62\x38\x20\x7b\x5c\x00\xa7\xe1\x96\x72\x96\x58\xc4\x70\x40\x06\xb9\x00\x4e\xc3\x2f\xe5\x2c\xb9\x88\xe1\xc0\x2c\x72\x01\x9e\x96\x63\xca\x79\x82\x11\x23\x02\x99\xe4\x02\x40\x0d\xcf\x94\xb3\x24\x33\x03\x47\x89\x66\x26\x38\x1b\x49\xc4\xa0\x67\x11\x33\x3a\x2a\xe7\xb8\x68\x88\x97\xf5\xa2\xc4\x43\x00\xb8\x5e\x48\x88\xd9\xf4\x03\x1a\xef\x98\x4c\x54\x8c\x77\x56\x64\x5e\x5d\x18\xdf\x90\x89\xba\x5e\x4b\x6a\x0b\x43\x1b\xde\x60\x8d\x1e\xea\x53\xf5\x42\xb1\x8c\x6d\x04\x3a\x11\x76\x63\xce\x89\x2c\x93\x63\x95\xa4\x64\x90\x7d\x5a\x1c\x0e\x19\x14\x40\xd0\x4e\x50\xb3\xb2\xcf\xb4\x83\x30\xc6\x76\x18\xdc\x28\xc0\x2a\x8b\x3c\xbf\x4f\xd2\xef\x5c\x60\x60\x07\x55\x68\x6e\xe0\x5a\xed\x7a\x91\x86\x46\x86\x2f\x30\x5f\x65\x50\x3b\xcf\xa7\x7e\x56\xf4\xa9\x66\xb8\x1d\x69\x91\xc3\x13\x67\xa7\x3a\x34\x86\xd9\x25\x2c\x31\x34\xcf\xa0\xeb\x53\xb5\xcc\x8d\xf2\xa5\xf7\x57\x36\x4f\xfa\x74\x4d\x97\x82\x05\xad\xe4\xc1\x04\x6a\xe9\xad\x6d\x09\x60\xe7\x45\x0b\x42\x9b\xb6\x0a\xe9\x6f\x80\x49\x81\xfe\xcc\x68\x43\xd0\x7a\x41\xa0\x40\x6d\x56\x64\x91\x49\x6f\x4d\xf2\xa5\xc0\xf0\x88\xed\xf8\x06\x6f\xb0\x66\xea\x64\xd6\x3f\xd1\xbe\x42\x55\x95\x15\xc7\xe1\xca\x80\x9a\xd8\x74\xdf\xbc\x91\xc0\x20\x96\x9b\xe7\xb0\xd0\xc9\xf3\x81\xc4\x4e\xb3\xc0\xe0\xbc\xc8\x33\x22\xef\xdc\x37\x09\xcf\x39\x5b\xf7\xec\x2d\x23\x42\x2c\x3b\x7b\x13\x11\xc0\x64\x5d\x98\xe1\x36\x88\xb1\x63\xbb\x66\xd3\xa7\x0b\x7b\x69\xdf\x0b\xc2\x5e\x29\x81\xbd\x56\xce\x02\x2d\xd1\x0f\x8c\xaa\x7a\xff\x03\x23\x8c\x28\x7b\x0d\x94\x36\x79\x2c\x5c\x94\x7d\x85\xf0\x90\x0d\x71\xc8\xfb\x34\xa6\xbc\x21\x4f\xd3\x10\x24\x0a\x9c\x0b\xbd\xf4\x25\xc3\xf7\xed\xba\xa5\x93\xbc\x78\x04\xfc\xc1\xf8\x29\xcf\x0b\x5c\xcd\x8b\x7d\xa9\x69\x58\xbb\x2d\xf9\xf4\xf5\xe8\x7f\xa8\xab\xb1\x90\x46\x63\x29\xd1\x07\x53\x1b\xfd\xab\xa8\x93\x7c\x5f\x65\xbf\xa3\x89\xd2\x7a\x0f\x99\xce\xee\x9f\x9b\x10\x76\x56\x61\xbb\x8d\x1f\x71\x14\x36\xf1\xa9\xfc\x18\xad\x1b\x8f\xcd\x74\xf1\x46\xf5\xbc\x29\xf6\xb6\x1b\x81\xe2\x36\xbb\x1d\x11\x19\xb8\x43\x37\x43\x45\xf5\x02\xeb\x89\x0d\x53\xd5\x3e\x95\x59\x8d\xf6\x0f\x59\x35\xf1\x2f\x5d\x8b\x92\xd7\x93\x81\xec\x44\x16\xd1\x67\x18\xf8\xc4\x0b\xe9\x3e\xe9\x6f\x5b\x43\x8d\xf1\x75\xc6\xb3\xa5\xea\xf9\x98\x4e\xf6\xc1\xe4\x99\x2c\x0f\xf1\xe0\xce\x71\x0f\xbc\x37\xd0\xde\xde\x6a\xad\x22\x24\x79\xe6\xee\xee\xae\x2e\x4a\xa4\x8d\x02\x4e\x2f\xf2\xa6\x03\x35\x5a\xc8\x8a\x7d\x89\x92\x07\x30\x69\x95\x3c\x48\x87\xb8\xb0\x64\xb6\xb4\xf8\x92\xd9\x12\x99\x8a\xa6\xcf\x67\xf8\xeb\xed\x2d\x27\x8c\x9d\x6a\x93\x00\x60\xda\x54\x73\x78\xa3\x39\xb1\x79\x30\x6d\x5a\x46\x60\x03\xe6\x32\x5d\x65\xad\x7e\x27\x1b\xf6\x91\x72\x67\x92\x3d\x20\x14\xa6\x5e\x6b\x63\x5b\xb2\x50\x98\xc2\x21\x43\x9d\x5f\xdf\x80\x02\x15\x97\x72\xef\x90\xa0\x65\xcc\x05\x0b\x9a\xbd\x02\x78\xd0\x91\xf2\x27\x7c\x3f\x51\xff\x99\xeb\x55\x16\x36\xd3\xfc\x1c\x02\xa6\xf3\x09\x84\xa9\xd6\xc7\xfe\x86\x2a\xcd\x32\x37\x21\xfd\xd4\x45\x6e\x86\x97\x5d\xb0\x0d\x9d\x30\xbc\xb7\xbb\x89\xb1\xe3\x3b\x44\x6b\x0e\xe1\xa8\xc5\x99\x06\xdb\xa6\xd3\xd5\x37\x2a\xfb\xeb\x2a\x3b\x3e\xe6\x68\x7f\x4a\xca\x3a\x6b\xf6\x4c\xf0\x6e\x56\xd8\x51\x39\x15\xb0\x65\x59\x5f\x9d\x68\x28\xd2\x23\x05\xc0\x07\x9c\xd7\x99\x04\x5e\x51\x3f\xe9\xf8\xcb\xe9\xbd\xe1\x2e\xdd\x24\x3c\x58\xbb\xf5\x3e\x87\xbf\xde\xfc\xfa\x19\x3c\x92\x3b\xf7\x23\x82\xf4\xf0\xee\xe3\xbb\xf5\x24\x6e\x3d\x89\x5b\x4f\xe2\xd6\x93\xb8\x17\x3d\x89\xe3\x67\x81\xd6\x63\xb4\xf5\x18\x6d\x3d\x46\x5b\x8f\xd1\xa0\xad\xf2\x9a\x3b\x1e\xc8\xfd\xc3\x72\xc7\xf6\xd6\x26\x51\xa1\x6b\xfa\xa4\x3f\xcd\xe2\x6f\x37\xdb\xf3\xe6\x60\xbb\xf5\x16\x1d\x3a\xda\xce\xd6\x27\x2b\xca\xd0\x87\xa2\x40\x6f\x94\x17\x69\x02\x85\x73\xf4\xf9\x62\x0f\x1d\x63\x37\x0a\xfc\x18\x3b\x37\xba\xc7\x9f\x37\x27\x7c\x38\x14\xa0\xc7\x66\x0d\x2f\x00\x6d\xba\x27\xe1\x00\xec\x59\x24\x1c\x5c\x64\x55\x5d\x66\xf7\xb8\x46\x50\x0a\xa7\xd7\x3a\xb7\x1b\x51\x59\x1e\xe2\x79\xf6\x33\xf0\x6c\x87\x63\x86\xc4\xc0\x95\x32\x59\x97\x0d\xd9\x28\xe6\x29\xc9\xea\x3d\xfa\x89\x8e\x50\x64\xbc\x60\xb3\xb0\xa1\x87\x0a\x7a\xe8\x2a\x23\xaa\x9e\xab\x1a\x1d\x1a\x4c\xd9\xb1\x46\xe5\x31\xc9\x9b\x64\x34\x41\x5b\x8d\xdc\x74\xd3\x81\x34\x5d\x0a\xf6\x9c\x16\xd5\x3e\x7d\xf0\xb5\x65\x88\x59\x66\xf4\x94\x72\x11\x9f\x3b\x2c\x40\xbc\xb3\xf4\xcd\x32\x98\x65\xf1\x44\x48\xe5\x3b\x45\xc1\xc5\x3a\xe8\x75\x11\x56\x96\xce\x5a\xb4\x04\x0a\xfe\xcb\x2f\x16\x00\xcb\x93\x3a\xfd\xb6\x10\x1b\x1d\x83\x0b\x8f\xb5\x2e\x59\x98\xbd\x60\x64\x09\x4c\x16\x7f\xf0\x60\xb2\x56\x21\xcc\xb3\xf7\x84\x51\xc0\x44\xc7\x43\x2c\x4a\xbf\xce\x10\xdd\x25\x43\x4e\x89\x6e\x61\x11\x84\x0c\xb7\x49\x00\xe2\xf0\x5c\x76\x40\xf4\x5d\x9c\xdd\xd0\x1c\xcf\xcd\xc2\x95\x65\x37\x55\xcc\x1d\xd3\x71\x30\xf3\x99\x6e\x0e\xf3\x94\xdf\xba\xc0\x57\x1d\xe8\x88\xeb\x38\x68\xf9\x5c\x37\xb3\x0d\x15\x11\x9c\xf2\x3a\x28\xf8\x2b\x00\x20\x3b\x31\xb2\x39\x86\x53\x05\xd7\xb0\x1d\x07\x1f\x87\xed\xe6\xad\x69\x9e\xe3\x54\x81\x36\x7c\xc7\x01\xca\xe1\x3b\xce\xee\x8b\x87\x49\xbe\x48\xa2\x4d\xd8\x46\x81\xd7\x9e\x83\x08\x6a\x42\x6e\x14\xe2\xbe\xfe\x90\xfd\x90\xb9\x3f\x24\x3b\x1f\xef\x97\x7d\x0c\xd3\xe7\xda\xb8\xcc\x04\x1d\x59\x45\x09\x14\xd2\xf3\x7b\xc8\xb8\x36\x33\xf4\x43\x3e\x50\x6b\x13\xdd\xb4\x4f\x38\xa0\x7b\x11\x3e\x17\xfe\x03\x9a\x83\x0f\xf5\x10\xb8\xbc\xf9\x8a\x99\xb5\xfc\xe8\x0f\x2c\x3f\xf2\x3f\x7c\x21\x9b\x78\x87\xac\x12\x8b\x4e\xd0\x70\x1d\x09\x9d\x08\xbe\xd7\x4c\xb4\xb8\xdf\xa7\x27\xbc\x3f\xa1\x32\x45\xa3\xa5\x43\x9e\x97\xe3\xfc\xdb\x9b\xbf\x0d\x52\x0b\x5c\x01\x40\x18\xb3\x0b\xe8\x36\xd6\x70\xda\x68\xc2\xf2\x2c\x77\xf4\x6d\xdb\x09\xdb\xcd\xaf\xed\x05\x72\xd5\xa1\xbc\x81\xad\x20\xda\xca\x0c\xdf\x69\xe2\x80\x0e\x45\xf9\x0c\x2a\xa3\x69\xc2\x55\xf2\x28\x54\x88\x60\x6e\x1c\xcd\xbc\x0f\xdf\xd3\x13\xe4\xc5\x9a\x50\x19\xa8\x99\xf3\x01\x1d\x2a\xf2\x15\x70\xca\xed\x78\xa3\x46\x70\xda\xf2\xb2\x27\x29\xdb\x53\x4a\x73\x17\x86\x1d\x63\x43\x27\x11\x90\x65\x04\xf4\x53\x57\x65\x80\xfe\x50\xec\xeb\x12\x3e\x94\x84\x6a\xa7\x24\xfd\x8e\x48\x3c\x3a\xcd\x87\x2b\xb8\x75\x26\xbe\x8f\x5e\x4d\x7c\x81\x27\x51\x7a\x81\x25\xdc\x75\x2b\x77\xaa\x2f\x20\xf0\x30\x2c\xe2\xd2\x23\x9a\xf5\xec\x47\x97\x1b\xd7\x12\xbd\x89\xfb\xe7\x1a\x0d\xfd\x91\x62\xa1\x06\xf0\x6e\x80\xc2\x05\xf8\xad\x88\x5e\x09\xb7\x2e\x03\x78\x1b\x92\x02\x3b\xa5\xc3\x2f\x61\x5c\x86\xd1\xd7\xbf\x5c\x35\x86\xbd\xb5\x58\x5e\x4f\x6f\xbd\x9f\x1d\x1a\x6e\x8c\x6d\x57\x57\xaa\x19\x95\x1c\xa6\x25\xb8\x13\x3a\xa2\x87\x7d\x8a\xcb\xaa\x28\x2b\xe8\x94\xef\x84\x8e\x6d\xf3\xd0\xd8\x47\x14\x27\x27\xb8\xeb\x0e\x55\x1a\x88\xca\xd9\x5f\xaa\x0e\x61\xbd\x31\xb3\xde\x98\xe1\x42\x5b\x6f\xcc\xac\x37\x66\x5e\xf3\x8d\x99\xf5\x42\xc2\x7a\x21\xe1\xaf\x79\x21\xe1\xff\xab\xba\xff\x15\x5e\xaa\x58\x7c\x21\xa1\xbf\xe0\xfb\x63\x00\x29\x6c\xb5\x43\x5d\xa6\x16\x60\x98\x2d\x89\xa8\xad\xed\x2e\xe2\x1e\xfe\x9c\xf7\xb2\x4c\x05\x34\xab\x5d\xe1\x34\x85\xea\x30\x71\x9a\xa2\xaa\x52\x88\x36\x78\xb8\xac\x9d\xb1\x21\xf1\xc7\x16\x98\xaa\x00\xd7\xd7\x24\x83\x0a\x1b\xc8\x63\x35\x12\x9c\x53\x38\xef\xd5\x4d\x03\x10\x60\x6e\x97\x1f\x59\xf5\xd5\xd5\x1f\x46\x22\xf3\x06\xa9\xeb\x7c\x84\x31\x5c\xea\xa3\xa7\xd2\x2b\x5d\x8c\xeb\xd2\x8b\xfa\x6b\x29\xfd\x2b\x2f\xa5\xef\xef\x3f\x81\xd7\xce\x72\x8a\xfa\x8d\xcb\x36\xb1\xc4\x0d\x6d\x0c\xf6\x5c\x66\xbf\x7a\xeb\xd1\x24\x01\x75\xa8\x9c\xcb\x21\x5d\xe6\x50\x21\xdb\x47\x7c\x84\x6e\x78\xdc\x70\x82\xc5\x0f\x67\xab\xc2\xd5\xe8\x60\x88\xb6\x0f\xf4\xf7\xde\xe3\xbd\xe9\x73\x99\x9c\xd6\x93\xce\x91\xdb\xd4\xc3\xf1\x05\xb3\x0e\x72\x92\xdd\x5d\x68\x9f\x93\x39\xa6\xce\x7c\x26\x3d\x4a\xa1\x7f\xeb\x86\x3f\xe4\x90\xe4\x3f\x45\xb9\xff\x5a\x22\xf4\x3b\xda\xd7\x65\xf6\xf8\x78\x2e\x3a\x6c\x97\x52\xff\x99\x50\x78\x97\xd9\x24\x31\x4e\x9e\x1d\xb2\x1a\xe6\x2b\xda\x34\x8c\xd1\x7a\x4f\x06\x32\x86\xf9\xd5\xf5\xca\x9f\xb6\x5e\xf9\x5b\xaf\xfc\xad\x57\xfe\x5e\xf6\xca\x5f\xe7\x9e\x94\xf7\xb3\x96\x63\x39\xe2\x01\x9a\xa9\xdc\xd3\xf0\x2c\x4d\xd2\x6f\x6c\x36\xfb\xc3\xfd\x60\x42\xbd\x76\x49\xa2\xa7\x95\xa5\x12\x92\xcb\xe2\x49\x20\xf7\xdc\x2a\xe9\xd8\x78\x55\xad\xf3\x38\x4e\x79\x72\x14\x00\xe9\x9a\x65\x90\xf8\x79\xf1\xa8\x49\x89\xa5\xbb\x40\xbe\xd8\xae\x59\x46\xec\x7d\x5e\x14\x07\xed\x6b\x96\xd7\xa8\x94\x13\x4f\xbf\xb1\x67\xdf\x10\xbf\xfe\x51\x37\x19\x38\x79\x91\x26\xe4\x4f\x39\x28\x6d\x6f\x01\x8c\x61\x17\xbe\x43\x16\x1a\xcd\x8c\x81\x99\x4e\x70\x2e\x2f\x90\x3b\x9b\x07\xcd\x0c\x1c\x06\x30\xb6\x6f\x59\xbd\x2f\xc9\xa4\xa4\xcc\xad\x3d\xac\x95\xb2\x37\x11\x84\xce\xea\x60\x00\xb0\xdd\xf1\xc5\x4b\x19\x9e\x08\x50\xcf\xfc\x60\x44\x1c\x03\xe4\x41\x82\x2c\x50\x24\xbf\x67\x87\xb0\x7c\x8e\x25\xf2\xe4\x8b\x4c\x71\x66\x6d\x8c\x0d\x92\xbb\x44\x44\x26\xc9\xc3\xc5\xb3\x49\x11\xa6\x91\x65\xc2\x78\x04\xb6\x39\xa9\xac\x98\x93\x2c\x36\xd1\x41\x61\x95\x62\x56\x6a\x62\xa8\xa2\xc1\x00\x73\x2d\xd1\x8f\x7d\x7f\xa3\x35\x63\xae\xf2\xd6\x2a\x81\xa3\xb3\x59\x18\x05\xc7\x66\xa5\xed\x43\x02\x42\xcf\x4a\x60\x0c\x3c\x2b\x51\x36\x12\xb9\xf7\x32\x36\x15\xee\xeb\x11\x9a\x8a\x92\xa5\x48\x00\x1b\xd9\x0b\x0c\x4a\x64\x2f\x02\x73\xe1\x8b\xef\xea\x96\x84\x09\x8e\xf3\xaf\x7b\xef\x6f\x7f\x0b\x3f\xfd\xf6\x36\xfc\xf7\xe4\x37\x05\xfc\x1c\x57\xe4\x8d\xdc\xfe\x44\xe5\xcf\x0c\x3d\xf5\x07\xdf\xd9\xa9\x1d\x63\xe7\x6b\x62\x76\xe5\x00\x5f\x1f\x62\x6c\xef\x5c\x12\xbc\xef\x52\xa9\x1c\xca\x6b\xfc\xed\x81\x1f\x18\x95\xcf\x52\x59\xaa\x57\x73\x81\x9a\x4d\x49\x36\xf3\xfa\xe7\xf9\x11\xd4\xf6\xc8\xe8\x2f\x5f\x0f\xd0\x15\x48\xc8\x2c\x80\x3f\xf9\x4f\x42\x2a\x5d\xb2\x7d\x3d\x17\x84\x94\x4e\x57\x64\xee\x0b\xfc\x37\x00\x00\xff\xff\x36\x08\x32\x4d\x20\x62\x00\x00") func internalAssetsMetric_zh_cnYamlBytes() ([]byte, error) { return bindataRead( @@ -134,7 +134,7 @@ func internalAssetsMetric_zh_cnYaml() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "internal/assets/metric_zh_CN.yaml", size: 25073, mode: os.FileMode(420), modTime: time.Unix(1708935041, 0)} + info := bindataFileInfo{name: "internal/assets/metric_zh_CN.yaml", size: 25120, mode: os.FileMode(420), modTime: time.Unix(1710924046, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -200,13 +200,11 @@ var _bindata = map[string]func() (*asset, error){ // directory embedded in the file by go-bindata. // For example if you run go-bindata on data/... and data contains the // following hierarchy: -// -// data/ -// foo.txt -// img/ -// a.png -// b.png -// +// data/ +// foo.txt +// img/ +// a.png +// b.png // then AssetDir("data") would return []string{"foo.txt", "img"} // AssetDir("data/img") would return []string{"a.png", "b.png"} // AssetDir("foo.txt") and AssetDir("notexist") would return an error diff --git a/internal/dashboard/generated/swagger/docs.go b/internal/dashboard/generated/swagger/docs.go index 680f7f72b..658679a02 100644 --- a/internal/dashboard/generated/swagger/docs.go +++ b/internal/dashboard/generated/swagger/docs.go @@ -38,7 +38,8 @@ const docTemplate = `{ { "enum": [ "OBCLUSTER", - "OBTENANT" + "OBTENANT", + "OBBACKUPPOLICY" ], "type": "string", "description": "related object types", @@ -1242,14 +1243,14 @@ const docTemplate = `{ } } }, - "/api/v1/obclusters/{namespace}/{name}/essential-parameters": { + "/api/v1/obclusters/{namespace}/{name}/resource-usages": { "get": { "security": [ { "ApiKeyAuth": [] } ], - "description": "list essential parameters of specific obcluster", + "description": "list resource usages of specific obcluster, such as cpu, memory, storage, etc. The old router ending with /essential-parameters is deprecated", "consumes": [ "application/json" ], @@ -1259,7 +1260,7 @@ const docTemplate = `{ "tags": [ "OBCluster" ], - "summary": "list essential parameters", + "summary": "list resource usages, the old router ending with /essential-parameters is deprecated", "operationId": "ListOBClusterResources", "parameters": [ { @@ -3790,6 +3791,12 @@ const docTemplate = `{ "type": "string", "example": "NFS" }, + "events": { + "type": "array", + "items": { + "$ref": "#/definitions/response.K8sEvent" + } + }, "jobKeepDays": { "type": "integer", "example": 5 @@ -3859,10 +3866,10 @@ const docTemplate = `{ "type": "integer" }, "firstOccur": { - "type": "number" + "type": "integer" }, "lastSeen": { - "type": "number" + "type": "integer" }, "message": { "type": "string" @@ -3949,7 +3956,7 @@ const docTemplate = `{ "type": "string" }, "uptime": { - "type": "number" + "type": "integer" }, "version": { "type": "string" diff --git a/internal/dashboard/generated/swagger/swagger.json b/internal/dashboard/generated/swagger/swagger.json index 0dcaad7cb..56476bfde 100644 --- a/internal/dashboard/generated/swagger/swagger.json +++ b/internal/dashboard/generated/swagger/swagger.json @@ -31,7 +31,8 @@ { "enum": [ "OBCLUSTER", - "OBTENANT" + "OBTENANT", + "OBBACKUPPOLICY" ], "type": "string", "description": "related object types", @@ -1235,14 +1236,14 @@ } } }, - "/api/v1/obclusters/{namespace}/{name}/essential-parameters": { + "/api/v1/obclusters/{namespace}/{name}/resource-usages": { "get": { "security": [ { "ApiKeyAuth": [] } ], - "description": "list essential parameters of specific obcluster", + "description": "list resource usages of specific obcluster, such as cpu, memory, storage, etc. The old router ending with /essential-parameters is deprecated", "consumes": [ "application/json" ], @@ -1252,7 +1253,7 @@ "tags": [ "OBCluster" ], - "summary": "list essential parameters", + "summary": "list resource usages, the old router ending with /essential-parameters is deprecated", "operationId": "ListOBClusterResources", "parameters": [ { @@ -3783,6 +3784,12 @@ "type": "string", "example": "NFS" }, + "events": { + "type": "array", + "items": { + "$ref": "#/definitions/response.K8sEvent" + } + }, "jobKeepDays": { "type": "integer", "example": 5 @@ -3852,10 +3859,10 @@ "type": "integer" }, "firstOccur": { - "type": "number" + "type": "integer" }, "lastSeen": { - "type": "number" + "type": "integer" }, "message": { "type": "string" @@ -3942,7 +3949,7 @@ "type": "string" }, "uptime": { - "type": "number" + "type": "integer" }, "version": { "type": "string" diff --git a/internal/dashboard/generated/swagger/swagger.yaml b/internal/dashboard/generated/swagger/swagger.yaml index 71fb6533a..8e17022fe 100644 --- a/internal/dashboard/generated/swagger/swagger.yaml +++ b/internal/dashboard/generated/swagger/swagger.yaml @@ -720,6 +720,10 @@ definitions: description: 'Enum: NFS, OSS' example: NFS type: string + events: + items: + $ref: '#/definitions/response.K8sEvent' + type: array jobKeepDays: example: 5 type: integer @@ -774,9 +778,9 @@ definitions: count: type: integer firstOccur: - type: number + type: integer lastSeen: - type: number + type: integer message: type: string namespace: @@ -833,7 +837,7 @@ definitions: status: type: string uptime: - type: number + type: integer version: type: string type: object @@ -1358,6 +1362,7 @@ paths: enum: - OBCLUSTER - OBTENANT + - OBBACKUPPOLICY in: query name: objectType type: string @@ -1806,11 +1811,12 @@ paths: summary: create obcluster tags: - OBCluster - /api/v1/obclusters/{namespace}/{name}/essential-parameters: + /api/v1/obclusters/{namespace}/{name}/resource-usages: get: consumes: - application/json - description: list essential parameters of specific obcluster + description: list resource usages of specific obcluster, such as cpu, memory, + storage, etc. The old router ending with /essential-parameters is deprecated operationId: ListOBClusterResources parameters: - description: obcluster namespace @@ -1849,7 +1855,8 @@ paths: $ref: '#/definitions/response.APIResponse' security: - ApiKeyAuth: [] - summary: list essential parameters + summary: list resource usages, the old router ending with /essential-parameters + is deprecated tags: - OBCluster /api/v1/obclusters/namespace/{namespace}/name/{name}: diff --git a/internal/dashboard/handler/info_handler.go b/internal/dashboard/handler/info_handler.go index e124a46b4..4e6260704 100644 --- a/internal/dashboard/handler/info_handler.go +++ b/internal/dashboard/handler/info_handler.go @@ -18,12 +18,13 @@ import ( "time" "github.com/gin-gonic/gin" + logger "github.com/sirupsen/logrus" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "github.com/oceanbase/ob-operator/api/v1alpha1" + "github.com/oceanbase/ob-operator/internal/clients" "github.com/oceanbase/ob-operator/internal/dashboard/model/response" - "github.com/oceanbase/ob-operator/internal/oceanbase" "github.com/oceanbase/ob-operator/internal/telemetry" "github.com/oceanbase/ob-operator/internal/telemetry/models" crypto "github.com/oceanbase/ob-operator/pkg/crypto" @@ -74,7 +75,7 @@ func GetProcessInfo(_ *gin.Context) (*response.DashboardInfo, error) { func GetStatistics(c *gin.Context) (*response.StatisticDataResponse, error) { reportData := response.StatisticData{} clusterList := v1alpha1.OBClusterList{} - err := oceanbase.ClusterClient.List(c, corev1.NamespaceAll, &clusterList, metav1.ListOptions{}) + err := clients.ClusterClient.List(c, corev1.NamespaceAll, &clusterList, metav1.ListOptions{}) if err != nil { return nil, httpErr.NewInternal(err.Error()) } @@ -85,7 +86,7 @@ func GetStatistics(c *gin.Context) (*response.StatisticDataResponse, error) { } zoneList := v1alpha1.OBZoneList{} - err = oceanbase.ZoneClient.List(c, corev1.NamespaceAll, &zoneList, metav1.ListOptions{}) + err = clients.ZoneClient.List(c, corev1.NamespaceAll, &zoneList, metav1.ListOptions{}) if err != nil { return nil, httpErr.NewInternal(err.Error()) } @@ -96,7 +97,7 @@ func GetStatistics(c *gin.Context) (*response.StatisticDataResponse, error) { } serverList := v1alpha1.OBServerList{} - err = oceanbase.ServerClient.List(c, corev1.NamespaceAll, &serverList, metav1.ListOptions{}) + err = clients.ServerClient.List(c, corev1.NamespaceAll, &serverList, metav1.ListOptions{}) if err != nil { return nil, httpErr.NewInternal(err.Error()) } @@ -107,7 +108,7 @@ func GetStatistics(c *gin.Context) (*response.StatisticDataResponse, error) { } tenantList := v1alpha1.OBTenantList{} - err = oceanbase.TenantClient.List(c, corev1.NamespaceAll, &tenantList, metav1.ListOptions{}) + err = clients.TenantClient.List(c, corev1.NamespaceAll, &tenantList, metav1.ListOptions{}) if err != nil { return nil, httpErr.NewInternal(err.Error()) } @@ -118,7 +119,7 @@ func GetStatistics(c *gin.Context) (*response.StatisticDataResponse, error) { } backupPolicyList := v1alpha1.OBTenantBackupPolicyList{} - err = oceanbase.BackupPolicyClient.List(c, corev1.NamespaceAll, &backupPolicyList, metav1.ListOptions{}) + err = clients.BackupPolicyClient.List(c, corev1.NamespaceAll, &backupPolicyList, metav1.ListOptions{}) if err != nil { return nil, httpErr.NewInternal(err.Error()) } @@ -151,7 +152,7 @@ func GetStatistics(c *gin.Context) (*response.StatisticDataResponse, error) { reportData.Version = Version currentTime := time.Now() - + logger.Debugf("Get statistic data: %+v", reportData) return &response.StatisticDataResponse{ Component: telemetry.TelemetryComponentDashboard, Time: currentTime.Format(time.DateTime), diff --git a/internal/dashboard/handler/k8s_handler.go b/internal/dashboard/handler/k8s_handler.go index f21d44c8f..81949071c 100644 --- a/internal/dashboard/handler/k8s_handler.go +++ b/internal/dashboard/handler/k8s_handler.go @@ -14,6 +14,7 @@ package handler import ( "github.com/gin-gonic/gin" + logger "github.com/sirupsen/logrus" "github.com/oceanbase/ob-operator/internal/dashboard/business/k8s" "github.com/oceanbase/ob-operator/internal/dashboard/model/param" @@ -27,7 +28,7 @@ import ( // @Tags Cluster // @Accept application/json // @Produce application/json -// @Param objectType query string false "related object types" Enums(OBCLUSTER, OBTENANT) +// @Param objectType query string false "related object types" Enums(OBCLUSTER, OBTENANT, OBBACKUPPOLICY) // @Param type query string false "event level" Enums(NORMAL, WARNING) // @Param name query string false "Object name" string // @Param namespace query string false "Namespace" string @@ -48,6 +49,7 @@ func ListK8sEvents(c *gin.Context) ([]response.K8sEvent, error) { if err != nil { return nil, err } + logger.Debugf("List k8s events: %v", events) return events, nil } @@ -68,6 +70,7 @@ func ListK8sNodes(_ *gin.Context) ([]response.K8sNode, error) { if err != nil { return nil, err } + logger.Debugf("List k8s nodes: %v", nodes) return nodes, nil } @@ -88,6 +91,7 @@ func ListK8sNamespaces(_ *gin.Context) ([]response.Namespace, error) { if err != nil { return nil, err } + logger.Debugf("List k8s namespaces: %v", namespaces) return namespaces, nil } @@ -108,6 +112,7 @@ func ListK8sStorageClasses(_ *gin.Context) ([]response.StorageClass, error) { if err != nil { return nil, err } + logger.Debugf("List k8s storage classes: %v", storageClasses) return storageClasses, nil } @@ -130,6 +135,7 @@ func CreateK8sNamespace(c *gin.Context) (any, error) { if err != nil { return nil, httpErr.NewBadRequest(err.Error()) } + logger.Infof("Create k8s namespace: %+v", param) err = k8s.CreateNamespace(param) if err != nil { return nil, err diff --git a/internal/dashboard/handler/metric_handler.go b/internal/dashboard/handler/metric_handler.go index 7f1926c5b..8a1f3c333 100644 --- a/internal/dashboard/handler/metric_handler.go +++ b/internal/dashboard/handler/metric_handler.go @@ -16,6 +16,7 @@ import ( "errors" "github.com/gin-gonic/gin" + logger "github.com/sirupsen/logrus" "github.com/oceanbase/ob-operator/internal/dashboard/business/metric" metricconst "github.com/oceanbase/ob-operator/internal/dashboard/business/metric/constant" @@ -49,6 +50,7 @@ func ListMetricMetas(c *gin.Context) ([]response.MetricClass, error) { if err != nil { return nil, err } + logger.Debugf("List metric classes: %+v", metricClasses) return metricClasses, nil } @@ -71,6 +73,8 @@ func QueryMetrics(c *gin.Context) ([]response.MetricData, error) { if err != nil { return nil, httpErr.NewBadRequest(err.Error()) } + logger.Infof("Query metric data with param: %+v", queryParam) metricDatas := metric.QueryMetricData(queryParam) + logger.Debugf("Query metric data: %+v", metricDatas) return metricDatas, nil } diff --git a/internal/dashboard/handler/obcluster_handler.go b/internal/dashboard/handler/obcluster_handler.go index b24ba503c..b5188d141 100644 --- a/internal/dashboard/handler/obcluster_handler.go +++ b/internal/dashboard/handler/obcluster_handler.go @@ -35,11 +35,11 @@ import ( // @Failure 500 object response.APIResponse // @Router /api/v1/obclusters/statistic [GET] func GetOBClusterStatistic(c *gin.Context) ([]response.OBClusterStastistic, error) { - // return mock data obclusterStastics, err := oceanbase.GetOBClusterStatistic(c) if err != nil { return nil, err } + logger.Debugf("Get obcluster statistic: %v", obclusterStastics) return obclusterStastics, nil } @@ -60,6 +60,7 @@ func ListOBClusters(c *gin.Context) ([]response.OBClusterOverview, error) { if err != nil { return nil, err } + logger.Debugf("List obclusters: %v", obclusters) return obclusters, nil } @@ -87,6 +88,7 @@ func GetOBCluster(c *gin.Context) (*response.OBCluster, error) { if err != nil { return nil, err } + logger.Debugf("Get obcluster: %v", obcluster) return obcluster, nil } @@ -113,7 +115,7 @@ func CreateOBCluster(c *gin.Context) (any, error) { if err != nil { return nil, httpErr.NewBadRequest(err.Error()) } - logger.Debugf("Create obcluster: %v", param) + logger.Infof("Create obcluster with param: %+v", param) err = oceanbase.CreateOBCluster(c, param) if err != nil { return nil, err @@ -147,6 +149,7 @@ func UpgradeOBCluster(c *gin.Context) (any, error) { if err != nil { return nil, httpErr.NewBadRequest(err.Error()) } + logger.Infof("Upgrade obcluster with param: %+v", updateParam) err = oceanbase.UpgradeObCluster(c, obclusterIdentity, updateParam) if err != nil { return nil, err @@ -207,6 +210,7 @@ func AddOBZone(c *gin.Context) (any, error) { if err != nil { return nil, httpErr.NewBadRequest(err.Error()) } + logger.Infof("Add obzone with param: %+v", param) err = oceanbase.AddOBZone(c, obclusterIdentity, param) if err != nil { return nil, err @@ -241,6 +245,7 @@ func ScaleOBServer(c *gin.Context) (any, error) { if err != nil { return nil, httpErr.NewBadRequest(err.Error()) } + logger.Infof("Scale observer with param: %+v", scaleParam) err = oceanbase.ScaleOBServer(c, obzoneIdentity, scaleParam) if err != nil { return nil, err @@ -277,8 +282,8 @@ func DeleteOBZone(c *gin.Context) (any, error) { } // @ID ListOBClusterResources -// @Summary list essential parameters -// @Description list essential parameters of specific obcluster +// @Summary list resource usages, the old router ending with /essential-parameters is deprecated +// @Description list resource usages of specific obcluster, such as cpu, memory, storage, etc. The old router ending with /essential-parameters is deprecated // @Tags OBCluster // @Accept application/json // @Produce application/json @@ -288,7 +293,7 @@ func DeleteOBZone(c *gin.Context) (any, error) { // @Failure 400 object response.APIResponse // @Failure 401 object response.APIResponse // @Failure 500 object response.APIResponse -// @Router /api/v1/obclusters/{namespace}/{name}/essential-parameters [GET] +// @Router /api/v1/obclusters/{namespace}/{name}/resource-usages [GET] // @Security ApiKeyAuth func ListOBClusterResources(c *gin.Context) (*response.OBClusterResources, error) { obclusterIdentity := ¶m.K8sObjectIdentity{} @@ -296,5 +301,10 @@ func ListOBClusterResources(c *gin.Context) (*response.OBClusterResources, error if err != nil { return nil, httpErr.NewBadRequest(err.Error()) } - return oceanbase.GetOBClusterEssentialParameters(c, obclusterIdentity) + usages, err := oceanbase.GetOBClusterUsages(c, obclusterIdentity) + if err != nil { + return nil, err + } + logger.Debugf("Get resource usages of obcluster: %v", obclusterIdentity) + return usages, nil } diff --git a/internal/dashboard/handler/obtenant_handler.go b/internal/dashboard/handler/obtenant_handler.go index 175fe8ae3..cb42c60c8 100644 --- a/internal/dashboard/handler/obtenant_handler.go +++ b/internal/dashboard/handler/obtenant_handler.go @@ -66,6 +66,7 @@ func ListAllTenants(c *gin.Context) ([]*response.OBTenantOverview, error) { } } } + logger.Debugf("List all tenants: %+v", tenants) return tenants, nil } @@ -99,6 +100,7 @@ func GetTenant(c *gin.Context) (*response.OBTenantDetail, error) { } return nil, httpErr.NewInternal(err.Error()) } + logger.Debugf("Get obtenant: %+v", tenant) return tenant, nil } @@ -121,7 +123,6 @@ func CreateTenant(c *gin.Context) (*response.OBTenantDetail, error) { if err != nil { return nil, httpErr.NewBadRequest(err.Error()) } - logger.Infof("Create obtenant: %+v", tenantParam) tenantParam.RootPassword, err = crypto.DecryptWithPrivateKey(tenantParam.RootPassword) if err != nil { return nil, httpErr.NewBadRequest(err.Error()) @@ -144,6 +145,7 @@ func CreateTenant(c *gin.Context) (*response.OBTenantDetail, error) { } } } + logger.Infof("Create obtenant with param: %+v", tenantParam) tenant, err := oceanbase.CreateOBTenant(c, types.NamespacedName{ Namespace: tenantParam.Namespace, Name: tenantParam.Name, @@ -151,6 +153,7 @@ func CreateTenant(c *gin.Context) (*response.OBTenantDetail, error) { if err != nil { return nil, httpErr.NewInternal(err.Error()) } + logger.Debugf("Create obtenant: %+v", tenant) return tenant, nil } @@ -216,6 +219,7 @@ func PatchTenant(c *gin.Context) (*response.OBTenantDetail, error) { if patch.UnitNumber == nil && patch.UnitConfig == nil { return nil, httpErr.NewBadRequest("unitNumber or unitConfig is required") } + logger.Infof("Patch obtenant with param: %+v", patch) tenant, err := oceanbase.PatchTenant(c, types.NamespacedName{ Namespace: nn.Namespace, Name: nn.Name, @@ -223,6 +227,7 @@ func PatchTenant(c *gin.Context) (*response.OBTenantDetail, error) { if err != nil { return nil, err } + logger.Debugf("Patch obtenant: %+v", tenant) return tenant, nil } @@ -255,6 +260,7 @@ func ChangeUserPassword(c *gin.Context) (*response.OBTenantDetail, error) { if passwordParam.User != "root" { return nil, httpErr.NewBadRequest("only root user is supported") } + logger.Infof("Change obtenant root password with param: %+v", passwordParam) tenant, err := oceanbase.ModifyOBTenantRootPassword(c, types.NamespacedName{ Namespace: nn.Namespace, Name: nn.Name, @@ -263,6 +269,7 @@ func ChangeUserPassword(c *gin.Context) (*response.OBTenantDetail, error) { if err != nil { return nil, httpErr.NewInternal(err.Error()) } + logger.Debugf("Change obtenant root password: %+v", tenant) return tenant, nil } @@ -295,6 +302,7 @@ func ReplayStandbyLog(c *gin.Context) (*response.OBTenantDetail, error) { if !logReplayParam.Unlimited && logReplayParam.Timestamp == nil { return nil, httpErr.NewBadRequest("timestamp is required if the restore is limited") } + logger.Infof("Replay standby log with param: %+v", logReplayParam) tenant, err := oceanbase.ReplayStandbyLog(c, types.NamespacedName{ Name: nn.Name, Namespace: nn.Namespace, @@ -302,6 +310,7 @@ func ReplayStandbyLog(c *gin.Context) (*response.OBTenantDetail, error) { if err != nil { return nil, httpErr.NewInternal(err.Error()) } + logger.Debugf("Replay standby log: %+v", tenant) return tenant, nil } @@ -332,6 +341,7 @@ func UpgradeTenantVersion(c *gin.Context) (*response.OBTenantDetail, error) { if err != nil { return nil, httpErr.NewInternal(err.Error()) } + logger.Debugf("Upgrade tenant version: %+v", tenant) return tenant, nil } @@ -364,6 +374,7 @@ func ChangeTenantRole(c *gin.Context) (*response.OBTenantDetail, error) { if !p.Failover != p.Switchover { return nil, httpErr.NewBadRequest("one and only one of failover and switchover can be true") } + logger.Infof("Change tenant role with param: %+v", p) tenant, err := oceanbase.ChangeTenantRole(c, types.NamespacedName{ Name: nn.Name, Namespace: nn.Namespace, @@ -371,6 +382,7 @@ func ChangeTenantRole(c *gin.Context) (*response.OBTenantDetail, error) { if err != nil { return nil, err } + logger.Debugf("Change tenant role: %+v", tenant) return tenant, nil } @@ -416,6 +428,7 @@ func CreateBackupPolicy(c *gin.Context) (*response.BackupPolicy, error) { return nil, httpErr.NewBadRequest(err.Error()) } } + logger.Infof("Create backup policy with param: %+v", createPolicyParam) policy, err := oceanbase.CreateTenantBackupPolicy(c, types.NamespacedName{ Name: nn.Name, Namespace: nn.Namespace, @@ -423,6 +436,7 @@ func CreateBackupPolicy(c *gin.Context) (*response.BackupPolicy, error) { if err != nil { return nil, err } + logger.Debugf("Create backup policy: %+v", policy) return policy, nil } @@ -452,6 +466,7 @@ func UpdateBackupPolicy(c *gin.Context) (*response.BackupPolicy, error) { if err != nil { return nil, httpErr.NewBadRequest(err.Error()) } + logger.Infof("Update backup policy with param: %+v", updatePolicyParam) policy, err := oceanbase.UpdateTenantBackupPolicy(c, types.NamespacedName{ Name: nn.Name, Namespace: nn.Namespace, @@ -459,6 +474,7 @@ func UpdateBackupPolicy(c *gin.Context) (*response.BackupPolicy, error) { if err != nil { return nil, err } + logger.Debugf("Update backup policy: %+v", policy) return policy, nil } @@ -520,6 +536,7 @@ func GetBackupPolicy(c *gin.Context) (*response.BackupPolicy, error) { if err != nil { return nil, httpErr.NewInternal(err.Error()) } + logger.Debugf("Get backup policy: %+v", policy) return policy, nil } @@ -564,6 +581,7 @@ func ListBackupJobs(c *gin.Context) ([]*response.BackupJob, error) { if err != nil { return nil, httpErr.NewInternal(err.Error()) } + logger.Debugf("List backup jobs: %+v", jobs) return jobs, nil } @@ -584,6 +602,7 @@ func GetOBTenantStatistic(c *gin.Context) ([]response.OBTenantStatistic, error) if err != nil { return nil, err } + logger.Debugf("Get obtenant statistics: %+v", tenants) return tenants, nil } @@ -612,7 +631,7 @@ func CreateOBTenantPool(c *gin.Context) (bool, error) { if err != nil { return false, httpErr.NewBadRequest(err.Error()) } - + logger.Infof("Create obtenant pool with param: %+v", p) return oceanbase.CreateTenantPool(c, nn, &p) } @@ -663,6 +682,6 @@ func PatchOBTenantPool(c *gin.Context) (bool, error) { if err != nil { return false, httpErr.NewBadRequest(err.Error()) } - + logger.Infof("Patch obtenant pool with param: %+v", p) return oceanbase.PatchTenantPool(c, nn, &p) } diff --git a/internal/dashboard/middleware/logging.go b/internal/dashboard/middleware/logging.go index c56ae14ec..8ec1645f0 100644 --- a/internal/dashboard/middleware/logging.go +++ b/internal/dashboard/middleware/logging.go @@ -46,12 +46,16 @@ func Logging() gin.HandlerFunc { // Request ID requestID := requestid.Get(ctx) + // Query + query := ctx.Request.URL.Query() + log.WithFields(log.Fields{ "METHOD": reqMethod, - "REQUEST_URI": reqUri, "STATUS": statusCode, "LATENCY": latencyTime, "REQUEST_ID": requestID, + "REQUEST_URI": reqUri, + "QUERY": query, }).Info("[HTTP REQUEST]") ctx.Next() diff --git a/internal/dashboard/model/response/backup.go b/internal/dashboard/model/response/backup.go index 235b2b0be..f27a0f45c 100644 --- a/internal/dashboard/model/response/backup.go +++ b/internal/dashboard/model/response/backup.go @@ -12,7 +12,9 @@ See the Mulan PSL v2 for more details. package response -import "github.com/oceanbase/ob-operator/internal/dashboard/model/param" +import ( + "github.com/oceanbase/ob-operator/internal/dashboard/model/param" +) type BackupPolicy struct { param.BackupPolicyBase `json:",inline"` @@ -24,7 +26,8 @@ type BackupPolicy struct { OSSAccessSecret string `json:"ossAccessSecret,omitempty"` BakEncryptionSecret string `json:"bakEncryptionSecret,omitempty"` - CreateTime string `json:"createTime"` + CreateTime string `json:"createTime"` + Events []K8sEvent `json:"events"` } type BackupJob struct { diff --git a/internal/dashboard/model/response/k8s.go b/internal/dashboard/model/response/k8s.go index 51aec3f5c..896229441 100644 --- a/internal/dashboard/model/response/k8s.go +++ b/internal/dashboard/model/response/k8s.go @@ -15,14 +15,14 @@ package response import "github.com/oceanbase/ob-operator/internal/dashboard/model/common" type K8sEvent struct { - Namespace string `json:"namespace"` - Type string `json:"type"` - Count int32 `json:"count"` - FirstOccur float64 `json:"firstOccur"` - LastSeen float64 `json:"lastSeen"` - Reason string `json:"reason"` - Object string `json:"object"` - Message string `json:"message"` + Namespace string `json:"namespace"` + Type string `json:"type"` + Count int32 `json:"count"` + FirstOccur int64 `json:"firstOccur"` + LastSeen int64 `json:"lastSeen"` + Reason string `json:"reason"` + Object string `json:"object"` + Message string `json:"message"` } type K8sNodeCondition struct { @@ -37,7 +37,7 @@ type K8sNodeInfo struct { Conditions []K8sNodeCondition `json:"conditions"` Roles []string `json:"roles"` Labels []common.KVPair `json:"labels"` - Uptime float64 `json:"uptime"` + Uptime int64 `json:"uptime"` Version string `json:"version"` InternalIP string `json:"internalIP"` ExternalIP string `json:"externalIP"` diff --git a/internal/dashboard/router/v1/obcluster_router.go b/internal/dashboard/router/v1/obcluster_router.go index 1d5a09474..be8e9c0be 100644 --- a/internal/dashboard/router/v1/obcluster_router.go +++ b/internal/dashboard/router/v1/obcluster_router.go @@ -28,5 +28,5 @@ func InitOBClusterRoutes(g *gin.RouterGroup) { g.POST("/obclusters/namespace/:namespace/name/:name/obzones", h.Wrap(h.AddOBZone)) g.POST("/obclusters/namespace/:namespace/name/:name/obzones/:obzoneName/scale", h.Wrap(h.ScaleOBServer)) g.DELETE("/obclusters/namespace/:namespace/name/:name/obzones/:obzoneName", h.Wrap(h.DeleteOBZone)) - g.GET("/obclusters/:namespace/:name/essential-parameters", h.Wrap(h.ListOBClusterResources)) + g.GET("/obclusters/:namespace/:name/resource-usages", h.Wrap(h.ListOBClusterResources)) } diff --git a/ui/README.md b/ui/README.md deleted file mode 100644 index 3dab1f372..000000000 --- a/ui/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# README - -`@umijs/max` 模板项目,更多功能参考 [Umi Max 简介](https://umijs.org/docs/max/introduce)