diff --git a/operatorapi/tenant_logs_handlers.go b/operatorapi/tenant_logs_handlers.go new file mode 100644 index 000000000..8b3c8ab7c --- /dev/null +++ b/operatorapi/tenant_logs_handlers.go @@ -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 +} diff --git a/operatorapi/tenants.go b/operatorapi/tenants.go index 5c482824e..8d6858df7 100644 --- a/operatorapi/tenants.go +++ b/operatorapi/tenants.go @@ -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()