From 14979480e3aa5d7ee4ba790a522cee4786125615 Mon Sep 17 00:00:00 2001 From: Qu Xuan Date: Thu, 4 Feb 2021 17:38:24 +0800 Subject: [PATCH] fix(logger): distinct field optimized for logger --- pkg/apis/list.go | 26 ++ pkg/apis/logger/input.go | 8 + pkg/cloudcommon/db/distinct_fields.go | 10 +- pkg/cloudcommon/db/fetch.go | 6 +- pkg/cloudcommon/db/opslog.go | 105 ++--- pkg/logger/models/actionlog.go | 102 ++++- pkg/logger/models/initdb.go | 37 ++ pkg/logger/service/handlers.go | 1 + pkg/logger/service/service.go | 2 +- pkg/util/logclient/consts_i18n.go | 628 ++++++++++++++++++++++++++ 10 files changed, 862 insertions(+), 63 deletions(-) create mode 100644 pkg/logger/models/initdb.go diff --git a/pkg/apis/list.go b/pkg/apis/list.go index e969b23500..5835265c5d 100644 --- a/pkg/apis/list.go +++ b/pkg/apis/list.go @@ -14,6 +14,8 @@ package apis +import "time" + type ScopedResourceInput struct { // 指定查询的权限范围,可能值为project, domain or system Scope string `json:"scope"` @@ -323,3 +325,27 @@ type MultiArchResourceBaseListInput struct { type AutoDeleteResourceBaseListInput struct { AutoDelete *bool } + +type OpsLogListInput struct { + OwnerProjectIds []string `json:"owner_project_ids"` + OwnerDomainIds []string `json:"owner_domain_ids"` + + // filter by obj type + ObjTypes []string `json:"obj_type"` + + // filter by obj name or obj id + Objs []string `json:"obj"` + + // filter by obj ids + ObjIds []string `json:"obj_id"` + + // filter by obj name + ObjNames []string `json:"obj_name"` + + // filter by action + Actions []string `json:"action"` + + Since time.Time `json:"since"` + + Until time.Time `json:"until"` +} diff --git a/pkg/apis/logger/input.go b/pkg/apis/logger/input.go index c872838b93..0b8c702cd1 100644 --- a/pkg/apis/logger/input.go +++ b/pkg/apis/logger/input.go @@ -28,3 +28,11 @@ type BaremetalEventListInput struct { // until Until time.Time `json:"until"` } + +type ActionLogListInput struct { + apis.OpsLogListInput + + Service []string `json:"service"` + + Success *bool `json:"success"` +} diff --git a/pkg/cloudcommon/db/distinct_fields.go b/pkg/cloudcommon/db/distinct_fields.go index 9596650949..6a0e57dafe 100644 --- a/pkg/cloudcommon/db/distinct_fields.go +++ b/pkg/cloudcommon/db/distinct_fields.go @@ -19,6 +19,7 @@ import ( "fmt" "yunion.io/x/pkg/errors" + "yunion.io/x/sqlchemy" ) type SDistinctFieldManager struct { @@ -84,5 +85,12 @@ func (manager *SDistinctFieldManager) InsertOrUpdate(ctx context.Context, modelM Id: modelManager.Keyword() + DISTINCT_FIELD_SEP + key + DISTINCT_FIELD_SEP + value, } distinct.SetModelManager(manager, distinct) - return manager.TableSpec().InsertOrUpdate(ctx, distinct) + err := manager.TableSpec().InsertOrUpdate(ctx, distinct) + if err != nil { + if errors.Cause(err) == sqlchemy.ErrUnexpectRowCount { + return nil + } + return err + } + return nil } diff --git a/pkg/cloudcommon/db/fetch.go b/pkg/cloudcommon/db/fetch.go index beb4d2da01..34833858b8 100644 --- a/pkg/cloudcommon/db/fetch.go +++ b/pkg/cloudcommon/db/fetch.go @@ -529,12 +529,14 @@ func FetchDistinctField(modelManager IModelManager, field string) ([]string, err values := []string{} for rows.Next() { - var value string + var value sql.NullString err := rows.Scan(&value) if err != nil { return values, errors.Wrap(err, "rows.Scan") } - values = append(values, value) + if value.Valid { + values = append(values, value.String) + } } return values, nil } diff --git a/pkg/cloudcommon/db/opslog.go b/pkg/cloudcommon/db/opslog.go index 23eb109537..b5c0a68354 100644 --- a/pkg/cloudcommon/db/opslog.go +++ b/pkg/cloudcommon/db/opslog.go @@ -248,78 +248,69 @@ func (manager *SOpsLogManager) ListItemFilter( ctx context.Context, q *sqlchemy.SQuery, userCred mcclient.TokenCredential, - query jsonutils.JSONObject, + input apis.OpsLogListInput, ) (*sqlchemy.SQuery, error) { - projStrs := jsonutils.GetQueryStringArray(query, "owner_project_ids") - if len(projStrs) > 0 { - for i := range projStrs { - projObj, err := DefaultProjectFetcher(ctx, projStrs[i]) - if err != nil { - if err == sql.ErrNoRows { - return nil, httperrors.NewResourceNotFoundError2("project", projStrs[i]) - } else { - return nil, httperrors.NewGeneralError(err) - } + for idx, projectId := range input.OwnerProjectIds { + projObj, err := DefaultProjectFetcher(ctx, projectId) + if err != nil { + if err == sql.ErrNoRows { + return nil, httperrors.NewResourceNotFoundError2("project", projectId) + } else { + return nil, httperrors.NewGeneralError(err) } - projStrs[i] = projObj.GetId() } - q = q.Filter(sqlchemy.In(q.Field("owner_tenant_id"), projStrs)) + input.OwnerProjectIds[idx] = projObj.GetId() } - domainStrs := jsonutils.GetQueryStringArray(query, "owner_domain_ids") - if len(domainStrs) > 0 { - for i := range domainStrs { - domainObj, err := DefaultDomainFetcher(ctx, domainStrs[i]) - if err != nil { - if err == sql.ErrNoRows { - return nil, httperrors.NewResourceNotFoundError2("domain", domainStrs[i]) - } else { - return nil, httperrors.NewGeneralError(err) - } + if len(input.OwnerProjectIds) > 0 { + q = q.Filter(sqlchemy.In(q.Field("owner_tenant_id"), input.OwnerProjectIds)) + } + for idx, domainId := range input.OwnerDomainIds { + domainObj, err := DefaultDomainFetcher(ctx, domainId) + if err != nil { + if err == sql.ErrNoRows { + return nil, httperrors.NewResourceNotFoundError2("domain", domainId) + } else { + return nil, httperrors.NewGeneralError(err) } - domainStrs[i] = domainObj.GetId() } - q = q.Filter(sqlchemy.In(q.Field("owner_domain_id"), domainStrs)) + input.OwnerDomainIds[idx] = domainObj.GetId() } - objTypes := jsonutils.GetQueryStringArray(query, "obj_type") - if len(objTypes) > 0 { - if len(objTypes) == 1 { - q = q.Filter(sqlchemy.Equals(q.Field("obj_type"), objTypes[0])) + if len(input.OwnerDomainIds) > 0 { + q = q.Filter(sqlchemy.In(q.Field("owner_domain_id"), input.OwnerDomainIds)) + } + if len(input.ObjTypes) > 0 { + if len(input.ObjTypes) == 1 { + q = q.Filter(sqlchemy.Equals(q.Field("obj_type"), input.ObjTypes[0])) } else { - q = q.Filter(sqlchemy.In(q.Field("obj_type"), objTypes)) + q = q.Filter(sqlchemy.In(q.Field("obj_type"), input.ObjTypes)) } } - objs := jsonutils.GetQueryStringArray(query, "obj") - if len(objs) > 0 { - if len(objs) == 1 { - q = q.Filter(sqlchemy.OR(sqlchemy.Equals(q.Field("obj_id"), objs[0]), sqlchemy.Equals(q.Field("obj_name"), objs[0]))) + if len(input.Objs) > 0 { + if len(input.Objs) == 1 { + q = q.Filter(sqlchemy.OR(sqlchemy.Equals(q.Field("obj_id"), input.Objs[0]), sqlchemy.Equals(q.Field("obj_name"), input.Objs[0]))) } else { - q = q.Filter(sqlchemy.OR(sqlchemy.In(q.Field("obj_id"), objs), sqlchemy.In(q.Field("obj_name"), objs))) + q = q.Filter(sqlchemy.OR(sqlchemy.In(q.Field("obj_id"), input.Objs), sqlchemy.In(q.Field("obj_name"), input.Objs))) } } - objIds := jsonutils.GetQueryStringArray(query, "obj_id") - if len(objIds) > 0 { - if len(objIds) == 1 { - q = q.Filter(sqlchemy.Equals(q.Field("obj_id"), objIds[0])) + if len(input.ObjIds) > 0 { + if len(input.ObjIds) == 1 { + q = q.Filter(sqlchemy.Equals(q.Field("obj_id"), input.ObjIds[0])) } else { - q = q.Filter(sqlchemy.In(q.Field("obj_id"), objIds)) + q = q.Filter(sqlchemy.In(q.Field("obj_id"), input.ObjIds)) } } - objNames := jsonutils.GetQueryStringArray(query, "obj_name") - if len(objNames) > 0 { - if len(objNames) == 1 { - q = q.Filter(sqlchemy.Equals(q.Field("obj_name"), objNames[0])) + if len(input.ObjNames) > 0 { + if len(input.ObjNames) == 1 { + q = q.Filter(sqlchemy.Equals(q.Field("obj_name"), input.ObjNames[0])) } else { - q = q.Filter(sqlchemy.In(q.Field("obj_name"), objNames)) + q = q.Filter(sqlchemy.In(q.Field("obj_name"), input.ObjNames)) } } - queryDict := query.(*jsonutils.JSONDict) - queryDict.Remove("obj_id") - action := jsonutils.GetQueryStringArray(query, "action") - if action != nil && len(action) > 0 { - if len(action) == 1 { - q = q.Filter(sqlchemy.Equals(q.Field("action"), action[0])) + if len(input.Actions) > 0 { + if len(input.Actions) == 1 { + q = q.Filter(sqlchemy.Equals(q.Field("action"), input.Actions[0])) } else { - q = q.Filter(sqlchemy.In(q.Field("action"), action)) + q = q.Filter(sqlchemy.In(q.Field("action"), input.Actions)) } } //if !IsAdminAllowList(userCred, manager) { @@ -328,13 +319,11 @@ func (manager *SOpsLogManager) ListItemFilter( // sqlchemy.Equals(q.Field("tenant_id"), manager.GetOwnerId(userCred)), // )) //} - since, _ := query.GetTime("since") - if !since.IsZero() { - q = q.GT("ops_time", since) + if !input.Since.IsZero() { + q = q.GT("ops_time", input.Since) } - until, _ := query.GetTime("until") - if !until.IsZero() { - q = q.LE("ops_time", until) + if !input.Until.IsZero() { + q = q.LE("ops_time", input.Until) } return q, nil } diff --git a/pkg/logger/models/actionlog.go b/pkg/logger/models/actionlog.go index 5e8c14cb19..009d320e73 100644 --- a/pkg/logger/models/actionlog.go +++ b/pkg/logger/models/actionlog.go @@ -20,7 +20,11 @@ import ( "yunion.io/x/jsonutils" "yunion.io/x/log" + "yunion.io/x/pkg/errors" + "yunion.io/x/sqlchemy" + "yunion.io/x/onecloud/pkg/apis" + api "yunion.io/x/onecloud/pkg/apis/logger" "yunion.io/x/onecloud/pkg/cloudcommon/consts" "yunion.io/x/onecloud/pkg/cloudcommon/db" "yunion.io/x/onecloud/pkg/mcclient" @@ -84,10 +88,71 @@ func (action *SActionlog) CustomizeCreate(ctx context.Context, userCred mcclient return action.SOpsLog.CustomizeCreate(ctx, userCred, ownerId, query, data) } +func (self *SActionlog) PostCreate(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, data jsonutils.JSONObject) { + for k, v := range map[string]string{ + "service": self.Service, + "action": self.Action, + "obj_type": self.ObjType, + } { + db.DistinctFieldManager.InsertOrUpdate(ctx, ActionLog, k, v) + } +} + +// 操作日志列表 +func (manager *SActionlogManager) ListItemFilter( + ctx context.Context, + q *sqlchemy.SQuery, + userCred mcclient.TokenCredential, + input api.ActionLogListInput, +) (*sqlchemy.SQuery, error) { + var err error + q, err = manager.SOpsLogManager.ListItemFilter(ctx, q, userCred, input.OpsLogListInput) + if err != nil { + return nil, errors.Wrapf(err, "ListItemFilter") + } + + if len(input.Service) > 0 { + if len(input.Service) == 1 { + q = q.Equals("service", input.Service[0]) + } else { + q = q.In("service", input.Service) + } + } + + if input.Success != nil { + q = q.Equals("success", *input.Success) + } + return q, nil +} + +func (manager *SActionlogManager) GetPropertyDistinctField(ctx context.Context, userCred mcclient.TokenCredential, input apis.DistinctFieldInput) (jsonutils.JSONObject, error) { + fields, err := db.DistinctFieldManager.GetObjectDistinctFields(manager.Keyword()) + if err != nil { + return nil, errors.Wrapf(err, "DistinctFieldManager.GetObjectDistinctFields") + } + fieldMaps := map[string][]string{} + for _, field := range fields { + _, ok := fieldMaps[field.Key] + if !ok { + fieldMaps[field.Key] = []string{} + } + fieldMaps[field.Key] = append(fieldMaps[field.Key], field.Value) + } + ret := map[string][]string{} + for _, key := range input.Field { + ret[key], _ = fieldMaps[key] + } + return jsonutils.Marshal(ret), nil +} + func (action *SActionlog) GetI18N(ctx context.Context) *jsonutils.JSONDict { r := jsonutils.NewDict() act18 := logclient.OpsActionI18nTable.Lookup(ctx, action.Action) + ser18 := logclient.OpsServiceI18nTable.Lookup(ctx, action.Service) + obj18 := logclient.OpsObjTypeI18nTable.Lookup(ctx, action.ObjType) r.Set("action", jsonutils.NewString(act18)) + r.Set("service", jsonutils.NewString(ser18)) + r.Set("obj_type", jsonutils.NewString(obj18)) return r } @@ -96,7 +161,9 @@ func (man *SActionlogManager) GetI18N(ctx context.Context, idstr string, resObj return nil } res := &struct { - Action []string `json:"action"` + Action []string `json:"action"` + Service []string `json:"service"` + ObjType []string `json:"obj_type"` }{} if err := resObj.Unmarshal(res); err != nil { return nil @@ -105,6 +172,14 @@ func (man *SActionlogManager) GetI18N(ctx context.Context, idstr string, resObj act18 := logclient.OpsActionI18nTable.Lookup(ctx, act) res.Action[i] = act18 } + for i, ser := range res.Service { + ser18 := logclient.OpsServiceI18nTable.Lookup(ctx, ser) + res.Service[i] = ser18 + } + for i, obj := range res.ObjType { + obj18 := logclient.OpsObjTypeI18nTable.Lookup(ctx, obj) + res.ObjType[i] = obj18 + } robj := jsonutils.Marshal(res) rdict := robj.(*jsonutils.JSONDict) return rdict @@ -137,3 +212,28 @@ func StartNotifyToWebsocketWorker() { } }() } + +func (manager *SActionlogManager) InitializeData() error { + fileds, err := db.DistinctFieldManager.GetObjectDistinctFields(manager.Keyword()) + if err != nil { + return errors.Wrapf(err, "GetObjectDistinctFields") + } + if len(fileds) > 0 { + return nil + } + for _, key := range []string{"service", "obj_type", "action"} { + values, err := db.FetchDistinctField(manager, key) + if err != nil { + return errors.Wrapf(err, "db.FetchDistinctField") + } + for _, value := range values { + if len(value) > 0 { + err = db.DistinctFieldManager.InsertOrUpdate(context.TODO(), manager, key, value) + if err != nil { + return errors.Wrapf(err, "DistinctFieldManager.InsertOrUpdate(%s, %s)", key, value) + } + } + } + } + return nil +} diff --git a/pkg/logger/models/initdb.go b/pkg/logger/models/initdb.go new file mode 100644 index 0000000000..a1da5a79d8 --- /dev/null +++ b/pkg/logger/models/initdb.go @@ -0,0 +1,37 @@ +// Copyright 2019 Yunion +// +// 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 models + +import ( + "yunion.io/x/log" + + "yunion.io/x/onecloud/pkg/cloudcommon/db" +) + +func InitDB() error { + for _, manager := range []db.IModelManager{ + /* + * Important!!! + * initialization order matters, do not change the order + */ + ActionLog, + } { + err := manager.InitializeData() + if err != nil { + log.Errorf("Manager %s initializeData fail %s", manager.Keyword(), err) + } + } + return nil +} diff --git a/pkg/logger/service/handlers.go b/pkg/logger/service/handlers.go index 66f122d620..515ad2dcbb 100644 --- a/pkg/logger/service/handlers.go +++ b/pkg/logger/service/handlers.go @@ -27,6 +27,7 @@ func initHandlers(app *appsrv.Application) { for _, manager := range []db.IModelManager{ db.UserCacheManager, db.TenantCacheManager, + db.DistinctFieldManager, } { db.RegisterModelManager(manager) } diff --git a/pkg/logger/service/service.go b/pkg/logger/service/service.go index e8ced51cc7..dbfd8abd51 100644 --- a/pkg/logger/service/service.go +++ b/pkg/logger/service/service.go @@ -49,7 +49,7 @@ func StartService() { app := app_common.InitApp(baseOpts, true) initHandlers(app) - db.EnsureAppInitSyncDB(app, dbOpts, nil) + db.EnsureAppInitSyncDB(app, dbOpts, models.InitDB) defer cloudcommon.CloseDB() models.StartNotifyToWebsocketWorker() diff --git a/pkg/util/logclient/consts_i18n.go b/pkg/util/logclient/consts_i18n.go index 14a64739d1..0d1e3298bf 100644 --- a/pkg/util/logclient/consts_i18n.go +++ b/pkg/util/logclient/consts_i18n.go @@ -15,13 +15,18 @@ package logclient import ( + "yunion.io/x/onecloud/pkg/apis" "yunion.io/x/onecloud/pkg/i18n" ) var OpsActionI18nTable = i18n.Table{} +var OpsServiceI18nTable = i18n.Table{} +var OpsObjTypeI18nTable = i18n.Table{} func init() { t := OpsActionI18nTable + s := OpsServiceI18nTable + o := OpsObjTypeI18nTable t.Set(ACT_ADDTAG, i18n.NewTableEntry(). EN("Addtag"). @@ -665,4 +670,627 @@ func init() { EN("Set Alert"). CN("配置报警"), ) + + s.Set(apis.SERVICE_TYPE_MONITOR, i18n.NewTableEntry(). + EN("Monitor"). + CN("监控"), + ) + s.Set(apis.SERVICE_TYPE_REGION, i18n.NewTableEntry(). + EN("Compute"). + CN("计算"), + ) + s.Set(apis.SERVICE_TYPE_IMAGE, i18n.NewTableEntry(). + EN("Image"). + CN("镜像"), + ) + s.Set(apis.SERVICE_TYPE_CLOUDID, i18n.NewTableEntry(). + EN("Cloud SSO"). + CN("多云统一认证"), + ) + s.Set(apis.SERVICE_TYPE_DEVTOOL, i18n.NewTableEntry(). + EN("Dev Tools"). + CN("运维工具"), + ) + s.Set(apis.SERVICE_TYPE_ANSIBLE, i18n.NewTableEntry(). + EN("Ansible"). + CN("Ansible"), + ) + s.Set(apis.SERVICE_TYPE_KEYSTONE, i18n.NewTableEntry(). + EN("Keystone"). + CN("认证服务"), + ) + s.Set(apis.SERVICE_TYPE_NOTIFY, i18n.NewTableEntry(). + EN("Notify"). + CN("通知服务"), + ) + s.Set(apis.SERVICE_TYPE_SUGGESTION, i18n.NewTableEntry(). + EN("Suggestion"). + CN("优化建议"), + ) + s.Set(apis.SERVICE_TYPE_METER, i18n.NewTableEntry(). + EN("Suggestion"). + CN("计费服务"), + ) + s.Set("k8s", i18n.NewTableEntry(). + EN("Kubernetes"). + CN("容器服务"), + ) + + o.Set("domain", i18n.NewTableEntry(). + EN("Domain"). + CN("域"), + ) + o.Set("kubemachine", i18n.NewTableEntry(). + EN("Kube Machine"). + CN("Kube Machine"), + ) + o.Set("clouduser", i18n.NewTableEntry(). + EN("Cloud user"). + CN("云上用户"), + ) + o.Set("x509keypair", i18n.NewTableEntry(). + EN("x509 Keypair"). + CN("x509 Keypair"), + ) + o.Set("kubecluster", i18n.NewTableEntry(). + EN("Kube Cluster"). + CN("Kube Cluster"), + ) + o.Set("role", i18n.NewTableEntry(). + EN("Role"). + CN("角色"), + ) + o.Set("notifyconfig", i18n.NewTableEntry(). + EN("Notify Config"). + CN("通知配置"), + ) + o.Set("wire", i18n.NewTableEntry(). + EN("Wire"). + CN("二层网络"), + ) + o.Set("loadbalancerlistenerrule", i18n.NewTableEntry(). + EN("Loadbalancer Listener Rule"). + CN("负载均衡监听规则"), + ) + o.Set("loadbalancerlistener", i18n.NewTableEntry(). + EN("Loadbalancer Listener"). + CN("负载均衡监听器"), + ) + o.Set("elasticcache", i18n.NewTableEntry(). + EN("Elastic Cache"). + CN("弹性缓存"), + ) + o.Set("notifytemplate", i18n.NewTableEntry(). + EN("Notify Templete"). + CN("通知模板"), + ) + o.Set("policy", i18n.NewTableEntry(). + EN("Policy"). + CN("Policy"), + ) + o.Set("scheduledtask", i18n.NewTableEntry(). + EN("Scheduled Task"). + CN("Scheduled Task"), + ) + o.Set("saml_provider", i18n.NewTableEntry(). + EN("SAML Provider"). + CN("SAML 身份提供商"), + ) + o.Set("daemonset", i18n.NewTableEntry(). + EN("Daemonset"). + CN("Daemonset"), + ) + o.Set("network", i18n.NewTableEntry(). + EN("Network"). + CN("IP子网"), + ) + o.Set("vpc", i18n.NewTableEntry(). + EN("VPC"). + CN("VPC"), + ) + o.Set("dbinstancebackup", i18n.NewTableEntry(). + EN("RDS Backup"). + CN("关系型数据库备份"), + ) + o.Set("host", i18n.NewTableEntry(). + EN("Host"). + CN("宿主机"), + ) + o.Set("identity_provider", i18n.NewTableEntry(). + EN("Identity Provider"). + CN("身份提供商"), + ) + o.Set("commonalert", i18n.NewTableEntry(). + EN("Common Alert"). + CN("Common Alert"), + ) + o.Set("loadbalanceragent", i18n.NewTableEntry(). + EN("Loadbalancer Agent"). + CN("负载均衡Agent"), + ) + o.Set("loadbalancer", i18n.NewTableEntry(). + EN("Loadbalancer"). + CN("负载均衡"), + ) + o.Set("cloudgroup", i18n.NewTableEntry(). + EN("Cloud Group"). + CN("权限组"), + ) + o.Set("cloudgroupcache", i18n.NewTableEntry(). + EN("Cloud group cache"). + CN("权限组缓存"), + ) + o.Set("samluser", i18n.NewTableEntry(). + EN("SAML User"). + CN("免密用户"), + ) + o.Set("project", i18n.NewTableEntry(). + EN("Project"). + CN("项目"), + ) + o.Set("keypair", i18n.NewTableEntry(). + EN("Keypair"). + CN("秘钥对"), + ) + o.Set("loadbalancerbackendgroup", i18n.NewTableEntry(). + EN("Loadbalancer Backendgroup"). + CN("后端服务器组"), + ) + o.Set("statefulset", i18n.NewTableEntry(). + EN("State Fulset"). + CN("State Fulset"), + ) + o.Set("bucket", i18n.NewTableEntry(). + EN("Bucket"). + CN("存储桶"), + ) + o.Set("receiver", i18n.NewTableEntry(). + EN("Receiver"). + CN("接收者"), + ) + o.Set("suggestsysrule", i18n.NewTableEntry(). + EN("Suggest sysrule"). + CN("建议规则"), + ) + o.Set("dbinstance", i18n.NewTableEntry(). + EN("RDS"). + CN("关系型数据库"), + ) + o.Set("storagecachedimage", i18n.NewTableEntry(). + EN("Storage Cached Image"). + CN("存储镜像缓存"), + ) + o.Set("image", i18n.NewTableEntry(). + EN("Image"). + CN("镜像"), + ) + o.Set("itsm", i18n.NewTableEntry(). + EN("ITSM"). + CN("ITSM"), + ) + o.Set("disk", i18n.NewTableEntry(). + EN("Disk"). + CN("磁盘"), + ) + o.Set("eip", i18n.NewTableEntry(). + EN("Elastic Ip"). + CN("弹性公网IP"), + ) + o.Set("alert", i18n.NewTableEntry(). + EN("Alert"). + CN("报警"), + ) + o.Set("budget", i18n.NewTableEntry(). + EN("Budget"). + CN("预算"), + ) + o.Set("costalert", i18n.NewTableEntry(). + EN("Cost Alert"). + CN("Cost Alert"), + ) + o.Set("alert_notification", i18n.NewTableEntry(). + EN("Alert Notification"). + CN("Alert Notification"), + ) + o.Set("servertemplate", i18n.NewTableEntry(). + EN("Instance Templete"). + CN("主机模板"), + ) + o.Set("cachedimage", i18n.NewTableEntry(). + EN("Cached Image"). + CN("镜像缓存"), + ) + o.Set("suggestsysalert", i18n.NewTableEntry(). + EN("Suggest Sys Alert"). + CN("建议预警"), + ) + o.Set("cloudaccount", i18n.NewTableEntry(). + EN("Cloud Account"). + CN("云账号"), + ) + o.Set("cloudprovider", i18n.NewTableEntry(). + EN("Subscription"). + CN("订阅"), + ) + o.Set("snapshot", i18n.NewTableEntry(). + EN("Snapshot"). + CN("快照"), + ) + o.Set("costreport", i18n.NewTableEntry(). + EN("Cost Report"). + CN("消费报告"), + ) + o.Set("deployment", i18n.NewTableEntry(). + EN("Deployment"). + CN("Deployment"), + ) + o.Set("storage", i18n.NewTableEntry(). + EN("Storage"). + CN("块存储"), + ) + o.Set("server", i18n.NewTableEntry(). + EN("Server"). + CN("虚拟机"), + ) + o.Set("notification", i18n.NewTableEntry(). + EN("Notification"). + CN("通知"), + ) + o.Set("secgroup", i18n.NewTableEntry(). + EN("Security Group"). + CN("安全组"), + ) + o.Set("endpoint", i18n.NewTableEntry(). + EN("Endpoint"). + CN("端点"), + ) + o.Set("service", i18n.NewTableEntry(). + EN("Service"). + CN("服务"), + ) + o.Set("user", i18n.NewTableEntry(). + EN("User"). + CN("用户"), + ) + o.Set("instance_snapshot", i18n.NewTableEntry(). + EN("Instance Snapshot"). + CN("主机快照"), + ) + o.Set("guestimage", i18n.NewTableEntry(). + EN("Instance Image"). + CN("主机镜像"), + ) + o.Set("instancegroup", i18n.NewTableEntry(). + EN("Instance Group"). + CN("反亲和组"), + ) + o.Set("dbinstanceaccount", i18n.NewTableEntry(). + EN("RDS Account"). + CN("关系型数据库账号"), + ) + o.Set("elasticcacheaccount", i18n.NewTableEntry(). + EN("Elastic Cache Account"). + CN("弹性缓存账号"), + ) + o.Set("dbinstancedatabase", i18n.NewTableEntry(). + EN("RDS Database"). + CN("数据库"), + ) + o.Set("devtool_template", i18n.NewTableEntry(). + EN("DevTool Template"). + CN("DevTool Templete"), + ) + o.Set("devtool_cronjob", i18n.NewTableEntry(). + EN("DevTool Cronjob"). + CN("DevTool Cronjob"), + ) + o.Set("elasticcachebackup", i18n.NewTableEntry(). + EN("Elastic Cache Backup"). + CN("弹性缓存备份"), + ) + o.Set("kubecomponent", i18n.NewTableEntry(). + EN("Kube Component"). + CN("Kube Component"), + ) + o.Set("scalinggroup", i18n.NewTableEntry(). + EN("Scaling Group"). + CN("弹性伸缩组"), + ) + o.Set("scalingpolicy", i18n.NewTableEntry(). + EN("Scaling Policy"). + CN("弹性伸缩策略"), + ) + o.Set("proxysetting", i18n.NewTableEntry(). + EN("Proxy Setting"). + CN("代理"), + ) + o.Set("credential", i18n.NewTableEntry(). + EN("Credential"). + CN("Credential"), + ) + o.Set("cloudproviderquota", i18n.NewTableEntry(). + EN("Subscription Quota"). + CN("订阅配额"), + ) + o.Set("nodealert", i18n.NewTableEntry(). + EN("Node Alert"). + CN("Node Alert"), + ) + o.Set("globalvpc", i18n.NewTableEntry(). + EN("Gloal VPC"). + CN("全局VPC"), + ) + o.Set("contact", i18n.NewTableEntry(). + EN("Contact"). + CN("Contact"), + ) + o.Set("schedpolicy", i18n.NewTableEntry(). + EN("Scheduler Policy"). + CN("调度策略"), + ) + o.Set("config", i18n.NewTableEntry(). + EN("Config"). + CN("配置"), + ) + o.Set("namespace", i18n.NewTableEntry(). + EN("Namespace"). + CN("Namespace"), + ) + o.Set("repo", i18n.NewTableEntry(). + EN("Repo"). + CN("Repo"), + ) + o.Set("release", i18n.NewTableEntry(). + EN("Release"). + CN("Release"), + ) + o.Set("servicecertificate", i18n.NewTableEntry(). + EN("Service Certificate"). + CN("Service Certificate"), + ) + o.Set("pod", i18n.NewTableEntry(). + EN("Pod"). + CN("Pod"), + ) + o.Set("elasticcacheacl", i18n.NewTableEntry(). + EN("Elastic Cache Acl"). + CN("弹性缓存ACL"), + ) + o.Set("metricmeasurement", i18n.NewTableEntry(). + EN("Metric Measurement"). + CN("Metric Measurement"), + ) + o.Set("alertdashboard", i18n.NewTableEntry(). + EN("Alert Dashboard"). + CN("Alert Dashboard"), + ) + o.Set("dns_zone", i18n.NewTableEntry(). + EN("DNS Zone"). + CN("DNS Zone"), + ) + o.Set("dns_recordset", i18n.NewTableEntry(). + EN("DNS Records"). + CN("DNS Records"), + ) + o.Set("dns_zonecache", i18n.NewTableEntry(). + EN("DNS Zone Cache"). + CN("DNS Zone Cache"), + ) + o.Set("federatednamespace", i18n.NewTableEntry(). + EN("Federated Namespace"). + CN("Federated Namespace"), + ) + o.Set("ingress", i18n.NewTableEntry(). + EN("Ingress"). + CN("Ingress"), + ) + o.Set("cronjob", i18n.NewTableEntry(). + EN("Cronjob"). + CN("定时任务"), + ) + o.Set("federatedrole", i18n.NewTableEntry(). + EN("Federated Role"). + CN("Federated Role"), + ) + o.Set("federatedclusterrole", i18n.NewTableEntry(). + EN("Federated Cluster Role"). + CN("Federated Cluster Role"), + ) + o.Set("rbacclusterrole", i18n.NewTableEntry(). + EN("RBAC Cluster Role"). + CN("RBAC Cluster Role"), + ) + o.Set("job", i18n.NewTableEntry(). + EN("Job"). + CN("Job"), + ) + o.Set("rbacrole", i18n.NewTableEntry(). + EN("RBAC Role"). + CN("RBAC Role"), + ) + o.Set("federatedrolebinding", i18n.NewTableEntry(). + EN("Federated Role Binding"). + CN("Federated Role Binding"), + ) + o.Set("scopedpolicy", i18n.NewTableEntry(). + EN("Scoped Policy"). + CN("Scoped Policy"), + ) + o.Set("alertpanel", i18n.NewTableEntry(). + EN("Alert Panel"). + CN("监控面板"), + ) + o.Set("networkaddress", i18n.NewTableEntry(). + EN("Network Address"). + CN("网卡地址"), + ) + o.Set("networkaddress", i18n.NewTableEntry(). + EN("Network Address"). + CN("网卡地址"), + ) + o.Set("baremetalagent", i18n.NewTableEntry(). + EN("Baremetal Agent"). + CN("Baremetal Agent"), + ) + o.Set("notice", i18n.NewTableEntry(). + EN("Notice"). + CN("Notice"), + ) + o.Set("hostwire", i18n.NewTableEntry(). + EN("Host Wire"). + CN("宿主机网络"), + ) + o.Set("storagecache", i18n.NewTableEntry(). + EN("Storage Cache"). + CN("存储缓存"), + ) + o.Set("isolated_device", i18n.NewTableEntry(). + EN("Isolated Device"). + CN("透传设备"), + ) + o.Set("guestdisk", i18n.NewTableEntry(). + EN("Server Disk"). + CN("虚拟机磁盘"), + ) + o.Set("guestnetwork", i18n.NewTableEntry(). + EN("Server Network"). + CN("虚拟机网络"), + ) + o.Set("kube_node", i18n.NewTableEntry(). + EN("Kube Node"). + CN("Kube Node"), + ) + o.Set("secgrouprule", i18n.NewTableEntry(). + EN("Security Group Rule"). + CN("安全组规则"), + ) + o.Set("kube_node", i18n.NewTableEntry(). + EN("Kube Node"). + CN("Kube Node"), + ) + o.Set("kube_cluster", i18n.NewTableEntry(). + EN("Kube Cluster"). + CN("Kube Cluster"), + ) + o.Set("hoststorage", i18n.NewTableEntry(). + EN("Host Storage"). + CN("宿主机存储"), + ) + o.Set("servicetree", i18n.NewTableEntry(). + EN("Service Tree"). + CN("服务目录"), + ) + o.Set("baremetalnetwork", i18n.NewTableEntry(). + EN("Baremetal Network"). + CN("裸金属服务器网络"), + ) + o.Set("guestsecgroup", i18n.NewTableEntry(). + EN("Server Security Group"). + CN("虚拟机安全组"), + ) + o.Set("schedtaghost", i18n.NewTableEntry(). + EN("Schedtag Host"). + CN("Schedtag Host"), + ) + o.Set("loadbalancernetwork", i18n.NewTableEntry(). + EN("Loadbalancer Network"). + CN("负载均衡网络"), + ) + o.Set("infos", i18n.NewTableEntry(). + EN("Infos"). + CN("通知"), + ) + o.Set("finance-alert", i18n.NewTableEntry(). + EN("Finance Alert"). + CN(""), + ) + o.Set("group", i18n.NewTableEntry(). + EN("Group"). + CN("Group"), + ) + o.Set("readmark", i18n.NewTableEntry(). + EN("Readmark"). + CN("Readmark"), + ) + o.Set("meteralert", i18n.NewTableEntry(). + EN("Meter Alert"). + CN("Meter Alert"), + ) + o.Set("reservedip", i18n.NewTableEntry(). + EN("Reserve IP"). + CN("预留IP"), + ) + o.Set("cloudregion", i18n.NewTableEntry(). + EN("Cloudregion"). + CN("区域"), + ) + o.Set("meter_vm", i18n.NewTableEntry(). + EN("Meter VM"). + CN("Meter VM"), + ) + o.Set("route_table", i18n.NewTableEntry(). + EN("Route Table"). + CN("路由表"), + ) + o.Set("externalproject", i18n.NewTableEntry(). + EN("Cloud Project"). + CN("云上项目"), + ) + o.Set("cloudproviderregion", i18n.NewTableEntry(). + EN("Cloudprovider Region"). + CN("订阅区域"), + ) + o.Set("metadata", i18n.NewTableEntry(). + EN("Tag"). + CN("标签"), + ) + o.Set("ansibleplaybook", i18n.NewTableEntry(). + EN("Ansible Playbook"). + CN("Ansible Playbook"), + ) + o.Set("natdentry", i18n.NewTableEntry(). + EN("NAT D Entry"). + CN("NAT D Entry"), + ) + o.Set("natsentry", i18n.NewTableEntry(). + EN("NAT S Entry"). + CN("NAT S Entry"), + ) + o.Set("snapshotpolicy", i18n.NewTableEntry(). + EN("Snapshot Policy"). + CN("快照策略"), + ) + o.Set("meshnetwork_member", i18n.NewTableEntry(). + EN("Meshnetwork Member"). + CN("Meshnetwork Member"), + ) + o.Set("ifacepeer", i18n.NewTableEntry(). + EN("Iface Peer"). + CN("Iface Peer"), + ) + o.Set("iface", i18n.NewTableEntry(). + EN("Iface"). + CN("Iface"), + ) + o.Set("router", i18n.NewTableEntry(). + EN("Router"). + CN("路由"), + ) + o.Set("zone", i18n.NewTableEntry(). + EN("Zone"). + CN("可用区"), + ) + o.Set("schedtag", i18n.NewTableEntry(). + EN("Sched Tag"). + CN("调度标签"), + ) + o.Set("dynamicschedtag", i18n.NewTableEntry(). + EN("Dynamic Sched Tag"). + CN("动态调度标签"), + ) + o.Set("serversku", i18n.NewTableEntry(). + EN("Server Sku"). + CN("虚拟机套餐"), + ) + }