Compare commits

..

4 Commits

Author SHA1 Message Date
Minio Trusted
7bd898b2c7 update to v0.3.21 2020-09-05 23:50:46 -07:00
Lenin Alevski
dad66db49a Support for adding prometheus annotations on update minio tenant (#269) 2020-09-05 23:48:51 -07:00
Daniel Valdivia
adf3f929a4 Add Tenant Deletion Date to tenant responses (#270) 2020-09-05 23:37:01 -07:00
Lenin Alevski
3b23e877b5 delete unnecessary logs (#268) 2020-09-05 17:39:21 -07:00
11 changed files with 175 additions and 133 deletions

View File

@@ -15,7 +15,7 @@ spec:
serviceAccountName: console-sa serviceAccountName: console-sa
containers: containers:
- name: console - name: console
image: minio/console:v0.3.20 image: minio/console:v0.3.21
imagePullPolicy: "IfNotPresent" imagePullPolicy: "IfNotPresent"
args: args:
- server - server

View File

@@ -15,7 +15,7 @@ spec:
serviceAccountName: console-sa serviceAccountName: console-sa
containers: containers:
- name: console - name: console
image: minio/console:v0.3.20 image: minio/console:v0.3.21
imagePullPolicy: "IfNotPresent" imagePullPolicy: "IfNotPresent"
env: env:
- name: CONSOLE_OPERATOR_MODE - name: CONSOLE_OPERATOR_MODE

View File

@@ -35,12 +35,21 @@ import (
// swagger:model tenant // swagger:model tenant
type Tenant struct { type Tenant struct {
// console image
ConsoleImage string `json:"console_image,omitempty"`
// creation date // creation date
CreationDate string `json:"creation_date,omitempty"` CreationDate string `json:"creation_date,omitempty"`
// current state // current state
CurrentState string `json:"currentState,omitempty"` CurrentState string `json:"currentState,omitempty"`
// deletion date
DeletionDate string `json:"deletion_date,omitempty"`
// enable prometheus
EnablePrometheus bool `json:"enable_prometheus,omitempty"`
// image // image
Image string `json:"image,omitempty"` Image string `json:"image,omitempty"`

View File

@@ -38,6 +38,9 @@ type TenantList struct {
// current state // current state
CurrentState string `json:"currentState,omitempty"` CurrentState string `json:"currentState,omitempty"`
// deletion date
DeletionDate string `json:"deletion_date,omitempty"`
// instance count // instance count
InstanceCount int64 `json:"instance_count,omitempty"` InstanceCount int64 `json:"instance_count,omitempty"`

View File

@@ -1,113 +0,0 @@
// Code generated by go-swagger; DO NOT EDIT.
// This file is part of MinIO Console Server
// Copyright (c) 2020 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/>.
//
package models
// This file was generated by the swagger tool.
// Editing this file might prove futile when you re-run the swagger generate command
import (
"github.com/go-openapi/errors"
"github.com/go-openapi/strfmt"
"github.com/go-openapi/swag"
)
// UpdateCertificatesRequest update certificates request
//
// swagger:model updateCertificatesRequest
type UpdateCertificatesRequest struct {
// console
Console *KeyPairConfiguration `json:"console,omitempty"`
// minio
Minio *KeyPairConfiguration `json:"minio,omitempty"`
}
// Validate validates this update certificates request
func (m *UpdateCertificatesRequest) Validate(formats strfmt.Registry) error {
var res []error
if err := m.validateConsole(formats); err != nil {
res = append(res, err)
}
if err := m.validateMinio(formats); err != nil {
res = append(res, err)
}
if len(res) > 0 {
return errors.CompositeValidationError(res...)
}
return nil
}
func (m *UpdateCertificatesRequest) validateConsole(formats strfmt.Registry) error {
if swag.IsZero(m.Console) { // not required
return nil
}
if m.Console != nil {
if err := m.Console.Validate(formats); err != nil {
if ve, ok := err.(*errors.Validation); ok {
return ve.ValidateName("console")
}
return err
}
}
return nil
}
func (m *UpdateCertificatesRequest) validateMinio(formats strfmt.Registry) error {
if swag.IsZero(m.Minio) { // not required
return nil
}
if m.Minio != nil {
if err := m.Minio.Validate(formats); err != nil {
if ve, ok := err.(*errors.Validation); ok {
return ve.ValidateName("minio")
}
return err
}
}
return nil
}
// MarshalBinary interface implementation
func (m *UpdateCertificatesRequest) MarshalBinary() ([]byte, error) {
if m == nil {
return nil, nil
}
return swag.WriteJSON(m)
}
// UnmarshalBinary interface implementation
func (m *UpdateCertificatesRequest) UnmarshalBinary(b []byte) error {
var res UpdateCertificatesRequest
if err := swag.ReadJSON(b, &res); err != nil {
return err
}
*m = res
return nil
}

View File

@@ -38,6 +38,9 @@ type UpdateTenantRequest struct {
// Pattern: ^((.*?)/(.*?):(.+))$ // Pattern: ^((.*?)/(.*?):(.+))$
ConsoleImage string `json:"console_image,omitempty"` ConsoleImage string `json:"console_image,omitempty"`
// enable prometheus
EnablePrometheus bool `json:"enable_prometheus,omitempty"`
// image // image
// Pattern: ^((.*?)/(.*?):(.+))$ // Pattern: ^((.*?)/(.*?):(.+))$
Image string `json:"image,omitempty"` Image string `json:"image,omitempty"`

View File

@@ -119,7 +119,6 @@ func registerTenantHandlers(api *operations.ConsoleAPI) {
api.AdminAPITenantAddZoneHandler = admin_api.TenantAddZoneHandlerFunc(func(params admin_api.TenantAddZoneParams, session *models.Principal) middleware.Responder { api.AdminAPITenantAddZoneHandler = admin_api.TenantAddZoneHandlerFunc(func(params admin_api.TenantAddZoneParams, session *models.Principal) middleware.Responder {
err := getTenantAddZoneResponse(session, params) err := getTenantAddZoneResponse(session, params)
if err != nil { if err != nil {
log.Println(err)
return admin_api.NewTenantAddZoneDefault(int(err.Code)).WithPayload(err) return admin_api.NewTenantAddZoneDefault(int(err.Code)).WithPayload(err)
} }
return admin_api.NewTenantAddZoneCreated() return admin_api.NewTenantAddZoneCreated()
@@ -129,7 +128,6 @@ func registerTenantHandlers(api *operations.ConsoleAPI) {
api.AdminAPIGetTenantUsageHandler = admin_api.GetTenantUsageHandlerFunc(func(params admin_api.GetTenantUsageParams, session *models.Principal) middleware.Responder { api.AdminAPIGetTenantUsageHandler = admin_api.GetTenantUsageHandlerFunc(func(params admin_api.GetTenantUsageParams, session *models.Principal) middleware.Responder {
payload, err := getTenantUsageResponse(session, params) payload, err := getTenantUsageResponse(session, params)
if err != nil { if err != nil {
log.Println(err)
return admin_api.NewGetTenantUsageDefault(int(err.Code)).WithPayload(err) return admin_api.NewGetTenantUsageDefault(int(err.Code)).WithPayload(err)
} }
return admin_api.NewGetTenantUsageOK().WithPayload(payload) return admin_api.NewGetTenantUsageOK().WithPayload(payload)
@@ -139,7 +137,6 @@ func registerTenantHandlers(api *operations.ConsoleAPI) {
api.AdminAPITenantUpdateZonesHandler = admin_api.TenantUpdateZonesHandlerFunc(func(params admin_api.TenantUpdateZonesParams, session *models.Principal) middleware.Responder { api.AdminAPITenantUpdateZonesHandler = admin_api.TenantUpdateZonesHandlerFunc(func(params admin_api.TenantUpdateZonesParams, session *models.Principal) middleware.Responder {
resp, err := getTenantUpdateZoneResponse(session, params) resp, err := getTenantUpdateZoneResponse(session, params)
if err != nil { if err != nil {
log.Println(err)
return admin_api.NewTenantUpdateZonesDefault(int(err.Code)).WithPayload(err) return admin_api.NewTenantUpdateZonesDefault(int(err.Code)).WithPayload(err)
} }
return admin_api.NewTenantUpdateZonesOK().WithPayload(resp) return admin_api.NewTenantUpdateZonesOK().WithPayload(resp)
@@ -149,7 +146,6 @@ func registerTenantHandlers(api *operations.ConsoleAPI) {
api.AdminAPITenantUpdateCertificateHandler = admin_api.TenantUpdateCertificateHandlerFunc(func(params admin_api.TenantUpdateCertificateParams, session *models.Principal) middleware.Responder { api.AdminAPITenantUpdateCertificateHandler = admin_api.TenantUpdateCertificateHandlerFunc(func(params admin_api.TenantUpdateCertificateParams, session *models.Principal) middleware.Responder {
err := getTenantUpdateCertificatesResponse(session, params) err := getTenantUpdateCertificatesResponse(session, params)
if err != nil { if err != nil {
log.Println(err)
return admin_api.NewGetTenantUsageDefault(int(err.Code)).WithPayload(err) return admin_api.NewGetTenantUsageDefault(int(err.Code)).WithPayload(err)
} }
return admin_api.NewTenantUpdateCertificateCreated() return admin_api.NewTenantUpdateCertificateCreated()
@@ -159,7 +155,6 @@ func registerTenantHandlers(api *operations.ConsoleAPI) {
api.AdminAPITenantUpdateEncryptionHandler = admin_api.TenantUpdateEncryptionHandlerFunc(func(params admin_api.TenantUpdateEncryptionParams, session *models.Principal) middleware.Responder { api.AdminAPITenantUpdateEncryptionHandler = admin_api.TenantUpdateEncryptionHandlerFunc(func(params admin_api.TenantUpdateEncryptionParams, session *models.Principal) middleware.Responder {
err := getTenantUpdateEncryptionResponse(session, params) err := getTenantUpdateEncryptionResponse(session, params)
if err != nil { if err != nil {
log.Println(err)
return admin_api.NewGetTenantUsageDefault(int(err.Code)).WithPayload(err) return admin_api.NewGetTenantUsageDefault(int(err.Code)).WithPayload(err)
} }
return admin_api.NewTenantUpdateCertificateCreated() return admin_api.NewTenantUpdateCertificateCreated()
@@ -262,24 +257,59 @@ func getTenant(ctx context.Context, operatorClient OperatorClientI, namespace, t
return minInst, nil return minInst, nil
} }
func isPrometheusEnabled(annotations map[string]string) bool {
if annotations == nil {
return false
}
// if one of the following prometheus annotations are not present
// we consider the tenant as not integrated with prometheus
if _, ok := annotations[prometheusPath]; !ok {
return false
}
if _, ok := annotations[prometheusPort]; !ok {
return false
}
if _, ok := annotations[prometheusScrape]; !ok {
return false
}
return true
}
func getTenantInfo(tenant *operator.Tenant) *models.Tenant { func getTenantInfo(tenant *operator.Tenant) *models.Tenant {
var zones []*models.Zone var zones []*models.Zone
consoleImage := ""
var totalSize int64 var totalSize int64
for _, z := range tenant.Spec.Zones { for _, z := range tenant.Spec.Zones {
zones = append(zones, parseTenantZone(&z)) zones = append(zones, parseTenantZone(&z))
zoneSize := int64(z.Servers) * int64(z.VolumesPerServer) * z.VolumeClaimTemplate.Spec.Resources.Requests.Storage().Value() zoneSize := int64(z.Servers) * int64(z.VolumesPerServer) * z.VolumeClaimTemplate.Spec.Resources.Requests.Storage().Value()
totalSize = totalSize + zoneSize totalSize = totalSize + zoneSize
} }
var deletion string
if tenant.ObjectMeta.DeletionTimestamp != nil {
deletion = tenant.ObjectMeta.DeletionTimestamp.String()
}
if tenant.HasConsoleEnabled() {
consoleImage = tenant.Spec.Console.Image
}
if tenant.Spec.Metadata == nil {
tenant.Spec.Metadata = &metav1.ObjectMeta{
Annotations: map[string]string{},
}
}
return &models.Tenant{ return &models.Tenant{
CreationDate: tenant.ObjectMeta.CreationTimestamp.String(), CreationDate: tenant.ObjectMeta.CreationTimestamp.String(),
Name: tenant.Name, DeletionDate: deletion,
TotalSize: totalSize, Name: tenant.Name,
CurrentState: tenant.Status.CurrentState, TotalSize: totalSize,
Zones: zones, CurrentState: tenant.Status.CurrentState,
Namespace: tenant.ObjectMeta.Namespace, Zones: zones,
Image: tenant.Spec.Image, Namespace: tenant.ObjectMeta.Namespace,
Image: tenant.Spec.Image,
ConsoleImage: consoleImage,
EnablePrometheus: isPrometheusEnabled(tenant.Spec.Metadata.Annotations),
} }
} }
@@ -335,8 +365,14 @@ func listTenants(ctx context.Context, operatorClient OperatorClientI, namespace
} }
} }
var deletion string
if tenant.ObjectMeta.DeletionTimestamp != nil {
deletion = tenant.ObjectMeta.DeletionTimestamp.String()
}
tenants = append(tenants, &models.TenantList{ tenants = append(tenants, &models.TenantList{
CreationDate: tenant.ObjectMeta.CreationTimestamp.String(), CreationDate: tenant.ObjectMeta.CreationTimestamp.String(),
DeletionDate: deletion,
Name: tenant.ObjectMeta.Name, Name: tenant.ObjectMeta.Name,
ZoneCount: int64(len(tenant.Spec.Zones)), ZoneCount: int64(len(tenant.Spec.Zones)),
InstanceCount: instanceCount, InstanceCount: instanceCount,
@@ -621,7 +657,7 @@ func getTenantCreatedResponse(session *models.Principal, params admin_api.Create
return nil, prepareError(errorGeneric) return nil, prepareError(errorGeneric)
} }
const consoleVersion = "minio/console:v0.3.20" const consoleVersion = "minio/console:v0.3.21"
minInst.Spec.Console = &operator.ConsoleConfiguration{ minInst.Spec.Console = &operator.ConsoleConfiguration{
Replicas: 1, Replicas: 1,
Image: consoleVersion, Image: consoleVersion,
@@ -689,9 +725,9 @@ func getTenantCreatedResponse(session *models.Principal, params admin_api.Create
// prometheus annotations support // prometheus annotations support
if tenantReq.EnablePrometheus != nil && *tenantReq.EnablePrometheus && minInst.Spec.Metadata != nil && minInst.Spec.Metadata.Annotations != nil { if tenantReq.EnablePrometheus != nil && *tenantReq.EnablePrometheus && minInst.Spec.Metadata != nil && minInst.Spec.Metadata.Annotations != nil {
minInst.Spec.Metadata.Annotations["prometheus.io/path"] = "/minio/prometheus/metrics" minInst.Spec.Metadata.Annotations[prometheusPath] = "/minio/prometheus/metrics"
minInst.Spec.Metadata.Annotations["prometheus.io/port"] = fmt.Sprint(operator.MinIOPort) minInst.Spec.Metadata.Annotations[prometheusPort] = fmt.Sprint(operator.MinIOPort)
minInst.Spec.Metadata.Annotations["prometheus.io/scrape"] = "true" minInst.Spec.Metadata.Annotations[prometheusScrape] = "true"
} }
// set console image if provided // set console image if provided
@@ -825,6 +861,40 @@ func updateTenantAction(ctx context.Context, operatorClient OperatorClientI, cli
} }
} }
// Prometheus Annotations
if minInst.Spec.Metadata == nil {
minInst.Spec.Metadata = &metav1.ObjectMeta{
Annotations: map[string]string{},
}
}
currentAnnotations := minInst.Spec.Metadata.Annotations
prometheusAnnotations := map[string]string{
prometheusPath: "/minio/prometheus/metrics",
prometheusPort: fmt.Sprint(operator.MinIOPort),
prometheusScrape: "true",
}
if params.Body.EnablePrometheus && minInst.Spec.Metadata != nil && currentAnnotations != nil {
// add prometheus annotations to the tenant
minInst.Spec.Metadata.Annotations = addAnnotations(currentAnnotations, prometheusAnnotations)
// add prometheus annotations to the each zone
if minInst.Spec.Zones != nil {
for _, zone := range minInst.Spec.Zones {
zoneAnnotations := zone.VolumeClaimTemplate.GetObjectMeta().GetAnnotations()
zone.VolumeClaimTemplate.GetObjectMeta().SetAnnotations(addAnnotations(zoneAnnotations, prometheusAnnotations))
}
}
} else {
// remove prometheus annotations to the tenant
minInst.Spec.Metadata.Annotations = removeAnnotations(currentAnnotations, prometheusAnnotations)
// add prometheus annotations from each zone
if minInst.Spec.Zones != nil {
for _, zone := range minInst.Spec.Zones {
zoneAnnotations := zone.VolumeClaimTemplate.GetObjectMeta().GetAnnotations()
zone.VolumeClaimTemplate.GetObjectMeta().SetAnnotations(removeAnnotations(zoneAnnotations, prometheusAnnotations))
}
}
}
payloadBytes, err := json.Marshal(minInst) payloadBytes, err := json.Marshal(minInst)
if err != nil { if err != nil {
return err return err
@@ -836,6 +906,28 @@ func updateTenantAction(ctx context.Context, operatorClient OperatorClientI, cli
return nil return nil
} }
// addAnnotations will merge two annotation maps
func addAnnotations(annotationsOne, annotationsTwo map[string]string) map[string]string {
if annotationsOne == nil {
annotationsOne = map[string]string{}
}
for key, value := range annotationsTwo {
annotationsOne[key] = value
}
return annotationsOne
}
// removeAnnotations will remove keys from the first annotations map based on the second one
func removeAnnotations(annotationsOne, annotationsTwo map[string]string) map[string]string {
if annotationsOne == nil {
annotationsOne = map[string]string{}
}
for key := range annotationsTwo {
delete(annotationsOne, key)
}
return annotationsOne
}
func getUpdateTenantResponse(session *models.Principal, params admin_api.UpdateTenantParams) *models.Error { func getUpdateTenantResponse(session *models.Principal, params admin_api.UpdateTenantParams) *models.Error {
ctx := context.Background() ctx := context.Background()
opClientClientSet, err := cluster.OperatorClient(session.SessionToken) opClientClientSet, err := cluster.OperatorClient(session.SessionToken)

View File

@@ -871,7 +871,7 @@ func Test_UpdateTenantAction(t *testing.T) {
}, },
params: admin_api.UpdateTenantParams{ params: admin_api.UpdateTenantParams{
Body: &models.UpdateTenantRequest{ Body: &models.UpdateTenantRequest{
ConsoleImage: "minio/console:v0.3.20", ConsoleImage: "minio/console:v0.3.21",
}, },
}, },
}, },

View File

@@ -50,3 +50,11 @@ const (
ConsoleSecureFeaturePolicy = "CONSOLE_SECURE_FEATURE_POLICY" ConsoleSecureFeaturePolicy = "CONSOLE_SECURE_FEATURE_POLICY"
ConsoleSecureExpectCTHeader = "CONSOLE_SECURE_EXPECT_CT_HEADER" ConsoleSecureExpectCTHeader = "CONSOLE_SECURE_EXPECT_CT_HEADER"
) )
// prometheus annotations
const (
prometheusPath = "prometheus.io/path"
prometheusPort = "prometheus.io/port"
prometheusScrape = "prometheus.io/scrape"
)

View File

@@ -3150,12 +3150,21 @@ func init() {
"tenant": { "tenant": {
"type": "object", "type": "object",
"properties": { "properties": {
"console_image": {
"type": "string"
},
"creation_date": { "creation_date": {
"type": "string" "type": "string"
}, },
"currentState": { "currentState": {
"type": "string" "type": "string"
}, },
"deletion_date": {
"type": "string"
},
"enable_prometheus": {
"type": "boolean"
},
"image": { "image": {
"type": "string" "type": "string"
}, },
@@ -3186,6 +3195,9 @@ func init() {
"currentState": { "currentState": {
"type": "string" "type": "string"
}, },
"deletion_date": {
"type": "string"
},
"instance_count": { "instance_count": {
"type": "integer" "type": "integer"
}, },
@@ -3257,6 +3269,9 @@ func init() {
"type": "string", "type": "string",
"pattern": "^((.*?)/(.*?):(.+))$" "pattern": "^((.*?)/(.*?):(.+))$"
}, },
"enable_prometheus": {
"type": "boolean"
},
"image": { "image": {
"type": "string", "type": "string",
"pattern": "^((.*?)/(.*?):(.+))$" "pattern": "^((.*?)/(.*?):(.+))$"
@@ -7225,12 +7240,21 @@ func init() {
"tenant": { "tenant": {
"type": "object", "type": "object",
"properties": { "properties": {
"console_image": {
"type": "string"
},
"creation_date": { "creation_date": {
"type": "string" "type": "string"
}, },
"currentState": { "currentState": {
"type": "string" "type": "string"
}, },
"deletion_date": {
"type": "string"
},
"enable_prometheus": {
"type": "boolean"
},
"image": { "image": {
"type": "string" "type": "string"
}, },
@@ -7261,6 +7285,9 @@ func init() {
"currentState": { "currentState": {
"type": "string" "type": "string"
}, },
"deletion_date": {
"type": "string"
},
"instance_count": { "instance_count": {
"type": "integer" "type": "integer"
}, },
@@ -7332,6 +7359,9 @@ func init() {
"type": "string", "type": "string",
"pattern": "^((.*?)/(.*?):(.+))$" "pattern": "^((.*?)/(.*?):(.+))$"
}, },
"enable_prometheus": {
"type": "boolean"
},
"image": { "image": {
"type": "string", "type": "string",
"pattern": "^((.*?)/(.*?):(.+))$" "pattern": "^((.*?)/(.*?):(.+))$"

View File

@@ -1828,6 +1828,8 @@ definitions:
type: string type: string
creation_date: creation_date:
type: string type: string
deletion_date:
type: string
currentState: currentState:
type: string type: string
zones: zones:
@@ -1836,11 +1838,15 @@ definitions:
$ref: "#/definitions/zone" $ref: "#/definitions/zone"
image: image:
type: string type: string
console_image:
type: string
namespace: namespace:
type: string type: string
total_size: total_size:
type: integer type: integer
format: int64 format: int64
enable_prometheus:
type: boolean
tenantUsage: tenantUsage:
type: object type: object
@@ -1867,6 +1873,8 @@ definitions:
type: integer type: integer
creation_date: creation_date:
type: string type: string
deletion_date:
type: string
currentState: currentState:
type: string type: string
namespace: namespace:
@@ -1898,6 +1906,8 @@ definitions:
$ref: "#/definitions/imageRegistry" $ref: "#/definitions/imageRegistry"
image_pull_secret: image_pull_secret:
type: string type: string
enable_prometheus:
type: boolean
imageRegistry: imageRegistry:
type: object type: object