Compare commits
8 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
858d363e97 | ||
|
|
47704189d1 | ||
|
|
b72d424ec9 | ||
|
|
86426e95f7 | ||
|
|
e5f7870f5e | ||
|
|
c0ee739624 | ||
|
|
1dc99498d9 | ||
|
|
319d96c725 |
2
go.mod
2
go.mod
@@ -19,7 +19,7 @@ require (
|
||||
github.com/minio/mc v0.0.0-20200808005614-7e52c104bee1
|
||||
github.com/minio/minio v0.0.0-20200808024306-2a9819aff876
|
||||
github.com/minio/minio-go/v7 v7.0.5-0.20200807085956-d7db33ea7618
|
||||
github.com/minio/operator v0.0.0-20200904194631-b8aa01dc5d70
|
||||
github.com/minio/operator v0.0.0-20200922064400-af3315add727
|
||||
github.com/pquerna/cachecontrol v0.0.0-20180517163645-1555304b9b35 // indirect
|
||||
github.com/secure-io/sio-go v0.3.1
|
||||
github.com/stretchr/testify v1.6.1
|
||||
|
||||
6
go.sum
6
go.sum
@@ -781,8 +781,10 @@ github.com/minio/minio-go/v7 v7.0.2/go.mod h1:dJ80Mv2HeGkYLH1sqS/ksz07ON6csH3S6J
|
||||
github.com/minio/minio-go/v7 v7.0.3/go.mod h1:TA0CQCjJZHM5SJj9IjqR0NmpmQJ6bCbXifAJ3mUU6Hw=
|
||||
github.com/minio/minio-go/v7 v7.0.5-0.20200807085956-d7db33ea7618 h1:8iTb0TFs6kDGAUnhI/s2QCZOYcSTtYmY9dF+Cbc0WJo=
|
||||
github.com/minio/minio-go/v7 v7.0.5-0.20200807085956-d7db33ea7618/go.mod h1:CSt2ETZNs+bIIhWTse0mcZKZWMGrFU7Er7RR0TmkDYk=
|
||||
github.com/minio/operator v0.0.0-20200904194631-b8aa01dc5d70 h1:FjyhnnrOHMzhJryqNoOISgp8p1dmmn1IMOlgBAaf8r4=
|
||||
github.com/minio/operator v0.0.0-20200904194631-b8aa01dc5d70/go.mod h1:NVl1+c7TYxJB22opK/m2L5SkTvlEYd1ZFPuL6SX5fCg=
|
||||
github.com/minio/operator v0.0.0-20200921211523-69f9eef5b7b5 h1:yQ7WHA2wbTTGHz0Z4xXSRxfUTm5fafM0ajvlZlQ2Zl4=
|
||||
github.com/minio/operator v0.0.0-20200921211523-69f9eef5b7b5/go.mod h1:6lavbNo2YuJWeQR5bZYsEWdbpRCO2KrTyfQ0PtC/AN4=
|
||||
github.com/minio/operator v0.0.0-20200922064400-af3315add727 h1:MN8Knn7yxrd76Y3uL38DZh4RhihTZTck5u51NoEar/c=
|
||||
github.com/minio/operator v0.0.0-20200922064400-af3315add727/go.mod h1:6lavbNo2YuJWeQR5bZYsEWdbpRCO2KrTyfQ0PtC/AN4=
|
||||
github.com/minio/selfupdate v0.3.1 h1:BWEFSNnrZVMUWXbXIgLDNDjbejkmpAmZvy/nCz1HlEs=
|
||||
github.com/minio/selfupdate v0.3.1/go.mod h1:b8ThJzzH7u2MkF6PcIra7KaXO9Khf6alWPvMSyTDCFM=
|
||||
github.com/minio/sha256-simd v0.1.1 h1:5QHSlgo3nt5yKOJrC7W8w7X+NFl8cMPZm96iu8kKUJU=
|
||||
|
||||
@@ -7,7 +7,6 @@ rules:
|
||||
- ""
|
||||
resources:
|
||||
- namespaces
|
||||
- secrets
|
||||
- pods
|
||||
- services
|
||||
- events
|
||||
@@ -18,6 +17,18 @@ rules:
|
||||
- create
|
||||
- list
|
||||
- patch
|
||||
- apiGroups:
|
||||
- ""
|
||||
resources:
|
||||
- secrets
|
||||
verbs:
|
||||
- get
|
||||
- watch
|
||||
- create
|
||||
- list
|
||||
- patch
|
||||
- deletecollection
|
||||
- delete
|
||||
- apiGroups:
|
||||
- "storage.k8s.io"
|
||||
resources:
|
||||
|
||||
@@ -15,7 +15,7 @@ spec:
|
||||
serviceAccountName: console-sa
|
||||
containers:
|
||||
- name: console
|
||||
image: minio/console:v0.3.24
|
||||
image: minio/console:v0.3.26
|
||||
imagePullPolicy: "IfNotPresent"
|
||||
args:
|
||||
- server
|
||||
|
||||
@@ -15,7 +15,7 @@ spec:
|
||||
serviceAccountName: console-sa
|
||||
containers:
|
||||
- name: console
|
||||
image: minio/console:v0.3.24
|
||||
image: minio/console:v0.3.26
|
||||
imagePullPolicy: "IfNotPresent"
|
||||
env:
|
||||
- name: CONSOLE_OPERATOR_MODE
|
||||
|
||||
@@ -8,4 +8,4 @@ resources:
|
||||
- console-configmap.yaml
|
||||
- console-service.yaml
|
||||
- console-deployment.yaml
|
||||
- https://github.com/minio/operator/?ref=v3.0.10
|
||||
- https://github.com/minio/operator/?ref=v3.0.19
|
||||
|
||||
117
models/console_configuration.go
Normal file
117
models/console_configuration.go
Normal file
@@ -0,0 +1,117 @@
|
||||
// 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"
|
||||
)
|
||||
|
||||
// ConsoleConfiguration console configuration
|
||||
//
|
||||
// swagger:model consoleConfiguration
|
||||
type ConsoleConfiguration struct {
|
||||
MetadataFields
|
||||
|
||||
// image
|
||||
Image string `json:"image,omitempty"`
|
||||
}
|
||||
|
||||
// UnmarshalJSON unmarshals this object from a JSON structure
|
||||
func (m *ConsoleConfiguration) UnmarshalJSON(raw []byte) error {
|
||||
// AO0
|
||||
var aO0 MetadataFields
|
||||
if err := swag.ReadJSON(raw, &aO0); err != nil {
|
||||
return err
|
||||
}
|
||||
m.MetadataFields = aO0
|
||||
|
||||
// AO1
|
||||
var dataAO1 struct {
|
||||
Image string `json:"image,omitempty"`
|
||||
}
|
||||
if err := swag.ReadJSON(raw, &dataAO1); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
m.Image = dataAO1.Image
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// MarshalJSON marshals this object to a JSON structure
|
||||
func (m ConsoleConfiguration) MarshalJSON() ([]byte, error) {
|
||||
_parts := make([][]byte, 0, 2)
|
||||
|
||||
aO0, err := swag.WriteJSON(m.MetadataFields)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
_parts = append(_parts, aO0)
|
||||
var dataAO1 struct {
|
||||
Image string `json:"image,omitempty"`
|
||||
}
|
||||
|
||||
dataAO1.Image = m.Image
|
||||
|
||||
jsonDataAO1, errAO1 := swag.WriteJSON(dataAO1)
|
||||
if errAO1 != nil {
|
||||
return nil, errAO1
|
||||
}
|
||||
_parts = append(_parts, jsonDataAO1)
|
||||
return swag.ConcatJSON(_parts...), nil
|
||||
}
|
||||
|
||||
// Validate validates this console configuration
|
||||
func (m *ConsoleConfiguration) Validate(formats strfmt.Registry) error {
|
||||
var res []error
|
||||
|
||||
// validation for a type composition with MetadataFields
|
||||
if err := m.MetadataFields.Validate(formats); err != nil {
|
||||
res = append(res, err)
|
||||
}
|
||||
|
||||
if len(res) > 0 {
|
||||
return errors.CompositeValidationError(res...)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// MarshalBinary interface implementation
|
||||
func (m *ConsoleConfiguration) MarshalBinary() ([]byte, error) {
|
||||
if m == nil {
|
||||
return nil, nil
|
||||
}
|
||||
return swag.WriteJSON(m)
|
||||
}
|
||||
|
||||
// UnmarshalBinary interface implementation
|
||||
func (m *ConsoleConfiguration) UnmarshalBinary(b []byte) error {
|
||||
var res ConsoleConfiguration
|
||||
if err := swag.ReadJSON(b, &res); err != nil {
|
||||
return err
|
||||
}
|
||||
*m = res
|
||||
return nil
|
||||
}
|
||||
@@ -42,6 +42,9 @@ type CreateTenantRequest struct {
|
||||
// annotations
|
||||
Annotations map[string]string `json:"annotations,omitempty"`
|
||||
|
||||
// console
|
||||
Console *ConsoleConfiguration `json:"console,omitempty"`
|
||||
|
||||
// console image
|
||||
ConsoleImage string `json:"console_image,omitempty"`
|
||||
|
||||
@@ -105,6 +108,10 @@ type CreateTenantRequest struct {
|
||||
func (m *CreateTenantRequest) Validate(formats strfmt.Registry) error {
|
||||
var res []error
|
||||
|
||||
if err := m.validateConsole(formats); err != nil {
|
||||
res = append(res, err)
|
||||
}
|
||||
|
||||
if err := m.validateEncryption(formats); err != nil {
|
||||
res = append(res, err)
|
||||
}
|
||||
@@ -139,6 +146,24 @@ func (m *CreateTenantRequest) Validate(formats strfmt.Registry) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *CreateTenantRequest) 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 *CreateTenantRequest) validateEncryption(formats strfmt.Registry) error {
|
||||
|
||||
if swag.IsZero(m.Encryption) { // not required
|
||||
|
||||
@@ -32,6 +32,7 @@ import (
|
||||
//
|
||||
// swagger:model encryptionConfiguration
|
||||
type EncryptionConfiguration struct {
|
||||
MetadataFields
|
||||
|
||||
// aws
|
||||
Aws *AwsConfiguration `json:"aws,omitempty"`
|
||||
@@ -52,10 +53,100 @@ type EncryptionConfiguration struct {
|
||||
Vault *VaultConfiguration `json:"vault,omitempty"`
|
||||
}
|
||||
|
||||
// UnmarshalJSON unmarshals this object from a JSON structure
|
||||
func (m *EncryptionConfiguration) UnmarshalJSON(raw []byte) error {
|
||||
// AO0
|
||||
var aO0 MetadataFields
|
||||
if err := swag.ReadJSON(raw, &aO0); err != nil {
|
||||
return err
|
||||
}
|
||||
m.MetadataFields = aO0
|
||||
|
||||
// AO1
|
||||
var dataAO1 struct {
|
||||
Aws *AwsConfiguration `json:"aws,omitempty"`
|
||||
|
||||
Client *KeyPairConfiguration `json:"client,omitempty"`
|
||||
|
||||
Gemalto *GemaltoConfiguration `json:"gemalto,omitempty"`
|
||||
|
||||
Image string `json:"image,omitempty"`
|
||||
|
||||
Server *KeyPairConfiguration `json:"server,omitempty"`
|
||||
|
||||
Vault *VaultConfiguration `json:"vault,omitempty"`
|
||||
}
|
||||
if err := swag.ReadJSON(raw, &dataAO1); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
m.Aws = dataAO1.Aws
|
||||
|
||||
m.Client = dataAO1.Client
|
||||
|
||||
m.Gemalto = dataAO1.Gemalto
|
||||
|
||||
m.Image = dataAO1.Image
|
||||
|
||||
m.Server = dataAO1.Server
|
||||
|
||||
m.Vault = dataAO1.Vault
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// MarshalJSON marshals this object to a JSON structure
|
||||
func (m EncryptionConfiguration) MarshalJSON() ([]byte, error) {
|
||||
_parts := make([][]byte, 0, 2)
|
||||
|
||||
aO0, err := swag.WriteJSON(m.MetadataFields)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
_parts = append(_parts, aO0)
|
||||
var dataAO1 struct {
|
||||
Aws *AwsConfiguration `json:"aws,omitempty"`
|
||||
|
||||
Client *KeyPairConfiguration `json:"client,omitempty"`
|
||||
|
||||
Gemalto *GemaltoConfiguration `json:"gemalto,omitempty"`
|
||||
|
||||
Image string `json:"image,omitempty"`
|
||||
|
||||
Server *KeyPairConfiguration `json:"server,omitempty"`
|
||||
|
||||
Vault *VaultConfiguration `json:"vault,omitempty"`
|
||||
}
|
||||
|
||||
dataAO1.Aws = m.Aws
|
||||
|
||||
dataAO1.Client = m.Client
|
||||
|
||||
dataAO1.Gemalto = m.Gemalto
|
||||
|
||||
dataAO1.Image = m.Image
|
||||
|
||||
dataAO1.Server = m.Server
|
||||
|
||||
dataAO1.Vault = m.Vault
|
||||
|
||||
jsonDataAO1, errAO1 := swag.WriteJSON(dataAO1)
|
||||
if errAO1 != nil {
|
||||
return nil, errAO1
|
||||
}
|
||||
_parts = append(_parts, jsonDataAO1)
|
||||
return swag.ConcatJSON(_parts...), nil
|
||||
}
|
||||
|
||||
// Validate validates this encryption configuration
|
||||
func (m *EncryptionConfiguration) Validate(formats strfmt.Registry) error {
|
||||
var res []error
|
||||
|
||||
// validation for a type composition with MetadataFields
|
||||
if err := m.MetadataFields.Validate(formats); err != nil {
|
||||
res = append(res, err)
|
||||
}
|
||||
|
||||
if err := m.validateAws(formats); err != nil {
|
||||
res = append(res, err)
|
||||
}
|
||||
|
||||
138
models/metadata_configuration.go
Normal file
138
models/metadata_configuration.go
Normal file
@@ -0,0 +1,138 @@
|
||||
// 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"
|
||||
)
|
||||
|
||||
// MetadataConfiguration metadata configuration
|
||||
//
|
||||
// swagger:model metadataConfiguration
|
||||
type MetadataConfiguration struct {
|
||||
|
||||
// console
|
||||
Console *MetadataFields `json:"console,omitempty"`
|
||||
|
||||
// kes
|
||||
Kes *MetadataFields `json:"kes,omitempty"`
|
||||
|
||||
// minio
|
||||
Minio *MetadataFields `json:"minio,omitempty"`
|
||||
}
|
||||
|
||||
// Validate validates this metadata configuration
|
||||
func (m *MetadataConfiguration) Validate(formats strfmt.Registry) error {
|
||||
var res []error
|
||||
|
||||
if err := m.validateConsole(formats); err != nil {
|
||||
res = append(res, err)
|
||||
}
|
||||
|
||||
if err := m.validateKes(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 *MetadataConfiguration) 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 *MetadataConfiguration) validateKes(formats strfmt.Registry) error {
|
||||
|
||||
if swag.IsZero(m.Kes) { // not required
|
||||
return nil
|
||||
}
|
||||
|
||||
if m.Kes != nil {
|
||||
if err := m.Kes.Validate(formats); err != nil {
|
||||
if ve, ok := err.(*errors.Validation); ok {
|
||||
return ve.ValidateName("kes")
|
||||
}
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *MetadataConfiguration) 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 *MetadataConfiguration) MarshalBinary() ([]byte, error) {
|
||||
if m == nil {
|
||||
return nil, nil
|
||||
}
|
||||
return swag.WriteJSON(m)
|
||||
}
|
||||
|
||||
// UnmarshalBinary interface implementation
|
||||
func (m *MetadataConfiguration) UnmarshalBinary(b []byte) error {
|
||||
var res MetadataConfiguration
|
||||
if err := swag.ReadJSON(b, &res); err != nil {
|
||||
return err
|
||||
}
|
||||
*m = res
|
||||
return nil
|
||||
}
|
||||
66
models/metadata_fields.go
Normal file
66
models/metadata_fields.go
Normal file
@@ -0,0 +1,66 @@
|
||||
// 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/strfmt"
|
||||
"github.com/go-openapi/swag"
|
||||
)
|
||||
|
||||
// MetadataFields metadata fields
|
||||
//
|
||||
// swagger:model metadataFields
|
||||
type MetadataFields struct {
|
||||
|
||||
// annotations
|
||||
Annotations map[string]string `json:"annotations,omitempty"`
|
||||
|
||||
// labels
|
||||
Labels map[string]string `json:"labels,omitempty"`
|
||||
|
||||
// node selector
|
||||
NodeSelector map[string]string `json:"node_selector,omitempty"`
|
||||
}
|
||||
|
||||
// Validate validates this metadata fields
|
||||
func (m *MetadataFields) Validate(formats strfmt.Registry) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// MarshalBinary interface implementation
|
||||
func (m *MetadataFields) MarshalBinary() ([]byte, error) {
|
||||
if m == nil {
|
||||
return nil, nil
|
||||
}
|
||||
return swag.WriteJSON(m)
|
||||
}
|
||||
|
||||
// UnmarshalBinary interface implementation
|
||||
func (m *MetadataFields) UnmarshalBinary(b []byte) error {
|
||||
var res MetadataFields
|
||||
if err := swag.ReadJSON(b, &res); err != nil {
|
||||
return err
|
||||
}
|
||||
*m = res
|
||||
return nil
|
||||
}
|
||||
37
models/parity_response.go
Normal file
37
models/parity_response.go
Normal file
@@ -0,0 +1,37 @@
|
||||
// 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/strfmt"
|
||||
)
|
||||
|
||||
// ParityResponse parity response
|
||||
//
|
||||
// swagger:model parityResponse
|
||||
type ParityResponse []string
|
||||
|
||||
// Validate validates this parity response
|
||||
func (m ParityResponse) Validate(formats strfmt.Registry) error {
|
||||
return nil
|
||||
}
|
||||
@@ -155,10 +155,10 @@ const (
|
||||
// or data key provided as plaintext.
|
||||
//
|
||||
// The returned ciphertext data consists of:
|
||||
// iv | AEAD ID | nonce | encrypted data
|
||||
// 32 1 12 ~ len(data)
|
||||
// AEAD ID | iv | nonce | encrypted data
|
||||
// 1 16 12 ~ len(data)
|
||||
func encrypt(plaintext, associatedData []byte) ([]byte, error) {
|
||||
iv, err := sioutil.Random(32) // 32 bytes IV
|
||||
iv, err := sioutil.Random(16) // 16 bytes IV
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -186,7 +186,7 @@ func encrypt(plaintext, associatedData []byte) ([]byte, error) {
|
||||
}
|
||||
case c20p1305:
|
||||
var sealingKey []byte
|
||||
sealingKey, err = chacha20.HChaCha20(derivedKey, iv[:16]) // HChaCha20 expects nonce of 16 bytes
|
||||
sealingKey, err = chacha20.HChaCha20(derivedKey, iv) // HChaCha20 expects nonce of 16 bytes
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -202,11 +202,11 @@ func encrypt(plaintext, associatedData []byte) ([]byte, error) {
|
||||
|
||||
sealedBytes := aead.Seal(nil, nonce, plaintext, associatedData)
|
||||
|
||||
// ciphertext = iv | AEAD ID | nonce | sealed bytes
|
||||
// ciphertext = AEAD ID | iv | nonce | sealed bytes
|
||||
|
||||
var buf bytes.Buffer
|
||||
buf.Write(iv)
|
||||
buf.WriteByte(algorithm)
|
||||
buf.Write(iv)
|
||||
buf.Write(nonce)
|
||||
buf.Write(sealedBytes)
|
||||
|
||||
@@ -218,16 +218,16 @@ func encrypt(plaintext, associatedData []byte) ([]byte, error) {
|
||||
// and a pbkdf2 derived key
|
||||
func decrypt(ciphertext []byte, associatedData []byte) ([]byte, error) {
|
||||
var (
|
||||
iv [32]byte
|
||||
algorithm [1]byte
|
||||
iv [16]byte
|
||||
nonce [12]byte // This depends on the AEAD but both used ciphers have the same nonce length.
|
||||
)
|
||||
|
||||
r := bytes.NewReader(ciphertext)
|
||||
if _, err := io.ReadFull(r, iv[:]); err != nil {
|
||||
if _, err := io.ReadFull(r, algorithm[:]); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if _, err := io.ReadFull(r, algorithm[:]); err != nil {
|
||||
if _, err := io.ReadFull(r, iv[:]); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if _, err := io.ReadFull(r, nonce[:]); err != nil {
|
||||
@@ -249,7 +249,7 @@ func decrypt(ciphertext []byte, associatedData []byte) ([]byte, error) {
|
||||
return nil, err
|
||||
}
|
||||
case c20p1305:
|
||||
sealingKey, err := chacha20.HChaCha20(derivedKey, iv[:16]) // HChaCha20 expects nonce of 16 bytes
|
||||
sealingKey, err := chacha20.HChaCha20(derivedKey, iv[:]) // HChaCha20 expects nonce of 16 bytes
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
219
pkg/utils/parity.go
Normal file
219
pkg/utils/parity.go
Normal file
@@ -0,0 +1,219 @@
|
||||
// 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 utils
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"sort"
|
||||
|
||||
"github.com/minio/minio/pkg/ellipses"
|
||||
)
|
||||
|
||||
// This file implements and supports ellipses pattern for
|
||||
// `minio server` command line arguments.
|
||||
|
||||
// Supported set sizes this is used to find the optimal
|
||||
// single set size.
|
||||
var setSizes = []uint64{4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}
|
||||
|
||||
// getDivisibleSize - returns a greatest common divisor of
|
||||
// all the ellipses sizes.
|
||||
func getDivisibleSize(totalSizes []uint64) (result uint64) {
|
||||
gcd := func(x, y uint64) uint64 {
|
||||
for y != 0 {
|
||||
x, y = y, x%y
|
||||
}
|
||||
return x
|
||||
}
|
||||
result = totalSizes[0]
|
||||
for i := 1; i < len(totalSizes); i++ {
|
||||
result = gcd(result, totalSizes[i])
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// isValidSetSize - checks whether given count is a valid set size for erasure coding.
|
||||
var isValidSetSize = func(count uint64) bool {
|
||||
return (count >= setSizes[0] && count <= setSizes[len(setSizes)-1])
|
||||
}
|
||||
|
||||
// possibleSetCountsWithSymmetry returns symmetrical setCounts based on the
|
||||
// input argument patterns, the symmetry calculation is to ensure that
|
||||
// we also use uniform number of drives common across all ellipses patterns.
|
||||
func possibleSetCountsWithSymmetry(setCounts []uint64, argPatterns []ellipses.ArgPattern) []uint64 {
|
||||
var newSetCounts = make(map[uint64]struct{})
|
||||
for _, ss := range setCounts {
|
||||
var symmetry bool
|
||||
for _, argPattern := range argPatterns {
|
||||
for _, p := range argPattern {
|
||||
if uint64(len(p.Seq)) > ss {
|
||||
symmetry = uint64(len(p.Seq))%ss == 0
|
||||
} else {
|
||||
symmetry = ss%uint64(len(p.Seq)) == 0
|
||||
}
|
||||
}
|
||||
}
|
||||
// With no arg patterns, it is expected that user knows
|
||||
// the right symmetry, so either ellipses patterns are
|
||||
// provided (recommended) or no ellipses patterns.
|
||||
if _, ok := newSetCounts[ss]; !ok && (symmetry || argPatterns == nil) {
|
||||
newSetCounts[ss] = struct{}{}
|
||||
}
|
||||
}
|
||||
|
||||
setCounts = []uint64{}
|
||||
for setCount := range newSetCounts {
|
||||
setCounts = append(setCounts, setCount)
|
||||
}
|
||||
|
||||
// Not necessarily needed but it ensures to the readers
|
||||
// eyes that we prefer a sorted setCount slice for the
|
||||
// subsequent function to figure out the right common
|
||||
// divisor, it avoids loops.
|
||||
sort.Slice(setCounts, func(i, j int) bool {
|
||||
return setCounts[i] < setCounts[j]
|
||||
})
|
||||
|
||||
return setCounts
|
||||
}
|
||||
|
||||
func commonSetDriveCount(divisibleSize uint64, setCounts []uint64) (setSize uint64) {
|
||||
// prefers setCounts to be sorted for optimal behavior.
|
||||
if divisibleSize < setCounts[len(setCounts)-1] {
|
||||
return divisibleSize
|
||||
}
|
||||
|
||||
// Figure out largest value of total_drives_in_erasure_set which results
|
||||
// in least number of total_drives/total_drives_erasure_set ratio.
|
||||
prevD := divisibleSize / setCounts[0]
|
||||
for _, cnt := range setCounts {
|
||||
if divisibleSize%cnt == 0 {
|
||||
d := divisibleSize / cnt
|
||||
if d <= prevD {
|
||||
prevD = d
|
||||
setSize = cnt
|
||||
}
|
||||
}
|
||||
}
|
||||
return setSize
|
||||
}
|
||||
|
||||
// getSetIndexes returns list of indexes which provides the set size
|
||||
// on each index, this function also determines the final set size
|
||||
// The final set size has the affinity towards choosing smaller
|
||||
// indexes (total sets)
|
||||
func getSetIndexes(args []string, totalSizes []uint64, argPatterns []ellipses.ArgPattern) (setIndexes [][]uint64, err error) {
|
||||
if len(totalSizes) == 0 || len(args) == 0 {
|
||||
return nil, errors.New("invalid argument")
|
||||
}
|
||||
|
||||
setIndexes = make([][]uint64, len(totalSizes))
|
||||
for _, totalSize := range totalSizes {
|
||||
// Check if totalSize has minimum range upto setSize
|
||||
if totalSize < setSizes[0] {
|
||||
return nil, fmt.Errorf("incorrect number of endpoints provided %s", args)
|
||||
}
|
||||
}
|
||||
|
||||
commonSize := getDivisibleSize(totalSizes)
|
||||
possibleSetCounts := func(setSize uint64) (ss []uint64) {
|
||||
for _, s := range setSizes {
|
||||
if setSize%s == 0 {
|
||||
ss = append(ss, s)
|
||||
}
|
||||
}
|
||||
return ss
|
||||
}
|
||||
|
||||
setCounts := possibleSetCounts(commonSize)
|
||||
if len(setCounts) == 0 {
|
||||
err = fmt.Errorf("incorrect number of endpoints provided %s, number of disks %d is not divisible by any supported erasure set sizes %d", args, commonSize, setSizes)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Returns possible set counts with symmetry.
|
||||
setCounts = possibleSetCountsWithSymmetry(setCounts, argPatterns)
|
||||
if len(setCounts) == 0 {
|
||||
err = fmt.Errorf("no symmetric distribution detected with input endpoints provided %s, disks %d cannot be spread symmetrically by any supported erasure set sizes %d", args, commonSize, setSizes)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Final set size with all the symmetry accounted for.
|
||||
setSize := commonSetDriveCount(commonSize, setCounts)
|
||||
|
||||
// Check whether setSize is with the supported range.
|
||||
if !isValidSetSize(setSize) {
|
||||
err = fmt.Errorf("incorrect number of endpoints provided %s, number of disks %d is not divisible by any supported erasure set sizes %d", args, commonSize, setSizes)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for i := range totalSizes {
|
||||
for j := uint64(0); j < totalSizes[i]/setSize; j++ {
|
||||
setIndexes[i] = append(setIndexes[i], setSize)
|
||||
}
|
||||
}
|
||||
|
||||
return setIndexes, nil
|
||||
}
|
||||
|
||||
// Return the total size for each argument patterns.
|
||||
func getTotalSizes(argPatterns []ellipses.ArgPattern) []uint64 {
|
||||
var totalSizes []uint64
|
||||
for _, argPattern := range argPatterns {
|
||||
var totalSize uint64 = 1
|
||||
for _, p := range argPattern {
|
||||
totalSize = totalSize * uint64(len(p.Seq))
|
||||
}
|
||||
totalSizes = append(totalSizes, totalSize)
|
||||
}
|
||||
return totalSizes
|
||||
}
|
||||
|
||||
// PossibleParityValues returns possible parities for input args,
|
||||
// parties are calculated in uniform manner for one zone or
|
||||
// multiple zones, ensuring that parities returned are common
|
||||
// and applicable across all zones.
|
||||
func PossibleParityValues(args ...string) ([]string, error) {
|
||||
setIndexes, err := parseEndpointSet(args...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
maximumParity := setIndexes[0][0] / 2
|
||||
var parities []string
|
||||
for maximumParity >= 2 {
|
||||
parities = append(parities, fmt.Sprintf("EC:%d", maximumParity))
|
||||
maximumParity--
|
||||
}
|
||||
return parities, nil
|
||||
}
|
||||
|
||||
// Parses all arguments and returns an endpointSet which is a collection
|
||||
// of endpoints following the ellipses pattern, this is what is used
|
||||
// by the object layer for initializing itself.
|
||||
func parseEndpointSet(args ...string) (setIndexes [][]uint64, err error) {
|
||||
var argPatterns = make([]ellipses.ArgPattern, len(args))
|
||||
for i, arg := range args {
|
||||
patterns, err := ellipses.FindEllipsesPatterns(arg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
argPatterns[i] = patterns
|
||||
}
|
||||
|
||||
return getSetIndexes(args, getTotalSizes(argPatterns), argPatterns)
|
||||
}
|
||||
281
pkg/utils/parity_test.go
Normal file
281
pkg/utils/parity_test.go
Normal file
@@ -0,0 +1,281 @@
|
||||
// This file is part of MinIO Console Server
|
||||
// Copyright (c) 2020 MinIO, Inc.
|
||||
//
|
||||
// All rights reserved
|
||||
|
||||
package utils
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/minio/minio/pkg/ellipses"
|
||||
)
|
||||
|
||||
func TestGetDivisibleSize(t *testing.T) {
|
||||
testCases := []struct {
|
||||
totalSizes []uint64
|
||||
result uint64
|
||||
}{{[]uint64{24, 32, 16}, 8},
|
||||
{[]uint64{32, 8, 4}, 4},
|
||||
{[]uint64{8, 8, 8}, 8},
|
||||
{[]uint64{24}, 24},
|
||||
}
|
||||
|
||||
for _, testCase := range testCases {
|
||||
testCase := testCase
|
||||
t.Run("", func(t *testing.T) {
|
||||
gotGCD := getDivisibleSize(testCase.totalSizes)
|
||||
if testCase.result != gotGCD {
|
||||
t.Errorf("Expected %v, got %v", testCase.result, gotGCD)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// Test tests calculating set indexes.
|
||||
func TestGetSetIndexes(t *testing.T) {
|
||||
testCases := []struct {
|
||||
args []string
|
||||
totalSizes []uint64
|
||||
indexes [][]uint64
|
||||
success bool
|
||||
}{
|
||||
// Invalid inputs.
|
||||
{
|
||||
[]string{"data{1...3}"},
|
||||
[]uint64{3},
|
||||
nil,
|
||||
false,
|
||||
},
|
||||
{
|
||||
[]string{"data/controller1/export{1...2}, data/controller2/export{1...4}, data/controller3/export{1...8}"},
|
||||
[]uint64{2, 4, 8},
|
||||
nil,
|
||||
false,
|
||||
},
|
||||
{
|
||||
[]string{"data{1...17}/export{1...52}"},
|
||||
[]uint64{14144},
|
||||
nil,
|
||||
false,
|
||||
},
|
||||
// Valid inputs.
|
||||
{
|
||||
[]string{"data{1...27}"},
|
||||
[]uint64{27},
|
||||
[][]uint64{{9, 9, 9}},
|
||||
true,
|
||||
},
|
||||
{
|
||||
[]string{"http://host{1...3}/data{1...180}"},
|
||||
[]uint64{540},
|
||||
[][]uint64{{15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15}},
|
||||
true,
|
||||
},
|
||||
{
|
||||
[]string{"http://host{1...2}.rack{1...4}/data{1...180}"},
|
||||
[]uint64{1440},
|
||||
[][]uint64{{16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16}},
|
||||
true,
|
||||
},
|
||||
{
|
||||
[]string{"http://host{1...2}/data{1...180}"},
|
||||
[]uint64{360},
|
||||
[][]uint64{{12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12}},
|
||||
true,
|
||||
},
|
||||
{
|
||||
[]string{"data/controller1/export{1...4}, data/controller2/export{1...8}, data/controller3/export{1...12}"},
|
||||
[]uint64{4, 8, 12},
|
||||
[][]uint64{{4}, {4, 4}, {4, 4, 4}},
|
||||
true,
|
||||
},
|
||||
{
|
||||
[]string{"data{1...64}"},
|
||||
[]uint64{64},
|
||||
[][]uint64{{16, 16, 16, 16}},
|
||||
true,
|
||||
},
|
||||
{
|
||||
[]string{"data{1...24}"},
|
||||
[]uint64{24},
|
||||
[][]uint64{{12, 12}},
|
||||
true,
|
||||
},
|
||||
{
|
||||
[]string{"data/controller{1...11}/export{1...8}"},
|
||||
[]uint64{88},
|
||||
[][]uint64{{11, 11, 11, 11, 11, 11, 11, 11}},
|
||||
true,
|
||||
},
|
||||
{
|
||||
[]string{"data{1...4}"},
|
||||
[]uint64{4},
|
||||
[][]uint64{{4}},
|
||||
true,
|
||||
},
|
||||
{
|
||||
[]string{"data/controller1/export{1...10}, data/controller2/export{1...10}, data/controller3/export{1...10}"},
|
||||
[]uint64{10, 10, 10},
|
||||
[][]uint64{{10}, {10}, {10}},
|
||||
true,
|
||||
},
|
||||
{
|
||||
[]string{"data{1...16}/export{1...52}"},
|
||||
[]uint64{832},
|
||||
[][]uint64{{16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16}},
|
||||
true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, testCase := range testCases {
|
||||
testCase := testCase
|
||||
t.Run("", func(t *testing.T) {
|
||||
var argPatterns = make([]ellipses.ArgPattern, len(testCase.args))
|
||||
for i, arg := range testCase.args {
|
||||
patterns, err := ellipses.FindEllipsesPatterns(arg)
|
||||
if err != nil {
|
||||
t.Fatalf("Unexpected failure %s", err)
|
||||
}
|
||||
argPatterns[i] = patterns
|
||||
}
|
||||
gotIndexes, err := getSetIndexes(testCase.args, testCase.totalSizes, argPatterns)
|
||||
if err != nil && testCase.success {
|
||||
t.Errorf("Expected success but failed instead %s", err)
|
||||
}
|
||||
if err == nil && !testCase.success {
|
||||
t.Errorf("Expected failure but passed instead")
|
||||
}
|
||||
if !reflect.DeepEqual(testCase.indexes, gotIndexes) {
|
||||
t.Errorf("Expected %v, got %v", testCase.indexes, gotIndexes)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// Test tests possible parities returned for any input args
|
||||
func TestPossibleParities(t *testing.T) {
|
||||
testCases := []struct {
|
||||
arg string
|
||||
parities []string
|
||||
success bool
|
||||
}{
|
||||
// Tests invalid inputs.
|
||||
{
|
||||
"...",
|
||||
nil,
|
||||
false,
|
||||
},
|
||||
// No range specified.
|
||||
{
|
||||
"{...}",
|
||||
nil,
|
||||
false,
|
||||
},
|
||||
// Invalid range.
|
||||
{
|
||||
"http://minio{2...3}/export/set{1...0}",
|
||||
nil,
|
||||
false,
|
||||
},
|
||||
// Range cannot be smaller than 4 minimum.
|
||||
{
|
||||
"/export{1..2}",
|
||||
nil,
|
||||
false,
|
||||
},
|
||||
// Unsupported characters.
|
||||
{
|
||||
"/export/test{1...2O}",
|
||||
nil,
|
||||
false,
|
||||
},
|
||||
// Tests valid inputs.
|
||||
{
|
||||
"{1...27}",
|
||||
[]string{"EC:4", "EC:3", "EC:2"},
|
||||
true,
|
||||
},
|
||||
{
|
||||
"/export/set{1...64}",
|
||||
[]string{"EC:8", "EC:7", "EC:6", "EC:5", "EC:4", "EC:3", "EC:2"},
|
||||
true,
|
||||
},
|
||||
// Valid input for distributed setup.
|
||||
{
|
||||
"http://minio{2...3}/export/set{1...64}",
|
||||
[]string{"EC:8", "EC:7", "EC:6", "EC:5", "EC:4", "EC:3", "EC:2"},
|
||||
true,
|
||||
},
|
||||
// Supporting some advanced cases.
|
||||
{
|
||||
"http://minio{1...64}.mydomain.net/data",
|
||||
[]string{"EC:8", "EC:7", "EC:6", "EC:5", "EC:4", "EC:3", "EC:2"},
|
||||
true,
|
||||
},
|
||||
{
|
||||
"http://rack{1...4}.mydomain.minio{1...16}/data",
|
||||
[]string{"EC:8", "EC:7", "EC:6", "EC:5", "EC:4", "EC:3", "EC:2"},
|
||||
true,
|
||||
},
|
||||
// Supporting kubernetes cases.
|
||||
{
|
||||
"http://minio{0...15}.mydomain.net/data{0...1}",
|
||||
[]string{"EC:8", "EC:7", "EC:6", "EC:5", "EC:4", "EC:3", "EC:2"},
|
||||
true,
|
||||
},
|
||||
// No host regex, just disks.
|
||||
{
|
||||
"http://server1/data{1...32}",
|
||||
[]string{"EC:8", "EC:7", "EC:6", "EC:5", "EC:4", "EC:3", "EC:2"},
|
||||
true,
|
||||
},
|
||||
// No host regex, just disks with two position numerics.
|
||||
{
|
||||
"http://server1/data{01...32}",
|
||||
[]string{"EC:8", "EC:7", "EC:6", "EC:5", "EC:4", "EC:3", "EC:2"},
|
||||
true,
|
||||
},
|
||||
// More than 2 ellipses are supported as well.
|
||||
{
|
||||
"http://minio{2...3}/export/set{1...64}/test{1...2}",
|
||||
[]string{"EC:8", "EC:7", "EC:6", "EC:5", "EC:4", "EC:3", "EC:2"},
|
||||
true,
|
||||
},
|
||||
// More than 1 ellipses per argument for standalone setup.
|
||||
{
|
||||
"/export{1...10}/disk{1...10}",
|
||||
[]string{"EC:5", "EC:4", "EC:3", "EC:2"},
|
||||
true,
|
||||
},
|
||||
// IPv6 ellipses with hexadecimal expansion
|
||||
{
|
||||
"http://[2001:3984:3989::{1...a}]/disk{1...10}",
|
||||
[]string{"EC:5", "EC:4", "EC:3", "EC:2"},
|
||||
true,
|
||||
},
|
||||
// IPv6 ellipses with hexadecimal expansion with 3 position numerics.
|
||||
{
|
||||
"http://[2001:3984:3989::{001...00a}]/disk{1...10}",
|
||||
[]string{"EC:5", "EC:4", "EC:3", "EC:2"},
|
||||
true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, testCase := range testCases {
|
||||
testCase := testCase
|
||||
t.Run("", func(t *testing.T) {
|
||||
gotPs, err := PossibleParityValues(testCase.arg)
|
||||
if err != nil && testCase.success {
|
||||
t.Errorf("Expected success but failed instead %s", err)
|
||||
}
|
||||
if err == nil && !testCase.success {
|
||||
t.Errorf("Expected failure but passed instead")
|
||||
}
|
||||
if !reflect.DeepEqual(testCase.parities, gotPs) {
|
||||
t.Errorf("Expected %v, got %v", testCase.parities, gotPs)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -265,7 +265,7 @@ const TableWrapper = ({
|
||||
</Grid>
|
||||
</Grid>
|
||||
)}
|
||||
{records && records.length > 0 ? (
|
||||
{records && !isLoading && records.length > 0 ? (
|
||||
<Table size="small" stickyHeader={stickyHeader}>
|
||||
<TableHead className={classes.minTableHeader}>
|
||||
<TableRow>
|
||||
|
||||
@@ -40,7 +40,7 @@ import {
|
||||
} from "../../../../common/utils";
|
||||
import {
|
||||
commonFormValidation,
|
||||
IValidation
|
||||
IValidation,
|
||||
} from "../../../../utils/validationFunctions";
|
||||
import GenericWizard from "../../Common/GenericWizard/GenericWizard";
|
||||
import { IWizardElement } from "../../Common/GenericWizard/types";
|
||||
@@ -52,12 +52,13 @@ import {
|
||||
ICapacity,
|
||||
ITenantCreator,
|
||||
} from "../../../../common/types";
|
||||
import { NewTenantCredential } from "./TenantCredentialsPrompt/types";
|
||||
|
||||
interface IAddTenantProps {
|
||||
open: boolean;
|
||||
closeModalAndRefresh: (
|
||||
reloadData: boolean,
|
||||
res: NewServiceAccount | null
|
||||
res: NewTenantCredential | null
|
||||
) => any;
|
||||
classes: any;
|
||||
}
|
||||
@@ -65,19 +66,19 @@ interface IAddTenantProps {
|
||||
const styles = (theme: Theme) =>
|
||||
createStyles({
|
||||
errorBlock: {
|
||||
color: "red"
|
||||
color: "red",
|
||||
},
|
||||
buttonContainer: {
|
||||
textAlign: "right"
|
||||
textAlign: "right",
|
||||
},
|
||||
multiContainer: {
|
||||
display: "flex",
|
||||
alignItems: "center" as const,
|
||||
justifyContent: "flex-start" as const
|
||||
justifyContent: "flex-start" as const,
|
||||
},
|
||||
sizeFactorContainer: {
|
||||
marginLeft: 8,
|
||||
alignSelf: "flex-start" as const
|
||||
alignSelf: "flex-start" as const,
|
||||
},
|
||||
headerElement: {
|
||||
position: "sticky",
|
||||
@@ -85,16 +86,16 @@ const styles = (theme: Theme) =>
|
||||
paddingTop: 5,
|
||||
marginBottom: 10,
|
||||
backgroundColor: "#fff",
|
||||
zIndex: 500
|
||||
zIndex: 500,
|
||||
},
|
||||
tableTitle: {
|
||||
fontWeight: 700,
|
||||
width: "30%"
|
||||
width: "30%",
|
||||
},
|
||||
zoneError: {
|
||||
color: "#dc1f2e",
|
||||
fontSize: "0.75rem",
|
||||
paddingLeft: 120
|
||||
paddingLeft: 120,
|
||||
},
|
||||
error: {
|
||||
color: "#dc1f2e",
|
||||
@@ -111,7 +112,7 @@ interface Opts {
|
||||
const AddTenant = ({
|
||||
open,
|
||||
closeModalAndRefresh,
|
||||
classes
|
||||
classes,
|
||||
}: IAddTenantProps) => {
|
||||
// Fields
|
||||
const [addSending, setAddSending] = useState<boolean>(false);
|
||||
@@ -212,7 +213,9 @@ const AddTenant = ({
|
||||
const elements = get(res, "elements", []);
|
||||
|
||||
const newStorage = elements.map((storageClass: any) => {
|
||||
const name = get(storageClass, "name", "").split(".")[0];
|
||||
const name = get(storageClass, "name", "").split(
|
||||
".storageclass.storage.k8s.io/requests.storage"
|
||||
)[0];
|
||||
|
||||
return { label: name, value: name };
|
||||
});
|
||||
@@ -265,16 +268,6 @@ const AddTenant = ({
|
||||
);
|
||||
|
||||
setDistribution(distrCalculate);
|
||||
|
||||
/*const errorDistribution = get(distrCalculate, "error", "");
|
||||
|
||||
if (errorDistribution === "") {
|
||||
const disksPerServer = get(distrCalculate, "disks", 0);
|
||||
const totalNodes = get(distrCalculate, "nodes", 0);
|
||||
const sizePerVolume = get(distrCalculate, "pvSize", 0);
|
||||
|
||||
getParity(totalNodes, disksPerServer, sizePerVolume);
|
||||
}*/
|
||||
};
|
||||
|
||||
/*Calculate Allocation End*/
|
||||
@@ -301,8 +294,8 @@ const AddTenant = ({
|
||||
|
||||
setNameTenantValid(
|
||||
!("tenant-name" in commonValidation) &&
|
||||
!("namespace" in commonValidation) &&
|
||||
storageClasses.length > 0
|
||||
!("namespace" in commonValidation) &&
|
||||
storageClasses.length > 0
|
||||
);
|
||||
|
||||
setValidationErrors(commonValidation);
|
||||
@@ -337,9 +330,9 @@ const AddTenant = ({
|
||||
|
||||
setConfigValid(
|
||||
!("nodes" in commonValidation) &&
|
||||
!("volume_size" in commonValidation) &&
|
||||
!("memory_per_node" in commonValidation) &&
|
||||
distribution.error === ""
|
||||
!("volume_size" in commonValidation) &&
|
||||
!("memory_per_node" in commonValidation) &&
|
||||
distribution.error === ""
|
||||
);
|
||||
|
||||
setValidationErrors(commonValidation);
|
||||
@@ -356,8 +349,8 @@ const AddTenant = ({
|
||||
required: true,
|
||||
value: imageName,
|
||||
pattern: /^((.*?)\/(.*?):(.+))$/,
|
||||
customPatternMessage: "Format must be of form: 'minio/minio:VERSION'"
|
||||
}
|
||||
customPatternMessage: "Format must be of form: 'minio/minio:VERSION'",
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
@@ -590,9 +583,13 @@ const AddTenant = ({
|
||||
api
|
||||
.invoke("POST", `/api/v1/tenants`, dataSend)
|
||||
.then((res) => {
|
||||
const newSrvAcc: NewServiceAccount = {
|
||||
const newSrvAcc: NewTenantCredential = {
|
||||
accessKey: res.access_key,
|
||||
secretKey: res.secret_key,
|
||||
console: {
|
||||
accessKey: res.console.access_key,
|
||||
secretKey: res.console.secret_key,
|
||||
},
|
||||
};
|
||||
|
||||
setAddSending(false);
|
||||
@@ -620,7 +617,7 @@ const AddTenant = ({
|
||||
enabled: true,
|
||||
action: () => {
|
||||
closeModalAndRefresh(false, null);
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
const wizardSteps: IWizardElement[] = [
|
||||
@@ -690,7 +687,7 @@ const AddTenant = ({
|
||||
id="adv_mode"
|
||||
name="adv_mode"
|
||||
checked={advancedMode}
|
||||
onChange={e => {
|
||||
onChange={(e) => {
|
||||
const targetD = e.target;
|
||||
const checked = targetD.checked;
|
||||
|
||||
@@ -703,8 +700,8 @@ const AddTenant = ({
|
||||
),
|
||||
buttons: [
|
||||
cancelButton,
|
||||
{ label: "Next", type: "next", enabled: nameTenantValid }
|
||||
]
|
||||
{ label: "Next", type: "next", enabled: nameTenantValid },
|
||||
],
|
||||
},
|
||||
{
|
||||
label: "Configure",
|
||||
@@ -1080,8 +1077,8 @@ const AddTenant = ({
|
||||
buttons: [
|
||||
cancelButton,
|
||||
{ label: "Back", type: "back", enabled: true },
|
||||
{ label: "Next", type: "next", enabled: true }
|
||||
]
|
||||
{ label: "Next", type: "next", enabled: true },
|
||||
],
|
||||
},
|
||||
{
|
||||
label: "Encryption",
|
||||
@@ -1504,8 +1501,8 @@ const AddTenant = ({
|
||||
buttons: [
|
||||
cancelButton,
|
||||
{ label: "Back", type: "back", enabled: true },
|
||||
{ label: "Next", type: "next", enabled: true }
|
||||
]
|
||||
{ label: "Next", type: "next", enabled: true },
|
||||
],
|
||||
},
|
||||
{
|
||||
label: "Tenant Size",
|
||||
@@ -1720,16 +1717,16 @@ const AddTenant = ({
|
||||
enabled: !addSending,
|
||||
action: () => {
|
||||
setAddSending(true);
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
let filteredWizardSteps = wizardSteps;
|
||||
|
||||
if (!advancedMode) {
|
||||
filteredWizardSteps = wizardSteps.filter(step => !step.advancedOnly);
|
||||
filteredWizardSteps = wizardSteps.filter((step) => !step.advancedOnly);
|
||||
}
|
||||
|
||||
return (
|
||||
|
||||
@@ -20,7 +20,7 @@ import Typography from "@material-ui/core/Typography";
|
||||
import TextField from "@material-ui/core/TextField";
|
||||
import InputAdornment from "@material-ui/core/InputAdornment";
|
||||
import SearchIcon from "@material-ui/icons/Search";
|
||||
import { Button } from "@material-ui/core";
|
||||
import { Button, IconButton } from "@material-ui/core";
|
||||
import { CreateIcon } from "../../../../icons";
|
||||
import TableWrapper from "../../Common/TableWrapper/TableWrapper";
|
||||
import { MinTablePaginationActions } from "../../../../common/MinTablePaginationActions";
|
||||
@@ -33,6 +33,9 @@ import AddTenant from "./AddTenant";
|
||||
import { NewServiceAccount } from "../../Common/CredentialsPrompt/types";
|
||||
import CredentialsPrompt from "../../Common/CredentialsPrompt/CredentialsPrompt";
|
||||
import history from "../../../../history";
|
||||
import RefreshIcon from "@material-ui/icons/Refresh";
|
||||
import TenantCredentialsPrompt from "./TenantCredentialsPrompt/TenantCredentialsPrompt";
|
||||
import { NewTenantCredential } from "./TenantCredentialsPrompt/types";
|
||||
|
||||
interface ITenantsList {
|
||||
classes: any;
|
||||
@@ -97,11 +100,11 @@ const ListTenants = ({ classes }: ITenantsList) => {
|
||||
const [
|
||||
createdAccount,
|
||||
setCreatedAccount,
|
||||
] = useState<NewServiceAccount | null>(null);
|
||||
] = useState<NewTenantCredential | null>(null);
|
||||
|
||||
const closeAddModalAndRefresh = (
|
||||
reloadData: boolean,
|
||||
res: NewServiceAccount | null
|
||||
res: NewTenantCredential | null
|
||||
) => {
|
||||
setCreateTenantOpen(false);
|
||||
|
||||
@@ -235,7 +238,7 @@ const ListTenants = ({ classes }: ITenantsList) => {
|
||||
/>
|
||||
)}
|
||||
{showNewCredentials && (
|
||||
<CredentialsPrompt
|
||||
<TenantCredentialsPrompt
|
||||
newServiceAccount={createdAccount}
|
||||
open={showNewCredentials}
|
||||
closeModal={() => {
|
||||
@@ -252,6 +255,17 @@ const ListTenants = ({ classes }: ITenantsList) => {
|
||||
<br />
|
||||
</Grid>
|
||||
<Grid item xs={12} className={classes.actionsTray}>
|
||||
<IconButton
|
||||
color="primary"
|
||||
aria-label="Refresh Tenant List"
|
||||
component="span"
|
||||
onClick={() => {
|
||||
setIsLoading(true);
|
||||
}}
|
||||
>
|
||||
<RefreshIcon />
|
||||
</IconButton>
|
||||
|
||||
<TextField
|
||||
placeholder="Search Tenants"
|
||||
className={classes.searchField}
|
||||
|
||||
@@ -8,7 +8,7 @@ import Grid from "@material-ui/core/Grid";
|
||||
import {
|
||||
factorForDropdown,
|
||||
getTotalSize,
|
||||
niceBytes
|
||||
niceBytes,
|
||||
} from "../../../../common/utils";
|
||||
import { Button, LinearProgress } from "@material-ui/core";
|
||||
import api from "../../../../common/api";
|
||||
@@ -24,18 +24,18 @@ interface IAddZoneProps {
|
||||
const styles = (theme: Theme) =>
|
||||
createStyles({
|
||||
errorBlock: {
|
||||
color: "red"
|
||||
color: "red",
|
||||
},
|
||||
buttonContainer: {
|
||||
textAlign: "right"
|
||||
textAlign: "right",
|
||||
},
|
||||
multiContainer: {
|
||||
display: "flex",
|
||||
alignItems: "center" as const,
|
||||
justifyContent: "flex-start" as const
|
||||
justifyContent: "flex-start" as const,
|
||||
},
|
||||
sizeFactorContainer: {
|
||||
marginLeft: 8
|
||||
marginLeft: 8,
|
||||
},
|
||||
bottomContainer: {
|
||||
display: "flex",
|
||||
@@ -43,31 +43,31 @@ const styles = (theme: Theme) =>
|
||||
alignItems: "center",
|
||||
"& div": {
|
||||
flexGrow: 1,
|
||||
width: "100%"
|
||||
}
|
||||
width: "100%",
|
||||
},
|
||||
},
|
||||
factorElements: {
|
||||
display: "flex",
|
||||
justifyContent: "flex-start"
|
||||
justifyContent: "flex-start",
|
||||
},
|
||||
sizeNumber: {
|
||||
fontSize: 35,
|
||||
fontWeight: 700,
|
||||
textAlign: "center"
|
||||
textAlign: "center",
|
||||
},
|
||||
sizeDescription: {
|
||||
fontSize: 14,
|
||||
color: "#777",
|
||||
textAlign: "center"
|
||||
textAlign: "center",
|
||||
},
|
||||
...modalBasic
|
||||
...modalBasic,
|
||||
});
|
||||
|
||||
const AddZoneModal = ({
|
||||
tenant,
|
||||
classes,
|
||||
open,
|
||||
onCloseZoneAndReload
|
||||
onCloseZoneAndReload,
|
||||
}: IAddZoneProps) => {
|
||||
const [addSending, setAddSending] = useState<boolean>(false);
|
||||
const [numberOfNodes, setNumberOfNodes] = useState<number>(0);
|
||||
@@ -96,8 +96,8 @@ const AddZoneModal = ({
|
||||
volume_configuration: {
|
||||
size: volumeSize * 1073741824,
|
||||
storage_class: "",
|
||||
labels: null
|
||||
}
|
||||
labels: null,
|
||||
},
|
||||
};
|
||||
api
|
||||
.invoke(
|
||||
@@ -109,7 +109,7 @@ const AddZoneModal = ({
|
||||
setAddSending(false);
|
||||
onCloseZoneAndReload(true);
|
||||
})
|
||||
.catch(err => {
|
||||
.catch((err) => {
|
||||
setAddSending(false);
|
||||
// setDeleteError(err);
|
||||
});
|
||||
|
||||
@@ -42,25 +42,25 @@ interface ITenantDetailsProps {
|
||||
const styles = (theme: Theme) =>
|
||||
createStyles({
|
||||
errorBlock: {
|
||||
color: "red"
|
||||
color: "red",
|
||||
},
|
||||
buttonContainer: {
|
||||
textAlign: "right"
|
||||
textAlign: "right",
|
||||
},
|
||||
multiContainer: {
|
||||
display: "flex",
|
||||
alignItems: "center" as const,
|
||||
justifyContent: "flex-start" as const
|
||||
justifyContent: "flex-start" as const,
|
||||
},
|
||||
sizeFactorContainer: {
|
||||
marginLeft: 8
|
||||
marginLeft: 8,
|
||||
},
|
||||
containerHeader: {
|
||||
display: "flex",
|
||||
justifyContent: "space-between"
|
||||
justifyContent: "space-between",
|
||||
},
|
||||
paperContainer: {
|
||||
padding: "15px 15px 15px 50px"
|
||||
padding: "15px 15px 15px 50px",
|
||||
},
|
||||
infoGrid: {
|
||||
display: "grid",
|
||||
@@ -68,42 +68,29 @@ const styles = (theme: Theme) =>
|
||||
gridGap: 8,
|
||||
"& div": {
|
||||
display: "flex",
|
||||
alignItems: "center"
|
||||
alignItems: "center",
|
||||
},
|
||||
"& div:nth-child(odd)": {
|
||||
justifyContent: "flex-end",
|
||||
fontWeight: 700
|
||||
fontWeight: 700,
|
||||
},
|
||||
"& div:nth-child(2n)": {
|
||||
paddingRight: 35
|
||||
}
|
||||
paddingRight: 35,
|
||||
},
|
||||
},
|
||||
masterActions: {
|
||||
width: "25%",
|
||||
minWidth: "120px",
|
||||
"& div": {
|
||||
margin: "5px 0px"
|
||||
}
|
||||
margin: "5px 0px",
|
||||
},
|
||||
},
|
||||
actionsTray: {
|
||||
textAlign: "right"
|
||||
textAlign: "right",
|
||||
},
|
||||
...modalBasic
|
||||
...modalBasic,
|
||||
});
|
||||
|
||||
const mainPagination = {
|
||||
rowsPerPageOptions: [5, 10, 25],
|
||||
colSpan: 3,
|
||||
count: 0,
|
||||
rowsPerPage: 0,
|
||||
page: 0,
|
||||
SelectProps: {
|
||||
inputProps: { "aria-label": "rows per page" },
|
||||
native: true
|
||||
},
|
||||
ActionsComponent: MinTablePaginationActions
|
||||
};
|
||||
|
||||
const TenantDetails = ({ classes, match }: ITenantDetailsProps) => {
|
||||
const [selectedTab, setSelectedTab] = useState<number>(0);
|
||||
const [capacity, setCapacity] = useState<number>(0);
|
||||
@@ -180,7 +167,7 @@ const TenantDetails = ({ classes, match }: ITenantDetailsProps) => {
|
||||
setError("");
|
||||
setLoading(false);
|
||||
})
|
||||
.catch(err => {
|
||||
.catch((err) => {
|
||||
setError(err);
|
||||
setLoading(false);
|
||||
});
|
||||
@@ -227,10 +214,10 @@ const TenantDetails = ({ classes, match }: ITenantDetailsProps) => {
|
||||
<div>{niceBytes(capacity.toString(10))}</div>
|
||||
<div>Minio:</div>
|
||||
<div>{tenant ? tenant.image : ""}</div>
|
||||
<div>Console:</div>
|
||||
<div>{tenant ? tenant.console_image : ""}</div>
|
||||
<div>Zones:</div>
|
||||
<div>{zoneCount}</div>
|
||||
<div>Console:</div>
|
||||
<div>{tenant ? tenant.console_image : ""}</div>
|
||||
<div>Instances:</div>
|
||||
<div>{instances}</div>
|
||||
<div>Volumes:</div>
|
||||
@@ -274,26 +261,35 @@ const TenantDetails = ({ classes, match }: ITenantDetailsProps) => {
|
||||
itemActions={[
|
||||
{
|
||||
type: "delete",
|
||||
onClick: element => {
|
||||
onClick: (element) => {
|
||||
console.log(element);
|
||||
},
|
||||
sendOnlyId: true
|
||||
}
|
||||
sendOnlyId: true,
|
||||
},
|
||||
]}
|
||||
columns={[
|
||||
{ label: "Name", elementKey: "name" },
|
||||
{ label: "Capacity", elementKey: "capacity" },
|
||||
{ label: "# of Instances", elementKey: "servers" },
|
||||
{ label: "# of Drives", elementKey: "volumes" }
|
||||
{ label: "# of Drives", elementKey: "volumes" },
|
||||
]}
|
||||
isLoading={false}
|
||||
records={zones}
|
||||
entityName="Zones"
|
||||
idField="name"
|
||||
paginatorConfig={{
|
||||
...mainPagination,
|
||||
rowsPerPageOptions: [5, 10, 25],
|
||||
colSpan: 3,
|
||||
count: zoneCount,
|
||||
rowsPerPage: 10,
|
||||
page: 0,
|
||||
SelectProps: {
|
||||
inputProps: { "aria-label": "rows per page" },
|
||||
native: true,
|
||||
},
|
||||
ActionsComponent: MinTablePaginationActions,
|
||||
onChangePage: () => {},
|
||||
onChangeRowsPerPage: () => {}
|
||||
onChangeRowsPerPage: () => {},
|
||||
}}
|
||||
/>
|
||||
</Grid>
|
||||
|
||||
63
restapi/admin_parity.go
Normal file
63
restapi/admin_parity.go
Normal file
@@ -0,0 +1,63 @@
|
||||
// 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 restapi
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
"github.com/minio/console/pkg/utils"
|
||||
|
||||
"github.com/go-openapi/runtime/middleware"
|
||||
"github.com/minio/console/models"
|
||||
"github.com/minio/console/restapi/operations"
|
||||
"github.com/minio/console/restapi/operations/admin_api"
|
||||
)
|
||||
|
||||
func registerParityHandlers(api *operations.ConsoleAPI) {
|
||||
api.AdminAPIGetParityHandler = admin_api.GetParityHandlerFunc(func(params admin_api.GetParityParams, principal *models.Principal) middleware.Responder {
|
||||
resp, err := getParityResponse(params)
|
||||
if err != nil {
|
||||
return admin_api.NewGetParityDefault(int(err.Code)).WithPayload(err)
|
||||
}
|
||||
return admin_api.NewGetParityOK().WithPayload(resp)
|
||||
})
|
||||
}
|
||||
|
||||
func GetParityInfo(nodes int64, disksPerNode int64) (models.ParityResponse, error) {
|
||||
parityVals, err := utils.PossibleParityValues(fmt.Sprintf(`http://minio{1...%d}/export/set{1...%d}`, nodes, disksPerNode))
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return parityVals, nil
|
||||
}
|
||||
|
||||
func getParityResponse(params admin_api.GetParityParams) (models.ParityResponse, *models.Error) {
|
||||
nodes := params.Nodes
|
||||
disksPerNode := params.DisksPerNode
|
||||
|
||||
parityValues, err := GetParityInfo(nodes, disksPerNode)
|
||||
|
||||
if err != nil {
|
||||
log.Println("error getting parity info:", err)
|
||||
return nil, prepareError(err)
|
||||
}
|
||||
|
||||
return parityValues, nil
|
||||
}
|
||||
79
restapi/admin_parity_test.go
Normal file
79
restapi/admin_parity_test.go
Normal file
@@ -0,0 +1,79 @@
|
||||
// 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 restapi
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/minio/console/models"
|
||||
)
|
||||
|
||||
func Test_getParityInfo(t *testing.T) {
|
||||
tests := []struct {
|
||||
description string
|
||||
wantErr bool
|
||||
nodes int64
|
||||
disksPerNode int64
|
||||
expectedResp models.ParityResponse
|
||||
}{
|
||||
{
|
||||
description: "Incorrect Number of endpoints provided",
|
||||
wantErr: true,
|
||||
nodes: 1,
|
||||
disksPerNode: 1,
|
||||
expectedResp: nil,
|
||||
},
|
||||
{
|
||||
description: "Number of endpoints is valid",
|
||||
wantErr: false,
|
||||
nodes: 4,
|
||||
disksPerNode: 10,
|
||||
expectedResp: models.ParityResponse{"EC:4", "EC:3", "EC:2"},
|
||||
},
|
||||
{
|
||||
description: "More nodes than disks",
|
||||
wantErr: false,
|
||||
nodes: 4,
|
||||
disksPerNode: 1,
|
||||
expectedResp: models.ParityResponse{"EC:2"},
|
||||
},
|
||||
{
|
||||
description: "More disks than nodes",
|
||||
wantErr: false,
|
||||
nodes: 2,
|
||||
disksPerNode: 50,
|
||||
expectedResp: models.ParityResponse{"EC:5", "EC:4", "EC:3", "EC:2"},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.description, func(t *testing.T) {
|
||||
parity, err := GetParityInfo(tt.nodes, tt.disksPerNode)
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("GetParityInfo() error = %v, wantErr %v", err, tt.wantErr)
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(parity, tt.expectedResp) {
|
||||
ji, _ := json.Marshal(parity)
|
||||
vi, _ := json.Marshal(tt.expectedResp)
|
||||
t.Errorf("\ngot: %s \nwant: %s", ji, vi)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -218,15 +218,19 @@ func deleteTenantAction(
|
||||
return nil
|
||||
}
|
||||
|
||||
func getTenantScheme(mi *operator.Tenant) string {
|
||||
// GetTenantServiceURL gets tenant's service url with the proper scheme and port
|
||||
func GetTenantServiceURL(mi *operator.Tenant) (svcURL string) {
|
||||
scheme := "http"
|
||||
port := operator.MinIOPortLoadBalancerSVC
|
||||
if mi.AutoCert() || mi.ExternalCert() {
|
||||
scheme = "https"
|
||||
port = operator.MinIOTLSPortLoadBalancerSVC
|
||||
}
|
||||
return scheme
|
||||
svc := fmt.Sprintf("%s.%s.svc.cluster.local", mi.MinIOCIServiceName(), mi.Namespace)
|
||||
return fmt.Sprintf("%s://%s", scheme, net.JoinHostPort(svc, strconv.Itoa(port)))
|
||||
}
|
||||
|
||||
func getTenantAdminClient(ctx context.Context, client K8sClientI, namespace, tenantName, serviceName, scheme string, insecure bool) (*madmin.AdminClient, error) {
|
||||
func getTenantAdminClient(ctx context.Context, client K8sClientI, namespace, tenantName, svcURL string, insecure bool) (*madmin.AdminClient, error) {
|
||||
// get admin credentials from secret
|
||||
creds, err := client.getSecret(ctx, namespace, fmt.Sprintf("%s-secret", tenantName), metav1.GetOptions{})
|
||||
if err != nil {
|
||||
@@ -242,7 +246,7 @@ func getTenantAdminClient(ctx context.Context, client K8sClientI, namespace, ten
|
||||
log.Println("tenant's secret doesn't contain secretkey")
|
||||
return nil, errorGeneric
|
||||
}
|
||||
mAdmin, pErr := NewAdminClientWithInsecure(scheme+"://"+net.JoinHostPort(serviceName, strconv.Itoa(operator.MinIOPort)), string(accessKey), string(secretkey), insecure)
|
||||
mAdmin, pErr := NewAdminClientWithInsecure(svcURL, string(accessKey), string(secretkey), insecure)
|
||||
if pErr != nil {
|
||||
return nil, pErr.Cause
|
||||
}
|
||||
@@ -565,16 +569,16 @@ func getTenantCreatedResponse(session *models.Principal, params admin_api.Create
|
||||
}
|
||||
}
|
||||
|
||||
isEncryptionAvailable := false
|
||||
isEncryptionEnabled := false
|
||||
if tenantReq.EnableTLS != nil && *tenantReq.EnableTLS {
|
||||
// If user request autoCert, Operator will generate certificate keypair for MinIO (server), Console (server) and KES (server and app mTLS)
|
||||
isEncryptionAvailable = true
|
||||
isEncryptionEnabled = true
|
||||
minInst.Spec.RequestAutoCert = *tenantReq.EnableTLS
|
||||
}
|
||||
|
||||
if !minInst.Spec.RequestAutoCert && tenantReq.TLS != nil && tenantReq.TLS.Minio != nil {
|
||||
// User provided TLS certificates for MinIO
|
||||
isEncryptionAvailable = true
|
||||
isEncryptionEnabled = true
|
||||
// disable autoCert
|
||||
minInst.Spec.RequestAutoCert = false
|
||||
// Certificates used by the MinIO instance
|
||||
@@ -586,7 +590,7 @@ func getTenantCreatedResponse(session *models.Principal, params admin_api.Create
|
||||
minInst.Spec.ExternalCertSecret = externalCertSecret
|
||||
}
|
||||
|
||||
if tenantReq.Encryption != nil && isEncryptionAvailable {
|
||||
if tenantReq.Encryption != nil && isEncryptionEnabled {
|
||||
// Enable auto encryption
|
||||
minInst.Spec.Env = append(minInst.Spec.Env, corev1.EnvVar{
|
||||
Name: "MINIO_KMS_AUTO_ENCRYPTION",
|
||||
@@ -605,6 +609,10 @@ func getTenantCreatedResponse(session *models.Principal, params admin_api.Create
|
||||
if err != nil {
|
||||
return nil, prepareError(errorGeneric)
|
||||
}
|
||||
// Set Labels, Annotations and Node Selector for KES
|
||||
minInst.Spec.KES.Labels = tenantReq.Encryption.Labels
|
||||
minInst.Spec.KES.Annotations = tenantReq.Encryption.Annotations
|
||||
minInst.Spec.KES.NodeSelector = tenantReq.Encryption.NodeSelector
|
||||
}
|
||||
|
||||
// optionals are set below
|
||||
@@ -665,7 +673,7 @@ func getTenantCreatedResponse(session *models.Principal, params admin_api.Create
|
||||
return nil, prepareError(errorGeneric)
|
||||
}
|
||||
|
||||
const consoleVersion = "minio/console:v0.3.24"
|
||||
const consoleVersion = "minio/console:v0.3.26"
|
||||
minInst.Spec.Console = &operator.ConsoleConfiguration{
|
||||
Replicas: 1,
|
||||
Image: consoleVersion,
|
||||
@@ -685,6 +693,13 @@ func getTenantCreatedResponse(session *models.Principal, params admin_api.Create
|
||||
}
|
||||
minInst.Spec.Console.ExternalCertSecret = externalCertSecret
|
||||
}
|
||||
|
||||
// Set Labels, Annotations and Node Selector for Console
|
||||
if tenantReq.Console != nil {
|
||||
minInst.Spec.Console.Annotations = tenantReq.Console.Annotations
|
||||
minInst.Spec.Console.Labels = tenantReq.Console.Labels
|
||||
minInst.Spec.Console.NodeSelector = tenantReq.Console.NodeSelector
|
||||
}
|
||||
}
|
||||
|
||||
// set the service name if provided
|
||||
@@ -872,7 +887,7 @@ func updateTenantAction(ctx context.Context, operatorClient OperatorClientI, cli
|
||||
prometheusPort: fmt.Sprint(operator.MinIOPort),
|
||||
prometheusScrape: "true",
|
||||
}
|
||||
if params.Body.EnablePrometheus && minInst.Spec.Metadata != nil && currentAnnotations != nil {
|
||||
if params.Body.EnablePrometheus && currentAnnotations != nil {
|
||||
// add prometheus annotations to the tenant
|
||||
minInst.Annotations = addAnnotations(currentAnnotations, prometheusAnnotations)
|
||||
// add prometheus annotations to the each zone
|
||||
@@ -1019,17 +1034,15 @@ func getTenantUsageResponse(session *models.Principal, params admin_api.GetTenan
|
||||
return nil, prepareError(err, errorUnableToGetTenantUsage)
|
||||
}
|
||||
minTenant.EnsureDefaults()
|
||||
tenantScheme := getTenantScheme(minTenant)
|
||||
|
||||
svcName := fmt.Sprintf("%s.%s.svc.cluster.local", minTenant.MinIOCIServiceName(), minTenant.Namespace)
|
||||
svcURL := GetTenantServiceURL(minTenant)
|
||||
|
||||
mAdmin, err := getTenantAdminClient(
|
||||
ctx,
|
||||
k8sClient,
|
||||
params.Namespace,
|
||||
params.Tenant,
|
||||
svcName,
|
||||
tenantScheme,
|
||||
svcURL,
|
||||
true)
|
||||
if err != nil {
|
||||
return nil, prepareError(err, errorUnableToGetTenantUsage)
|
||||
|
||||
@@ -195,7 +195,6 @@ func getKESConfiguration(ctx context.Context, clientSet K8sClientI, ns string, e
|
||||
kesConfiguration = &operator.KESConfig{
|
||||
Image: "minio/kes:v0.11.0",
|
||||
Replicas: 1,
|
||||
Metadata: nil,
|
||||
}
|
||||
// Using custom image for KES
|
||||
if encryptionCfg.Image != "" {
|
||||
|
||||
@@ -87,13 +87,12 @@ func Test_TenantInfoTenantAdminClient(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
kClient := k8sClientMock{}
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
client K8sClientI
|
||||
namespace string
|
||||
tenantName string
|
||||
serviceName string
|
||||
scheme string
|
||||
insecure bool
|
||||
ctx context.Context
|
||||
client K8sClientI
|
||||
namespace string
|
||||
tenantName string
|
||||
serviceURL string
|
||||
insecure bool
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
@@ -105,12 +104,11 @@ func Test_TenantInfoTenantAdminClient(t *testing.T) {
|
||||
{
|
||||
name: "Return Tenant Admin, no errors",
|
||||
args: args{
|
||||
ctx: ctx,
|
||||
client: kClient,
|
||||
namespace: "default",
|
||||
tenantName: "tenant-1",
|
||||
serviceName: "service-1",
|
||||
scheme: "http",
|
||||
ctx: ctx,
|
||||
client: kClient,
|
||||
namespace: "default",
|
||||
tenantName: "tenant-1",
|
||||
serviceURL: "http://service-1.default.svc.cluster.local:80",
|
||||
},
|
||||
mockGetSecret: func(ctx context.Context, namespace, secretName string, opts metav1.GetOptions) (*corev1.Secret, error) {
|
||||
vals := make(map[string][]byte)
|
||||
@@ -134,12 +132,11 @@ func Test_TenantInfoTenantAdminClient(t *testing.T) {
|
||||
{
|
||||
name: "Access key not stored on secrets",
|
||||
args: args{
|
||||
ctx: ctx,
|
||||
client: kClient,
|
||||
namespace: "default",
|
||||
tenantName: "tenant-1",
|
||||
serviceName: "service-1",
|
||||
scheme: "http",
|
||||
ctx: ctx,
|
||||
client: kClient,
|
||||
namespace: "default",
|
||||
tenantName: "tenant-1",
|
||||
serviceURL: "http://service-1.default.svc.cluster.local:80",
|
||||
},
|
||||
mockGetSecret: func(ctx context.Context, namespace, secretName string, opts metav1.GetOptions) (*corev1.Secret, error) {
|
||||
vals := make(map[string][]byte)
|
||||
@@ -162,12 +159,11 @@ func Test_TenantInfoTenantAdminClient(t *testing.T) {
|
||||
{
|
||||
name: "Secret key not stored on secrets",
|
||||
args: args{
|
||||
ctx: ctx,
|
||||
client: kClient,
|
||||
namespace: "default",
|
||||
tenantName: "tenant-1",
|
||||
serviceName: "service-1",
|
||||
scheme: "http",
|
||||
ctx: ctx,
|
||||
client: kClient,
|
||||
namespace: "default",
|
||||
tenantName: "tenant-1",
|
||||
serviceURL: "http://service-1.default.svc.cluster.local:80",
|
||||
},
|
||||
mockGetSecret: func(ctx context.Context, namespace, secretName string, opts metav1.GetOptions) (*corev1.Secret, error) {
|
||||
vals := make(map[string][]byte)
|
||||
@@ -190,12 +186,11 @@ func Test_TenantInfoTenantAdminClient(t *testing.T) {
|
||||
{
|
||||
name: "Handle error on getService",
|
||||
args: args{
|
||||
ctx: ctx,
|
||||
client: kClient,
|
||||
namespace: "default",
|
||||
tenantName: "tenant-1",
|
||||
serviceName: "service-1",
|
||||
scheme: "http",
|
||||
ctx: ctx,
|
||||
client: kClient,
|
||||
namespace: "default",
|
||||
tenantName: "tenant-1",
|
||||
serviceURL: "http://service-1.default.svc.cluster.local:80",
|
||||
},
|
||||
mockGetSecret: func(ctx context.Context, namespace, secretName string, opts metav1.GetOptions) (*corev1.Secret, error) {
|
||||
vals := make(map[string][]byte)
|
||||
@@ -214,12 +209,11 @@ func Test_TenantInfoTenantAdminClient(t *testing.T) {
|
||||
{
|
||||
name: "Handle error on getSecret",
|
||||
args: args{
|
||||
ctx: ctx,
|
||||
client: kClient,
|
||||
namespace: "default",
|
||||
tenantName: "tenant-1",
|
||||
serviceName: "service-1",
|
||||
scheme: "http",
|
||||
ctx: ctx,
|
||||
client: kClient,
|
||||
namespace: "default",
|
||||
tenantName: "tenant-1",
|
||||
serviceURL: "http://service-1.default.svc.cluster.local:80",
|
||||
},
|
||||
mockGetSecret: func(ctx context.Context, namespace, secretName string, opts metav1.GetOptions) (*corev1.Secret, error) {
|
||||
return nil, errors.New("error")
|
||||
@@ -239,7 +233,7 @@ func Test_TenantInfoTenantAdminClient(t *testing.T) {
|
||||
k8sclientGetSecretMock = tt.mockGetSecret
|
||||
k8sclientGetServiceMock = tt.mockGetService
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got, err := getTenantAdminClient(tt.args.ctx, tt.args.client, tt.args.namespace, tt.args.tenantName, tt.args.serviceName, tt.args.scheme, tt.args.insecure)
|
||||
got, err := getTenantAdminClient(tt.args.ctx, tt.args.client, tt.args.namespace, tt.args.tenantName, tt.args.serviceURL, tt.args.insecure)
|
||||
if err != nil {
|
||||
if tt.wantErr {
|
||||
return
|
||||
@@ -1002,7 +996,7 @@ func Test_UpdateTenantAction(t *testing.T) {
|
||||
},
|
||||
params: admin_api.UpdateTenantParams{
|
||||
Body: &models.UpdateTenantRequest{
|
||||
ConsoleImage: "minio/console:v0.3.24",
|
||||
ConsoleImage: "minio/console:v0.3.26",
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
@@ -114,6 +114,8 @@ func configureAPI(api *operations.ConsoleAPI) http.Handler {
|
||||
registerResourceQuotaHandlers(api)
|
||||
// Register Nodes' handlers
|
||||
registerNodesHandlers(api)
|
||||
// Register Parity' handlers
|
||||
registerParityHandlers(api)
|
||||
|
||||
api.PreServerShutdown = func() {}
|
||||
|
||||
|
||||
@@ -572,6 +572,45 @@ func init() {
|
||||
}
|
||||
}
|
||||
},
|
||||
"/get-parity/{nodes}/{disksPerNode}": {
|
||||
"get": {
|
||||
"tags": [
|
||||
"AdminAPI"
|
||||
],
|
||||
"summary": "Gets parity by sending number of nodes \u0026 number of disks",
|
||||
"operationId": "GetParity",
|
||||
"parameters": [
|
||||
{
|
||||
"minimum": 2,
|
||||
"type": "integer",
|
||||
"name": "nodes",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"minimum": 1,
|
||||
"type": "integer",
|
||||
"name": "disksPerNode",
|
||||
"in": "path",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "A successful response.",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/parityResponse"
|
||||
}
|
||||
},
|
||||
"default": {
|
||||
"description": "Generic error response.",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/error"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/groups": {
|
||||
"get": {
|
||||
"tags": [
|
||||
@@ -2174,6 +2213,21 @@ func init() {
|
||||
}
|
||||
}
|
||||
},
|
||||
"consoleConfiguration": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/metadataFields"
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"image": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"createTenantRequest": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
@@ -2191,6 +2245,10 @@ func init() {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"console": {
|
||||
"type": "object",
|
||||
"$ref": "#/definitions/consoleConfiguration"
|
||||
},
|
||||
"console_image": {
|
||||
"type": "string"
|
||||
},
|
||||
@@ -2291,32 +2349,39 @@ func init() {
|
||||
}
|
||||
},
|
||||
"encryptionConfiguration": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"aws": {
|
||||
"type": "object",
|
||||
"$ref": "#/definitions/awsConfiguration"
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/metadataFields"
|
||||
},
|
||||
"client": {
|
||||
{
|
||||
"type": "object",
|
||||
"$ref": "#/definitions/keyPairConfiguration"
|
||||
},
|
||||
"gemalto": {
|
||||
"type": "object",
|
||||
"$ref": "#/definitions/gemaltoConfiguration"
|
||||
},
|
||||
"image": {
|
||||
"type": "string"
|
||||
},
|
||||
"server": {
|
||||
"type": "object",
|
||||
"$ref": "#/definitions/keyPairConfiguration"
|
||||
},
|
||||
"vault": {
|
||||
"type": "object",
|
||||
"$ref": "#/definitions/vaultConfiguration"
|
||||
"properties": {
|
||||
"aws": {
|
||||
"type": "object",
|
||||
"$ref": "#/definitions/awsConfiguration"
|
||||
},
|
||||
"client": {
|
||||
"type": "object",
|
||||
"$ref": "#/definitions/keyPairConfiguration"
|
||||
},
|
||||
"gemalto": {
|
||||
"type": "object",
|
||||
"$ref": "#/definitions/gemaltoConfiguration"
|
||||
},
|
||||
"image": {
|
||||
"type": "string"
|
||||
},
|
||||
"server": {
|
||||
"type": "object",
|
||||
"$ref": "#/definitions/keyPairConfiguration"
|
||||
},
|
||||
"vault": {
|
||||
"type": "object",
|
||||
"$ref": "#/definitions/vaultConfiguration"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"error": {
|
||||
"type": "object",
|
||||
@@ -2692,6 +2757,29 @@ func init() {
|
||||
}
|
||||
}
|
||||
},
|
||||
"metadataFields": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"annotations": {
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"labels": {
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"node_selector": {
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"nodeSelectorTerm": {
|
||||
"description": "A null or empty node selector term matches no objects. The requirements of them are ANDed. The TopologySelectorTerm type implements a subset of the NodeSelectorTerm.",
|
||||
"type": "object",
|
||||
@@ -2881,6 +2969,12 @@ func init() {
|
||||
"get"
|
||||
]
|
||||
},
|
||||
"parityResponse": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"podAffinityTerm": {
|
||||
"description": "Required. A pod affinity term, associated with the corresponding weight.",
|
||||
"type": "object",
|
||||
@@ -4223,6 +4317,45 @@ func init() {
|
||||
}
|
||||
}
|
||||
},
|
||||
"/get-parity/{nodes}/{disksPerNode}": {
|
||||
"get": {
|
||||
"tags": [
|
||||
"AdminAPI"
|
||||
],
|
||||
"summary": "Gets parity by sending number of nodes \u0026 number of disks",
|
||||
"operationId": "GetParity",
|
||||
"parameters": [
|
||||
{
|
||||
"minimum": 2,
|
||||
"type": "integer",
|
||||
"name": "nodes",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"minimum": 1,
|
||||
"type": "integer",
|
||||
"name": "disksPerNode",
|
||||
"in": "path",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "A successful response.",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/parityResponse"
|
||||
}
|
||||
},
|
||||
"default": {
|
||||
"description": "Generic error response.",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/error"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/groups": {
|
||||
"get": {
|
||||
"tags": [
|
||||
@@ -6348,6 +6481,21 @@ func init() {
|
||||
}
|
||||
}
|
||||
},
|
||||
"consoleConfiguration": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/metadataFields"
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"image": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"createTenantRequest": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
@@ -6365,6 +6513,10 @@ func init() {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"console": {
|
||||
"type": "object",
|
||||
"$ref": "#/definitions/consoleConfiguration"
|
||||
},
|
||||
"console_image": {
|
||||
"type": "string"
|
||||
},
|
||||
@@ -6465,32 +6617,39 @@ func init() {
|
||||
}
|
||||
},
|
||||
"encryptionConfiguration": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"aws": {
|
||||
"type": "object",
|
||||
"$ref": "#/definitions/awsConfiguration"
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/metadataFields"
|
||||
},
|
||||
"client": {
|
||||
{
|
||||
"type": "object",
|
||||
"$ref": "#/definitions/keyPairConfiguration"
|
||||
},
|
||||
"gemalto": {
|
||||
"type": "object",
|
||||
"$ref": "#/definitions/gemaltoConfiguration"
|
||||
},
|
||||
"image": {
|
||||
"type": "string"
|
||||
},
|
||||
"server": {
|
||||
"type": "object",
|
||||
"$ref": "#/definitions/keyPairConfiguration"
|
||||
},
|
||||
"vault": {
|
||||
"type": "object",
|
||||
"$ref": "#/definitions/vaultConfiguration"
|
||||
"properties": {
|
||||
"aws": {
|
||||
"type": "object",
|
||||
"$ref": "#/definitions/awsConfiguration"
|
||||
},
|
||||
"client": {
|
||||
"type": "object",
|
||||
"$ref": "#/definitions/keyPairConfiguration"
|
||||
},
|
||||
"gemalto": {
|
||||
"type": "object",
|
||||
"$ref": "#/definitions/gemaltoConfiguration"
|
||||
},
|
||||
"image": {
|
||||
"type": "string"
|
||||
},
|
||||
"server": {
|
||||
"type": "object",
|
||||
"$ref": "#/definitions/keyPairConfiguration"
|
||||
},
|
||||
"vault": {
|
||||
"type": "object",
|
||||
"$ref": "#/definitions/vaultConfiguration"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"error": {
|
||||
"type": "object",
|
||||
@@ -6866,6 +7025,29 @@ func init() {
|
||||
}
|
||||
}
|
||||
},
|
||||
"metadataFields": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"annotations": {
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"labels": {
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"node_selector": {
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"nodeSelectorTerm": {
|
||||
"description": "A null or empty node selector term matches no objects. The requirements of them are ANDed. The TopologySelectorTerm type implements a subset of the NodeSelectorTerm.",
|
||||
"type": "object",
|
||||
@@ -7011,6 +7193,12 @@ func init() {
|
||||
"get"
|
||||
]
|
||||
},
|
||||
"parityResponse": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"podAffinityTerm": {
|
||||
"description": "Required. A pod affinity term, associated with the corresponding weight.",
|
||||
"type": "object",
|
||||
|
||||
90
restapi/operations/admin_api/get_parity.go
Normal file
90
restapi/operations/admin_api/get_parity.go
Normal file
@@ -0,0 +1,90 @@
|
||||
// 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 admin_api
|
||||
|
||||
// This file was generated by the swagger tool.
|
||||
// Editing this file might prove futile when you re-run the generate command
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/go-openapi/runtime/middleware"
|
||||
|
||||
"github.com/minio/console/models"
|
||||
)
|
||||
|
||||
// GetParityHandlerFunc turns a function with the right signature into a get parity handler
|
||||
type GetParityHandlerFunc func(GetParityParams, *models.Principal) middleware.Responder
|
||||
|
||||
// Handle executing the request and returning a response
|
||||
func (fn GetParityHandlerFunc) Handle(params GetParityParams, principal *models.Principal) middleware.Responder {
|
||||
return fn(params, principal)
|
||||
}
|
||||
|
||||
// GetParityHandler interface for that can handle valid get parity params
|
||||
type GetParityHandler interface {
|
||||
Handle(GetParityParams, *models.Principal) middleware.Responder
|
||||
}
|
||||
|
||||
// NewGetParity creates a new http.Handler for the get parity operation
|
||||
func NewGetParity(ctx *middleware.Context, handler GetParityHandler) *GetParity {
|
||||
return &GetParity{Context: ctx, Handler: handler}
|
||||
}
|
||||
|
||||
/*GetParity swagger:route GET /get-parity/{nodes}/{disksPerNode} AdminAPI getParity
|
||||
|
||||
Gets parity by sending number of nodes & number of disks
|
||||
|
||||
*/
|
||||
type GetParity struct {
|
||||
Context *middleware.Context
|
||||
Handler GetParityHandler
|
||||
}
|
||||
|
||||
func (o *GetParity) ServeHTTP(rw http.ResponseWriter, r *http.Request) {
|
||||
route, rCtx, _ := o.Context.RouteInfo(r)
|
||||
if rCtx != nil {
|
||||
r = rCtx
|
||||
}
|
||||
var Params = NewGetParityParams()
|
||||
|
||||
uprinc, aCtx, err := o.Context.Authorize(r, route)
|
||||
if err != nil {
|
||||
o.Context.Respond(rw, r, route.Produces, route, err)
|
||||
return
|
||||
}
|
||||
if aCtx != nil {
|
||||
r = aCtx
|
||||
}
|
||||
var principal *models.Principal
|
||||
if uprinc != nil {
|
||||
principal = uprinc.(*models.Principal) // this is really a models.Principal, I promise
|
||||
}
|
||||
|
||||
if err := o.Context.BindValidRequest(r, route, &Params); err != nil { // bind params
|
||||
o.Context.Respond(rw, r, route.Produces, route, err)
|
||||
return
|
||||
}
|
||||
|
||||
res := o.Handler.Handle(Params, principal) // actually handle the request
|
||||
|
||||
o.Context.Respond(rw, r, route.Produces, route, res)
|
||||
|
||||
}
|
||||
154
restapi/operations/admin_api/get_parity_parameters.go
Normal file
154
restapi/operations/admin_api/get_parity_parameters.go
Normal file
@@ -0,0 +1,154 @@
|
||||
// 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 admin_api
|
||||
|
||||
// This file was generated by the swagger tool.
|
||||
// Editing this file might prove futile when you re-run the swagger generate command
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/go-openapi/errors"
|
||||
"github.com/go-openapi/runtime/middleware"
|
||||
"github.com/go-openapi/strfmt"
|
||||
"github.com/go-openapi/swag"
|
||||
"github.com/go-openapi/validate"
|
||||
)
|
||||
|
||||
// NewGetParityParams creates a new GetParityParams object
|
||||
// no default values defined in spec.
|
||||
func NewGetParityParams() GetParityParams {
|
||||
|
||||
return GetParityParams{}
|
||||
}
|
||||
|
||||
// GetParityParams contains all the bound params for the get parity operation
|
||||
// typically these are obtained from a http.Request
|
||||
//
|
||||
// swagger:parameters GetParity
|
||||
type GetParityParams struct {
|
||||
|
||||
// HTTP Request Object
|
||||
HTTPRequest *http.Request `json:"-"`
|
||||
|
||||
/*
|
||||
Required: true
|
||||
Minimum: 1
|
||||
In: path
|
||||
*/
|
||||
DisksPerNode int64
|
||||
/*
|
||||
Required: true
|
||||
Minimum: 2
|
||||
In: path
|
||||
*/
|
||||
Nodes int64
|
||||
}
|
||||
|
||||
// BindRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface
|
||||
// for simple values it will use straight method calls.
|
||||
//
|
||||
// To ensure default values, the struct must have been initialized with NewGetParityParams() beforehand.
|
||||
func (o *GetParityParams) BindRequest(r *http.Request, route *middleware.MatchedRoute) error {
|
||||
var res []error
|
||||
|
||||
o.HTTPRequest = r
|
||||
|
||||
rDisksPerNode, rhkDisksPerNode, _ := route.Params.GetOK("disksPerNode")
|
||||
if err := o.bindDisksPerNode(rDisksPerNode, rhkDisksPerNode, route.Formats); err != nil {
|
||||
res = append(res, err)
|
||||
}
|
||||
|
||||
rNodes, rhkNodes, _ := route.Params.GetOK("nodes")
|
||||
if err := o.bindNodes(rNodes, rhkNodes, route.Formats); err != nil {
|
||||
res = append(res, err)
|
||||
}
|
||||
|
||||
if len(res) > 0 {
|
||||
return errors.CompositeValidationError(res...)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// bindDisksPerNode binds and validates parameter DisksPerNode from path.
|
||||
func (o *GetParityParams) bindDisksPerNode(rawData []string, hasKey bool, formats strfmt.Registry) error {
|
||||
var raw string
|
||||
if len(rawData) > 0 {
|
||||
raw = rawData[len(rawData)-1]
|
||||
}
|
||||
|
||||
// Required: true
|
||||
// Parameter is provided by construction from the route
|
||||
|
||||
value, err := swag.ConvertInt64(raw)
|
||||
if err != nil {
|
||||
return errors.InvalidType("disksPerNode", "path", "int64", raw)
|
||||
}
|
||||
o.DisksPerNode = value
|
||||
|
||||
if err := o.validateDisksPerNode(formats); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// validateDisksPerNode carries on validations for parameter DisksPerNode
|
||||
func (o *GetParityParams) validateDisksPerNode(formats strfmt.Registry) error {
|
||||
|
||||
if err := validate.MinimumInt("disksPerNode", "path", int64(o.DisksPerNode), 1, false); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// bindNodes binds and validates parameter Nodes from path.
|
||||
func (o *GetParityParams) bindNodes(rawData []string, hasKey bool, formats strfmt.Registry) error {
|
||||
var raw string
|
||||
if len(rawData) > 0 {
|
||||
raw = rawData[len(rawData)-1]
|
||||
}
|
||||
|
||||
// Required: true
|
||||
// Parameter is provided by construction from the route
|
||||
|
||||
value, err := swag.ConvertInt64(raw)
|
||||
if err != nil {
|
||||
return errors.InvalidType("nodes", "path", "int64", raw)
|
||||
}
|
||||
o.Nodes = value
|
||||
|
||||
if err := o.validateNodes(formats); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// validateNodes carries on validations for parameter Nodes
|
||||
func (o *GetParityParams) validateNodes(formats strfmt.Registry) error {
|
||||
|
||||
if err := validate.MinimumInt("nodes", "path", int64(o.Nodes), 2, false); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
136
restapi/operations/admin_api/get_parity_responses.go
Normal file
136
restapi/operations/admin_api/get_parity_responses.go
Normal file
@@ -0,0 +1,136 @@
|
||||
// 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 admin_api
|
||||
|
||||
// This file was generated by the swagger tool.
|
||||
// Editing this file might prove futile when you re-run the swagger generate command
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/go-openapi/runtime"
|
||||
|
||||
"github.com/minio/console/models"
|
||||
)
|
||||
|
||||
// GetParityOKCode is the HTTP code returned for type GetParityOK
|
||||
const GetParityOKCode int = 200
|
||||
|
||||
/*GetParityOK A successful response.
|
||||
|
||||
swagger:response getParityOK
|
||||
*/
|
||||
type GetParityOK struct {
|
||||
|
||||
/*
|
||||
In: Body
|
||||
*/
|
||||
Payload models.ParityResponse `json:"body,omitempty"`
|
||||
}
|
||||
|
||||
// NewGetParityOK creates GetParityOK with default headers values
|
||||
func NewGetParityOK() *GetParityOK {
|
||||
|
||||
return &GetParityOK{}
|
||||
}
|
||||
|
||||
// WithPayload adds the payload to the get parity o k response
|
||||
func (o *GetParityOK) WithPayload(payload models.ParityResponse) *GetParityOK {
|
||||
o.Payload = payload
|
||||
return o
|
||||
}
|
||||
|
||||
// SetPayload sets the payload to the get parity o k response
|
||||
func (o *GetParityOK) SetPayload(payload models.ParityResponse) {
|
||||
o.Payload = payload
|
||||
}
|
||||
|
||||
// WriteResponse to the client
|
||||
func (o *GetParityOK) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) {
|
||||
|
||||
rw.WriteHeader(200)
|
||||
payload := o.Payload
|
||||
if payload == nil {
|
||||
// return empty array
|
||||
payload = models.ParityResponse{}
|
||||
}
|
||||
|
||||
if err := producer.Produce(rw, payload); err != nil {
|
||||
panic(err) // let the recovery middleware deal with this
|
||||
}
|
||||
}
|
||||
|
||||
/*GetParityDefault Generic error response.
|
||||
|
||||
swagger:response getParityDefault
|
||||
*/
|
||||
type GetParityDefault struct {
|
||||
_statusCode int
|
||||
|
||||
/*
|
||||
In: Body
|
||||
*/
|
||||
Payload *models.Error `json:"body,omitempty"`
|
||||
}
|
||||
|
||||
// NewGetParityDefault creates GetParityDefault with default headers values
|
||||
func NewGetParityDefault(code int) *GetParityDefault {
|
||||
if code <= 0 {
|
||||
code = 500
|
||||
}
|
||||
|
||||
return &GetParityDefault{
|
||||
_statusCode: code,
|
||||
}
|
||||
}
|
||||
|
||||
// WithStatusCode adds the status to the get parity default response
|
||||
func (o *GetParityDefault) WithStatusCode(code int) *GetParityDefault {
|
||||
o._statusCode = code
|
||||
return o
|
||||
}
|
||||
|
||||
// SetStatusCode sets the status to the get parity default response
|
||||
func (o *GetParityDefault) SetStatusCode(code int) {
|
||||
o._statusCode = code
|
||||
}
|
||||
|
||||
// WithPayload adds the payload to the get parity default response
|
||||
func (o *GetParityDefault) WithPayload(payload *models.Error) *GetParityDefault {
|
||||
o.Payload = payload
|
||||
return o
|
||||
}
|
||||
|
||||
// SetPayload sets the payload to the get parity default response
|
||||
func (o *GetParityDefault) SetPayload(payload *models.Error) {
|
||||
o.Payload = payload
|
||||
}
|
||||
|
||||
// WriteResponse to the client
|
||||
func (o *GetParityDefault) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) {
|
||||
|
||||
rw.WriteHeader(o._statusCode)
|
||||
if o.Payload != nil {
|
||||
payload := o.Payload
|
||||
if err := producer.Produce(rw, payload); err != nil {
|
||||
panic(err) // let the recovery middleware deal with this
|
||||
}
|
||||
}
|
||||
}
|
||||
126
restapi/operations/admin_api/get_parity_urlbuilder.go
Normal file
126
restapi/operations/admin_api/get_parity_urlbuilder.go
Normal file
@@ -0,0 +1,126 @@
|
||||
// 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 admin_api
|
||||
|
||||
// This file was generated by the swagger tool.
|
||||
// Editing this file might prove futile when you re-run the generate command
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net/url"
|
||||
golangswaggerpaths "path"
|
||||
"strings"
|
||||
|
||||
"github.com/go-openapi/swag"
|
||||
)
|
||||
|
||||
// GetParityURL generates an URL for the get parity operation
|
||||
type GetParityURL struct {
|
||||
DisksPerNode int64
|
||||
Nodes int64
|
||||
|
||||
_basePath string
|
||||
// avoid unkeyed usage
|
||||
_ struct{}
|
||||
}
|
||||
|
||||
// WithBasePath sets the base path for this url builder, only required when it's different from the
|
||||
// base path specified in the swagger spec.
|
||||
// When the value of the base path is an empty string
|
||||
func (o *GetParityURL) WithBasePath(bp string) *GetParityURL {
|
||||
o.SetBasePath(bp)
|
||||
return o
|
||||
}
|
||||
|
||||
// SetBasePath sets the base path for this url builder, only required when it's different from the
|
||||
// base path specified in the swagger spec.
|
||||
// When the value of the base path is an empty string
|
||||
func (o *GetParityURL) SetBasePath(bp string) {
|
||||
o._basePath = bp
|
||||
}
|
||||
|
||||
// Build a url path and query string
|
||||
func (o *GetParityURL) Build() (*url.URL, error) {
|
||||
var _result url.URL
|
||||
|
||||
var _path = "/get-parity/{nodes}/{disksPerNode}"
|
||||
|
||||
disksPerNode := swag.FormatInt64(o.DisksPerNode)
|
||||
if disksPerNode != "" {
|
||||
_path = strings.Replace(_path, "{disksPerNode}", disksPerNode, -1)
|
||||
} else {
|
||||
return nil, errors.New("disksPerNode is required on GetParityURL")
|
||||
}
|
||||
|
||||
nodes := swag.FormatInt64(o.Nodes)
|
||||
if nodes != "" {
|
||||
_path = strings.Replace(_path, "{nodes}", nodes, -1)
|
||||
} else {
|
||||
return nil, errors.New("nodes is required on GetParityURL")
|
||||
}
|
||||
|
||||
_basePath := o._basePath
|
||||
if _basePath == "" {
|
||||
_basePath = "/api/v1"
|
||||
}
|
||||
_result.Path = golangswaggerpaths.Join(_basePath, _path)
|
||||
|
||||
return &_result, nil
|
||||
}
|
||||
|
||||
// Must is a helper function to panic when the url builder returns an error
|
||||
func (o *GetParityURL) Must(u *url.URL, err error) *url.URL {
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if u == nil {
|
||||
panic("url can't be nil")
|
||||
}
|
||||
return u
|
||||
}
|
||||
|
||||
// String returns the string representation of the path with query string
|
||||
func (o *GetParityURL) String() string {
|
||||
return o.Must(o.Build()).String()
|
||||
}
|
||||
|
||||
// BuildFull builds a full url with scheme, host, path and query string
|
||||
func (o *GetParityURL) BuildFull(scheme, host string) (*url.URL, error) {
|
||||
if scheme == "" {
|
||||
return nil, errors.New("scheme is required for a full url on GetParityURL")
|
||||
}
|
||||
if host == "" {
|
||||
return nil, errors.New("host is required for a full url on GetParityURL")
|
||||
}
|
||||
|
||||
base, err := o.Build()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
base.Scheme = scheme
|
||||
base.Host = host
|
||||
return base, nil
|
||||
}
|
||||
|
||||
// StringFull returns the string representation of a complete url
|
||||
func (o *GetParityURL) StringFull(scheme, host string) string {
|
||||
return o.Must(o.BuildFull(scheme, host)).String()
|
||||
}
|
||||
@@ -117,6 +117,9 @@ func NewConsoleAPI(spec *loads.Document) *ConsoleAPI {
|
||||
AdminAPIGetMaxAllocatableMemHandler: admin_api.GetMaxAllocatableMemHandlerFunc(func(params admin_api.GetMaxAllocatableMemParams, principal *models.Principal) middleware.Responder {
|
||||
return middleware.NotImplemented("operation admin_api.GetMaxAllocatableMem has not yet been implemented")
|
||||
}),
|
||||
AdminAPIGetParityHandler: admin_api.GetParityHandlerFunc(func(params admin_api.GetParityParams, principal *models.Principal) middleware.Responder {
|
||||
return middleware.NotImplemented("operation admin_api.GetParity has not yet been implemented")
|
||||
}),
|
||||
AdminAPIGetResourceQuotaHandler: admin_api.GetResourceQuotaHandlerFunc(func(params admin_api.GetResourceQuotaParams, principal *models.Principal) middleware.Responder {
|
||||
return middleware.NotImplemented("operation admin_api.GetResourceQuota has not yet been implemented")
|
||||
}),
|
||||
@@ -319,6 +322,8 @@ type ConsoleAPI struct {
|
||||
AdminAPIDeleteTenantHandler admin_api.DeleteTenantHandler
|
||||
// AdminAPIGetMaxAllocatableMemHandler sets the operation handler for the get max allocatable mem operation
|
||||
AdminAPIGetMaxAllocatableMemHandler admin_api.GetMaxAllocatableMemHandler
|
||||
// AdminAPIGetParityHandler sets the operation handler for the get parity operation
|
||||
AdminAPIGetParityHandler admin_api.GetParityHandler
|
||||
// AdminAPIGetResourceQuotaHandler sets the operation handler for the get resource quota operation
|
||||
AdminAPIGetResourceQuotaHandler admin_api.GetResourceQuotaHandler
|
||||
// AdminAPIGetTenantUsageHandler sets the operation handler for the get tenant usage operation
|
||||
@@ -524,6 +529,9 @@ func (o *ConsoleAPI) Validate() error {
|
||||
if o.AdminAPIGetMaxAllocatableMemHandler == nil {
|
||||
unregistered = append(unregistered, "admin_api.GetMaxAllocatableMemHandler")
|
||||
}
|
||||
if o.AdminAPIGetParityHandler == nil {
|
||||
unregistered = append(unregistered, "admin_api.GetParityHandler")
|
||||
}
|
||||
if o.AdminAPIGetResourceQuotaHandler == nil {
|
||||
unregistered = append(unregistered, "admin_api.GetResourceQuotaHandler")
|
||||
}
|
||||
@@ -816,6 +824,10 @@ func (o *ConsoleAPI) initHandlerCache() {
|
||||
if o.handlers["GET"] == nil {
|
||||
o.handlers["GET"] = make(map[string]http.Handler)
|
||||
}
|
||||
o.handlers["GET"]["/get-parity/{nodes}/{disksPerNode}"] = admin_api.NewGetParity(o.context, o.AdminAPIGetParityHandler)
|
||||
if o.handlers["GET"] == nil {
|
||||
o.handlers["GET"] = make(map[string]http.Handler)
|
||||
}
|
||||
o.handlers["GET"]["/namespaces/{namespace}/resourcequotas/{resource-quota-name}"] = admin_api.NewGetResourceQuota(o.context, o.AdminAPIGetResourceQuotaHandler)
|
||||
if o.handlers["GET"] == nil {
|
||||
o.handlers["GET"] = make(map[string]http.Handler)
|
||||
|
||||
99
swagger.yml
99
swagger.yml
@@ -1306,6 +1306,33 @@ paths:
|
||||
tags:
|
||||
- AdminAPI
|
||||
|
||||
/get-parity/{nodes}/{disksPerNode}:
|
||||
get:
|
||||
summary: Gets parity by sending number of nodes & number of disks
|
||||
operationId: GetParity
|
||||
parameters:
|
||||
- name: nodes
|
||||
in: path
|
||||
required: true
|
||||
type: integer
|
||||
minimum: 2
|
||||
- name: disksPerNode
|
||||
in: path
|
||||
required: true
|
||||
type: integer
|
||||
minimum: 1
|
||||
responses:
|
||||
200:
|
||||
description: A successful response.
|
||||
schema:
|
||||
$ref: "#/definitions/parityResponse"
|
||||
default:
|
||||
description: Generic error response.
|
||||
schema:
|
||||
$ref: "#/definitions/error"
|
||||
tags:
|
||||
- AdminAPI
|
||||
|
||||
definitions:
|
||||
bucketAccess:
|
||||
type: string
|
||||
@@ -1983,6 +2010,25 @@ definitions:
|
||||
encryption:
|
||||
type: object
|
||||
$ref: "#/definitions/encryptionConfiguration"
|
||||
console:
|
||||
type: object
|
||||
$ref: '#/definitions/consoleConfiguration'
|
||||
|
||||
metadataFields:
|
||||
type: object
|
||||
properties:
|
||||
annotations:
|
||||
type: object
|
||||
additionalProperties:
|
||||
type: string
|
||||
labels:
|
||||
type: object
|
||||
additionalProperties:
|
||||
type: string
|
||||
node_selector:
|
||||
type: object
|
||||
additionalProperties:
|
||||
type: string
|
||||
|
||||
keyPairConfiguration:
|
||||
type: object
|
||||
@@ -2045,26 +2091,36 @@ definitions:
|
||||
server_insecure:
|
||||
type: boolean
|
||||
|
||||
consoleConfiguration:
|
||||
allOf:
|
||||
- $ref: '#/definitions/metadataFields'
|
||||
- type: object
|
||||
properties:
|
||||
image:
|
||||
type: string
|
||||
|
||||
encryptionConfiguration:
|
||||
type: object
|
||||
properties:
|
||||
image:
|
||||
type: string
|
||||
server:
|
||||
type: object
|
||||
$ref: "#/definitions/keyPairConfiguration"
|
||||
client:
|
||||
type: object
|
||||
$ref: "#/definitions/keyPairConfiguration"
|
||||
gemalto:
|
||||
type: object
|
||||
$ref: "#/definitions/gemaltoConfiguration"
|
||||
aws:
|
||||
type: object
|
||||
$ref: "#/definitions/awsConfiguration"
|
||||
vault:
|
||||
type: object
|
||||
$ref: "#/definitions/vaultConfiguration"
|
||||
allOf:
|
||||
- $ref: '#/definitions/metadataFields'
|
||||
- type: object
|
||||
properties:
|
||||
image:
|
||||
type: string
|
||||
server:
|
||||
type: object
|
||||
$ref: "#/definitions/keyPairConfiguration"
|
||||
client:
|
||||
type: object
|
||||
$ref: "#/definitions/keyPairConfiguration"
|
||||
gemalto:
|
||||
type: object
|
||||
$ref: "#/definitions/gemaltoConfiguration"
|
||||
aws:
|
||||
type: object
|
||||
$ref: "#/definitions/awsConfiguration"
|
||||
vault:
|
||||
type: object
|
||||
$ref: "#/definitions/vaultConfiguration"
|
||||
|
||||
vaultConfiguration:
|
||||
type: object
|
||||
@@ -2677,3 +2733,8 @@ definitions:
|
||||
max_memory:
|
||||
type: integer
|
||||
format: int64
|
||||
|
||||
parityResponse:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
|
||||
Reference in New Issue
Block a user