diff --git a/internal/dashboard/business/oceanbase/obcluster.go b/internal/dashboard/business/oceanbase/obcluster.go index 1f94b9ca9..af5758250 100644 --- a/internal/dashboard/business/oceanbase/obcluster.go +++ b/internal/dashboard/business/oceanbase/obcluster.go @@ -148,21 +148,24 @@ func buildOBClusterResponse(ctx context.Context, obcluster *v1alpha1.OBCluster) Value: toleration.Value, }) } - - topology = append(topology, response.OBZone{ + respZone := response.OBZone{ Namespace: obzone.Namespace, Name: obzone.Name, Zone: obzone.Spec.Topology.Zone, Replicas: obzone.Spec.Topology.Replica, Status: convertStatus(obzone.Status.Status), StatusDetail: obzone.Status.Status, + RootService: "", // TODO: query real rs - RootService: obzone.Status.OBServerStatus[0].Server, OBServers: observers, NodeSelector: nodeSelector, Affinities: affinities, Tolerations: tolerations, - }) + } + if len(obzone.Status.OBServerStatus) > 0 { + respZone.RootService = obzone.Status.OBServerStatus[0].Server + } + topology = append(topology, respZone) } respCluster := &response.OBCluster{ @@ -172,7 +175,7 @@ func buildOBClusterResponse(ctx context.Context, obcluster *v1alpha1.OBCluster) ClusterId: obcluster.Spec.ClusterId, Status: getStatisticStatus(obcluster), StatusDetail: obcluster.Status.Status, - CreateTime: float64(obcluster.ObjectMeta.CreationTimestamp.UnixMilli()) / 1000, + CreateTime: obcluster.ObjectMeta.CreationTimestamp.Unix(), Image: obcluster.Status.Image, Topology: topology, OBClusterExtra: response.OBClusterExtra{ @@ -219,6 +222,27 @@ func buildOBClusterResponse(ctx context.Context, obcluster *v1alpha1.OBCluster) respCluster.Mode = modelcommon.ClusterModeNormal } } + if obcluster.Spec.OBServerTemplate != nil { + respCluster.OBClusterExtra.Resource = modelcommon.ResourceSpec{ + Cpu: obcluster.Spec.OBServerTemplate.Resource.Cpu.Value(), + MemoryGB: obcluster.Spec.OBServerTemplate.Resource.Memory.Value() >> 30, + } + respCluster.OBClusterExtra.Storage = response.OBServerStorage{ + DataStorage: response.StorageSpec{ + StorageClass: obcluster.Spec.OBServerTemplate.Storage.DataStorage.StorageClass, + SizeGB: obcluster.Spec.OBServerTemplate.Storage.DataStorage.Size.Value() >> 30, + }, + RedoLogStorage: response.StorageSpec{ + StorageClass: obcluster.Spec.OBServerTemplate.Storage.RedoLogStorage.StorageClass, + SizeGB: obcluster.Spec.OBServerTemplate.Storage.RedoLogStorage.Size.Value() >> 30, + }, + SysLogStorage: response.StorageSpec{ + StorageClass: obcluster.Spec.OBServerTemplate.Storage.LogStorage.StorageClass, + SizeGB: obcluster.Spec.OBServerTemplate.Storage.LogStorage.Size.Value() >> 30, + }, + } + } + return respCluster, nil } diff --git a/internal/dashboard/business/oceanbase/obtenant_pool.go b/internal/dashboard/business/oceanbase/obtenant_pool.go new file mode 100644 index 000000000..bdcc90a6f --- /dev/null +++ b/internal/dashboard/business/oceanbase/obtenant_pool.go @@ -0,0 +1,156 @@ +/* +Copyright (c) 2023 OceanBase +ob-operator is licensed under Mulan PSL v2. +You can use this software according to the terms and conditions of the Mulan PSL v2. +You may obtain a copy of Mulan PSL v2 at: + http://license.coscl.org.cn/MulanPSL2 +THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, +EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, +MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. +See the Mulan PSL v2 for more details. +*/ + +package oceanbase + +import ( + "context" + + "k8s.io/apimachinery/pkg/api/resource" + "k8s.io/apimachinery/pkg/types" + + "github.com/oceanbase/ob-operator/api/v1alpha1" + "github.com/oceanbase/ob-operator/internal/dashboard/model/param" + "github.com/oceanbase/ob-operator/internal/oceanbase" + oberr "github.com/oceanbase/ob-operator/pkg/errors" +) + +func CreateTenantPool(ctx context.Context, nn param.TenantPoolName, p *param.TenantPoolSpec) (bool, error) { + cpuCount, err := resource.ParseQuantity(p.UnitConfig.CPUCount) + if err != nil { + return false, oberr.NewBadRequest("invalid cpu count: " + err.Error()) + } + memorySize, err := resource.ParseQuantity(p.UnitConfig.MemorySize) + if err != nil { + return false, oberr.NewBadRequest("invalid memory size: " + err.Error()) + } + logDiskSize, err := resource.ParseQuantity(p.UnitConfig.LogDiskSize) + if err != nil { + return false, oberr.NewBadRequest("invalid log disk size: " + err.Error()) + } + + tenantCR, err := oceanbase.GetOBTenant(ctx, types.NamespacedName{ + Namespace: nn.Namespace, + Name: nn.Name, + }) + if err != nil { + return false, err + } + for _, pool := range tenantCR.Spec.Pools { + if pool.Zone == nn.ZoneName { + return false, oberr.NewBadRequest("pool already exists") + } + } + clusterCR, err := oceanbase.GetOBCluster(ctx, nn.Namespace, tenantCR.Spec.ClusterName) + if err != nil { + return false, err + } + for _, zone := range clusterCR.Spec.Topology { + if zone.Zone == nn.ZoneName { + tenantCR.Spec.Pools = append(tenantCR.Spec.Pools, v1alpha1.ResourcePoolSpec{ + Zone: nn.ZoneName, + Priority: p.Priority, + Type: &v1alpha1.LocalityType{ + Name: "Full", + Replica: 1, + IsActive: true, + }, + UnitConfig: &v1alpha1.UnitConfig{ + MaxCPU: cpuCount, + MemorySize: memorySize, + MinCPU: cpuCount, + MaxIops: p.UnitConfig.MaxIops, + MinIops: p.UnitConfig.MaxIops, + IopsWeight: p.UnitConfig.IopsWeight, + LogDiskSize: logDiskSize, + }, + }) + _, err = oceanbase.UpdateOBTenant(ctx, tenantCR) + if err != nil { + return false, err + } + return true, nil + } + } + return false, oberr.NewBadRequest("zone not found in the cluster") +} + +func DeleteTenantPool(ctx context.Context, nn param.TenantPoolName) (bool, error) { + tenantCR, err := oceanbase.GetOBTenant(ctx, types.NamespacedName{ + Namespace: nn.Namespace, + Name: nn.Name, + }) + if err != nil { + return false, err + } + if len(tenantCR.Spec.Pools) == 1 { + return false, oberr.NewBadRequest("at least one pool is required") + } + remainPools := make([]v1alpha1.ResourcePoolSpec, 0, len(tenantCR.Spec.Pools)-1) + for i, pool := range tenantCR.Spec.Pools { + if pool.Zone != nn.ZoneName { + remainPools = append(remainPools, tenantCR.Spec.Pools[i]) + } + } + if len(remainPools) == len(tenantCR.Spec.Pools) { + return false, oberr.NewBadRequest("pool not found") + } + + tenantCR.Spec.Pools = remainPools + _, err = oceanbase.UpdateOBTenant(ctx, tenantCR) + if err != nil { + return false, err + } + return true, nil +} + +func PatchTenantPool(ctx context.Context, nn param.TenantPoolName, p *param.TenantPoolSpec) (bool, error) { + tenantCR, err := oceanbase.GetOBTenant(ctx, types.NamespacedName{ + Namespace: nn.Namespace, + Name: nn.Name, + }) + if err != nil { + return false, err + } + for i, pool := range tenantCR.Spec.Pools { + if pool.Zone == nn.ZoneName { + tenantCR.Spec.Pools[i].Priority = p.Priority + if tenantCR.Spec.Pools[i].UnitConfig != nil { + if cpuCount, err := resource.ParseQuantity(p.UnitConfig.CPUCount); err == nil { + tenantCR.Spec.Pools[i].UnitConfig.MaxCPU = cpuCount + tenantCR.Spec.Pools[i].UnitConfig.MinCPU = cpuCount + } + if memorySize, err := resource.ParseQuantity(p.UnitConfig.MemorySize); err == nil { + tenantCR.Spec.Pools[i].UnitConfig.MemorySize = memorySize + } + if logDiskSize, err := resource.ParseQuantity(p.UnitConfig.LogDiskSize); err == nil { + tenantCR.Spec.Pools[i].UnitConfig.LogDiskSize = logDiskSize + } + if p.UnitConfig.MaxIops != 0 { + tenantCR.Spec.Pools[i].UnitConfig.MaxIops = p.UnitConfig.MaxIops + } + if p.UnitConfig.MinIops != 0 { + tenantCR.Spec.Pools[i].UnitConfig.MinIops = p.UnitConfig.MinIops + } + if p.UnitConfig.IopsWeight != 0 { + tenantCR.Spec.Pools[i].UnitConfig.IopsWeight = p.UnitConfig.IopsWeight + } + } + _, err = oceanbase.UpdateOBTenant(ctx, tenantCR) + if err != nil { + return false, err + } + return true, nil + } + } + return false, oberr.NewBadRequest("pool not found") +} diff --git a/internal/dashboard/business/oceanbase/obtenantbackup.go b/internal/dashboard/business/oceanbase/obtenantbackup.go index 88816727f..57182bb79 100644 --- a/internal/dashboard/business/oceanbase/obtenantbackup.go +++ b/internal/dashboard/business/oceanbase/obtenantbackup.go @@ -226,6 +226,7 @@ func buildBackupPolicyModelType(p *v1alpha1.OBTenantBackupPolicy) *response.Back Status: string(p.Status.Status), OSSAccessSecret: p.Spec.LogArchive.Destination.OSSAccessSecret, BakEncryptionSecret: p.Spec.DataBackup.EncryptionSecret, + CreateTime: p.CreationTimestamp.Format("2006-01-02 15:04:05"), } res.ScheduleBase = getScheduleDatesFromPolicy(p) return res diff --git a/internal/dashboard/generated/swagger/docs.go b/internal/dashboard/generated/swagger/docs.go index 1cdf60835..17a36bf47 100644 --- a/internal/dashboard/generated/swagger/docs.go +++ b/internal/dashboard/generated/swagger/docs.go @@ -60,6 +60,12 @@ const docTemplate = `{ "description": "Object name", "name": "name", "in": "query" + }, + { + "type": "string", + "description": "Namespace", + "name": "namespace", + "in": "query" } ], "responses": { @@ -634,65 +640,6 @@ const docTemplate = `{ } } }, - "/api/v1/metrics/telemetry": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "get telemetry data", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Info" - ], - "summary": "get telemetry data", - "operationId": "GetStatistics", - "responses": { - "200": { - "description": "OK", - "schema": { - "allOf": [ - { - "$ref": "#/definitions/response.APIResponse" - }, - { - "type": "object", - "properties": { - "data": { - "$ref": "#/definitions/response.StatisticDataResponse" - } - } - } - ] - } - }, - "400": { - "description": "Bad Request", - "schema": { - "$ref": "#/definitions/response.APIResponse" - } - }, - "401": { - "description": "Unauthorized", - "schema": { - "$ref": "#/definitions/response.APIResponse" - } - }, - "500": { - "description": "Internal Server Error", - "schema": { - "$ref": "#/definitions/response.APIResponse" - } - } - } - } - }, "/api/v1/obclusters": { "get": { "security": [ @@ -708,7 +655,7 @@ const docTemplate = `{ "application/json" ], "tags": [ - "Obcluster" + "OBCluster" ], "summary": "list obclusters", "operationId": "ListOBClusters", @@ -768,7 +715,7 @@ const docTemplate = `{ "application/json" ], "tags": [ - "Obcluster" + "OBCluster" ], "summary": "create obcluster", "operationId": "CreateOBCluster", @@ -826,7 +773,7 @@ const docTemplate = `{ "application/json" ], "tags": [ - "Obcluster" + "OBCluster" ], "summary": "get obcluster", "operationId": "GetOBCluster", @@ -899,7 +846,7 @@ const docTemplate = `{ "application/json" ], "tags": [ - "Obcluster" + "OBCluster" ], "summary": "upgrade obcluster", "operationId": "UpgradeOBCluster", @@ -969,7 +916,7 @@ const docTemplate = `{ "application/json" ], "tags": [ - "Obcluster" + "OBCluster" ], "summary": "delete obcluster", "operationId": "DeleteOBCluster", @@ -1032,7 +979,7 @@ const docTemplate = `{ "application/json" ], "tags": [ - "Obcluster" + "OBCluster" ], "summary": "add obzone", "operationId": "AddOBZone", @@ -1104,7 +1051,7 @@ const docTemplate = `{ "application/json" ], "tags": [ - "Obcluster" + "OBCluster" ], "summary": "delete obzone", "operationId": "DeleteOBZone", @@ -1174,7 +1121,7 @@ const docTemplate = `{ "application/json" ], "tags": [ - "Obcluster" + "OBCluster" ], "summary": "scale observer", "operationId": "ScaleOBServer", @@ -1248,7 +1195,7 @@ const docTemplate = `{ "application/json" ], "tags": [ - "Obcluster" + "OBCluster" ], "summary": "get obcluster statistic", "operationId": "GetOBClusterStatistic", @@ -1310,7 +1257,7 @@ const docTemplate = `{ "application/json" ], "tags": [ - "Obcluster" + "OBCluster" ], "summary": "list essential parameters", "operationId": "ListOBClusterResources", @@ -1385,7 +1332,7 @@ const docTemplate = `{ "application/json" ], "tags": [ - "Obtenant" + "OBTenant" ], "summary": "List all tenants", "operationId": "ListAllTenants", @@ -1453,7 +1400,7 @@ const docTemplate = `{ "application/json" ], "tags": [ - "Obtenant" + "OBTenant" ], "summary": "Create tenant", "operationId": "CreateTenant", @@ -1523,7 +1470,7 @@ const docTemplate = `{ "application/json" ], "tags": [ - "Obtenant" + "OBTenant" ], "summary": "List statistics information of tenants", "operationId": "GetOBTenantStatistic", @@ -1585,7 +1532,7 @@ const docTemplate = `{ "application/json" ], "tags": [ - "Obtenant" + "OBTenant" ], "summary": "Get tenant", "operationId": "GetTenant", @@ -1658,7 +1605,7 @@ const docTemplate = `{ "application/json" ], "tags": [ - "Obtenant" + "OBTenant" ], "summary": "Delete tenant", "operationId": "DeleteTenant", @@ -1719,7 +1666,7 @@ const docTemplate = `{ "application/json" ], "tags": [ - "Obtenant" + "OBTenant" ], "summary": "Patch tenant's configuration", "operationId": "PatchTenant", @@ -1803,7 +1750,7 @@ const docTemplate = `{ "application/json" ], "tags": [ - "Obtenant" + "OBTenant" ], "summary": "List backup jobs of specific tenant", "operationId": "ListBackupJobs", @@ -1901,7 +1848,7 @@ const docTemplate = `{ "application/json" ], "tags": [ - "Obtenant" + "OBTenant" ], "summary": "Get backup policy of specific tenant", "operationId": "GetBackupPolicy", @@ -1974,7 +1921,7 @@ const docTemplate = `{ "application/json" ], "tags": [ - "Obtenant" + "OBTenant" ], "summary": "Create backup policy of specific tenant", "operationId": "CreateBackupPolicy", @@ -2056,7 +2003,7 @@ const docTemplate = `{ "application/json" ], "tags": [ - "Obtenant" + "OBTenant" ], "summary": "Delete backup policy of specific tenant", "operationId": "DeleteBackupPolicy", @@ -2124,7 +2071,7 @@ const docTemplate = `{ "application/json" ], "tags": [ - "Obtenant" + "OBTenant" ], "summary": "Update backup policy of specific tenant", "operationId": "UpdateBackupPolicy", @@ -2208,7 +2155,7 @@ const docTemplate = `{ "application/json" ], "tags": [ - "Obtenant" + "OBTenant" ], "summary": "Replay standby log of specific standby tenant", "operationId": "ReplayStandbyLog", @@ -2277,6 +2224,201 @@ const docTemplate = `{ } } }, + "/api/v1/obtenants/{namespace}/{name}/pools/{zoneName}": { + "put": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "Create an obtenant pool in a specific namespace", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "OBTenant" + ], + "summary": "Create obtenant pool", + "operationId": "CreateOBTenantPool", + "parameters": [ + { + "description": "create obtenant pool request body", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/param.TenantPoolSpec" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/response.APIResponse" + }, + { + "type": "object", + "properties": { + "data": { + "type": "boolean" + } + } + } + ] + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/response.APIResponse" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/response.APIResponse" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.APIResponse" + } + } + } + }, + "delete": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "Delete an obtenant pool in a specific namespace", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "OBTenant" + ], + "summary": "Delete obtenant pool", + "operationId": "DeleteOBTenantPool", + "responses": { + "200": { + "description": "OK", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/response.APIResponse" + }, + { + "type": "object", + "properties": { + "data": { + "type": "boolean" + } + } + } + ] + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/response.APIResponse" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/response.APIResponse" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.APIResponse" + } + } + } + }, + "patch": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "Patch an obtenant pool in a specific namespace", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "OBTenant" + ], + "summary": "Patch obtenant pool", + "operationId": "PatchOBTenantPool", + "parameters": [ + { + "description": "patch obtenant pool request body", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/param.TenantPoolSpec" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/response.APIResponse" + }, + { + "type": "object", + "properties": { + "data": { + "type": "boolean" + } + } + } + ] + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/response.APIResponse" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/response.APIResponse" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.APIResponse" + } + } + } + } + }, "/api/v1/obtenants/{namespace}/{name}/role": { "post": { "security": [ @@ -2292,7 +2434,7 @@ const docTemplate = `{ "application/json" ], "tags": [ - "Obtenant" + "OBTenant" ], "summary": "Change tenant role of specific tenant", "operationId": "ChangeTenantRole", @@ -2376,7 +2518,7 @@ const docTemplate = `{ "application/json" ], "tags": [ - "Obtenant" + "OBTenant" ], "summary": "Change root password of specific tenant", "operationId": "ChangeUserPassword", @@ -2460,7 +2602,7 @@ const docTemplate = `{ "application/json" ], "tags": [ - "Obtenant" + "OBTenant" ], "summary": "Upgrade tenant compatibility version of specific tenant", "operationId": "UpgradeTenantVersion", @@ -2519,6 +2661,65 @@ const docTemplate = `{ } } } + }, + "/api/v1/statistics": { + "get": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "get statistic data", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Info" + ], + "summary": "get statistic data", + "operationId": "GetStatistics", + "responses": { + "200": { + "description": "OK", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/response.APIResponse" + }, + { + "type": "object", + "properties": { + "data": { + "$ref": "#/definitions/response.StatisticDataResponse" + } + } + } + ] + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/response.APIResponse" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/response.APIResponse" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.APIResponse" + } + } + } + } } }, "definitions": { @@ -3241,7 +3442,12 @@ const docTemplate = `{ "type": "object", "properties": { "unitConfig": { - "$ref": "#/definitions/param.PatchUnitConfig" + "description": "Deprecated\nDescription: Deprecated, use PATCH /obtenants/:namespace/:name/pools/:zoneName instead", + "allOf": [ + { + "$ref": "#/definitions/param.PatchUnitConfig" + } + ] }, "unitNum": { "type": "integer" @@ -3381,6 +3587,17 @@ const docTemplate = `{ } } }, + "param.TenantPoolSpec": { + "type": "object", + "properties": { + "priority": { + "type": "integer" + }, + "unitConfig": { + "$ref": "#/definitions/param.UnitConfig" + } + } + }, "param.TenantSourceSpec": { "type": "object", "properties": { @@ -3565,6 +3782,9 @@ const docTemplate = `{ "bakEncryptionSecret": { "type": "string" }, + "createTime": { + "type": "string" + }, "destType": { "description": "Enum: NFS, OSS", "type": "string", @@ -3624,6 +3844,9 @@ const docTemplate = `{ "publicKey": { "type": "string" }, + "reportStatistics": { + "type": "boolean" + }, "version": { "type": "string" } @@ -3892,7 +4115,7 @@ const docTemplate = `{ "type": "string" }, "createTime": { - "type": "number" + "type": "integer" }, "image": { "type": "string" @@ -3918,6 +4141,9 @@ const docTemplate = `{ "$ref": "#/definitions/common.KVPair" } }, + "resource": { + "$ref": "#/definitions/common.ResourceSpec" + }, "rootPasswordSecret": { "type": "string" }, @@ -3927,6 +4153,9 @@ const docTemplate = `{ "statusDetail": { "type": "string" }, + "storage": { + "$ref": "#/definitions/response.OBServerStorage" + }, "topology": { "type": "array", "items": { @@ -4039,6 +4268,20 @@ const docTemplate = `{ } } }, + "response.OBServerStorage": { + "type": "object", + "properties": { + "dataStorage": { + "$ref": "#/definitions/response.StorageSpec" + }, + "redoLogStorage": { + "$ref": "#/definitions/response.StorageSpec" + }, + "sysLogStorage": { + "$ref": "#/definitions/response.StorageSpec" + } + } + }, "response.OBTenantBrief": { "description": "Brief information about OBTenant", "type": "object", @@ -4047,7 +4290,7 @@ const docTemplate = `{ "description": "Charset of the tenant", "type": "string" }, - "clusterName": { + "clusterResourceName": { "description": "Name of the cluster belonging to", "type": "string" }, @@ -4099,7 +4342,7 @@ const docTemplate = `{ "description": "Charset of the tenant", "type": "string" }, - "clusterName": { + "clusterResourceName": { "description": "Name of the cluster belonging to", "type": "string" }, @@ -4398,6 +4641,17 @@ const docTemplate = `{ "type": "string" } } + }, + "response.StorageSpec": { + "type": "object", + "properties": { + "size": { + "type": "integer" + }, + "storageClass": { + "type": "string" + } + } } }, "securityDefinitions": { diff --git a/internal/dashboard/generated/swagger/swagger.json b/internal/dashboard/generated/swagger/swagger.json index beb95bb88..ad2cc6b9d 100644 --- a/internal/dashboard/generated/swagger/swagger.json +++ b/internal/dashboard/generated/swagger/swagger.json @@ -53,6 +53,12 @@ "description": "Object name", "name": "name", "in": "query" + }, + { + "type": "string", + "description": "Namespace", + "name": "namespace", + "in": "query" } ], "responses": { @@ -627,65 +633,6 @@ } } }, - "/api/v1/metrics/telemetry": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "get telemetry data", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Info" - ], - "summary": "get telemetry data", - "operationId": "GetStatistics", - "responses": { - "200": { - "description": "OK", - "schema": { - "allOf": [ - { - "$ref": "#/definitions/response.APIResponse" - }, - { - "type": "object", - "properties": { - "data": { - "$ref": "#/definitions/response.StatisticDataResponse" - } - } - } - ] - } - }, - "400": { - "description": "Bad Request", - "schema": { - "$ref": "#/definitions/response.APIResponse" - } - }, - "401": { - "description": "Unauthorized", - "schema": { - "$ref": "#/definitions/response.APIResponse" - } - }, - "500": { - "description": "Internal Server Error", - "schema": { - "$ref": "#/definitions/response.APIResponse" - } - } - } - } - }, "/api/v1/obclusters": { "get": { "security": [ @@ -701,7 +648,7 @@ "application/json" ], "tags": [ - "Obcluster" + "OBCluster" ], "summary": "list obclusters", "operationId": "ListOBClusters", @@ -761,7 +708,7 @@ "application/json" ], "tags": [ - "Obcluster" + "OBCluster" ], "summary": "create obcluster", "operationId": "CreateOBCluster", @@ -819,7 +766,7 @@ "application/json" ], "tags": [ - "Obcluster" + "OBCluster" ], "summary": "get obcluster", "operationId": "GetOBCluster", @@ -892,7 +839,7 @@ "application/json" ], "tags": [ - "Obcluster" + "OBCluster" ], "summary": "upgrade obcluster", "operationId": "UpgradeOBCluster", @@ -962,7 +909,7 @@ "application/json" ], "tags": [ - "Obcluster" + "OBCluster" ], "summary": "delete obcluster", "operationId": "DeleteOBCluster", @@ -1025,7 +972,7 @@ "application/json" ], "tags": [ - "Obcluster" + "OBCluster" ], "summary": "add obzone", "operationId": "AddOBZone", @@ -1097,7 +1044,7 @@ "application/json" ], "tags": [ - "Obcluster" + "OBCluster" ], "summary": "delete obzone", "operationId": "DeleteOBZone", @@ -1167,7 +1114,7 @@ "application/json" ], "tags": [ - "Obcluster" + "OBCluster" ], "summary": "scale observer", "operationId": "ScaleOBServer", @@ -1241,7 +1188,7 @@ "application/json" ], "tags": [ - "Obcluster" + "OBCluster" ], "summary": "get obcluster statistic", "operationId": "GetOBClusterStatistic", @@ -1303,7 +1250,7 @@ "application/json" ], "tags": [ - "Obcluster" + "OBCluster" ], "summary": "list essential parameters", "operationId": "ListOBClusterResources", @@ -1378,7 +1325,7 @@ "application/json" ], "tags": [ - "Obtenant" + "OBTenant" ], "summary": "List all tenants", "operationId": "ListAllTenants", @@ -1446,7 +1393,7 @@ "application/json" ], "tags": [ - "Obtenant" + "OBTenant" ], "summary": "Create tenant", "operationId": "CreateTenant", @@ -1516,7 +1463,7 @@ "application/json" ], "tags": [ - "Obtenant" + "OBTenant" ], "summary": "List statistics information of tenants", "operationId": "GetOBTenantStatistic", @@ -1578,7 +1525,7 @@ "application/json" ], "tags": [ - "Obtenant" + "OBTenant" ], "summary": "Get tenant", "operationId": "GetTenant", @@ -1651,7 +1598,7 @@ "application/json" ], "tags": [ - "Obtenant" + "OBTenant" ], "summary": "Delete tenant", "operationId": "DeleteTenant", @@ -1712,7 +1659,7 @@ "application/json" ], "tags": [ - "Obtenant" + "OBTenant" ], "summary": "Patch tenant's configuration", "operationId": "PatchTenant", @@ -1796,7 +1743,7 @@ "application/json" ], "tags": [ - "Obtenant" + "OBTenant" ], "summary": "List backup jobs of specific tenant", "operationId": "ListBackupJobs", @@ -1894,7 +1841,7 @@ "application/json" ], "tags": [ - "Obtenant" + "OBTenant" ], "summary": "Get backup policy of specific tenant", "operationId": "GetBackupPolicy", @@ -1967,7 +1914,7 @@ "application/json" ], "tags": [ - "Obtenant" + "OBTenant" ], "summary": "Create backup policy of specific tenant", "operationId": "CreateBackupPolicy", @@ -2049,7 +1996,7 @@ "application/json" ], "tags": [ - "Obtenant" + "OBTenant" ], "summary": "Delete backup policy of specific tenant", "operationId": "DeleteBackupPolicy", @@ -2117,7 +2064,7 @@ "application/json" ], "tags": [ - "Obtenant" + "OBTenant" ], "summary": "Update backup policy of specific tenant", "operationId": "UpdateBackupPolicy", @@ -2201,7 +2148,7 @@ "application/json" ], "tags": [ - "Obtenant" + "OBTenant" ], "summary": "Replay standby log of specific standby tenant", "operationId": "ReplayStandbyLog", @@ -2270,6 +2217,201 @@ } } }, + "/api/v1/obtenants/{namespace}/{name}/pools/{zoneName}": { + "put": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "Create an obtenant pool in a specific namespace", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "OBTenant" + ], + "summary": "Create obtenant pool", + "operationId": "CreateOBTenantPool", + "parameters": [ + { + "description": "create obtenant pool request body", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/param.TenantPoolSpec" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/response.APIResponse" + }, + { + "type": "object", + "properties": { + "data": { + "type": "boolean" + } + } + } + ] + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/response.APIResponse" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/response.APIResponse" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.APIResponse" + } + } + } + }, + "delete": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "Delete an obtenant pool in a specific namespace", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "OBTenant" + ], + "summary": "Delete obtenant pool", + "operationId": "DeleteOBTenantPool", + "responses": { + "200": { + "description": "OK", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/response.APIResponse" + }, + { + "type": "object", + "properties": { + "data": { + "type": "boolean" + } + } + } + ] + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/response.APIResponse" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/response.APIResponse" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.APIResponse" + } + } + } + }, + "patch": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "Patch an obtenant pool in a specific namespace", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "OBTenant" + ], + "summary": "Patch obtenant pool", + "operationId": "PatchOBTenantPool", + "parameters": [ + { + "description": "patch obtenant pool request body", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/param.TenantPoolSpec" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/response.APIResponse" + }, + { + "type": "object", + "properties": { + "data": { + "type": "boolean" + } + } + } + ] + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/response.APIResponse" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/response.APIResponse" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.APIResponse" + } + } + } + } + }, "/api/v1/obtenants/{namespace}/{name}/role": { "post": { "security": [ @@ -2285,7 +2427,7 @@ "application/json" ], "tags": [ - "Obtenant" + "OBTenant" ], "summary": "Change tenant role of specific tenant", "operationId": "ChangeTenantRole", @@ -2369,7 +2511,7 @@ "application/json" ], "tags": [ - "Obtenant" + "OBTenant" ], "summary": "Change root password of specific tenant", "operationId": "ChangeUserPassword", @@ -2453,7 +2595,7 @@ "application/json" ], "tags": [ - "Obtenant" + "OBTenant" ], "summary": "Upgrade tenant compatibility version of specific tenant", "operationId": "UpgradeTenantVersion", @@ -2512,6 +2654,65 @@ } } } + }, + "/api/v1/statistics": { + "get": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "get statistic data", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Info" + ], + "summary": "get statistic data", + "operationId": "GetStatistics", + "responses": { + "200": { + "description": "OK", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/response.APIResponse" + }, + { + "type": "object", + "properties": { + "data": { + "$ref": "#/definitions/response.StatisticDataResponse" + } + } + } + ] + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/response.APIResponse" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/response.APIResponse" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.APIResponse" + } + } + } + } } }, "definitions": { @@ -3234,7 +3435,12 @@ "type": "object", "properties": { "unitConfig": { - "$ref": "#/definitions/param.PatchUnitConfig" + "description": "Deprecated\nDescription: Deprecated, use PATCH /obtenants/:namespace/:name/pools/:zoneName instead", + "allOf": [ + { + "$ref": "#/definitions/param.PatchUnitConfig" + } + ] }, "unitNum": { "type": "integer" @@ -3374,6 +3580,17 @@ } } }, + "param.TenantPoolSpec": { + "type": "object", + "properties": { + "priority": { + "type": "integer" + }, + "unitConfig": { + "$ref": "#/definitions/param.UnitConfig" + } + } + }, "param.TenantSourceSpec": { "type": "object", "properties": { @@ -3558,6 +3775,9 @@ "bakEncryptionSecret": { "type": "string" }, + "createTime": { + "type": "string" + }, "destType": { "description": "Enum: NFS, OSS", "type": "string", @@ -3617,6 +3837,9 @@ "publicKey": { "type": "string" }, + "reportStatistics": { + "type": "boolean" + }, "version": { "type": "string" } @@ -3885,7 +4108,7 @@ "type": "string" }, "createTime": { - "type": "number" + "type": "integer" }, "image": { "type": "string" @@ -3911,6 +4134,9 @@ "$ref": "#/definitions/common.KVPair" } }, + "resource": { + "$ref": "#/definitions/common.ResourceSpec" + }, "rootPasswordSecret": { "type": "string" }, @@ -3920,6 +4146,9 @@ "statusDetail": { "type": "string" }, + "storage": { + "$ref": "#/definitions/response.OBServerStorage" + }, "topology": { "type": "array", "items": { @@ -4032,6 +4261,20 @@ } } }, + "response.OBServerStorage": { + "type": "object", + "properties": { + "dataStorage": { + "$ref": "#/definitions/response.StorageSpec" + }, + "redoLogStorage": { + "$ref": "#/definitions/response.StorageSpec" + }, + "sysLogStorage": { + "$ref": "#/definitions/response.StorageSpec" + } + } + }, "response.OBTenantBrief": { "description": "Brief information about OBTenant", "type": "object", @@ -4040,7 +4283,7 @@ "description": "Charset of the tenant", "type": "string" }, - "clusterName": { + "clusterResourceName": { "description": "Name of the cluster belonging to", "type": "string" }, @@ -4092,7 +4335,7 @@ "description": "Charset of the tenant", "type": "string" }, - "clusterName": { + "clusterResourceName": { "description": "Name of the cluster belonging to", "type": "string" }, @@ -4391,6 +4634,17 @@ "type": "string" } } + }, + "response.StorageSpec": { + "type": "object", + "properties": { + "size": { + "type": "integer" + }, + "storageClass": { + "type": "string" + } + } } }, "securityDefinitions": { diff --git a/internal/dashboard/generated/swagger/swagger.yaml b/internal/dashboard/generated/swagger/swagger.yaml index 9ab774531..eea15d2b4 100644 --- a/internal/dashboard/generated/swagger/swagger.yaml +++ b/internal/dashboard/generated/swagger/swagger.yaml @@ -485,7 +485,11 @@ definitions: param.PatchTenant: properties: unitConfig: - $ref: '#/definitions/param.PatchUnitConfig' + allOf: + - $ref: '#/definitions/param.PatchUnitConfig' + description: |- + Deprecated + Description: Deprecated, use PATCH /obtenants/:namespace/:name/pools/:zoneName instead unitNum: type: integer type: object @@ -579,6 +583,13 @@ definitions: - backupType - day type: object + param.TenantPoolSpec: + properties: + priority: + type: integer + unitConfig: + $ref: '#/definitions/param.UnitConfig' + type: object param.TenantSourceSpec: properties: restore: @@ -703,6 +714,8 @@ definitions: type: string bakEncryptionSecret: type: string + createTime: + type: string destType: description: 'Enum: NFS, OSS' example: NFS @@ -751,6 +764,8 @@ definitions: type: string publicKey: type: string + reportStatistics: + type: boolean version: type: string type: object @@ -925,7 +940,7 @@ definitions: clusterName: type: string createTime: - type: number + type: integer image: type: string metrics: @@ -942,12 +957,16 @@ definitions: items: $ref: '#/definitions/common.KVPair' type: array + resource: + $ref: '#/definitions/common.ResourceSpec' rootPasswordSecret: type: string status: type: string statusDetail: type: string + storage: + $ref: '#/definitions/response.OBServerStorage' topology: items: $ref: '#/definitions/response.OBZone' @@ -1023,13 +1042,22 @@ definitions: example: 3 type: integer type: object + response.OBServerStorage: + properties: + dataStorage: + $ref: '#/definitions/response.StorageSpec' + redoLogStorage: + $ref: '#/definitions/response.StorageSpec' + sysLogStorage: + $ref: '#/definitions/response.StorageSpec' + type: object response.OBTenantBrief: description: Brief information about OBTenant properties: charset: description: Charset of the tenant type: string - clusterName: + clusterResourceName: description: Name of the cluster belonging to type: string createTime: @@ -1067,7 +1095,7 @@ definitions: charset: description: Charset of the tenant type: string - clusterName: + clusterResourceName: description: Name of the cluster belonging to type: string createTime: @@ -1270,6 +1298,13 @@ definitions: volumeBindingMode: type: string type: object + response.StorageSpec: + properties: + size: + type: integer + storageClass: + type: string + type: object info: contact: {} description: OceanBase Dashboard @@ -1301,6 +1336,10 @@ paths: in: query name: name type: string + - description: Namespace + in: query + name: namespace + type: string produces: - application/json responses: @@ -1658,41 +1697,6 @@ paths: summary: query metrics tags: - Metric - /api/v1/metrics/telemetry: - get: - consumes: - - application/json - description: get telemetry data - operationId: GetStatistics - produces: - - application/json - responses: - "200": - description: OK - schema: - allOf: - - $ref: '#/definitions/response.APIResponse' - - properties: - data: - $ref: '#/definitions/response.StatisticDataResponse' - type: object - "400": - description: Bad Request - schema: - $ref: '#/definitions/response.APIResponse' - "401": - description: Unauthorized - schema: - $ref: '#/definitions/response.APIResponse' - "500": - description: Internal Server Error - schema: - $ref: '#/definitions/response.APIResponse' - security: - - ApiKeyAuth: [] - summary: get telemetry data - tags: - - Info /api/v1/obclusters: get: consumes: @@ -1729,7 +1733,7 @@ paths: - ApiKeyAuth: [] summary: list obclusters tags: - - Obcluster + - OBCluster post: consumes: - application/json @@ -1765,7 +1769,7 @@ paths: - ApiKeyAuth: [] summary: create obcluster tags: - - Obcluster + - OBCluster /api/v1/obclusters/{namespace}/{name}/essential-parameters: get: consumes: @@ -1811,7 +1815,7 @@ paths: - ApiKeyAuth: [] summary: list essential parameters tags: - - Obcluster + - OBCluster /api/v1/obclusters/namespace/{namespace}/name/{name}: delete: consumes: @@ -1852,7 +1856,7 @@ paths: - ApiKeyAuth: [] summary: delete obcluster tags: - - Obcluster + - OBCluster get: consumes: - application/json @@ -1897,7 +1901,7 @@ paths: - ApiKeyAuth: [] summary: get obcluster tags: - - Obcluster + - OBCluster post: consumes: - application/json @@ -1943,7 +1947,7 @@ paths: - ApiKeyAuth: [] summary: upgrade obcluster tags: - - Obcluster + - OBCluster /api/v1/obclusters/namespace/{namespace}/name/{name}/obzones: post: consumes: @@ -1990,7 +1994,7 @@ paths: - ApiKeyAuth: [] summary: add obzone tags: - - Obcluster + - OBCluster /api/v1/obclusters/namespace/{namespace}/name/{name}/obzones/{obzoneName}: delete: consumes: @@ -2036,7 +2040,7 @@ paths: - ApiKeyAuth: [] summary: delete obzone tags: - - Obcluster + - OBCluster /api/v1/obclusters/namespace/{namespace}/name/{name}/obzones/{obzoneName}/scale: post: consumes: @@ -2088,7 +2092,7 @@ paths: - ApiKeyAuth: [] summary: scale observer tags: - - Obcluster + - OBCluster /api/v1/obclusters/statistic: get: consumes: @@ -2123,7 +2127,7 @@ paths: $ref: '#/definitions/response.APIResponse' summary: get obcluster statistic tags: - - Obcluster + - OBCluster /api/v1/obtenants: get: consumes: @@ -2165,7 +2169,7 @@ paths: - ApiKeyAuth: [] summary: List all tenants tags: - - Obtenant + - OBTenant put: consumes: - application/json @@ -2207,7 +2211,7 @@ paths: - ApiKeyAuth: [] summary: Create tenant tags: - - Obtenant + - OBTenant /api/v1/obtenants/{namespace}/{name}: delete: consumes: @@ -2249,7 +2253,7 @@ paths: - ApiKeyAuth: [] summary: Delete tenant tags: - - Obtenant + - OBTenant get: consumes: - application/json @@ -2294,7 +2298,7 @@ paths: - ApiKeyAuth: [] summary: Get tenant tags: - - Obtenant + - OBTenant patch: consumes: - application/json @@ -2345,7 +2349,7 @@ paths: - ApiKeyAuth: [] summary: Patch tenant's configuration tags: - - Obtenant + - OBTenant /api/v1/obtenants/{namespace}/{name}/backup/{type}/jobs: get: consumes: @@ -2408,7 +2412,7 @@ paths: - ApiKeyAuth: [] summary: List backup jobs of specific tenant tags: - - Obtenant + - OBTenant /api/v1/obtenants/{namespace}/{name}/backupPolicy: delete: consumes: @@ -2454,7 +2458,7 @@ paths: - ApiKeyAuth: [] summary: Delete backup policy of specific tenant tags: - - Obtenant + - OBTenant get: consumes: - application/json @@ -2499,7 +2503,7 @@ paths: - ApiKeyAuth: [] summary: Get backup policy of specific tenant tags: - - Obtenant + - OBTenant patch: consumes: - application/json @@ -2550,7 +2554,7 @@ paths: - ApiKeyAuth: [] summary: Update backup policy of specific tenant tags: - - Obtenant + - OBTenant put: consumes: - application/json @@ -2602,7 +2606,7 @@ paths: - ApiKeyAuth: [] summary: Create backup policy of specific tenant tags: - - Obtenant + - OBTenant /api/v1/obtenants/{namespace}/{name}/logreplay: post: consumes: @@ -2654,7 +2658,124 @@ paths: - ApiKeyAuth: [] summary: Replay standby log of specific standby tenant tags: - - Obtenant + - OBTenant + /api/v1/obtenants/{namespace}/{name}/pools/{zoneName}: + delete: + consumes: + - application/json + description: Delete an obtenant pool in a specific namespace + operationId: DeleteOBTenantPool + produces: + - application/json + responses: + "200": + description: OK + schema: + allOf: + - $ref: '#/definitions/response.APIResponse' + - properties: + data: + type: boolean + type: object + "400": + description: Bad Request + schema: + $ref: '#/definitions/response.APIResponse' + "401": + description: Unauthorized + schema: + $ref: '#/definitions/response.APIResponse' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/response.APIResponse' + security: + - ApiKeyAuth: [] + summary: Delete obtenant pool + tags: + - OBTenant + patch: + consumes: + - application/json + description: Patch an obtenant pool in a specific namespace + operationId: PatchOBTenantPool + parameters: + - description: patch obtenant pool request body + in: body + name: body + required: true + schema: + $ref: '#/definitions/param.TenantPoolSpec' + produces: + - application/json + responses: + "200": + description: OK + schema: + allOf: + - $ref: '#/definitions/response.APIResponse' + - properties: + data: + type: boolean + type: object + "400": + description: Bad Request + schema: + $ref: '#/definitions/response.APIResponse' + "401": + description: Unauthorized + schema: + $ref: '#/definitions/response.APIResponse' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/response.APIResponse' + security: + - ApiKeyAuth: [] + summary: Patch obtenant pool + tags: + - OBTenant + put: + consumes: + - application/json + description: Create an obtenant pool in a specific namespace + operationId: CreateOBTenantPool + parameters: + - description: create obtenant pool request body + in: body + name: body + required: true + schema: + $ref: '#/definitions/param.TenantPoolSpec' + produces: + - application/json + responses: + "200": + description: OK + schema: + allOf: + - $ref: '#/definitions/response.APIResponse' + - properties: + data: + type: boolean + type: object + "400": + description: Bad Request + schema: + $ref: '#/definitions/response.APIResponse' + "401": + description: Unauthorized + schema: + $ref: '#/definitions/response.APIResponse' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/response.APIResponse' + security: + - ApiKeyAuth: [] + summary: Create obtenant pool + tags: + - OBTenant /api/v1/obtenants/{namespace}/{name}/role: post: consumes: @@ -2707,7 +2828,7 @@ paths: - ApiKeyAuth: [] summary: Change tenant role of specific tenant tags: - - Obtenant + - OBTenant /api/v1/obtenants/{namespace}/{name}/userCredentials: post: consumes: @@ -2759,7 +2880,7 @@ paths: - ApiKeyAuth: [] summary: Change root password of specific tenant tags: - - Obtenant + - OBTenant /api/v1/obtenants/{namespace}/{name}/version: post: consumes: @@ -2806,7 +2927,7 @@ paths: - ApiKeyAuth: [] summary: Upgrade tenant compatibility version of specific tenant tags: - - Obtenant + - OBTenant /api/v1/obtenants/statistic: get: consumes: @@ -2843,7 +2964,42 @@ paths: - ApiKeyAuth: [] summary: List statistics information of tenants tags: - - Obtenant + - OBTenant + /api/v1/statistics: + get: + consumes: + - application/json + description: get statistic data + operationId: GetStatistics + produces: + - application/json + responses: + "200": + description: OK + schema: + allOf: + - $ref: '#/definitions/response.APIResponse' + - properties: + data: + $ref: '#/definitions/response.StatisticDataResponse' + type: object + "400": + description: Bad Request + schema: + $ref: '#/definitions/response.APIResponse' + "401": + description: Unauthorized + schema: + $ref: '#/definitions/response.APIResponse' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/response.APIResponse' + security: + - ApiKeyAuth: [] + summary: get statistic data + tags: + - Info securityDefinitions: ApiKeyAuth: in: header diff --git a/internal/dashboard/handler/info_handler.go b/internal/dashboard/handler/info_handler.go index c1b656179..e124a46b4 100644 --- a/internal/dashboard/handler/info_handler.go +++ b/internal/dashboard/handler/info_handler.go @@ -60,8 +60,8 @@ func GetProcessInfo(_ *gin.Context) (*response.DashboardInfo, error) { } // @ID GetStatistics -// @Summary get telemetry data -// @Description get telemetry data +// @Summary get statistic data +// @Description get statistic data // @Tags Info // @Accept application/json // @Produce application/json @@ -69,7 +69,7 @@ func GetProcessInfo(_ *gin.Context) (*response.DashboardInfo, error) { // @Failure 400 object response.APIResponse // @Failure 401 object response.APIResponse // @Failure 500 object response.APIResponse -// @Router /api/v1/metrics/telemetry [GET] +// @Router /api/v1/statistics [GET] // @Security ApiKeyAuth func GetStatistics(c *gin.Context) (*response.StatisticDataResponse, error) { reportData := response.StatisticData{} diff --git a/internal/dashboard/handler/k8s_handler.go b/internal/dashboard/handler/k8s_handler.go index 9a12e15cc..f21d44c8f 100644 --- a/internal/dashboard/handler/k8s_handler.go +++ b/internal/dashboard/handler/k8s_handler.go @@ -30,6 +30,7 @@ import ( // @Param objectType query string false "related object types" Enums(OBCLUSTER, OBTENANT) // @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 // @Success 200 object response.APIResponse{data=[]response.K8sEvent} // @Failure 400 object response.APIResponse // @Failure 401 object response.APIResponse diff --git a/internal/dashboard/handler/obcluster_handler.go b/internal/dashboard/handler/obcluster_handler.go index b9efda0d7..7fa9d354c 100644 --- a/internal/dashboard/handler/obcluster_handler.go +++ b/internal/dashboard/handler/obcluster_handler.go @@ -26,7 +26,7 @@ import ( // @ID GetOBClusterStatistic // @Summary get obcluster statistic // @Description get obcluster statistic info -// @Tags Obcluster +// @Tags OBCluster // @Accept application/json // @Produce application/json // @Success 200 object response.APIResponse{data=[]response.OBClusterStastistic} @@ -46,7 +46,7 @@ func GetOBClusterStatistic(c *gin.Context) ([]response.OBClusterStastistic, erro // @ID ListOBClusters // @Summary list obclusters // @Description list obclusters -// @Tags Obcluster +// @Tags OBCluster // @Accept application/json // @Produce application/json // @Success 200 object response.APIResponse{data=[]response.OBCluster} @@ -66,7 +66,7 @@ func ListOBClusters(c *gin.Context) ([]response.OBCluster, error) { // @ID GetOBCluster // @Summary get obcluster // @Description get obcluster detailed info -// @Tags Obcluster +// @Tags OBCluster // @Accept application/json // @Produce application/json // @Param namespace path string true "obcluster namespace" @@ -93,7 +93,7 @@ func GetOBCluster(c *gin.Context) (*response.OBCluster, error) { // @ID CreateOBCluster // @Summary create obcluster // @Description create obcluster -// @Tags Obcluster +// @Tags OBCluster // @Accept application/json // @Produce application/json // @Param body body param.CreateOBClusterParam true "create obcluster request body" @@ -124,7 +124,7 @@ func CreateOBCluster(c *gin.Context) (any, error) { // @ID UpgradeOBCluster // @Summary upgrade obcluster // @Description upgrade obcluster -// @Tags Obcluster +// @Tags OBCluster // @Accept application/json // @Produce application/json // @Param namespace path string true "obcluster namespace" @@ -157,7 +157,7 @@ func UpgradeOBCluster(c *gin.Context) (any, error) { // @ID DeleteOBCluster // @Summary delete obcluster // @Description delete obcluster -// @Tags Obcluster +// @Tags OBCluster // @Accept application/json // @Produce application/json // @Param namespace path string true "obcluster namespace" @@ -184,7 +184,7 @@ func DeleteOBCluster(c *gin.Context) (any, error) { // @ID AddOBZone // @Summary add obzone // @Description add obzone -// @Tags Obcluster +// @Tags OBCluster // @Accept application/json // @Produce application/json // @Param namespace path string true "obcluster namespace" @@ -217,7 +217,7 @@ func AddOBZone(c *gin.Context) (any, error) { // @ID ScaleOBServer // @Summary scale observer // @Description scale observer -// @Tags Obcluster +// @Tags OBCluster // @Accept application/json // @Produce application/json // @Param namespace path string true "obcluster namespace" @@ -251,7 +251,7 @@ func ScaleOBServer(c *gin.Context) (any, error) { // @ID DeleteOBZone // @Summary delete obzone // @Description delete obzone -// @Tags Obcluster +// @Tags OBCluster // @Accept application/json // @Produce application/json // @Param namespace path string true "obcluster namespace" @@ -279,7 +279,7 @@ func DeleteOBZone(c *gin.Context) (any, error) { // @ID ListOBClusterResources // @Summary list essential parameters // @Description list essential parameters of specific obcluster -// @Tags Obcluster +// @Tags OBCluster // @Accept application/json // @Produce application/json // @Param namespace path string true "obcluster namespace" diff --git a/internal/dashboard/handler/obtenant_handler.go b/internal/dashboard/handler/obtenant_handler.go index 4af52dfd8..37d475980 100644 --- a/internal/dashboard/handler/obtenant_handler.go +++ b/internal/dashboard/handler/obtenant_handler.go @@ -31,7 +31,7 @@ import ( ) // @ID ListAllTenants -// @Tags Obtenant +// @Tags OBTenant // @Summary List all tenants // @Description List all tenants and return them // @Accept application/json @@ -70,7 +70,7 @@ func ListAllTenants(c *gin.Context) ([]*response.OBTenantBrief, error) { } // @ID GetTenant -// @Tags Obtenant +// @Tags OBTenant // @Summary Get tenant // @Description Get an obtenant in a specific namespace // @Accept application/json @@ -103,7 +103,7 @@ func GetTenant(c *gin.Context) (*response.OBTenantDetail, error) { } // @ID CreateTenant -// @Tags Obtenant +// @Tags OBTenant // @Summary Create tenant // @Description Create an obtenant in a specific namespace, passwords should be encrypted by AES // @Accept application/json @@ -155,7 +155,7 @@ func CreateTenant(c *gin.Context) (*response.OBTenantDetail, error) { } // @ID DeleteTenant -// @Tags Obtenant +// @Tags OBTenant // @Summary Delete tenant // @Description Delete an obtenant in a specific namespace, ask user to confrim the deletion carefully // @Accept application/json @@ -188,7 +188,7 @@ func DeleteTenant(c *gin.Context) (any, error) { } // @ID PatchTenant -// @Tags Obtenant +// @Tags OBTenant // @Summary Patch tenant's configuration // @Description Patch tenant's configuration // @Accept application/json @@ -227,7 +227,7 @@ func PatchTenant(c *gin.Context) (*response.OBTenantDetail, error) { } // @ID ChangeUserPassword -// @Tags Obtenant +// @Tags OBTenant // @Summary Change root password of specific tenant // @Description Change root password of specific tenant, encrypted by AES // @Accept application/json @@ -267,7 +267,7 @@ func ChangeUserPassword(c *gin.Context) (*response.OBTenantDetail, error) { } // @ID ReplayStandbyLog -// @Tags Obtenant +// @Tags OBTenant // @Summary Replay standby log of specific standby tenant // @Description Replay standby log of specific standby tenant // @Accept application/json @@ -306,7 +306,7 @@ func ReplayStandbyLog(c *gin.Context) (*response.OBTenantDetail, error) { } // @ID UpgradeTenantVersion -// @Tags Obtenant +// @Tags OBTenant // @Summary Upgrade tenant compatibility version of specific tenant // @Description Upgrade tenant compatibility version of specific tenant to match the version of cluster // @Accept application/json @@ -336,7 +336,7 @@ func UpgradeTenantVersion(c *gin.Context) (*response.OBTenantDetail, error) { } // @ID ChangeTenantRole -// @Tags Obtenant +// @Tags OBTenant // @Summary Change tenant role of specific tenant // @Description Change tenant role of specific tenant, if a tenant is a standby tenant, it can be changed to primary tenant, vice versa // @Accept application/json @@ -375,7 +375,7 @@ func ChangeTenantRole(c *gin.Context) (*response.OBTenantDetail, error) { } // @ID CreateBackupPolicy -// @Tags Obtenant +// @Tags OBTenant // @Summary Create backup policy of specific tenant // @Description Create backup policy of specific tenant, passwords should be encrypted by AES // @Accept application/json @@ -427,7 +427,7 @@ func CreateBackupPolicy(c *gin.Context) (*response.BackupPolicy, error) { } // @ID UpdateBackupPolicy -// @Tags Obtenant +// @Tags OBTenant // @Summary Update backup policy of specific tenant // @Description Update backup policy of specific tenant // @Accept application/json @@ -463,7 +463,7 @@ func UpdateBackupPolicy(c *gin.Context) (*response.BackupPolicy, error) { } // @ID DeleteBackupPolicy -// @Tags Obtenant +// @Tags OBTenant // @Summary Delete backup policy of specific tenant // @Description Delete backup policy of specific tenant // @Accept application/json @@ -494,7 +494,7 @@ func DeleteBackupPolicy(c *gin.Context) (*response.OBTenantDetail, error) { } // @ID GetBackupPolicy -// @Tags Obtenant +// @Tags OBTenant // @Summary Get backup policy of specific tenant // @Description Get backup policy of specific tenant // @Accept application/json @@ -524,7 +524,7 @@ func GetBackupPolicy(c *gin.Context) (*response.BackupPolicy, error) { } // @ID ListBackupJobs -// @Tags Obtenant +// @Tags OBTenant // @Summary List backup jobs of specific tenant // @Description List backup jobs of specific tenant // @Accept application/json @@ -568,7 +568,7 @@ func ListBackupJobs(c *gin.Context) ([]*response.BackupJob, error) { } // @ID GetOBTenantStatistic -// @Tags Obtenant +// @Tags OBTenant // @Summary List statistics information of tenants // @Description List statistics information of tenants // @Accept application/json @@ -586,3 +586,83 @@ func GetOBTenantStatistic(c *gin.Context) ([]response.OBTenantStatistic, error) } return tenants, nil } + +// @ID CreateOBTenantPool +// @Tags OBTenant +// @Summary Create obtenant pool +// @Description Create an obtenant pool in a specific namespace +// @Accept application/json +// @Produce application/json +// @Param body body param.TenantPoolSpec true "create obtenant pool request body" +// @Success 200 object response.APIResponse{data=bool} +// @Failure 400 object response.APIResponse +// @Failure 401 object response.APIResponse +// @Failure 500 object response.APIResponse +// @Router /api/v1/obtenants/{namespace}/{name}/pools/{zoneName} [PUT] +// @Security ApiKeyAuth +func CreateOBTenantPool(c *gin.Context) (bool, error) { + nn := param.TenantPoolName{} + err := c.BindUri(&nn) + if err != nil { + return false, httpErr.NewBadRequest(err.Error()) + } + + p := param.TenantPoolSpec{} + err = c.BindJSON(&p) + if err != nil { + return false, httpErr.NewBadRequest(err.Error()) + } + + return oceanbase.CreateTenantPool(c, nn, &p) +} + +// @ID DeleteOBTenantPool +// @Tags OBTenant +// @Summary Delete obtenant pool +// @Description Delete an obtenant pool in a specific namespace +// @Accept application/json +// @Produce application/json +// @Success 200 object response.APIResponse{data=bool} +// @Failure 400 object response.APIResponse +// @Failure 401 object response.APIResponse +// @Failure 500 object response.APIResponse +// @Router /api/v1/obtenants/{namespace}/{name}/pools/{zoneName} [DELETE] +// @Security ApiKeyAuth +func DeleteOBTenantPool(c *gin.Context) (bool, error) { + nn := param.TenantPoolName{} + err := c.BindUri(&nn) + if err != nil { + return false, httpErr.NewBadRequest(err.Error()) + } + + return oceanbase.DeleteTenantPool(c, nn) +} + +// @ID PatchOBTenantPool +// @Tags OBTenant +// @Summary Patch obtenant pool +// @Description Patch an obtenant pool in a specific namespace +// @Accept application/json +// @Produce application/json +// @Param body body param.TenantPoolSpec true "patch obtenant pool request body" +// @Success 200 object response.APIResponse{data=bool} +// @Failure 400 object response.APIResponse +// @Failure 401 object response.APIResponse +// @Failure 500 object response.APIResponse +// @Router /api/v1/obtenants/{namespace}/{name}/pools/{zoneName} [PATCH] +// @Security ApiKeyAuth +func PatchOBTenantPool(c *gin.Context) (bool, error) { + nn := param.TenantPoolName{} + err := c.BindUri(&nn) + if err != nil { + return false, httpErr.NewBadRequest(err.Error()) + } + + p := param.TenantPoolSpec{} + err = c.BindJSON(&p) + if err != nil { + return false, httpErr.NewBadRequest(err.Error()) + } + + return oceanbase.PatchTenantPool(c, nn, &p) +} diff --git a/internal/dashboard/model/param/obtenant_param.go b/internal/dashboard/model/param/obtenant_param.go index 4e2cef765..2d43d3b0d 100644 --- a/internal/dashboard/model/param/obtenant_param.go +++ b/internal/dashboard/model/param/obtenant_param.go @@ -89,6 +89,18 @@ type PatchUnitConfig struct { } type PatchTenant struct { - UnitNumber *int `json:"unitNum,omitempty"` + UnitNumber *int `json:"unitNum,omitempty"` + // Deprecated + // Description: Deprecated, use PATCH /obtenants/:namespace/:name/pools/:zoneName instead UnitConfig *PatchUnitConfig `json:"unitConfig,omitempty"` } + +type TenantPoolSpec struct { + Priority int `json:"priority"` + UnitConfig UnitConfig `json:"unitConfig"` +} + +type TenantPoolName struct { + NamespacedName `json:",inline"` + ZoneName string `json:"zoneName" uri:"zoneName"` +} diff --git a/internal/dashboard/model/response/backup.go b/internal/dashboard/model/response/backup.go index 183dc9d64..235b2b0be 100644 --- a/internal/dashboard/model/response/backup.go +++ b/internal/dashboard/model/response/backup.go @@ -23,6 +23,8 @@ type BackupPolicy struct { Status string `json:"status"` OSSAccessSecret string `json:"ossAccessSecret,omitempty"` BakEncryptionSecret string `json:"bakEncryptionSecret,omitempty"` + + CreateTime string `json:"createTime"` } type BackupJob struct { diff --git a/internal/dashboard/model/response/obcluster.go b/internal/dashboard/model/response/obcluster.go index 96200c175..4f75eb570 100644 --- a/internal/dashboard/model/response/obcluster.go +++ b/internal/dashboard/model/response/obcluster.go @@ -59,7 +59,7 @@ type OBCluster struct { Topology []OBZone `json:"topology"` Status string `json:"status"` StatusDetail string `json:"statusDetail"` - CreateTime float64 `json:"createTime"` + CreateTime int64 `json:"createTime"` Image string `json:"image"` Metrics *OBMetrics `json:"metrics"` Version string `json:"version"` @@ -68,6 +68,9 @@ type OBCluster struct { } type OBClusterExtra struct { + Resource common.ResourceSpec `json:"resource"` + Storage OBServerStorage `json:"storage"` + RootPasswordSecret string `json:"rootPasswordSecret"` Parameters []common.KVPair `json:"parameters"` Monitor *MonitorSpec `json:"monitor"` @@ -85,6 +88,17 @@ type NFSVolumeSpec struct { Path string `json:"path"` } +type OBServerStorage struct { + DataStorage StorageSpec `json:"dataStorage"` + RedoLogStorage StorageSpec `json:"redoLogStorage"` + SysLogStorage StorageSpec `json:"sysLogStorage"` +} + +type StorageSpec struct { + StorageClass string `json:"storageClass"` + SizeGB int64 `json:"size"` +} + type OBClusterResources struct { MinPoolMemory int64 `json:"minPoolMemory" example:"2147483648"` OBServerResources []OBServerAvailableResource `json:"obServerResources"` diff --git a/internal/dashboard/model/response/obtenant.go b/internal/dashboard/model/response/obtenant.go index 0018f0563..72da32e63 100644 --- a/internal/dashboard/model/response/obtenant.go +++ b/internal/dashboard/model/response/obtenant.go @@ -14,17 +14,17 @@ package response // @Description Brief information about OBTenant type OBTenantBrief struct { - Name string `json:"name"` // Name of the resource - Namespace string `json:"namespace"` // Namespace of the resource - TenantName string `json:"tenantName"` // Name of the tenant in the database - ClusterName string `json:"clusterName"` // Name of the cluster belonging to - TenantRole string `json:"tenantRole"` // Enum: Primary, Standby - UnitNumber int `json:"unitNumber"` // Number of units in every zone - Topology []OBTenantReplica `json:"topology"` // Topology of the tenant - Status string `json:"status"` // Status of the tenant - CreateTime string `json:"createTime"` // Creation time of the tenant - Locality string `json:"locality"` // Locality of the tenant units - Charset string `json:"charset"` // Charset of the tenant + Name string `json:"name"` // Name of the resource + Namespace string `json:"namespace"` // Namespace of the resource + TenantName string `json:"tenantName"` // Name of the tenant in the database + ClusterName string `json:"clusterResourceName"` // Name of the cluster belonging to + TenantRole string `json:"tenantRole"` // Enum: Primary, Standby + UnitNumber int `json:"unitNumber"` // Number of units in every zone + Topology []OBTenantReplica `json:"topology"` // Topology of the tenant + Status string `json:"status"` // Status of the tenant + CreateTime string `json:"createTime"` // Creation time of the tenant + Locality string `json:"locality"` // Locality of the tenant units + Charset string `json:"charset"` // Charset of the tenant } type OBTenantDetail struct { diff --git a/internal/dashboard/router/v1/info_router.go b/internal/dashboard/router/v1/info_router.go index 6ece93760..c86d22fb6 100644 --- a/internal/dashboard/router/v1/info_router.go +++ b/internal/dashboard/router/v1/info_router.go @@ -20,4 +20,5 @@ import ( func InitInfoRoutes(g *gin.RouterGroup) { g.GET("/info", h.Wrap(h.GetProcessInfo)) + g.GET("/statstics", h.Wrap(h.GetStatistics)) } diff --git a/internal/dashboard/router/v1/metric_router.go b/internal/dashboard/router/v1/metric_router.go index 9b6b76f74..3f8fe511a 100644 --- a/internal/dashboard/router/v1/metric_router.go +++ b/internal/dashboard/router/v1/metric_router.go @@ -21,5 +21,4 @@ import ( func InitMetricRoutes(g *gin.RouterGroup) { g.GET("/metrics", h.Wrap(h.ListMetricMetas)) g.POST("/metrics/query", h.Wrap(h.QueryMetrics)) - g.GET("/metrics/telemetry", h.Wrap(h.GetStatistics)) } diff --git a/internal/dashboard/router/v1/obtenant_router.go b/internal/dashboard/router/v1/obtenant_router.go index 81609bc24..b06357ac5 100644 --- a/internal/dashboard/router/v1/obtenant_router.go +++ b/internal/dashboard/router/v1/obtenant_router.go @@ -34,4 +34,7 @@ func InitOBTenantRoutes(g *gin.RouterGroup) { g.DELETE("/obtenants/:namespace/:name/backupPolicy", h.Wrap(h.DeleteBackupPolicy)) g.GET("/obtenants/:namespace/:name/backup/:type/jobs", h.Wrap(h.ListBackupJobs)) g.GET("/obtenants/statistic", h.Wrap(h.GetOBTenantStatistic)) + g.PUT("/obtenants/:namespace/:name/pools/:zoneName", h.Wrap(h.CreateOBTenantPool)) + g.DELETE("/obtenants/:namespace/:name/pools/:zoneName", h.Wrap(h.DeleteOBTenantPool)) + g.PATCH("/obtenants/:namespace/:name/pools/:zoneName", h.Wrap(h.PatchOBTenantPool)) } diff --git a/make/dashboard.mk b/make/dashboard.mk index 73e634328..9afd26f3c 100644 --- a/make/dashboard.mk +++ b/make/dashboard.mk @@ -7,7 +7,7 @@ PWD ?= $(shell pwd) DASHBOARD_VERSION ?= 1.0.0 COMMIT_HASH ?= $(shell git rev-parse --short HEAD) BUILD_TIMESTAMP ?= $(shell date '+%Y%m%d%H%M%S') -INJECT_PACKAGE=github.com/oceanbase/oceanbase-operator/internal/handler +INJECT_PACKAGE=github.com/oceanbase/ob-operator/internal/dashboard/handler BUILD_FLAG := -p $(PROCESSOR) -ldflags="-X '$(INJECT_PACKAGE).Version=$(DASHBOARD_VERSION)' -X '$(INJECT_PACKAGE).CommitHash=$(COMMIT_HASH)' -X '$(INJECT_PACKAGE).BuildTime=$(BUILD_TIMESTAMP)'" GOBUILD := go build $(BUILD_FLAG)