Move tenant logs logic to a new file (#2427)
Going to work and add new code on tenant logs so i make this small refactor to keep things separated Co-authored-by: Daniel Valdivia <18384552+dvaldivia@users.noreply.github.com>
This commit is contained in:
455
operatorapi/tenant_logs_handlers.go
Normal file
455
operatorapi/tenant_logs_handlers.go
Normal file
@@ -0,0 +1,455 @@
|
||||
package operatorapi
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strconv"
|
||||
|
||||
"github.com/dustin/go-humanize"
|
||||
"github.com/go-openapi/runtime/middleware"
|
||||
"github.com/go-openapi/swag"
|
||||
"github.com/minio/console/cluster"
|
||||
"github.com/minio/console/models"
|
||||
"github.com/minio/console/operatorapi/operations"
|
||||
"github.com/minio/console/operatorapi/operations/operator_api"
|
||||
"github.com/minio/console/restapi"
|
||||
miniov2 "github.com/minio/operator/pkg/apis/minio.min.io/v2"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/api/resource"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
)
|
||||
|
||||
func registerTenantLogsHandlers(api *operations.OperatorAPI) {
|
||||
api.OperatorAPIGetTenantLogsHandler = operator_api.GetTenantLogsHandlerFunc(func(params operator_api.GetTenantLogsParams, session *models.Principal) middleware.Responder {
|
||||
payload, err := getTenantLogsResponse(session, params)
|
||||
if err != nil {
|
||||
return operator_api.NewGetTenantLogsDefault(int(err.Code)).WithPayload(err)
|
||||
}
|
||||
return operator_api.NewGetTenantLogsOK().WithPayload(payload)
|
||||
})
|
||||
|
||||
api.OperatorAPISetTenantLogsHandler = operator_api.SetTenantLogsHandlerFunc(func(params operator_api.SetTenantLogsParams, session *models.Principal) middleware.Responder {
|
||||
payload, err := setTenantLogsResponse(session, params)
|
||||
if err != nil {
|
||||
return operator_api.NewSetTenantLogsDefault(int(err.Code)).WithPayload(err)
|
||||
}
|
||||
return operator_api.NewSetTenantLogsOK().WithPayload(payload)
|
||||
})
|
||||
|
||||
api.OperatorAPIEnableTenantLoggingHandler = operator_api.EnableTenantLoggingHandlerFunc(func(params operator_api.EnableTenantLoggingParams, session *models.Principal) middleware.Responder {
|
||||
payload, err := enableTenantLoggingResponse(session, params)
|
||||
if err != nil {
|
||||
return operator_api.NewEnableTenantLoggingDefault(int(err.Code)).WithPayload(err)
|
||||
}
|
||||
return operator_api.NewEnableTenantLoggingOK().WithPayload(payload)
|
||||
})
|
||||
|
||||
api.OperatorAPIDisableTenantLoggingHandler = operator_api.DisableTenantLoggingHandlerFunc(func(params operator_api.DisableTenantLoggingParams, session *models.Principal) middleware.Responder {
|
||||
payload, err := disableTenantLoggingResponse(session, params)
|
||||
if err != nil {
|
||||
return operator_api.NewDisableTenantLoggingDefault(int(err.Code)).WithPayload(err)
|
||||
}
|
||||
return operator_api.NewDisableTenantLoggingOK().WithPayload(payload)
|
||||
})
|
||||
}
|
||||
|
||||
// getTenantLogsResponse returns the Audit Log and Log DB configuration of a tenant
|
||||
func getTenantLogsResponse(session *models.Principal, params operator_api.GetTenantLogsParams) (*models.TenantLogs, *models.Error) {
|
||||
ctx, cancel := context.WithCancel(params.HTTPRequest.Context())
|
||||
defer cancel()
|
||||
|
||||
opClientClientSet, err := cluster.OperatorClient(session.STSSessionToken)
|
||||
if err != nil {
|
||||
return nil, restapi.ErrorWithContext(ctx, err, restapi.ErrUnableToGetTenantLogs)
|
||||
}
|
||||
|
||||
opClient := &operatorClient{
|
||||
client: opClientClientSet,
|
||||
}
|
||||
|
||||
minTenant, err := getTenant(ctx, opClient, params.Namespace, params.Tenant)
|
||||
if err != nil {
|
||||
return nil, restapi.ErrorWithContext(ctx, err, restapi.ErrUnableToGetTenantLogs)
|
||||
}
|
||||
if minTenant.Spec.Log == nil {
|
||||
return &models.TenantLogs{
|
||||
Disabled: true,
|
||||
}, nil
|
||||
}
|
||||
annotations := []*models.Annotation{}
|
||||
for k, v := range minTenant.Spec.Log.Annotations {
|
||||
annotations = append(annotations, &models.Annotation{Key: k, Value: v})
|
||||
}
|
||||
labels := []*models.Label{}
|
||||
for k, v := range minTenant.Spec.Log.Labels {
|
||||
labels = append(labels, &models.Label{Key: k, Value: v})
|
||||
}
|
||||
nodeSelector := []*models.NodeSelector{}
|
||||
for k, v := range minTenant.Spec.Log.NodeSelector {
|
||||
nodeSelector = append(nodeSelector, &models.NodeSelector{Key: k, Value: v})
|
||||
}
|
||||
if minTenant.Spec.Log.Db == nil {
|
||||
minTenant.Spec.Log.Db = &miniov2.LogDbConfig{}
|
||||
}
|
||||
dbAnnotations := []*models.Annotation{}
|
||||
for k, v := range minTenant.Spec.Log.Db.Annotations {
|
||||
dbAnnotations = append(dbAnnotations, &models.Annotation{Key: k, Value: v})
|
||||
}
|
||||
dbLabels := []*models.Label{}
|
||||
for k, v := range minTenant.Spec.Log.Db.Labels {
|
||||
dbLabels = append(dbLabels, &models.Label{Key: k, Value: v})
|
||||
}
|
||||
dbNodeSelector := []*models.NodeSelector{}
|
||||
for k, v := range minTenant.Spec.Log.Db.NodeSelector {
|
||||
dbNodeSelector = append(dbNodeSelector, &models.NodeSelector{Key: k, Value: v})
|
||||
}
|
||||
var logSecurityContext *models.SecurityContext
|
||||
var logDBSecurityContext *models.SecurityContext
|
||||
|
||||
if minTenant.Spec.Log.SecurityContext != nil {
|
||||
logSecurityContext = convertK8sSCToModelSC(minTenant.Spec.Log.SecurityContext)
|
||||
}
|
||||
if minTenant.Spec.Log.Db.SecurityContext != nil {
|
||||
logDBSecurityContext = convertK8sSCToModelSC(minTenant.Spec.Log.Db.SecurityContext)
|
||||
}
|
||||
|
||||
if minTenant.Spec.Log.Audit == nil || minTenant.Spec.Log.Audit.DiskCapacityGB == nil {
|
||||
minTenant.Spec.Log.Audit = &miniov2.AuditConfig{DiskCapacityGB: swag.Int(0)}
|
||||
}
|
||||
|
||||
tenantLoggingConfiguration := &models.TenantLogs{
|
||||
Image: minTenant.Spec.Log.Image,
|
||||
DiskCapacityGB: fmt.Sprintf("%d", *minTenant.Spec.Log.Audit.DiskCapacityGB),
|
||||
Annotations: annotations,
|
||||
Labels: labels,
|
||||
NodeSelector: nodeSelector,
|
||||
ServiceAccountName: minTenant.Spec.Log.ServiceAccountName,
|
||||
SecurityContext: logSecurityContext,
|
||||
DbImage: minTenant.Spec.Log.Db.Image,
|
||||
DbInitImage: minTenant.Spec.Log.Db.InitImage,
|
||||
DbAnnotations: dbAnnotations,
|
||||
DbLabels: dbLabels,
|
||||
DbNodeSelector: dbNodeSelector,
|
||||
DbServiceAccountName: minTenant.Spec.Log.Db.ServiceAccountName,
|
||||
DbSecurityContext: logDBSecurityContext,
|
||||
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)
|
||||
|
||||
tenantLoggingConfiguration.LogCPURequest = requestedCPU
|
||||
tenantLoggingConfiguration.LogMemRequest = requestedMem
|
||||
tenantLoggingConfiguration.LogDBCPURequest = requestedDBCPU
|
||||
tenantLoggingConfiguration.LogDBMemRequest = requestedDBMem
|
||||
}
|
||||
return tenantLoggingConfiguration, nil
|
||||
}
|
||||
|
||||
// setTenantLogsResponse updates the Audit Log and Log DB configuration for the tenant
|
||||
func setTenantLogsResponse(session *models.Principal, params operator_api.SetTenantLogsParams) (bool, *models.Error) {
|
||||
ctx, cancel := context.WithCancel(params.HTTPRequest.Context())
|
||||
defer cancel()
|
||||
opClientClientSet, err := cluster.OperatorClient(session.STSSessionToken)
|
||||
if err != nil {
|
||||
return false, restapi.ErrorWithContext(ctx, err, restapi.ErrUnableToGetTenantUsage)
|
||||
}
|
||||
|
||||
opClient := &operatorClient{
|
||||
client: opClientClientSet,
|
||||
}
|
||||
|
||||
minTenant, err := getTenant(ctx, opClient, params.Namespace, params.Tenant)
|
||||
if err != nil {
|
||||
return false, restapi.ErrorWithContext(ctx, err, restapi.ErrUnableToGetTenantUsage)
|
||||
}
|
||||
|
||||
labels := make(map[string]string)
|
||||
if params.Data.Labels != nil {
|
||||
for i := 0; i < len(params.Data.Labels); i++ {
|
||||
if params.Data.Labels[i] != nil {
|
||||
labels[params.Data.Labels[i].Key] = params.Data.Labels[i].Value
|
||||
}
|
||||
}
|
||||
minTenant.Spec.Log.Labels = labels
|
||||
}
|
||||
|
||||
if params.Data.Annotations != nil {
|
||||
annotations := make(map[string]string)
|
||||
for i := 0; i < len(params.Data.Annotations); i++ {
|
||||
if params.Data.Annotations[i] != nil {
|
||||
annotations[params.Data.Annotations[i].Key] = params.Data.Annotations[i].Value
|
||||
}
|
||||
}
|
||||
minTenant.Spec.Log.Annotations = annotations
|
||||
}
|
||||
if params.Data.NodeSelector != nil {
|
||||
nodeSelector := make(map[string]string)
|
||||
for i := 0; i < len(params.Data.NodeSelector); i++ {
|
||||
if params.Data.NodeSelector[i] != nil {
|
||||
nodeSelector[params.Data.NodeSelector[i].Key] = params.Data.NodeSelector[i].Value
|
||||
}
|
||||
}
|
||||
minTenant.Spec.Log.NodeSelector = nodeSelector
|
||||
}
|
||||
logResourceRequest := make(corev1.ResourceList)
|
||||
if len(params.Data.LogCPURequest) > 0 {
|
||||
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, restapi.ErrorWithContext(ctx, err)
|
||||
}
|
||||
logResourceRequest["cpu"] = cpuQuantity
|
||||
minTenant.Spec.Log.Resources.Requests = logResourceRequest
|
||||
}
|
||||
}
|
||||
if len(params.Data.LogMemRequest) > 0 {
|
||||
if reflect.TypeOf(params.Data.LogMemRequest).Kind() == reflect.String && params.Data.LogMemRequest != "" {
|
||||
memQuantity, err := resource.ParseQuantity(params.Data.LogMemRequest)
|
||||
if err != nil {
|
||||
return false, restapi.ErrorWithContext(ctx, err)
|
||||
}
|
||||
|
||||
logResourceRequest["memory"] = memQuantity
|
||||
minTenant.Spec.Log.Resources.Requests = logResourceRequest
|
||||
}
|
||||
}
|
||||
|
||||
modified := false
|
||||
if minTenant.Spec.Log.Db != nil {
|
||||
modified = true
|
||||
}
|
||||
dbLabels := make(map[string]string)
|
||||
if params.Data.DbLabels != nil {
|
||||
for i := 0; i < len(params.Data.DbLabels); i++ {
|
||||
if params.Data.DbLabels[i] != nil {
|
||||
dbLabels[params.Data.DbLabels[i].Key] = params.Data.DbLabels[i].Value
|
||||
}
|
||||
modified = true
|
||||
}
|
||||
}
|
||||
dbAnnotations := make(map[string]string)
|
||||
if params.Data.DbAnnotations != nil {
|
||||
for i := 0; i < len(params.Data.DbAnnotations); i++ {
|
||||
if params.Data.DbAnnotations[i] != nil {
|
||||
dbAnnotations[params.Data.DbAnnotations[i].Key] = params.Data.DbAnnotations[i].Value
|
||||
}
|
||||
modified = true
|
||||
}
|
||||
}
|
||||
dbNodeSelector := make(map[string]string)
|
||||
if params.Data.DbNodeSelector != nil {
|
||||
for i := 0; i < len(params.Data.DbNodeSelector); i++ {
|
||||
if params.Data.DbNodeSelector[i] != nil {
|
||||
dbNodeSelector[params.Data.DbNodeSelector[i].Key] = params.Data.DbNodeSelector[i].Value
|
||||
}
|
||||
modified = true
|
||||
}
|
||||
}
|
||||
logDBResourceRequest := make(corev1.ResourceList)
|
||||
if len(params.Data.LogDBCPURequest) > 0 {
|
||||
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, restapi.ErrorWithContext(ctx, err)
|
||||
}
|
||||
logDBResourceRequest["cpu"] = dbCPUQuantity
|
||||
minTenant.Spec.Log.Db.Resources.Requests = logDBResourceRequest
|
||||
}
|
||||
}
|
||||
if len(params.Data.LogDBMemRequest) > 0 {
|
||||
if reflect.TypeOf(params.Data.LogDBMemRequest).Kind() == reflect.String && params.Data.LogDBMemRequest != "" {
|
||||
dbMemQuantity, err := resource.ParseQuantity(params.Data.LogDBMemRequest)
|
||||
if err != nil {
|
||||
return false, restapi.ErrorWithContext(ctx, err)
|
||||
}
|
||||
logDBResourceRequest["memory"] = dbMemQuantity
|
||||
minTenant.Spec.Log.Db.Resources.Requests = logDBResourceRequest
|
||||
}
|
||||
}
|
||||
if len(params.Data.Image) > 0 {
|
||||
minTenant.Spec.Log.Image = params.Data.Image
|
||||
}
|
||||
if params.Data.SecurityContext != nil {
|
||||
minTenant.Spec.Log.SecurityContext, err = convertModelSCToK8sSC(params.Data.SecurityContext)
|
||||
if err != nil {
|
||||
return false, restapi.ErrorWithContext(ctx, err)
|
||||
}
|
||||
}
|
||||
if len(params.Data.DiskCapacityGB) > 0 {
|
||||
diskCapacityGB, err := strconv.Atoi(params.Data.DiskCapacityGB)
|
||||
if err == nil {
|
||||
if minTenant.Spec.Log.Audit != nil && minTenant.Spec.Log.Audit.DiskCapacityGB != nil {
|
||||
*minTenant.Spec.Log.Audit.DiskCapacityGB = diskCapacityGB
|
||||
} else {
|
||||
minTenant.Spec.Log.Audit = &miniov2.AuditConfig{DiskCapacityGB: swag.Int(diskCapacityGB)}
|
||||
}
|
||||
}
|
||||
}
|
||||
if len(params.Data.ServiceAccountName) > 0 {
|
||||
minTenant.Spec.Log.ServiceAccountName = params.Data.ServiceAccountName
|
||||
}
|
||||
if params.Data.DbLabels != nil {
|
||||
|
||||
if params.Data.DbImage != "" || params.Data.DbServiceAccountName != "" {
|
||||
modified = true
|
||||
}
|
||||
if modified {
|
||||
if minTenant.Spec.Log.Db == nil {
|
||||
// Default class name for Log search
|
||||
diskSpaceFromAPI := int64(5) * humanize.GiByte // Default is 5Gi
|
||||
logSearchStorageClass := "standard"
|
||||
|
||||
logSearchDiskSpace := resource.NewQuantity(diskSpaceFromAPI, resource.DecimalExponent)
|
||||
|
||||
minTenant.Spec.Log.Db = &miniov2.LogDbConfig{
|
||||
VolumeClaimTemplate: &corev1.PersistentVolumeClaim{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: params.Tenant + "-log",
|
||||
},
|
||||
Spec: corev1.PersistentVolumeClaimSpec{
|
||||
AccessModes: []corev1.PersistentVolumeAccessMode{
|
||||
corev1.ReadWriteOnce,
|
||||
},
|
||||
Resources: corev1.ResourceRequirements{
|
||||
Requests: corev1.ResourceList{
|
||||
corev1.ResourceStorage: *logSearchDiskSpace,
|
||||
},
|
||||
},
|
||||
StorageClassName: &logSearchStorageClass,
|
||||
},
|
||||
},
|
||||
Labels: dbLabels,
|
||||
Annotations: dbAnnotations,
|
||||
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
|
||||
minTenant.Spec.Log.Db.Annotations = dbAnnotations
|
||||
minTenant.Spec.Log.Db.NodeSelector = dbNodeSelector
|
||||
minTenant.Spec.Log.Db.Image = params.Data.DbImage
|
||||
minTenant.Spec.Log.Db.InitImage = params.Data.DbInitImage
|
||||
minTenant.Spec.Log.Db.ServiceAccountName = params.Data.DbServiceAccountName
|
||||
minTenant.Spec.Log.Db.SecurityContext, err = convertModelSCToK8sSC(params.Data.DbSecurityContext)
|
||||
if err != nil {
|
||||
return false, restapi.ErrorWithContext(ctx, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_, err = opClient.TenantUpdate(ctx, minTenant, metav1.UpdateOptions{})
|
||||
if err != nil {
|
||||
return false, restapi.ErrorWithContext(ctx, err)
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
||||
// enableTenantLoggingResponse enables Tenant Logging
|
||||
func enableTenantLoggingResponse(session *models.Principal, params operator_api.EnableTenantLoggingParams) (bool, *models.Error) {
|
||||
ctx, cancel := context.WithCancel(params.HTTPRequest.Context())
|
||||
defer cancel()
|
||||
|
||||
opClientClientSet, err := cluster.OperatorClient(session.STSSessionToken)
|
||||
if err != nil {
|
||||
return false, restapi.ErrorWithContext(ctx, err, restapi.ErrUnableToGetTenantUsage)
|
||||
}
|
||||
|
||||
opClient := &operatorClient{
|
||||
client: opClientClientSet,
|
||||
}
|
||||
|
||||
minTenant, err := getTenant(ctx, opClient, params.Namespace, params.Tenant)
|
||||
if err != nil {
|
||||
return false, restapi.ErrorWithContext(ctx, err, restapi.ErrUnableToGetTenantUsage)
|
||||
}
|
||||
minTenant.EnsureDefaults()
|
||||
// Default class name for Log search
|
||||
diskSpaceFromAPI := int64(5) * humanize.GiByte // Default is 5Gi
|
||||
logSearchStorageClass := "standard"
|
||||
|
||||
logSearchDiskSpace := resource.NewQuantity(diskSpaceFromAPI, resource.DecimalExponent)
|
||||
|
||||
auditMaxCap := 10
|
||||
if (diskSpaceFromAPI / humanize.GiByte) < int64(auditMaxCap) {
|
||||
auditMaxCap = int(diskSpaceFromAPI / humanize.GiByte)
|
||||
}
|
||||
|
||||
minTenant.Spec.Log = &miniov2.LogConfig{
|
||||
Audit: &miniov2.AuditConfig{DiskCapacityGB: swag.Int(auditMaxCap)},
|
||||
Db: &miniov2.LogDbConfig{
|
||||
VolumeClaimTemplate: &corev1.PersistentVolumeClaim{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: params.Tenant + "-log",
|
||||
},
|
||||
Spec: corev1.PersistentVolumeClaimSpec{
|
||||
AccessModes: []corev1.PersistentVolumeAccessMode{
|
||||
corev1.ReadWriteOnce,
|
||||
},
|
||||
Resources: corev1.ResourceRequirements{
|
||||
Requests: corev1.ResourceList{
|
||||
corev1.ResourceStorage: *logSearchDiskSpace,
|
||||
},
|
||||
},
|
||||
StorageClassName: &logSearchStorageClass,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
_, err = opClient.TenantUpdate(ctx, minTenant, metav1.UpdateOptions{})
|
||||
if err != nil {
|
||||
return false, restapi.ErrorWithContext(ctx, err)
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
||||
// disableTenantLoggingResponse disables Tenant Logging
|
||||
func disableTenantLoggingResponse(session *models.Principal, params operator_api.DisableTenantLoggingParams) (bool, *models.Error) {
|
||||
ctx, cancel := context.WithCancel(params.HTTPRequest.Context())
|
||||
defer cancel()
|
||||
|
||||
opClientClientSet, err := cluster.OperatorClient(session.STSSessionToken)
|
||||
if err != nil {
|
||||
return false, restapi.ErrorWithContext(ctx, err, restapi.ErrUnableToGetTenantUsage)
|
||||
}
|
||||
if err != nil {
|
||||
return false, restapi.ErrorWithContext(ctx, err, restapi.ErrUnableToGetTenantUsage)
|
||||
}
|
||||
|
||||
opClient := &operatorClient{
|
||||
client: opClientClientSet,
|
||||
}
|
||||
|
||||
minTenant, err := getTenant(ctx, opClient, params.Namespace, params.Tenant)
|
||||
if err != nil {
|
||||
return false, restapi.ErrorWithContext(ctx, err, restapi.ErrUnableToGetTenantUsage)
|
||||
}
|
||||
minTenant.EnsureDefaults()
|
||||
minTenant.Spec.Log = nil
|
||||
|
||||
_, err = opClient.TenantUpdate(ctx, minTenant, metav1.UpdateOptions{})
|
||||
if err != nil {
|
||||
return false, restapi.ErrorWithContext(ctx, err)
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
@@ -27,7 +27,6 @@ import (
|
||||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
"reflect"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
@@ -35,7 +34,6 @@ import (
|
||||
|
||||
utils2 "github.com/minio/console/pkg/http"
|
||||
|
||||
"github.com/dustin/go-humanize"
|
||||
"github.com/minio/madmin-go"
|
||||
|
||||
"github.com/minio/console/restapi"
|
||||
@@ -218,39 +216,7 @@ func registerTenantHandlers(api *operations.OperatorAPI) {
|
||||
return operator_api.NewGetTenantUsageOK().WithPayload(payload)
|
||||
})
|
||||
|
||||
// Get Tenant Logs
|
||||
api.OperatorAPIGetTenantLogsHandler = operator_api.GetTenantLogsHandlerFunc(func(params operator_api.GetTenantLogsParams, session *models.Principal) middleware.Responder {
|
||||
payload, err := getTenantLogsResponse(session, params)
|
||||
if err != nil {
|
||||
return operator_api.NewGetTenantLogsDefault(int(err.Code)).WithPayload(err)
|
||||
}
|
||||
return operator_api.NewGetTenantLogsOK().WithPayload(payload)
|
||||
})
|
||||
|
||||
api.OperatorAPISetTenantLogsHandler = operator_api.SetTenantLogsHandlerFunc(func(params operator_api.SetTenantLogsParams, session *models.Principal) middleware.Responder {
|
||||
payload, err := setTenantLogsResponse(session, params)
|
||||
if err != nil {
|
||||
return operator_api.NewSetTenantLogsDefault(int(err.Code)).WithPayload(err)
|
||||
}
|
||||
return operator_api.NewSetTenantLogsOK().WithPayload(payload)
|
||||
})
|
||||
|
||||
// Get Tenant Logs
|
||||
api.OperatorAPIEnableTenantLoggingHandler = operator_api.EnableTenantLoggingHandlerFunc(func(params operator_api.EnableTenantLoggingParams, session *models.Principal) middleware.Responder {
|
||||
payload, err := enableTenantLoggingResponse(session, params)
|
||||
if err != nil {
|
||||
return operator_api.NewEnableTenantLoggingDefault(int(err.Code)).WithPayload(err)
|
||||
}
|
||||
return operator_api.NewEnableTenantLoggingOK().WithPayload(payload)
|
||||
})
|
||||
|
||||
api.OperatorAPIDisableTenantLoggingHandler = operator_api.DisableTenantLoggingHandlerFunc(func(params operator_api.DisableTenantLoggingParams, session *models.Principal) middleware.Responder {
|
||||
payload, err := disableTenantLoggingResponse(session, params)
|
||||
if err != nil {
|
||||
return operator_api.NewDisableTenantLoggingDefault(int(err.Code)).WithPayload(err)
|
||||
}
|
||||
return operator_api.NewDisableTenantLoggingOK().WithPayload(payload)
|
||||
})
|
||||
registerTenantLogsHandlers(api)
|
||||
|
||||
api.OperatorAPIGetTenantPodsHandler = operator_api.GetTenantPodsHandlerFunc(func(params operator_api.GetTenantPodsParams, session *models.Principal) middleware.Responder {
|
||||
payload, err := getTenantPodsResponse(session, params)
|
||||
@@ -1571,406 +1537,6 @@ func getTenantUsageResponse(session *models.Principal, params operator_api.GetTe
|
||||
return info, nil
|
||||
}
|
||||
|
||||
// getTenantLogsResponse returns the Audit Log and Log DB configuration of a tenant
|
||||
func getTenantLogsResponse(session *models.Principal, params operator_api.GetTenantLogsParams) (*models.TenantLogs, *models.Error) {
|
||||
ctx, cancel := context.WithCancel(params.HTTPRequest.Context())
|
||||
defer cancel()
|
||||
|
||||
opClientClientSet, err := cluster.OperatorClient(session.STSSessionToken)
|
||||
if err != nil {
|
||||
return nil, restapi.ErrorWithContext(ctx, err, restapi.ErrUnableToGetTenantLogs)
|
||||
}
|
||||
|
||||
opClient := &operatorClient{
|
||||
client: opClientClientSet,
|
||||
}
|
||||
|
||||
minTenant, err := getTenant(ctx, opClient, params.Namespace, params.Tenant)
|
||||
if err != nil {
|
||||
return nil, restapi.ErrorWithContext(ctx, err, restapi.ErrUnableToGetTenantLogs)
|
||||
}
|
||||
if minTenant.Spec.Log == nil {
|
||||
return &models.TenantLogs{
|
||||
Disabled: true,
|
||||
}, nil
|
||||
}
|
||||
annotations := []*models.Annotation{}
|
||||
for k, v := range minTenant.Spec.Log.Annotations {
|
||||
annotations = append(annotations, &models.Annotation{Key: k, Value: v})
|
||||
}
|
||||
labels := []*models.Label{}
|
||||
for k, v := range minTenant.Spec.Log.Labels {
|
||||
labels = append(labels, &models.Label{Key: k, Value: v})
|
||||
}
|
||||
nodeSelector := []*models.NodeSelector{}
|
||||
for k, v := range minTenant.Spec.Log.NodeSelector {
|
||||
nodeSelector = append(nodeSelector, &models.NodeSelector{Key: k, Value: v})
|
||||
}
|
||||
if minTenant.Spec.Log.Db == nil {
|
||||
minTenant.Spec.Log.Db = &miniov2.LogDbConfig{}
|
||||
}
|
||||
dbAnnotations := []*models.Annotation{}
|
||||
for k, v := range minTenant.Spec.Log.Db.Annotations {
|
||||
dbAnnotations = append(dbAnnotations, &models.Annotation{Key: k, Value: v})
|
||||
}
|
||||
dbLabels := []*models.Label{}
|
||||
for k, v := range minTenant.Spec.Log.Db.Labels {
|
||||
dbLabels = append(dbLabels, &models.Label{Key: k, Value: v})
|
||||
}
|
||||
dbNodeSelector := []*models.NodeSelector{}
|
||||
for k, v := range minTenant.Spec.Log.Db.NodeSelector {
|
||||
dbNodeSelector = append(dbNodeSelector, &models.NodeSelector{Key: k, Value: v})
|
||||
}
|
||||
var logSecurityContext *models.SecurityContext
|
||||
var logDBSecurityContext *models.SecurityContext
|
||||
|
||||
if minTenant.Spec.Log.SecurityContext != nil {
|
||||
logSecurityContext = convertK8sSCToModelSC(minTenant.Spec.Log.SecurityContext)
|
||||
}
|
||||
if minTenant.Spec.Log.Db.SecurityContext != nil {
|
||||
logDBSecurityContext = convertK8sSCToModelSC(minTenant.Spec.Log.Db.SecurityContext)
|
||||
}
|
||||
|
||||
if minTenant.Spec.Log.Audit == nil || minTenant.Spec.Log.Audit.DiskCapacityGB == nil {
|
||||
minTenant.Spec.Log.Audit = &miniov2.AuditConfig{DiskCapacityGB: swag.Int(0)}
|
||||
}
|
||||
|
||||
tenantLoggingConfiguration := &models.TenantLogs{
|
||||
Image: minTenant.Spec.Log.Image,
|
||||
DiskCapacityGB: fmt.Sprintf("%d", *minTenant.Spec.Log.Audit.DiskCapacityGB),
|
||||
Annotations: annotations,
|
||||
Labels: labels,
|
||||
NodeSelector: nodeSelector,
|
||||
ServiceAccountName: minTenant.Spec.Log.ServiceAccountName,
|
||||
SecurityContext: logSecurityContext,
|
||||
DbImage: minTenant.Spec.Log.Db.Image,
|
||||
DbInitImage: minTenant.Spec.Log.Db.InitImage,
|
||||
DbAnnotations: dbAnnotations,
|
||||
DbLabels: dbLabels,
|
||||
DbNodeSelector: dbNodeSelector,
|
||||
DbServiceAccountName: minTenant.Spec.Log.Db.ServiceAccountName,
|
||||
DbSecurityContext: logDBSecurityContext,
|
||||
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)
|
||||
|
||||
tenantLoggingConfiguration.LogCPURequest = requestedCPU
|
||||
tenantLoggingConfiguration.LogMemRequest = requestedMem
|
||||
tenantLoggingConfiguration.LogDBCPURequest = requestedDBCPU
|
||||
tenantLoggingConfiguration.LogDBMemRequest = requestedDBMem
|
||||
}
|
||||
return tenantLoggingConfiguration, nil
|
||||
}
|
||||
|
||||
// setTenantLogsResponse updates the Audit Log and Log DB configuration for the tenant
|
||||
func setTenantLogsResponse(session *models.Principal, params operator_api.SetTenantLogsParams) (bool, *models.Error) {
|
||||
ctx, cancel := context.WithCancel(params.HTTPRequest.Context())
|
||||
defer cancel()
|
||||
opClientClientSet, err := cluster.OperatorClient(session.STSSessionToken)
|
||||
if err != nil {
|
||||
return false, restapi.ErrorWithContext(ctx, err, restapi.ErrUnableToGetTenantUsage)
|
||||
}
|
||||
|
||||
opClient := &operatorClient{
|
||||
client: opClientClientSet,
|
||||
}
|
||||
|
||||
minTenant, err := getTenant(ctx, opClient, params.Namespace, params.Tenant)
|
||||
if err != nil {
|
||||
return false, restapi.ErrorWithContext(ctx, err, restapi.ErrUnableToGetTenantUsage)
|
||||
}
|
||||
|
||||
labels := make(map[string]string)
|
||||
if params.Data.Labels != nil {
|
||||
for i := 0; i < len(params.Data.Labels); i++ {
|
||||
if params.Data.Labels[i] != nil {
|
||||
labels[params.Data.Labels[i].Key] = params.Data.Labels[i].Value
|
||||
}
|
||||
}
|
||||
minTenant.Spec.Log.Labels = labels
|
||||
}
|
||||
|
||||
if params.Data.Annotations != nil {
|
||||
annotations := make(map[string]string)
|
||||
for i := 0; i < len(params.Data.Annotations); i++ {
|
||||
if params.Data.Annotations[i] != nil {
|
||||
annotations[params.Data.Annotations[i].Key] = params.Data.Annotations[i].Value
|
||||
}
|
||||
}
|
||||
minTenant.Spec.Log.Annotations = annotations
|
||||
}
|
||||
if params.Data.NodeSelector != nil {
|
||||
nodeSelector := make(map[string]string)
|
||||
for i := 0; i < len(params.Data.NodeSelector); i++ {
|
||||
if params.Data.NodeSelector[i] != nil {
|
||||
nodeSelector[params.Data.NodeSelector[i].Key] = params.Data.NodeSelector[i].Value
|
||||
}
|
||||
}
|
||||
minTenant.Spec.Log.NodeSelector = nodeSelector
|
||||
}
|
||||
logResourceRequest := make(corev1.ResourceList)
|
||||
if len(params.Data.LogCPURequest) > 0 {
|
||||
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, restapi.ErrorWithContext(ctx, err)
|
||||
}
|
||||
logResourceRequest["cpu"] = cpuQuantity
|
||||
minTenant.Spec.Log.Resources.Requests = logResourceRequest
|
||||
}
|
||||
}
|
||||
if len(params.Data.LogMemRequest) > 0 {
|
||||
if reflect.TypeOf(params.Data.LogMemRequest).Kind() == reflect.String && params.Data.LogMemRequest != "" {
|
||||
memQuantity, err := resource.ParseQuantity(params.Data.LogMemRequest)
|
||||
if err != nil {
|
||||
return false, restapi.ErrorWithContext(ctx, err)
|
||||
}
|
||||
|
||||
logResourceRequest["memory"] = memQuantity
|
||||
minTenant.Spec.Log.Resources.Requests = logResourceRequest
|
||||
}
|
||||
}
|
||||
|
||||
modified := false
|
||||
if minTenant.Spec.Log.Db != nil {
|
||||
modified = true
|
||||
}
|
||||
dbLabels := make(map[string]string)
|
||||
if params.Data.DbLabels != nil {
|
||||
for i := 0; i < len(params.Data.DbLabels); i++ {
|
||||
if params.Data.DbLabels[i] != nil {
|
||||
dbLabels[params.Data.DbLabels[i].Key] = params.Data.DbLabels[i].Value
|
||||
}
|
||||
modified = true
|
||||
}
|
||||
}
|
||||
dbAnnotations := make(map[string]string)
|
||||
if params.Data.DbAnnotations != nil {
|
||||
for i := 0; i < len(params.Data.DbAnnotations); i++ {
|
||||
if params.Data.DbAnnotations[i] != nil {
|
||||
dbAnnotations[params.Data.DbAnnotations[i].Key] = params.Data.DbAnnotations[i].Value
|
||||
}
|
||||
modified = true
|
||||
}
|
||||
}
|
||||
dbNodeSelector := make(map[string]string)
|
||||
if params.Data.DbNodeSelector != nil {
|
||||
for i := 0; i < len(params.Data.DbNodeSelector); i++ {
|
||||
if params.Data.DbNodeSelector[i] != nil {
|
||||
dbNodeSelector[params.Data.DbNodeSelector[i].Key] = params.Data.DbNodeSelector[i].Value
|
||||
}
|
||||
modified = true
|
||||
}
|
||||
}
|
||||
logDBResourceRequest := make(corev1.ResourceList)
|
||||
if len(params.Data.LogDBCPURequest) > 0 {
|
||||
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, restapi.ErrorWithContext(ctx, err)
|
||||
}
|
||||
logDBResourceRequest["cpu"] = dbCPUQuantity
|
||||
minTenant.Spec.Log.Db.Resources.Requests = logDBResourceRequest
|
||||
}
|
||||
}
|
||||
if len(params.Data.LogDBMemRequest) > 0 {
|
||||
if reflect.TypeOf(params.Data.LogDBMemRequest).Kind() == reflect.String && params.Data.LogDBMemRequest != "" {
|
||||
dbMemQuantity, err := resource.ParseQuantity(params.Data.LogDBMemRequest)
|
||||
if err != nil {
|
||||
return false, restapi.ErrorWithContext(ctx, err)
|
||||
}
|
||||
logDBResourceRequest["memory"] = dbMemQuantity
|
||||
minTenant.Spec.Log.Db.Resources.Requests = logDBResourceRequest
|
||||
}
|
||||
}
|
||||
if len(params.Data.Image) > 0 {
|
||||
minTenant.Spec.Log.Image = params.Data.Image
|
||||
}
|
||||
if params.Data.SecurityContext != nil {
|
||||
minTenant.Spec.Log.SecurityContext, err = convertModelSCToK8sSC(params.Data.SecurityContext)
|
||||
if err != nil {
|
||||
return false, restapi.ErrorWithContext(ctx, err)
|
||||
}
|
||||
}
|
||||
if len(params.Data.DiskCapacityGB) > 0 {
|
||||
diskCapacityGB, err := strconv.Atoi(params.Data.DiskCapacityGB)
|
||||
if err == nil {
|
||||
if minTenant.Spec.Log.Audit != nil && minTenant.Spec.Log.Audit.DiskCapacityGB != nil {
|
||||
*minTenant.Spec.Log.Audit.DiskCapacityGB = diskCapacityGB
|
||||
} else {
|
||||
minTenant.Spec.Log.Audit = &miniov2.AuditConfig{DiskCapacityGB: swag.Int(diskCapacityGB)}
|
||||
}
|
||||
}
|
||||
}
|
||||
if len(params.Data.ServiceAccountName) > 0 {
|
||||
minTenant.Spec.Log.ServiceAccountName = params.Data.ServiceAccountName
|
||||
}
|
||||
if params.Data.DbLabels != nil {
|
||||
|
||||
if params.Data.DbImage != "" || params.Data.DbServiceAccountName != "" {
|
||||
modified = true
|
||||
}
|
||||
if modified {
|
||||
if minTenant.Spec.Log.Db == nil {
|
||||
// Default class name for Log search
|
||||
diskSpaceFromAPI := int64(5) * humanize.GiByte // Default is 5Gi
|
||||
logSearchStorageClass := "standard"
|
||||
|
||||
logSearchDiskSpace := resource.NewQuantity(diskSpaceFromAPI, resource.DecimalExponent)
|
||||
|
||||
minTenant.Spec.Log.Db = &miniov2.LogDbConfig{
|
||||
VolumeClaimTemplate: &corev1.PersistentVolumeClaim{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: params.Tenant + "-log",
|
||||
},
|
||||
Spec: corev1.PersistentVolumeClaimSpec{
|
||||
AccessModes: []corev1.PersistentVolumeAccessMode{
|
||||
corev1.ReadWriteOnce,
|
||||
},
|
||||
Resources: corev1.ResourceRequirements{
|
||||
Requests: corev1.ResourceList{
|
||||
corev1.ResourceStorage: *logSearchDiskSpace,
|
||||
},
|
||||
},
|
||||
StorageClassName: &logSearchStorageClass,
|
||||
},
|
||||
},
|
||||
Labels: dbLabels,
|
||||
Annotations: dbAnnotations,
|
||||
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
|
||||
minTenant.Spec.Log.Db.Annotations = dbAnnotations
|
||||
minTenant.Spec.Log.Db.NodeSelector = dbNodeSelector
|
||||
minTenant.Spec.Log.Db.Image = params.Data.DbImage
|
||||
minTenant.Spec.Log.Db.InitImage = params.Data.DbInitImage
|
||||
minTenant.Spec.Log.Db.ServiceAccountName = params.Data.DbServiceAccountName
|
||||
minTenant.Spec.Log.Db.SecurityContext, err = convertModelSCToK8sSC(params.Data.DbSecurityContext)
|
||||
if err != nil {
|
||||
return false, restapi.ErrorWithContext(ctx, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_, err = opClient.TenantUpdate(ctx, minTenant, metav1.UpdateOptions{})
|
||||
if err != nil {
|
||||
return false, restapi.ErrorWithContext(ctx, err)
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
||||
// enableTenantLoggingResponse enables Tenant Logging
|
||||
func enableTenantLoggingResponse(session *models.Principal, params operator_api.EnableTenantLoggingParams) (bool, *models.Error) {
|
||||
ctx, cancel := context.WithCancel(params.HTTPRequest.Context())
|
||||
defer cancel()
|
||||
|
||||
opClientClientSet, err := cluster.OperatorClient(session.STSSessionToken)
|
||||
if err != nil {
|
||||
return false, restapi.ErrorWithContext(ctx, err, restapi.ErrUnableToGetTenantUsage)
|
||||
}
|
||||
|
||||
opClient := &operatorClient{
|
||||
client: opClientClientSet,
|
||||
}
|
||||
|
||||
minTenant, err := getTenant(ctx, opClient, params.Namespace, params.Tenant)
|
||||
if err != nil {
|
||||
return false, restapi.ErrorWithContext(ctx, err, restapi.ErrUnableToGetTenantUsage)
|
||||
}
|
||||
minTenant.EnsureDefaults()
|
||||
// Default class name for Log search
|
||||
diskSpaceFromAPI := int64(5) * humanize.GiByte // Default is 5Gi
|
||||
logSearchStorageClass := "standard"
|
||||
|
||||
logSearchDiskSpace := resource.NewQuantity(diskSpaceFromAPI, resource.DecimalExponent)
|
||||
|
||||
auditMaxCap := 10
|
||||
if (diskSpaceFromAPI / humanize.GiByte) < int64(auditMaxCap) {
|
||||
auditMaxCap = int(diskSpaceFromAPI / humanize.GiByte)
|
||||
}
|
||||
|
||||
minTenant.Spec.Log = &miniov2.LogConfig{
|
||||
Audit: &miniov2.AuditConfig{DiskCapacityGB: swag.Int(auditMaxCap)},
|
||||
Db: &miniov2.LogDbConfig{
|
||||
VolumeClaimTemplate: &corev1.PersistentVolumeClaim{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: params.Tenant + "-log",
|
||||
},
|
||||
Spec: corev1.PersistentVolumeClaimSpec{
|
||||
AccessModes: []corev1.PersistentVolumeAccessMode{
|
||||
corev1.ReadWriteOnce,
|
||||
},
|
||||
Resources: corev1.ResourceRequirements{
|
||||
Requests: corev1.ResourceList{
|
||||
corev1.ResourceStorage: *logSearchDiskSpace,
|
||||
},
|
||||
},
|
||||
StorageClassName: &logSearchStorageClass,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
_, err = opClient.TenantUpdate(ctx, minTenant, metav1.UpdateOptions{})
|
||||
if err != nil {
|
||||
return false, restapi.ErrorWithContext(ctx, err)
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
||||
// disableTenantLoggingResponse disables Tenant Logging
|
||||
func disableTenantLoggingResponse(session *models.Principal, params operator_api.DisableTenantLoggingParams) (bool, *models.Error) {
|
||||
ctx, cancel := context.WithCancel(params.HTTPRequest.Context())
|
||||
defer cancel()
|
||||
|
||||
opClientClientSet, err := cluster.OperatorClient(session.STSSessionToken)
|
||||
if err != nil {
|
||||
return false, restapi.ErrorWithContext(ctx, err, restapi.ErrUnableToGetTenantUsage)
|
||||
}
|
||||
if err != nil {
|
||||
return false, restapi.ErrorWithContext(ctx, err, restapi.ErrUnableToGetTenantUsage)
|
||||
}
|
||||
|
||||
opClient := &operatorClient{
|
||||
client: opClientClientSet,
|
||||
}
|
||||
|
||||
minTenant, err := getTenant(ctx, opClient, params.Namespace, params.Tenant)
|
||||
if err != nil {
|
||||
return false, restapi.ErrorWithContext(ctx, err, restapi.ErrUnableToGetTenantUsage)
|
||||
}
|
||||
minTenant.EnsureDefaults()
|
||||
minTenant.Spec.Log = nil
|
||||
|
||||
_, err = opClient.TenantUpdate(ctx, minTenant, metav1.UpdateOptions{})
|
||||
if err != nil {
|
||||
return false, restapi.ErrorWithContext(ctx, err)
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func getTenantPodsResponse(session *models.Principal, params operator_api.GetTenantPodsParams) ([]*models.TenantPod, *models.Error) {
|
||||
ctx, cancel := context.WithCancel(params.HTTPRequest.Context())
|
||||
defer cancel()
|
||||
|
||||
Reference in New Issue
Block a user