Add Audit Log and Log DB security context selector and split screen into tabs (#2156)
* Added security context selector for logging and log DB to Audit Log screen, split Audit Log screen into tabs * Cleaned up tab titles, disabled Save button while loading
This commit is contained in:
@@ -54,6 +54,9 @@ type TenantLogs struct {
|
||||
// db node selector
|
||||
DbNodeSelector []*NodeSelector `json:"dbNodeSelector"`
|
||||
|
||||
// db security context
|
||||
DbSecurityContext *SecurityContext `json:"dbSecurityContext,omitempty"`
|
||||
|
||||
// db service account name
|
||||
DbServiceAccountName string `json:"dbServiceAccountName,omitempty"`
|
||||
|
||||
@@ -84,6 +87,9 @@ type TenantLogs struct {
|
||||
// node selector
|
||||
NodeSelector []*NodeSelector `json:"nodeSelector"`
|
||||
|
||||
// security context
|
||||
SecurityContext *SecurityContext `json:"securityContext,omitempty"`
|
||||
|
||||
// service account name
|
||||
ServiceAccountName string `json:"serviceAccountName,omitempty"`
|
||||
}
|
||||
@@ -108,6 +114,10 @@ func (m *TenantLogs) Validate(formats strfmt.Registry) error {
|
||||
res = append(res, err)
|
||||
}
|
||||
|
||||
if err := m.validateDbSecurityContext(formats); err != nil {
|
||||
res = append(res, err)
|
||||
}
|
||||
|
||||
if err := m.validateLabels(formats); err != nil {
|
||||
res = append(res, err)
|
||||
}
|
||||
@@ -116,6 +126,10 @@ func (m *TenantLogs) Validate(formats strfmt.Registry) error {
|
||||
res = append(res, err)
|
||||
}
|
||||
|
||||
if err := m.validateSecurityContext(formats); err != nil {
|
||||
res = append(res, err)
|
||||
}
|
||||
|
||||
if len(res) > 0 {
|
||||
return errors.CompositeValidationError(res...)
|
||||
}
|
||||
@@ -226,6 +240,25 @@ func (m *TenantLogs) validateDbNodeSelector(formats strfmt.Registry) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *TenantLogs) validateDbSecurityContext(formats strfmt.Registry) error {
|
||||
if swag.IsZero(m.DbSecurityContext) { // not required
|
||||
return nil
|
||||
}
|
||||
|
||||
if m.DbSecurityContext != nil {
|
||||
if err := m.DbSecurityContext.Validate(formats); err != nil {
|
||||
if ve, ok := err.(*errors.Validation); ok {
|
||||
return ve.ValidateName("dbSecurityContext")
|
||||
} else if ce, ok := err.(*errors.CompositeError); ok {
|
||||
return ce.ValidateName("dbSecurityContext")
|
||||
}
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *TenantLogs) validateLabels(formats strfmt.Registry) error {
|
||||
if swag.IsZero(m.Labels) { // not required
|
||||
return nil
|
||||
@@ -278,6 +311,25 @@ func (m *TenantLogs) validateNodeSelector(formats strfmt.Registry) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *TenantLogs) validateSecurityContext(formats strfmt.Registry) error {
|
||||
if swag.IsZero(m.SecurityContext) { // not required
|
||||
return nil
|
||||
}
|
||||
|
||||
if m.SecurityContext != nil {
|
||||
if err := m.SecurityContext.Validate(formats); err != nil {
|
||||
if ve, ok := err.(*errors.Validation); ok {
|
||||
return ve.ValidateName("securityContext")
|
||||
} else if ce, ok := err.(*errors.CompositeError); ok {
|
||||
return ce.ValidateName("securityContext")
|
||||
}
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ContextValidate validate this tenant logs based on the context it is used
|
||||
func (m *TenantLogs) ContextValidate(ctx context.Context, formats strfmt.Registry) error {
|
||||
var res []error
|
||||
@@ -298,6 +350,10 @@ func (m *TenantLogs) ContextValidate(ctx context.Context, formats strfmt.Registr
|
||||
res = append(res, err)
|
||||
}
|
||||
|
||||
if err := m.contextValidateDbSecurityContext(ctx, formats); err != nil {
|
||||
res = append(res, err)
|
||||
}
|
||||
|
||||
if err := m.contextValidateLabels(ctx, formats); err != nil {
|
||||
res = append(res, err)
|
||||
}
|
||||
@@ -306,6 +362,10 @@ func (m *TenantLogs) ContextValidate(ctx context.Context, formats strfmt.Registr
|
||||
res = append(res, err)
|
||||
}
|
||||
|
||||
if err := m.contextValidateSecurityContext(ctx, formats); err != nil {
|
||||
res = append(res, err)
|
||||
}
|
||||
|
||||
if len(res) > 0 {
|
||||
return errors.CompositeValidationError(res...)
|
||||
}
|
||||
@@ -392,6 +452,22 @@ func (m *TenantLogs) contextValidateDbNodeSelector(ctx context.Context, formats
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *TenantLogs) contextValidateDbSecurityContext(ctx context.Context, formats strfmt.Registry) error {
|
||||
|
||||
if m.DbSecurityContext != nil {
|
||||
if err := m.DbSecurityContext.ContextValidate(ctx, formats); err != nil {
|
||||
if ve, ok := err.(*errors.Validation); ok {
|
||||
return ve.ValidateName("dbSecurityContext")
|
||||
} else if ce, ok := err.(*errors.CompositeError); ok {
|
||||
return ce.ValidateName("dbSecurityContext")
|
||||
}
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *TenantLogs) contextValidateLabels(ctx context.Context, formats strfmt.Registry) error {
|
||||
|
||||
for i := 0; i < len(m.Labels); i++ {
|
||||
@@ -432,6 +508,22 @@ func (m *TenantLogs) contextValidateNodeSelector(ctx context.Context, formats st
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *TenantLogs) contextValidateSecurityContext(ctx context.Context, formats strfmt.Registry) error {
|
||||
|
||||
if m.SecurityContext != nil {
|
||||
if err := m.SecurityContext.ContextValidate(ctx, formats); err != nil {
|
||||
if ve, ok := err.(*errors.Validation); ok {
|
||||
return ve.ValidateName("securityContext")
|
||||
} else if ce, ok := err.(*errors.CompositeError); ok {
|
||||
return ce.ValidateName("securityContext")
|
||||
}
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// MarshalBinary interface implementation
|
||||
func (m *TenantLogs) MarshalBinary() ([]byte, error) {
|
||||
if m == nil {
|
||||
|
||||
@@ -4206,6 +4206,10 @@ func init() {
|
||||
"$ref": "#/definitions/nodeSelector"
|
||||
}
|
||||
},
|
||||
"dbSecurityContext": {
|
||||
"type": "object",
|
||||
"$ref": "#/definitions/securityContext"
|
||||
},
|
||||
"dbServiceAccountName": {
|
||||
"type": "string"
|
||||
},
|
||||
@@ -4242,6 +4246,10 @@ func init() {
|
||||
"$ref": "#/definitions/nodeSelector"
|
||||
}
|
||||
},
|
||||
"securityContext": {
|
||||
"type": "object",
|
||||
"$ref": "#/definitions/securityContext"
|
||||
},
|
||||
"serviceAccountName": {
|
||||
"type": "string"
|
||||
}
|
||||
@@ -9568,6 +9576,10 @@ func init() {
|
||||
"$ref": "#/definitions/nodeSelector"
|
||||
}
|
||||
},
|
||||
"dbSecurityContext": {
|
||||
"type": "object",
|
||||
"$ref": "#/definitions/securityContext"
|
||||
},
|
||||
"dbServiceAccountName": {
|
||||
"type": "string"
|
||||
},
|
||||
@@ -9604,6 +9616,10 @@ func init() {
|
||||
"$ref": "#/definitions/nodeSelector"
|
||||
}
|
||||
},
|
||||
"securityContext": {
|
||||
"type": "object",
|
||||
"$ref": "#/definitions/securityContext"
|
||||
},
|
||||
"serviceAccountName": {
|
||||
"type": "string"
|
||||
}
|
||||
|
||||
@@ -1357,7 +1357,7 @@ func getTenantUsageResponse(session *models.Principal, params operator_api.GetTe
|
||||
return info, nil
|
||||
}
|
||||
|
||||
// getTenantLogsResponse returns the logs of a tenant
|
||||
// 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()
|
||||
@@ -1392,11 +1392,9 @@ func getTenantLogsResponse(session *models.Principal, params operator_api.GetTen
|
||||
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})
|
||||
@@ -1409,6 +1407,15 @@ func getTenantLogsResponse(session *models.Principal, params operator_api.GetTen
|
||||
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)}
|
||||
@@ -1421,12 +1428,14 @@ func getTenantLogsResponse(session *models.Principal, params operator_api.GetTen
|
||||
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,
|
||||
}
|
||||
|
||||
@@ -1454,7 +1463,7 @@ func getTenantLogsResponse(session *models.Principal, params operator_api.GetTen
|
||||
return tenantLoggingConfiguration, nil
|
||||
}
|
||||
|
||||
// setTenantLogsResponse returns the logs of a tenant
|
||||
// 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()
|
||||
@@ -1474,44 +1483,54 @@ func setTenantLogsResponse(session *models.Principal, params operator_api.SetTen
|
||||
}
|
||||
|
||||
labels := make(map[string]string)
|
||||
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
|
||||
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
|
||||
}
|
||||
minTenant.Spec.Log.Labels = labels
|
||||
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
|
||||
|
||||
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
|
||||
}
|
||||
minTenant.Spec.Log.Annotations = annotations
|
||||
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
|
||||
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
|
||||
}
|
||||
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, restapi.ErrorWithContext(ctx, err)
|
||||
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
|
||||
}
|
||||
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, restapi.ErrorWithContext(ctx, err)
|
||||
}
|
||||
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
|
||||
logResourceRequest["memory"] = memQuantity
|
||||
minTenant.Spec.Log.Resources.Requests = logResourceRequest
|
||||
}
|
||||
}
|
||||
|
||||
modified := false
|
||||
@@ -1519,97 +1538,122 @@ func setTenantLogsResponse(session *models.Principal, params operator_api.SetTen
|
||||
modified = true
|
||||
}
|
||||
dbLabels := make(map[string]string)
|
||||
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
|
||||
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
|
||||
}
|
||||
modified = true
|
||||
}
|
||||
dbAnnotations := make(map[string]string)
|
||||
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
|
||||
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
|
||||
}
|
||||
modified = true
|
||||
}
|
||||
dbNodeSelector := make(map[string]string)
|
||||
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 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 reflect.TypeOf(params.Data.LogDBMemRequest).Kind() == reflect.String {
|
||||
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
|
||||
}
|
||||
minTenant.Spec.Log.Image = params.Data.Image
|
||||
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)}
|
||||
}
|
||||
}
|
||||
minTenant.Spec.Log.ServiceAccountName = params.Data.ServiceAccountName
|
||||
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,
|
||||
},
|
||||
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 params.Data.DbLabels != nil {
|
||||
minTenant.Spec.Log.ServiceAccountName = params.Data.ServiceAccountName
|
||||
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.ServiceAccountName = params.Data.DbServiceAccountName
|
||||
minTenant.Spec.Log.Db.SecurityContext, err = convertModelSCToK8sSC(params.Data.DbSecurityContext)
|
||||
if err != nil {
|
||||
return false, restapi.ErrorWithContext(ctx, err)
|
||||
}
|
||||
}
|
||||
} 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.ServiceAccountName = params.Data.DbServiceAccountName
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -795,6 +795,16 @@ export const wizardCommon = {
|
||||
alignItems: "center" as const,
|
||||
justifyContent: "flex-start" as const,
|
||||
},
|
||||
multiContainerStackNarrow: {
|
||||
display: "flex" ,
|
||||
alignItems: "center" ,
|
||||
justifyContent: "flex-start",
|
||||
gap: "8px",
|
||||
"@media (max-width: 750px)": {
|
||||
flexFlow: "column",
|
||||
flexDirection: "column",
|
||||
},
|
||||
},
|
||||
sizeFactorContainer: {
|
||||
marginLeft: 8,
|
||||
alignSelf: "flex-start" as const,
|
||||
|
||||
@@ -238,6 +238,8 @@ export interface ITenantLogsStruct {
|
||||
logMemRequest: string;
|
||||
logDBCPURequest: string;
|
||||
logDBMemRequest: string;
|
||||
securityContext: ISecurityContext;
|
||||
dbSecurityContext: ISecurityContext;
|
||||
}
|
||||
|
||||
export interface ValueUnit {
|
||||
@@ -273,3 +275,10 @@ export interface IEditPoolRequest {
|
||||
export interface IPlotBarValues {
|
||||
[key: string]: CapacityValue;
|
||||
}
|
||||
|
||||
export interface ITenantAuditLogs {
|
||||
classes: any;
|
||||
labels: IKeyValue[];
|
||||
annotations: IKeyValue[];
|
||||
nodeSelector: IKeyValue[];
|
||||
}
|
||||
@@ -0,0 +1,346 @@
|
||||
// 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
//import { ISecurityContext} from "../types";
|
||||
import { Theme } from "@mui/material/styles";
|
||||
import createStyles from "@mui/styles/createStyles";
|
||||
import withStyles from "@mui/styles/withStyles";
|
||||
import {
|
||||
containerForHeader,
|
||||
createTenantCommon,
|
||||
formFieldStyles,
|
||||
modalBasic,
|
||||
spacingUtils,
|
||||
tenantDetailsStyles,
|
||||
wizardCommon,
|
||||
} from "../../Common/FormComponents/common/styleLibrary";
|
||||
import React, { Fragment, useState } from "react";
|
||||
import { useSelector } from "react-redux";
|
||||
import { AppState, useAppDispatch } from "../../../../store";
|
||||
import api from "../../../../common/api";
|
||||
import { ErrorResponseHandler } from "../../../../common/types";
|
||||
import { useParams } from "react-router-dom";
|
||||
|
||||
import Grid from "@mui/material/Grid";
|
||||
import InputBoxWrapper from "../../Common/FormComponents/InputBoxWrapper/InputBoxWrapper";
|
||||
import { Button } from "@mui/material";
|
||||
import {
|
||||
setErrorSnackMessage,
|
||||
setSnackBarMessage,
|
||||
} from "../../../../systemSlice";
|
||||
import { IKeyValue, ITenantAuditLogs } from "../ListTenants/types";
|
||||
import KeyPairEdit from "./KeyPairEdit";
|
||||
import InputUnitMenu from "../../Common/FormComponents/InputUnitMenu/InputUnitMenu";
|
||||
import {
|
||||
setDBImage,
|
||||
setDBInitImage,
|
||||
setDBCPURequest,
|
||||
setDBMemRequest,
|
||||
setDBRunAsUser,
|
||||
setDBFSGroup,
|
||||
setDBRunAsGroup,
|
||||
setDBRunAsNonRoot,
|
||||
setRefreshLoggingInfo,
|
||||
} from "../TenantDetails/tenantAuditLogSlice";
|
||||
|
||||
|
||||
import SecurityContextSelector from "../securityContextSelector";
|
||||
|
||||
import { clearValidationError } from "../utils";
|
||||
|
||||
const styles = (theme: Theme) =>
|
||||
createStyles({
|
||||
...tenantDetailsStyles,
|
||||
...spacingUtils,
|
||||
bold: { fontWeight: "bold" },
|
||||
italic: { fontStyle: "italic" },
|
||||
fileItem: {
|
||||
marginRight: 10,
|
||||
display: "flex",
|
||||
"& div label": {
|
||||
minWidth: 50,
|
||||
},
|
||||
|
||||
"@media (max-width: 900px)": {
|
||||
flexFlow: "column",
|
||||
},
|
||||
},
|
||||
...containerForHeader(theme.spacing(4)),
|
||||
...createTenantCommon,
|
||||
...formFieldStyles,
|
||||
...modalBasic,
|
||||
...wizardCommon,
|
||||
});
|
||||
|
||||
const LoggingDBDetails = ({ classes, labels, annotations, nodeSelector }: ITenantAuditLogs) => {
|
||||
const dispatch = useAppDispatch();
|
||||
const { tenantName, tenantNamespace } = useParams();
|
||||
const dbImage = useSelector(
|
||||
(state: AppState) => state.editTenantLogging.dbImage
|
||||
);
|
||||
const dbInitImage = useSelector(
|
||||
(state: AppState) => state.editTenantLogging.dbInitImage
|
||||
);
|
||||
const dbCpuRequest = useSelector(
|
||||
(state: AppState) => state.editTenantLogging.dbCPURequest
|
||||
);
|
||||
const dbMemRequest = useSelector(
|
||||
(state: AppState) => state.editTenantLogging.dbMemRequest
|
||||
);
|
||||
const dbServiceAccountName = useSelector(
|
||||
(state: AppState) => state.editTenantLogging.dbServiceAccountName
|
||||
);
|
||||
|
||||
const dbRunAsGroup = useSelector(
|
||||
(state: AppState) => state.editTenantLogging.dbSecurityContext.runAsGroup
|
||||
);
|
||||
const dbRunAsUser = useSelector(
|
||||
(state: AppState) => state.editTenantLogging.dbSecurityContext.runAsUser
|
||||
)
|
||||
const dbFSGroup = useSelector(
|
||||
(state: AppState) => state.editTenantLogging.dbSecurityContext.fsGroup
|
||||
)
|
||||
const dbRunAsNonRoot = useSelector(
|
||||
(state: AppState) => state.editTenantLogging.dbSecurityContext.runAsNonRoot
|
||||
)
|
||||
const [validationErrors, setValidationErrors] = useState<any>({});
|
||||
|
||||
const [dbLabels, setDBLabels] = useState<IKeyValue[]>((labels != null && labels.length > 0) ? labels : [{ key: "", value: "" }]);
|
||||
const [dbAnnotations, setDBAnnotations] = useState<IKeyValue[]>((annotations != null && annotations.length > 0)? annotations : [{ key: "", value: "" }]);
|
||||
const [dbNodeSelector, setDBNodeSelector] = useState<IKeyValue[]>((nodeSelector != null && nodeSelector.length > 0)? nodeSelector :[{ key: "", value: "" }]);
|
||||
|
||||
const [dbLabelsError, setDBLabelsError] = useState<any>({});
|
||||
const [dbAnnotationsError, setDBAnnotationsError] = useState<any>({});
|
||||
const [dbNodeSelectorError, setDBNodeSelectorError] = useState<any>({});
|
||||
|
||||
const cleanValidation = (fieldName: string) => {
|
||||
setValidationErrors(clearValidationError(validationErrors, fieldName));
|
||||
};
|
||||
|
||||
|
||||
|
||||
const trim = (x: IKeyValue[]): IKeyValue[] => {
|
||||
let retval: IKeyValue[] = [];
|
||||
for (let i = 0; i < x.length; i++) {
|
||||
if (x[i].key !== "") {
|
||||
retval.push(x[i]);
|
||||
}
|
||||
}
|
||||
return retval;
|
||||
};
|
||||
|
||||
const checkValid = (): boolean => {
|
||||
if (
|
||||
Object.keys(validationErrors).length !== 0 ||
|
||||
Object.keys(dbNodeSelectorError).length !== 0 ||
|
||||
Object.keys(dbAnnotationsError).length !== 0 ||
|
||||
Object.keys(dbLabelsError).length !== 0
|
||||
) {
|
||||
let err: ErrorResponseHandler = {
|
||||
errorMessage: "Invalid entry",
|
||||
detailedError: "",
|
||||
};
|
||||
dispatch(setErrorSnackMessage(err));
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
const submitLoggingInfo = () => {
|
||||
if (checkValid()) {
|
||||
const dbSecurityContext = {
|
||||
runAsGroup: dbRunAsGroup != null ? dbRunAsGroup : "",
|
||||
runAsUser: dbRunAsUser != null ? dbRunAsUser : "",
|
||||
fsGroup: dbFSGroup != null ? dbFSGroup : "",
|
||||
runAsNonRoot: dbRunAsNonRoot != null ? dbRunAsNonRoot : true,
|
||||
}
|
||||
api
|
||||
.invoke(
|
||||
"PUT",
|
||||
`/api/v1/namespaces/${tenantNamespace}/tenants/${tenantName}/log`,
|
||||
{
|
||||
dbLabels: trim(dbLabels),
|
||||
dbAnnotations: trim(dbAnnotations),
|
||||
dbNodeSelector: trim(dbNodeSelector),
|
||||
dbImage: dbImage,
|
||||
dbInitImage: dbInitImage,
|
||||
dbServiceAccountName: dbServiceAccountName,
|
||||
logDBCPURequest: dbCpuRequest,
|
||||
logDBMemRequest: dbMemRequest,
|
||||
dbSecurityContext: dbSecurityContext,
|
||||
}
|
||||
)
|
||||
.then(() => {
|
||||
setRefreshLoggingInfo(true);
|
||||
dispatch(setSnackBarMessage(`Audit Log DB configuration updated.`));
|
||||
})
|
||||
.catch((err: ErrorResponseHandler) => {
|
||||
setErrorSnackMessage(err);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<Fragment>
|
||||
|
||||
<Grid item xs={12} paddingBottom={2}>
|
||||
<InputBoxWrapper
|
||||
id={`dbImage`}
|
||||
label={"DB Postgres Image"}
|
||||
placeholder={"library/postgres:13"}
|
||||
name={`dbImage`}
|
||||
value={dbImage}
|
||||
onChange={(event: React.ChangeEvent<HTMLInputElement>) => {
|
||||
if (event.target.validity.valid) {
|
||||
dispatch(setDBImage(event.target.value));
|
||||
}
|
||||
cleanValidation(`dbImage`);
|
||||
}}
|
||||
key={`dbImage`}
|
||||
pattern={"^[a-zA-Z0-9-./:]{1,253}$"}
|
||||
error={validationErrors[`dbImage`] || ""}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12} paddingBottom={2}>
|
||||
<InputBoxWrapper
|
||||
id={`dbInitImage`}
|
||||
label={"DB Init Image"}
|
||||
placeholder={"library/busybox:1.33.1"}
|
||||
name={`dbInitImage`}
|
||||
value={dbInitImage}
|
||||
onChange={(event: React.ChangeEvent<HTMLInputElement>) => {
|
||||
if (event.target.validity.valid) {
|
||||
dispatch(setDBInitImage(event.target.value));
|
||||
}
|
||||
cleanValidation(`dbInitImage`);
|
||||
}}
|
||||
key={`dbInitImage`}
|
||||
pattern={"^[a-zA-Z0-9-./:]{1,253}$"}
|
||||
error={validationErrors[`dbInitImage`] || ""}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12} paddingBottom={2}>
|
||||
<InputBoxWrapper
|
||||
id={`dbCPURequest`}
|
||||
label={"DB CPU Request"}
|
||||
placeholder={"DB CPU Request"}
|
||||
name={`dbCPURequest`}
|
||||
value={dbCpuRequest}
|
||||
pattern={"[0-9]*"}
|
||||
onChange={(event: React.ChangeEvent<HTMLInputElement>) => {
|
||||
if (event.target.validity.valid) {
|
||||
dispatch(setDBCPURequest(event.target.value));
|
||||
}
|
||||
cleanValidation(`dbCPURequest`);
|
||||
}}
|
||||
key={`dbCPURequest`}
|
||||
error={validationErrors[`dbCPURequest`] || ""}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12} paddingBottom={2}>
|
||||
<InputBoxWrapper
|
||||
id={`dbMemRequest`}
|
||||
label={"DB Memory Request"}
|
||||
placeholder={"DB Memory request"}
|
||||
name={`dbMemRequest`}
|
||||
value={dbMemRequest}
|
||||
onChange={(event: React.ChangeEvent<HTMLInputElement>) => {
|
||||
if (event.target.validity.valid) {
|
||||
dispatch(setDBMemRequest(event.target.value));
|
||||
}
|
||||
cleanValidation(`dbMemRequest`);
|
||||
}}
|
||||
pattern={"[0-9]*"}
|
||||
key={`dbMemRequest`}
|
||||
error={validationErrors[`dbMemRequest`] || ""}
|
||||
overlayObject={
|
||||
<InputUnitMenu
|
||||
id={"size-unit"}
|
||||
onUnitChange={() => {}}
|
||||
unitSelected={"Gi"}
|
||||
unitsList={[{ label: "Gi", value: "Gi" }]}
|
||||
disabled={true}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
</Grid>
|
||||
|
||||
<Grid item xs={12} className={classes.formFieldRow}>
|
||||
<span className={classes.inputLabel}>DB Labels</span>
|
||||
<KeyPairEdit
|
||||
newValues={dbLabels}
|
||||
setNewValues={setDBLabels}
|
||||
paramName={"dbLabels"}
|
||||
error={dbLabelsError}
|
||||
setError={setDBLabelsError}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12} className={classes.formFieldRow}>
|
||||
<span className={classes.inputLabel}>DB Annotations</span>
|
||||
<KeyPairEdit
|
||||
newValues={dbAnnotations}
|
||||
setNewValues={setDBAnnotations}
|
||||
paramName={"dbAnnotations"}
|
||||
error={dbAnnotationsError}
|
||||
setError={setDBAnnotationsError}
|
||||
/>
|
||||
</Grid>
|
||||
|
||||
<Grid item xs={12} className={classes.formFieldRow}>
|
||||
<span className={classes.inputLabel}>DB Node Selector</span>
|
||||
<KeyPairEdit
|
||||
newValues={dbNodeSelector}
|
||||
setNewValues={setDBNodeSelector}
|
||||
paramName={"DB Node Selector"}
|
||||
error={dbNodeSelectorError}
|
||||
setError={setDBNodeSelectorError}
|
||||
/>
|
||||
</Grid>
|
||||
|
||||
<Grid item xs={12} className={classes.formFieldRow}>
|
||||
<SecurityContextSelector classes={classes}
|
||||
runAsGroup={dbRunAsGroup}
|
||||
runAsUser={dbRunAsUser}
|
||||
fsGroup={dbFSGroup}
|
||||
runAsNonRoot={dbRunAsNonRoot}
|
||||
setFSGroup={(value : string)=>dispatch(setDBFSGroup(value))}
|
||||
setRunAsUser={(value : string)=>dispatch(setDBRunAsUser(value))}
|
||||
setRunAsGroup={(value : string)=>dispatch(setDBRunAsGroup(value))}
|
||||
setRunAsNonRoot={(value : boolean)=>dispatch(setDBRunAsNonRoot(value))}
|
||||
/></Grid>
|
||||
<Grid item xs={12} textAlign={"right"}>
|
||||
<Button
|
||||
type="submit"
|
||||
variant="contained"
|
||||
color="primary"
|
||||
disabled={!checkValid()}
|
||||
onClick={() => submitLoggingInfo()}
|
||||
>
|
||||
Save
|
||||
</Button>
|
||||
</Grid>
|
||||
</Fragment>
|
||||
|
||||
</Fragment>
|
||||
);
|
||||
};
|
||||
|
||||
export default withStyles(styles)(LoggingDBDetails);
|
||||
@@ -0,0 +1,379 @@
|
||||
// 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
//import { ISecurityContext} from "../types";
|
||||
import { Theme } from "@mui/material/styles";
|
||||
import createStyles from "@mui/styles/createStyles";
|
||||
import withStyles from "@mui/styles/withStyles";
|
||||
import {
|
||||
containerForHeader,
|
||||
createTenantCommon,
|
||||
formFieldStyles,
|
||||
modalBasic,
|
||||
spacingUtils,
|
||||
tenantDetailsStyles,
|
||||
wizardCommon,
|
||||
} from "../../Common/FormComponents/common/styleLibrary";
|
||||
import React, { Fragment, useState } from "react";
|
||||
import { useSelector } from "react-redux";
|
||||
import { AppState, useAppDispatch } from "../../../../store";
|
||||
import api from "../../../../common/api";
|
||||
import { ErrorResponseHandler } from "../../../../common/types";
|
||||
import { useParams } from "react-router-dom";
|
||||
import Grid from "@mui/material/Grid";
|
||||
import InputBoxWrapper from "../../Common/FormComponents/InputBoxWrapper/InputBoxWrapper";
|
||||
import { Button } from "@mui/material";
|
||||
import {
|
||||
setErrorSnackMessage,
|
||||
setSnackBarMessage,
|
||||
} from "../../../../systemSlice";
|
||||
import { IKeyValue, ITenantAuditLogs } from "../ListTenants/types";
|
||||
import KeyPairEdit from "./KeyPairEdit";
|
||||
import InputUnitMenu from "../../Common/FormComponents/InputUnitMenu/InputUnitMenu";
|
||||
import SecurityContextSelector from "../securityContextSelector";
|
||||
import { clearValidationError } from "../utils";
|
||||
import {
|
||||
setImage,
|
||||
setDiskCapacityGB,
|
||||
setServiceAccountName,
|
||||
setCPURequest,
|
||||
setMemRequest,
|
||||
setRunAsUser,
|
||||
setFSGroup,
|
||||
setRunAsGroup,
|
||||
setRunAsNonRoot,
|
||||
setRefreshLoggingInfo,
|
||||
} from "../TenantDetails/tenantAuditLogSlice";
|
||||
|
||||
const styles = (theme: Theme) =>
|
||||
createStyles({
|
||||
...tenantDetailsStyles,
|
||||
...spacingUtils,
|
||||
bold: { fontWeight: "bold" },
|
||||
italic: { fontStyle: "italic" },
|
||||
fileItem: {
|
||||
marginRight: 10,
|
||||
display: "flex",
|
||||
"& div label": {
|
||||
minWidth: 50,
|
||||
},
|
||||
|
||||
"@media (max-width: 900px)": {
|
||||
flexFlow: "column",
|
||||
},
|
||||
},
|
||||
...containerForHeader(theme.spacing(4)),
|
||||
...createTenantCommon,
|
||||
...formFieldStyles,
|
||||
...modalBasic,
|
||||
...wizardCommon,
|
||||
});
|
||||
|
||||
const TenantAuditLogging = ({ classes, labels, annotations, nodeSelector }: ITenantAuditLogs) => {
|
||||
const dispatch = useAppDispatch();
|
||||
const { tenantName, tenantNamespace } = useParams();
|
||||
const auditLoggingEnabled = useSelector(
|
||||
(state: AppState) => state.editTenantLogging.auditLoggingEnabled
|
||||
);
|
||||
const image = useSelector(
|
||||
(state: AppState) => state.editTenantLogging.image
|
||||
);
|
||||
const diskCapacityGB = useSelector(
|
||||
(state: AppState) => state.editTenantLogging.diskCapacityGB
|
||||
);
|
||||
const cpuRequest = useSelector(
|
||||
(state: AppState) => state.editTenantLogging.cpuRequest
|
||||
);
|
||||
const memRequest = useSelector(
|
||||
(state: AppState) => state.editTenantLogging.memRequest
|
||||
);
|
||||
const serviceAccountName = useSelector(
|
||||
(state: AppState) => state.editTenantLogging.serviceAccountName
|
||||
);
|
||||
const runAsGroup = useSelector(
|
||||
(state: AppState) => state.editTenantLogging.securityContext.runAsGroup
|
||||
);
|
||||
const runAsUser = useSelector(
|
||||
(state: AppState) => state.editTenantLogging.securityContext.runAsUser
|
||||
)
|
||||
const fsGroup = useSelector(
|
||||
(state: AppState) => state.editTenantLogging.securityContext.fsGroup
|
||||
)
|
||||
const runAsNonRoot = useSelector(
|
||||
(state: AppState) => state.editTenantLogging.securityContext.runAsNonRoot
|
||||
)
|
||||
|
||||
const [validationErrors, setValidationErrors] = useState<any>({});
|
||||
const [loading, setLoading] = useState<boolean>(false);
|
||||
|
||||
const [logLabels, setLabels] = useState<IKeyValue[]>((labels != null && labels.length > 0) ? labels : [{ key: "", value: "" }]);
|
||||
const [logAnnotations, setAnnotations] = useState<IKeyValue[]>((annotations != null && annotations.length > 0)? annotations : [{ key: "", value: "" }]);
|
||||
const [logNodeSelector, setNodeSelector] = useState<IKeyValue[]>((nodeSelector != null && nodeSelector.length > 0)? nodeSelector :[{ key: "", value: "" }]);
|
||||
|
||||
const [labelsError, setLabelsError] = useState<any>({});
|
||||
const [annotationsError, setAnnotationsError] = useState<any>({});
|
||||
const [nodeSelectorError, setNodeSelectorError] = useState<any>({});
|
||||
|
||||
const cleanValidation = (fieldName: string) => {
|
||||
setValidationErrors(clearValidationError(validationErrors, fieldName));
|
||||
};
|
||||
|
||||
const trim = (x: IKeyValue[]): IKeyValue[] => {
|
||||
let retval: IKeyValue[] = [];
|
||||
for (let i = 0; i < x.length; i++) {
|
||||
if (x[i].key !== "") {
|
||||
retval.push(x[i]);
|
||||
}
|
||||
}
|
||||
return retval;
|
||||
};
|
||||
|
||||
const checkValid = (): boolean => {
|
||||
if (
|
||||
Object.keys(validationErrors).length !== 0 ||
|
||||
Object.keys(labelsError).length !== 0 ||
|
||||
Object.keys(annotationsError).length !== 0 ||
|
||||
Object.keys(nodeSelectorError).length !== 0
|
||||
) {
|
||||
let err: ErrorResponseHandler = {
|
||||
errorMessage: "Invalid entry",
|
||||
detailedError: "",
|
||||
};
|
||||
dispatch(setErrorSnackMessage(err));
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
const submitLoggingInfo = () => {
|
||||
|
||||
if (checkValid()) {
|
||||
setLoading(true);
|
||||
const securityContext = {
|
||||
runAsGroup: runAsGroup != null ? runAsGroup : "",
|
||||
runAsUser: runAsUser != null ? runAsUser : "",
|
||||
fsGroup: fsGroup != null ? fsGroup : "",
|
||||
runAsNonRoot: runAsNonRoot != null ? runAsNonRoot : true,
|
||||
}
|
||||
|
||||
api
|
||||
.invoke(
|
||||
"PUT",
|
||||
`/api/v1/namespaces/${tenantNamespace}/tenants/${tenantName}/log`,
|
||||
{
|
||||
labels: trim(logLabels),
|
||||
annotations: trim(logAnnotations),
|
||||
nodeSelector: trim(logNodeSelector),
|
||||
image: image,
|
||||
diskCapacityGB: diskCapacityGB.toString(),
|
||||
serviceAccountName: serviceAccountName,
|
||||
logCPURequest: cpuRequest,
|
||||
logMemRequest: memRequest,
|
||||
securityContext: securityContext,
|
||||
}
|
||||
)
|
||||
.then(() => {
|
||||
setRefreshLoggingInfo(true);
|
||||
dispatch(setSnackBarMessage(`Audit Log configuration updated.`));
|
||||
setLoading(false);
|
||||
})
|
||||
.catch((err: ErrorResponseHandler) => {
|
||||
setErrorSnackMessage(err);
|
||||
setLoading(false);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
{auditLoggingEnabled && (
|
||||
<Fragment>
|
||||
<Grid item xs={12} paddingBottom={2}>
|
||||
<InputBoxWrapper
|
||||
id={`image`}
|
||||
label={"Image"}
|
||||
placeholder={"minio/operator:v4.4.22"}
|
||||
name={`image`}
|
||||
value={image}
|
||||
onChange={(event: React.ChangeEvent<HTMLInputElement>) => {
|
||||
if (event.target.validity.valid) {
|
||||
dispatch(setImage(event.target.value));
|
||||
}
|
||||
cleanValidation(`image`);
|
||||
}}
|
||||
key={`image`}
|
||||
pattern={"^[a-zA-Z0-9-./:]{1,253}$"}
|
||||
error={validationErrors[`image`] || ""}
|
||||
/>
|
||||
</Grid>
|
||||
|
||||
<Grid item xs={12} paddingBottom={2}>
|
||||
<InputBoxWrapper
|
||||
id={`diskCapacityGB`}
|
||||
label={"Disk Capacity"}
|
||||
placeholder={"Disk Capacity"}
|
||||
name={`diskCapacityGB`}
|
||||
value={!isNaN(diskCapacityGB) ? diskCapacityGB.toString() : "0"}
|
||||
onChange={(event: React.ChangeEvent<HTMLInputElement>) => {
|
||||
if (event.target.validity.valid) {
|
||||
dispatch(setDiskCapacityGB(parseInt(event.target.value)));
|
||||
}
|
||||
cleanValidation(`diskCapacityGB`);
|
||||
}}
|
||||
key={`diskCapacityGB`}
|
||||
pattern={"[0-9]*"}
|
||||
error={validationErrors[`diskCapacityGB`] || ""}
|
||||
overlayObject={
|
||||
<InputUnitMenu
|
||||
id={"size-unit"}
|
||||
onUnitChange={() => {}}
|
||||
unitSelected={"Gi"}
|
||||
unitsList={[{ label: "Gi", value: "Gi" }]}
|
||||
disabled={true}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12} paddingBottom={2}>
|
||||
<InputBoxWrapper
|
||||
id={`cpuRequest`}
|
||||
label={"CPU Request"}
|
||||
placeholder={"CPU Request"}
|
||||
name={`cpuRequest`}
|
||||
value={cpuRequest}
|
||||
pattern={"[0-9]*"}
|
||||
onChange={(event: React.ChangeEvent<HTMLInputElement>) => {
|
||||
if (event.target.validity.valid) {
|
||||
dispatch(setCPURequest(event.target.value));
|
||||
}
|
||||
cleanValidation(`cpuRequest`);
|
||||
}}
|
||||
key={`cpuRequest`}
|
||||
error={validationErrors[`cpuRequest`] || ""}
|
||||
/>
|
||||
</Grid>
|
||||
|
||||
<Grid item xs={12} paddingBottom={2}>
|
||||
<InputBoxWrapper
|
||||
id={`memRequest`}
|
||||
label={"Memory Request"}
|
||||
placeholder={"Memory request"}
|
||||
name={`memRequest`}
|
||||
value={memRequest}
|
||||
onChange={(event: React.ChangeEvent<HTMLInputElement>) => {
|
||||
if (event.target.validity.valid) {
|
||||
dispatch(setMemRequest(event.target.value));
|
||||
}
|
||||
cleanValidation(`memRequest`);
|
||||
}}
|
||||
pattern={"[0-9]*"}
|
||||
key={`memRequest`}
|
||||
error={validationErrors[`memRequest`] || ""}
|
||||
overlayObject={
|
||||
<InputUnitMenu
|
||||
id={"size-unit"}
|
||||
onUnitChange={() => {}}
|
||||
unitSelected={"Gi"}
|
||||
unitsList={[{ label: "Gi", value: "Gi" }]}
|
||||
disabled={true}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
</Grid>
|
||||
|
||||
<Grid item xs={12} paddingBottom={2}>
|
||||
<InputBoxWrapper
|
||||
id={`serviceAccountName`}
|
||||
label={"Service Account"}
|
||||
placeholder={"Service Account Name"}
|
||||
name={`serviceAccountName`}
|
||||
value={serviceAccountName}
|
||||
onChange={(event: React.ChangeEvent<HTMLInputElement>) => {
|
||||
if (event.target.validity.valid) {
|
||||
dispatch(setServiceAccountName(event.target.value));
|
||||
}
|
||||
cleanValidation(`serviceAccountName`);
|
||||
}}
|
||||
key={`serviceAccountName`}
|
||||
pattern={"^[a-zA-Z0-9-.]{1,253}$"}
|
||||
error={validationErrors[`serviceAccountName`] || ""}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12} className={classes.formFieldRow}>
|
||||
<SecurityContextSelector classes={classes}
|
||||
runAsGroup={runAsGroup}
|
||||
runAsUser={runAsUser}
|
||||
fsGroup={fsGroup}
|
||||
runAsNonRoot={runAsNonRoot}
|
||||
setFSGroup={(value : string)=>dispatch(setFSGroup(value))}
|
||||
setRunAsUser={(value : string)=>dispatch(setRunAsUser(value))}
|
||||
setRunAsGroup={(value : string)=>dispatch(setRunAsGroup(value))}
|
||||
setRunAsNonRoot={(value : boolean)=>dispatch(setRunAsNonRoot(value))}
|
||||
/>
|
||||
</Grid>
|
||||
|
||||
<Grid item xs={12} className={classes.formFieldRow}>
|
||||
<span className={classes.inputLabel}>Labels</span>
|
||||
<KeyPairEdit
|
||||
newValues={logLabels}
|
||||
setNewValues={setLabels}
|
||||
paramName={"Labels"}
|
||||
error={labelsError}
|
||||
setError={setLabelsError}
|
||||
/>
|
||||
</Grid>
|
||||
|
||||
<Grid item xs={12} className={classes.formFieldRow}>
|
||||
<span className={classes.inputLabel}>Annotations</span>
|
||||
<KeyPairEdit
|
||||
newValues={logAnnotations }
|
||||
setNewValues={setAnnotations}
|
||||
paramName={"Annotations"}
|
||||
error={annotationsError}
|
||||
setError={setAnnotationsError}
|
||||
/>
|
||||
</Grid>
|
||||
|
||||
<Grid item xs={12} className={classes.formFieldRow}>
|
||||
<span className={classes.inputLabel}>Node Selector</span>
|
||||
<KeyPairEdit
|
||||
newValues={logNodeSelector}
|
||||
setNewValues={setNodeSelector}
|
||||
paramName={"Node Selector"}
|
||||
error={nodeSelectorError}
|
||||
setError={setNodeSelectorError}
|
||||
/>
|
||||
</Grid>
|
||||
|
||||
<Grid item xs={12} textAlign={"right"}>
|
||||
<Button
|
||||
type="submit"
|
||||
variant="contained"
|
||||
color="primary"
|
||||
disabled={loading || !checkValid()}
|
||||
onClick={() => submitLoggingInfo()}
|
||||
>
|
||||
Save
|
||||
</Button>
|
||||
</Grid>
|
||||
</Fragment>
|
||||
)}
|
||||
</Fragment>
|
||||
);
|
||||
};
|
||||
|
||||
export default withStyles(styles)(TenantAuditLogging);
|
||||
@@ -1,5 +1,6 @@
|
||||
|
||||
// This file is part of MinIO Console Server
|
||||
// Copyright (c) 2022 MinIO, Inc.
|
||||
// Copyright (c) 2021 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
|
||||
@@ -14,220 +15,129 @@
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//import { ISecurityContext} from "../types";
|
||||
import React, { Fragment, useEffect, useState } from "react";
|
||||
import { Theme } from "@mui/material/styles";
|
||||
import { useParams } from "react-router-dom";
|
||||
import createStyles from "@mui/styles/createStyles";
|
||||
import withStyles from "@mui/styles/withStyles";
|
||||
import {
|
||||
containerForHeader,
|
||||
createTenantCommon,
|
||||
formFieldStyles,
|
||||
modalBasic,
|
||||
spacingUtils,
|
||||
tenantDetailsStyles,
|
||||
wizardCommon,
|
||||
} from "../../Common/FormComponents/common/styleLibrary";
|
||||
import React, { Fragment, useEffect, useState } from "react";
|
||||
import { containerForHeader } from "../../Common/FormComponents/common/styleLibrary";
|
||||
import Grid from "@mui/material/Grid";
|
||||
import Tabs from "@mui/material/Tabs";
|
||||
import Tab from "@mui/material/Tab";
|
||||
import { DialogContentText } from "@mui/material";
|
||||
import ConfirmDialog from "../../Common/ModalWrapper/ConfirmDialog";
|
||||
import api from "../../../../common/api";
|
||||
import { useSelector } from "react-redux";
|
||||
import { AppState, useAppDispatch } from "../../../../store";
|
||||
import api from "../../../../common/api";
|
||||
import { ErrorResponseHandler } from "../../../../common/types";
|
||||
import { useParams } from "react-router-dom";
|
||||
import { setErrorSnackMessage} from "../../../../systemSlice";
|
||||
import FormSwitchWrapper from "../../Common/FormComponents/FormSwitchWrapper/FormSwitchWrapper";
|
||||
import Grid from "@mui/material/Grid";
|
||||
import InputBoxWrapper from "../../Common/FormComponents/InputBoxWrapper/InputBoxWrapper";
|
||||
import { Button, DialogContentText } from "@mui/material";
|
||||
import ConfirmDialog from "../../Common/ModalWrapper/ConfirmDialog";
|
||||
import {
|
||||
setErrorSnackMessage,
|
||||
setSnackBarMessage,
|
||||
} from "../../../../systemSlice";
|
||||
import { IKeyValue } from "../ListTenants/types";
|
||||
import KeyPairEdit from "./KeyPairEdit";
|
||||
import InputUnitMenu from "../../Common/FormComponents/InputUnitMenu/InputUnitMenu";
|
||||
import { ITenantLogsStruct } from "../ListTenants/types";
|
||||
import { IKeyValue } from "../ListTenants/types";
|
||||
|
||||
import LoggingDetails from "./LoggingDetails";
|
||||
import LoggingDBDetails from "./LoggingDBDetails";
|
||||
import {
|
||||
setAuditLoggingEnabled,
|
||||
setAuditLoggingEnabled,
|
||||
setDBImage,
|
||||
setDBInitImage,
|
||||
setDBServiceAccountName,
|
||||
setDBCPURequest,
|
||||
setDBMemRequest,
|
||||
setDBRunAsUser,
|
||||
setDBFSGroup,
|
||||
setDBRunAsGroup,
|
||||
setDBRunAsNonRoot,
|
||||
setImage,
|
||||
setDBImage,
|
||||
setDBInitImage,
|
||||
setDiskCapacityGB,
|
||||
setServiceAccountName,
|
||||
setDBServiceAccountName,
|
||||
setCPURequest,
|
||||
setMemRequest,
|
||||
setDBCPURequest,
|
||||
setDBMemRequest,
|
||||
setRunAsUser,
|
||||
setFSGroup,
|
||||
setRunAsGroup,
|
||||
setRunAsNonRoot,
|
||||
resetAuditLogForm,
|
||||
} from "../TenantDetails/tenantAuditLogSlice";
|
||||
|
||||
import { clearValidationError } from "../utils";
|
||||
|
||||
interface ITenantAuditLogs {
|
||||
interface ILoggingScreenProps {
|
||||
classes: any;
|
||||
}
|
||||
|
||||
const styles = (theme: Theme) =>
|
||||
createStyles({
|
||||
...tenantDetailsStyles,
|
||||
...spacingUtils,
|
||||
bold: { fontWeight: "bold" },
|
||||
italic: { fontStyle: "italic" },
|
||||
fileItem: {
|
||||
marginRight: 10,
|
||||
display: "flex",
|
||||
"& div label": {
|
||||
minWidth: 50,
|
||||
},
|
||||
|
||||
"@media (max-width: 900px)": {
|
||||
flexFlow: "column",
|
||||
},
|
||||
breadcrumLink: {
|
||||
textDecoration: "none",
|
||||
color: "black",
|
||||
},
|
||||
...containerForHeader(theme.spacing(4)),
|
||||
...createTenantCommon,
|
||||
...formFieldStyles,
|
||||
...modalBasic,
|
||||
...wizardCommon,
|
||||
});
|
||||
|
||||
const TenantAuditLogging = ({ classes }: ITenantAuditLogs) => {
|
||||
const LoggingScreen = ({ classes }: ILoggingScreenProps) => {
|
||||
const { tenantNamespace, tenantName } = useParams();
|
||||
const [curTab, setCurTab] = useState<number>(0);
|
||||
const [loading, setLoading] = useState<boolean>(true);
|
||||
const [toggleConfirmOpen, setToggleConfirmOpen] = useState<boolean>(false);
|
||||
const [refreshLoggingInfo, setRefreshLoggingInfo] = useState<boolean>(true);
|
||||
const [dbLabels, setDBLabels] = useState<IKeyValue[]>([{ key: "", value: "" }]);
|
||||
const [dbAnnotations, setDBAnnotations] = useState<IKeyValue[]>([{ key: "", value: "" }]);
|
||||
const [dbNodeSelector, setDBNodeSelector] = useState<IKeyValue[]>([{ key: "", value: "" }]);
|
||||
const [labels, setLabels] = useState<IKeyValue[]>([{ key: "", value: "" }]);
|
||||
const [annotations, setAnnotations] = useState<IKeyValue[]>([{ key: "", value: "" }]);
|
||||
const [nodeSelector, setNodeSelector] = useState<IKeyValue[]>([{ key: "", value: "" }]);
|
||||
const dispatch = useAppDispatch();
|
||||
const { tenantName, tenantNamespace } = useParams();
|
||||
const auditLoggingEnabled = useSelector(
|
||||
(state: AppState) => state.editTenantLogging.auditLoggingEnabled
|
||||
);
|
||||
const image = useSelector(
|
||||
(state: AppState) => state.editTenantLogging.image
|
||||
);
|
||||
const dbImage = useSelector(
|
||||
(state: AppState) => state.editTenantLogging.dbImage
|
||||
);
|
||||
const dbInitImage = useSelector(
|
||||
(state: AppState) => state.editTenantLogging.dbInitImage
|
||||
);
|
||||
const diskCapacityGB = useSelector(
|
||||
(state: AppState) => state.editTenantLogging.diskCapacityGB
|
||||
);
|
||||
const cpuRequest = useSelector(
|
||||
(state: AppState) => state.editTenantLogging.cpuRequest
|
||||
);
|
||||
const memRequest = useSelector(
|
||||
(state: AppState) => state.editTenantLogging.memRequest
|
||||
);
|
||||
|
||||
const dbCpuRequest = useSelector(
|
||||
(state: AppState) => state.editTenantLogging.dbCPURequest
|
||||
);
|
||||
const dbMemRequest = useSelector(
|
||||
(state: AppState) => state.editTenantLogging.dbMemRequest
|
||||
);
|
||||
const serviceAccountName = useSelector(
|
||||
(state: AppState) => state.editTenantLogging.serviceAccountName
|
||||
);
|
||||
const dbServiceAccountName = useSelector(
|
||||
(state: AppState) => state.editTenantLogging.dbServiceAccountName
|
||||
);
|
||||
const [validationErrors, setValidationErrors] = useState<any>({});
|
||||
const [toggleConfirmOpen, setToggleConfirmOpen] = useState<boolean>(false);
|
||||
|
||||
const [labels, setLabels] = useState<IKeyValue[]>([{ key: "", value: "" }]);
|
||||
const [annotations, setAnnotations] = useState<IKeyValue[]>([
|
||||
{ key: "", value: "" },
|
||||
]);
|
||||
const [nodeSelector, setNodeSelector] = useState<IKeyValue[]>([
|
||||
{ key: "", value: "" },
|
||||
]);
|
||||
const [dbLabels, setDBLabels] = useState<IKeyValue[]>([{ key: "", value: "" }]);
|
||||
const [dbAnnotations, setDBAnnotations] = useState<IKeyValue[]>([
|
||||
{ key: "", value: "" },
|
||||
]);
|
||||
const [dbNodeSelector, setDBNodeSelector] = useState<IKeyValue[]>([
|
||||
{ key: "", value: "" },
|
||||
]);
|
||||
|
||||
const [refreshLoggingInfo, setRefreshLoggingInfo] =
|
||||
useState<boolean>(true);
|
||||
const [labelsError, setLabelsError] = useState<any>({});
|
||||
const [annotationsError, setAnnotationsError] = useState<any>({});
|
||||
const [nodeSelectorError, setNodeSelectorError] = useState<any>({});
|
||||
|
||||
const [dbLabelsError, setDBLabelsError] = useState<any>({});
|
||||
const [dbAnnotationsError, setDBAnnotationsError] = useState<any>({});
|
||||
const [dbNodeSelectorError, setDBNodeSelectorError] = useState<any>({});
|
||||
|
||||
const cleanValidation = (fieldName: string) => {
|
||||
setValidationErrors(clearValidationError(validationErrors, fieldName));
|
||||
};
|
||||
function a11yProps(index: any) {
|
||||
return {
|
||||
id: `simple-tab-${index}`,
|
||||
"aria-controls": `simple-tabpanel-${index}`,
|
||||
};
|
||||
}
|
||||
|
||||
const setLoggingInfo = (res: ITenantLogsStruct) => {
|
||||
dispatch(setAuditLoggingEnabled(!res.disabled))
|
||||
dispatch(setImage(res.image));
|
||||
dispatch(setServiceAccountName(res.serviceAccountName));
|
||||
dispatch(setDBServiceAccountName(res.dbServiceAccountName));
|
||||
dispatch(setDBImage(res.dbImage));
|
||||
dispatch(setDBInitImage(res.dbInitImage));
|
||||
dispatch(setCPURequest(res.logCPURequest));
|
||||
dispatch(setDBCPURequest(res.logDBCPURequest));
|
||||
if (res.logMemRequest) {
|
||||
dispatch(
|
||||
setMemRequest(
|
||||
Math.floor(
|
||||
parseInt(res.logMemRequest, 10) / 1000000000
|
||||
).toString()
|
||||
)
|
||||
);
|
||||
} else {
|
||||
dispatch(setMemRequest("0"));
|
||||
}
|
||||
if (res !== null) {
|
||||
dispatch(setAuditLoggingEnabled(res !== null && !res.disabled));
|
||||
res.dbServiceAccountName != null && dispatch(setDBServiceAccountName(res.dbServiceAccountName));
|
||||
res.dbImage != null && dispatch(setDBImage(res.dbImage));
|
||||
res.dbInitImage != null && dispatch(setDBInitImage(res.dbInitImage));
|
||||
res.logDBCPURequest != null && dispatch(setDBCPURequest(res.logDBCPURequest));
|
||||
if (res.logDBMemRequest) {
|
||||
dispatch(
|
||||
setDBMemRequest(
|
||||
Math.floor(
|
||||
parseInt(res.logDBMemRequest, 10) / 1000000000
|
||||
).toString()
|
||||
)
|
||||
);
|
||||
dispatch(setDBMemRequest(Math.floor(parseInt(res.logDBMemRequest, 10)).toString()));
|
||||
} else {
|
||||
dispatch(setDBMemRequest("0"));
|
||||
}
|
||||
dispatch(setDiskCapacityGB(res.diskCapacityGB));
|
||||
res.labels.length > 0 ? setLabels(res.labels) : setLabels([{ key: "test", value: "test" }]);
|
||||
res.annotations.length > 0 ? setAnnotations(res.annotations) : setAnnotations([{ key: "", value: "" }]);
|
||||
res.nodeSelector.length > 0 ? setNodeSelector(res.nodeSelector) : setNodeSelector([{ key: "", value: "" }]);
|
||||
res.dbLabels.length > 0 ? setDBLabels(res.dbLabels) : setDBLabels([{ key: "", value: "" }]);
|
||||
res.dbAnnotations.length > 0 ? setDBAnnotations(res.dbAnnotations) : setDBAnnotations([{ key: "", value: "" }]);
|
||||
res.dbNodeSelector.length > 0 ? setDBNodeSelector(res.dbNodeSelector) : setDBNodeSelector([{ key: "", value: "" }]);
|
||||
};
|
||||
|
||||
const trim = (x: IKeyValue[]): IKeyValue[] => {
|
||||
let retval: IKeyValue[] = [];
|
||||
for (let i = 0; i < x.length; i++) {
|
||||
if (x[i].key !== "") {
|
||||
retval.push(x[i]);
|
||||
}
|
||||
}
|
||||
return retval;
|
||||
};
|
||||
|
||||
const checkValid = (): boolean => {
|
||||
if (
|
||||
Object.keys(validationErrors).length !== 0 ||
|
||||
Object.keys(labelsError).length !== 0 ||
|
||||
Object.keys(annotationsError).length !== 0 ||
|
||||
Object.keys(nodeSelectorError).length !== 0 ||
|
||||
Object.keys(dbNodeSelectorError).length !== 0 ||
|
||||
Object.keys(dbAnnotationsError).length !== 0 ||
|
||||
Object.keys(dbLabelsError).length !== 0
|
||||
) {
|
||||
let err: ErrorResponseHandler = {
|
||||
errorMessage: "Invalid entry",
|
||||
detailedError: "",
|
||||
};
|
||||
dispatch(setErrorSnackMessage(err));
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
if (res.dbSecurityContext) {
|
||||
dispatch(setDBRunAsGroup(res.dbSecurityContext.runAsGroup));
|
||||
dispatch(setDBRunAsUser(res.dbSecurityContext.runAsUser));
|
||||
dispatch(setDBFSGroup(res.dbSecurityContext.fsGroup));
|
||||
dispatch(setDBRunAsNonRoot(res.dbSecurityContext.runAsNonRoot));
|
||||
}
|
||||
res.image != null && dispatch(setImage(res.image));
|
||||
res.serviceAccountName != null && dispatch(setServiceAccountName(res.serviceAccountName));
|
||||
res.logCPURequest != null && dispatch(setCPURequest(res.logCPURequest));
|
||||
if (res.logMemRequest) {
|
||||
dispatch(setMemRequest(Math.floor(parseInt(res.logMemRequest, 10)).toString()));
|
||||
} else {
|
||||
dispatch(setMemRequest("0"));
|
||||
}
|
||||
if (res.securityContext) {
|
||||
dispatch(setRunAsGroup(res.securityContext.runAsGroup));
|
||||
dispatch(setRunAsUser(res.securityContext.runAsUser));
|
||||
dispatch(setFSGroup(res.securityContext.fsGroup));
|
||||
dispatch(setRunAsNonRoot(res.securityContext.runAsNonRoot));
|
||||
}
|
||||
|
||||
res.diskCapacityGB != null && dispatch(setDiskCapacityGB(res.diskCapacityGB));
|
||||
res.labels != null ? setLabels(res.labels) : setLabels([{ key: "", value: "" }]);
|
||||
res.annotations != null ? setAnnotations(res.annotations) : setAnnotations([{ key: "", value: "" }]);
|
||||
res.nodeSelector != null ? setNodeSelector(res.nodeSelector) : setNodeSelector([{ key: "", value: "" }]);
|
||||
res.dbLabels != null ? setDBLabels(res.dbLabels) : setDBLabels([{ key: "", value: "" }]);
|
||||
res.dbAnnotations != null ? setDBAnnotations(res.dbAnnotations) : setDBAnnotations([{ key: "", value: "" }]);
|
||||
res.dbNodeSelector != null ? setDBNodeSelector(res.dbNodeSelector) : setDBNodeSelector([{ key: "", value: "" }]);
|
||||
setRefreshLoggingInfo(false);
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
@@ -238,9 +148,11 @@ const TenantAuditLogging = ({ classes }: ITenantAuditLogs) => {
|
||||
`/api/v1/namespaces/${tenantNamespace}/tenants/${tenantName}/log`
|
||||
)
|
||||
.then((res: ITenantLogsStruct) => {
|
||||
if (res !== null) {
|
||||
dispatch(setAuditLoggingEnabled(res.auditLoggingEnabled));
|
||||
setLoggingInfo(res);
|
||||
setRefreshLoggingInfo(false);
|
||||
}
|
||||
})
|
||||
.catch((err: ErrorResponseHandler) => {
|
||||
dispatch(setErrorSnackMessage(err));
|
||||
@@ -250,42 +162,14 @@ const TenantAuditLogging = ({ classes }: ITenantAuditLogs) => {
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [refreshLoggingInfo]);
|
||||
|
||||
const submitLoggingInfo = () => {
|
||||
if (checkValid()) {
|
||||
api
|
||||
.invoke(
|
||||
"PUT",
|
||||
`/api/v1/namespaces/${tenantNamespace}/tenants/${tenantName}/log`,
|
||||
{
|
||||
labels: trim(labels),
|
||||
annotations: trim(annotations),
|
||||
nodeSelector: trim(nodeSelector),
|
||||
image: image,
|
||||
diskCapacityGB: diskCapacityGB.toString(),
|
||||
serviceAccountName: serviceAccountName,
|
||||
dbLabels: trim(dbLabels),
|
||||
dbAnnotations: trim(dbAnnotations),
|
||||
dbNodeSelector: trim(dbNodeSelector),
|
||||
dbImage: dbImage,
|
||||
dbInitImage: dbInitImage,
|
||||
dbServiceAccountName: dbServiceAccountName,
|
||||
logCPURequest: cpuRequest,
|
||||
logMemRequest: memRequest + "Gi",
|
||||
logDBCPURequest: dbCpuRequest,
|
||||
logDBMemRequest: dbMemRequest + "Gi",
|
||||
}
|
||||
)
|
||||
.then(() => {
|
||||
setRefreshLoggingInfo(true);
|
||||
dispatch(setSnackBarMessage(`Audit Log configuration updated.`));
|
||||
})
|
||||
.catch((err: ErrorResponseHandler) => {
|
||||
setErrorSnackMessage(err);
|
||||
});
|
||||
useEffect(() => {
|
||||
if (loading) {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
}, [loading, refreshLoggingInfo]);
|
||||
|
||||
const toggleLogging = () => {
|
||||
dispatch(resetAuditLogForm());
|
||||
if(!auditLoggingEnabled) {
|
||||
api
|
||||
.invoke(
|
||||
@@ -295,6 +179,7 @@ const TenantAuditLogging = ({ classes }: ITenantAuditLogs) => {
|
||||
.then(() => {
|
||||
setRefreshLoggingInfo(true);
|
||||
setToggleConfirmOpen(false);
|
||||
setAuditLoggingEnabled(true);
|
||||
})
|
||||
.catch((err: ErrorResponseHandler) => {
|
||||
dispatch(
|
||||
@@ -311,8 +196,10 @@ const TenantAuditLogging = ({ classes }: ITenantAuditLogs) => {
|
||||
`/api/v1/namespaces/${tenantNamespace}/tenants/${tenantName}/disable-logging`
|
||||
)
|
||||
.then(() => {
|
||||
setAuditLoggingEnabled(false);
|
||||
setRefreshLoggingInfo(true);
|
||||
setToggleConfirmOpen(false);
|
||||
dispatch(resetAuditLogForm());
|
||||
})
|
||||
.catch((err: ErrorResponseHandler) => {
|
||||
dispatch(
|
||||
@@ -324,9 +211,13 @@ const TenantAuditLogging = ({ classes }: ITenantAuditLogs) => {
|
||||
});
|
||||
};
|
||||
};
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
{toggleConfirmOpen && (
|
||||
<Fragment>
|
||||
|
||||
<Grid item xs>
|
||||
{toggleConfirmOpen && (
|
||||
|
||||
<ConfirmDialog
|
||||
isOpen={toggleConfirmOpen}
|
||||
title={
|
||||
@@ -347,11 +238,12 @@ const TenantAuditLogging = ({ classes }: ITenantAuditLogs) => {
|
||||
}
|
||||
/>
|
||||
)}
|
||||
<Grid container spacing={1}>
|
||||
<Grid item xs>
|
||||
</Grid>
|
||||
<Grid container >
|
||||
<Grid item xs>
|
||||
<h1 className={classes.sectionTitle}>Audit Logs</h1>
|
||||
</Grid>
|
||||
<Grid item xs={7} justifyContent={"end"} textAlign={"right"}>
|
||||
<Grid >
|
||||
<FormSwitchWrapper
|
||||
label={""}
|
||||
indicatorLabels={["Enabled", "Disabled"]}
|
||||
@@ -365,291 +257,50 @@ const TenantAuditLogging = ({ classes }: ITenantAuditLogs) => {
|
||||
description=""
|
||||
/>
|
||||
</Grid>
|
||||
<Grid xs={12}>
|
||||
<hr className={classes.hrClass} />
|
||||
|
||||
</Grid>
|
||||
<Grid container>
|
||||
{auditLoggingEnabled && (
|
||||
<Fragment>
|
||||
<Grid item xs={9}>
|
||||
<Tabs
|
||||
value={curTab}
|
||||
onChange={(e: React.ChangeEvent<{}>, newValue: number) => {
|
||||
setCurTab(newValue);
|
||||
}}
|
||||
indicatorColor="primary"
|
||||
textColor="primary"
|
||||
aria-label="cluster-tabs"
|
||||
variant="scrollable"
|
||||
scrollButtons="auto"
|
||||
>
|
||||
<Tab label="Configuration" {...a11yProps(0)} />
|
||||
<Tab label="DB Configuration" {...a11yProps(1)} />
|
||||
</Tabs>
|
||||
</Grid>
|
||||
</Grid>
|
||||
|
||||
{auditLoggingEnabled && (
|
||||
<Fragment>
|
||||
<Grid item xs={12} paddingBottom={2}>
|
||||
<InputBoxWrapper
|
||||
id={`image`}
|
||||
label={"Image"}
|
||||
placeholder={"minio/operator:v4.4.22"}
|
||||
name={`image`}
|
||||
value={image}
|
||||
onChange={(event: React.ChangeEvent<HTMLInputElement>) => {
|
||||
if (event.target.validity.valid) {
|
||||
dispatch(setImage(event.target.value));
|
||||
}
|
||||
cleanValidation(`image`);
|
||||
}}
|
||||
key={`image`}
|
||||
pattern={"^[a-zA-Z0-9-./:]{1,253}$"}
|
||||
error={validationErrors[`image`] || ""}
|
||||
<Grid item xs={12}>
|
||||
<hr className={classes.hrClass} />
|
||||
</Grid>
|
||||
{curTab === 0 && (
|
||||
<LoggingDetails
|
||||
classes={classes}
|
||||
labels={labels}
|
||||
annotations={annotations}
|
||||
nodeSelector={nodeSelector}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12} paddingBottom={2}>
|
||||
<InputBoxWrapper
|
||||
id={`dbImage`}
|
||||
label={"DB Postgres Image"}
|
||||
placeholder={"library/postgres:13"}
|
||||
name={`dbImage`}
|
||||
value={dbImage}
|
||||
onChange={(event: React.ChangeEvent<HTMLInputElement>) => {
|
||||
if (event.target.validity.valid) {
|
||||
dispatch(setDBImage(event.target.value));
|
||||
}
|
||||
cleanValidation(`dbImage`);
|
||||
}}
|
||||
key={`dbImage`}
|
||||
pattern={"^[a-zA-Z0-9-./:]{1,253}$"}
|
||||
error={validationErrors[`dbImage`] || ""}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12} paddingBottom={2}>
|
||||
<InputBoxWrapper
|
||||
id={`dbInitImage`}
|
||||
label={"DB Init Image"}
|
||||
placeholder={"library/busybox:1.33.1"}
|
||||
name={`dbInitImage`}
|
||||
value={dbInitImage}
|
||||
onChange={(event: React.ChangeEvent<HTMLInputElement>) => {
|
||||
if (event.target.validity.valid) {
|
||||
dispatch(setDBInitImage(event.target.value));
|
||||
}
|
||||
cleanValidation(`dbInitImage`);
|
||||
}}
|
||||
key={`dbInitImage`}
|
||||
pattern={"^[a-zA-Z0-9-./:]{1,253}$"}
|
||||
error={validationErrors[`dbInitImage`] || ""}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12} paddingBottom={2}>
|
||||
<InputBoxWrapper
|
||||
id={`diskCapacityGB`}
|
||||
label={"Disk Capacity"}
|
||||
placeholder={"Disk Capacity"}
|
||||
name={`diskCapacityGB`}
|
||||
value={!isNaN(diskCapacityGB) ? diskCapacityGB.toString() : "0"}
|
||||
onChange={(event: React.ChangeEvent<HTMLInputElement>) => {
|
||||
if (event.target.validity.valid) {
|
||||
dispatch(setDiskCapacityGB(parseInt(event.target.value)));
|
||||
}
|
||||
cleanValidation(`diskCapacityGB`);
|
||||
}}
|
||||
key={`diskCapacityGB`}
|
||||
pattern={"[0-9]*"}
|
||||
error={validationErrors[`diskCapacityGB`] || ""}
|
||||
overlayObject={
|
||||
<InputUnitMenu
|
||||
id={"size-unit"}
|
||||
onUnitChange={() => {}}
|
||||
unitSelected={"Gi"}
|
||||
unitsList={[{ label: "Gi", value: "Gi" }]}
|
||||
disabled={true}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12} paddingBottom={2}>
|
||||
<InputBoxWrapper
|
||||
id={`cpuRequest`}
|
||||
label={"CPU Request"}
|
||||
placeholder={"CPU Request"}
|
||||
name={`cpuRequest`}
|
||||
value={cpuRequest}
|
||||
pattern={"[0-9]*"}
|
||||
onChange={(event: React.ChangeEvent<HTMLInputElement>) => {
|
||||
if (event.target.validity.valid) {
|
||||
dispatch(setCPURequest(event.target.value));
|
||||
}
|
||||
cleanValidation(`cpuRequest`);
|
||||
}}
|
||||
key={`cpuRequest`}
|
||||
error={validationErrors[`cpuRequest`] || ""}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12} paddingBottom={2}>
|
||||
<InputBoxWrapper
|
||||
id={`dbCPURequest`}
|
||||
label={"DB CPU Request"}
|
||||
placeholder={"DB CPU Request"}
|
||||
name={`dbCPURequest`}
|
||||
value={dbCpuRequest}
|
||||
pattern={"[0-9]*"}
|
||||
onChange={(event: React.ChangeEvent<HTMLInputElement>) => {
|
||||
if (event.target.validity.valid) {
|
||||
dispatch(setDBCPURequest(event.target.value));
|
||||
}
|
||||
cleanValidation(`dbCPURequest`);
|
||||
}}
|
||||
key={`dbCPURequest`}
|
||||
error={validationErrors[`dbCPURequest`] || ""}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12} paddingBottom={2}>
|
||||
<InputBoxWrapper
|
||||
id={`memRequest`}
|
||||
label={"Memory Request"}
|
||||
placeholder={"Memory request"}
|
||||
name={`memRequest`}
|
||||
value={memRequest}
|
||||
onChange={(event: React.ChangeEvent<HTMLInputElement>) => {
|
||||
if (event.target.validity.valid) {
|
||||
dispatch(setMemRequest(event.target.value));
|
||||
}
|
||||
cleanValidation(`memRequest`);
|
||||
}}
|
||||
pattern={"[0-9]*"}
|
||||
key={`memRequest`}
|
||||
error={validationErrors[`memRequest`] || ""}
|
||||
overlayObject={
|
||||
<InputUnitMenu
|
||||
id={"size-unit"}
|
||||
onUnitChange={() => {}}
|
||||
unitSelected={"Gi"}
|
||||
unitsList={[{ label: "Gi", value: "Gi" }]}
|
||||
disabled={true}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12} paddingBottom={2}>
|
||||
<InputBoxWrapper
|
||||
id={`dbMemRequest`}
|
||||
label={"DB Memory Request"}
|
||||
placeholder={"DB Memory request"}
|
||||
name={`dbMemRequest`}
|
||||
value={dbMemRequest}
|
||||
onChange={(event: React.ChangeEvent<HTMLInputElement>) => {
|
||||
if (event.target.validity.valid) {
|
||||
dispatch(setDBMemRequest(event.target.value));
|
||||
}
|
||||
cleanValidation(`dbMemRequest`);
|
||||
}}
|
||||
pattern={"[0-9]*"}
|
||||
key={`dbMemRequest`}
|
||||
error={validationErrors[`dbMemRequest`] || ""}
|
||||
overlayObject={
|
||||
<InputUnitMenu
|
||||
id={"size-unit"}
|
||||
onUnitChange={() => {}}
|
||||
unitSelected={"Gi"}
|
||||
unitsList={[{ label: "Gi", value: "Gi" }]}
|
||||
disabled={true}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12} paddingBottom={2}>
|
||||
<InputBoxWrapper
|
||||
id={`serviceAccountName`}
|
||||
label={"Service Account"}
|
||||
placeholder={"Service Account Name"}
|
||||
name={`serviceAccountName`}
|
||||
value={serviceAccountName}
|
||||
onChange={(event: React.ChangeEvent<HTMLInputElement>) => {
|
||||
if (event.target.validity.valid) {
|
||||
dispatch(setServiceAccountName(event.target.value));
|
||||
}
|
||||
cleanValidation(`serviceAccountName`);
|
||||
}}
|
||||
key={`serviceAccountName`}
|
||||
pattern={"^[a-zA-Z0-9-.]{1,253}$"}
|
||||
error={validationErrors[`serviceAccountName`] || ""}
|
||||
/>
|
||||
</Grid>
|
||||
{labels !== null && (
|
||||
<Grid item xs={12} className={classes.formFieldRow}>
|
||||
<span className={classes.inputLabel}>Labels</span>
|
||||
<KeyPairEdit
|
||||
newValues={labels}
|
||||
setNewValues={setLabels}
|
||||
paramName={"Labels"}
|
||||
error={labelsError}
|
||||
setError={setLabelsError}
|
||||
/>
|
||||
</Grid>
|
||||
)}
|
||||
|
||||
{annotations !== null && (
|
||||
<Grid item xs={12} className={classes.formFieldRow}>
|
||||
<span className={classes.inputLabel}>Annotations</span>
|
||||
<KeyPairEdit
|
||||
newValues={annotations}
|
||||
setNewValues={setAnnotations}
|
||||
paramName={"Annotations"}
|
||||
error={annotationsError}
|
||||
setError={setAnnotationsError}
|
||||
/>
|
||||
</Grid>
|
||||
)}
|
||||
{nodeSelector !== null && (
|
||||
<Grid item xs={12} className={classes.formFieldRow}>
|
||||
<span className={classes.inputLabel}>Node Selector</span>
|
||||
<KeyPairEdit
|
||||
newValues={nodeSelector}
|
||||
setNewValues={setNodeSelector}
|
||||
paramName={"Node Selector"}
|
||||
error={nodeSelectorError}
|
||||
setError={setNodeSelectorError}
|
||||
/>
|
||||
</Grid>
|
||||
)}
|
||||
{dbLabels !== null && (
|
||||
<Grid item xs={12} className={classes.formFieldRow}>
|
||||
<span className={classes.inputLabel}>DB Labels</span>
|
||||
<KeyPairEdit
|
||||
newValues={dbLabels}
|
||||
setNewValues={setDBLabels}
|
||||
paramName={"dbLabels"}
|
||||
error={dbLabelsError}
|
||||
setError={setDBLabelsError}
|
||||
/>
|
||||
</Grid>
|
||||
)}
|
||||
|
||||
{dbAnnotations !== null && (
|
||||
<Grid item xs={12} className={classes.formFieldRow}>
|
||||
<span className={classes.inputLabel}>DB Annotations</span>
|
||||
<KeyPairEdit
|
||||
newValues={dbAnnotations}
|
||||
setNewValues={setDBAnnotations}
|
||||
paramName={"dbAnnotations"}
|
||||
error={dbAnnotationsError}
|
||||
setError={setDBAnnotationsError}
|
||||
/>
|
||||
</Grid>
|
||||
)}
|
||||
{dbNodeSelector !== null && (
|
||||
<Grid item xs={12} className={classes.formFieldRow}>
|
||||
<span className={classes.inputLabel}>DB Node Selector</span>
|
||||
<KeyPairEdit
|
||||
newValues={dbNodeSelector}
|
||||
setNewValues={setDBNodeSelector}
|
||||
paramName={"DB Node Selector"}
|
||||
error={dbNodeSelectorError}
|
||||
setError={setDBNodeSelectorError}
|
||||
/>
|
||||
</Grid>
|
||||
)}
|
||||
<Grid item xs={12} textAlign={"right"}>
|
||||
<Button
|
||||
type="submit"
|
||||
variant="contained"
|
||||
color="primary"
|
||||
disabled={!checkValid()}
|
||||
onClick={() => submitLoggingInfo()}
|
||||
>
|
||||
Save
|
||||
</Button>
|
||||
</Grid>
|
||||
)}
|
||||
{curTab === 1 && (
|
||||
<LoggingDBDetails classes={classes}
|
||||
labels={dbLabels}
|
||||
annotations={dbAnnotations}
|
||||
nodeSelector={dbNodeSelector}
|
||||
/>
|
||||
)}
|
||||
</Fragment>
|
||||
)}
|
||||
)}
|
||||
</Grid>
|
||||
</Fragment>
|
||||
);
|
||||
};
|
||||
|
||||
export default withStyles(styles)(TenantAuditLogging);
|
||||
export default withStyles(styles)(LoggingScreen);
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
import { createSlice, PayloadAction } from "@reduxjs/toolkit";
|
||||
import { IKeyValue } from "../ListTenants/types";
|
||||
import { ISecurityContext } from "../types";
|
||||
|
||||
export interface IEditTenantAuditLogging {
|
||||
auditLoggingEnabled: boolean;
|
||||
@@ -34,6 +35,9 @@ export interface IEditTenantAuditLogging {
|
||||
memRequest: string;
|
||||
dbCPURequest: string;
|
||||
dbMemRequest: string;
|
||||
securityContext: ISecurityContext;
|
||||
dbSecurityContext: ISecurityContext;
|
||||
refreshLoggingInfo: boolean;
|
||||
}
|
||||
|
||||
const initialState: IEditTenantAuditLogging = {
|
||||
@@ -54,6 +58,19 @@ const initialState: IEditTenantAuditLogging = {
|
||||
dbServiceAccountName: "",
|
||||
cpuRequest: "",
|
||||
memRequest: "",
|
||||
securityContext: {
|
||||
runAsUser: "1000",
|
||||
runAsGroup: "1000",
|
||||
fsGroup: "1000",
|
||||
runAsNonRoot: false,
|
||||
},
|
||||
dbSecurityContext: {
|
||||
runAsUser: "1000",
|
||||
runAsGroup: "1000",
|
||||
fsGroup: "1000",
|
||||
runAsNonRoot: false,
|
||||
},
|
||||
refreshLoggingInfo: true
|
||||
};
|
||||
|
||||
export const editTenantAuditLoggingSlice = createSlice({
|
||||
@@ -111,6 +128,34 @@ export const editTenantAuditLoggingSlice = createSlice({
|
||||
setDBMemRequest: (state, action: PayloadAction<string>) => {
|
||||
state.dbMemRequest = action.payload;
|
||||
},
|
||||
setRunAsUser: (state, action: PayloadAction<string>) => {
|
||||
state.securityContext.runAsUser = action.payload;
|
||||
},
|
||||
setRunAsGroup: (state, action: PayloadAction<string>) => {
|
||||
state.securityContext.runAsGroup = action.payload;
|
||||
},
|
||||
setFSGroup: (state, action: PayloadAction<string>) => {
|
||||
state.securityContext.fsGroup = action.payload;
|
||||
},
|
||||
setRunAsNonRoot: (state, action: PayloadAction<boolean>) => {
|
||||
state.securityContext.runAsNonRoot = action.payload;
|
||||
},
|
||||
setDBRunAsUser: (state, action: PayloadAction<string>) => {
|
||||
state.dbSecurityContext.runAsUser = action.payload;
|
||||
},
|
||||
setDBRunAsGroup: (state, action: PayloadAction<string>) => {
|
||||
state.dbSecurityContext.runAsGroup = action.payload;
|
||||
},
|
||||
setDBFSGroup: (state, action: PayloadAction<string>) => {
|
||||
state.dbSecurityContext.fsGroup = action.payload;
|
||||
},
|
||||
setDBRunAsNonRoot: (state, action: PayloadAction<boolean>) => {
|
||||
state.dbSecurityContext.runAsNonRoot = action.payload;
|
||||
},
|
||||
setRefreshLoggingInfo: (state, action: PayloadAction<boolean>) => {
|
||||
state.refreshLoggingInfo = action.payload;
|
||||
},
|
||||
resetAuditLogForm: () => initialState,
|
||||
},
|
||||
});
|
||||
|
||||
@@ -132,6 +177,16 @@ export const {
|
||||
setMemRequest,
|
||||
setDBCPURequest,
|
||||
setDBMemRequest,
|
||||
setRunAsUser,
|
||||
setFSGroup,
|
||||
setRunAsGroup,
|
||||
setRunAsNonRoot,
|
||||
setDBRunAsUser,
|
||||
setDBFSGroup,
|
||||
setDBRunAsGroup,
|
||||
setDBRunAsNonRoot,
|
||||
setRefreshLoggingInfo,
|
||||
resetAuditLogForm,
|
||||
} = editTenantAuditLoggingSlice.actions;
|
||||
|
||||
export default editTenantAuditLoggingSlice.reducer;
|
||||
|
||||
@@ -0,0 +1,110 @@
|
||||
// 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
import React, { Fragment } from "react";
|
||||
import InputBoxWrapper from "../Common/FormComponents/InputBoxWrapper/InputBoxWrapper";
|
||||
import FormSwitchWrapper from "../Common/FormComponents/FormSwitchWrapper/FormSwitchWrapper";
|
||||
import { Grid } from "@mui/material";
|
||||
import { useDispatch } from "react-redux";
|
||||
|
||||
interface IEditSecurityContextProps {
|
||||
classes: any;
|
||||
runAsUser: string;
|
||||
runAsGroup: string;
|
||||
fsGroup: string;
|
||||
runAsNonRoot: boolean;
|
||||
setRunAsUser: any;
|
||||
setRunAsGroup: any;
|
||||
setFSGroup: any;
|
||||
setRunAsNonRoot: any;
|
||||
}
|
||||
const SecurityContextSelector = ({ classes, runAsGroup, runAsUser, fsGroup, runAsNonRoot, setRunAsUser, setRunAsGroup, setFSGroup, setRunAsNonRoot }: IEditSecurityContextProps ) => {
|
||||
const dispatch = useDispatch();
|
||||
return (
|
||||
<Fragment>
|
||||
<fieldset
|
||||
className={`${classes.fieldGroup} ${classes.fieldSpaceTop} `}
|
||||
>
|
||||
<legend className={classes.descriptionText}>
|
||||
Security Context
|
||||
</legend>
|
||||
|
||||
<Grid item xs={12}>
|
||||
<div
|
||||
className={`${classes.multiContainerStackNarrow} `}
|
||||
>
|
||||
<div className={classes.configSectionItem}>
|
||||
<InputBoxWrapper
|
||||
type="number"
|
||||
id="securityContext_runAsUser"
|
||||
name="securityContext_runAsUser"
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
dispatch(setRunAsUser(e.target.value));
|
||||
}}
|
||||
label="Run As User"
|
||||
value={runAsUser}
|
||||
required
|
||||
min="0"
|
||||
/>
|
||||
</div>
|
||||
<div className={classes.configSectionItem}>
|
||||
<InputBoxWrapper
|
||||
type="number"
|
||||
id="securityContext_runAsGroup"
|
||||
name="securityContext_runAsGroup"
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) => { dispatch(setRunAsGroup(e.target.value));
|
||||
}}
|
||||
label="Run As Group"
|
||||
value={runAsGroup}
|
||||
required
|
||||
min="0"
|
||||
/>
|
||||
</div>
|
||||
<div className={classes.configSectionItem}>
|
||||
<InputBoxWrapper
|
||||
type="number"
|
||||
id="securityContext_fsGroup"
|
||||
name="securityContext_fsGroup"
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {dispatch(setFSGroup(e.target.value)); }}
|
||||
label="FsGroup"
|
||||
value={fsGroup}
|
||||
required
|
||||
min="0"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</Grid>
|
||||
<br />
|
||||
<Grid item xs={12}>
|
||||
<div className={classes.multiContainer} >
|
||||
<FormSwitchWrapper
|
||||
value="prometheusSecurityContextRunAsNonRoot"
|
||||
id="prometheus_securityContext_runAsNonRoot"
|
||||
name="prometheus_securityContext_runAsNonRoot"
|
||||
checked={runAsNonRoot}
|
||||
onChange={() => {
|
||||
dispatch(setRunAsNonRoot(!runAsNonRoot));
|
||||
}
|
||||
}
|
||||
label={"Do not run as Root"}
|
||||
/>
|
||||
</div>
|
||||
</Grid>
|
||||
</fieldset>
|
||||
</Fragment>
|
||||
);
|
||||
};
|
||||
export default SecurityContextSelector;
|
||||
@@ -338,3 +338,4 @@ export interface ITenantIdentityProviderResponse {
|
||||
user_dn_search_filter: string;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -34,6 +34,7 @@ import editPoolReducer from "./screens/Console/Tenants/TenantDetails/Pools/EditP
|
||||
import editTenantMonitoringReducer from "./screens/Console/Tenants/TenantDetails/tenantMonitoringSlice";
|
||||
import editTenantAuditLoggingReducer from "./screens/Console/Tenants/TenantDetails/tenantAuditLogSlice";
|
||||
|
||||
|
||||
const rootReducer = combineReducers({
|
||||
system: systemReducer,
|
||||
trace: traceReducer,
|
||||
|
||||
@@ -2908,6 +2908,12 @@ definitions:
|
||||
type: string
|
||||
logDBMemRequest:
|
||||
type: string
|
||||
securityContext:
|
||||
type: object
|
||||
$ref: "#/definitions/securityContext"
|
||||
dbSecurityContext:
|
||||
type: object
|
||||
$ref: "#/definitions/securityContext"
|
||||
|
||||
|
||||
listPVCsResponse:
|
||||
|
||||
Reference in New Issue
Block a user