Compare commits
8 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c1963c6122 | ||
|
|
73154e8dd7 | ||
|
|
e2e8cbe46c | ||
|
|
b9b776c278 | ||
|
|
7710df62ee | ||
|
|
63e1c554b7 | ||
|
|
a9d8f3fc41 | ||
|
|
59bf546b4a |
@@ -23,6 +23,33 @@ builds:
|
||||
goarch:
|
||||
- amd64
|
||||
- arm64
|
||||
|
||||
ignore:
|
||||
- goos: darwin
|
||||
goarch: arm64
|
||||
- goos: darwin
|
||||
goarch: arm
|
||||
- goos: darwin
|
||||
goarch: ppc64le
|
||||
- goos: darwin
|
||||
goarch: s390x
|
||||
- goos: windows
|
||||
goarch: arm64
|
||||
- goos: windows
|
||||
goarch: arm
|
||||
- goos: windows
|
||||
goarch: ppc64le
|
||||
- goos: windows
|
||||
goarch: s390x
|
||||
- goos: freebsd
|
||||
goarch: arm
|
||||
- goos: freebsd
|
||||
goarch: arm64
|
||||
- goos: freebsd
|
||||
goarch: ppc64le
|
||||
- goos: freebsd
|
||||
goarch: s390x
|
||||
|
||||
env:
|
||||
- CGO_ENABLED=0
|
||||
main: ./cmd/console/
|
||||
|
||||
@@ -15,7 +15,7 @@ spec:
|
||||
serviceAccountName: console-sa
|
||||
containers:
|
||||
- name: console
|
||||
image: minio/console:v0.3.4
|
||||
image: minio/console:v0.3.7
|
||||
imagePullPolicy: "IfNotPresent"
|
||||
args:
|
||||
- server
|
||||
|
||||
@@ -6,8 +6,18 @@ rules:
|
||||
- apiGroups:
|
||||
- ""
|
||||
resources:
|
||||
- namespaces
|
||||
- secrets
|
||||
verbs:
|
||||
- get
|
||||
- watch
|
||||
- create
|
||||
- list
|
||||
- patch
|
||||
- update
|
||||
- apiGroups:
|
||||
- ""
|
||||
resources:
|
||||
- namespaces
|
||||
- pods
|
||||
- services
|
||||
- events
|
||||
|
||||
@@ -15,7 +15,7 @@ spec:
|
||||
serviceAccountName: console-sa
|
||||
containers:
|
||||
- name: console
|
||||
image: minio/console:v0.3.4
|
||||
image: minio/console:v0.3.7
|
||||
imagePullPolicy: "IfNotPresent"
|
||||
env:
|
||||
- name: CONSOLE_OPERATOR_MODE
|
||||
|
||||
@@ -51,12 +51,18 @@ type CreateTenantRequest struct {
|
||||
// encryption
|
||||
Encryption *EncryptionConfiguration `json:"encryption,omitempty"`
|
||||
|
||||
// erasure coding parity
|
||||
ErasureCodingParity int64 `json:"erasureCodingParity,omitempty"`
|
||||
|
||||
// idp
|
||||
Idp *IdpConfiguration `json:"idp,omitempty"`
|
||||
|
||||
// image
|
||||
Image string `json:"image,omitempty"`
|
||||
|
||||
// image registry
|
||||
ImageRegistry *ImageRegistry `json:"image_registry,omitempty"`
|
||||
|
||||
// mounth path
|
||||
MounthPath string `json:"mounth_path,omitempty"`
|
||||
|
||||
@@ -95,6 +101,10 @@ func (m *CreateTenantRequest) Validate(formats strfmt.Registry) error {
|
||||
res = append(res, err)
|
||||
}
|
||||
|
||||
if err := m.validateImageRegistry(formats); err != nil {
|
||||
res = append(res, err)
|
||||
}
|
||||
|
||||
if err := m.validateName(formats); err != nil {
|
||||
res = append(res, err)
|
||||
}
|
||||
@@ -153,6 +163,24 @@ func (m *CreateTenantRequest) validateIdp(formats strfmt.Registry) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *CreateTenantRequest) validateImageRegistry(formats strfmt.Registry) error {
|
||||
|
||||
if swag.IsZero(m.ImageRegistry) { // not required
|
||||
return nil
|
||||
}
|
||||
|
||||
if m.ImageRegistry != nil {
|
||||
if err := m.ImageRegistry.Validate(formats); err != nil {
|
||||
if ve, ok := err.(*errors.Validation); ok {
|
||||
return ve.ValidateName("image_registry")
|
||||
}
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *CreateTenantRequest) validateName(formats strfmt.Registry) error {
|
||||
|
||||
if err := validate.Required("name", "body", m.Name); err != nil {
|
||||
|
||||
@@ -29,37 +29,37 @@ import (
|
||||
"github.com/go-openapi/validate"
|
||||
)
|
||||
|
||||
// EncryptionKesConfig encryption kes config
|
||||
// ImageRegistry image registry
|
||||
//
|
||||
// swagger:model encryptionKesConfig
|
||||
type EncryptionKesConfig struct {
|
||||
// swagger:model imageRegistry
|
||||
type ImageRegistry struct {
|
||||
|
||||
// server cert
|
||||
// password
|
||||
// Required: true
|
||||
ServerCert *string `json:"server_cert"`
|
||||
Password *string `json:"password"`
|
||||
|
||||
// server config
|
||||
// registry
|
||||
// Required: true
|
||||
ServerConfig *string `json:"server_config"`
|
||||
Registry *string `json:"registry"`
|
||||
|
||||
// server key
|
||||
// username
|
||||
// Required: true
|
||||
ServerKey *string `json:"server_key"`
|
||||
Username *string `json:"username"`
|
||||
}
|
||||
|
||||
// Validate validates this encryption kes config
|
||||
func (m *EncryptionKesConfig) Validate(formats strfmt.Registry) error {
|
||||
// Validate validates this image registry
|
||||
func (m *ImageRegistry) Validate(formats strfmt.Registry) error {
|
||||
var res []error
|
||||
|
||||
if err := m.validateServerCert(formats); err != nil {
|
||||
if err := m.validatePassword(formats); err != nil {
|
||||
res = append(res, err)
|
||||
}
|
||||
|
||||
if err := m.validateServerConfig(formats); err != nil {
|
||||
if err := m.validateRegistry(formats); err != nil {
|
||||
res = append(res, err)
|
||||
}
|
||||
|
||||
if err := m.validateServerKey(formats); err != nil {
|
||||
if err := m.validateUsername(formats); err != nil {
|
||||
res = append(res, err)
|
||||
}
|
||||
|
||||
@@ -69,27 +69,27 @@ func (m *EncryptionKesConfig) Validate(formats strfmt.Registry) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *EncryptionKesConfig) validateServerCert(formats strfmt.Registry) error {
|
||||
func (m *ImageRegistry) validatePassword(formats strfmt.Registry) error {
|
||||
|
||||
if err := validate.Required("server_cert", "body", m.ServerCert); err != nil {
|
||||
if err := validate.Required("password", "body", m.Password); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *EncryptionKesConfig) validateServerConfig(formats strfmt.Registry) error {
|
||||
func (m *ImageRegistry) validateRegistry(formats strfmt.Registry) error {
|
||||
|
||||
if err := validate.Required("server_config", "body", m.ServerConfig); err != nil {
|
||||
if err := validate.Required("registry", "body", m.Registry); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *EncryptionKesConfig) validateServerKey(formats strfmt.Registry) error {
|
||||
func (m *ImageRegistry) validateUsername(formats strfmt.Registry) error {
|
||||
|
||||
if err := validate.Required("server_key", "body", m.ServerKey); err != nil {
|
||||
if err := validate.Required("username", "body", m.Username); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -97,7 +97,7 @@ func (m *EncryptionKesConfig) validateServerKey(formats strfmt.Registry) error {
|
||||
}
|
||||
|
||||
// MarshalBinary interface implementation
|
||||
func (m *EncryptionKesConfig) MarshalBinary() ([]byte, error) {
|
||||
func (m *ImageRegistry) MarshalBinary() ([]byte, error) {
|
||||
if m == nil {
|
||||
return nil, nil
|
||||
}
|
||||
@@ -105,8 +105,8 @@ func (m *EncryptionKesConfig) MarshalBinary() ([]byte, error) {
|
||||
}
|
||||
|
||||
// UnmarshalBinary interface implementation
|
||||
func (m *EncryptionKesConfig) UnmarshalBinary(b []byte) error {
|
||||
var res EncryptionKesConfig
|
||||
func (m *ImageRegistry) UnmarshalBinary(b []byte) error {
|
||||
var res ImageRegistry
|
||||
if err := swag.ReadJSON(b, &res); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -1,269 +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"
|
||||
"github.com/go-openapi/validate"
|
||||
)
|
||||
|
||||
// KesConfiguration kes configuration
|
||||
//
|
||||
// swagger:model kesConfiguration
|
||||
type KesConfiguration struct {
|
||||
|
||||
// client
|
||||
// Required: true
|
||||
Client *KesConfigurationClient `json:"client"`
|
||||
|
||||
// server
|
||||
// Required: true
|
||||
Server *KesConfigurationServer `json:"server"`
|
||||
|
||||
// server config yaml
|
||||
// Required: true
|
||||
ServerConfigYaml *string `json:"server-config.yaml"`
|
||||
}
|
||||
|
||||
// Validate validates this kes configuration
|
||||
func (m *KesConfiguration) Validate(formats strfmt.Registry) error {
|
||||
var res []error
|
||||
|
||||
if err := m.validateClient(formats); err != nil {
|
||||
res = append(res, err)
|
||||
}
|
||||
|
||||
if err := m.validateServer(formats); err != nil {
|
||||
res = append(res, err)
|
||||
}
|
||||
|
||||
if err := m.validateServerConfigYaml(formats); err != nil {
|
||||
res = append(res, err)
|
||||
}
|
||||
|
||||
if len(res) > 0 {
|
||||
return errors.CompositeValidationError(res...)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *KesConfiguration) validateClient(formats strfmt.Registry) error {
|
||||
|
||||
if err := validate.Required("client", "body", m.Client); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if m.Client != nil {
|
||||
if err := m.Client.Validate(formats); err != nil {
|
||||
if ve, ok := err.(*errors.Validation); ok {
|
||||
return ve.ValidateName("client")
|
||||
}
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *KesConfiguration) validateServer(formats strfmt.Registry) error {
|
||||
|
||||
if err := validate.Required("server", "body", m.Server); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if m.Server != nil {
|
||||
if err := m.Server.Validate(formats); err != nil {
|
||||
if ve, ok := err.(*errors.Validation); ok {
|
||||
return ve.ValidateName("server")
|
||||
}
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *KesConfiguration) validateServerConfigYaml(formats strfmt.Registry) error {
|
||||
|
||||
if err := validate.Required("server-config.yaml", "body", m.ServerConfigYaml); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// MarshalBinary interface implementation
|
||||
func (m *KesConfiguration) MarshalBinary() ([]byte, error) {
|
||||
if m == nil {
|
||||
return nil, nil
|
||||
}
|
||||
return swag.WriteJSON(m)
|
||||
}
|
||||
|
||||
// UnmarshalBinary interface implementation
|
||||
func (m *KesConfiguration) UnmarshalBinary(b []byte) error {
|
||||
var res KesConfiguration
|
||||
if err := swag.ReadJSON(b, &res); err != nil {
|
||||
return err
|
||||
}
|
||||
*m = res
|
||||
return nil
|
||||
}
|
||||
|
||||
// KesConfigurationClient kes configuration client
|
||||
//
|
||||
// swagger:model KesConfigurationClient
|
||||
type KesConfigurationClient struct {
|
||||
|
||||
// tls crt
|
||||
// Required: true
|
||||
TLSCrt *string `json:"tls.crt"`
|
||||
|
||||
// tls key
|
||||
// Required: true
|
||||
TLSKey *string `json:"tls.key"`
|
||||
}
|
||||
|
||||
// Validate validates this kes configuration client
|
||||
func (m *KesConfigurationClient) Validate(formats strfmt.Registry) error {
|
||||
var res []error
|
||||
|
||||
if err := m.validateTLSCrt(formats); err != nil {
|
||||
res = append(res, err)
|
||||
}
|
||||
|
||||
if err := m.validateTLSKey(formats); err != nil {
|
||||
res = append(res, err)
|
||||
}
|
||||
|
||||
if len(res) > 0 {
|
||||
return errors.CompositeValidationError(res...)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *KesConfigurationClient) validateTLSCrt(formats strfmt.Registry) error {
|
||||
|
||||
if err := validate.Required("client"+"."+"tls.crt", "body", m.TLSCrt); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *KesConfigurationClient) validateTLSKey(formats strfmt.Registry) error {
|
||||
|
||||
if err := validate.Required("client"+"."+"tls.key", "body", m.TLSKey); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// MarshalBinary interface implementation
|
||||
func (m *KesConfigurationClient) MarshalBinary() ([]byte, error) {
|
||||
if m == nil {
|
||||
return nil, nil
|
||||
}
|
||||
return swag.WriteJSON(m)
|
||||
}
|
||||
|
||||
// UnmarshalBinary interface implementation
|
||||
func (m *KesConfigurationClient) UnmarshalBinary(b []byte) error {
|
||||
var res KesConfigurationClient
|
||||
if err := swag.ReadJSON(b, &res); err != nil {
|
||||
return err
|
||||
}
|
||||
*m = res
|
||||
return nil
|
||||
}
|
||||
|
||||
// KesConfigurationServer kes configuration server
|
||||
//
|
||||
// swagger:model KesConfigurationServer
|
||||
type KesConfigurationServer struct {
|
||||
|
||||
// tls crt
|
||||
// Required: true
|
||||
TLSCrt *string `json:"tls.crt"`
|
||||
|
||||
// tls key
|
||||
// Required: true
|
||||
TLSKey *string `json:"tls.key"`
|
||||
}
|
||||
|
||||
// Validate validates this kes configuration server
|
||||
func (m *KesConfigurationServer) Validate(formats strfmt.Registry) error {
|
||||
var res []error
|
||||
|
||||
if err := m.validateTLSCrt(formats); err != nil {
|
||||
res = append(res, err)
|
||||
}
|
||||
|
||||
if err := m.validateTLSKey(formats); err != nil {
|
||||
res = append(res, err)
|
||||
}
|
||||
|
||||
if len(res) > 0 {
|
||||
return errors.CompositeValidationError(res...)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *KesConfigurationServer) validateTLSCrt(formats strfmt.Registry) error {
|
||||
|
||||
if err := validate.Required("server"+"."+"tls.crt", "body", m.TLSCrt); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *KesConfigurationServer) validateTLSKey(formats strfmt.Registry) error {
|
||||
|
||||
if err := validate.Required("server"+"."+"tls.key", "body", m.TLSKey); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// MarshalBinary interface implementation
|
||||
func (m *KesConfigurationServer) MarshalBinary() ([]byte, error) {
|
||||
if m == nil {
|
||||
return nil, nil
|
||||
}
|
||||
return swag.WriteJSON(m)
|
||||
}
|
||||
|
||||
// UnmarshalBinary interface implementation
|
||||
func (m *KesConfigurationServer) UnmarshalBinary(b []byte) error {
|
||||
var res KesConfigurationServer
|
||||
if err := swag.ReadJSON(b, &res); err != nil {
|
||||
return err
|
||||
}
|
||||
*m = res
|
||||
return nil
|
||||
}
|
||||
@@ -32,8 +32,11 @@ import (
|
||||
// swagger:model tenantUsage
|
||||
type TenantUsage struct {
|
||||
|
||||
// used size
|
||||
UsedSize int64 `json:"used_size,omitempty"`
|
||||
// disk used
|
||||
DiskUsed int64 `json:"disk_used,omitempty"`
|
||||
|
||||
// used
|
||||
Used int64 `json:"used,omitempty"`
|
||||
}
|
||||
|
||||
// Validate validates this tenant usage
|
||||
|
||||
@@ -37,6 +37,9 @@ type UpdateTenantRequest struct {
|
||||
// image
|
||||
// Pattern: ^((.*?)/(.*?):(.+))$
|
||||
Image string `json:"image,omitempty"`
|
||||
|
||||
// image registry
|
||||
ImageRegistry *ImageRegistry `json:"image_registry,omitempty"`
|
||||
}
|
||||
|
||||
// Validate validates this update tenant request
|
||||
@@ -47,6 +50,10 @@ func (m *UpdateTenantRequest) Validate(formats strfmt.Registry) error {
|
||||
res = append(res, err)
|
||||
}
|
||||
|
||||
if err := m.validateImageRegistry(formats); err != nil {
|
||||
res = append(res, err)
|
||||
}
|
||||
|
||||
if len(res) > 0 {
|
||||
return errors.CompositeValidationError(res...)
|
||||
}
|
||||
@@ -66,6 +73,24 @@ func (m *UpdateTenantRequest) validateImage(formats strfmt.Registry) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *UpdateTenantRequest) validateImageRegistry(formats strfmt.Registry) error {
|
||||
|
||||
if swag.IsZero(m.ImageRegistry) { // not required
|
||||
return nil
|
||||
}
|
||||
|
||||
if m.ImageRegistry != nil {
|
||||
if err := m.ImageRegistry.Validate(formats); err != nil {
|
||||
if ve, ok := err.(*errors.Validation); ok {
|
||||
return ve.ValidateName("image_registry")
|
||||
}
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// MarshalBinary interface implementation
|
||||
func (m *UpdateTenantRequest) MarshalBinary() ([]byte, error) {
|
||||
if m == nil {
|
||||
|
||||
@@ -250,7 +250,10 @@ const Login = ({ classes, userLoggedIn }: ILoginProps) => {
|
||||
</Typography>
|
||||
<Button
|
||||
component={"a"}
|
||||
href={loginStrategy.redirect.replace("%5BHOSTNAME%5D", window.location.hostname)}
|
||||
href={loginStrategy.redirect.replace(
|
||||
"%5BHOSTNAME%5D",
|
||||
window.location.hostname
|
||||
)}
|
||||
type="submit"
|
||||
fullWidth
|
||||
variant="contained"
|
||||
|
||||
@@ -49,9 +49,25 @@ import (
|
||||
"github.com/minio/console/restapi/operations"
|
||||
"github.com/minio/console/restapi/operations/admin_api"
|
||||
operator "github.com/minio/operator/pkg/apis/minio.min.io/v1"
|
||||
k8sErrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
v1 "k8s.io/client-go/kubernetes/typed/core/v1"
|
||||
)
|
||||
|
||||
const (
|
||||
minioRegCred = "minio-regcred-secret"
|
||||
)
|
||||
|
||||
type imageRegistry struct {
|
||||
Auths map[string]imageRegistryCredentials `json:"auths"`
|
||||
}
|
||||
|
||||
type imageRegistryCredentials struct {
|
||||
Username string `json:"username"`
|
||||
Password string `json:"password"`
|
||||
Auth string `json:"auth"`
|
||||
}
|
||||
|
||||
func registerTenantHandlers(api *operations.ConsoleAPI) {
|
||||
// Add Tenant
|
||||
api.AdminAPICreateTenantHandler = admin_api.CreateTenantHandlerFunc(func(params admin_api.CreateTenantParams, session *models.Principal) middleware.Responder {
|
||||
@@ -334,7 +350,9 @@ func getListTenantsResponse(session *models.Principal, params admin_api.ListTena
|
||||
}
|
||||
|
||||
func getTenantCreatedResponse(session *models.Principal, params admin_api.CreateTenantParams) (*models.CreateTenantResponse, error) {
|
||||
minioImage := params.Body.Image
|
||||
tenantReq := params.Body
|
||||
minioImage := tenantReq.Image
|
||||
ctx := context.Background()
|
||||
|
||||
if minioImage == "" {
|
||||
minImg, err := cluster.GetMinioImage()
|
||||
@@ -349,20 +367,20 @@ func getTenantCreatedResponse(session *models.Principal, params admin_api.Create
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ns := *params.Body.Namespace
|
||||
ns := *tenantReq.Namespace
|
||||
|
||||
// if access/secret are provided, use them, else create a random pair
|
||||
accessKey := RandomCharString(16)
|
||||
secretKey := RandomCharString(32)
|
||||
|
||||
if params.Body.AccessKey != "" {
|
||||
accessKey = params.Body.AccessKey
|
||||
if tenantReq.AccessKey != "" {
|
||||
accessKey = tenantReq.AccessKey
|
||||
}
|
||||
if params.Body.SecretKey != "" {
|
||||
secretKey = params.Body.SecretKey
|
||||
if tenantReq.SecretKey != "" {
|
||||
secretKey = tenantReq.SecretKey
|
||||
}
|
||||
|
||||
secretName := fmt.Sprintf("%s-secret", *params.Body.Name)
|
||||
secretName := fmt.Sprintf("%s-secret", *tenantReq.Name)
|
||||
imm := true
|
||||
|
||||
instanceSecret := corev1.Secret{
|
||||
@@ -376,15 +394,27 @@ func getTenantCreatedResponse(session *models.Principal, params admin_api.Create
|
||||
},
|
||||
}
|
||||
|
||||
_, err = clientset.CoreV1().Secrets(ns).Create(context.Background(), &instanceSecret, metav1.CreateOptions{})
|
||||
_, err = clientset.CoreV1().Secrets(ns).Create(ctx, &instanceSecret, metav1.CreateOptions{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var envrionmentVariables []corev1.EnvVar
|
||||
// Check the Erasure Coding Parity for validity and pass it to Tenant
|
||||
if tenantReq.ErasureCodingParity > 0 {
|
||||
if tenantReq.ErasureCodingParity < 2 && tenantReq.ErasureCodingParity > 8 {
|
||||
return nil, errors.New("invalid Erasure Coding Value")
|
||||
}
|
||||
envrionmentVariables = append(envrionmentVariables, corev1.EnvVar{
|
||||
Name: "MINIO_STORAGE_CLASS_STANDARD",
|
||||
Value: fmt.Sprintf("%d", tenantReq.ErasureCodingParity),
|
||||
})
|
||||
}
|
||||
|
||||
//Construct a MinIO Instance with everything we are getting from parameters
|
||||
minInst := operator.Tenant{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: *params.Body.Name,
|
||||
Name: *tenantReq.Name,
|
||||
},
|
||||
Spec: operator.TenantSpec{
|
||||
Image: minioImage,
|
||||
@@ -392,20 +422,20 @@ func getTenantCreatedResponse(session *models.Principal, params admin_api.Create
|
||||
CredsSecret: &corev1.LocalObjectReference{
|
||||
Name: secretName,
|
||||
},
|
||||
Env: []corev1.EnvVar{},
|
||||
Env: envrionmentVariables,
|
||||
},
|
||||
}
|
||||
idpEnabled := false
|
||||
// Enable IDP (Active Directory) for MinIO
|
||||
if params.Body.Idp != nil && params.Body.Idp.ActiveDirectory != nil {
|
||||
url := *params.Body.Idp.ActiveDirectory.URL
|
||||
userNameFormat := *params.Body.Idp.ActiveDirectory.UsernameFormat
|
||||
userSearchFilter := *params.Body.Idp.ActiveDirectory.UserSearchFilter
|
||||
tlsSkipVerify := params.Body.Idp.ActiveDirectory.SkipSslVerification
|
||||
serverInsecure := params.Body.Idp.ActiveDirectory.ServerInsecure
|
||||
groupSearchDN := params.Body.Idp.ActiveDirectory.GroupSearchBaseDn
|
||||
groupSearchFilter := params.Body.Idp.ActiveDirectory.GroupSearchFilter
|
||||
groupNameAttribute := params.Body.Idp.ActiveDirectory.GroupNameAttribute
|
||||
if tenantReq.Idp != nil && tenantReq.Idp.ActiveDirectory != nil {
|
||||
url := *tenantReq.Idp.ActiveDirectory.URL
|
||||
userNameFormat := *tenantReq.Idp.ActiveDirectory.UsernameFormat
|
||||
userSearchFilter := *tenantReq.Idp.ActiveDirectory.UserSearchFilter
|
||||
tlsSkipVerify := tenantReq.Idp.ActiveDirectory.SkipSslVerification
|
||||
serverInsecure := tenantReq.Idp.ActiveDirectory.ServerInsecure
|
||||
groupSearchDN := tenantReq.Idp.ActiveDirectory.GroupSearchBaseDn
|
||||
groupSearchFilter := tenantReq.Idp.ActiveDirectory.GroupSearchFilter
|
||||
groupNameAttribute := tenantReq.Idp.ActiveDirectory.GroupNameAttribute
|
||||
if url != "" && userNameFormat != "" && userSearchFilter != "" {
|
||||
// CONSOLE_LDAP_ENABLED
|
||||
idpEnabled = true
|
||||
@@ -449,24 +479,24 @@ func getTenantCreatedResponse(session *models.Principal, params admin_api.Create
|
||||
|
||||
// operator request AutoCert feature
|
||||
encryption := false
|
||||
if params.Body.EnableSsl != nil {
|
||||
if tenantReq.EnableSsl != nil {
|
||||
encryption = true
|
||||
minInst.Spec.RequestAutoCert = *params.Body.EnableSsl
|
||||
minInst.Spec.RequestAutoCert = *tenantReq.EnableSsl
|
||||
}
|
||||
|
||||
// User provided TLS certificates (this will take priority over autoCert)
|
||||
if params.Body.TLS != nil && params.Body.TLS.Crt != nil && params.Body.TLS.Key != nil {
|
||||
if tenantReq.TLS != nil && tenantReq.TLS.Crt != nil && tenantReq.TLS.Key != nil {
|
||||
encryption = true
|
||||
externalTLSCertificateSecretName := fmt.Sprintf("%s-instance-external-certificates", secretName)
|
||||
// disable autoCert
|
||||
minInst.Spec.RequestAutoCert = false
|
||||
|
||||
tlsCrt, err := base64.StdEncoding.DecodeString(*params.Body.TLS.Crt)
|
||||
tlsCrt, err := base64.StdEncoding.DecodeString(*tenantReq.TLS.Crt)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
tlsKey, err := base64.StdEncoding.DecodeString(*params.Body.TLS.Key)
|
||||
tlsKey, err := base64.StdEncoding.DecodeString(*tenantReq.TLS.Key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -482,7 +512,7 @@ func getTenantCreatedResponse(session *models.Principal, params admin_api.Create
|
||||
"tls.key": tlsKey,
|
||||
},
|
||||
}
|
||||
_, err = clientset.CoreV1().Secrets(ns).Create(context.Background(), &externalTLSCertificateSecret, metav1.CreateOptions{})
|
||||
_, err = clientset.CoreV1().Secrets(ns).Create(ctx, &externalTLSCertificateSecret, metav1.CreateOptions{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -493,19 +523,19 @@ func getTenantCreatedResponse(session *models.Principal, params admin_api.Create
|
||||
}
|
||||
}
|
||||
|
||||
if params.Body.Encryption != nil && encryption {
|
||||
if tenantReq.Encryption != nil && encryption {
|
||||
// Enable auto encryption
|
||||
minInst.Spec.Env = append(minInst.Spec.Env, corev1.EnvVar{
|
||||
Name: "MINIO_KMS_AUTO_ENCRYPTION",
|
||||
Value: "on",
|
||||
})
|
||||
|
||||
if params.Body.Encryption.MasterKey != "" {
|
||||
if tenantReq.Encryption.MasterKey != "" {
|
||||
// Configure MinIO to use MINIO_KMS_MASTER_KEY legacy key
|
||||
// https://docs.min.io/docs/minio-vault-legacy.html
|
||||
minInst.Spec.Env = append(minInst.Spec.Env, corev1.EnvVar{
|
||||
Name: "MINIO_KMS_MASTER_KEY",
|
||||
Value: params.Body.Encryption.MasterKey,
|
||||
Value: tenantReq.Encryption.MasterKey,
|
||||
})
|
||||
} else {
|
||||
// KES configuration for Tenant instance
|
||||
@@ -515,16 +545,16 @@ func getTenantCreatedResponse(session *models.Principal, params admin_api.Create
|
||||
Metadata: nil,
|
||||
}
|
||||
// Using custom image for KES
|
||||
if params.Body.Encryption.Image != "" {
|
||||
minInst.Spec.KES.Image = params.Body.Encryption.Image
|
||||
if tenantReq.Encryption.Image != "" {
|
||||
minInst.Spec.KES.Image = tenantReq.Encryption.Image
|
||||
}
|
||||
// Secret to store KES server TLS certificates
|
||||
// TODO check if AutoCert it's already configured
|
||||
serverTLSCrt, err := base64.StdEncoding.DecodeString(*params.Body.Encryption.Server.Crt)
|
||||
serverTLSCrt, err := base64.StdEncoding.DecodeString(*tenantReq.Encryption.Server.Crt)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
serverTLSKey, err := base64.StdEncoding.DecodeString(*params.Body.Encryption.Server.Key)
|
||||
serverTLSKey, err := base64.StdEncoding.DecodeString(*tenantReq.Encryption.Server.Key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -540,7 +570,7 @@ func getTenantCreatedResponse(session *models.Principal, params admin_api.Create
|
||||
"tls.key": serverTLSKey,
|
||||
},
|
||||
}
|
||||
_, err = clientset.CoreV1().Secrets(ns).Create(context.Background(), &kesExternalCertificateSecret, metav1.CreateOptions{})
|
||||
_, err = clientset.CoreV1().Secrets(ns).Create(ctx, &kesExternalCertificateSecret, metav1.CreateOptions{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -551,11 +581,11 @@ func getTenantCreatedResponse(session *models.Principal, params admin_api.Create
|
||||
}
|
||||
|
||||
// Secret to store KES clients TLS certificates (mTLS authentication)
|
||||
clientTLSCrt, err := base64.StdEncoding.DecodeString(*params.Body.Encryption.Client.Crt)
|
||||
clientTLSCrt, err := base64.StdEncoding.DecodeString(*tenantReq.Encryption.Client.Crt)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
clientTLSKey, err := base64.StdEncoding.DecodeString(*params.Body.Encryption.Client.Key)
|
||||
clientTLSKey, err := base64.StdEncoding.DecodeString(*tenantReq.Encryption.Client.Key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -571,7 +601,7 @@ func getTenantCreatedResponse(session *models.Principal, params admin_api.Create
|
||||
"tls.key": clientTLSKey,
|
||||
},
|
||||
}
|
||||
_, err = clientset.CoreV1().Secrets(ns).Create(context.Background(), &instanceExternalClientCertificateSecret, metav1.CreateOptions{})
|
||||
_, err = clientset.CoreV1().Secrets(ns).Create(ctx, &instanceExternalClientCertificateSecret, metav1.CreateOptions{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -621,66 +651,66 @@ func getTenantCreatedResponse(session *models.Principal, params admin_api.Create
|
||||
Keys: kes.Keys{},
|
||||
}
|
||||
// if encryption is enabled and encryption is configured to use Vault
|
||||
if params.Body.Encryption.Vault != nil {
|
||||
if tenantReq.Encryption.Vault != nil {
|
||||
// Initialize Vault Config
|
||||
kesConfig.Keys.Vault = &kes.Vault{
|
||||
Endpoint: *params.Body.Encryption.Vault.Endpoint,
|
||||
EnginePath: params.Body.Encryption.Vault.Engine,
|
||||
Namespace: params.Body.Encryption.Vault.Namespace,
|
||||
Prefix: params.Body.Encryption.Vault.Prefix,
|
||||
Endpoint: *tenantReq.Encryption.Vault.Endpoint,
|
||||
EnginePath: tenantReq.Encryption.Vault.Engine,
|
||||
Namespace: tenantReq.Encryption.Vault.Namespace,
|
||||
Prefix: tenantReq.Encryption.Vault.Prefix,
|
||||
Status: &kes.VaultStatus{
|
||||
Ping: 10 * time.Second,
|
||||
},
|
||||
}
|
||||
// Vault AppRole credentials
|
||||
if params.Body.Encryption.Vault.Approle != nil {
|
||||
if tenantReq.Encryption.Vault.Approle != nil {
|
||||
kesConfig.Keys.Vault.AppRole = &kes.AppRole{
|
||||
EnginePath: params.Body.Encryption.Vault.Approle.Engine,
|
||||
ID: *params.Body.Encryption.Vault.Approle.ID,
|
||||
Secret: *params.Body.Encryption.Vault.Approle.Secret,
|
||||
EnginePath: tenantReq.Encryption.Vault.Approle.Engine,
|
||||
ID: *tenantReq.Encryption.Vault.Approle.ID,
|
||||
Secret: *tenantReq.Encryption.Vault.Approle.Secret,
|
||||
Retry: 15 * time.Second,
|
||||
}
|
||||
} else {
|
||||
return nil, errors.New("approle credentials missing for kes")
|
||||
}
|
||||
} else if params.Body.Encryption.Aws != nil {
|
||||
} else if tenantReq.Encryption.Aws != nil {
|
||||
// Initialize AWS
|
||||
kesConfig.Keys.Aws = &kes.Aws{
|
||||
SecretsManager: &kes.AwsSecretManager{},
|
||||
}
|
||||
// AWS basic configuration
|
||||
if params.Body.Encryption.Aws.Secretsmanager != nil {
|
||||
kesConfig.Keys.Aws.SecretsManager.Endpoint = *params.Body.Encryption.Aws.Secretsmanager.Endpoint
|
||||
kesConfig.Keys.Aws.SecretsManager.Region = *params.Body.Encryption.Aws.Secretsmanager.Region
|
||||
kesConfig.Keys.Aws.SecretsManager.KmsKey = params.Body.Encryption.Aws.Secretsmanager.Kmskey
|
||||
if tenantReq.Encryption.Aws.Secretsmanager != nil {
|
||||
kesConfig.Keys.Aws.SecretsManager.Endpoint = *tenantReq.Encryption.Aws.Secretsmanager.Endpoint
|
||||
kesConfig.Keys.Aws.SecretsManager.Region = *tenantReq.Encryption.Aws.Secretsmanager.Region
|
||||
kesConfig.Keys.Aws.SecretsManager.KmsKey = tenantReq.Encryption.Aws.Secretsmanager.Kmskey
|
||||
// AWS credentials
|
||||
if params.Body.Encryption.Aws.Secretsmanager.Credentials != nil {
|
||||
if tenantReq.Encryption.Aws.Secretsmanager.Credentials != nil {
|
||||
kesConfig.Keys.Aws.SecretsManager.Login = &kes.AwsSecretManagerLogin{
|
||||
AccessKey: *params.Body.Encryption.Aws.Secretsmanager.Credentials.Accesskey,
|
||||
SecretKey: *params.Body.Encryption.Aws.Secretsmanager.Credentials.Secretkey,
|
||||
SessionToken: params.Body.Encryption.Aws.Secretsmanager.Credentials.Token,
|
||||
AccessKey: *tenantReq.Encryption.Aws.Secretsmanager.Credentials.Accesskey,
|
||||
SecretKey: *tenantReq.Encryption.Aws.Secretsmanager.Credentials.Secretkey,
|
||||
SessionToken: tenantReq.Encryption.Aws.Secretsmanager.Credentials.Token,
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if params.Body.Encryption.Gemalto != nil {
|
||||
} else if tenantReq.Encryption.Gemalto != nil {
|
||||
// Initialize Gemalto
|
||||
kesConfig.Keys.Gemalto = &kes.Gemalto{
|
||||
KeySecure: &kes.GemaltoKeySecure{},
|
||||
}
|
||||
// Gemalto Configuration
|
||||
if params.Body.Encryption.Gemalto.Keysecure != nil {
|
||||
kesConfig.Keys.Gemalto.KeySecure.Endpoint = *params.Body.Encryption.Gemalto.Keysecure.Endpoint
|
||||
if tenantReq.Encryption.Gemalto.Keysecure != nil {
|
||||
kesConfig.Keys.Gemalto.KeySecure.Endpoint = *tenantReq.Encryption.Gemalto.Keysecure.Endpoint
|
||||
// Gemalto TLS configuration
|
||||
if params.Body.Encryption.Gemalto.Keysecure.TLS != nil {
|
||||
if tenantReq.Encryption.Gemalto.Keysecure.TLS != nil {
|
||||
kesConfig.Keys.Gemalto.KeySecure.TLS = &kes.GemaltoTLS{
|
||||
CAPath: *params.Body.Encryption.Gemalto.Keysecure.TLS.Ca,
|
||||
CAPath: *tenantReq.Encryption.Gemalto.Keysecure.TLS.Ca,
|
||||
}
|
||||
}
|
||||
// Gemalto Login
|
||||
if params.Body.Encryption.Gemalto.Keysecure.Credentials != nil {
|
||||
if tenantReq.Encryption.Gemalto.Keysecure.Credentials != nil {
|
||||
kesConfig.Keys.Gemalto.KeySecure.Credentials = &kes.GemaltoCredentials{
|
||||
Token: *params.Body.Encryption.Gemalto.Keysecure.Credentials.Token,
|
||||
Domain: *params.Body.Encryption.Gemalto.Keysecure.Credentials.Domain,
|
||||
Token: *tenantReq.Encryption.Gemalto.Keysecure.Credentials.Token,
|
||||
Domain: *tenantReq.Encryption.Gemalto.Keysecure.Credentials.Domain,
|
||||
Retry: 15 * time.Second,
|
||||
}
|
||||
}
|
||||
@@ -702,7 +732,7 @@ func getTenantCreatedResponse(session *models.Principal, params admin_api.Create
|
||||
"server-config.yaml": serverConfigYaml,
|
||||
},
|
||||
}
|
||||
_, err = clientset.CoreV1().Secrets(ns).Create(context.Background(), &kesConfigurationSecret, metav1.CreateOptions{})
|
||||
_, err = clientset.CoreV1().Secrets(ns).Create(ctx, &kesConfigurationSecret, metav1.CreateOptions{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -718,12 +748,12 @@ func getTenantCreatedResponse(session *models.Principal, params admin_api.Create
|
||||
var consoleSecret string
|
||||
|
||||
enableConsole := true
|
||||
if params.Body.EnableConsole != nil {
|
||||
enableConsole = *params.Body.EnableConsole
|
||||
if tenantReq.EnableConsole != nil {
|
||||
enableConsole = *tenantReq.EnableConsole
|
||||
}
|
||||
|
||||
if enableConsole {
|
||||
consoleSelector := fmt.Sprintf("%s-console", *params.Body.Name)
|
||||
consoleSelector := fmt.Sprintf("%s-console", *tenantReq.Name)
|
||||
consoleSecretName := fmt.Sprintf("%s-secret", consoleSelector)
|
||||
consoleAccess = RandomCharString(16)
|
||||
consoleSecret = RandomCharString(32)
|
||||
@@ -743,10 +773,10 @@ func getTenantCreatedResponse(session *models.Principal, params admin_api.Create
|
||||
}
|
||||
|
||||
// Enable IDP (Open ID Connect) for console
|
||||
if !idpEnabled && params.Body.Idp != nil && params.Body.Idp.Oidc != nil {
|
||||
url := *params.Body.Idp.Oidc.URL
|
||||
clientID := *params.Body.Idp.Oidc.ClientID
|
||||
secretID := *params.Body.Idp.Oidc.SecretID
|
||||
if !idpEnabled && tenantReq.Idp != nil && tenantReq.Idp.Oidc != nil {
|
||||
url := *tenantReq.Idp.Oidc.URL
|
||||
clientID := *tenantReq.Idp.Oidc.ClientID
|
||||
secretID := *tenantReq.Idp.Oidc.SecretID
|
||||
if url != "" && clientID != "" && secretID != "" {
|
||||
instanceSecret.Data["CONSOLE_IDP_URL"] = []byte(url)
|
||||
instanceSecret.Data["CONSOLE_IDP_CLIENT_ID"] = []byte(clientID)
|
||||
@@ -763,12 +793,12 @@ func getTenantCreatedResponse(session *models.Principal, params admin_api.Create
|
||||
}
|
||||
}
|
||||
|
||||
_, err = clientset.CoreV1().Secrets(ns).Create(context.Background(), &instanceSecret, metav1.CreateOptions{})
|
||||
_, err = clientset.CoreV1().Secrets(ns).Create(ctx, &instanceSecret, metav1.CreateOptions{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
const consoleVersion = "minio/console:v0.3.4"
|
||||
const consoleVersion = "minio/console:v0.3.7"
|
||||
minInst.Spec.Console = &operator.ConsoleConfiguration{
|
||||
Replicas: 2,
|
||||
Image: consoleVersion,
|
||||
@@ -782,11 +812,11 @@ func getTenantCreatedResponse(session *models.Principal, params admin_api.Create
|
||||
}
|
||||
|
||||
// set the service name if provided
|
||||
if params.Body.ServiceName != "" {
|
||||
minInst.Spec.ServiceName = params.Body.ServiceName
|
||||
if tenantReq.ServiceName != "" {
|
||||
minInst.Spec.ServiceName = tenantReq.ServiceName
|
||||
}
|
||||
// set the zones if they are provided
|
||||
for _, zone := range params.Body.Zones {
|
||||
for _, zone := range tenantReq.Zones {
|
||||
zone, err := parseTenantZoneRequest(zone)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -795,15 +825,24 @@ func getTenantCreatedResponse(session *models.Principal, params admin_api.Create
|
||||
}
|
||||
|
||||
// Set Mount Path if provided
|
||||
if params.Body.MounthPath != "" {
|
||||
minInst.Spec.Mountpath = params.Body.MounthPath
|
||||
if tenantReq.MounthPath != "" {
|
||||
minInst.Spec.Mountpath = tenantReq.MounthPath
|
||||
}
|
||||
// add annotations
|
||||
if len(params.Body.Annotations) > 0 {
|
||||
if len(tenantReq.Annotations) > 0 {
|
||||
if minInst.Spec.Metadata == nil {
|
||||
minInst.Spec.Metadata = &metav1.ObjectMeta{}
|
||||
}
|
||||
minInst.Spec.Metadata.Annotations = params.Body.Annotations
|
||||
minInst.Spec.Metadata.Annotations = tenantReq.Annotations
|
||||
}
|
||||
|
||||
if err := setImageRegistry(ctx, tenantReq.ImageRegistry, clientset.CoreV1(), ns); err != nil {
|
||||
log.Println("error setting image registry secret:", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
minInst.Spec.ImagePullSecret = corev1.LocalObjectReference{
|
||||
Name: minioRegCred,
|
||||
}
|
||||
|
||||
opClient, err := cluster.OperatorClient(session.SessionToken)
|
||||
@@ -818,7 +857,7 @@ func getTenantCreatedResponse(session *models.Principal, params admin_api.Create
|
||||
|
||||
// Integratrions
|
||||
if os.Getenv("GKE_INTEGRATION") != "" {
|
||||
err := gkeIntegration(clientset, *params.Body.Name, ns, session.SessionToken)
|
||||
err := gkeIntegration(clientset, *tenantReq.Name, ns, session.SessionToken)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -829,24 +868,84 @@ func getTenantCreatedResponse(session *models.Principal, params admin_api.Create
|
||||
}
|
||||
// Attach Console Credentials
|
||||
if enableConsole {
|
||||
response.Console = &models.CreateTenantResponseConsole{}
|
||||
response.Console.AccessKey = consoleAccess
|
||||
response.Console.SecretKey = consoleSecret
|
||||
response.Console = &models.CreateTenantResponseConsole{
|
||||
AccessKey: consoleAccess,
|
||||
SecretKey: consoleSecret,
|
||||
}
|
||||
}
|
||||
return response, nil
|
||||
}
|
||||
|
||||
func setImageRegistry(ctx context.Context, req *models.ImageRegistry, clientset v1.CoreV1Interface, namespace string) error {
|
||||
if req == nil || req.Registry == nil || req.Username == nil || req.Password == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
credentials := make(map[string]imageRegistryCredentials)
|
||||
// username:password encoded
|
||||
authData := []byte(fmt.Sprintf("%s:%s", *req.Username, *req.Password))
|
||||
authStr := base64.StdEncoding.EncodeToString(authData)
|
||||
|
||||
credentials[*req.Registry] = imageRegistryCredentials{
|
||||
Username: *req.Username,
|
||||
Password: *req.Password,
|
||||
Auth: authStr,
|
||||
}
|
||||
imRegistry := imageRegistry{
|
||||
Auths: credentials,
|
||||
}
|
||||
imRegistryJSON, err := json.Marshal(imRegistry)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
instanceSecret := corev1.Secret{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: minioRegCred,
|
||||
},
|
||||
Data: map[string][]byte{
|
||||
corev1.DockerConfigJsonKey: []byte(string(imRegistryJSON)),
|
||||
},
|
||||
Type: corev1.SecretTypeDockerConfigJson,
|
||||
}
|
||||
|
||||
// Get or Create secret if it doesn't exist
|
||||
_, err = clientset.Secrets(namespace).Get(ctx, minioRegCred, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
if k8sErrors.IsNotFound(err) {
|
||||
_, err = clientset.Secrets(namespace).Create(ctx, &instanceSecret, metav1.CreateOptions{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
}
|
||||
_, err = clientset.Secrets(namespace).Update(ctx, &instanceSecret, metav1.UpdateOptions{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// updateTenantAction does an update on the minioTenant by patching the desired changes
|
||||
func updateTenantAction(ctx context.Context, operatorClient OperatorClient, httpCl cluster.HTTPClientI, nameSpace string, params admin_api.UpdateTenantParams) error {
|
||||
func updateTenantAction(ctx context.Context, operatorClient OperatorClient, clientset v1.CoreV1Interface, httpCl cluster.HTTPClientI, namespace string, params admin_api.UpdateTenantParams) error {
|
||||
imageToUpdate := params.Body.Image
|
||||
minInst, err := operatorClient.TenantGet(ctx, nameSpace, params.Tenant, metav1.GetOptions{})
|
||||
imageRegistryReq := params.Body.ImageRegistry
|
||||
|
||||
if err := setImageRegistry(ctx, imageRegistryReq, clientset, namespace); err != nil {
|
||||
log.Println("error setting image registry secret:", err)
|
||||
return err
|
||||
}
|
||||
|
||||
minInst, err := operatorClient.TenantGet(ctx, namespace, params.Tenant, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// if image to update is empty we'll use the latest image by default
|
||||
if strings.TrimSpace(imageToUpdate) != "" {
|
||||
minInst.Spec.Image = params.Body.Image
|
||||
minInst.Spec.Image = imageToUpdate
|
||||
} else {
|
||||
im, err := cluster.GetLatestMinioImage(httpCl)
|
||||
if err != nil {
|
||||
@@ -859,7 +958,7 @@ func updateTenantAction(ctx context.Context, operatorClient OperatorClient, http
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = operatorClient.TenantPatch(ctx, nameSpace, minInst.Name, types.MergePatchType, payloadBytes, metav1.PatchOptions{})
|
||||
_, err = operatorClient.TenantPatch(ctx, namespace, minInst.Name, types.MergePatchType, payloadBytes, metav1.PatchOptions{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -873,6 +972,11 @@ func getUpdateTenantResponse(session *models.Principal, params admin_api.UpdateT
|
||||
log.Println("error getting operator client:", err)
|
||||
return err
|
||||
}
|
||||
// get Kubernetes Client
|
||||
clientset, err := cluster.K8sClient(session.SessionToken)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
opClient := &operatorClient{
|
||||
client: opClientClientSet,
|
||||
@@ -882,7 +986,8 @@ func getUpdateTenantResponse(session *models.Principal, params admin_api.UpdateT
|
||||
Timeout: 4 * time.Second,
|
||||
},
|
||||
}
|
||||
if err := updateTenantAction(ctx, opClient, httpC, params.Namespace, params); err != nil {
|
||||
|
||||
if err := updateTenantAction(ctx, opClient, clientset.CoreV1(), httpC, params.Namespace, params); err != nil {
|
||||
log.Println("error patching Tenant:", err)
|
||||
return err
|
||||
}
|
||||
@@ -939,6 +1044,7 @@ func getTenantUsageResponse(session *models.Principal, params admin_api.GetTenan
|
||||
|
||||
opClientClientSet, err := cluster.OperatorClient(session.SessionToken)
|
||||
if err != nil {
|
||||
log.Println("error operator client", err)
|
||||
return nil, err
|
||||
}
|
||||
clientset, err := cluster.K8sClient(session.SessionToken)
|
||||
@@ -989,7 +1095,7 @@ func getTenantUsageResponse(session *models.Principal, params admin_api.GetTenan
|
||||
log.Println("error getting admin info:", err)
|
||||
return nil, err
|
||||
}
|
||||
info := &models.TenantUsage{UsedSize: adminInfo.Usage}
|
||||
info := &models.TenantUsage{Used: adminInfo.Usage, DiskUsed: adminInfo.DisksUsage}
|
||||
return info, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -35,7 +35,9 @@ import (
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/api/resource"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
types "k8s.io/apimachinery/pkg/types"
|
||||
"k8s.io/client-go/kubernetes/fake"
|
||||
)
|
||||
|
||||
var opClientTenantDeleteMock func(ctx context.Context, namespace string, tenantName string, options metav1.DeleteOptions) error
|
||||
@@ -573,6 +575,7 @@ func Test_UpdateTenantAction(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
objs []runtime.Object
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
@@ -708,8 +711,9 @@ func Test_UpdateTenantAction(t *testing.T) {
|
||||
opClientTenantGetMock = tt.args.mockTenantGet
|
||||
opClientTenantPatchMock = tt.args.mockTenantPatch
|
||||
httpClientGetMock = tt.args.mockHTTPClientGet
|
||||
cnsClient := fake.NewSimpleClientset(tt.objs...)
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if err := updateTenantAction(tt.args.ctx, tt.args.operatorClient, tt.args.httpCl, tt.args.nameSpace, tt.args.params); (err != nil) != tt.wantErr {
|
||||
if err := updateTenantAction(tt.args.ctx, tt.args.operatorClient, cnsClient.CoreV1(), tt.args.httpCl, tt.args.nameSpace, tt.args.params); (err != nil) != tt.wantErr {
|
||||
t.Errorf("deleteTenantAction() error = %v, wantErr %v", err, tt.wantErr)
|
||||
}
|
||||
})
|
||||
|
||||
@@ -2036,6 +2036,9 @@ func init() {
|
||||
"type": "object",
|
||||
"$ref": "#/definitions/encryptionConfiguration"
|
||||
},
|
||||
"erasureCodingParity": {
|
||||
"type": "integer"
|
||||
},
|
||||
"idp": {
|
||||
"type": "object",
|
||||
"$ref": "#/definitions/idpConfiguration"
|
||||
@@ -2043,6 +2046,9 @@ func init() {
|
||||
"image": {
|
||||
"type": "string"
|
||||
},
|
||||
"image_registry": {
|
||||
"$ref": "#/definitions/imageRegistry"
|
||||
},
|
||||
"mounth_path": {
|
||||
"type": "string"
|
||||
},
|
||||
@@ -2289,6 +2295,25 @@ func init() {
|
||||
}
|
||||
}
|
||||
},
|
||||
"imageRegistry": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"registry",
|
||||
"username",
|
||||
"password"
|
||||
],
|
||||
"properties": {
|
||||
"password": {
|
||||
"type": "string"
|
||||
},
|
||||
"registry": {
|
||||
"type": "string"
|
||||
},
|
||||
"username": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"listBucketEventsResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@@ -3000,7 +3025,11 @@ func init() {
|
||||
"tenantUsage": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"used_size": {
|
||||
"disk_used": {
|
||||
"type": "integer",
|
||||
"format": "int64"
|
||||
},
|
||||
"used": {
|
||||
"type": "integer",
|
||||
"format": "int64"
|
||||
}
|
||||
@@ -3045,6 +3074,9 @@ func init() {
|
||||
"image": {
|
||||
"type": "string",
|
||||
"pattern": "^((.*?)/(.*?):(.+))$"
|
||||
},
|
||||
"image_registry": {
|
||||
"$ref": "#/definitions/imageRegistry"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -5923,6 +5955,9 @@ func init() {
|
||||
"type": "object",
|
||||
"$ref": "#/definitions/encryptionConfiguration"
|
||||
},
|
||||
"erasureCodingParity": {
|
||||
"type": "integer"
|
||||
},
|
||||
"idp": {
|
||||
"type": "object",
|
||||
"$ref": "#/definitions/idpConfiguration"
|
||||
@@ -5930,6 +5965,9 @@ func init() {
|
||||
"image": {
|
||||
"type": "string"
|
||||
},
|
||||
"image_registry": {
|
||||
"$ref": "#/definitions/imageRegistry"
|
||||
},
|
||||
"mounth_path": {
|
||||
"type": "string"
|
||||
},
|
||||
@@ -6176,6 +6214,25 @@ func init() {
|
||||
}
|
||||
}
|
||||
},
|
||||
"imageRegistry": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"registry",
|
||||
"username",
|
||||
"password"
|
||||
],
|
||||
"properties": {
|
||||
"password": {
|
||||
"type": "string"
|
||||
},
|
||||
"registry": {
|
||||
"type": "string"
|
||||
},
|
||||
"username": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"listBucketEventsResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@@ -6821,7 +6878,11 @@ func init() {
|
||||
"tenantUsage": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"used_size": {
|
||||
"disk_used": {
|
||||
"type": "integer",
|
||||
"format": "int64"
|
||||
},
|
||||
"used": {
|
||||
"type": "integer",
|
||||
"format": "int64"
|
||||
}
|
||||
@@ -6866,6 +6927,9 @@ func init() {
|
||||
"image": {
|
||||
"type": "string",
|
||||
"pattern": "^((.*?)/(.*?):(.+))$"
|
||||
},
|
||||
"image_registry": {
|
||||
"$ref": "#/definitions/imageRegistry"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
27
swagger.yml
27
swagger.yml
@@ -1733,7 +1733,10 @@ definitions:
|
||||
tenantUsage:
|
||||
type: object
|
||||
properties:
|
||||
used_size:
|
||||
used:
|
||||
type: integer
|
||||
format: int64
|
||||
disk_used:
|
||||
type: integer
|
||||
format: int64
|
||||
|
||||
@@ -1768,12 +1771,30 @@ definitions:
|
||||
type: integer
|
||||
format: int64
|
||||
title: number of tenants accessible to tenant user
|
||||
|
||||
updateTenantRequest:
|
||||
type: object
|
||||
properties:
|
||||
image:
|
||||
type: string
|
||||
pattern: "^((.*?)/(.*?):(.+))$"
|
||||
image_registry:
|
||||
$ref: "#/definitions/imageRegistry"
|
||||
|
||||
imageRegistry:
|
||||
type: object
|
||||
required:
|
||||
- registry
|
||||
- username
|
||||
- password
|
||||
properties:
|
||||
registry:
|
||||
type: string
|
||||
username:
|
||||
type: string
|
||||
password:
|
||||
type: string
|
||||
|
||||
createTenantRequest:
|
||||
type: object
|
||||
required:
|
||||
@@ -1806,10 +1827,14 @@ definitions:
|
||||
default: true
|
||||
namespace:
|
||||
type: string
|
||||
erasureCodingParity:
|
||||
type: integer
|
||||
annotations:
|
||||
type: object
|
||||
additionalProperties:
|
||||
type: string
|
||||
image_registry:
|
||||
$ref: "#/definitions/imageRegistry"
|
||||
idp:
|
||||
type: object
|
||||
$ref: "#/definitions/idpConfiguration"
|
||||
|
||||
Reference in New Issue
Block a user