diff --git a/models/tenant_logs.go b/models/tenant_logs.go index 0b51d141f..3a9c015d7 100644 --- a/models/tenant_logs.go +++ b/models/tenant_logs.go @@ -66,6 +66,18 @@ type TenantLogs struct { // labels Labels []*Label `json:"labels"` + // log CPU request + LogCPURequest string `json:"logCPURequest,omitempty"` + + // log d b CPU request + LogDBCPURequest string `json:"logDBCPURequest,omitempty"` + + // log d b mem request + LogDBMemRequest string `json:"logDBMemRequest,omitempty"` + + // log mem request + LogMemRequest string `json:"logMemRequest,omitempty"` + // node selector NodeSelector []*NodeSelector `json:"nodeSelector"` diff --git a/operatorapi/embedded_spec.go b/operatorapi/embedded_spec.go index 49f101704..ed506b61a 100644 --- a/operatorapi/embedded_spec.go +++ b/operatorapi/embedded_spec.go @@ -3368,6 +3368,18 @@ func init() { "$ref": "#/definitions/label" } }, + "logCPURequest": { + "type": "string" + }, + "logDBCPURequest": { + "type": "string" + }, + "logDBMemRequest": { + "type": "string" + }, + "logMemRequest": { + "type": "string" + }, "nodeSelector": { "type": "array", "items": { @@ -7619,6 +7631,18 @@ func init() { "$ref": "#/definitions/label" } }, + "logCPURequest": { + "type": "string" + }, + "logDBCPURequest": { + "type": "string" + }, + "logDBMemRequest": { + "type": "string" + }, + "logMemRequest": { + "type": "string" + }, "nodeSelector": { "type": "array", "items": { diff --git a/operatorapi/operator_tenants.go b/operatorapi/operator_tenants.go index 9ea591c34..99fb7d3d3 100644 --- a/operatorapi/operator_tenants.go +++ b/operatorapi/operator_tenants.go @@ -28,6 +28,7 @@ import ( "net" "net/http" "os" + "reflect" "sort" "strconv" "strings" @@ -237,6 +238,7 @@ func registerTenantHandlers(api *operations.OperatorAPI) { //Get tenant monitoring info api.OperatorAPIGetTenantMonitoringHandler = operator_api.GetTenantMonitoringHandlerFunc(func(params operator_api.GetTenantMonitoringParams, session *models.Principal) middleware.Responder { + payload, err := getTenantMonitoringResponse(session, params) if err != nil { return operator_api.NewGetTenantMonitoringDefault(int(err.Code)).WithPayload(err) @@ -1789,14 +1791,6 @@ func getTenantLogsResponse(session *models.Principal, params operator_api.GetTen minTenant.Spec.Log.Audit = &miniov2.AuditConfig{DiskCapacityGB: swag.Int(0)} } - /*if minTenant.Spec.Log.Image == "" { - minTenant.Spec.Log.Image = miniov2.DefaultLogSearchAPIImage - } - - if minTenant.Spec.Log.Db.Image == "" { - minTenant.Spec.Log.Db.Image = miniov2.LogPgImage - }*/ - retval := &models.TenantLogs{ Image: minTenant.Spec.Log.Image, DiskCapacityGB: fmt.Sprintf("%d", *minTenant.Spec.Log.Audit.DiskCapacityGB), @@ -1811,11 +1805,33 @@ func getTenantLogsResponse(session *models.Principal, params operator_api.GetTen DbServiceAccountName: minTenant.Spec.Log.Db.ServiceAccountName, Disabled: false, } + + var requestedCPU string + var requestedMem string + var requestedDBCPU string + var requestedDBMem string + if minTenant.Spec.Log.Resources.Requests != nil { + requestedCPUQ := minTenant.Spec.Log.Resources.Requests["cpu"] + requestedCPU = strconv.FormatInt(requestedCPUQ.Value(), 10) + requestedMemQ := minTenant.Spec.Log.Resources.Requests["memory"] + requestedMem = strconv.FormatInt(requestedMemQ.Value(), 10) + + requestedDBCPUQ := minTenant.Spec.Log.Db.Resources.Requests["cpu"] + requestedDBCPU = strconv.FormatInt(requestedDBCPUQ.Value(), 10) + requestedDBMemQ := minTenant.Spec.Log.Db.Resources.Requests["memory"] + requestedDBMem = strconv.FormatInt(requestedDBMemQ.Value(), 10) + + retval.LogCPURequest = requestedCPU + retval.LogMemRequest = requestedMem + retval.LogDBCPURequest = requestedDBCPU + retval.LogDBMemRequest = requestedDBMem + } return retval, nil } // setTenantLogsResponse returns the logs of a tenant func setTenantLogsResponse(session *models.Principal, params operator_api.SetTenantLogsParams) (bool, *models.Error) { + // 30 seconds timeout ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) defer cancel() @@ -1833,6 +1849,7 @@ func setTenantLogsResponse(session *models.Principal, params operator_api.SetTen if err != nil { return false, prepareError(err, errorUnableToGetTenantUsage) } + var labels = make(map[string]string) for i := 0; i < len(params.Data.Labels); i++ { if params.Data.Labels[i] != nil { @@ -1854,6 +1871,26 @@ func setTenantLogsResponse(session *models.Principal, params operator_api.SetTen } } minTenant.Spec.Log.NodeSelector = nodeSelector + logResourceRequest := make(corev1.ResourceList) + + if reflect.TypeOf(params.Data.LogCPURequest).Kind() == reflect.String && params.Data.LogCPURequest != "0Gi" && params.Data.LogCPURequest != "" { + cpuQuantity, err := resource.ParseQuantity(params.Data.LogCPURequest) + if err != nil { + return false, prepareError(err) + } + logResourceRequest["cpu"] = cpuQuantity + minTenant.Spec.Log.Resources.Requests = logResourceRequest + } + if reflect.TypeOf(params.Data.LogMemRequest).Kind() == reflect.String { + memQuantity, err := resource.ParseQuantity(params.Data.LogMemRequest) + if err != nil { + return false, prepareError(err) + } + + logResourceRequest["memory"] = memQuantity + minTenant.Spec.Log.Resources.Requests = logResourceRequest + } + modified := false if minTenant.Spec.Log.Db != nil { modified = true @@ -1879,6 +1916,24 @@ func setTenantLogsResponse(session *models.Principal, params operator_api.SetTen } modified = true } + + logDBResourceRequest := make(corev1.ResourceList) + if reflect.TypeOf(params.Data.LogDBCPURequest).Kind() == reflect.String && params.Data.LogDBCPURequest != "0Gi" && params.Data.LogDBCPURequest != "" { + dbCPUQuantity, err := resource.ParseQuantity(params.Data.LogDBCPURequest) + if err != nil { + return false, prepareError(err) + } + logDBResourceRequest["cpu"] = dbCPUQuantity + minTenant.Spec.Log.Db.Resources.Requests = logDBResourceRequest + } + if reflect.TypeOf(params.Data.LogDBMemRequest).Kind() == reflect.String { + dbMemQuantity, err := resource.ParseQuantity(params.Data.LogDBMemRequest) + if err != nil { + return false, prepareError(err) + } + logDBResourceRequest["memory"] = dbMemQuantity + minTenant.Spec.Log.Db.Resources.Requests = logDBResourceRequest + } minTenant.Spec.Log.Image = params.Data.Image diskCapacityGB, err := strconv.Atoi(params.Data.DiskCapacityGB) if err == nil { @@ -1922,6 +1977,9 @@ func setTenantLogsResponse(session *models.Principal, params operator_api.SetTen NodeSelector: dbNodeSelector, Image: params.Data.DbImage, ServiceAccountName: params.Data.DbServiceAccountName, + Resources: corev1.ResourceRequirements{ + Requests: minTenant.Spec.Log.Db.Resources.Requests, + }, } } else { minTenant.Spec.Log.Db.Labels = dbLabels @@ -1931,6 +1989,7 @@ func setTenantLogsResponse(session *models.Principal, params operator_api.SetTen minTenant.Spec.Log.Db.ServiceAccountName = params.Data.DbServiceAccountName } } + _, err = opClient.TenantUpdate(ctx, minTenant, metav1.UpdateOptions{}) if err != nil { return false, prepareError(err) diff --git a/portal-ui/src/screens/Console/Tenants/ListTenants/types.ts b/portal-ui/src/screens/Console/Tenants/ListTenants/types.ts index 3fe726ddb..18ea1e2c8 100644 --- a/portal-ui/src/screens/Console/Tenants/ListTenants/types.ts +++ b/portal-ui/src/screens/Console/Tenants/ListTenants/types.ts @@ -177,6 +177,10 @@ export interface ITenantLogsStruct { dbNodeSelector: IKeyValue[]; dbServiceAccountName: string; disabled: boolean; + logCPURequest: string; + logMemRequest: string; + logDBCPURequest: string; + logDBMemRequest: string; } export interface ValueUnit { diff --git a/portal-ui/src/screens/Console/Tenants/TenantDetails/EditTenantLogsModal.tsx b/portal-ui/src/screens/Console/Tenants/TenantDetails/EditTenantLogsModal.tsx index 8f150fd97..b31cf1f1a 100644 --- a/portal-ui/src/screens/Console/Tenants/TenantDetails/EditTenantLogsModal.tsx +++ b/portal-ui/src/screens/Console/Tenants/TenantDetails/EditTenantLogsModal.tsx @@ -1,3 +1,19 @@ +// This file is part of MinIO Console Server +// Copyright (c) 2022 MinIO, Inc. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + import React, { useEffect, useState } from "react"; import ModalWrapper from "../../Common/ModalWrapper/ModalWrapper"; import createStyles from "@mui/styles/createStyles"; @@ -38,6 +54,10 @@ interface IEditTenantLogsProps { dbAnnotations: IKeyValue[]; dbNodeSelector: IKeyValue[]; dbServiceAccountName: string; + cpuRequest: string; + memRequest: string; + dbCPURequest:string; + dbMemRequest:string; } const styles = (theme: Theme) => @@ -102,6 +122,10 @@ const EditTenantLogsModal = ({ dbNodeSelector, dbImage, dbServiceAccountName, + cpuRequest, + memRequest, + dbCPURequest, + dbMemRequest }: IEditTenantLogsProps) => { const [validationErrors, setValidationErrors] = useState({}); const [newLabels, setNewLabels] = useState( @@ -137,6 +161,14 @@ const EditTenantLogsModal = ({ const [dbLabelsError, setDbLabelsError] = useState({}); const [dbAnnotationsError, setDbAnnotationsError] = useState({}); const [dbNodeSelectorError, setDbNodeSelectorError] = useState({}); + const [newCPURequest, setNewCPURequest] = useState(cpuRequest); + const [newMemRequest, setNewMemRequest] = useState( memRequest ? + Math.floor(parseInt(memRequest, 10) / 1000000000).toString() : "0" + ); + const [newDBCPURequest, setNewDBCPURequest] = useState(dbCPURequest); + const [newDBMemRequest, setNewDBMemRequest] = useState(dbMemRequest ? + Math.floor(parseInt(dbMemRequest, 10) / 1000000000).toString() : "0" + ); const trim = (x: IKeyValue[]): IKeyValue[] => { let retval: IKeyValue[] = []; @@ -192,6 +224,34 @@ const EditTenantLogsModal = ({ pattern: /^[a-zA-Z0-9-.]{1,253}$/, customPatternMessage: "Invalid service account name", }); + tenantLogValidation.push({ + fieldKey: `cpuRequest`, + required: true, + value: newCPURequest as any as string, + pattern: /^[0-9]*$/, + customPatternMessage: "Please enter an integer value for number of CPUs requested", + }); + tenantLogValidation.push({ + fieldKey: `memRequest`, + required: true, + value: newMemRequest as any as string, + pattern: /^[0-9]*$/, + customPatternMessage: "Please enter an integer value (Gi) for memory requested", + }); + tenantLogValidation.push({ + fieldKey: `dbCPURequest`, + required: true, + value: newDBCPURequest as any as string, + pattern: /^[0-9]*$/, + customPatternMessage: "Please enter an integer value for number of DB CPUs requested", + }); + tenantLogValidation.push({ + fieldKey: `dbMemRequest`, + required: true, + value: newDBMemRequest as any as string, + pattern: /^[0-9]*$/, + customPatternMessage: "Please enter an integer value (Gi) for DB memory requested", + }); const commonVal = commonFormValidation(tenantLogValidation); setValidationErrors(commonVal); @@ -201,6 +261,10 @@ const EditTenantLogsModal = ({ newDiskCapacityGB, newServiceAccountName, newDbServiceAccountName, + newCPURequest, + newMemRequest, + newDBCPURequest, + newDBMemRequest, setValidationErrors, ]); @@ -253,6 +317,10 @@ const EditTenantLogsModal = ({ dbNodeSelector: trim(newDbNodeSelector), dbImage: newDbImage, dbServiceAccountName: newDbServiceAccountName, + logCPURequest: newCPURequest, + logMemRequest: newMemRequest + "Gi", + logDBCPURequest: newDBCPURequest, + logDBMemRequest: newDBMemRequest+ "Gi", } ) .then(() => { @@ -312,6 +380,38 @@ const EditTenantLogsModal = ({ error={validationErrors[`serviceAccountName`] || ""} /> + + + { + setNewCPURequest(e.target.value as any as string); + cleanValidation(`cpuRequest`); + }} + key={`cpuRequest`} + error={validationErrors[`cpuRequest`] || ""} + /> + + + { + setNewMemRequest(e.target.value as any as string); + cleanValidation(`memRequest`); + }} + key={`memRequest`} + error={validationErrors[`memRequest`] || ""} + /> + + Labels + + { + setNewDBCPURequest(e.target.value as any as string); + cleanValidation(`dbCpuRequest`); + }} + key={`dbCpuRequest`} + error={validationErrors[`dbCpuRequest`] || ""} + /> + + + { + setNewDBMemRequest(e.target.value as any as string); + cleanValidation(`dbMemRequest`); + }} + key={`dbMemRequest`} + error={validationErrors[`dbMemRequest`] || ""} + /> + Labels )} Logging @@ -249,25 +254,49 @@ const TenantLogging = ({ ) : ( +{logInfo?.logCPURequest != null && ( + + CPU Request: + {logInfo?.logCPURequest} + + )} + {logInfo?.logMemRequest != null && ( + + Memory Request: + + {niceBytes( + logInfo?.logMemRequest, + true + )} + + + )} + {logInfo?.image != null && ( Image: {logInfo?.image} + )} + {logInfo?.diskCapacityGB != null && ( Disk Capacity (GB): {logInfo?.diskCapacityGB} + )} + {logInfo?.serviceAccountName != null && ( Service Account: {logInfo?.serviceAccountName} + )} + {logInfo?.labels != null && logInfo.labels.length > 0 && ( Labels - + + + )} + {logInfo?.annotations != null && logInfo.annotations.length > 0 && ( Annotations @@ -297,6 +329,9 @@ const TenantLogging = ({ /> + + )} + {logInfo?.nodeSelector != null && logInfo.nodeSelector.length > 0 &&( Node Selector @@ -314,6 +349,8 @@ const TenantLogging = ({ /> + + )} )} @@ -331,19 +368,41 @@ const TenantLogging = ({ ) : ( + {logInfo?.logDBCPURequest != null && ( + + DB CPU Request: + {logInfo?.logDBCPURequest} + + )} + {logInfo?.logDBMemRequest != null && ( + + DB Memory Request: + + {niceBytes( + logInfo?.logDBMemRequest, + true + )} + + + )} + {logInfo?.dbImage != null && ( Postgres Image: {logInfo?.dbImage} + )} + {logInfo?.dbServiceAccountName != null && ( Service Account: {logInfo?.dbServiceAccountName} - - + + )} + {logInfo?.dbLabels != null && logInfo.dbLabels.length > 0 &&( Labels + + + )} + {logInfo?.annotations != null && logInfo.dbAnnotations.length > 0 &&( Annotations @@ -374,9 +436,12 @@ const TenantLogging = ({ /> + + )} + {logInfo?.nodeSelector != null && logInfo.dbNodeSelector.length > 0 &&( - Node Selector + Node Selector @@ -392,6 +457,8 @@ const TenantLogging = ({ /> + + )} )} diff --git a/swagger-operator.yml b/swagger-operator.yml index 6ac2b2633..c9edade25 100644 --- a/swagger-operator.yml +++ b/swagger-operator.yml @@ -2521,6 +2521,15 @@ definitions: type: string disabled: type: boolean + logCPURequest: + type: string + logMemRequest: + type: string + logDBCPURequest: + type: string + logDBMemRequest: + type: string + listPVCsResponse: type: object