Compare commits
49 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
812fd5f253 | ||
|
|
da9b393e1b | ||
|
|
aeaa1a23ce | ||
|
|
a8d403a216 | ||
|
|
7bd898b2c7 | ||
|
|
dad66db49a | ||
|
|
adf3f929a4 | ||
|
|
3b23e877b5 | ||
|
|
af4bebb6eb | ||
|
|
8530eb5368 | ||
|
|
0ba1e76400 | ||
|
|
94096ee657 | ||
|
|
c59387c2b4 | ||
|
|
c5a3eff745 | ||
|
|
624891ae1f | ||
|
|
83435e1ab9 | ||
|
|
2b4606e773 | ||
|
|
30f5943f8a | ||
|
|
412ac0a603 | ||
|
|
b2aa1349f8 | ||
|
|
8b62aec7fb | ||
|
|
83fe33b499 | ||
|
|
54d0a1d342 | ||
|
|
c59737a71d | ||
|
|
7c2ba707eb | ||
|
|
545a890c45 | ||
|
|
4b42308484 | ||
|
|
5a95fed35b | ||
|
|
f880e3976f | ||
|
|
25fa2f3275 | ||
|
|
9f005b7537 | ||
|
|
1ad6e977f2 | ||
|
|
e9a64c5479 | ||
|
|
a2e7259ccb | ||
|
|
d28e66a353 | ||
|
|
e0ff6623bb | ||
|
|
3d59e9ac30 | ||
|
|
cff712f071 | ||
|
|
b8bca9d2fe | ||
|
|
a6ccae52d2 | ||
|
|
bdfa6dc9bf | ||
|
|
6eb5731eb5 | ||
|
|
953574f7a3 | ||
|
|
8ec6d695de | ||
|
|
47274817fa | ||
|
|
3b123c6182 | ||
|
|
d7f72e0c41 | ||
|
|
c0bf9c5da8 | ||
|
|
16a6524b11 |
@@ -47,12 +47,12 @@ var serverCmd = cli.Command{
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "tls-host",
|
||||
Value: restapi.GetSSLHostname(),
|
||||
Value: restapi.GetTLSHostname(),
|
||||
Usage: "HTTPS server hostname",
|
||||
},
|
||||
cli.IntFlag{
|
||||
Name: "tls-port",
|
||||
Value: restapi.GetSSLPort(),
|
||||
Value: restapi.GetTLSPort(),
|
||||
Usage: "HTTPS server port",
|
||||
},
|
||||
cli.StringFlag{
|
||||
|
||||
21
go.mod
21
go.mod
@@ -15,19 +15,20 @@ require (
|
||||
github.com/gorilla/websocket v1.4.2
|
||||
github.com/jessevdk/go-flags v1.4.0
|
||||
github.com/minio/cli v1.22.0
|
||||
github.com/minio/kes v0.10.1
|
||||
github.com/minio/mc v0.0.0-20200725183142-90d22b271f60
|
||||
github.com/minio/minio v0.0.0-20200725154241-abbf6ce6ccf8
|
||||
github.com/minio/minio-go/v7 v7.0.2-0.20200722162308-e0105ca08252
|
||||
github.com/minio/operator v0.0.0-20200730044813-c2895a5065a1
|
||||
github.com/minio/kes v0.11.0
|
||||
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/pquerna/cachecontrol v0.0.0-20180517163645-1555304b9b35 // indirect
|
||||
github.com/secure-io/sio-go v0.3.1
|
||||
github.com/stretchr/testify v1.6.1
|
||||
github.com/unrolled/secure v1.0.7
|
||||
golang.org/x/crypto v0.0.0-20200709230013-948cd5f35899
|
||||
golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de
|
||||
golang.org/x/net v0.0.0-20200707034311-ab3426394381
|
||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45
|
||||
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d
|
||||
gopkg.in/yaml.v2 v2.3.0
|
||||
k8s.io/api v0.18.0
|
||||
k8s.io/apimachinery v0.18.0
|
||||
k8s.io/client-go v0.18.0
|
||||
k8s.io/api v0.18.6
|
||||
k8s.io/apimachinery v0.18.6
|
||||
k8s.io/client-go v0.18.6
|
||||
)
|
||||
|
||||
@@ -15,7 +15,7 @@ spec:
|
||||
serviceAccountName: console-sa
|
||||
containers:
|
||||
- name: console
|
||||
image: minio/console:v0.3.7
|
||||
image: minio/console:v0.3.23
|
||||
imagePullPolicy: "IfNotPresent"
|
||||
args:
|
||||
- server
|
||||
|
||||
@@ -8,4 +8,4 @@ resources:
|
||||
- console-configmap.yaml
|
||||
- console-service.yaml
|
||||
- console-deployment.yaml
|
||||
- minio-operator.yaml
|
||||
- https://github.com/minio/operator/?ref=v3.0.10
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -14,6 +14,7 @@ rules:
|
||||
- list
|
||||
- patch
|
||||
- update
|
||||
- deletecollection
|
||||
- apiGroups:
|
||||
- ""
|
||||
resources:
|
||||
@@ -22,12 +23,21 @@ rules:
|
||||
- services
|
||||
- events
|
||||
- resourcequotas
|
||||
- nodes
|
||||
verbs:
|
||||
- get
|
||||
- watch
|
||||
- create
|
||||
- list
|
||||
- patch
|
||||
- apiGroups:
|
||||
- ""
|
||||
resources:
|
||||
- persistentvolumeclaims
|
||||
verbs:
|
||||
- deletecollection
|
||||
- list
|
||||
- get
|
||||
- apiGroups:
|
||||
- "storage.k8s.io"
|
||||
resources:
|
||||
|
||||
@@ -15,7 +15,7 @@ spec:
|
||||
serviceAccountName: console-sa
|
||||
containers:
|
||||
- name: console
|
||||
image: minio/console:v0.3.7
|
||||
image: minio/console:v0.3.23
|
||||
imagePullPolicy: "IfNotPresent"
|
||||
env:
|
||||
- name: CONSOLE_OPERATOR_MODE
|
||||
|
||||
@@ -8,4 +8,4 @@ resources:
|
||||
- console-configmap.yaml
|
||||
- console-service.yaml
|
||||
- console-deployment.yaml
|
||||
- minio-operator.yaml
|
||||
- https://github.com/minio/operator/?ref=v3.0.10
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -42,11 +42,17 @@ type CreateTenantRequest struct {
|
||||
// annotations
|
||||
Annotations map[string]string `json:"annotations,omitempty"`
|
||||
|
||||
// console image
|
||||
ConsoleImage string `json:"console_image,omitempty"`
|
||||
|
||||
// enable console
|
||||
EnableConsole *bool `json:"enable_console,omitempty"`
|
||||
|
||||
// enable ssl
|
||||
EnableSsl *bool `json:"enable_ssl,omitempty"`
|
||||
// enable prometheus
|
||||
EnablePrometheus *bool `json:"enable_prometheus,omitempty"`
|
||||
|
||||
// enable tls
|
||||
EnableTLS *bool `json:"enable_tls,omitempty"`
|
||||
|
||||
// encryption
|
||||
Encryption *EncryptionConfiguration `json:"encryption,omitempty"`
|
||||
@@ -60,6 +66,9 @@ type CreateTenantRequest struct {
|
||||
// image
|
||||
Image string `json:"image,omitempty"`
|
||||
|
||||
// image pull secret
|
||||
ImagePullSecret string `json:"image_pull_secret,omitempty"`
|
||||
|
||||
// image registry
|
||||
ImageRegistry *ImageRegistry `json:"image_registry,omitempty"`
|
||||
|
||||
|
||||
60
models/delete_tenant_request.go
Normal file
60
models/delete_tenant_request.go
Normal file
@@ -0,0 +1,60 @@
|
||||
// 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"
|
||||
)
|
||||
|
||||
// DeleteTenantRequest delete tenant request
|
||||
//
|
||||
// swagger:model deleteTenantRequest
|
||||
type DeleteTenantRequest struct {
|
||||
|
||||
// delete pvcs
|
||||
DeletePvcs bool `json:"delete_pvcs,omitempty"`
|
||||
}
|
||||
|
||||
// Validate validates this delete tenant request
|
||||
func (m *DeleteTenantRequest) Validate(formats strfmt.Registry) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// MarshalBinary interface implementation
|
||||
func (m *DeleteTenantRequest) MarshalBinary() ([]byte, error) {
|
||||
if m == nil {
|
||||
return nil, nil
|
||||
}
|
||||
return swag.WriteJSON(m)
|
||||
}
|
||||
|
||||
// UnmarshalBinary interface implementation
|
||||
func (m *DeleteTenantRequest) UnmarshalBinary(b []byte) error {
|
||||
var res DeleteTenantRequest
|
||||
if err := swag.ReadJSON(b, &res); err != nil {
|
||||
return err
|
||||
}
|
||||
*m = res
|
||||
return nil
|
||||
}
|
||||
@@ -26,7 +26,6 @@ import (
|
||||
"github.com/go-openapi/errors"
|
||||
"github.com/go-openapi/strfmt"
|
||||
"github.com/go-openapi/swag"
|
||||
"github.com/go-openapi/validate"
|
||||
)
|
||||
|
||||
// EncryptionConfiguration encryption configuration
|
||||
@@ -38,7 +37,7 @@ type EncryptionConfiguration struct {
|
||||
Aws *AwsConfiguration `json:"aws,omitempty"`
|
||||
|
||||
// client
|
||||
Client *EncryptionConfigurationClient `json:"client,omitempty"`
|
||||
Client *KeyPairConfiguration `json:"client,omitempty"`
|
||||
|
||||
// gemalto
|
||||
Gemalto *GemaltoConfiguration `json:"gemalto,omitempty"`
|
||||
@@ -46,11 +45,8 @@ type EncryptionConfiguration struct {
|
||||
// image
|
||||
Image string `json:"image,omitempty"`
|
||||
|
||||
// master key
|
||||
MasterKey string `json:"master_key,omitempty"`
|
||||
|
||||
// server
|
||||
Server *EncryptionConfigurationServer `json:"server,omitempty"`
|
||||
Server *KeyPairConfiguration `json:"server,omitempty"`
|
||||
|
||||
// vault
|
||||
Vault *VaultConfiguration `json:"vault,omitempty"`
|
||||
@@ -193,139 +189,3 @@ func (m *EncryptionConfiguration) UnmarshalBinary(b []byte) error {
|
||||
*m = res
|
||||
return nil
|
||||
}
|
||||
|
||||
// EncryptionConfigurationClient encryption configuration client
|
||||
//
|
||||
// swagger:model EncryptionConfigurationClient
|
||||
type EncryptionConfigurationClient struct {
|
||||
|
||||
// crt
|
||||
// Required: true
|
||||
Crt *string `json:"crt"`
|
||||
|
||||
// key
|
||||
// Required: true
|
||||
Key *string `json:"key"`
|
||||
}
|
||||
|
||||
// Validate validates this encryption configuration client
|
||||
func (m *EncryptionConfigurationClient) Validate(formats strfmt.Registry) error {
|
||||
var res []error
|
||||
|
||||
if err := m.validateCrt(formats); err != nil {
|
||||
res = append(res, err)
|
||||
}
|
||||
|
||||
if err := m.validateKey(formats); err != nil {
|
||||
res = append(res, err)
|
||||
}
|
||||
|
||||
if len(res) > 0 {
|
||||
return errors.CompositeValidationError(res...)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *EncryptionConfigurationClient) validateCrt(formats strfmt.Registry) error {
|
||||
|
||||
if err := validate.Required("client"+"."+"crt", "body", m.Crt); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *EncryptionConfigurationClient) validateKey(formats strfmt.Registry) error {
|
||||
|
||||
if err := validate.Required("client"+"."+"key", "body", m.Key); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// MarshalBinary interface implementation
|
||||
func (m *EncryptionConfigurationClient) MarshalBinary() ([]byte, error) {
|
||||
if m == nil {
|
||||
return nil, nil
|
||||
}
|
||||
return swag.WriteJSON(m)
|
||||
}
|
||||
|
||||
// UnmarshalBinary interface implementation
|
||||
func (m *EncryptionConfigurationClient) UnmarshalBinary(b []byte) error {
|
||||
var res EncryptionConfigurationClient
|
||||
if err := swag.ReadJSON(b, &res); err != nil {
|
||||
return err
|
||||
}
|
||||
*m = res
|
||||
return nil
|
||||
}
|
||||
|
||||
// EncryptionConfigurationServer encryption configuration server
|
||||
//
|
||||
// swagger:model EncryptionConfigurationServer
|
||||
type EncryptionConfigurationServer struct {
|
||||
|
||||
// crt
|
||||
// Required: true
|
||||
Crt *string `json:"crt"`
|
||||
|
||||
// key
|
||||
// Required: true
|
||||
Key *string `json:"key"`
|
||||
}
|
||||
|
||||
// Validate validates this encryption configuration server
|
||||
func (m *EncryptionConfigurationServer) Validate(formats strfmt.Registry) error {
|
||||
var res []error
|
||||
|
||||
if err := m.validateCrt(formats); err != nil {
|
||||
res = append(res, err)
|
||||
}
|
||||
|
||||
if err := m.validateKey(formats); err != nil {
|
||||
res = append(res, err)
|
||||
}
|
||||
|
||||
if len(res) > 0 {
|
||||
return errors.CompositeValidationError(res...)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *EncryptionConfigurationServer) validateCrt(formats strfmt.Registry) error {
|
||||
|
||||
if err := validate.Required("server"+"."+"crt", "body", m.Crt); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *EncryptionConfigurationServer) validateKey(formats strfmt.Registry) error {
|
||||
|
||||
if err := validate.Required("server"+"."+"key", "body", m.Key); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// MarshalBinary interface implementation
|
||||
func (m *EncryptionConfigurationServer) MarshalBinary() ([]byte, error) {
|
||||
if m == nil {
|
||||
return nil, nil
|
||||
}
|
||||
return swag.WriteJSON(m)
|
||||
}
|
||||
|
||||
// UnmarshalBinary interface implementation
|
||||
func (m *EncryptionConfigurationServer) UnmarshalBinary(b []byte) error {
|
||||
var res EncryptionConfigurationServer
|
||||
if err := swag.ReadJSON(b, &res); err != nil {
|
||||
return err
|
||||
}
|
||||
*m = res
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ import (
|
||||
type Error struct {
|
||||
|
||||
// code
|
||||
Code int64 `json:"code,omitempty"`
|
||||
Code int32 `json:"code,omitempty"`
|
||||
|
||||
// message
|
||||
// Required: true
|
||||
|
||||
@@ -130,8 +130,8 @@ type IdpConfigurationActiveDirectory struct {
|
||||
// server insecure
|
||||
ServerInsecure bool `json:"server_insecure,omitempty"`
|
||||
|
||||
// skip ssl verification
|
||||
SkipSslVerification bool `json:"skip_ssl_verification,omitempty"`
|
||||
// skip tls verification
|
||||
SkipTLSVerification bool `json:"skip_tls_verification,omitempty"`
|
||||
|
||||
// url
|
||||
// Required: true
|
||||
|
||||
98
models/key_pair_configuration.go
Normal file
98
models/key_pair_configuration.go
Normal file
@@ -0,0 +1,98 @@
|
||||
// Code generated by go-swagger; DO NOT EDIT.
|
||||
|
||||
// This file is part of MinIO Console Server
|
||||
// Copyright (c) 2020 MinIO, Inc.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
package models
|
||||
|
||||
// This file was generated by the swagger tool.
|
||||
// Editing this file might prove futile when you re-run the swagger generate command
|
||||
|
||||
import (
|
||||
"github.com/go-openapi/errors"
|
||||
"github.com/go-openapi/strfmt"
|
||||
"github.com/go-openapi/swag"
|
||||
"github.com/go-openapi/validate"
|
||||
)
|
||||
|
||||
// KeyPairConfiguration key pair configuration
|
||||
//
|
||||
// swagger:model keyPairConfiguration
|
||||
type KeyPairConfiguration struct {
|
||||
|
||||
// crt
|
||||
// Required: true
|
||||
Crt *string `json:"crt"`
|
||||
|
||||
// key
|
||||
// Required: true
|
||||
Key *string `json:"key"`
|
||||
}
|
||||
|
||||
// Validate validates this key pair configuration
|
||||
func (m *KeyPairConfiguration) Validate(formats strfmt.Registry) error {
|
||||
var res []error
|
||||
|
||||
if err := m.validateCrt(formats); err != nil {
|
||||
res = append(res, err)
|
||||
}
|
||||
|
||||
if err := m.validateKey(formats); err != nil {
|
||||
res = append(res, err)
|
||||
}
|
||||
|
||||
if len(res) > 0 {
|
||||
return errors.CompositeValidationError(res...)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *KeyPairConfiguration) validateCrt(formats strfmt.Registry) error {
|
||||
|
||||
if err := validate.Required("crt", "body", m.Crt); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *KeyPairConfiguration) validateKey(formats strfmt.Registry) error {
|
||||
|
||||
if err := validate.Required("key", "body", m.Key); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// MarshalBinary interface implementation
|
||||
func (m *KeyPairConfiguration) MarshalBinary() ([]byte, error) {
|
||||
if m == nil {
|
||||
return nil, nil
|
||||
}
|
||||
return swag.WriteJSON(m)
|
||||
}
|
||||
|
||||
// UnmarshalBinary interface implementation
|
||||
func (m *KeyPairConfiguration) UnmarshalBinary(b []byte) error {
|
||||
var res KeyPairConfiguration
|
||||
if err := swag.ReadJSON(b, &res); err != nil {
|
||||
return err
|
||||
}
|
||||
*m = res
|
||||
return nil
|
||||
}
|
||||
60
models/max_allocatable_mem_response.go
Normal file
60
models/max_allocatable_mem_response.go
Normal file
@@ -0,0 +1,60 @@
|
||||
// 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"
|
||||
)
|
||||
|
||||
// MaxAllocatableMemResponse max allocatable mem response
|
||||
//
|
||||
// swagger:model maxAllocatableMemResponse
|
||||
type MaxAllocatableMemResponse struct {
|
||||
|
||||
// max memory
|
||||
MaxMemory int64 `json:"max_memory,omitempty"`
|
||||
}
|
||||
|
||||
// Validate validates this max allocatable mem response
|
||||
func (m *MaxAllocatableMemResponse) Validate(formats strfmt.Registry) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// MarshalBinary interface implementation
|
||||
func (m *MaxAllocatableMemResponse) MarshalBinary() ([]byte, error) {
|
||||
if m == nil {
|
||||
return nil, nil
|
||||
}
|
||||
return swag.WriteJSON(m)
|
||||
}
|
||||
|
||||
// UnmarshalBinary interface implementation
|
||||
func (m *MaxAllocatableMemResponse) UnmarshalBinary(b []byte) error {
|
||||
var res MaxAllocatableMemResponse
|
||||
if err := swag.ReadJSON(b, &res); err != nil {
|
||||
return err
|
||||
}
|
||||
*m = res
|
||||
return nil
|
||||
}
|
||||
@@ -35,12 +35,21 @@ import (
|
||||
// swagger:model tenant
|
||||
type Tenant struct {
|
||||
|
||||
// console image
|
||||
ConsoleImage string `json:"console_image,omitempty"`
|
||||
|
||||
// creation date
|
||||
CreationDate string `json:"creation_date,omitempty"`
|
||||
|
||||
// current state
|
||||
CurrentState string `json:"currentState,omitempty"`
|
||||
|
||||
// deletion date
|
||||
DeletionDate string `json:"deletion_date,omitempty"`
|
||||
|
||||
// enable prometheus
|
||||
EnablePrometheus bool `json:"enable_prometheus,omitempty"`
|
||||
|
||||
// image
|
||||
Image string `json:"image,omitempty"`
|
||||
|
||||
|
||||
@@ -38,6 +38,9 @@ type TenantList struct {
|
||||
// current state
|
||||
CurrentState string `json:"currentState,omitempty"`
|
||||
|
||||
// deletion date
|
||||
DeletionDate string `json:"deletion_date,omitempty"`
|
||||
|
||||
// instance count
|
||||
InstanceCount int64 `json:"instance_count,omitempty"`
|
||||
|
||||
|
||||
@@ -26,7 +26,6 @@ import (
|
||||
"github.com/go-openapi/errors"
|
||||
"github.com/go-openapi/strfmt"
|
||||
"github.com/go-openapi/swag"
|
||||
"github.com/go-openapi/validate"
|
||||
)
|
||||
|
||||
// TLSConfiguration tls configuration
|
||||
@@ -34,24 +33,22 @@ import (
|
||||
// swagger:model tlsConfiguration
|
||||
type TLSConfiguration struct {
|
||||
|
||||
// crt
|
||||
// Required: true
|
||||
Crt *string `json:"crt"`
|
||||
// console
|
||||
Console *KeyPairConfiguration `json:"console,omitempty"`
|
||||
|
||||
// key
|
||||
// Required: true
|
||||
Key *string `json:"key"`
|
||||
// minio
|
||||
Minio *KeyPairConfiguration `json:"minio,omitempty"`
|
||||
}
|
||||
|
||||
// Validate validates this tls configuration
|
||||
func (m *TLSConfiguration) Validate(formats strfmt.Registry) error {
|
||||
var res []error
|
||||
|
||||
if err := m.validateCrt(formats); err != nil {
|
||||
if err := m.validateConsole(formats); err != nil {
|
||||
res = append(res, err)
|
||||
}
|
||||
|
||||
if err := m.validateKey(formats); err != nil {
|
||||
if err := m.validateMinio(formats); err != nil {
|
||||
res = append(res, err)
|
||||
}
|
||||
|
||||
@@ -61,19 +58,37 @@ func (m *TLSConfiguration) Validate(formats strfmt.Registry) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *TLSConfiguration) validateCrt(formats strfmt.Registry) error {
|
||||
func (m *TLSConfiguration) validateConsole(formats strfmt.Registry) error {
|
||||
|
||||
if err := validate.Required("crt", "body", m.Crt); err != nil {
|
||||
return err
|
||||
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 *TLSConfiguration) validateKey(formats strfmt.Registry) error {
|
||||
func (m *TLSConfiguration) validateMinio(formats strfmt.Registry) error {
|
||||
|
||||
if err := validate.Required("key", "body", m.Key); err != nil {
|
||||
return err
|
||||
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
|
||||
|
||||
@@ -34,10 +34,20 @@ import (
|
||||
// swagger:model updateTenantRequest
|
||||
type UpdateTenantRequest struct {
|
||||
|
||||
// console image
|
||||
// Pattern: ^((.*?)/(.*?):(.+))$
|
||||
ConsoleImage string `json:"console_image,omitempty"`
|
||||
|
||||
// enable prometheus
|
||||
EnablePrometheus bool `json:"enable_prometheus,omitempty"`
|
||||
|
||||
// image
|
||||
// Pattern: ^((.*?)/(.*?):(.+))$
|
||||
Image string `json:"image,omitempty"`
|
||||
|
||||
// image pull secret
|
||||
ImagePullSecret string `json:"image_pull_secret,omitempty"`
|
||||
|
||||
// image registry
|
||||
ImageRegistry *ImageRegistry `json:"image_registry,omitempty"`
|
||||
}
|
||||
@@ -46,6 +56,10 @@ type UpdateTenantRequest struct {
|
||||
func (m *UpdateTenantRequest) Validate(formats strfmt.Registry) error {
|
||||
var res []error
|
||||
|
||||
if err := m.validateConsoleImage(formats); err != nil {
|
||||
res = append(res, err)
|
||||
}
|
||||
|
||||
if err := m.validateImage(formats); err != nil {
|
||||
res = append(res, err)
|
||||
}
|
||||
@@ -60,6 +74,19 @@ func (m *UpdateTenantRequest) Validate(formats strfmt.Registry) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *UpdateTenantRequest) validateConsoleImage(formats strfmt.Registry) error {
|
||||
|
||||
if swag.IsZero(m.ConsoleImage) { // not required
|
||||
return nil
|
||||
}
|
||||
|
||||
if err := validate.Pattern("console_image", "body", string(m.ConsoleImage), `^((.*?)/(.*?):(.+))$`); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *UpdateTenantRequest) validateImage(formats strfmt.Registry) error {
|
||||
|
||||
if swag.IsZero(m.Image) { // not required
|
||||
|
||||
@@ -53,6 +53,9 @@ type VaultConfiguration struct {
|
||||
|
||||
// status
|
||||
Status *VaultConfigurationStatus `json:"status,omitempty"`
|
||||
|
||||
// tls
|
||||
TLS *VaultConfigurationTLS `json:"tls,omitempty"`
|
||||
}
|
||||
|
||||
// Validate validates this vault configuration
|
||||
@@ -71,6 +74,10 @@ func (m *VaultConfiguration) Validate(formats strfmt.Registry) error {
|
||||
res = append(res, err)
|
||||
}
|
||||
|
||||
if err := m.validateTLS(formats); err != nil {
|
||||
res = append(res, err)
|
||||
}
|
||||
|
||||
if len(res) > 0 {
|
||||
return errors.CompositeValidationError(res...)
|
||||
}
|
||||
@@ -122,6 +129,24 @@ func (m *VaultConfiguration) validateStatus(formats strfmt.Registry) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *VaultConfiguration) validateTLS(formats strfmt.Registry) error {
|
||||
|
||||
if swag.IsZero(m.TLS) { // not required
|
||||
return nil
|
||||
}
|
||||
|
||||
if m.TLS != nil {
|
||||
if err := m.TLS.Validate(formats); err != nil {
|
||||
if ve, ok := err.(*errors.Validation); ok {
|
||||
return ve.ValidateName("tls")
|
||||
}
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// MarshalBinary interface implementation
|
||||
func (m *VaultConfiguration) MarshalBinary() ([]byte, error) {
|
||||
if m == nil {
|
||||
@@ -245,3 +270,41 @@ func (m *VaultConfigurationStatus) UnmarshalBinary(b []byte) error {
|
||||
*m = res
|
||||
return nil
|
||||
}
|
||||
|
||||
// VaultConfigurationTLS vault configuration TLS
|
||||
//
|
||||
// swagger:model VaultConfigurationTLS
|
||||
type VaultConfigurationTLS struct {
|
||||
|
||||
// ca
|
||||
Ca string `json:"ca,omitempty"`
|
||||
|
||||
// crt
|
||||
Crt string `json:"crt,omitempty"`
|
||||
|
||||
// key
|
||||
Key string `json:"key,omitempty"`
|
||||
}
|
||||
|
||||
// Validate validates this vault configuration TLS
|
||||
func (m *VaultConfigurationTLS) Validate(formats strfmt.Registry) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// MarshalBinary interface implementation
|
||||
func (m *VaultConfigurationTLS) MarshalBinary() ([]byte, error) {
|
||||
if m == nil {
|
||||
return nil, nil
|
||||
}
|
||||
return swag.WriteJSON(m)
|
||||
}
|
||||
|
||||
// UnmarshalBinary interface implementation
|
||||
func (m *VaultConfigurationTLS) UnmarshalBinary(b []byte) error {
|
||||
var res VaultConfigurationTLS
|
||||
if err := swag.ReadJSON(b, &res); err != nil {
|
||||
return err
|
||||
}
|
||||
*m = res
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -207,6 +207,9 @@ func (m *Zone) UnmarshalBinary(b []byte) error {
|
||||
// swagger:model ZoneVolumeConfiguration
|
||||
type ZoneVolumeConfiguration struct {
|
||||
|
||||
// labels
|
||||
Labels map[string]string `json:"labels,omitempty"`
|
||||
|
||||
// size
|
||||
// Required: true
|
||||
Size *int64 `json:"size"`
|
||||
|
||||
81
models/zone_toleration_seconds.go
Normal file
81
models/zone_toleration_seconds.go
Normal file
@@ -0,0 +1,81 @@
|
||||
// Code generated by go-swagger; DO NOT EDIT.
|
||||
|
||||
// This file is part of MinIO Console Server
|
||||
// Copyright (c) 2020 MinIO, Inc.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
package models
|
||||
|
||||
// This file was generated by the swagger tool.
|
||||
// Editing this file might prove futile when you re-run the swagger generate command
|
||||
|
||||
import (
|
||||
"github.com/go-openapi/errors"
|
||||
"github.com/go-openapi/strfmt"
|
||||
"github.com/go-openapi/swag"
|
||||
"github.com/go-openapi/validate"
|
||||
)
|
||||
|
||||
// ZoneTolerationSeconds TolerationSeconds represents the period of time the toleration (which must be of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, it is not set, which means tolerate the taint forever (do not evict). Zero and negative values will be treated as 0 (evict immediately) by the system.
|
||||
//
|
||||
// swagger:model zoneTolerationSeconds
|
||||
type ZoneTolerationSeconds struct {
|
||||
|
||||
// seconds
|
||||
// Required: true
|
||||
Seconds *int64 `json:"seconds"`
|
||||
}
|
||||
|
||||
// Validate validates this zone toleration seconds
|
||||
func (m *ZoneTolerationSeconds) Validate(formats strfmt.Registry) error {
|
||||
var res []error
|
||||
|
||||
if err := m.validateSeconds(formats); err != nil {
|
||||
res = append(res, err)
|
||||
}
|
||||
|
||||
if len(res) > 0 {
|
||||
return errors.CompositeValidationError(res...)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *ZoneTolerationSeconds) validateSeconds(formats strfmt.Registry) error {
|
||||
|
||||
if err := validate.Required("seconds", "body", m.Seconds); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// MarshalBinary interface implementation
|
||||
func (m *ZoneTolerationSeconds) MarshalBinary() ([]byte, error) {
|
||||
if m == nil {
|
||||
return nil, nil
|
||||
}
|
||||
return swag.WriteJSON(m)
|
||||
}
|
||||
|
||||
// UnmarshalBinary interface implementation
|
||||
func (m *ZoneTolerationSeconds) UnmarshalBinary(b []byte) error {
|
||||
var res ZoneTolerationSeconds
|
||||
if err := swag.ReadJSON(b, &res); err != nil {
|
||||
return err
|
||||
}
|
||||
*m = res
|
||||
return nil
|
||||
}
|
||||
@@ -75,8 +75,8 @@ type ZoneTolerationsItems0 struct {
|
||||
// Operator represents a key's relationship to the value. Valid operators are Exists and Equal. Defaults to Equal. Exists is equivalent to wildcard for value, so that a pod can tolerate all taints of a particular category.
|
||||
Operator string `json:"operator,omitempty"`
|
||||
|
||||
// TolerationSeconds represents the period of time the toleration (which must be of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, it is not set, which means tolerate the taint forever (do not evict). Zero and negative values will be treated as 0 (evict immediately) by the system.
|
||||
TolerationSeconds int64 `json:"tolerationSeconds,omitempty"`
|
||||
// toleration seconds
|
||||
TolerationSeconds *ZoneTolerationSeconds `json:"tolerationSeconds,omitempty"`
|
||||
|
||||
// Value is the taint value the toleration matches to. If the operator is Exists, the value should be empty, otherwise just a regular string.
|
||||
Value string `json:"value,omitempty"`
|
||||
@@ -84,6 +84,33 @@ type ZoneTolerationsItems0 struct {
|
||||
|
||||
// Validate validates this zone tolerations items0
|
||||
func (m *ZoneTolerationsItems0) Validate(formats strfmt.Registry) error {
|
||||
var res []error
|
||||
|
||||
if err := m.validateTolerationSeconds(formats); err != nil {
|
||||
res = append(res, err)
|
||||
}
|
||||
|
||||
if len(res) > 0 {
|
||||
return errors.CompositeValidationError(res...)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *ZoneTolerationsItems0) validateTolerationSeconds(formats strfmt.Registry) error {
|
||||
|
||||
if swag.IsZero(m.TolerationSeconds) { // not required
|
||||
return nil
|
||||
}
|
||||
|
||||
if m.TolerationSeconds != nil {
|
||||
if err := m.TolerationSeconds.Validate(formats); err != nil {
|
||||
if ve, ok := err.(*errors.Validation); ok {
|
||||
return ve.ValidateName("tolerationSeconds")
|
||||
}
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
99
models/zone_update_request.go
Normal file
99
models/zone_update_request.go
Normal file
@@ -0,0 +1,99 @@
|
||||
// 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 (
|
||||
"strconv"
|
||||
|
||||
"github.com/go-openapi/errors"
|
||||
"github.com/go-openapi/strfmt"
|
||||
"github.com/go-openapi/swag"
|
||||
"github.com/go-openapi/validate"
|
||||
)
|
||||
|
||||
// ZoneUpdateRequest zone update request
|
||||
//
|
||||
// swagger:model zoneUpdateRequest
|
||||
type ZoneUpdateRequest struct {
|
||||
|
||||
// zones
|
||||
// Required: true
|
||||
Zones []*Zone `json:"zones"`
|
||||
}
|
||||
|
||||
// Validate validates this zone update request
|
||||
func (m *ZoneUpdateRequest) Validate(formats strfmt.Registry) error {
|
||||
var res []error
|
||||
|
||||
if err := m.validateZones(formats); err != nil {
|
||||
res = append(res, err)
|
||||
}
|
||||
|
||||
if len(res) > 0 {
|
||||
return errors.CompositeValidationError(res...)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *ZoneUpdateRequest) validateZones(formats strfmt.Registry) error {
|
||||
|
||||
if err := validate.Required("zones", "body", m.Zones); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for i := 0; i < len(m.Zones); i++ {
|
||||
if swag.IsZero(m.Zones[i]) { // not required
|
||||
continue
|
||||
}
|
||||
|
||||
if m.Zones[i] != nil {
|
||||
if err := m.Zones[i].Validate(formats); err != nil {
|
||||
if ve, ok := err.(*errors.Validation); ok {
|
||||
return ve.ValidateName("zones" + "." + strconv.Itoa(i))
|
||||
}
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// MarshalBinary interface implementation
|
||||
func (m *ZoneUpdateRequest) MarshalBinary() ([]byte, error) {
|
||||
if m == nil {
|
||||
return nil, nil
|
||||
}
|
||||
return swag.WriteJSON(m)
|
||||
}
|
||||
|
||||
// UnmarshalBinary interface implementation
|
||||
func (m *ZoneUpdateRequest) UnmarshalBinary(b []byte) error {
|
||||
var res ZoneUpdateRequest
|
||||
if err := swag.ReadJSON(b, &res); err != nil {
|
||||
return err
|
||||
}
|
||||
*m = res
|
||||
return nil
|
||||
}
|
||||
@@ -17,14 +17,17 @@
|
||||
package auth
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/aes"
|
||||
"crypto/cipher"
|
||||
"crypto/rand"
|
||||
"crypto/hmac"
|
||||
"crypto/sha1"
|
||||
"crypto/sha256"
|
||||
"encoding/base64"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net/http"
|
||||
"strings"
|
||||
@@ -33,6 +36,9 @@ import (
|
||||
"github.com/minio/console/models"
|
||||
"github.com/minio/console/pkg/auth/token"
|
||||
"github.com/minio/minio-go/v7/pkg/credentials"
|
||||
"github.com/secure-io/sio-go/sioutil"
|
||||
"golang.org/x/crypto/chacha20"
|
||||
"golang.org/x/crypto/chacha20poly1305"
|
||||
"golang.org/x/crypto/pbkdf2"
|
||||
)
|
||||
|
||||
@@ -40,6 +46,7 @@ var (
|
||||
errNoAuthToken = errors.New("session token missing")
|
||||
errReadingToken = errors.New("session token internal data is malformed")
|
||||
errClaimsFormat = errors.New("encrypted session token claims not in the right format")
|
||||
errorGeneric = errors.New("an error has occurred")
|
||||
)
|
||||
|
||||
// derivedKey is the key used to encrypt the session token claims, its derived using pbkdf on CONSOLE_PBKDF_PASSPHRASE with CONSOLE_PBKDF_SALT
|
||||
@@ -102,9 +109,10 @@ func NewEncryptedTokenForClient(credentials *credentials.Value, actions []string
|
||||
// returns a base64 encoded ciphertext
|
||||
func encryptClaims(accessKeyID, secretAccessKey, sessionToken string, actions []string) (string, error) {
|
||||
payload := []byte(fmt.Sprintf("%s#%s#%s#%s", accessKeyID, secretAccessKey, sessionToken, strings.Join(actions, ",")))
|
||||
ciphertext, err := encrypt(payload)
|
||||
ciphertext, err := encrypt(payload, []byte{})
|
||||
if err != nil {
|
||||
return "", err
|
||||
log.Println(err)
|
||||
return "", errorGeneric
|
||||
}
|
||||
return base64.StdEncoding.EncodeToString(ciphertext), nil
|
||||
}
|
||||
@@ -116,7 +124,7 @@ func decryptClaims(ciphertext string) (*DecryptedClaims, error) {
|
||||
log.Println(err)
|
||||
return nil, errClaimsFormat
|
||||
}
|
||||
plaintext, err := decrypt(decoded)
|
||||
plaintext, err := decrypt(decoded, []byte{})
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
return nil, errClaimsFormat
|
||||
@@ -136,37 +144,137 @@ func decryptClaims(ciphertext string) (*DecryptedClaims, error) {
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Encrypt a blob of data using AEAD (AES-GCM) with a pbkdf2 derived key
|
||||
func encrypt(plaintext []byte) ([]byte, error) {
|
||||
block, _ := aes.NewCipher(derivedKey)
|
||||
gcm, err := cipher.NewGCM(block)
|
||||
const (
|
||||
aesGcm = 0x00
|
||||
c20p1305 = 0x01
|
||||
)
|
||||
|
||||
// Encrypt a blob of data using AEAD scheme, AES-GCM if the executing CPU
|
||||
// provides AES hardware support, otherwise will use ChaCha20-Poly1305
|
||||
// with a pbkdf2 derived key, this function should be used to encrypt a session
|
||||
// or data key provided as plaintext.
|
||||
//
|
||||
// The returned ciphertext data consists of:
|
||||
// iv | AEAD ID | nonce | encrypted data
|
||||
// 32 1 12 ~ len(data)
|
||||
func encrypt(plaintext, associatedData []byte) ([]byte, error) {
|
||||
iv, err := sioutil.Random(32) // 32 bit IV
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
nonce := make([]byte, gcm.NonceSize())
|
||||
if _, err = io.ReadFull(rand.Reader, nonce); err != nil {
|
||||
var algorithm byte
|
||||
if sioutil.NativeAES() {
|
||||
algorithm = aesGcm
|
||||
} else {
|
||||
algorithm = c20p1305
|
||||
}
|
||||
var aead cipher.AEAD
|
||||
switch algorithm {
|
||||
case aesGcm:
|
||||
mac := hmac.New(sha256.New, derivedKey)
|
||||
mac.Write(iv)
|
||||
sealingKey := mac.Sum(nil)
|
||||
|
||||
var block cipher.Block
|
||||
block, err = aes.NewCipher(sealingKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
aead, err = cipher.NewGCM(block)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
case c20p1305:
|
||||
var sealingKey []byte
|
||||
sealingKey, err = chacha20.HChaCha20(derivedKey, iv)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
aead, err = chacha20poly1305.New(sealingKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
nonce, err := sioutil.Random(aead.NonceSize())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cipherText := gcm.Seal(nonce, nonce, plaintext, nil)
|
||||
return cipherText, nil
|
||||
|
||||
sealedBytes := aead.Seal(nil, nonce, plaintext, associatedData)
|
||||
|
||||
// ciphertext = iv | AEAD ID | nonce | sealed bytes
|
||||
|
||||
var buf bytes.Buffer
|
||||
buf.Write(iv)
|
||||
buf.WriteByte(algorithm)
|
||||
buf.Write(nonce)
|
||||
buf.Write(sealedBytes)
|
||||
|
||||
return buf.Bytes(), nil
|
||||
}
|
||||
|
||||
// Decrypts a blob of data using AEAD (AES-GCM) with a pbkdf2 derived key
|
||||
func decrypt(data []byte) ([]byte, error) {
|
||||
block, err := aes.NewCipher(derivedKey)
|
||||
// Decrypts a blob of data using AEAD scheme AES-GCM if the executing CPU
|
||||
// provides AES hardware support, otherwise will use ChaCha20-Poly1305with
|
||||
// and a pbkdf2 derived key
|
||||
func decrypt(ciphertext []byte, associatedData []byte) ([]byte, error) {
|
||||
var (
|
||||
iv [32]byte
|
||||
algorithm [1]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 {
|
||||
return nil, err
|
||||
}
|
||||
if _, err := io.ReadFull(r, algorithm[:]); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if _, err := io.ReadFull(r, nonce[:]); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var aead cipher.AEAD
|
||||
switch algorithm[0] {
|
||||
case aesGcm:
|
||||
mac := hmac.New(sha256.New, derivedKey)
|
||||
mac.Write(iv[:])
|
||||
sealingKey := mac.Sum(nil)
|
||||
block, err := aes.NewCipher(sealingKey[:])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
aead, err = cipher.NewGCM(block)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
case c20p1305:
|
||||
sealingKey, err := chacha20.HChaCha20(derivedKey, iv[:])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
aead, err = chacha20poly1305.New(sealingKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
default:
|
||||
return nil, fmt.Errorf("invalid algorithm: %v", algorithm)
|
||||
}
|
||||
|
||||
if len(nonce) != aead.NonceSize() {
|
||||
return nil, fmt.Errorf("invalid nonce size %d, expected %d", len(nonce), aead.NonceSize())
|
||||
}
|
||||
|
||||
sealedBytes, err := ioutil.ReadAll(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
gcm, err := cipher.NewGCM(block)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
nonceSize := gcm.NonceSize()
|
||||
nonce, cipherText := data[:nonceSize], data[nonceSize:]
|
||||
plaintext, err := gcm.Open(nil, nonce, cipherText, nil)
|
||||
|
||||
plaintext, err := aead.Open(nil, nonce[:], sealedBytes, associatedData)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return plaintext, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -36,12 +36,12 @@ func TestNewJWTWithClaimsForClient(t *testing.T) {
|
||||
funcAssert := assert.New(t)
|
||||
// Test-1 : NewEncryptedTokenForClient() is generated correctly without errors
|
||||
function := "NewEncryptedTokenForClient()"
|
||||
jwt, err := NewEncryptedTokenForClient(creds, []string{""})
|
||||
if err != nil || jwt == "" {
|
||||
token, err := NewEncryptedTokenForClient(creds, []string{""})
|
||||
if err != nil || token == "" {
|
||||
t.Errorf("Failed on %s:, error occurred: %s", function, err)
|
||||
}
|
||||
// saving jwt for future tests
|
||||
goodToken = jwt
|
||||
// saving token for future tests
|
||||
goodToken = token
|
||||
// Test-2 : NewEncryptedTokenForClient() throws error because of empty credentials
|
||||
if _, err = NewEncryptedTokenForClient(nil, []string{""}); err != nil {
|
||||
funcAssert.Equal("provided credentials are empty", err.Error())
|
||||
|
||||
@@ -9,12 +9,14 @@ import (
|
||||
"github.com/minio/kes"
|
||||
)
|
||||
|
||||
type Identity = kes.Identity
|
||||
|
||||
type TLSProxyHeader struct {
|
||||
ClientCert string `yaml:"cert,omitempty"`
|
||||
}
|
||||
|
||||
type TLSProxy struct {
|
||||
Identities *[]kes.Identity `yaml:"identities,omitempty"`
|
||||
Identities *[]Identity `yaml:"identities,omitempty"`
|
||||
Header *TLSProxyHeader `yaml:"header,omitempty"`
|
||||
}
|
||||
|
||||
@@ -25,8 +27,8 @@ type TLS struct {
|
||||
}
|
||||
|
||||
type Policy struct {
|
||||
Paths []string `yaml:"paths,omitempty"`
|
||||
Identities []kes.Identity `yaml:"identities,omitempty"`
|
||||
Paths []string `yaml:"paths,omitempty"`
|
||||
Identities []Identity `yaml:"identities,omitempty"`
|
||||
}
|
||||
|
||||
type Expiry struct {
|
||||
@@ -120,7 +122,7 @@ type Keys struct {
|
||||
|
||||
type ServerConfig struct {
|
||||
Addr string `yaml:"address,omitempty"`
|
||||
Root kes.Identity `yaml:"root,omitempty"`
|
||||
Root Identity `yaml:"root,omitempty"`
|
||||
TLS TLS `yaml:"tls,omitempty"`
|
||||
Policies map[string]Policy `yaml:"policy,omitempty"`
|
||||
Cache Cache `yaml:"cache,omitempty"`
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -111,7 +111,7 @@ const AddTenant = ({
|
||||
const [accessKey, setAccessKey] = useState<string>("");
|
||||
const [secretKey, setSecretKey] = useState<string>("");
|
||||
const [enableConsole, setEnableConsole] = useState<boolean>(true);
|
||||
const [enableSSL, setEnableSSL] = useState<boolean>(false);
|
||||
const [enableTLS, setEnableTLS] = useState<boolean>(false);
|
||||
const [sizeFactor, setSizeFactor] = useState<string>("Gi");
|
||||
const [storageClasses, setStorageClassesList] = useState<Opts[]>([]);
|
||||
const [validationErrors, setValidationErrors] = useState<any>({});
|
||||
@@ -274,7 +274,7 @@ const AddTenant = ({
|
||||
name: tenantName,
|
||||
service_name: tenantName,
|
||||
image: imageName,
|
||||
enable_ssl: enableSSL,
|
||||
enable_tls: enableTLS,
|
||||
enable_console: enableConsole,
|
||||
access_key: accessKey,
|
||||
secret_key: secretKey,
|
||||
@@ -750,17 +750,17 @@ const AddTenant = ({
|
||||
</Grid>
|
||||
<Grid item xs={12}>
|
||||
<CheckboxWrapper
|
||||
value="enable_ssl"
|
||||
id="enable_ssl"
|
||||
name="enable_ssl"
|
||||
checked={enableSSL}
|
||||
value="enable_tls"
|
||||
id="enable_tls"
|
||||
name="enable_tls"
|
||||
checked={enableTLS}
|
||||
onChange={(e) => {
|
||||
const targetD = e.target;
|
||||
const checked = targetD.checked;
|
||||
|
||||
setEnableSSL(checked);
|
||||
setEnableTLS(checked);
|
||||
}}
|
||||
label={"Enable SSL"}
|
||||
label={"Enable TLS"}
|
||||
/>
|
||||
</Grid>
|
||||
</React.Fragment>
|
||||
@@ -882,9 +882,9 @@ const AddTenant = ({
|
||||
<React.Fragment>
|
||||
<TableRow>
|
||||
<TableCell align="right" className={classes.tableTitle}>
|
||||
Enable SSL
|
||||
Enable TLS
|
||||
</TableCell>
|
||||
<TableCell>{enableSSL ? "Enabled" : "Disabled"}</TableCell>
|
||||
<TableCell>{enableTLS ? "Enabled" : "Disabled"}</TableCell>
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
<TableCell align="right" className={classes.tableTitle}>
|
||||
|
||||
2635
portal-ui/yarn.lock
2635
portal-ui/yarn.lock
File diff suppressed because it is too large
Load Diff
@@ -18,11 +18,9 @@ package restapi
|
||||
|
||||
import (
|
||||
"context"
|
||||
"log"
|
||||
"time"
|
||||
|
||||
"github.com/go-openapi/runtime/middleware"
|
||||
"github.com/go-openapi/swag"
|
||||
"github.com/minio/console/models"
|
||||
"github.com/minio/console/restapi/operations"
|
||||
"github.com/minio/console/restapi/operations/admin_api"
|
||||
@@ -33,7 +31,7 @@ func registerAdminArnsHandlers(api *operations.ConsoleAPI) {
|
||||
api.AdminAPIArnListHandler = admin_api.ArnListHandlerFunc(func(params admin_api.ArnListParams, session *models.Principal) middleware.Responder {
|
||||
arnsResp, err := getArnsResponse(session)
|
||||
if err != nil {
|
||||
return admin_api.NewArnListDefault(500).WithPayload(&models.Error{Code: 500, Message: swag.String(err.Error())})
|
||||
return admin_api.NewArnListDefault(int(err.Code)).WithPayload(err)
|
||||
}
|
||||
return admin_api.NewArnListOK().WithPayload(arnsResp)
|
||||
})
|
||||
@@ -53,11 +51,10 @@ func getArns(ctx context.Context, client MinioAdmin) (*models.ArnsResponse, erro
|
||||
}
|
||||
|
||||
// getArnsResponse returns a list of active arns in the instance
|
||||
func getArnsResponse(session *models.Principal) (*models.ArnsResponse, error) {
|
||||
func getArnsResponse(session *models.Principal) (*models.ArnsResponse, *models.Error) {
|
||||
mAdmin, err := newMAdminClient(session)
|
||||
if err != nil {
|
||||
log.Println("error creating Madmin Client:", err)
|
||||
return nil, err
|
||||
return nil, prepareError(err)
|
||||
}
|
||||
// create a minioClient interface implementation
|
||||
// defining the client to be used
|
||||
@@ -68,8 +65,7 @@ func getArnsResponse(session *models.Principal) (*models.ArnsResponse, error) {
|
||||
// serialize output
|
||||
arnsList, err := getArns(ctx, adminClient)
|
||||
if err != nil {
|
||||
log.Println("error getting arn list:", err)
|
||||
return nil, err
|
||||
return nil, prepareError(err)
|
||||
}
|
||||
return arnsList, nil
|
||||
}
|
||||
|
||||
@@ -19,7 +19,6 @@ package restapi
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log"
|
||||
"strings"
|
||||
|
||||
"github.com/go-openapi/runtime/middleware"
|
||||
@@ -36,7 +35,7 @@ func registerConfigHandlers(api *operations.ConsoleAPI) {
|
||||
api.AdminAPIListConfigHandler = admin_api.ListConfigHandlerFunc(func(params admin_api.ListConfigParams, session *models.Principal) middleware.Responder {
|
||||
configListResp, err := getListConfigResponse(session)
|
||||
if err != nil {
|
||||
return admin_api.NewListConfigDefault(500).WithPayload(&models.Error{Code: 500, Message: swag.String(err.Error())})
|
||||
return admin_api.NewListConfigDefault(int(err.Code)).WithPayload(err)
|
||||
}
|
||||
return admin_api.NewListConfigOK().WithPayload(configListResp)
|
||||
})
|
||||
@@ -44,14 +43,14 @@ func registerConfigHandlers(api *operations.ConsoleAPI) {
|
||||
api.AdminAPIConfigInfoHandler = admin_api.ConfigInfoHandlerFunc(func(params admin_api.ConfigInfoParams, session *models.Principal) middleware.Responder {
|
||||
config, err := getConfigResponse(session, params)
|
||||
if err != nil {
|
||||
return admin_api.NewConfigInfoDefault(500).WithPayload(&models.Error{Code: 500, Message: swag.String(err.Error())})
|
||||
return admin_api.NewConfigInfoDefault(int(err.Code)).WithPayload(err)
|
||||
}
|
||||
return admin_api.NewConfigInfoOK().WithPayload(config)
|
||||
})
|
||||
// Set Configuration
|
||||
api.AdminAPISetConfigHandler = admin_api.SetConfigHandlerFunc(func(params admin_api.SetConfigParams, session *models.Principal) middleware.Responder {
|
||||
if err := setConfigResponse(session, params.Name, params.Body); err != nil {
|
||||
return admin_api.NewSetConfigDefault(500).WithPayload(&models.Error{Code: 500, Message: swag.String(err.Error())})
|
||||
return admin_api.NewSetConfigDefault(int(err.Code)).WithPayload(err)
|
||||
}
|
||||
return admin_api.NewSetConfigNoContent()
|
||||
})
|
||||
@@ -76,11 +75,10 @@ func listConfig(client MinioAdmin) ([]*models.ConfigDescription, error) {
|
||||
}
|
||||
|
||||
// getListConfigResponse performs listConfig() and serializes it to the handler's output
|
||||
func getListConfigResponse(session *models.Principal) (*models.ListConfigResponse, error) {
|
||||
func getListConfigResponse(session *models.Principal) (*models.ListConfigResponse, *models.Error) {
|
||||
mAdmin, err := newMAdminClient(session)
|
||||
if err != nil {
|
||||
log.Println("error creating Madmin Client:", err)
|
||||
return nil, err
|
||||
return nil, prepareError(err)
|
||||
}
|
||||
// create a MinIO Admin Client interface implementation
|
||||
// defining the client to be used
|
||||
@@ -88,8 +86,7 @@ func getListConfigResponse(session *models.Principal) (*models.ListConfigRespons
|
||||
|
||||
configDescs, err := listConfig(adminClient)
|
||||
if err != nil {
|
||||
log.Println("error listing configurations:", err)
|
||||
return nil, err
|
||||
return nil, prepareError(err)
|
||||
}
|
||||
listGroupsResponse := &models.ListConfigResponse{
|
||||
Configurations: configDescs,
|
||||
@@ -127,11 +124,10 @@ func getConfig(client MinioAdmin, name string) ([]*models.ConfigurationKV, error
|
||||
}
|
||||
|
||||
// getConfigResponse performs getConfig() and serializes it to the handler's output
|
||||
func getConfigResponse(session *models.Principal, params admin_api.ConfigInfoParams) (*models.Configuration, error) {
|
||||
func getConfigResponse(session *models.Principal, params admin_api.ConfigInfoParams) (*models.Configuration, *models.Error) {
|
||||
mAdmin, err := newMAdminClient(session)
|
||||
if err != nil {
|
||||
log.Println("error creating Madmin Client:", err)
|
||||
return nil, err
|
||||
return nil, prepareError(err)
|
||||
}
|
||||
// create a MinIO Admin Client interface implementation
|
||||
// defining the client to be used
|
||||
@@ -139,8 +135,7 @@ func getConfigResponse(session *models.Principal, params admin_api.ConfigInfoPar
|
||||
|
||||
configkv, err := getConfig(adminClient, params.Name)
|
||||
if err != nil {
|
||||
log.Println("error getting configuration:", err)
|
||||
return nil, err
|
||||
return nil, prepareError(err)
|
||||
}
|
||||
configurationObj := &models.Configuration{
|
||||
Name: params.Name,
|
||||
@@ -180,11 +175,10 @@ func buildConfig(configName *string, kvs []*models.ConfigurationKV) *string {
|
||||
}
|
||||
|
||||
// setConfigResponse implements setConfig() to be used by handler
|
||||
func setConfigResponse(session *models.Principal, name string, configRequest *models.SetConfigRequest) error {
|
||||
func setConfigResponse(session *models.Principal, name string, configRequest *models.SetConfigRequest) *models.Error {
|
||||
mAdmin, err := newMAdminClient(session)
|
||||
if err != nil {
|
||||
log.Println("error creating Madmin Client:", err)
|
||||
return err
|
||||
return prepareError(err)
|
||||
}
|
||||
// create a MinIO Admin Client interface implementation
|
||||
// defining the client to be used
|
||||
@@ -194,8 +188,7 @@ func setConfigResponse(session *models.Principal, name string, configRequest *mo
|
||||
ctx := context.Background()
|
||||
|
||||
if err := setConfigWithARNAccountID(ctx, adminClient, &configName, configRequest.KeyValues, configRequest.ArnResourceID); err != nil {
|
||||
log.Println("error listing configurations:", err)
|
||||
return err
|
||||
return prepareError(err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -22,7 +22,6 @@ import (
|
||||
|
||||
"github.com/go-openapi/errors"
|
||||
"github.com/go-openapi/runtime/middleware"
|
||||
"github.com/go-openapi/swag"
|
||||
"github.com/minio/console/restapi/operations"
|
||||
"github.com/minio/minio/pkg/madmin"
|
||||
|
||||
@@ -36,7 +35,7 @@ func registerGroupsHandlers(api *operations.ConsoleAPI) {
|
||||
api.AdminAPIListGroupsHandler = admin_api.ListGroupsHandlerFunc(func(params admin_api.ListGroupsParams, session *models.Principal) middleware.Responder {
|
||||
listGroupsResponse, err := getListGroupsResponse(session)
|
||||
if err != nil {
|
||||
return admin_api.NewListGroupsDefault(500).WithPayload(&models.Error{Code: 500, Message: swag.String(err.Error())})
|
||||
return admin_api.NewListGroupsDefault(int(err.Code)).WithPayload(err)
|
||||
}
|
||||
return admin_api.NewListGroupsOK().WithPayload(listGroupsResponse)
|
||||
})
|
||||
@@ -44,21 +43,21 @@ func registerGroupsHandlers(api *operations.ConsoleAPI) {
|
||||
api.AdminAPIGroupInfoHandler = admin_api.GroupInfoHandlerFunc(func(params admin_api.GroupInfoParams, session *models.Principal) middleware.Responder {
|
||||
groupInfo, err := getGroupInfoResponse(session, params)
|
||||
if err != nil {
|
||||
return admin_api.NewGroupInfoDefault(500).WithPayload(&models.Error{Code: 500, Message: swag.String(err.Error())})
|
||||
return admin_api.NewGroupInfoDefault(int(err.Code)).WithPayload(err)
|
||||
}
|
||||
return admin_api.NewGroupInfoOK().WithPayload(groupInfo)
|
||||
})
|
||||
// Add Group
|
||||
api.AdminAPIAddGroupHandler = admin_api.AddGroupHandlerFunc(func(params admin_api.AddGroupParams, session *models.Principal) middleware.Responder {
|
||||
if err := getAddGroupResponse(session, params.Body); err != nil {
|
||||
return admin_api.NewAddGroupDefault(500).WithPayload(&models.Error{Code: 500, Message: swag.String(err.Error())})
|
||||
return admin_api.NewAddGroupDefault(int(err.Code)).WithPayload(err)
|
||||
}
|
||||
return admin_api.NewAddGroupCreated()
|
||||
})
|
||||
// Remove Group
|
||||
api.AdminAPIRemoveGroupHandler = admin_api.RemoveGroupHandlerFunc(func(params admin_api.RemoveGroupParams, session *models.Principal) middleware.Responder {
|
||||
if err := getRemoveGroupResponse(session, params); err != nil {
|
||||
return admin_api.NewRemoveGroupDefault(500).WithPayload(&models.Error{Code: 500, Message: swag.String(err.Error())})
|
||||
return admin_api.NewRemoveGroupDefault(int(err.Code)).WithPayload(err)
|
||||
}
|
||||
return admin_api.NewRemoveGroupNoContent()
|
||||
})
|
||||
@@ -66,7 +65,7 @@ func registerGroupsHandlers(api *operations.ConsoleAPI) {
|
||||
api.AdminAPIUpdateGroupHandler = admin_api.UpdateGroupHandlerFunc(func(params admin_api.UpdateGroupParams, session *models.Principal) middleware.Responder {
|
||||
groupUpdateResp, err := getUpdateGroupResponse(session, params)
|
||||
if err != nil {
|
||||
return admin_api.NewUpdateGroupDefault(500).WithPayload(&models.Error{Code: 500, Message: swag.String(err.Error())})
|
||||
return admin_api.NewUpdateGroupDefault(int(err.Code)).WithPayload(err)
|
||||
}
|
||||
return admin_api.NewUpdateGroupOK().WithPayload(groupUpdateResp)
|
||||
})
|
||||
@@ -82,12 +81,11 @@ func listGroups(ctx context.Context, client MinioAdmin) (*[]string, error) {
|
||||
}
|
||||
|
||||
// getListGroupsResponse performs listGroups() and serializes it to the handler's output
|
||||
func getListGroupsResponse(session *models.Principal) (*models.ListGroupsResponse, error) {
|
||||
func getListGroupsResponse(session *models.Principal) (*models.ListGroupsResponse, *models.Error) {
|
||||
ctx := context.Background()
|
||||
mAdmin, err := newMAdminClient(session)
|
||||
if err != nil {
|
||||
log.Println("error creating Madmin Client:", err)
|
||||
return nil, err
|
||||
return nil, prepareError(err)
|
||||
}
|
||||
// create a MinIO Admin Client interface implementation
|
||||
// defining the client to be used
|
||||
@@ -95,8 +93,7 @@ func getListGroupsResponse(session *models.Principal) (*models.ListGroupsRespons
|
||||
|
||||
groups, err := listGroups(ctx, adminClient)
|
||||
if err != nil {
|
||||
log.Println("error listing groups:", err)
|
||||
return nil, err
|
||||
return nil, prepareError(err)
|
||||
}
|
||||
// serialize output
|
||||
listGroupsResponse := &models.ListGroupsResponse{
|
||||
@@ -116,12 +113,11 @@ func groupInfo(ctx context.Context, client MinioAdmin, group string) (*madmin.Gr
|
||||
}
|
||||
|
||||
// getGroupInfoResponse performs groupInfo() and serializes it to the handler's output
|
||||
func getGroupInfoResponse(session *models.Principal, params admin_api.GroupInfoParams) (*models.Group, error) {
|
||||
func getGroupInfoResponse(session *models.Principal, params admin_api.GroupInfoParams) (*models.Group, *models.Error) {
|
||||
ctx := context.Background()
|
||||
mAdmin, err := newMAdminClient(session)
|
||||
if err != nil {
|
||||
log.Println("error creating Madmin Client:", err)
|
||||
return nil, err
|
||||
return nil, prepareError(err)
|
||||
}
|
||||
// create a MinIO Admin Client interface implementation
|
||||
// defining the client to be used
|
||||
@@ -129,8 +125,7 @@ func getGroupInfoResponse(session *models.Principal, params admin_api.GroupInfoP
|
||||
|
||||
groupDesc, err := groupInfo(ctx, adminClient, params.Name)
|
||||
if err != nil {
|
||||
log.Println("error getting group info:", err)
|
||||
return nil, err
|
||||
return nil, prepareError(err)
|
||||
}
|
||||
|
||||
groupResponse := &models.Group{
|
||||
@@ -157,26 +152,23 @@ func addGroup(ctx context.Context, client MinioAdmin, group string, members []st
|
||||
}
|
||||
|
||||
// getAddGroupResponse performs addGroup() and serializes it to the handler's output
|
||||
func getAddGroupResponse(session *models.Principal, params *models.AddGroupRequest) error {
|
||||
func getAddGroupResponse(session *models.Principal, params *models.AddGroupRequest) *models.Error {
|
||||
ctx := context.Background()
|
||||
// AddGroup request needed to proceed
|
||||
if params == nil {
|
||||
log.Println("error AddGroup body not in request")
|
||||
return errors.New(500, "error AddGroup body not in request")
|
||||
return prepareError(errGroupBodyNotInRequest)
|
||||
}
|
||||
|
||||
mAdmin, err := newMAdminClient(session)
|
||||
if err != nil {
|
||||
log.Println("error creating Madmin Client:", err)
|
||||
return err
|
||||
return prepareError(err)
|
||||
}
|
||||
// create a MinIO Admin Client interface implementation
|
||||
// defining the client to be used
|
||||
adminClient := adminClient{client: mAdmin}
|
||||
|
||||
if err := addGroup(ctx, adminClient, *params.Group, params.Members); err != nil {
|
||||
log.Println("error adding group:", err)
|
||||
return err
|
||||
return prepareError(err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -196,25 +188,22 @@ func removeGroup(ctx context.Context, client MinioAdmin, group string) error {
|
||||
}
|
||||
|
||||
// getRemoveGroupResponse performs removeGroup() and serializes it to the handler's output
|
||||
func getRemoveGroupResponse(session *models.Principal, params admin_api.RemoveGroupParams) error {
|
||||
func getRemoveGroupResponse(session *models.Principal, params admin_api.RemoveGroupParams) *models.Error {
|
||||
ctx := context.Background()
|
||||
|
||||
if params.Name == "" {
|
||||
log.Println("error group name not in request")
|
||||
return errors.New(500, "error group name not in request")
|
||||
return prepareError(errGroupNameNotInRequest)
|
||||
}
|
||||
mAdmin, err := newMAdminClient(session)
|
||||
if err != nil {
|
||||
log.Println("error creating Madmin Client:", err)
|
||||
return err
|
||||
return prepareError(err)
|
||||
}
|
||||
// create a MinIO Admin Client interface implementation
|
||||
// defining the client to be used
|
||||
adminClient := adminClient{client: mAdmin}
|
||||
|
||||
if err := removeGroup(ctx, adminClient, params.Name); err != nil {
|
||||
log.Println("error removing group:", err)
|
||||
return err
|
||||
return prepareError(err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -276,23 +265,21 @@ func setGroupStatus(ctx context.Context, client MinioAdmin, group, status string
|
||||
// getUpdateGroupResponse updates a group by adding or removing it's members depending on the request,
|
||||
// also sets the group's status if status in the request is different than the current one.
|
||||
// Then serializes the output to be used by the handler.
|
||||
func getUpdateGroupResponse(session *models.Principal, params admin_api.UpdateGroupParams) (*models.Group, error) {
|
||||
func getUpdateGroupResponse(session *models.Principal, params admin_api.UpdateGroupParams) (*models.Group, *models.Error) {
|
||||
ctx := context.Background()
|
||||
if params.Name == "" {
|
||||
log.Println("error group name not in request")
|
||||
return nil, errors.New(500, "error group name not in request")
|
||||
return nil, prepareError(errGroupNameNotInRequest)
|
||||
}
|
||||
if params.Body == nil {
|
||||
log.Println("error body not in request")
|
||||
return nil, errors.New(500, "error body not in request")
|
||||
return nil, prepareError(errGroupBodyNotInRequest)
|
||||
|
||||
}
|
||||
expectedGroupUpdate := params.Body
|
||||
groupName := params.Name
|
||||
|
||||
mAdmin, err := newMAdminClient(session)
|
||||
if err != nil {
|
||||
log.Println("error creating Madmin Client:", err)
|
||||
return nil, err
|
||||
return nil, prepareError(err)
|
||||
}
|
||||
// create a MinIO Admin Client interface implementation
|
||||
// defining the client to be used
|
||||
@@ -300,8 +287,7 @@ func getUpdateGroupResponse(session *models.Principal, params admin_api.UpdateGr
|
||||
|
||||
groupUpdated, err := groupUpdate(ctx, adminClient, groupName, expectedGroupUpdate)
|
||||
if err != nil {
|
||||
log.Println("error updating group:", err)
|
||||
return nil, err
|
||||
return nil, prepareError(err)
|
||||
}
|
||||
groupResponse := &models.Group{
|
||||
Name: groupUpdated.Name,
|
||||
|
||||
@@ -18,11 +18,9 @@ package restapi
|
||||
|
||||
import (
|
||||
"context"
|
||||
"log"
|
||||
"time"
|
||||
|
||||
"github.com/go-openapi/runtime/middleware"
|
||||
"github.com/go-openapi/swag"
|
||||
"github.com/minio/console/models"
|
||||
"github.com/minio/console/restapi/operations"
|
||||
"github.com/minio/console/restapi/operations/admin_api"
|
||||
@@ -33,7 +31,7 @@ func registerAdminInfoHandlers(api *operations.ConsoleAPI) {
|
||||
api.AdminAPIAdminInfoHandler = admin_api.AdminInfoHandlerFunc(func(params admin_api.AdminInfoParams, session *models.Principal) middleware.Responder {
|
||||
infoResp, err := getAdminInfoResponse(session)
|
||||
if err != nil {
|
||||
return admin_api.NewAdminInfoDefault(500).WithPayload(&models.Error{Code: 500, Message: swag.String(err.Error())})
|
||||
return admin_api.NewAdminInfoDefault(int(err.Code)).WithPayload(err)
|
||||
}
|
||||
return admin_api.NewAdminInfoOK().WithPayload(infoResp)
|
||||
})
|
||||
@@ -72,11 +70,10 @@ func getAdminInfo(ctx context.Context, client MinioAdmin) (*usageInfo, error) {
|
||||
}
|
||||
|
||||
// getAdminInfoResponse returns the response containing total buckets, objects and usage.
|
||||
func getAdminInfoResponse(session *models.Principal) (*models.AdminInfoResponse, error) {
|
||||
func getAdminInfoResponse(session *models.Principal) (*models.AdminInfoResponse, *models.Error) {
|
||||
mAdmin, err := newMAdminClient(session)
|
||||
if err != nil {
|
||||
log.Println("error creating Madmin Client:", err)
|
||||
return nil, err
|
||||
return nil, prepareError(err)
|
||||
}
|
||||
// create a minioClient interface implementation
|
||||
// defining the client to be used
|
||||
@@ -87,8 +84,7 @@ func getAdminInfoResponse(session *models.Principal) (*models.AdminInfoResponse,
|
||||
// serialize output
|
||||
usage, err := getAdminInfo(ctx, adminClient)
|
||||
if err != nil {
|
||||
log.Println("error getting information:", err)
|
||||
return nil, err
|
||||
return nil, prepareError(err)
|
||||
}
|
||||
sessionResp := &models.AdminInfoResponse{
|
||||
Buckets: usage.Buckets,
|
||||
|
||||
136
restapi/admin_nodes.go
Normal file
136
restapi/admin_nodes.go
Normal file
@@ -0,0 +1,136 @@
|
||||
// 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 (
|
||||
"context"
|
||||
"sort"
|
||||
|
||||
"github.com/minio/console/cluster"
|
||||
|
||||
"errors"
|
||||
|
||||
"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"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
v1 "k8s.io/client-go/kubernetes/typed/core/v1"
|
||||
)
|
||||
|
||||
func registerNodesHandlers(api *operations.ConsoleAPI) {
|
||||
api.AdminAPIGetMaxAllocatableMemHandler = admin_api.GetMaxAllocatableMemHandlerFunc(func(params admin_api.GetMaxAllocatableMemParams, principal *models.Principal) middleware.Responder {
|
||||
resp, err := getMaxAllocatableMemoryResponse(principal, params.NumNodes)
|
||||
if err != nil {
|
||||
return admin_api.NewGetMaxAllocatableMemDefault(int(err.Code)).WithPayload(err)
|
||||
}
|
||||
return admin_api.NewGetMaxAllocatableMemOK().WithPayload(resp)
|
||||
})
|
||||
}
|
||||
|
||||
// getMaxAllocatableMemory get max allocatable memory given a desired number of nodes
|
||||
func getMaxAllocatableMemory(ctx context.Context, clientset v1.CoreV1Interface, numNodes int32) (*models.MaxAllocatableMemResponse, error) {
|
||||
if numNodes == 0 {
|
||||
return nil, errors.New("error NumNodes must be greated than 0")
|
||||
}
|
||||
|
||||
// get all nodes from cluster
|
||||
nodes, err := clientset.Nodes().List(ctx, metav1.ListOptions{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
availableMemSizes := []int64{}
|
||||
OUTER:
|
||||
for _, n := range nodes.Items {
|
||||
// Don't consider node if it has a NoSchedule or NoExecute Taint
|
||||
for _, t := range n.Spec.Taints {
|
||||
switch t.Effect {
|
||||
case corev1.TaintEffectNoSchedule:
|
||||
continue OUTER
|
||||
case corev1.TaintEffectNoExecute:
|
||||
continue OUTER
|
||||
default:
|
||||
continue
|
||||
}
|
||||
}
|
||||
if quantity, ok := n.Status.Allocatable[corev1.ResourceMemory]; ok {
|
||||
availableMemSizes = append(availableMemSizes, quantity.Value())
|
||||
}
|
||||
}
|
||||
|
||||
maxAllocatableMemory := getMaxClusterMemory(numNodes, availableMemSizes)
|
||||
|
||||
res := &models.MaxAllocatableMemResponse{
|
||||
MaxMemory: maxAllocatableMemory,
|
||||
}
|
||||
|
||||
return res, nil
|
||||
}
|
||||
|
||||
// getMaxClusterMemory returns the maximum memory size that can be used
|
||||
// across numNodes (number of nodes)
|
||||
func getMaxClusterMemory(numNodes int32, nodesMemorySizes []int64) int64 {
|
||||
if int32(len(nodesMemorySizes)) < numNodes || numNodes == 0 {
|
||||
return 0
|
||||
}
|
||||
|
||||
// sort nodesMemorySizes int64 array
|
||||
sort.Slice(nodesMemorySizes, func(i, j int) bool { return nodesMemorySizes[i] < nodesMemorySizes[j] })
|
||||
maxIndex := 0
|
||||
maxAllocatableMemory := nodesMemorySizes[maxIndex]
|
||||
|
||||
for i, size := range nodesMemorySizes {
|
||||
// maxAllocatableMemory is the minimum value of nodesMemorySizes array
|
||||
// only within the size of numNodes, if more nodes are available
|
||||
// then the maxAllocatableMemory is equal to the next minimum value
|
||||
// on the sorted nodesMemorySizes array.
|
||||
// e.g. with numNodes = 4;
|
||||
// maxAllocatableMemory of [2,4,8,8] => 2
|
||||
// maxAllocatableMemory of [2,4,8,8,16] => 4
|
||||
if int32(i) < numNodes {
|
||||
maxAllocatableMemory = min(maxAllocatableMemory, size)
|
||||
} else {
|
||||
maxIndex++
|
||||
maxAllocatableMemory = nodesMemorySizes[maxIndex]
|
||||
}
|
||||
}
|
||||
return maxAllocatableMemory
|
||||
}
|
||||
|
||||
// min returns the smaller of x or y.
|
||||
func min(x, y int64) int64 {
|
||||
if x > y {
|
||||
return y
|
||||
}
|
||||
return x
|
||||
}
|
||||
|
||||
func getMaxAllocatableMemoryResponse(session *models.Principal, numNodes int32) (*models.MaxAllocatableMemResponse, *models.Error) {
|
||||
ctx := context.Background()
|
||||
client, err := cluster.K8sClient(session.SessionToken)
|
||||
if err != nil {
|
||||
return nil, prepareError(err)
|
||||
}
|
||||
|
||||
clusterResources, err := getMaxAllocatableMemory(ctx, client.CoreV1(), numNodes)
|
||||
if err != nil {
|
||||
return nil, prepareError(err)
|
||||
}
|
||||
return clusterResources, nil
|
||||
}
|
||||
366
restapi/admin_nodes_test.go
Normal file
366
restapi/admin_nodes_test.go
Normal file
@@ -0,0 +1,366 @@
|
||||
// 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 (
|
||||
"context"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/minio/console/models"
|
||||
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/api/resource"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/client-go/kubernetes/fake"
|
||||
)
|
||||
|
||||
func Test_MaxAllocatableMemory(t *testing.T) {
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
numNodes int32
|
||||
objs []runtime.Object
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
expected *models.MaxAllocatableMemResponse
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "Get Max Ram No Taints",
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
numNodes: 2,
|
||||
objs: []runtime.Object{
|
||||
&corev1.Node{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "node1",
|
||||
},
|
||||
Status: corev1.NodeStatus{
|
||||
Allocatable: corev1.ResourceList{
|
||||
corev1.ResourceMemory: resource.MustParse("2Ki"),
|
||||
corev1.ResourceCPU: resource.MustParse("4Ki"),
|
||||
},
|
||||
},
|
||||
},
|
||||
&corev1.Node{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "node2",
|
||||
},
|
||||
Status: corev1.NodeStatus{
|
||||
Allocatable: corev1.ResourceList{
|
||||
corev1.ResourceMemory: resource.MustParse("512"),
|
||||
corev1.ResourceCPU: resource.MustParse("1Ki"),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
expected: &models.MaxAllocatableMemResponse{
|
||||
MaxMemory: int64(512),
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
// Description: if there are more nodes than the amount
|
||||
// of nodes we want to use, but one has taints of NoSchedule
|
||||
// node should not be considered for max memory
|
||||
name: "Get Max Ram on nodes with NoSchedule",
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
numNodes: 2,
|
||||
objs: []runtime.Object{
|
||||
&corev1.Node{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "node1",
|
||||
},
|
||||
Status: corev1.NodeStatus{
|
||||
Allocatable: corev1.ResourceList{
|
||||
corev1.ResourceMemory: resource.MustParse("2Ki"),
|
||||
corev1.ResourceCPU: resource.MustParse("4Ki"),
|
||||
},
|
||||
},
|
||||
},
|
||||
&corev1.Node{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "node2",
|
||||
},
|
||||
Spec: corev1.NodeSpec{
|
||||
Taints: []corev1.Taint{
|
||||
corev1.Taint{
|
||||
Key: "node.kubernetes.io/unreachable",
|
||||
Effect: corev1.TaintEffectNoSchedule,
|
||||
},
|
||||
},
|
||||
},
|
||||
Status: corev1.NodeStatus{
|
||||
Allocatable: corev1.ResourceList{
|
||||
corev1.ResourceMemory: resource.MustParse("6Ki"),
|
||||
corev1.ResourceCPU: resource.MustParse("1Ki"),
|
||||
},
|
||||
},
|
||||
},
|
||||
&corev1.Node{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "node3",
|
||||
},
|
||||
Status: corev1.NodeStatus{
|
||||
Allocatable: corev1.ResourceList{
|
||||
corev1.ResourceMemory: resource.MustParse("4Ki"),
|
||||
corev1.ResourceCPU: resource.MustParse("1Ki"),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
expected: &models.MaxAllocatableMemResponse{
|
||||
MaxMemory: int64(2048),
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
// Description: if there are more nodes than the amount
|
||||
// of nodes we want to use, but one has taints of NoExecute
|
||||
// node should not be considered for max memory
|
||||
// if one node has PreferNoSchedule that should be considered.
|
||||
name: "Get Max Ram on nodes with NoExecute",
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
numNodes: 2,
|
||||
objs: []runtime.Object{
|
||||
&corev1.Node{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "node1",
|
||||
},
|
||||
Status: corev1.NodeStatus{
|
||||
Allocatable: corev1.ResourceList{
|
||||
corev1.ResourceMemory: resource.MustParse("2Ki"),
|
||||
corev1.ResourceCPU: resource.MustParse("4Ki"),
|
||||
},
|
||||
},
|
||||
},
|
||||
&corev1.Node{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "node2",
|
||||
},
|
||||
Spec: corev1.NodeSpec{
|
||||
Taints: []corev1.Taint{
|
||||
corev1.Taint{
|
||||
Key: "node.kubernetes.io/unreachable",
|
||||
Effect: corev1.TaintEffectNoExecute,
|
||||
},
|
||||
},
|
||||
},
|
||||
Status: corev1.NodeStatus{
|
||||
Allocatable: corev1.ResourceList{
|
||||
corev1.ResourceMemory: resource.MustParse("6Ki"),
|
||||
corev1.ResourceCPU: resource.MustParse("1Ki"),
|
||||
},
|
||||
},
|
||||
},
|
||||
&corev1.Node{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "node3",
|
||||
},
|
||||
Spec: corev1.NodeSpec{
|
||||
Taints: []corev1.Taint{
|
||||
corev1.Taint{
|
||||
Key: "node.kubernetes.io/unreachable",
|
||||
Effect: corev1.TaintEffectPreferNoSchedule,
|
||||
},
|
||||
},
|
||||
},
|
||||
Status: corev1.NodeStatus{
|
||||
Allocatable: corev1.ResourceList{
|
||||
corev1.ResourceMemory: resource.MustParse("4Ki"),
|
||||
corev1.ResourceCPU: resource.MustParse("1Ki"),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
expected: &models.MaxAllocatableMemResponse{
|
||||
MaxMemory: int64(2048),
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
// Description: if there are more nodes than the amount
|
||||
// of nodes we want to use, max allocatable memory should
|
||||
// be the minimum ram on the n nodes requested
|
||||
name: "Get Max Ram, several nodes available",
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
numNodes: 2,
|
||||
objs: []runtime.Object{
|
||||
&corev1.Node{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "node1",
|
||||
},
|
||||
Status: corev1.NodeStatus{
|
||||
Allocatable: corev1.ResourceList{
|
||||
corev1.ResourceMemory: resource.MustParse("2Ki"),
|
||||
corev1.ResourceCPU: resource.MustParse("4Ki"),
|
||||
},
|
||||
},
|
||||
},
|
||||
&corev1.Node{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "node2",
|
||||
},
|
||||
Status: corev1.NodeStatus{
|
||||
Allocatable: corev1.ResourceList{
|
||||
corev1.ResourceMemory: resource.MustParse("6Ki"),
|
||||
corev1.ResourceCPU: resource.MustParse("1Ki"),
|
||||
},
|
||||
},
|
||||
},
|
||||
&corev1.Node{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "node3",
|
||||
},
|
||||
Status: corev1.NodeStatus{
|
||||
Allocatable: corev1.ResourceList{
|
||||
corev1.ResourceMemory: resource.MustParse("4Ki"),
|
||||
corev1.ResourceCPU: resource.MustParse("1Ki"),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
expected: &models.MaxAllocatableMemResponse{
|
||||
MaxMemory: int64(4096),
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
// Description: if request has nil as request, expect error
|
||||
name: "Nil nodes should be greater than 0",
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
numNodes: 0,
|
||||
},
|
||||
wantErr: true,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
kubeClient := fake.NewSimpleClientset(tt.args.objs...)
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got, err := getMaxAllocatableMemory(tt.args.ctx, kubeClient.CoreV1(), tt.args.numNodes)
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("getMaxAllocatableMemory() error = %v, wantErr %v", err, tt.wantErr)
|
||||
}
|
||||
if !reflect.DeepEqual(got, tt.expected) {
|
||||
t.Errorf("\ngot: %d \nwant: %d", got, tt.expected)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_MaxMemoryFunc(t *testing.T) {
|
||||
type args struct {
|
||||
numNodes int32
|
||||
nodesMemorySizes []int64
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
expected int64
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "Get Max memory",
|
||||
args: args{
|
||||
numNodes: int32(4),
|
||||
nodesMemorySizes: []int64{4294967296, 8589934592, 8589934592, 17179869184, 17179869184, 17179869184, 25769803776, 25769803776, 68719476736},
|
||||
},
|
||||
expected: int64(17179869184),
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
// Description, if not enough nodes return 0
|
||||
name: "Get Max memory Not enough nodes",
|
||||
args: args{
|
||||
numNodes: int32(4),
|
||||
nodesMemorySizes: []int64{4294967296, 8589934592, 68719476736},
|
||||
},
|
||||
expected: int64(0),
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
// Description, if not enough nodes return 0
|
||||
name: "Get Max memory no nodes",
|
||||
args: args{
|
||||
numNodes: int32(4),
|
||||
nodesMemorySizes: []int64{},
|
||||
},
|
||||
expected: int64(0),
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
// Description, if not enough nodes return 0
|
||||
name: "Get Max memory no nodes, no request",
|
||||
args: args{
|
||||
numNodes: int32(0),
|
||||
nodesMemorySizes: []int64{},
|
||||
},
|
||||
expected: int64(0),
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
// Description, if there are multiple nodes
|
||||
// and required nodes is only 1, max should be equal to max memory
|
||||
name: "Get Max memory one node",
|
||||
args: args{
|
||||
numNodes: int32(1),
|
||||
nodesMemorySizes: []int64{4294967296, 8589934592, 68719476736},
|
||||
},
|
||||
expected: int64(68719476736),
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
// Description: if more nodes max memory should be the minimum
|
||||
// value across pairs of numNodes
|
||||
name: "Get Max memory two nodes",
|
||||
args: args{
|
||||
numNodes: int32(2),
|
||||
nodesMemorySizes: []int64{8589934592, 68719476736, 4294967296},
|
||||
},
|
||||
expected: int64(8589934592),
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "Get Max Multiple Memory Sizes",
|
||||
args: args{
|
||||
numNodes: int32(4),
|
||||
nodesMemorySizes: []int64{0, 0, 0, 0, 4294967296, 8589934592, 8589934592, 17179869184, 17179869184, 17179869184, 25769803776, 25769803776, 68719476736, 34359738368, 34359738368, 34359738368, 34359738368},
|
||||
},
|
||||
expected: int64(34359738368),
|
||||
wantErr: false,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got := getMaxClusterMemory(tt.args.numNodes, tt.args.nodesMemorySizes)
|
||||
if !reflect.DeepEqual(got, tt.expected) {
|
||||
t.Errorf("\ngot: %d \nwant: %d", got, tt.expected)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -19,11 +19,9 @@ package restapi
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"log"
|
||||
"time"
|
||||
|
||||
"github.com/go-openapi/runtime/middleware"
|
||||
"github.com/go-openapi/swag"
|
||||
"github.com/minio/console/models"
|
||||
"github.com/minio/console/restapi/operations"
|
||||
"github.com/minio/console/restapi/operations/admin_api"
|
||||
@@ -34,7 +32,7 @@ func registerAdminNotificationEndpointsHandlers(api *operations.ConsoleAPI) {
|
||||
api.AdminAPINotificationEndpointListHandler = admin_api.NotificationEndpointListHandlerFunc(func(params admin_api.NotificationEndpointListParams, session *models.Principal) middleware.Responder {
|
||||
notifEndpoints, err := getNotificationEndpointsResponse(session)
|
||||
if err != nil {
|
||||
return admin_api.NewNotificationEndpointListDefault(500).WithPayload(&models.Error{Code: 500, Message: swag.String(err.Error())})
|
||||
return admin_api.NewNotificationEndpointListDefault(int(err.Code)).WithPayload(err)
|
||||
}
|
||||
return admin_api.NewNotificationEndpointListOK().WithPayload(notifEndpoints)
|
||||
})
|
||||
@@ -42,7 +40,7 @@ func registerAdminNotificationEndpointsHandlers(api *operations.ConsoleAPI) {
|
||||
api.AdminAPIAddNotificationEndpointHandler = admin_api.AddNotificationEndpointHandlerFunc(func(params admin_api.AddNotificationEndpointParams, session *models.Principal) middleware.Responder {
|
||||
notifEndpoints, err := getAddNotificationEndpointResponse(session, ¶ms)
|
||||
if err != nil {
|
||||
return admin_api.NewAddNotificationEndpointDefault(500).WithPayload(&models.Error{Code: 500, Message: swag.String(err.Error())})
|
||||
return admin_api.NewAddNotificationEndpointDefault(int(err.Code)).WithPayload(err)
|
||||
}
|
||||
return admin_api.NewAddNotificationEndpointCreated().WithPayload(notifEndpoints)
|
||||
})
|
||||
@@ -78,11 +76,10 @@ func getNotificationEndpoints(ctx context.Context, client MinioAdmin) (*models.N
|
||||
}
|
||||
|
||||
// getNotificationEndpointsResponse returns a list of notification endpoints in the instance
|
||||
func getNotificationEndpointsResponse(session *models.Principal) (*models.NotifEndpointResponse, error) {
|
||||
func getNotificationEndpointsResponse(session *models.Principal) (*models.NotifEndpointResponse, *models.Error) {
|
||||
mAdmin, err := newMAdminClient(session)
|
||||
if err != nil {
|
||||
log.Println("error creating Madmin Client:", err)
|
||||
return nil, err
|
||||
return nil, prepareError(err)
|
||||
}
|
||||
// create a minioClient interface implementation
|
||||
// defining the client to be used
|
||||
@@ -93,8 +90,7 @@ func getNotificationEndpointsResponse(session *models.Principal) (*models.NotifE
|
||||
// serialize output
|
||||
notfEndpointResp, err := getNotificationEndpoints(ctx, adminClient)
|
||||
if err != nil {
|
||||
log.Println("error getting notification endpoint list:", err)
|
||||
return nil, err
|
||||
return nil, prepareError(err)
|
||||
}
|
||||
return notfEndpointResp, nil
|
||||
}
|
||||
@@ -150,11 +146,10 @@ func addNotificationEndpoint(ctx context.Context, client MinioAdmin, params *adm
|
||||
}
|
||||
|
||||
// getNotificationEndpointsResponse returns a list of notification endpoints in the instance
|
||||
func getAddNotificationEndpointResponse(session *models.Principal, params *admin_api.AddNotificationEndpointParams) (*models.NotificationEndpoint, error) {
|
||||
func getAddNotificationEndpointResponse(session *models.Principal, params *admin_api.AddNotificationEndpointParams) (*models.NotificationEndpoint, *models.Error) {
|
||||
mAdmin, err := newMAdminClient(session)
|
||||
if err != nil {
|
||||
log.Println("error creating Madmin Client:", err)
|
||||
return nil, err
|
||||
return nil, prepareError(err)
|
||||
}
|
||||
// create a minioClient interface implementation
|
||||
// defining the client to be used
|
||||
@@ -165,8 +160,7 @@ func getAddNotificationEndpointResponse(session *models.Principal, params *admin
|
||||
// serialize output
|
||||
notfEndpointResp, err := addNotificationEndpoint(ctx, adminClient, params)
|
||||
if err != nil {
|
||||
log.Println("error getting notification endpoint list:", err)
|
||||
return nil, err
|
||||
return nil, prepareError(err)
|
||||
}
|
||||
return notfEndpointResp, nil
|
||||
}
|
||||
|
||||
@@ -22,10 +22,7 @@ import (
|
||||
"encoding/json"
|
||||
"log"
|
||||
|
||||
"github.com/go-openapi/errors"
|
||||
|
||||
"github.com/go-openapi/runtime/middleware"
|
||||
"github.com/go-openapi/swag"
|
||||
"github.com/minio/console/models"
|
||||
"github.com/minio/console/restapi/operations"
|
||||
"github.com/minio/console/restapi/operations/admin_api"
|
||||
@@ -37,7 +34,7 @@ func registersPoliciesHandler(api *operations.ConsoleAPI) {
|
||||
api.AdminAPIListPoliciesHandler = admin_api.ListPoliciesHandlerFunc(func(params admin_api.ListPoliciesParams, session *models.Principal) middleware.Responder {
|
||||
listPoliciesResponse, err := getListPoliciesResponse(session)
|
||||
if err != nil {
|
||||
return admin_api.NewListPoliciesDefault(500).WithPayload(&models.Error{Code: 500, Message: swag.String(err.Error())})
|
||||
return admin_api.NewListPoliciesDefault(int(err.Code)).WithPayload(err)
|
||||
}
|
||||
return admin_api.NewListPoliciesOK().WithPayload(listPoliciesResponse)
|
||||
})
|
||||
@@ -45,7 +42,7 @@ func registersPoliciesHandler(api *operations.ConsoleAPI) {
|
||||
api.AdminAPIPolicyInfoHandler = admin_api.PolicyInfoHandlerFunc(func(params admin_api.PolicyInfoParams, session *models.Principal) middleware.Responder {
|
||||
policyInfo, err := getPolicyInfoResponse(session, params)
|
||||
if err != nil {
|
||||
return admin_api.NewPolicyInfoDefault(500).WithPayload(&models.Error{Code: 500, Message: swag.String(err.Error())})
|
||||
return admin_api.NewPolicyInfoDefault(int(err.Code)).WithPayload(err)
|
||||
}
|
||||
return admin_api.NewPolicyInfoOK().WithPayload(policyInfo)
|
||||
})
|
||||
@@ -53,24 +50,21 @@ func registersPoliciesHandler(api *operations.ConsoleAPI) {
|
||||
api.AdminAPIAddPolicyHandler = admin_api.AddPolicyHandlerFunc(func(params admin_api.AddPolicyParams, session *models.Principal) middleware.Responder {
|
||||
policyResponse, err := getAddPolicyResponse(session, params.Body)
|
||||
if err != nil {
|
||||
return admin_api.NewAddPolicyDefault(500).WithPayload(&models.Error{
|
||||
Code: 500,
|
||||
Message: swag.String(err.Error()),
|
||||
})
|
||||
return admin_api.NewAddPolicyDefault(int(err.Code)).WithPayload(err)
|
||||
}
|
||||
return admin_api.NewAddPolicyCreated().WithPayload(policyResponse)
|
||||
})
|
||||
// Remove Policy
|
||||
api.AdminAPIRemovePolicyHandler = admin_api.RemovePolicyHandlerFunc(func(params admin_api.RemovePolicyParams, session *models.Principal) middleware.Responder {
|
||||
if err := getRemovePolicyResponse(session, params); err != nil {
|
||||
return admin_api.NewRemovePolicyDefault(500).WithPayload(&models.Error{Code: 500, Message: swag.String(err.Error())})
|
||||
return admin_api.NewRemovePolicyDefault(int(err.Code)).WithPayload(err)
|
||||
}
|
||||
return admin_api.NewRemovePolicyNoContent()
|
||||
})
|
||||
// Set Policy
|
||||
api.AdminAPISetPolicyHandler = admin_api.SetPolicyHandlerFunc(func(params admin_api.SetPolicyParams, session *models.Principal) middleware.Responder {
|
||||
if err := getSetPolicyResponse(session, params.Name, params.Body); err != nil {
|
||||
return admin_api.NewSetPolicyDefault(500).WithPayload(&models.Error{Code: 500, Message: swag.String(err.Error())})
|
||||
return admin_api.NewSetPolicyDefault(int(err.Code)).WithPayload(err)
|
||||
}
|
||||
return admin_api.NewSetPolicyNoContent()
|
||||
})
|
||||
@@ -97,12 +91,11 @@ func listPolicies(ctx context.Context, client MinioAdmin) ([]*models.Policy, err
|
||||
}
|
||||
|
||||
// getListPoliciesResponse performs listPolicies() and serializes it to the handler's output
|
||||
func getListPoliciesResponse(session *models.Principal) (*models.ListPoliciesResponse, error) {
|
||||
func getListPoliciesResponse(session *models.Principal) (*models.ListPoliciesResponse, *models.Error) {
|
||||
ctx := context.Background()
|
||||
mAdmin, err := newMAdminClient(session)
|
||||
if err != nil {
|
||||
log.Println("error creating Madmin Client:", err)
|
||||
return nil, err
|
||||
return nil, prepareError(err)
|
||||
}
|
||||
// create a MinIO Admin Client interface implementation
|
||||
// defining the client to be used
|
||||
@@ -110,8 +103,7 @@ func getListPoliciesResponse(session *models.Principal) (*models.ListPoliciesRes
|
||||
|
||||
policies, err := listPolicies(ctx, adminClient)
|
||||
if err != nil {
|
||||
log.Println("error listing policies:", err)
|
||||
return nil, err
|
||||
return nil, prepareError(err)
|
||||
}
|
||||
// serialize output
|
||||
listPoliciesResponse := &models.ListPoliciesResponse{
|
||||
@@ -131,24 +123,21 @@ func removePolicy(ctx context.Context, client MinioAdmin, name string) error {
|
||||
}
|
||||
|
||||
// getRemovePolicyResponse() performs removePolicy() and serializes it to the handler's output
|
||||
func getRemovePolicyResponse(session *models.Principal, params admin_api.RemovePolicyParams) error {
|
||||
func getRemovePolicyResponse(session *models.Principal, params admin_api.RemovePolicyParams) *models.Error {
|
||||
ctx := context.Background()
|
||||
if params.Name == "" {
|
||||
log.Println("error policy name not in request")
|
||||
return errors.New(500, "error policy name not in request")
|
||||
return prepareError(errPolicyNameNotInRequest)
|
||||
}
|
||||
mAdmin, err := newMAdminClient(session)
|
||||
if err != nil {
|
||||
log.Println("error creating Madmin Client:", err)
|
||||
return err
|
||||
return prepareError(err)
|
||||
}
|
||||
// create a MinIO Admin Client interface implementation
|
||||
// defining the client to be used
|
||||
adminClient := adminClient{client: mAdmin}
|
||||
|
||||
if err := removePolicy(ctx, adminClient, params.Name); err != nil {
|
||||
log.Println("error removing policy:", err)
|
||||
return err
|
||||
return prepareError(err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -173,25 +162,23 @@ func addPolicy(ctx context.Context, client MinioAdmin, name, policy string) (*mo
|
||||
}
|
||||
|
||||
// getAddPolicyResponse performs addPolicy() and serializes it to the handler's output
|
||||
func getAddPolicyResponse(session *models.Principal, params *models.AddPolicyRequest) (*models.Policy, error) {
|
||||
func getAddPolicyResponse(session *models.Principal, params *models.AddPolicyRequest) (*models.Policy, *models.Error) {
|
||||
ctx := context.Background()
|
||||
if params == nil {
|
||||
log.Println("error AddPolicy body not in request")
|
||||
return nil, errors.New(500, "error AddPolicy body not in request")
|
||||
return nil, prepareError(errPolicyBodyNotInRequest)
|
||||
}
|
||||
|
||||
mAdmin, err := newMAdminClient(session)
|
||||
if err != nil {
|
||||
log.Println("error creating Madmin Client:", err)
|
||||
return nil, err
|
||||
return nil, prepareError(err)
|
||||
}
|
||||
// create a MinIO Admin Client interface implementation
|
||||
// defining the client to be used
|
||||
adminClient := adminClient{client: mAdmin}
|
||||
policy, err := addPolicy(ctx, adminClient, *params.Name, *params.Policy)
|
||||
if err != nil {
|
||||
log.Println("error adding policy")
|
||||
return nil, err
|
||||
return nil, prepareError(err)
|
||||
}
|
||||
return policy, nil
|
||||
}
|
||||
@@ -213,20 +200,18 @@ func policyInfo(ctx context.Context, client MinioAdmin, name string) (*models.Po
|
||||
}
|
||||
|
||||
// getPolicyInfoResponse performs policyInfo() and serializes it to the handler's output
|
||||
func getPolicyInfoResponse(session *models.Principal, params admin_api.PolicyInfoParams) (*models.Policy, error) {
|
||||
func getPolicyInfoResponse(session *models.Principal, params admin_api.PolicyInfoParams) (*models.Policy, *models.Error) {
|
||||
ctx := context.Background()
|
||||
mAdmin, err := newMAdminClient(session)
|
||||
if err != nil {
|
||||
log.Println("error creating Madmin Client:", err)
|
||||
return nil, err
|
||||
return nil, prepareError(err)
|
||||
}
|
||||
// create a MinIO Admin Client interface implementation
|
||||
// defining the client to be used
|
||||
adminClient := adminClient{client: mAdmin}
|
||||
policy, err := policyInfo(ctx, adminClient, params.Name)
|
||||
if err != nil {
|
||||
log.Println("error getting group info:", err)
|
||||
return nil, err
|
||||
return nil, prepareError(err)
|
||||
}
|
||||
return policy, nil
|
||||
}
|
||||
@@ -244,24 +229,21 @@ func setPolicy(ctx context.Context, client MinioAdmin, name, entityName string,
|
||||
}
|
||||
|
||||
// getSetPolicyResponse() performs setPolicy() and serializes it to the handler's output
|
||||
func getSetPolicyResponse(session *models.Principal, name string, params *models.SetPolicyRequest) error {
|
||||
func getSetPolicyResponse(session *models.Principal, name string, params *models.SetPolicyRequest) *models.Error {
|
||||
ctx := context.Background()
|
||||
if name == "" {
|
||||
log.Println("error policy name not in request")
|
||||
return errors.New(500, "error policy name not in request")
|
||||
return prepareError(errPolicyNameNotInRequest)
|
||||
}
|
||||
mAdmin, err := newMAdminClient(session)
|
||||
if err != nil {
|
||||
log.Println("error creating Madmin Client:", err)
|
||||
return err
|
||||
return prepareError(err)
|
||||
}
|
||||
// create a MinIO Admin Client interface implementation
|
||||
// defining the client to be used
|
||||
adminClient := adminClient{client: mAdmin}
|
||||
|
||||
if err := setPolicy(ctx, adminClient, name, *params.EntityName, params.EntityType); err != nil {
|
||||
log.Println("error setting policy:", err)
|
||||
return err
|
||||
return prepareError(err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -22,10 +22,8 @@ import (
|
||||
"log"
|
||||
"net/http"
|
||||
|
||||
"github.com/go-openapi/errors"
|
||||
"github.com/go-openapi/runtime"
|
||||
"github.com/go-openapi/runtime/middleware"
|
||||
"github.com/go-openapi/swag"
|
||||
"github.com/minio/console/models"
|
||||
"github.com/minio/console/restapi/operations"
|
||||
"github.com/minio/console/restapi/operations/admin_api"
|
||||
@@ -37,7 +35,7 @@ func registerProfilingHandler(api *operations.ConsoleAPI) {
|
||||
api.AdminAPIProfilingStartHandler = admin_api.ProfilingStartHandlerFunc(func(params admin_api.ProfilingStartParams, session *models.Principal) middleware.Responder {
|
||||
profilingStartResponse, err := getProfilingStartResponse(session, params.Body)
|
||||
if err != nil {
|
||||
return admin_api.NewProfilingStartDefault(500).WithPayload(&models.Error{Code: 500, Message: swag.String(err.Error())})
|
||||
return admin_api.NewProfilingStartDefault(int(err.Code)).WithPayload(err)
|
||||
}
|
||||
return admin_api.NewProfilingStartCreated().WithPayload(profilingStartResponse)
|
||||
})
|
||||
@@ -45,7 +43,7 @@ func registerProfilingHandler(api *operations.ConsoleAPI) {
|
||||
api.AdminAPIProfilingStopHandler = admin_api.ProfilingStopHandlerFunc(func(params admin_api.ProfilingStopParams, session *models.Principal) middleware.Responder {
|
||||
profilingStopResponse, err := getProfilingStopResponse(session)
|
||||
if err != nil {
|
||||
return admin_api.NewProfilingStopDefault(500).WithPayload(&models.Error{Code: 500, Message: swag.String(err.Error())})
|
||||
return admin_api.NewProfilingStopDefault(int(err.Code)).WithPayload(err)
|
||||
}
|
||||
// Custom response writer to set the content-disposition header to tell the
|
||||
// HTTP client the name and extension of the file we are returning
|
||||
@@ -90,24 +88,21 @@ func startProfiling(ctx context.Context, client MinioAdmin, profilerType models.
|
||||
}
|
||||
|
||||
// getProfilingStartResponse performs startProfiling() and serializes it to the handler's output
|
||||
func getProfilingStartResponse(session *models.Principal, params *models.ProfilingStartRequest) (*models.StartProfilingList, error) {
|
||||
func getProfilingStartResponse(session *models.Principal, params *models.ProfilingStartRequest) (*models.StartProfilingList, *models.Error) {
|
||||
ctx := context.Background()
|
||||
if params == nil {
|
||||
log.Println("error profiling type not in body request")
|
||||
return nil, errors.New(500, "error AddPolicy body not in request")
|
||||
return nil, prepareError(errPolicyBodyNotInRequest)
|
||||
}
|
||||
mAdmin, err := newMAdminClient(session)
|
||||
if err != nil {
|
||||
log.Println("error creating Madmin Client:", err)
|
||||
return nil, err
|
||||
return nil, prepareError(err)
|
||||
}
|
||||
// create a MinIO Admin Client interface implementation
|
||||
// defining the client to be used
|
||||
adminClient := adminClient{client: mAdmin}
|
||||
profilingItems, err := startProfiling(ctx, adminClient, params.Type)
|
||||
if err != nil {
|
||||
log.Println("error starting profiling:", err)
|
||||
return nil, err
|
||||
return nil, prepareError(err)
|
||||
}
|
||||
profilingList := &models.StartProfilingList{
|
||||
StartResults: profilingItems,
|
||||
@@ -127,20 +122,18 @@ func stopProfiling(ctx context.Context, client MinioAdmin) (io.ReadCloser, error
|
||||
}
|
||||
|
||||
// getProfilingStopResponse() performs setPolicy() and serializes it to the handler's output
|
||||
func getProfilingStopResponse(session *models.Principal) (io.ReadCloser, error) {
|
||||
func getProfilingStopResponse(session *models.Principal) (io.ReadCloser, *models.Error) {
|
||||
ctx := context.Background()
|
||||
mAdmin, err := newMAdminClient(session)
|
||||
if err != nil {
|
||||
log.Println("error creating Madmin Client:", err)
|
||||
return nil, err
|
||||
return nil, prepareError(err)
|
||||
}
|
||||
// create a MinIO Admin Client interface implementation
|
||||
// defining the client to be used
|
||||
adminClient := adminClient{client: mAdmin}
|
||||
profilingData, err := stopProfiling(ctx, adminClient)
|
||||
if err != nil {
|
||||
log.Println("error stopping profiling:", err)
|
||||
return nil, err
|
||||
return nil, prepareError(err)
|
||||
}
|
||||
return profilingData, nil
|
||||
}
|
||||
|
||||
@@ -18,11 +18,9 @@ package restapi
|
||||
|
||||
import (
|
||||
"context"
|
||||
"log"
|
||||
"time"
|
||||
|
||||
"github.com/go-openapi/runtime/middleware"
|
||||
"github.com/go-openapi/swag"
|
||||
"github.com/minio/console/models"
|
||||
"github.com/minio/console/restapi/operations"
|
||||
|
||||
@@ -33,7 +31,7 @@ func registerServiceHandlers(api *operations.ConsoleAPI) {
|
||||
// Restart Service
|
||||
api.AdminAPIRestartServiceHandler = admin_api.RestartServiceHandlerFunc(func(params admin_api.RestartServiceParams, session *models.Principal) middleware.Responder {
|
||||
if err := getRestartServiceResponse(session); err != nil {
|
||||
return admin_api.NewRestartServiceDefault(500).WithPayload(&models.Error{Code: 500, Message: swag.String(err.Error())})
|
||||
return admin_api.NewRestartServiceDefault(int(err.Code)).WithPayload(err)
|
||||
}
|
||||
return admin_api.NewRestartServiceNoContent()
|
||||
})
|
||||
@@ -61,20 +59,18 @@ func serviceRestart(ctx context.Context, client MinioAdmin) error {
|
||||
}
|
||||
|
||||
// getRestartServiceResponse performs serviceRestart()
|
||||
func getRestartServiceResponse(session *models.Principal) error {
|
||||
func getRestartServiceResponse(session *models.Principal) *models.Error {
|
||||
ctx := context.Background()
|
||||
mAdmin, err := newMAdminClient(session)
|
||||
if err != nil {
|
||||
log.Println("error creating Madmin Client:", err)
|
||||
return err
|
||||
return prepareError(err)
|
||||
}
|
||||
// create a MinIO Admin Client interface implementation
|
||||
// defining the client to be used
|
||||
adminClient := adminClient{client: mAdmin}
|
||||
|
||||
if err := serviceRestart(ctx, adminClient); err != nil {
|
||||
log.Println("error restarting service:", err)
|
||||
return err
|
||||
return prepareError(err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
516
restapi/admin_tenants_helper.go
Normal file
516
restapi/admin_tenants_helper.go
Normal file
@@ -0,0 +1,516 @@
|
||||
// This file is part of MinIO Kubernetes Cloud
|
||||
// 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 (
|
||||
"context"
|
||||
"crypto"
|
||||
"encoding/base64"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"log"
|
||||
"time"
|
||||
|
||||
"errors"
|
||||
|
||||
"github.com/minio/console/cluster"
|
||||
"github.com/minio/console/models"
|
||||
"github.com/minio/console/pkg/kes"
|
||||
"github.com/minio/console/restapi/operations/admin_api"
|
||||
operator "github.com/minio/operator/pkg/apis/minio.min.io/v1"
|
||||
"gopkg.in/yaml.v2"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
)
|
||||
|
||||
// tenantUpdateCertificates receives the keyPair certificates (public and private keys) for Minio and Console and will try
|
||||
// to replace the existing kubernetes secrets with the new values, then will restart the affected pods so the new volumes can be mounted
|
||||
func tenantUpdateCertificates(ctx context.Context, operatorClient OperatorClientI, clientSet K8sClientI, namespace string, params admin_api.TenantUpdateCertificateParams) error {
|
||||
tenantName := params.Tenant
|
||||
tenant, err := operatorClient.TenantGet(ctx, namespace, tenantName, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
secretName := fmt.Sprintf("%s-secret", tenantName)
|
||||
body := params.Body
|
||||
// check if MinIO is deployed with external certs and user provided new MinIO keypair
|
||||
if tenant.ExternalCert() && body.Minio != nil {
|
||||
minioCertSecretName := fmt.Sprintf("%s-instance-external-certificates", secretName)
|
||||
// update certificates
|
||||
if _, err := createOrReplaceExternalCertSecret(ctx, clientSet, namespace, body.Minio, minioCertSecretName, tenantName); err != nil {
|
||||
return err
|
||||
}
|
||||
// restart MinIO pods
|
||||
err := clientSet.deletePodCollection(ctx, namespace, metav1.DeleteOptions{}, metav1.ListOptions{
|
||||
LabelSelector: fmt.Sprintf("%s=%s", operator.TenantLabel, tenantName),
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
// check if Console is deployed with external certs and user provided new Console keypair
|
||||
if tenant.ConsoleExternalCert() && tenant.HasConsoleEnabled() && body.Console != nil {
|
||||
consoleCertSecretName := fmt.Sprintf("%s-console-external-certificates", secretName)
|
||||
// update certificates
|
||||
if _, err := createOrReplaceExternalCertSecret(ctx, clientSet, namespace, body.Console, consoleCertSecretName, tenantName); err != nil {
|
||||
return err
|
||||
}
|
||||
// restart Console pods
|
||||
err := clientSet.deletePodCollection(ctx, namespace, metav1.DeleteOptions{}, metav1.ListOptions{
|
||||
LabelSelector: fmt.Sprintf("%s=%s", operator.ConsoleTenantLabel, fmt.Sprintf("%s-console", tenantName)),
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// getTenantUpdateCertificatesResponse wrapper of tenantUpdateCertificates
|
||||
func getTenantUpdateCertificatesResponse(session *models.Principal, params admin_api.TenantUpdateCertificateParams) *models.Error {
|
||||
ctx := context.Background()
|
||||
// get Kubernetes Client
|
||||
clientSet, err := cluster.K8sClient(session.SessionToken)
|
||||
if err != nil {
|
||||
return prepareError(err, errorUnableToUpdateTenantCertificates)
|
||||
}
|
||||
k8sClient := k8sClient{
|
||||
client: clientSet,
|
||||
}
|
||||
opClientClientSet, err := cluster.OperatorClient(session.SessionToken)
|
||||
if err != nil {
|
||||
return prepareError(err, errorUnableToUpdateTenantCertificates)
|
||||
}
|
||||
opClient := operatorClient{
|
||||
client: opClientClientSet,
|
||||
}
|
||||
if err := tenantUpdateCertificates(ctx, &opClient, &k8sClient, params.Namespace, params); err != nil {
|
||||
return prepareError(err, errorUnableToUpdateTenantCertificates)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// tenantUpdateEncryption allow user to update KES server certificates, KES client certificates (used by MinIO for mTLS) and KES configuration (KMS configuration, credentials, etc)
|
||||
func tenantUpdateEncryption(ctx context.Context, operatorClient OperatorClientI, clientSet K8sClientI, namespace string, params admin_api.TenantUpdateEncryptionParams) error {
|
||||
tenantName := params.Tenant
|
||||
secretName := fmt.Sprintf("%s-secret", tenantName)
|
||||
tenant, err := operatorClient.TenantGet(ctx, namespace, tenantName, metav1.GetOptions{})
|
||||
body := params.Body
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Check if encryption is enabled for MinIO via KES
|
||||
if tenant.HasKESEnabled() {
|
||||
// check if KES is deployed with external certificates and user provided new server keypair
|
||||
if tenant.KESExternalCert() && body.Server != nil {
|
||||
kesExternalCertSecretName := fmt.Sprintf("%s-kes-external-cert", secretName)
|
||||
// update certificates
|
||||
if _, err := createOrReplaceExternalCertSecret(ctx, clientSet, namespace, body.Server, kesExternalCertSecretName, tenantName); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
// check if Tenant is deployed with external client certificates and user provided new client keypaiir
|
||||
if tenant.ExternalClientCert() && body.Client != nil {
|
||||
tenantExternalClientCertSecretName := fmt.Sprintf("%s-tenant-external-client-cert", secretName)
|
||||
// Update certificates
|
||||
if _, err := createOrReplaceExternalCertSecret(ctx, clientSet, namespace, body.Client, tenantExternalClientCertSecretName, tenantName); err != nil {
|
||||
return err
|
||||
}
|
||||
// Restart MinIO pods to mount the new client secrets
|
||||
err := clientSet.deletePodCollection(ctx, namespace, metav1.DeleteOptions{}, metav1.ListOptions{
|
||||
LabelSelector: fmt.Sprintf("%s=%s", operator.TenantLabel, tenantName),
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
// update KES identities in kes-configuration.yaml secret
|
||||
kesConfigurationSecretName := fmt.Sprintf("%s-kes-configuration", secretName)
|
||||
kesClientCertSecretName := fmt.Sprintf("%s-kes-client-cert", secretName)
|
||||
_, _, err := createOrReplaceKesConfigurationSecrets(ctx, clientSet, namespace, body, kesConfigurationSecretName, kesClientCertSecretName, tenantName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Restart KES pods to mount the new configuration
|
||||
err = clientSet.deletePodCollection(ctx, namespace, metav1.DeleteOptions{}, metav1.ListOptions{
|
||||
LabelSelector: fmt.Sprintf("%s=%s", operator.KESInstanceLabel, fmt.Sprintf("%s-kes", tenantName)),
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// getTenantUpdateEncryptionResponse is a wrapper for tenantUpdateEncryption
|
||||
func getTenantUpdateEncryptionResponse(session *models.Principal, params admin_api.TenantUpdateEncryptionParams) *models.Error {
|
||||
ctx := context.Background()
|
||||
// get Kubernetes Client
|
||||
clientSet, err := cluster.K8sClient(session.SessionToken)
|
||||
if err != nil {
|
||||
return prepareError(err, errorUpdatingEncryptionConfig)
|
||||
}
|
||||
k8sClient := k8sClient{
|
||||
client: clientSet,
|
||||
}
|
||||
opClientClientSet, err := cluster.OperatorClient(session.SessionToken)
|
||||
if err != nil {
|
||||
return prepareError(err, errorUpdatingEncryptionConfig)
|
||||
}
|
||||
opClient := operatorClient{
|
||||
client: opClientClientSet,
|
||||
}
|
||||
if err := tenantUpdateEncryption(ctx, &opClient, &k8sClient, params.Namespace, params); err != nil {
|
||||
return prepareError(err, errorUpdatingEncryptionConfig)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// getKESConfiguration will generate the KES server certificate secrets, the tenant client secrets for mTLS authentication between MinIO and KES and the
|
||||
// kes-configuration.yaml file used by the KES service (how to connect to the external KMS, eg: Vault, AWS, Gemalto, etc)
|
||||
func getKESConfiguration(ctx context.Context, clientSet K8sClientI, ns string, encryptionCfg *models.EncryptionConfiguration, secretName, tenantName string, autoCert bool) (kesConfiguration *operator.KESConfig, err error) {
|
||||
// Secrets used by the MiniO tenant service
|
||||
//
|
||||
// tenantExternalClientCertSecretName is the name of the secret that will store the certificates for mTLS between MinIO and the KES, eg: app.key and app.crt
|
||||
tenantExternalClientCertSecretName := fmt.Sprintf("%s-tenant-external-client-cert", secretName)
|
||||
// Secrets used by the KES service
|
||||
//
|
||||
// kesExternalCertSecretName is the name of the secret that will store the certificates for TLS in the KES server, eg: server.key and server.crt
|
||||
kesExternalCertSecretName := fmt.Sprintf("%s-kes-external-cert", secretName)
|
||||
// kesClientCertSecretName is the name of the secret that will store the certificates for mTLS between KES and the KMS, eg: mTLS with Vault or Gemalto KMS
|
||||
kesClientCertSecretName := fmt.Sprintf("%s-kes-client-cert", secretName)
|
||||
// kesConfigurationSecretName is the name of the secret that will store the configuration file, eg: kes-configuration.yaml
|
||||
kesConfigurationSecretName := fmt.Sprintf("%s-kes-configuration", secretName)
|
||||
// if there's an error during this process we delete all KES configuration secrets
|
||||
defer func() {
|
||||
if err != nil {
|
||||
errDelete := clientSet.deleteSecret(ctx, ns, tenantExternalClientCertSecretName, metav1.DeleteOptions{})
|
||||
if errDelete != nil {
|
||||
log.Print(errDelete)
|
||||
}
|
||||
errDelete = clientSet.deleteSecret(ctx, ns, kesExternalCertSecretName, metav1.DeleteOptions{})
|
||||
if errDelete != nil {
|
||||
log.Print(errDelete)
|
||||
}
|
||||
errDelete = clientSet.deleteSecret(ctx, ns, kesClientCertSecretName, metav1.DeleteOptions{})
|
||||
if errDelete != nil {
|
||||
log.Print(errDelete)
|
||||
}
|
||||
errDelete = clientSet.deleteSecret(ctx, ns, kesConfigurationSecretName, metav1.DeleteOptions{})
|
||||
if errDelete != nil {
|
||||
log.Print(errDelete)
|
||||
}
|
||||
return
|
||||
}
|
||||
}()
|
||||
kesConfiguration = &operator.KESConfig{
|
||||
Image: "minio/kes:v0.11.0",
|
||||
Replicas: 1,
|
||||
Metadata: nil,
|
||||
}
|
||||
// Using custom image for KES
|
||||
if encryptionCfg.Image != "" {
|
||||
kesConfiguration.Image = encryptionCfg.Image
|
||||
}
|
||||
// Generate server certificates for KES only if autoCert is disabled
|
||||
if !autoCert {
|
||||
kesExternalCertSecret, err := createOrReplaceExternalCertSecret(ctx, clientSet, ns, encryptionCfg.Server, kesExternalCertSecretName, tenantName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// External TLS certificates used by KES
|
||||
kesConfiguration.ExternalCertSecret = kesExternalCertSecret
|
||||
}
|
||||
// Prepare kesConfiguration for KES
|
||||
serverConfigSecret, clientCertSecret, err := createOrReplaceKesConfigurationSecrets(ctx, clientSet, ns, encryptionCfg, kesConfigurationSecretName, kesClientCertSecretName, tenantName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// Configuration used by KES
|
||||
kesConfiguration.Configuration = serverConfigSecret
|
||||
kesConfiguration.ClientCertSecret = clientCertSecret
|
||||
|
||||
return kesConfiguration, nil
|
||||
}
|
||||
|
||||
// createOrReplaceExternalCertSecret receives a keypair, public and private key, encoded in base64, decode it and generate a new kubernetes secret
|
||||
// to be used by the operator for TLS encryption
|
||||
func createOrReplaceExternalCertSecret(ctx context.Context, clientSet K8sClientI, ns string, keyPair *models.KeyPairConfiguration, secretName, tenantName string) (*operator.LocalCertificateReference, error) {
|
||||
if keyPair == nil || keyPair.Crt == nil || keyPair.Key == nil || *keyPair.Crt == "" || *keyPair.Key == "" {
|
||||
return nil, errors.New("certificate files must not be empty")
|
||||
}
|
||||
// delete secret with same name if exists
|
||||
err := clientSet.deleteSecret(ctx, ns, secretName, metav1.DeleteOptions{})
|
||||
if err != nil {
|
||||
// log the error if any and continue
|
||||
log.Println(err)
|
||||
}
|
||||
imm := true
|
||||
tlsCrt, err := base64.StdEncoding.DecodeString(*keyPair.Crt)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
tlsKey, err := base64.StdEncoding.DecodeString(*keyPair.Key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
externalTLSCertificateSecret := &corev1.Secret{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: secretName,
|
||||
Labels: map[string]string{
|
||||
operator.TenantLabel: tenantName,
|
||||
},
|
||||
},
|
||||
Type: corev1.SecretTypeTLS,
|
||||
Immutable: &imm,
|
||||
Data: map[string][]byte{
|
||||
"tls.crt": tlsCrt,
|
||||
"tls.key": tlsKey,
|
||||
},
|
||||
}
|
||||
_, err = clientSet.createSecret(ctx, ns, externalTLSCertificateSecret, metav1.CreateOptions{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// Certificates used by the minio instance
|
||||
return &operator.LocalCertificateReference{
|
||||
Name: secretName,
|
||||
Type: "kubernetes.io/tls",
|
||||
}, nil
|
||||
}
|
||||
|
||||
func createOrReplaceKesConfigurationSecrets(ctx context.Context, clientSet K8sClientI, ns string, encryptionCfg *models.EncryptionConfiguration, kesConfigurationSecretName, kesClientCertSecretName, tenantName string) (*corev1.LocalObjectReference, *operator.LocalCertificateReference, error) {
|
||||
// delete KES configuration secret if exists
|
||||
if err := clientSet.deleteSecret(ctx, ns, kesConfigurationSecretName, metav1.DeleteOptions{}); err != nil {
|
||||
// log the error if any and continue
|
||||
log.Println(err)
|
||||
}
|
||||
// delete KES client cert secret if exists
|
||||
if err := clientSet.deleteSecret(ctx, ns, kesClientCertSecretName, metav1.DeleteOptions{}); err != nil {
|
||||
// log the error if any and continue
|
||||
log.Println(err)
|
||||
}
|
||||
// if autoCert is enabled then Operator will generate the client certificates, calculate the client cert identity
|
||||
// and pass it to KES via the $MINIO_KES_IDENTITY variable
|
||||
clientCrtIdentity := "$MINIO_KES_IDENTITY"
|
||||
// If a client certificate is provided proceed to calculate the identity
|
||||
if encryptionCfg.Client != nil {
|
||||
// Client certificate for KES used by Minio to mTLS
|
||||
clientTLSCrt, err := base64.StdEncoding.DecodeString(*encryptionCfg.Client.Crt)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
// Calculate the client cert identity based on the clientTLSCrt
|
||||
h := crypto.SHA256.New()
|
||||
certificate, err := kes.ParseCertificate(clientTLSCrt)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
h.Write(certificate.RawSubjectPublicKeyInfo)
|
||||
clientCrtIdentity = hex.EncodeToString(h.Sum(nil))
|
||||
}
|
||||
// Default kesConfiguration for KES
|
||||
kesConfig := &kes.ServerConfig{
|
||||
Addr: "0.0.0.0:7373",
|
||||
Root: "disabled",
|
||||
TLS: kes.TLS{
|
||||
KeyPath: "/tmp/kes/server.key",
|
||||
CertPath: "/tmp/kes/server.crt",
|
||||
},
|
||||
Policies: map[string]kes.Policy{
|
||||
"default-policy": {
|
||||
Paths: []string{
|
||||
"/v1/key/create/my-minio-key",
|
||||
"/v1/key/generate/my-minio-key",
|
||||
"/v1/key/decrypt/my-minio-key",
|
||||
},
|
||||
Identities: []kes.Identity{
|
||||
kes.Identity(clientCrtIdentity),
|
||||
},
|
||||
},
|
||||
},
|
||||
Cache: kes.Cache{
|
||||
Expiry: &kes.Expiry{
|
||||
Any: 5 * time.Minute,
|
||||
Unused: 20 * time.Second,
|
||||
},
|
||||
},
|
||||
Log: kes.Log{
|
||||
Error: "on",
|
||||
Audit: "off",
|
||||
},
|
||||
Keys: kes.Keys{},
|
||||
}
|
||||
// operator will mount the mTLSCertificates in the following paths
|
||||
// therefore we set these values in the KES yaml kesConfiguration
|
||||
var mTLSClientCrtPath = "/tmp/kes/client.crt"
|
||||
var mTLSClientKeyPath = "/tmp/kes/client.key"
|
||||
var mTLSClientCaPath = "/tmp/kes/ca.crt"
|
||||
// map to hold mTLSCertificates for KES mTLS against Vault
|
||||
mTLSCertificates := map[string][]byte{}
|
||||
// if encryption is enabled and encryption is configured to use Vault
|
||||
if encryptionCfg.Vault != nil {
|
||||
// Initialize Vault Config
|
||||
kesConfig.Keys.Vault = &kes.Vault{
|
||||
Endpoint: *encryptionCfg.Vault.Endpoint,
|
||||
EnginePath: encryptionCfg.Vault.Engine,
|
||||
Namespace: encryptionCfg.Vault.Namespace,
|
||||
Prefix: encryptionCfg.Vault.Prefix,
|
||||
Status: &kes.VaultStatus{
|
||||
Ping: 10 * time.Second,
|
||||
},
|
||||
}
|
||||
// Vault AppRole credentials
|
||||
if encryptionCfg.Vault.Approle != nil {
|
||||
kesConfig.Keys.Vault.AppRole = &kes.AppRole{
|
||||
EnginePath: encryptionCfg.Vault.Approle.Engine,
|
||||
ID: *encryptionCfg.Vault.Approle.ID,
|
||||
Secret: *encryptionCfg.Vault.Approle.Secret,
|
||||
Retry: 15 * time.Second,
|
||||
}
|
||||
} else {
|
||||
return nil, nil, errors.New("approle credentials missing for kes")
|
||||
}
|
||||
// Vault mTLS kesConfiguration
|
||||
if encryptionCfg.Vault.TLS != nil {
|
||||
vaultTLSConfig := encryptionCfg.Vault.TLS
|
||||
kesConfig.Keys.Vault.TLS = &kes.VaultTLS{}
|
||||
if vaultTLSConfig.Crt != "" {
|
||||
clientCrt, err := base64.StdEncoding.DecodeString(vaultTLSConfig.Crt)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
mTLSCertificates["client.crt"] = clientCrt
|
||||
kesConfig.Keys.Vault.TLS.CertPath = mTLSClientCrtPath
|
||||
}
|
||||
if vaultTLSConfig.Key != "" {
|
||||
clientKey, err := base64.StdEncoding.DecodeString(vaultTLSConfig.Key)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
mTLSCertificates["client.key"] = clientKey
|
||||
kesConfig.Keys.Vault.TLS.KeyPath = mTLSClientKeyPath
|
||||
}
|
||||
if vaultTLSConfig.Ca != "" {
|
||||
caCrt, err := base64.StdEncoding.DecodeString(vaultTLSConfig.Ca)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
mTLSCertificates["ca.crt"] = caCrt
|
||||
kesConfig.Keys.Vault.TLS.CAPath = mTLSClientCaPath
|
||||
}
|
||||
}
|
||||
} else if encryptionCfg.Aws != nil {
|
||||
// Initialize AWS
|
||||
kesConfig.Keys.Aws = &kes.Aws{
|
||||
SecretsManager: &kes.AwsSecretManager{},
|
||||
}
|
||||
// AWS basic kesConfiguration
|
||||
if encryptionCfg.Aws.Secretsmanager != nil {
|
||||
kesConfig.Keys.Aws.SecretsManager.Endpoint = *encryptionCfg.Aws.Secretsmanager.Endpoint
|
||||
kesConfig.Keys.Aws.SecretsManager.Region = *encryptionCfg.Aws.Secretsmanager.Region
|
||||
kesConfig.Keys.Aws.SecretsManager.KmsKey = encryptionCfg.Aws.Secretsmanager.Kmskey
|
||||
// AWS credentials
|
||||
if encryptionCfg.Aws.Secretsmanager.Credentials != nil {
|
||||
kesConfig.Keys.Aws.SecretsManager.Login = &kes.AwsSecretManagerLogin{
|
||||
AccessKey: *encryptionCfg.Aws.Secretsmanager.Credentials.Accesskey,
|
||||
SecretKey: *encryptionCfg.Aws.Secretsmanager.Credentials.Secretkey,
|
||||
SessionToken: encryptionCfg.Aws.Secretsmanager.Credentials.Token,
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if encryptionCfg.Gemalto != nil {
|
||||
// Initialize Gemalto
|
||||
kesConfig.Keys.Gemalto = &kes.Gemalto{
|
||||
KeySecure: &kes.GemaltoKeySecure{},
|
||||
}
|
||||
// Gemalto Configuration
|
||||
if encryptionCfg.Gemalto.Keysecure != nil {
|
||||
kesConfig.Keys.Gemalto.KeySecure.Endpoint = *encryptionCfg.Gemalto.Keysecure.Endpoint
|
||||
// Gemalto TLS kesConfiguration
|
||||
if encryptionCfg.Gemalto.Keysecure.TLS != nil {
|
||||
if encryptionCfg.Gemalto.Keysecure.TLS.Ca != nil {
|
||||
caCrt, err := base64.StdEncoding.DecodeString(*encryptionCfg.Gemalto.Keysecure.TLS.Ca)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
mTLSCertificates["ca.crt"] = caCrt
|
||||
kesConfig.Keys.Gemalto.KeySecure.TLS = &kes.GemaltoTLS{
|
||||
CAPath: mTLSClientCaPath,
|
||||
}
|
||||
}
|
||||
}
|
||||
// Gemalto Login
|
||||
if encryptionCfg.Gemalto.Keysecure.Credentials != nil {
|
||||
kesConfig.Keys.Gemalto.KeySecure.Credentials = &kes.GemaltoCredentials{
|
||||
Token: *encryptionCfg.Gemalto.Keysecure.Credentials.Token,
|
||||
Domain: *encryptionCfg.Gemalto.Keysecure.Credentials.Domain,
|
||||
Retry: 15 * time.Second,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
imm := true
|
||||
// if mTLSCertificates contains elements we create the kubernetes secret
|
||||
var clientCertSecretReference *operator.LocalCertificateReference
|
||||
if len(mTLSCertificates) > 0 {
|
||||
// Secret to store KES mTLS kesConfiguration to authenticate against a KMS
|
||||
kesClientCertSecret := corev1.Secret{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: kesClientCertSecretName,
|
||||
Labels: map[string]string{
|
||||
operator.TenantLabel: tenantName,
|
||||
},
|
||||
},
|
||||
Immutable: &imm,
|
||||
Data: mTLSCertificates,
|
||||
}
|
||||
_, err := clientSet.createSecret(ctx, ns, &kesClientCertSecret, metav1.CreateOptions{})
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
// kubernetes generic secret
|
||||
clientCertSecretReference = &operator.LocalCertificateReference{
|
||||
Name: kesClientCertSecretName,
|
||||
}
|
||||
}
|
||||
// Generate Yaml kesConfiguration for KES
|
||||
serverConfigYaml, err := yaml.Marshal(kesConfig)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
// Secret to store KES server kesConfiguration
|
||||
kesConfigurationSecret := corev1.Secret{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: kesConfigurationSecretName,
|
||||
Labels: map[string]string{
|
||||
operator.TenantLabel: tenantName,
|
||||
},
|
||||
},
|
||||
Immutable: &imm,
|
||||
Data: map[string][]byte{
|
||||
"server-config.yaml": serverConfigYaml,
|
||||
},
|
||||
}
|
||||
_, err = clientSet.createSecret(ctx, ns, &kesConfigurationSecret, metav1.CreateOptions{})
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
return &corev1.LocalObjectReference{
|
||||
Name: kesConfigurationSecretName,
|
||||
}, clientCertSecretReference, nil
|
||||
}
|
||||
472
restapi/admin_tenants_helper_test.go
Normal file
472
restapi/admin_tenants_helper_test.go
Normal file
@@ -0,0 +1,472 @@
|
||||
// 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 (
|
||||
"context"
|
||||
"errors"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/minio/console/models"
|
||||
"github.com/minio/console/restapi/operations/admin_api"
|
||||
operator "github.com/minio/operator/pkg/apis/minio.min.io/v1"
|
||||
v1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
)
|
||||
|
||||
var DeletePodCollectionMock func(ctx context.Context, namespace string, opts metav1.DeleteOptions, listOpts metav1.ListOptions) error
|
||||
var DeleteSecretMock func(ctx context.Context, namespace string, name string, opts metav1.DeleteOptions) error
|
||||
var CreateSecretMock func(ctx context.Context, namespace string, secret *v1.Secret, opts metav1.CreateOptions) (*v1.Secret, error)
|
||||
|
||||
func (c k8sClientMock) deletePodCollection(ctx context.Context, namespace string, opts metav1.DeleteOptions, listOpts metav1.ListOptions) error {
|
||||
return DeletePodCollectionMock(ctx, namespace, opts, listOpts)
|
||||
}
|
||||
|
||||
func (c k8sClientMock) deleteSecret(ctx context.Context, namespace string, name string, opts metav1.DeleteOptions) error {
|
||||
return DeleteSecretMock(ctx, namespace, name, opts)
|
||||
}
|
||||
|
||||
func (c k8sClientMock) createSecret(ctx context.Context, namespace string, secret *v1.Secret, opts metav1.CreateOptions) (*v1.Secret, error) {
|
||||
return CreateSecretMock(ctx, namespace, secret, opts)
|
||||
}
|
||||
|
||||
func Test_tenantUpdateCertificates(t *testing.T) {
|
||||
k8sClient := k8sClientMock{}
|
||||
opClient := opClientMock{}
|
||||
crt := "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUUzRENDQTBTZ0F3SUJBZ0lRS0pDalNyK0xaMnJrYVo5ODAvZnV5akFOQmdrcWhraUc5dzBCQVFzRkFEQ0IKdFRFZU1Cd0dBMVVFQ2hNVmJXdGpaWEowSUdSbGRtVnNiM0J0Wlc1MElFTkJNVVV3UXdZRFZRUUxERHhoYkdWMgpjMnRBVEdWdWFXNXpMVTFoWTBKdmIyc3RVSEp2TG14dlkyRnNJQ2hNWlc1cGJpQkJiR1YyYzJ0cElFaDFaWEowCllTQkJjbWxoY3lreFREQktCZ05WQkFNTVEyMXJZMlZ5ZENCaGJHVjJjMnRBVEdWdWFXNXpMVTFoWTBKdmIyc3QKVUhKdkxteHZZMkZzSUNoTVpXNXBiaUJCYkdWMmMydHBJRWgxWlhKMFlTQkJjbWxoY3lrd0hoY05NVGt3TmpBeApNREF3TURBd1doY05NekF3T0RBeU1ERTFNekEzV2pCaU1TY3dKUVlEVlFRS0V4NXRhMk5sY25RZ1pHVjJaV3h2CmNHMWxiblFnWTJWeWRHbG1hV05oZEdVeE56QTFCZ05WQkFzTUxtRnNaWFp6YTBCMGFXWmhMbXh2WTJGc0lDaE0KWlc1cGJpQkJiR1YyYzJ0cElFaDFaWEowWVNCQmNtbGhjeWt3Z2dFaU1BMEdDU3FHU0liM0RRRUJBUVVBQTRJQgpEd0F3Z2dFS0FvSUJBUUM2dlhLVyswWmhJQUNycmpxTU9QZ3VSdGpSemk1L0VxK2JvZTJkQ1BpT3djdXo0WFlhCm1rVlcxSkhBS3VTc0I1UHE0QnFSRXFueUhYT0ZROWQ1bEFjRGNDYmhlTFRVb2h2ZkhOWW9SdWRrYkZ3RzAyOFQKdVMxTFNtcHU5VjhFU2Q0Q3BiOGRvUkcvUW8vRTF4RGk5STFhNVhoeUdHTTNsUFlYQU1HU1ZkWUNNNzh0M2ZLTwp0NFVlcEt6d2dFQ2NKRVg4MVFoem1ZT25ELysyazNxSVppZU9nOGFkbDNFUWV2eFBISXlXQ1JkaDJZTkZsRi9rCmEwTzQyRVl2NVNUT1N0dzI2TzMwTVRrcEg0dzRRZm9VV3BnZU93MDZyYTluRHdzV3VhMUZIaHlKZmxOanR1USsKU0NlaDdqTVlVUThYV1JkbXVHbzFRT0g5cjdDKy82L1JhMlZIQWdNQkFBR2pnYmt3Z2JZd0RnWURWUjBQQVFILwpCQVFEQWdXZ01CTUdBMVVkSlFRTU1Bb0dDQ3NHQVFVRkJ3TUJNQXdHQTFVZEV3RUIvd1FDTUFBd0h3WURWUjBqCkJCZ3dGb0FVNHg4NUIyeGVlQzg0UEdvM1dZVWwxRGVvZlFNd1lBWURWUjBSQkZrd1Y0SWpLaTV0YVc1cGJ5MWgKYkdWMmMyc3Ribk11YzNaakxtTnNkWE4wWlhJdWJHOWpZV3lDTUNvdWFHOXVaWGwzWld4c0xXaHNMbTFwYm1sdgpMV0ZzWlhaemF5MXVjeTV6ZG1NdVkyeDFjM1JsY2k1c2IyTmhiREFOQmdrcWhraUc5dzBCQVFzRkFBT0NBWUVBCnZnMFlIVGtzd3Z4NEE5ZXl0b1V3eTBOSFVjQXpuNy9BVCt3WEt6d3Fqa0RiS3hVYlFTMFNQVVI4SkVDMkpuUUgKU3pTNGFCNXRURVRYZUcrbHJZVU02b0RNcXlIalpUN1NJaW83OUNxOFloWWxORU9qMkhvaXdxalczZm10UU9kVApoVG1tS01lRnZleHo2cnRxbHp0cVdKa3kvOGd1MkMrMWw5UDFFUmhFNDZZY0puVmJ5REFTSGNvV2tiZVhFUGErCjNpNFd4bU1yMDlNZXFTNkFUb2NKanFBeEtYcURYWmlFZjRUVEp1ZTRBQ2s4WmhqaEtUUEV6RnQ3WllVaHY3dVoKdlZCOXhla2FqRzdMRU5kSHZncXVMRUxUV3czWkpBaXpSTU5KUUpzZU11LzdQN1NIeXRKTVJYdlVwd2R2dWhDOApKNm54aGRmUS91QVlQY1lHdlU5NUZPZ1NjWVZqNW1WQktXM0ZHbkl2YzZuamQ1OFhBSTE3dlk0K0ZZTnY4M2UxCm9mOGlxRFdWNTFyT1FlbG9FZFdmdHkvZTI2bXVWUUQzQlVjY2Z5SWpGYy9SeGNHdm5maUEwUm1uRDNkWFcyZ0oKUHFTd01ZZ3hxQndqMm1Qck5jdkFWY3BOeWRjTWJKOTFIOHRWY0ttRHMrY1NiV0tnblpmKzUvZm5yaTdmU3FLUQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg=="
|
||||
key := "LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUV2Z0lCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQktnd2dnU2tBZ0VBQW9JQkFRQzZ2WEtXKzBaaElBQ3IKcmpxTU9QZ3VSdGpSemk1L0VxK2JvZTJkQ1BpT3djdXo0WFlhbWtWVzFKSEFLdVNzQjVQcTRCcVJFcW55SFhPRgpROWQ1bEFjRGNDYmhlTFRVb2h2ZkhOWW9SdWRrYkZ3RzAyOFR1UzFMU21wdTlWOEVTZDRDcGI4ZG9SRy9Rby9FCjF4RGk5STFhNVhoeUdHTTNsUFlYQU1HU1ZkWUNNNzh0M2ZLT3Q0VWVwS3p3Z0VDY0pFWDgxUWh6bVlPbkQvKzIKazNxSVppZU9nOGFkbDNFUWV2eFBISXlXQ1JkaDJZTkZsRi9rYTBPNDJFWXY1U1RPU3R3MjZPMzBNVGtwSDR3NApRZm9VV3BnZU93MDZyYTluRHdzV3VhMUZIaHlKZmxOanR1UStTQ2VoN2pNWVVROFhXUmRtdUdvMVFPSDlyN0MrCi82L1JhMlZIQWdNQkFBRUNnZ0VCQUlyTlVFUnJSM2ZmK3IraGhJRS93ekZhbGNUMUZWaDh3aXpUWXJQcnZCMFkKYlZvcVJzZ2xUVTdxTjkvM3dmc2dzdEROZk5IQ1pySEJOR0drK0orMDZMV2tnakhycjdXeFBUaE16ZDRvUGN4RwpRdTBMOGE5ZVlBMXJwY3NOOVc5Um5JU3BRSEk4aTkxM0V6Z0RoOWk2WCt0bFQyNjNNK0JYaDhlM1Z5cDNSTmhpCjZZUTQwcWJsNlQ0TUlyLzRSMGJmcFExZWVMNVNnbHB6Z1d6ZGs4WGtmc0E5YnRiU1RoMjZKRlBPUU1tMm5adkcKbjBlZm85TDZtaktwRW9rRWpTY1hWYTRZNHJaREZFYTVIbkpUSDBHblByQzU1cDhBb3BFN1c1M2RDT3lxd29CcQo4SWtZb2grcm1qTUZrOGc5VlRVYlcwVE9YVTFSY1E1Z0gxWS9jam5uVTRrQ2dZRUE4amw5ZEQyN2JaQ2ZaTW9jCjJYRThiYkJTaFVXTjRvaklKc1lHY2xyTjJDUEtUNmExaVhvS3BrTXdGNUdsODEzQURGR1pTbWtUSUFVQXRXQU8KNzZCcEpGUlVCZ1hmUXhSU0gyS1RaRldxbE5yekZPQjNsT3h2bFJ1amw5eE9ueStyWUhJWC9BOWNqQlp3a2orSAo3MDZRTExvS1ZFL2lMYy9DMlI5VzRLRVI3R3NDZ1lFQXhWd3FyM1JnUXhHUmpueG1zbDZtUW5DQ3k2MXFoUzUxCkJicDJzWldraFNTV0w0YzFDY0NDMnZ2ektPSmJkZ2NZQU43L05sTHgzWjlCZUFjTVZMUEVoc2NPalB6YUlneEMKczJ2UkdwQUFtYnRjWi9MVlpKaERWTjIrSHowRHhnRUtCa1JzQU5XTG51cGRoUWJBdlZuTkVsY29YVlo1cC9qcwp3U1BCelFoSklaVUNnWUJqTUlHY0dTOW9SWUhRRHlmVEx4aVV2bEI4ZktnR2JRYXhRZ1FmemVsZktnRE5yekhGCnN6RXJOblk2SUkxNVpCbWhzY1I1QVNBd3kzdW55a2N6ZjFldTVjMW1qZjhJQkFsQkN1ZmFmVzRWK0xiMEJKdFQKWTZLcHg2Q3RMaTBQNk1CZ0JUaW5JazgrbW0zTXBiRnZvSmRQaVh0elhTYjhwWWhmeXdLVGg4SEVNd0tCZ1FDUwpvR0VPTFpYKy9pUjRDYkI2d0pzaExWbmZYSjJSQ096a0xwNVVYV3IzaURFVWFvMWJDMjJzcUJjRnZ2WllmL2l6ClhQbWJNSkNGS1BhSTZDT2ZJbGZXRWptYlFaZ0dSN21lZDNISkhFZDE3NTg5azBvN0RHeXB0bnl6MUs3akFvNmkKRFY5NFZ5NytCLzBuQWRkY1ZrVm5aTjJXU3RMam1xcTY2NGZtZmt0bTZRS0JnQzBsMk5OVlFWK2N0OFFRRFpINQpBRFIrSGM3Qk0wNDhURGhNTmhoR3JHc2tWNngwMCtMZTdISGdpT3h2NXJudkNlTlY2M001YUZHdFVWbllTN1VoCkE1NndaNVlZeFFnQ0xzNi9PRmZhK3NiTngrSjdnSjRjNXdMZVlJMXVPMTlzZHBHa2VHZ25vK3dXVmxDSzFCbW0KRGM0TXA2STRiUTVtdy93YVpLQnpjRTJLCi0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0K"
|
||||
badCrt := "ASD"
|
||||
badKey := "ASD"
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
opClient OperatorClientI
|
||||
clientSet K8sClientI
|
||||
namespace string
|
||||
params admin_api.TenantUpdateCertificateParams
|
||||
mockTenantGet func(ctx context.Context, namespace string, tenantName string, options metav1.GetOptions) (*operator.Tenant, error)
|
||||
mockDeleteSecret func(ctx context.Context, namespace string, name string, opts metav1.DeleteOptions) error
|
||||
mockCreateSecret func(ctx context.Context, namespace string, secret *v1.Secret, opts metav1.CreateOptions) (*v1.Secret, error)
|
||||
mockDeletePodCollection func(ctx context.Context, namespace string, opts metav1.DeleteOptions, listOpts metav1.ListOptions) error
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "error getting tenant information",
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
opClient: opClient,
|
||||
clientSet: k8sClient,
|
||||
namespace: "",
|
||||
params: admin_api.TenantUpdateCertificateParams{},
|
||||
mockTenantGet: func(ctx context.Context, namespace string, tenantName string, options metav1.GetOptions) (*operator.Tenant, error) {
|
||||
return nil, errors.New("invalid tenant")
|
||||
},
|
||||
},
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "error replacing external certs for tenant because of missing keypair",
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
opClient: opClient,
|
||||
clientSet: k8sClient,
|
||||
namespace: "",
|
||||
params: admin_api.TenantUpdateCertificateParams{
|
||||
Body: &models.TLSConfiguration{
|
||||
Minio: &models.KeyPairConfiguration{},
|
||||
},
|
||||
},
|
||||
mockTenantGet: func(ctx context.Context, namespace string, tenantName string, options metav1.GetOptions) (*operator.Tenant, error) {
|
||||
return &operator.Tenant{
|
||||
Spec: operator.TenantSpec{
|
||||
ExternalCertSecret: &operator.LocalCertificateReference{
|
||||
Name: "secret",
|
||||
},
|
||||
},
|
||||
}, nil
|
||||
},
|
||||
},
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "error replacing external certs for tenant because of malformed encoded certs",
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
opClient: opClient,
|
||||
clientSet: k8sClient,
|
||||
namespace: "",
|
||||
params: admin_api.TenantUpdateCertificateParams{
|
||||
Body: &models.TLSConfiguration{
|
||||
Minio: &models.KeyPairConfiguration{
|
||||
Crt: &badCrt,
|
||||
Key: &badKey,
|
||||
},
|
||||
},
|
||||
},
|
||||
mockTenantGet: func(ctx context.Context, namespace string, tenantName string, options metav1.GetOptions) (*operator.Tenant, error) {
|
||||
return &operator.Tenant{
|
||||
Spec: operator.TenantSpec{
|
||||
ExternalCertSecret: &operator.LocalCertificateReference{
|
||||
Name: "secret",
|
||||
},
|
||||
},
|
||||
}, nil
|
||||
},
|
||||
mockDeleteSecret: func(ctx context.Context, namespace string, name string, opts metav1.DeleteOptions) error {
|
||||
return nil
|
||||
},
|
||||
},
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "error replacing external certs for tenant because of error during secret creation",
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
opClient: opClient,
|
||||
clientSet: k8sClient,
|
||||
namespace: "",
|
||||
params: admin_api.TenantUpdateCertificateParams{
|
||||
Body: &models.TLSConfiguration{
|
||||
Minio: &models.KeyPairConfiguration{
|
||||
Crt: &crt,
|
||||
Key: &key,
|
||||
},
|
||||
},
|
||||
},
|
||||
mockTenantGet: func(ctx context.Context, namespace string, tenantName string, options metav1.GetOptions) (*operator.Tenant, error) {
|
||||
return &operator.Tenant{
|
||||
Spec: operator.TenantSpec{
|
||||
ExternalCertSecret: &operator.LocalCertificateReference{
|
||||
Name: "secret",
|
||||
},
|
||||
},
|
||||
}, nil
|
||||
},
|
||||
mockDeleteSecret: func(ctx context.Context, namespace string, name string, opts metav1.DeleteOptions) error {
|
||||
return nil
|
||||
},
|
||||
mockCreateSecret: func(ctx context.Context, namespace string, secret *v1.Secret, opts metav1.CreateOptions) (*v1.Secret, error) {
|
||||
return nil, errors.New("error creating secret")
|
||||
},
|
||||
},
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "certificates replaced but error during deleting existing tenant pods",
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
opClient: opClient,
|
||||
clientSet: k8sClient,
|
||||
namespace: "",
|
||||
params: admin_api.TenantUpdateCertificateParams{
|
||||
Body: &models.TLSConfiguration{
|
||||
Minio: &models.KeyPairConfiguration{
|
||||
Crt: &crt,
|
||||
Key: &key,
|
||||
},
|
||||
},
|
||||
},
|
||||
mockTenantGet: func(ctx context.Context, namespace string, tenantName string, options metav1.GetOptions) (*operator.Tenant, error) {
|
||||
return &operator.Tenant{
|
||||
Spec: operator.TenantSpec{
|
||||
ExternalCertSecret: &operator.LocalCertificateReference{
|
||||
Name: "secret",
|
||||
},
|
||||
},
|
||||
}, nil
|
||||
},
|
||||
mockDeleteSecret: func(ctx context.Context, namespace string, name string, opts metav1.DeleteOptions) error {
|
||||
return nil
|
||||
},
|
||||
mockCreateSecret: func(ctx context.Context, namespace string, secret *v1.Secret, opts metav1.CreateOptions) (*v1.Secret, error) {
|
||||
return &v1.Secret{}, nil
|
||||
},
|
||||
mockDeletePodCollection: func(ctx context.Context, namespace string, opts metav1.DeleteOptions, listOpts metav1.ListOptions) error {
|
||||
return errors.New("error deleting minio pods")
|
||||
},
|
||||
},
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "error replacing external certs for console because of missing keypair",
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
opClient: opClient,
|
||||
clientSet: k8sClient,
|
||||
namespace: "",
|
||||
params: admin_api.TenantUpdateCertificateParams{
|
||||
Body: &models.TLSConfiguration{
|
||||
Console: &models.KeyPairConfiguration{},
|
||||
},
|
||||
},
|
||||
mockTenantGet: func(ctx context.Context, namespace string, tenantName string, options metav1.GetOptions) (*operator.Tenant, error) {
|
||||
return &operator.Tenant{
|
||||
Spec: operator.TenantSpec{
|
||||
Console: &operator.ConsoleConfiguration{
|
||||
ExternalCertSecret: &operator.LocalCertificateReference{
|
||||
Name: "secret",
|
||||
},
|
||||
},
|
||||
},
|
||||
}, nil
|
||||
},
|
||||
},
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "certificates replaced but error during deleting existing tenant pods",
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
opClient: opClient,
|
||||
clientSet: k8sClient,
|
||||
namespace: "",
|
||||
params: admin_api.TenantUpdateCertificateParams{
|
||||
Body: &models.TLSConfiguration{
|
||||
Console: &models.KeyPairConfiguration{
|
||||
Crt: &crt,
|
||||
Key: &key,
|
||||
},
|
||||
},
|
||||
},
|
||||
mockTenantGet: func(ctx context.Context, namespace string, tenantName string, options metav1.GetOptions) (*operator.Tenant, error) {
|
||||
return &operator.Tenant{
|
||||
Spec: operator.TenantSpec{
|
||||
Console: &operator.ConsoleConfiguration{
|
||||
ExternalCertSecret: &operator.LocalCertificateReference{
|
||||
Name: "secret",
|
||||
},
|
||||
},
|
||||
},
|
||||
}, nil
|
||||
},
|
||||
mockDeleteSecret: func(ctx context.Context, namespace string, name string, opts metav1.DeleteOptions) error {
|
||||
return nil
|
||||
},
|
||||
mockCreateSecret: func(ctx context.Context, namespace string, secret *v1.Secret, opts metav1.CreateOptions) (*v1.Secret, error) {
|
||||
return &v1.Secret{}, nil
|
||||
},
|
||||
mockDeletePodCollection: func(ctx context.Context, namespace string, opts metav1.DeleteOptions, listOpts metav1.ListOptions) error {
|
||||
return errors.New("error deleting console pods")
|
||||
},
|
||||
},
|
||||
wantErr: true,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
opClientTenantGetMock = tt.args.mockTenantGet
|
||||
DeleteSecretMock = tt.args.mockDeleteSecret
|
||||
CreateSecretMock = tt.args.mockCreateSecret
|
||||
DeletePodCollectionMock = tt.args.mockDeletePodCollection
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if err := tenantUpdateCertificates(tt.args.ctx, tt.args.opClient, tt.args.clientSet, tt.args.namespace, tt.args.params); (err != nil) != tt.wantErr {
|
||||
t.Errorf("tenantUpdateCertificates() error = %v, wantErr %v", err, tt.wantErr)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_tenantUpdateEncryption(t *testing.T) {
|
||||
k8sClient := k8sClientMock{}
|
||||
opClient := opClientMock{}
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
opClient OperatorClientI
|
||||
clientSet K8sClientI
|
||||
namespace string
|
||||
params admin_api.TenantUpdateEncryptionParams
|
||||
mockTenantGet func(ctx context.Context, namespace string, tenantName string, options metav1.GetOptions) (*operator.Tenant, error)
|
||||
mockDeleteSecret func(ctx context.Context, namespace string, name string, opts metav1.DeleteOptions) error
|
||||
mockCreateSecret func(ctx context.Context, namespace string, secret *v1.Secret, opts metav1.CreateOptions) (*v1.Secret, error)
|
||||
mockDeletePodCollection func(ctx context.Context, namespace string, opts metav1.DeleteOptions, listOpts metav1.ListOptions) error
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "error updating encryption configuration because of error getting tenant",
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
opClient: opClient,
|
||||
clientSet: k8sClient,
|
||||
namespace: "",
|
||||
params: admin_api.TenantUpdateEncryptionParams{},
|
||||
mockTenantGet: func(ctx context.Context, namespace string, tenantName string, options metav1.GetOptions) (*operator.Tenant, error) {
|
||||
return nil, errors.New("invalid tenant")
|
||||
},
|
||||
},
|
||||
wantErr: true,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
opClientTenantGetMock = tt.args.mockTenantGet
|
||||
DeleteSecretMock = tt.args.mockDeleteSecret
|
||||
CreateSecretMock = tt.args.mockCreateSecret
|
||||
DeletePodCollectionMock = tt.args.mockDeletePodCollection
|
||||
if err := tenantUpdateEncryption(tt.args.ctx, tt.args.opClient, tt.args.clientSet, tt.args.namespace, tt.args.params); (err != nil) != tt.wantErr {
|
||||
t.Errorf("tenantUpdateEncryption() error = %v, wantErr %v", err, tt.wantErr)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_createOrReplaceKesConfigurationSecrets(t *testing.T) {
|
||||
k8sClient := k8sClientMock{}
|
||||
crt := "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUUzRENDQTBTZ0F3SUJBZ0lRS0pDalNyK0xaMnJrYVo5ODAvZnV5akFOQmdrcWhraUc5dzBCQVFzRkFEQ0IKdFRFZU1Cd0dBMVVFQ2hNVmJXdGpaWEowSUdSbGRtVnNiM0J0Wlc1MElFTkJNVVV3UXdZRFZRUUxERHhoYkdWMgpjMnRBVEdWdWFXNXpMVTFoWTBKdmIyc3RVSEp2TG14dlkyRnNJQ2hNWlc1cGJpQkJiR1YyYzJ0cElFaDFaWEowCllTQkJjbWxoY3lreFREQktCZ05WQkFNTVEyMXJZMlZ5ZENCaGJHVjJjMnRBVEdWdWFXNXpMVTFoWTBKdmIyc3QKVUhKdkxteHZZMkZzSUNoTVpXNXBiaUJCYkdWMmMydHBJRWgxWlhKMFlTQkJjbWxoY3lrd0hoY05NVGt3TmpBeApNREF3TURBd1doY05NekF3T0RBeU1ERTFNekEzV2pCaU1TY3dKUVlEVlFRS0V4NXRhMk5sY25RZ1pHVjJaV3h2CmNHMWxiblFnWTJWeWRHbG1hV05oZEdVeE56QTFCZ05WQkFzTUxtRnNaWFp6YTBCMGFXWmhMbXh2WTJGc0lDaE0KWlc1cGJpQkJiR1YyYzJ0cElFaDFaWEowWVNCQmNtbGhjeWt3Z2dFaU1BMEdDU3FHU0liM0RRRUJBUVVBQTRJQgpEd0F3Z2dFS0FvSUJBUUM2dlhLVyswWmhJQUNycmpxTU9QZ3VSdGpSemk1L0VxK2JvZTJkQ1BpT3djdXo0WFlhCm1rVlcxSkhBS3VTc0I1UHE0QnFSRXFueUhYT0ZROWQ1bEFjRGNDYmhlTFRVb2h2ZkhOWW9SdWRrYkZ3RzAyOFQKdVMxTFNtcHU5VjhFU2Q0Q3BiOGRvUkcvUW8vRTF4RGk5STFhNVhoeUdHTTNsUFlYQU1HU1ZkWUNNNzh0M2ZLTwp0NFVlcEt6d2dFQ2NKRVg4MVFoem1ZT25ELysyazNxSVppZU9nOGFkbDNFUWV2eFBISXlXQ1JkaDJZTkZsRi9rCmEwTzQyRVl2NVNUT1N0dzI2TzMwTVRrcEg0dzRRZm9VV3BnZU93MDZyYTluRHdzV3VhMUZIaHlKZmxOanR1USsKU0NlaDdqTVlVUThYV1JkbXVHbzFRT0g5cjdDKy82L1JhMlZIQWdNQkFBR2pnYmt3Z2JZd0RnWURWUjBQQVFILwpCQVFEQWdXZ01CTUdBMVVkSlFRTU1Bb0dDQ3NHQVFVRkJ3TUJNQXdHQTFVZEV3RUIvd1FDTUFBd0h3WURWUjBqCkJCZ3dGb0FVNHg4NUIyeGVlQzg0UEdvM1dZVWwxRGVvZlFNd1lBWURWUjBSQkZrd1Y0SWpLaTV0YVc1cGJ5MWgKYkdWMmMyc3Ribk11YzNaakxtTnNkWE4wWlhJdWJHOWpZV3lDTUNvdWFHOXVaWGwzWld4c0xXaHNMbTFwYm1sdgpMV0ZzWlhaemF5MXVjeTV6ZG1NdVkyeDFjM1JsY2k1c2IyTmhiREFOQmdrcWhraUc5dzBCQVFzRkFBT0NBWUVBCnZnMFlIVGtzd3Z4NEE5ZXl0b1V3eTBOSFVjQXpuNy9BVCt3WEt6d3Fqa0RiS3hVYlFTMFNQVVI4SkVDMkpuUUgKU3pTNGFCNXRURVRYZUcrbHJZVU02b0RNcXlIalpUN1NJaW83OUNxOFloWWxORU9qMkhvaXdxalczZm10UU9kVApoVG1tS01lRnZleHo2cnRxbHp0cVdKa3kvOGd1MkMrMWw5UDFFUmhFNDZZY0puVmJ5REFTSGNvV2tiZVhFUGErCjNpNFd4bU1yMDlNZXFTNkFUb2NKanFBeEtYcURYWmlFZjRUVEp1ZTRBQ2s4WmhqaEtUUEV6RnQ3WllVaHY3dVoKdlZCOXhla2FqRzdMRU5kSHZncXVMRUxUV3czWkpBaXpSTU5KUUpzZU11LzdQN1NIeXRKTVJYdlVwd2R2dWhDOApKNm54aGRmUS91QVlQY1lHdlU5NUZPZ1NjWVZqNW1WQktXM0ZHbkl2YzZuamQ1OFhBSTE3dlk0K0ZZTnY4M2UxCm9mOGlxRFdWNTFyT1FlbG9FZFdmdHkvZTI2bXVWUUQzQlVjY2Z5SWpGYy9SeGNHdm5maUEwUm1uRDNkWFcyZ0oKUHFTd01ZZ3hxQndqMm1Qck5jdkFWY3BOeWRjTWJKOTFIOHRWY0ttRHMrY1NiV0tnblpmKzUvZm5yaTdmU3FLUQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg=="
|
||||
key := "LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUV2Z0lCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQktnd2dnU2tBZ0VBQW9JQkFRQzZ2WEtXKzBaaElBQ3IKcmpxTU9QZ3VSdGpSemk1L0VxK2JvZTJkQ1BpT3djdXo0WFlhbWtWVzFKSEFLdVNzQjVQcTRCcVJFcW55SFhPRgpROWQ1bEFjRGNDYmhlTFRVb2h2ZkhOWW9SdWRrYkZ3RzAyOFR1UzFMU21wdTlWOEVTZDRDcGI4ZG9SRy9Rby9FCjF4RGk5STFhNVhoeUdHTTNsUFlYQU1HU1ZkWUNNNzh0M2ZLT3Q0VWVwS3p3Z0VDY0pFWDgxUWh6bVlPbkQvKzIKazNxSVppZU9nOGFkbDNFUWV2eFBISXlXQ1JkaDJZTkZsRi9rYTBPNDJFWXY1U1RPU3R3MjZPMzBNVGtwSDR3NApRZm9VV3BnZU93MDZyYTluRHdzV3VhMUZIaHlKZmxOanR1UStTQ2VoN2pNWVVROFhXUmRtdUdvMVFPSDlyN0MrCi82L1JhMlZIQWdNQkFBRUNnZ0VCQUlyTlVFUnJSM2ZmK3IraGhJRS93ekZhbGNUMUZWaDh3aXpUWXJQcnZCMFkKYlZvcVJzZ2xUVTdxTjkvM3dmc2dzdEROZk5IQ1pySEJOR0drK0orMDZMV2tnakhycjdXeFBUaE16ZDRvUGN4RwpRdTBMOGE5ZVlBMXJwY3NOOVc5Um5JU3BRSEk4aTkxM0V6Z0RoOWk2WCt0bFQyNjNNK0JYaDhlM1Z5cDNSTmhpCjZZUTQwcWJsNlQ0TUlyLzRSMGJmcFExZWVMNVNnbHB6Z1d6ZGs4WGtmc0E5YnRiU1RoMjZKRlBPUU1tMm5adkcKbjBlZm85TDZtaktwRW9rRWpTY1hWYTRZNHJaREZFYTVIbkpUSDBHblByQzU1cDhBb3BFN1c1M2RDT3lxd29CcQo4SWtZb2grcm1qTUZrOGc5VlRVYlcwVE9YVTFSY1E1Z0gxWS9jam5uVTRrQ2dZRUE4amw5ZEQyN2JaQ2ZaTW9jCjJYRThiYkJTaFVXTjRvaklKc1lHY2xyTjJDUEtUNmExaVhvS3BrTXdGNUdsODEzQURGR1pTbWtUSUFVQXRXQU8KNzZCcEpGUlVCZ1hmUXhSU0gyS1RaRldxbE5yekZPQjNsT3h2bFJ1amw5eE9ueStyWUhJWC9BOWNqQlp3a2orSAo3MDZRTExvS1ZFL2lMYy9DMlI5VzRLRVI3R3NDZ1lFQXhWd3FyM1JnUXhHUmpueG1zbDZtUW5DQ3k2MXFoUzUxCkJicDJzWldraFNTV0w0YzFDY0NDMnZ2ektPSmJkZ2NZQU43L05sTHgzWjlCZUFjTVZMUEVoc2NPalB6YUlneEMKczJ2UkdwQUFtYnRjWi9MVlpKaERWTjIrSHowRHhnRUtCa1JzQU5XTG51cGRoUWJBdlZuTkVsY29YVlo1cC9qcwp3U1BCelFoSklaVUNnWUJqTUlHY0dTOW9SWUhRRHlmVEx4aVV2bEI4ZktnR2JRYXhRZ1FmemVsZktnRE5yekhGCnN6RXJOblk2SUkxNVpCbWhzY1I1QVNBd3kzdW55a2N6ZjFldTVjMW1qZjhJQkFsQkN1ZmFmVzRWK0xiMEJKdFQKWTZLcHg2Q3RMaTBQNk1CZ0JUaW5JazgrbW0zTXBiRnZvSmRQaVh0elhTYjhwWWhmeXdLVGg4SEVNd0tCZ1FDUwpvR0VPTFpYKy9pUjRDYkI2d0pzaExWbmZYSjJSQ096a0xwNVVYV3IzaURFVWFvMWJDMjJzcUJjRnZ2WllmL2l6ClhQbWJNSkNGS1BhSTZDT2ZJbGZXRWptYlFaZ0dSN21lZDNISkhFZDE3NTg5azBvN0RHeXB0bnl6MUs3akFvNmkKRFY5NFZ5NytCLzBuQWRkY1ZrVm5aTjJXU3RMam1xcTY2NGZtZmt0bTZRS0JnQzBsMk5OVlFWK2N0OFFRRFpINQpBRFIrSGM3Qk0wNDhURGhNTmhoR3JHc2tWNngwMCtMZTdISGdpT3h2NXJudkNlTlY2M001YUZHdFVWbllTN1VoCkE1NndaNVlZeFFnQ0xzNi9PRmZhK3NiTngrSjdnSjRjNXdMZVlJMXVPMTlzZHBHa2VHZ25vK3dXVmxDSzFCbW0KRGM0TXA2STRiUTVtdy93YVpLQnpjRTJLCi0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0K"
|
||||
badCrt := "ASD"
|
||||
badKey := "ASD"
|
||||
appRole := "ASD"
|
||||
appSecret := "ASD"
|
||||
endpoint := "ASD"
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
clientSet K8sClientI
|
||||
ns string
|
||||
encryptionCfg *models.EncryptionConfiguration
|
||||
kesConfigurationSecretName string
|
||||
kesClientCertSecretName string
|
||||
tenantName string
|
||||
mockDeleteSecret func(ctx context.Context, namespace string, name string, opts metav1.DeleteOptions) error
|
||||
mockCreateSecret func(ctx context.Context, namespace string, secret *v1.Secret, opts metav1.CreateOptions) (*v1.Secret, error)
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want *v1.LocalObjectReference
|
||||
want1 *operator.LocalCertificateReference
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "error decoding the client certificate",
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
clientSet: k8sClient,
|
||||
encryptionCfg: &models.EncryptionConfiguration{
|
||||
Client: &models.KeyPairConfiguration{
|
||||
Crt: &badCrt,
|
||||
Key: &badKey,
|
||||
},
|
||||
},
|
||||
ns: "default",
|
||||
kesConfigurationSecretName: "test-secret",
|
||||
kesClientCertSecretName: "test-client-secret",
|
||||
tenantName: "test",
|
||||
mockDeleteSecret: func(ctx context.Context, namespace string, name string, opts metav1.DeleteOptions) error {
|
||||
return nil
|
||||
},
|
||||
},
|
||||
want: nil,
|
||||
want1: nil,
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "error because of malformed decoded certificate",
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
clientSet: k8sClient,
|
||||
encryptionCfg: &models.EncryptionConfiguration{
|
||||
Client: &models.KeyPairConfiguration{
|
||||
Crt: &key, // will cause an error because we are passing a private key as the public key
|
||||
Key: &key,
|
||||
},
|
||||
},
|
||||
ns: "default",
|
||||
kesConfigurationSecretName: "test-secret",
|
||||
kesClientCertSecretName: "test-client-secret",
|
||||
tenantName: "test",
|
||||
mockDeleteSecret: func(ctx context.Context, namespace string, name string, opts metav1.DeleteOptions) error {
|
||||
return nil
|
||||
},
|
||||
},
|
||||
want: nil,
|
||||
want1: nil,
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "error because of malformed decoded certificate",
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
clientSet: k8sClient,
|
||||
encryptionCfg: &models.EncryptionConfiguration{
|
||||
Client: &models.KeyPairConfiguration{
|
||||
Crt: &crt,
|
||||
Key: &key,
|
||||
},
|
||||
Vault: &models.VaultConfiguration{
|
||||
Approle: &models.VaultConfigurationApprole{
|
||||
Engine: "",
|
||||
ID: &appRole,
|
||||
Retry: 0,
|
||||
Secret: &appSecret,
|
||||
},
|
||||
Endpoint: &endpoint,
|
||||
Engine: "",
|
||||
Namespace: "",
|
||||
Prefix: "",
|
||||
Status: nil,
|
||||
TLS: &models.VaultConfigurationTLS{
|
||||
Ca: crt,
|
||||
Crt: crt,
|
||||
Key: key,
|
||||
},
|
||||
},
|
||||
},
|
||||
ns: "default",
|
||||
kesConfigurationSecretName: "test-secret",
|
||||
kesClientCertSecretName: "test-client-secret",
|
||||
tenantName: "test",
|
||||
mockDeleteSecret: func(ctx context.Context, namespace string, name string, opts metav1.DeleteOptions) error {
|
||||
return nil
|
||||
},
|
||||
mockCreateSecret: func(ctx context.Context, namespace string, secret *v1.Secret, opts metav1.CreateOptions) (*v1.Secret, error) {
|
||||
return &v1.Secret{}, nil
|
||||
},
|
||||
},
|
||||
want: &v1.LocalObjectReference{
|
||||
Name: "test-secret",
|
||||
},
|
||||
want1: &operator.LocalCertificateReference{
|
||||
Name: "test-client-secret",
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
DeleteSecretMock = tt.args.mockDeleteSecret
|
||||
CreateSecretMock = tt.args.mockCreateSecret
|
||||
got, got1, err := createOrReplaceKesConfigurationSecrets(tt.args.ctx, tt.args.clientSet, tt.args.ns, tt.args.encryptionCfg, tt.args.kesConfigurationSecretName, tt.args.kesClientCertSecretName, tt.args.tenantName)
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("createOrReplaceKesConfigurationSecrets() error = %v, wantErr %v", err, tt.wantErr)
|
||||
return
|
||||
}
|
||||
if !reflect.DeepEqual(got, tt.want) {
|
||||
t.Errorf("createOrReplaceKesConfigurationSecrets() got = %v, want %v", got, tt.want)
|
||||
}
|
||||
if !reflect.DeepEqual(got1, tt.want1) {
|
||||
t.Errorf("createOrReplaceKesConfigurationSecrets() got1 = %v, want %v", got1, tt.want1)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -33,9 +33,11 @@ import (
|
||||
operator "github.com/minio/operator/pkg/apis/minio.min.io/v1"
|
||||
v1 "github.com/minio/operator/pkg/apis/minio.min.io/v1"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
k8sErrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
"k8s.io/apimachinery/pkg/api/resource"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
types "k8s.io/apimachinery/pkg/types"
|
||||
"k8s.io/client-go/kubernetes/fake"
|
||||
)
|
||||
@@ -86,11 +88,12 @@ func Test_TenantInfoTenantAdminClient(t *testing.T) {
|
||||
kClient := k8sClientMock{}
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
client K8sClient
|
||||
client K8sClientI
|
||||
namespace string
|
||||
tenantName string
|
||||
serviceName string
|
||||
scheme string
|
||||
insecure bool
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
@@ -236,7 +239,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)
|
||||
got, err := getTenantAdminClient(tt.args.ctx, tt.args.client, tt.args.namespace, tt.args.tenantName, tt.args.serviceName, tt.args.scheme, tt.args.insecure)
|
||||
if err != nil {
|
||||
if tt.wantErr {
|
||||
return
|
||||
@@ -334,12 +337,13 @@ func Test_TenantInfo(t *testing.T) {
|
||||
|
||||
func Test_deleteTenantAction(t *testing.T) {
|
||||
opClient := opClientMock{}
|
||||
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
operatorClient OperatorClient
|
||||
operatorClient OperatorClientI
|
||||
nameSpace string
|
||||
tenantName string
|
||||
deletePvcs bool
|
||||
objs []runtime.Object
|
||||
mockTenantDelete func(ctx context.Context, namespace string, tenantName string, options metav1.DeleteOptions) error
|
||||
}
|
||||
tests := []struct {
|
||||
@@ -354,6 +358,7 @@ func Test_deleteTenantAction(t *testing.T) {
|
||||
operatorClient: opClient,
|
||||
nameSpace: "default",
|
||||
tenantName: "minio-tenant",
|
||||
deletePvcs: false,
|
||||
mockTenantDelete: func(ctx context.Context, namespace string, tenantName string, options metav1.DeleteOptions) error {
|
||||
return nil
|
||||
},
|
||||
@@ -367,17 +372,155 @@ func Test_deleteTenantAction(t *testing.T) {
|
||||
operatorClient: opClient,
|
||||
nameSpace: "default",
|
||||
tenantName: "minio-tenant",
|
||||
deletePvcs: false,
|
||||
mockTenantDelete: func(ctx context.Context, namespace string, tenantName string, options metav1.DeleteOptions) error {
|
||||
return errors.New("something happened")
|
||||
},
|
||||
},
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
// Delete only PVCs of the defined tenant on the specific namespace
|
||||
name: "Delete PVCs on Tenant Deletion",
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
operatorClient: opClient,
|
||||
nameSpace: "minio-tenant",
|
||||
tenantName: "tenant1",
|
||||
deletePvcs: true,
|
||||
objs: []runtime.Object{
|
||||
&corev1.PersistentVolumeClaim{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "PVC1",
|
||||
Namespace: "minio-tenant",
|
||||
Labels: map[string]string{
|
||||
operator.TenantLabel: "tenant1",
|
||||
operator.ZoneLabel: "zone-1",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
mockTenantDelete: func(ctx context.Context, namespace string, tenantName string, options metav1.DeleteOptions) error {
|
||||
return nil
|
||||
},
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
// Do not delete underlying pvcs
|
||||
name: "Don't Delete PVCs on Tenant Deletion",
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
operatorClient: opClient,
|
||||
nameSpace: "minio-tenant",
|
||||
tenantName: "tenant1",
|
||||
deletePvcs: false,
|
||||
objs: []runtime.Object{
|
||||
&corev1.PersistentVolumeClaim{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "PVC1",
|
||||
Namespace: "minio-tenant",
|
||||
Labels: map[string]string{
|
||||
operator.TenantLabel: "tenant1",
|
||||
operator.ZoneLabel: "zone-1",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
mockTenantDelete: func(ctx context.Context, namespace string, tenantName string, options metav1.DeleteOptions) error {
|
||||
return nil
|
||||
},
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
// If error is different than NotFound, PVC deletion should not continue
|
||||
name: "Don't delete pvcs if error Deleting Tenant, return",
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
operatorClient: opClient,
|
||||
nameSpace: "minio-tenant",
|
||||
tenantName: "tenant1",
|
||||
deletePvcs: true,
|
||||
objs: []runtime.Object{
|
||||
&corev1.PersistentVolumeClaim{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "PVC1",
|
||||
Namespace: "minio-tenant",
|
||||
Labels: map[string]string{
|
||||
operator.TenantLabel: "tenant1",
|
||||
operator.ZoneLabel: "zone-1",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
mockTenantDelete: func(ctx context.Context, namespace string, tenantName string, options metav1.DeleteOptions) error {
|
||||
return errors.New("error returned")
|
||||
},
|
||||
},
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
// If error is NotFound while trying to Delete Tenant, PVC deletion should continue
|
||||
name: "Delete pvcs if tenant not found",
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
operatorClient: opClient,
|
||||
nameSpace: "minio-tenant",
|
||||
tenantName: "tenant1",
|
||||
deletePvcs: true,
|
||||
objs: []runtime.Object{
|
||||
&corev1.PersistentVolumeClaim{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "PVC1",
|
||||
Namespace: "minio-tenant",
|
||||
Labels: map[string]string{
|
||||
operator.TenantLabel: "tenant1",
|
||||
operator.ZoneLabel: "zone-1",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
mockTenantDelete: func(ctx context.Context, namespace string, tenantName string, options metav1.DeleteOptions) error {
|
||||
return k8sErrors.NewNotFound(schema.GroupResource{}, "tenant1")
|
||||
},
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
// If error is NotFound while trying to Delete Tenant and pvcdeletion=false,
|
||||
// error should be returned
|
||||
name: "Don't delete pvcs and return error if tenant not found",
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
operatorClient: opClient,
|
||||
nameSpace: "minio-tenant",
|
||||
tenantName: "tenant1",
|
||||
deletePvcs: false,
|
||||
objs: []runtime.Object{
|
||||
&corev1.PersistentVolumeClaim{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "PVC1",
|
||||
Namespace: "minio-tenant",
|
||||
Labels: map[string]string{
|
||||
operator.TenantLabel: "tenant1",
|
||||
operator.ZoneLabel: "zone-1",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
mockTenantDelete: func(ctx context.Context, namespace string, tenantName string, options metav1.DeleteOptions) error {
|
||||
return k8sErrors.NewNotFound(schema.GroupResource{}, "tenant1")
|
||||
},
|
||||
},
|
||||
wantErr: true,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
opClientTenantDeleteMock = tt.args.mockTenantDelete
|
||||
kubeClient := fake.NewSimpleClientset(tt.args.objs...)
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if err := deleteTenantAction(tt.args.ctx, tt.args.operatorClient, tt.args.nameSpace, tt.args.tenantName); (err != nil) != tt.wantErr {
|
||||
if err := deleteTenantAction(tt.args.ctx, tt.args.operatorClient, kubeClient.CoreV1(), tt.args.nameSpace, tt.args.tenantName, tt.args.deletePvcs); (err != nil) != tt.wantErr {
|
||||
t.Errorf("deleteTenantAction() error = %v, wantErr %v", err, tt.wantErr)
|
||||
}
|
||||
})
|
||||
@@ -389,7 +532,7 @@ func Test_TenantAddZone(t *testing.T) {
|
||||
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
operatorClient OperatorClient
|
||||
operatorClient OperatorClientI
|
||||
nameSpace string
|
||||
mockTenantPatch func(ctx context.Context, namespace string, tenantName string, pt types.PatchType, data []byte, options metav1.PatchOptions) (*v1.Tenant, error)
|
||||
mockTenantGet func(ctx context.Context, namespace string, tenantName string, options metav1.GetOptions) (*v1.Tenant, error)
|
||||
@@ -563,7 +706,7 @@ func Test_UpdateTenantAction(t *testing.T) {
|
||||
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
operatorClient OperatorClient
|
||||
operatorClient OperatorClientI
|
||||
httpCl cluster.HTTPClientI
|
||||
nameSpace string
|
||||
tenantName string
|
||||
@@ -646,6 +789,7 @@ func Test_UpdateTenantAction(t *testing.T) {
|
||||
return &http.Response{}, nil
|
||||
},
|
||||
params: admin_api.UpdateTenantParams{
|
||||
Tenant: "minio-tenant",
|
||||
Body: &models.UpdateTenantRequest{
|
||||
Image: "minio/minio:RELEASE.2020-06-03T22-13-49Z",
|
||||
},
|
||||
@@ -674,6 +818,7 @@ func Test_UpdateTenantAction(t *testing.T) {
|
||||
}, nil
|
||||
},
|
||||
params: admin_api.UpdateTenantParams{
|
||||
Tenant: "minio-tenant",
|
||||
Body: &models.UpdateTenantRequest{
|
||||
Image: "",
|
||||
},
|
||||
@@ -682,7 +827,7 @@ func Test_UpdateTenantAction(t *testing.T) {
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "Empty image input Error retrieving latest image",
|
||||
name: "Empty image input Error retrieving latest image, nothing happens",
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
operatorClient: opClient,
|
||||
@@ -699,12 +844,63 @@ func Test_UpdateTenantAction(t *testing.T) {
|
||||
return nil, errors.New("error")
|
||||
},
|
||||
params: admin_api.UpdateTenantParams{
|
||||
Tenant: "minio-tenant",
|
||||
Body: &models.UpdateTenantRequest{
|
||||
Image: "",
|
||||
},
|
||||
},
|
||||
},
|
||||
wantErr: true,
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "Update minio console version no errors",
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
operatorClient: opClient,
|
||||
httpCl: httpClientM,
|
||||
nameSpace: "default",
|
||||
tenantName: "minio-tenant",
|
||||
mockTenantPatch: func(ctx context.Context, namespace string, tenantName string, pt types.PatchType, data []byte, options metav1.PatchOptions) (*v1.Tenant, error) {
|
||||
return &v1.Tenant{}, nil
|
||||
},
|
||||
mockTenantGet: func(ctx context.Context, namespace string, tenantName string, options metav1.GetOptions) (*v1.Tenant, error) {
|
||||
return &v1.Tenant{}, nil
|
||||
},
|
||||
mockHTTPClientGet: func(url string) (resp *http.Response, err error) {
|
||||
return nil, errors.New("use default minio")
|
||||
},
|
||||
params: admin_api.UpdateTenantParams{
|
||||
Body: &models.UpdateTenantRequest{
|
||||
ConsoleImage: "minio/console:v0.3.23",
|
||||
},
|
||||
},
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "Update minio image pull secrets no errors",
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
operatorClient: opClient,
|
||||
httpCl: httpClientM,
|
||||
nameSpace: "default",
|
||||
tenantName: "minio-tenant",
|
||||
mockTenantPatch: func(ctx context.Context, namespace string, tenantName string, pt types.PatchType, data []byte, options metav1.PatchOptions) (*v1.Tenant, error) {
|
||||
return &v1.Tenant{}, nil
|
||||
},
|
||||
mockTenantGet: func(ctx context.Context, namespace string, tenantName string, options metav1.GetOptions) (*v1.Tenant, error) {
|
||||
return &v1.Tenant{}, nil
|
||||
},
|
||||
mockHTTPClientGet: func(url string) (resp *http.Response, err error) {
|
||||
return nil, errors.New("use default minio")
|
||||
},
|
||||
params: admin_api.UpdateTenantParams{
|
||||
Body: &models.UpdateTenantRequest{
|
||||
ImagePullSecret: "minio-regcred",
|
||||
},
|
||||
},
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
@@ -714,7 +910,7 @@ func Test_UpdateTenantAction(t *testing.T) {
|
||||
cnsClient := fake.NewSimpleClientset(tt.objs...)
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if err := updateTenantAction(tt.args.ctx, tt.args.operatorClient, cnsClient.CoreV1(), tt.args.httpCl, tt.args.nameSpace, tt.args.params); (err != nil) != tt.wantErr {
|
||||
t.Errorf("deleteTenantAction() error = %v, wantErr %v", err, tt.wantErr)
|
||||
t.Errorf("updateTenantAction() error = %v, wantErr %v", err, tt.wantErr)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -19,7 +19,6 @@ package restapi
|
||||
import (
|
||||
"github.com/go-openapi/errors"
|
||||
"github.com/go-openapi/runtime/middleware"
|
||||
"github.com/go-openapi/swag"
|
||||
"github.com/minio/console/models"
|
||||
"github.com/minio/console/restapi/operations"
|
||||
"github.com/minio/console/restapi/operations/admin_api"
|
||||
@@ -36,7 +35,7 @@ func registerUsersHandlers(api *operations.ConsoleAPI) {
|
||||
api.AdminAPIListUsersHandler = admin_api.ListUsersHandlerFunc(func(params admin_api.ListUsersParams, session *models.Principal) middleware.Responder {
|
||||
listUsersResponse, err := getListUsersResponse(session)
|
||||
if err != nil {
|
||||
return admin_api.NewListUsersDefault(500).WithPayload(&models.Error{Code: 500, Message: swag.String(err.Error())})
|
||||
return admin_api.NewListUsersDefault(int(err.Code)).WithPayload(err)
|
||||
}
|
||||
return admin_api.NewListUsersOK().WithPayload(listUsersResponse)
|
||||
})
|
||||
@@ -44,7 +43,7 @@ func registerUsersHandlers(api *operations.ConsoleAPI) {
|
||||
api.AdminAPIAddUserHandler = admin_api.AddUserHandlerFunc(func(params admin_api.AddUserParams, session *models.Principal) middleware.Responder {
|
||||
userResponse, err := getUserAddResponse(session, params)
|
||||
if err != nil {
|
||||
return admin_api.NewAddUserDefault(500).WithPayload(&models.Error{Code: 500, Message: swag.String(err.Error())})
|
||||
return admin_api.NewAddUserDefault(int(err.Code)).WithPayload(err)
|
||||
}
|
||||
return admin_api.NewAddUserCreated().WithPayload(userResponse)
|
||||
})
|
||||
@@ -52,7 +51,7 @@ func registerUsersHandlers(api *operations.ConsoleAPI) {
|
||||
api.AdminAPIRemoveUserHandler = admin_api.RemoveUserHandlerFunc(func(params admin_api.RemoveUserParams, session *models.Principal) middleware.Responder {
|
||||
err := getRemoveUserResponse(session, params)
|
||||
if err != nil {
|
||||
return admin_api.NewRemoveUserDefault(500).WithPayload(&models.Error{Code: 500, Message: swag.String(err.Error())})
|
||||
return admin_api.NewRemoveUserDefault(int(err.Code)).WithPayload(err)
|
||||
}
|
||||
return admin_api.NewRemoveUserNoContent()
|
||||
})
|
||||
@@ -60,7 +59,7 @@ func registerUsersHandlers(api *operations.ConsoleAPI) {
|
||||
api.AdminAPIUpdateUserGroupsHandler = admin_api.UpdateUserGroupsHandlerFunc(func(params admin_api.UpdateUserGroupsParams, session *models.Principal) middleware.Responder {
|
||||
userUpdateResponse, err := getUpdateUserGroupsResponse(session, params)
|
||||
if err != nil {
|
||||
return admin_api.NewUpdateUserGroupsDefault(500).WithPayload(&models.Error{Code: 500, Message: swag.String(err.Error())})
|
||||
return admin_api.NewUpdateUserGroupsDefault(int(err.Code)).WithPayload(err)
|
||||
}
|
||||
|
||||
return admin_api.NewUpdateUserGroupsOK().WithPayload(userUpdateResponse)
|
||||
@@ -69,7 +68,7 @@ func registerUsersHandlers(api *operations.ConsoleAPI) {
|
||||
api.AdminAPIGetUserInfoHandler = admin_api.GetUserInfoHandlerFunc(func(params admin_api.GetUserInfoParams, session *models.Principal) middleware.Responder {
|
||||
userInfoResponse, err := getUserInfoResponse(session, params)
|
||||
if err != nil {
|
||||
return admin_api.NewGetUserInfoDefault(500).WithPayload(&models.Error{Code: 500, Message: swag.String(err.Error())})
|
||||
return admin_api.NewGetUserInfoDefault(int(err.Code)).WithPayload(err)
|
||||
}
|
||||
|
||||
return admin_api.NewGetUserInfoOK().WithPayload(userInfoResponse)
|
||||
@@ -78,7 +77,7 @@ func registerUsersHandlers(api *operations.ConsoleAPI) {
|
||||
api.AdminAPIUpdateUserInfoHandler = admin_api.UpdateUserInfoHandlerFunc(func(params admin_api.UpdateUserInfoParams, session *models.Principal) middleware.Responder {
|
||||
userUpdateResponse, err := getUpdateUserResponse(session, params)
|
||||
if err != nil {
|
||||
return admin_api.NewUpdateUserInfoDefault(500).WithPayload(&models.Error{Code: 500, Message: swag.String(err.Error())})
|
||||
return admin_api.NewUpdateUserInfoDefault(int(err.Code)).WithPayload(err)
|
||||
}
|
||||
|
||||
return admin_api.NewUpdateUserInfoOK().WithPayload(userUpdateResponse)
|
||||
@@ -87,7 +86,7 @@ func registerUsersHandlers(api *operations.ConsoleAPI) {
|
||||
api.AdminAPIBulkUpdateUsersGroupsHandler = admin_api.BulkUpdateUsersGroupsHandlerFunc(func(params admin_api.BulkUpdateUsersGroupsParams, session *models.Principal) middleware.Responder {
|
||||
err := getAddUsersListToGroupsResponse(session, params)
|
||||
if err != nil {
|
||||
return admin_api.NewBulkUpdateUsersGroupsDefault(500).WithPayload(&models.Error{Code: 500, Message: swag.String(err.Error())})
|
||||
return admin_api.NewBulkUpdateUsersGroupsDefault(int(err.Code)).WithPayload(err)
|
||||
}
|
||||
|
||||
return admin_api.NewBulkUpdateUsersGroupsOK()
|
||||
@@ -119,12 +118,11 @@ func listUsers(ctx context.Context, client MinioAdmin) ([]*models.User, error) {
|
||||
}
|
||||
|
||||
// getListUsersResponse performs listUsers() and serializes it to the handler's output
|
||||
func getListUsersResponse(session *models.Principal) (*models.ListUsersResponse, error) {
|
||||
func getListUsersResponse(session *models.Principal) (*models.ListUsersResponse, *models.Error) {
|
||||
ctx := context.Background()
|
||||
mAdmin, err := newMAdminClient(session)
|
||||
if err != nil {
|
||||
log.Println("error creating Madmin Client:", err)
|
||||
return nil, err
|
||||
return nil, prepareError(err)
|
||||
}
|
||||
// create a minioClient interface implementation
|
||||
// defining the client to be used
|
||||
@@ -132,8 +130,7 @@ func getListUsersResponse(session *models.Principal) (*models.ListUsersResponse,
|
||||
|
||||
users, err := listUsers(ctx, adminClient)
|
||||
if err != nil {
|
||||
log.Println("error listing users:", err)
|
||||
return nil, err
|
||||
return nil, prepareError(err)
|
||||
}
|
||||
// serialize output
|
||||
listUsersResponse := &models.ListUsersResponse{
|
||||
@@ -167,12 +164,11 @@ func addUser(ctx context.Context, client MinioAdmin, accessKey, secretKey *strin
|
||||
return userRet, nil
|
||||
}
|
||||
|
||||
func getUserAddResponse(session *models.Principal, params admin_api.AddUserParams) (*models.User, error) {
|
||||
func getUserAddResponse(session *models.Principal, params admin_api.AddUserParams) (*models.User, *models.Error) {
|
||||
ctx := context.Background()
|
||||
mAdmin, err := newMAdminClient(session)
|
||||
if err != nil {
|
||||
log.Println("error creating Madmin Client:", err)
|
||||
return nil, err
|
||||
return nil, prepareError(err)
|
||||
}
|
||||
// create a minioClient interface implementation
|
||||
// defining the client to be used
|
||||
@@ -180,8 +176,7 @@ func getUserAddResponse(session *models.Principal, params admin_api.AddUserParam
|
||||
|
||||
user, err := addUser(ctx, adminClient, params.Body.AccessKey, params.Body.SecretKey, params.Body.Groups)
|
||||
if err != nil {
|
||||
log.Println("error adding user:", err)
|
||||
return nil, err
|
||||
return nil, prepareError(err)
|
||||
}
|
||||
return user, nil
|
||||
}
|
||||
@@ -194,13 +189,12 @@ func removeUser(ctx context.Context, client MinioAdmin, accessKey string) error
|
||||
return nil
|
||||
}
|
||||
|
||||
func getRemoveUserResponse(session *models.Principal, params admin_api.RemoveUserParams) error {
|
||||
func getRemoveUserResponse(session *models.Principal, params admin_api.RemoveUserParams) *models.Error {
|
||||
ctx := context.Background()
|
||||
|
||||
mAdmin, err := newMAdminClient(session)
|
||||
if err != nil {
|
||||
log.Println("error creating Madmin Client:", err)
|
||||
return err
|
||||
return prepareError(err)
|
||||
}
|
||||
|
||||
// create a minioClient interface implementation
|
||||
@@ -208,8 +202,7 @@ func getRemoveUserResponse(session *models.Principal, params admin_api.RemoveUse
|
||||
adminClient := adminClient{client: mAdmin}
|
||||
|
||||
if err := removeUser(ctx, adminClient, params.Name); err != nil {
|
||||
log.Println("error removing user:", err)
|
||||
return err
|
||||
return prepareError(err)
|
||||
}
|
||||
|
||||
log.Println("User removed successfully:", params.Name)
|
||||
@@ -226,13 +219,12 @@ func getUserInfo(ctx context.Context, client MinioAdmin, accessKey string) (*mad
|
||||
return &userInfo, nil
|
||||
}
|
||||
|
||||
func getUserInfoResponse(session *models.Principal, params admin_api.GetUserInfoParams) (*models.User, error) {
|
||||
func getUserInfoResponse(session *models.Principal, params admin_api.GetUserInfoParams) (*models.User, *models.Error) {
|
||||
ctx := context.Background()
|
||||
|
||||
mAdmin, err := newMAdminClient(session)
|
||||
if err != nil {
|
||||
log.Println("error creating Madmin Client:", err)
|
||||
return nil, err
|
||||
return nil, prepareError(err)
|
||||
}
|
||||
|
||||
// create a minioClient interface implementation
|
||||
@@ -241,8 +233,7 @@ func getUserInfoResponse(session *models.Principal, params admin_api.GetUserInfo
|
||||
|
||||
user, err := getUserInfo(ctx, adminClient, params.Name)
|
||||
if err != nil {
|
||||
log.Println("error getting user:", err)
|
||||
return nil, err
|
||||
return nil, prepareError(err)
|
||||
}
|
||||
|
||||
userInformation := &models.User{
|
||||
@@ -341,13 +332,12 @@ func updateUserGroups(ctx context.Context, client MinioAdmin, user string, group
|
||||
return userReturn, nil
|
||||
}
|
||||
|
||||
func getUpdateUserGroupsResponse(session *models.Principal, params admin_api.UpdateUserGroupsParams) (*models.User, error) {
|
||||
func getUpdateUserGroupsResponse(session *models.Principal, params admin_api.UpdateUserGroupsParams) (*models.User, *models.Error) {
|
||||
ctx := context.Background()
|
||||
|
||||
mAdmin, err := newMAdminClient(session)
|
||||
if err != nil {
|
||||
log.Println("error creating Madmin Client:", err)
|
||||
return nil, err
|
||||
return nil, prepareError(err)
|
||||
}
|
||||
|
||||
// create a minioClient interface implementation
|
||||
@@ -357,8 +347,7 @@ func getUpdateUserGroupsResponse(session *models.Principal, params admin_api.Upd
|
||||
user, err := updateUserGroups(ctx, adminClient, params.Name, params.Body.Groups)
|
||||
|
||||
if err != nil {
|
||||
log.Println("error updating users's groups:", params.Body.Groups)
|
||||
return nil, err
|
||||
return nil, prepareError(err)
|
||||
}
|
||||
|
||||
return user, nil
|
||||
@@ -382,13 +371,12 @@ func setUserStatus(ctx context.Context, client MinioAdmin, user string, status s
|
||||
return nil
|
||||
}
|
||||
|
||||
func getUpdateUserResponse(session *models.Principal, params admin_api.UpdateUserInfoParams) (*models.User, error) {
|
||||
func getUpdateUserResponse(session *models.Principal, params admin_api.UpdateUserInfoParams) (*models.User, *models.Error) {
|
||||
ctx := context.Background()
|
||||
|
||||
mAdmin, err := newMAdminClient(session)
|
||||
if err != nil {
|
||||
log.Println("error creating Madmin Client:", err)
|
||||
return nil, err
|
||||
return nil, prepareError(err)
|
||||
}
|
||||
|
||||
// create a minioClient interface implementation
|
||||
@@ -400,14 +388,13 @@ func getUpdateUserResponse(session *models.Principal, params admin_api.UpdateUse
|
||||
groups := params.Body.Groups
|
||||
|
||||
if err := setUserStatus(ctx, adminClient, name, status); err != nil {
|
||||
log.Println("error updating user status:", status)
|
||||
return nil, err
|
||||
return nil, prepareError(err)
|
||||
}
|
||||
|
||||
userElem, errUG := updateUserGroups(ctx, adminClient, name, groups)
|
||||
|
||||
if errUG != nil {
|
||||
return nil, errUG
|
||||
return nil, prepareError(errUG)
|
||||
}
|
||||
return userElem, nil
|
||||
}
|
||||
@@ -455,13 +442,12 @@ func addUsersListToGroups(ctx context.Context, client MinioAdmin, usersToUpdate
|
||||
return nil
|
||||
}
|
||||
|
||||
func getAddUsersListToGroupsResponse(session *models.Principal, params admin_api.BulkUpdateUsersGroupsParams) error {
|
||||
func getAddUsersListToGroupsResponse(session *models.Principal, params admin_api.BulkUpdateUsersGroupsParams) *models.Error {
|
||||
ctx := context.Background()
|
||||
|
||||
mAdmin, err := newMAdminClient(session)
|
||||
if err != nil {
|
||||
log.Println("error creating Madmin Client:", err)
|
||||
return err
|
||||
return prepareError(err)
|
||||
}
|
||||
|
||||
// create a minioClient interface implementation
|
||||
@@ -472,8 +458,7 @@ func getAddUsersListToGroupsResponse(session *models.Principal, params admin_api
|
||||
groupsList := params.Body.Groups
|
||||
|
||||
if err := addUsersListToGroups(ctx, adminClient, usersList, groupsList); err != nil {
|
||||
log.Println("error updating groups bulk users:", err.Error())
|
||||
return err
|
||||
return prepareError(err)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
@@ -54,7 +54,8 @@ func NewAdminClientWithInsecure(url, accessKey, secretKey string, insecure bool)
|
||||
if err != nil {
|
||||
return nil, err.Trace(url)
|
||||
}
|
||||
s3Client.SetCustomTransport(STSClient.Transport)
|
||||
stsClient := PrepareSTSClient(insecure)
|
||||
s3Client.SetCustomTransport(stsClient.Transport)
|
||||
return s3Client, nil
|
||||
}
|
||||
|
||||
@@ -266,7 +267,8 @@ func newAdminFromClaims(claims *models.Principal) (*madmin.AdminClient, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
adminClient.SetCustomTransport(STSClient.Transport)
|
||||
stsClient := PrepareSTSClient(false)
|
||||
adminClient.SetCustomTransport(stsClient.Transport)
|
||||
return adminClient, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -164,7 +164,6 @@ func (s consoleSTSAssumeRole) IsExpired() bool {
|
||||
|
||||
// STSClient contains http.client configuration need it by STSAssumeRole
|
||||
var (
|
||||
STSClient = PrepareSTSClient()
|
||||
MinioEndpoint = getMinIOServer()
|
||||
)
|
||||
|
||||
@@ -204,8 +203,9 @@ func newConsoleCredentials(accessKey, secretKey, location string) (*credentials.
|
||||
Location: location,
|
||||
DurationSeconds: xjwt.GetConsoleSTSAndJWTDurationInSeconds(),
|
||||
}
|
||||
stsClient := PrepareSTSClient(false)
|
||||
stsAssumeRole := &credentials.STSAssumeRole{
|
||||
Client: STSClient,
|
||||
Client: stsClient,
|
||||
STSEndpoint: MinioEndpoint,
|
||||
Options: opts,
|
||||
}
|
||||
@@ -234,10 +234,11 @@ func getConsoleCredentialsFromSession(claims *models.Principal) *credentials.Cre
|
||||
// from the provided jwt
|
||||
func newMinioClient(claims *models.Principal) (*minio.Client, error) {
|
||||
creds := getConsoleCredentialsFromSession(claims)
|
||||
stsClient := PrepareSTSClient(false)
|
||||
minioClient, err := minio.New(getMinIOEndpoint(), &minio.Options{
|
||||
Creds: creds,
|
||||
Secure: getMinIOEndpointIsSecure(),
|
||||
Transport: STSClient.Transport,
|
||||
Transport: stsClient.Transport,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -248,7 +249,7 @@ func newMinioClient(claims *models.Principal) (*minio.Client, error) {
|
||||
// newS3BucketClient creates a new mc S3Client to talk to the server based on a bucket
|
||||
func newS3BucketClient(claims *models.Principal, bucketName string) (*mc.S3Client, error) {
|
||||
endpoint := getMinIOServer()
|
||||
useSSL := getMinIOEndpointIsSecure()
|
||||
useTLS := getMinIOEndpointIsSecure()
|
||||
|
||||
if strings.TrimSpace(bucketName) != "" {
|
||||
endpoint += fmt.Sprintf("/%s", bucketName)
|
||||
@@ -258,7 +259,7 @@ func newS3BucketClient(claims *models.Principal, bucketName string) (*mc.S3Clien
|
||||
return nil, fmt.Errorf("the provided credentials are invalid")
|
||||
}
|
||||
|
||||
s3Config := newS3Config(endpoint, claims.AccessKeyID, claims.SecretAccessKey, claims.SessionToken, !useSSL)
|
||||
s3Config := newS3Config(endpoint, claims.AccessKeyID, claims.SecretAccessKey, claims.SessionToken, !useTLS)
|
||||
client, pErr := mc.S3New(s3Config)
|
||||
if pErr != nil {
|
||||
return nil, pErr.Cause
|
||||
|
||||
@@ -105,15 +105,15 @@ func GetPort() int {
|
||||
return port
|
||||
}
|
||||
|
||||
// GetSSLHostname gets console ssl hostname set on env variable
|
||||
// GetTLSHostname gets console tls hostname set on env variable
|
||||
// or default one
|
||||
func GetSSLHostname() string {
|
||||
func GetTLSHostname() string {
|
||||
return strings.ToLower(env.Get(ConsoleTLSHostname, TLSHostname))
|
||||
}
|
||||
|
||||
// GetSSLPort gets console ssl port set on env variable
|
||||
// GetTLSPort gets console tls port set on env variable
|
||||
// or default one
|
||||
func GetSSLPort() int {
|
||||
func GetTLSPort() int {
|
||||
port, err := strconv.Atoi(env.Get(ConsoleTLSPort, TLSPort))
|
||||
if err != nil {
|
||||
port = 9443
|
||||
@@ -171,14 +171,14 @@ func getSecureHostsProxyHeaders() []string {
|
||||
return []string{}
|
||||
}
|
||||
|
||||
// If SSLRedirect is set to true, then only allow HTTPS requests. Default is true.
|
||||
func getSSLRedirect() bool {
|
||||
return strings.ToLower(env.Get(ConsoleSecureSSLRedirect, TLSRedirect)) == "on"
|
||||
// If TLSRedirect is set to true, then only allow HTTPS requests. Default is true.
|
||||
func getTLSRedirect() bool {
|
||||
return strings.ToLower(env.Get(ConsoleSecureTLSRedirect, TLSRedirect)) == "on"
|
||||
}
|
||||
|
||||
// SSLHost is the host name that is used to redirect HTTP requests to HTTPS. Default is "", which indicates to use the same host.
|
||||
func getSecureSSLHost() string {
|
||||
return env.Get(ConsoleSecureSSLHost, fmt.Sprintf("%s:%s", TLSHostname, TLSPort))
|
||||
// TLSHost is the host name that is used to redirect HTTP requests to HTTPS. Default is "", which indicates to use the same host.
|
||||
func getSecureTLSHost() string {
|
||||
return env.Get(ConsoleSecureTLSHost, fmt.Sprintf("%s:%s", TLSHostname, TLSPort))
|
||||
}
|
||||
|
||||
// STSSeconds is the max-age of the Strict-Transport-Security header. Default is 0, which would NOT include the header.
|
||||
@@ -200,9 +200,9 @@ func getSecureSTSPreload() bool {
|
||||
return strings.ToLower(env.Get(ConsoleSecureSTSPreload, "off")) == "on"
|
||||
}
|
||||
|
||||
// If SSLTemporaryRedirect is true, the a 302 will be used while redirecting. Default is false (301).
|
||||
func getSecureSSLTemporaryRedirect() bool {
|
||||
return strings.ToLower(env.Get(ConsoleSecureSSLTemporaryRedirect, "off")) == "on"
|
||||
// If TLSTemporaryRedirect is true, the a 302 will be used while redirecting. Default is false (301).
|
||||
func getSecureTLSTemporaryRedirect() bool {
|
||||
return strings.ToLower(env.Get(ConsoleSecureTLSTemporaryRedirect, "off")) == "on"
|
||||
}
|
||||
|
||||
// STS header is only included when the connection is HTTPS.
|
||||
|
||||
@@ -112,6 +112,8 @@ func configureAPI(api *operations.ConsoleAPI) http.Handler {
|
||||
registerTenantHandlers(api)
|
||||
// Register ResourceQuota handlers
|
||||
registerResourceQuotaHandlers(api)
|
||||
// Register Nodes' handlers
|
||||
registerNodesHandlers(api)
|
||||
|
||||
api.PreServerShutdown = func() {}
|
||||
|
||||
@@ -149,12 +151,12 @@ func setupGlobalMiddleware(handler http.Handler) http.Handler {
|
||||
AllowedHosts: getSecureAllowedHosts(),
|
||||
AllowedHostsAreRegex: getSecureAllowedHostsAreRegex(),
|
||||
HostsProxyHeaders: getSecureHostsProxyHeaders(),
|
||||
SSLRedirect: getSSLRedirect(),
|
||||
SSLHost: getSecureSSLHost(),
|
||||
SSLRedirect: getTLSRedirect(),
|
||||
SSLHost: getSecureTLSHost(),
|
||||
STSSeconds: getSecureSTSSeconds(),
|
||||
STSIncludeSubdomains: getSecureSTSIncludeSubdomains(),
|
||||
STSPreload: getSecureSTSPreload(),
|
||||
SSLTemporaryRedirect: getSecureSSLTemporaryRedirect(),
|
||||
SSLTemporaryRedirect: getSecureTLSTemporaryRedirect(),
|
||||
SSLHostFunc: nil,
|
||||
ForceSTSHeader: getSecureForceSTSHeader(),
|
||||
FrameDeny: getSecureFrameDeny(),
|
||||
|
||||
@@ -41,12 +41,20 @@ const (
|
||||
ConsoleSecureSTSSeconds = "CONSOLE_SECURE_STS_SECONDS"
|
||||
ConsoleSecureSTSIncludeSubdomains = "CONSOLE_SECURE_STS_INCLUDE_SUB_DOMAINS"
|
||||
ConsoleSecureSTSPreload = "CONSOLE_SECURE_STS_PRELOAD"
|
||||
ConsoleSecureSSLRedirect = "CONSOLE_SECURE_SSL_REDIRECT"
|
||||
ConsoleSecureSSLHost = "CONSOLE_SECURE_SSL_HOST"
|
||||
ConsoleSecureSSLTemporaryRedirect = "CONSOLE_SECURE_SSL_TEMPORARY_REDIRECT"
|
||||
ConsoleSecureTLSRedirect = "CONSOLE_SECURE_TLS_REDIRECT"
|
||||
ConsoleSecureTLSHost = "CONSOLE_SECURE_TLS_HOST"
|
||||
ConsoleSecureTLSTemporaryRedirect = "CONSOLE_SECURE_TLS_TEMPORARY_REDIRECT"
|
||||
ConsoleSecureForceSTSHeader = "CONSOLE_SECURE_FORCE_STS_HEADER"
|
||||
ConsoleSecurePublicKey = "CONSOLE_SECURE_PUBLIC_KEY"
|
||||
ConsoleSecureReferrerPolicy = "CONSOLE_SECURE_REFERRER_POLICY"
|
||||
ConsoleSecureFeaturePolicy = "CONSOLE_SECURE_FEATURE_POLICY"
|
||||
ConsoleSecureExpectCTHeader = "CONSOLE_SECURE_EXPECT_CT_HEADER"
|
||||
)
|
||||
|
||||
// prometheus annotations
|
||||
|
||||
const (
|
||||
prometheusPath = "prometheus.io/path"
|
||||
prometheusPort = "prometheus.io/port"
|
||||
prometheusScrape = "prometheus.io/scrape"
|
||||
)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
100
restapi/error.go
Normal file
100
restapi/error.go
Normal file
@@ -0,0 +1,100 @@
|
||||
package restapi
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"log"
|
||||
|
||||
"github.com/go-openapi/swag"
|
||||
"github.com/minio/console/models"
|
||||
k8sErrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
)
|
||||
|
||||
var (
|
||||
// Generic error messages
|
||||
errorGeneric = errors.New("an error occurred, please try again")
|
||||
errInvalidCredentials = errors.New("invalid Login")
|
||||
errorGenericInvalidSession = errors.New("invalid session")
|
||||
errorGenericUnauthorized = errors.New("unauthorized")
|
||||
errorGenericForbidden = errors.New("forbidden")
|
||||
errorGenericNotFound = errors.New("not found")
|
||||
// Explicit error messages
|
||||
errorInvalidErasureCodingValue = errors.New("invalid Erasure Coding Value")
|
||||
errorUnableToGetTenantUsage = errors.New("unable to get tenant usage")
|
||||
errorUnableToUpdateTenantCertificates = errors.New("unable to update tenant certificates")
|
||||
errorUpdatingEncryptionConfig = errors.New("unable to update encryption configuration")
|
||||
errBucketBodyNotInRequest = errors.New("error bucket body not in request")
|
||||
errBucketNameNotInRequest = errors.New("error bucket name not in request")
|
||||
errGroupBodyNotInRequest = errors.New("error group body not in request")
|
||||
errGroupNameNotInRequest = errors.New("error group name not in request")
|
||||
errPolicyNameNotInRequest = errors.New("error policy name not in request")
|
||||
errPolicyBodyNotInRequest = errors.New("error policy body not in request")
|
||||
)
|
||||
|
||||
// prepareError receives an error object and parse it against k8sErrors, returns the right error code paired with a generic error message
|
||||
func prepareError(err ...error) *models.Error {
|
||||
errorCode := int32(500)
|
||||
errorMessage := errorGeneric.Error()
|
||||
if len(err) > 0 {
|
||||
log.Print("original error: ", err[0].Error())
|
||||
if k8sErrors.IsUnauthorized(err[0]) {
|
||||
errorCode = 401
|
||||
errorMessage = errorGenericUnauthorized.Error()
|
||||
}
|
||||
if k8sErrors.IsForbidden(err[0]) {
|
||||
errorCode = 403
|
||||
errorMessage = errorGenericForbidden.Error()
|
||||
}
|
||||
if k8sErrors.IsNotFound(err[0]) {
|
||||
errorCode = 404
|
||||
errorMessage = errorGenericNotFound.Error()
|
||||
}
|
||||
if errors.Is(err[0], errInvalidCredentials) {
|
||||
errorCode = 401
|
||||
errorMessage = errInvalidCredentials.Error()
|
||||
}
|
||||
// console invalid erasure coding value
|
||||
if errors.Is(err[0], errorInvalidErasureCodingValue) {
|
||||
errorCode = 400
|
||||
errorMessage = errorInvalidErasureCodingValue.Error()
|
||||
}
|
||||
if errors.Is(err[0], errBucketBodyNotInRequest) {
|
||||
errorCode = 400
|
||||
errorMessage = errBucketBodyNotInRequest.Error()
|
||||
}
|
||||
if errors.Is(err[0], errBucketNameNotInRequest) {
|
||||
errorCode = 400
|
||||
errorMessage = errBucketNameNotInRequest.Error()
|
||||
}
|
||||
if errors.Is(err[0], errGroupBodyNotInRequest) {
|
||||
errorCode = 400
|
||||
errorMessage = errGroupBodyNotInRequest.Error()
|
||||
}
|
||||
if errors.Is(err[0], errGroupNameNotInRequest) {
|
||||
errorCode = 400
|
||||
errorMessage = errGroupNameNotInRequest.Error()
|
||||
}
|
||||
if errors.Is(err[0], errPolicyNameNotInRequest) {
|
||||
errorCode = 400
|
||||
errorMessage = errPolicyNameNotInRequest.Error()
|
||||
}
|
||||
if errors.Is(err[0], errPolicyBodyNotInRequest) {
|
||||
errorCode = 400
|
||||
errorMessage = errPolicyBodyNotInRequest.Error()
|
||||
}
|
||||
// console invalid session error
|
||||
if errors.Is(err[0], errorGenericInvalidSession) {
|
||||
errorCode = 401
|
||||
errorMessage = errorGenericInvalidSession.Error()
|
||||
}
|
||||
// if we received a second error take that as friendly message but dont override the code
|
||||
if len(err) > 1 && err[1] != nil {
|
||||
log.Print("friendly error: ", err[1].Error())
|
||||
errorMessage = err[1].Error()
|
||||
}
|
||||
// if we receive third error we just print that as debugging
|
||||
if len(err) > 2 && err[2] != nil {
|
||||
log.Print("debugging error: ", err[2].Error())
|
||||
}
|
||||
}
|
||||
return &models.Error{Code: errorCode, Message: swag.String(errorMessage)}
|
||||
}
|
||||
@@ -24,13 +24,16 @@ import (
|
||||
"k8s.io/client-go/kubernetes"
|
||||
)
|
||||
|
||||
// K8sClient interface with all functions to be implemented
|
||||
// by mock when testing, it should include all K8sClient respective api calls
|
||||
// K8sClientI interface with all functions to be implemented
|
||||
// by mock when testing, it should include all K8sClientI respective api calls
|
||||
// that are used within this project.
|
||||
type K8sClient interface {
|
||||
type K8sClientI interface {
|
||||
getResourceQuota(ctx context.Context, namespace, resource string, opts metav1.GetOptions) (*v1.ResourceQuota, error)
|
||||
getSecret(ctx context.Context, namespace, secretName string, opts metav1.GetOptions) (*v1.Secret, error)
|
||||
getService(ctx context.Context, namespace, serviceName string, opts metav1.GetOptions) (*v1.Service, error)
|
||||
deletePodCollection(ctx context.Context, namespace string, opts metav1.DeleteOptions, listOpts metav1.ListOptions) error
|
||||
deleteSecret(ctx context.Context, namespace string, name string, opts metav1.DeleteOptions) error
|
||||
createSecret(ctx context.Context, namespace string, secret *v1.Secret, opts metav1.CreateOptions) (*v1.Secret, error)
|
||||
}
|
||||
|
||||
// Interface implementation
|
||||
@@ -51,3 +54,15 @@ func (c *k8sClient) getSecret(ctx context.Context, namespace, secretName string,
|
||||
func (c *k8sClient) getService(ctx context.Context, namespace, serviceName string, opts metav1.GetOptions) (*v1.Service, error) {
|
||||
return c.client.CoreV1().Services(namespace).Get(ctx, serviceName, opts)
|
||||
}
|
||||
|
||||
func (c *k8sClient) deletePodCollection(ctx context.Context, namespace string, opts metav1.DeleteOptions, listOpts metav1.ListOptions) error {
|
||||
return c.client.CoreV1().Pods(namespace).DeleteCollection(ctx, opts, listOpts)
|
||||
}
|
||||
|
||||
func (c *k8sClient) deleteSecret(ctx context.Context, namespace string, name string, opts metav1.DeleteOptions) error {
|
||||
return c.client.CoreV1().Secrets(namespace).Delete(ctx, name, opts)
|
||||
}
|
||||
|
||||
func (c *k8sClient) createSecret(ctx context.Context, namespace string, secret *v1.Secret, opts metav1.CreateOptions) (*v1.Secret, error) {
|
||||
return c.client.CoreV1().Secrets(namespace).Create(ctx, secret, opts)
|
||||
}
|
||||
|
||||
@@ -50,7 +50,7 @@ func NewDeleteTenant(ctx *middleware.Context, handler DeleteTenantHandler) *Dele
|
||||
|
||||
/*DeleteTenant swagger:route DELETE /namespaces/{namespace}/tenants/{tenant} AdminAPI deleteTenant
|
||||
|
||||
Delete Tenant
|
||||
Delete tenant and underlying pvcs
|
||||
|
||||
*/
|
||||
type DeleteTenant struct {
|
||||
|
||||
@@ -26,8 +26,11 @@ import (
|
||||
"net/http"
|
||||
|
||||
"github.com/go-openapi/errors"
|
||||
"github.com/go-openapi/runtime"
|
||||
"github.com/go-openapi/runtime/middleware"
|
||||
"github.com/go-openapi/strfmt"
|
||||
|
||||
"github.com/minio/console/models"
|
||||
)
|
||||
|
||||
// NewDeleteTenantParams creates a new DeleteTenantParams object
|
||||
@@ -46,6 +49,10 @@ type DeleteTenantParams struct {
|
||||
// HTTP Request Object
|
||||
HTTPRequest *http.Request `json:"-"`
|
||||
|
||||
/*
|
||||
In: body
|
||||
*/
|
||||
Body *models.DeleteTenantRequest
|
||||
/*
|
||||
Required: true
|
||||
In: path
|
||||
@@ -67,6 +74,22 @@ func (o *DeleteTenantParams) BindRequest(r *http.Request, route *middleware.Matc
|
||||
|
||||
o.HTTPRequest = r
|
||||
|
||||
if runtime.HasBody(r) {
|
||||
defer r.Body.Close()
|
||||
var body models.DeleteTenantRequest
|
||||
if err := route.Consumer.Consume(r.Body, &body); err != nil {
|
||||
res = append(res, errors.NewParseError("body", "body", "", err))
|
||||
} else {
|
||||
// validate body object
|
||||
if err := body.Validate(route.Formats); err != nil {
|
||||
res = append(res, err)
|
||||
}
|
||||
|
||||
if len(res) == 0 {
|
||||
o.Body = &body
|
||||
}
|
||||
}
|
||||
}
|
||||
rNamespace, rhkNamespace, _ := route.Params.GetOK("namespace")
|
||||
if err := o.bindNamespace(rNamespace, rhkNamespace, route.Formats); err != nil {
|
||||
res = append(res, err)
|
||||
|
||||
90
restapi/operations/admin_api/get_max_allocatable_mem.go
Normal file
90
restapi/operations/admin_api/get_max_allocatable_mem.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"
|
||||
)
|
||||
|
||||
// GetMaxAllocatableMemHandlerFunc turns a function with the right signature into a get max allocatable mem handler
|
||||
type GetMaxAllocatableMemHandlerFunc func(GetMaxAllocatableMemParams, *models.Principal) middleware.Responder
|
||||
|
||||
// Handle executing the request and returning a response
|
||||
func (fn GetMaxAllocatableMemHandlerFunc) Handle(params GetMaxAllocatableMemParams, principal *models.Principal) middleware.Responder {
|
||||
return fn(params, principal)
|
||||
}
|
||||
|
||||
// GetMaxAllocatableMemHandler interface for that can handle valid get max allocatable mem params
|
||||
type GetMaxAllocatableMemHandler interface {
|
||||
Handle(GetMaxAllocatableMemParams, *models.Principal) middleware.Responder
|
||||
}
|
||||
|
||||
// NewGetMaxAllocatableMem creates a new http.Handler for the get max allocatable mem operation
|
||||
func NewGetMaxAllocatableMem(ctx *middleware.Context, handler GetMaxAllocatableMemHandler) *GetMaxAllocatableMem {
|
||||
return &GetMaxAllocatableMem{Context: ctx, Handler: handler}
|
||||
}
|
||||
|
||||
/*GetMaxAllocatableMem swagger:route GET /cluster/max-allocatable-memory AdminAPI getMaxAllocatableMem
|
||||
|
||||
Get maximum allocatable memory for given number of nodes
|
||||
|
||||
*/
|
||||
type GetMaxAllocatableMem struct {
|
||||
Context *middleware.Context
|
||||
Handler GetMaxAllocatableMemHandler
|
||||
}
|
||||
|
||||
func (o *GetMaxAllocatableMem) ServeHTTP(rw http.ResponseWriter, r *http.Request) {
|
||||
route, rCtx, _ := o.Context.RouteInfo(r)
|
||||
if rCtx != nil {
|
||||
r = rCtx
|
||||
}
|
||||
var Params = NewGetMaxAllocatableMemParams()
|
||||
|
||||
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)
|
||||
|
||||
}
|
||||
@@ -0,0 +1,119 @@
|
||||
// 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"
|
||||
"github.com/go-openapi/runtime/middleware"
|
||||
"github.com/go-openapi/strfmt"
|
||||
"github.com/go-openapi/swag"
|
||||
"github.com/go-openapi/validate"
|
||||
)
|
||||
|
||||
// NewGetMaxAllocatableMemParams creates a new GetMaxAllocatableMemParams object
|
||||
// no default values defined in spec.
|
||||
func NewGetMaxAllocatableMemParams() GetMaxAllocatableMemParams {
|
||||
|
||||
return GetMaxAllocatableMemParams{}
|
||||
}
|
||||
|
||||
// GetMaxAllocatableMemParams contains all the bound params for the get max allocatable mem operation
|
||||
// typically these are obtained from a http.Request
|
||||
//
|
||||
// swagger:parameters GetMaxAllocatableMem
|
||||
type GetMaxAllocatableMemParams struct {
|
||||
|
||||
// HTTP Request Object
|
||||
HTTPRequest *http.Request `json:"-"`
|
||||
|
||||
/*
|
||||
Required: true
|
||||
Minimum: 1
|
||||
In: query
|
||||
*/
|
||||
NumNodes int32
|
||||
}
|
||||
|
||||
// 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 NewGetMaxAllocatableMemParams() beforehand.
|
||||
func (o *GetMaxAllocatableMemParams) BindRequest(r *http.Request, route *middleware.MatchedRoute) error {
|
||||
var res []error
|
||||
|
||||
o.HTTPRequest = r
|
||||
|
||||
qs := runtime.Values(r.URL.Query())
|
||||
|
||||
qNumNodes, qhkNumNodes, _ := qs.GetOK("num_nodes")
|
||||
if err := o.bindNumNodes(qNumNodes, qhkNumNodes, route.Formats); err != nil {
|
||||
res = append(res, err)
|
||||
}
|
||||
|
||||
if len(res) > 0 {
|
||||
return errors.CompositeValidationError(res...)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// bindNumNodes binds and validates parameter NumNodes from query.
|
||||
func (o *GetMaxAllocatableMemParams) bindNumNodes(rawData []string, hasKey bool, formats strfmt.Registry) error {
|
||||
if !hasKey {
|
||||
return errors.Required("num_nodes", "query", rawData)
|
||||
}
|
||||
var raw string
|
||||
if len(rawData) > 0 {
|
||||
raw = rawData[len(rawData)-1]
|
||||
}
|
||||
|
||||
// Required: true
|
||||
// AllowEmptyValue: false
|
||||
if err := validate.RequiredString("num_nodes", "query", raw); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
value, err := swag.ConvertInt32(raw)
|
||||
if err != nil {
|
||||
return errors.InvalidType("num_nodes", "query", "int32", raw)
|
||||
}
|
||||
o.NumNodes = value
|
||||
|
||||
if err := o.validateNumNodes(formats); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// validateNumNodes carries on validations for parameter NumNodes
|
||||
func (o *GetMaxAllocatableMemParams) validateNumNodes(formats strfmt.Registry) error {
|
||||
|
||||
if err := validate.MinimumInt("num_nodes", "query", int64(o.NumNodes), 1, false); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,133 @@
|
||||
// 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"
|
||||
)
|
||||
|
||||
// GetMaxAllocatableMemOKCode is the HTTP code returned for type GetMaxAllocatableMemOK
|
||||
const GetMaxAllocatableMemOKCode int = 200
|
||||
|
||||
/*GetMaxAllocatableMemOK A successful response.
|
||||
|
||||
swagger:response getMaxAllocatableMemOK
|
||||
*/
|
||||
type GetMaxAllocatableMemOK struct {
|
||||
|
||||
/*
|
||||
In: Body
|
||||
*/
|
||||
Payload *models.MaxAllocatableMemResponse `json:"body,omitempty"`
|
||||
}
|
||||
|
||||
// NewGetMaxAllocatableMemOK creates GetMaxAllocatableMemOK with default headers values
|
||||
func NewGetMaxAllocatableMemOK() *GetMaxAllocatableMemOK {
|
||||
|
||||
return &GetMaxAllocatableMemOK{}
|
||||
}
|
||||
|
||||
// WithPayload adds the payload to the get max allocatable mem o k response
|
||||
func (o *GetMaxAllocatableMemOK) WithPayload(payload *models.MaxAllocatableMemResponse) *GetMaxAllocatableMemOK {
|
||||
o.Payload = payload
|
||||
return o
|
||||
}
|
||||
|
||||
// SetPayload sets the payload to the get max allocatable mem o k response
|
||||
func (o *GetMaxAllocatableMemOK) SetPayload(payload *models.MaxAllocatableMemResponse) {
|
||||
o.Payload = payload
|
||||
}
|
||||
|
||||
// WriteResponse to the client
|
||||
func (o *GetMaxAllocatableMemOK) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) {
|
||||
|
||||
rw.WriteHeader(200)
|
||||
if o.Payload != nil {
|
||||
payload := o.Payload
|
||||
if err := producer.Produce(rw, payload); err != nil {
|
||||
panic(err) // let the recovery middleware deal with this
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*GetMaxAllocatableMemDefault Generic error response.
|
||||
|
||||
swagger:response getMaxAllocatableMemDefault
|
||||
*/
|
||||
type GetMaxAllocatableMemDefault struct {
|
||||
_statusCode int
|
||||
|
||||
/*
|
||||
In: Body
|
||||
*/
|
||||
Payload *models.Error `json:"body,omitempty"`
|
||||
}
|
||||
|
||||
// NewGetMaxAllocatableMemDefault creates GetMaxAllocatableMemDefault with default headers values
|
||||
func NewGetMaxAllocatableMemDefault(code int) *GetMaxAllocatableMemDefault {
|
||||
if code <= 0 {
|
||||
code = 500
|
||||
}
|
||||
|
||||
return &GetMaxAllocatableMemDefault{
|
||||
_statusCode: code,
|
||||
}
|
||||
}
|
||||
|
||||
// WithStatusCode adds the status to the get max allocatable mem default response
|
||||
func (o *GetMaxAllocatableMemDefault) WithStatusCode(code int) *GetMaxAllocatableMemDefault {
|
||||
o._statusCode = code
|
||||
return o
|
||||
}
|
||||
|
||||
// SetStatusCode sets the status to the get max allocatable mem default response
|
||||
func (o *GetMaxAllocatableMemDefault) SetStatusCode(code int) {
|
||||
o._statusCode = code
|
||||
}
|
||||
|
||||
// WithPayload adds the payload to the get max allocatable mem default response
|
||||
func (o *GetMaxAllocatableMemDefault) WithPayload(payload *models.Error) *GetMaxAllocatableMemDefault {
|
||||
o.Payload = payload
|
||||
return o
|
||||
}
|
||||
|
||||
// SetPayload sets the payload to the get max allocatable mem default response
|
||||
func (o *GetMaxAllocatableMemDefault) SetPayload(payload *models.Error) {
|
||||
o.Payload = payload
|
||||
}
|
||||
|
||||
// WriteResponse to the client
|
||||
func (o *GetMaxAllocatableMemDefault) 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
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,119 @@
|
||||
// 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"
|
||||
|
||||
"github.com/go-openapi/swag"
|
||||
)
|
||||
|
||||
// GetMaxAllocatableMemURL generates an URL for the get max allocatable mem operation
|
||||
type GetMaxAllocatableMemURL struct {
|
||||
NumNodes int32
|
||||
|
||||
_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 *GetMaxAllocatableMemURL) WithBasePath(bp string) *GetMaxAllocatableMemURL {
|
||||
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 *GetMaxAllocatableMemURL) SetBasePath(bp string) {
|
||||
o._basePath = bp
|
||||
}
|
||||
|
||||
// Build a url path and query string
|
||||
func (o *GetMaxAllocatableMemURL) Build() (*url.URL, error) {
|
||||
var _result url.URL
|
||||
|
||||
var _path = "/cluster/max-allocatable-memory"
|
||||
|
||||
_basePath := o._basePath
|
||||
if _basePath == "" {
|
||||
_basePath = "/api/v1"
|
||||
}
|
||||
_result.Path = golangswaggerpaths.Join(_basePath, _path)
|
||||
|
||||
qs := make(url.Values)
|
||||
|
||||
numNodesQ := swag.FormatInt32(o.NumNodes)
|
||||
if numNodesQ != "" {
|
||||
qs.Set("num_nodes", numNodesQ)
|
||||
}
|
||||
|
||||
_result.RawQuery = qs.Encode()
|
||||
|
||||
return &_result, nil
|
||||
}
|
||||
|
||||
// Must is a helper function to panic when the url builder returns an error
|
||||
func (o *GetMaxAllocatableMemURL) 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 *GetMaxAllocatableMemURL) String() string {
|
||||
return o.Must(o.Build()).String()
|
||||
}
|
||||
|
||||
// BuildFull builds a full url with scheme, host, path and query string
|
||||
func (o *GetMaxAllocatableMemURL) BuildFull(scheme, host string) (*url.URL, error) {
|
||||
if scheme == "" {
|
||||
return nil, errors.New("scheme is required for a full url on GetMaxAllocatableMemURL")
|
||||
}
|
||||
if host == "" {
|
||||
return nil, errors.New("host is required for a full url on GetMaxAllocatableMemURL")
|
||||
}
|
||||
|
||||
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 *GetMaxAllocatableMemURL) StringFull(scheme, host string) string {
|
||||
return o.Must(o.BuildFull(scheme, host)).String()
|
||||
}
|
||||
90
restapi/operations/admin_api/tenant_update_certificate.go
Normal file
90
restapi/operations/admin_api/tenant_update_certificate.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"
|
||||
)
|
||||
|
||||
// TenantUpdateCertificateHandlerFunc turns a function with the right signature into a tenant update certificate handler
|
||||
type TenantUpdateCertificateHandlerFunc func(TenantUpdateCertificateParams, *models.Principal) middleware.Responder
|
||||
|
||||
// Handle executing the request and returning a response
|
||||
func (fn TenantUpdateCertificateHandlerFunc) Handle(params TenantUpdateCertificateParams, principal *models.Principal) middleware.Responder {
|
||||
return fn(params, principal)
|
||||
}
|
||||
|
||||
// TenantUpdateCertificateHandler interface for that can handle valid tenant update certificate params
|
||||
type TenantUpdateCertificateHandler interface {
|
||||
Handle(TenantUpdateCertificateParams, *models.Principal) middleware.Responder
|
||||
}
|
||||
|
||||
// NewTenantUpdateCertificate creates a new http.Handler for the tenant update certificate operation
|
||||
func NewTenantUpdateCertificate(ctx *middleware.Context, handler TenantUpdateCertificateHandler) *TenantUpdateCertificate {
|
||||
return &TenantUpdateCertificate{Context: ctx, Handler: handler}
|
||||
}
|
||||
|
||||
/*TenantUpdateCertificate swagger:route PUT /namespaces/{namespace}/tenants/{tenant}/certificates AdminAPI tenantUpdateCertificate
|
||||
|
||||
Tenant Update Certificates
|
||||
|
||||
*/
|
||||
type TenantUpdateCertificate struct {
|
||||
Context *middleware.Context
|
||||
Handler TenantUpdateCertificateHandler
|
||||
}
|
||||
|
||||
func (o *TenantUpdateCertificate) ServeHTTP(rw http.ResponseWriter, r *http.Request) {
|
||||
route, rCtx, _ := o.Context.RouteInfo(r)
|
||||
if rCtx != nil {
|
||||
r = rCtx
|
||||
}
|
||||
var Params = NewTenantUpdateCertificateParams()
|
||||
|
||||
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)
|
||||
|
||||
}
|
||||
@@ -0,0 +1,145 @@
|
||||
// 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 (
|
||||
"io"
|
||||
"net/http"
|
||||
|
||||
"github.com/go-openapi/errors"
|
||||
"github.com/go-openapi/runtime"
|
||||
"github.com/go-openapi/runtime/middleware"
|
||||
"github.com/go-openapi/strfmt"
|
||||
|
||||
"github.com/minio/console/models"
|
||||
)
|
||||
|
||||
// NewTenantUpdateCertificateParams creates a new TenantUpdateCertificateParams object
|
||||
// no default values defined in spec.
|
||||
func NewTenantUpdateCertificateParams() TenantUpdateCertificateParams {
|
||||
|
||||
return TenantUpdateCertificateParams{}
|
||||
}
|
||||
|
||||
// TenantUpdateCertificateParams contains all the bound params for the tenant update certificate operation
|
||||
// typically these are obtained from a http.Request
|
||||
//
|
||||
// swagger:parameters TenantUpdateCertificate
|
||||
type TenantUpdateCertificateParams struct {
|
||||
|
||||
// HTTP Request Object
|
||||
HTTPRequest *http.Request `json:"-"`
|
||||
|
||||
/*
|
||||
Required: true
|
||||
In: body
|
||||
*/
|
||||
Body *models.TLSConfiguration
|
||||
/*
|
||||
Required: true
|
||||
In: path
|
||||
*/
|
||||
Namespace string
|
||||
/*
|
||||
Required: true
|
||||
In: path
|
||||
*/
|
||||
Tenant string
|
||||
}
|
||||
|
||||
// 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 NewTenantUpdateCertificateParams() beforehand.
|
||||
func (o *TenantUpdateCertificateParams) BindRequest(r *http.Request, route *middleware.MatchedRoute) error {
|
||||
var res []error
|
||||
|
||||
o.HTTPRequest = r
|
||||
|
||||
if runtime.HasBody(r) {
|
||||
defer r.Body.Close()
|
||||
var body models.TLSConfiguration
|
||||
if err := route.Consumer.Consume(r.Body, &body); err != nil {
|
||||
if err == io.EOF {
|
||||
res = append(res, errors.Required("body", "body", ""))
|
||||
} else {
|
||||
res = append(res, errors.NewParseError("body", "body", "", err))
|
||||
}
|
||||
} else {
|
||||
// validate body object
|
||||
if err := body.Validate(route.Formats); err != nil {
|
||||
res = append(res, err)
|
||||
}
|
||||
|
||||
if len(res) == 0 {
|
||||
o.Body = &body
|
||||
}
|
||||
}
|
||||
} else {
|
||||
res = append(res, errors.Required("body", "body", ""))
|
||||
}
|
||||
rNamespace, rhkNamespace, _ := route.Params.GetOK("namespace")
|
||||
if err := o.bindNamespace(rNamespace, rhkNamespace, route.Formats); err != nil {
|
||||
res = append(res, err)
|
||||
}
|
||||
|
||||
rTenant, rhkTenant, _ := route.Params.GetOK("tenant")
|
||||
if err := o.bindTenant(rTenant, rhkTenant, route.Formats); err != nil {
|
||||
res = append(res, err)
|
||||
}
|
||||
|
||||
if len(res) > 0 {
|
||||
return errors.CompositeValidationError(res...)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// bindNamespace binds and validates parameter Namespace from path.
|
||||
func (o *TenantUpdateCertificateParams) bindNamespace(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
|
||||
|
||||
o.Namespace = raw
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// bindTenant binds and validates parameter Tenant from path.
|
||||
func (o *TenantUpdateCertificateParams) bindTenant(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
|
||||
|
||||
o.Tenant = raw
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
// 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"
|
||||
)
|
||||
|
||||
// TenantUpdateCertificateCreatedCode is the HTTP code returned for type TenantUpdateCertificateCreated
|
||||
const TenantUpdateCertificateCreatedCode int = 201
|
||||
|
||||
/*TenantUpdateCertificateCreated A successful response.
|
||||
|
||||
swagger:response tenantUpdateCertificateCreated
|
||||
*/
|
||||
type TenantUpdateCertificateCreated struct {
|
||||
}
|
||||
|
||||
// NewTenantUpdateCertificateCreated creates TenantUpdateCertificateCreated with default headers values
|
||||
func NewTenantUpdateCertificateCreated() *TenantUpdateCertificateCreated {
|
||||
|
||||
return &TenantUpdateCertificateCreated{}
|
||||
}
|
||||
|
||||
// WriteResponse to the client
|
||||
func (o *TenantUpdateCertificateCreated) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) {
|
||||
|
||||
rw.Header().Del(runtime.HeaderContentType) //Remove Content-Type on empty responses
|
||||
|
||||
rw.WriteHeader(201)
|
||||
}
|
||||
|
||||
/*TenantUpdateCertificateDefault Generic error response.
|
||||
|
||||
swagger:response tenantUpdateCertificateDefault
|
||||
*/
|
||||
type TenantUpdateCertificateDefault struct {
|
||||
_statusCode int
|
||||
|
||||
/*
|
||||
In: Body
|
||||
*/
|
||||
Payload *models.Error `json:"body,omitempty"`
|
||||
}
|
||||
|
||||
// NewTenantUpdateCertificateDefault creates TenantUpdateCertificateDefault with default headers values
|
||||
func NewTenantUpdateCertificateDefault(code int) *TenantUpdateCertificateDefault {
|
||||
if code <= 0 {
|
||||
code = 500
|
||||
}
|
||||
|
||||
return &TenantUpdateCertificateDefault{
|
||||
_statusCode: code,
|
||||
}
|
||||
}
|
||||
|
||||
// WithStatusCode adds the status to the tenant update certificate default response
|
||||
func (o *TenantUpdateCertificateDefault) WithStatusCode(code int) *TenantUpdateCertificateDefault {
|
||||
o._statusCode = code
|
||||
return o
|
||||
}
|
||||
|
||||
// SetStatusCode sets the status to the tenant update certificate default response
|
||||
func (o *TenantUpdateCertificateDefault) SetStatusCode(code int) {
|
||||
o._statusCode = code
|
||||
}
|
||||
|
||||
// WithPayload adds the payload to the tenant update certificate default response
|
||||
func (o *TenantUpdateCertificateDefault) WithPayload(payload *models.Error) *TenantUpdateCertificateDefault {
|
||||
o.Payload = payload
|
||||
return o
|
||||
}
|
||||
|
||||
// SetPayload sets the payload to the tenant update certificate default response
|
||||
func (o *TenantUpdateCertificateDefault) SetPayload(payload *models.Error) {
|
||||
o.Payload = payload
|
||||
}
|
||||
|
||||
// WriteResponse to the client
|
||||
func (o *TenantUpdateCertificateDefault) 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
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,124 @@
|
||||
// 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"
|
||||
)
|
||||
|
||||
// TenantUpdateCertificateURL generates an URL for the tenant update certificate operation
|
||||
type TenantUpdateCertificateURL struct {
|
||||
Namespace string
|
||||
Tenant string
|
||||
|
||||
_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 *TenantUpdateCertificateURL) WithBasePath(bp string) *TenantUpdateCertificateURL {
|
||||
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 *TenantUpdateCertificateURL) SetBasePath(bp string) {
|
||||
o._basePath = bp
|
||||
}
|
||||
|
||||
// Build a url path and query string
|
||||
func (o *TenantUpdateCertificateURL) Build() (*url.URL, error) {
|
||||
var _result url.URL
|
||||
|
||||
var _path = "/namespaces/{namespace}/tenants/{tenant}/certificates"
|
||||
|
||||
namespace := o.Namespace
|
||||
if namespace != "" {
|
||||
_path = strings.Replace(_path, "{namespace}", namespace, -1)
|
||||
} else {
|
||||
return nil, errors.New("namespace is required on TenantUpdateCertificateURL")
|
||||
}
|
||||
|
||||
tenant := o.Tenant
|
||||
if tenant != "" {
|
||||
_path = strings.Replace(_path, "{tenant}", tenant, -1)
|
||||
} else {
|
||||
return nil, errors.New("tenant is required on TenantUpdateCertificateURL")
|
||||
}
|
||||
|
||||
_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 *TenantUpdateCertificateURL) 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 *TenantUpdateCertificateURL) String() string {
|
||||
return o.Must(o.Build()).String()
|
||||
}
|
||||
|
||||
// BuildFull builds a full url with scheme, host, path and query string
|
||||
func (o *TenantUpdateCertificateURL) BuildFull(scheme, host string) (*url.URL, error) {
|
||||
if scheme == "" {
|
||||
return nil, errors.New("scheme is required for a full url on TenantUpdateCertificateURL")
|
||||
}
|
||||
if host == "" {
|
||||
return nil, errors.New("host is required for a full url on TenantUpdateCertificateURL")
|
||||
}
|
||||
|
||||
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 *TenantUpdateCertificateURL) StringFull(scheme, host string) string {
|
||||
return o.Must(o.BuildFull(scheme, host)).String()
|
||||
}
|
||||
90
restapi/operations/admin_api/tenant_update_encryption.go
Normal file
90
restapi/operations/admin_api/tenant_update_encryption.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"
|
||||
)
|
||||
|
||||
// TenantUpdateEncryptionHandlerFunc turns a function with the right signature into a tenant update encryption handler
|
||||
type TenantUpdateEncryptionHandlerFunc func(TenantUpdateEncryptionParams, *models.Principal) middleware.Responder
|
||||
|
||||
// Handle executing the request and returning a response
|
||||
func (fn TenantUpdateEncryptionHandlerFunc) Handle(params TenantUpdateEncryptionParams, principal *models.Principal) middleware.Responder {
|
||||
return fn(params, principal)
|
||||
}
|
||||
|
||||
// TenantUpdateEncryptionHandler interface for that can handle valid tenant update encryption params
|
||||
type TenantUpdateEncryptionHandler interface {
|
||||
Handle(TenantUpdateEncryptionParams, *models.Principal) middleware.Responder
|
||||
}
|
||||
|
||||
// NewTenantUpdateEncryption creates a new http.Handler for the tenant update encryption operation
|
||||
func NewTenantUpdateEncryption(ctx *middleware.Context, handler TenantUpdateEncryptionHandler) *TenantUpdateEncryption {
|
||||
return &TenantUpdateEncryption{Context: ctx, Handler: handler}
|
||||
}
|
||||
|
||||
/*TenantUpdateEncryption swagger:route PUT /namespaces/{namespace}/tenants/{tenant}/encryption AdminAPI tenantUpdateEncryption
|
||||
|
||||
Tenant Update Encryption
|
||||
|
||||
*/
|
||||
type TenantUpdateEncryption struct {
|
||||
Context *middleware.Context
|
||||
Handler TenantUpdateEncryptionHandler
|
||||
}
|
||||
|
||||
func (o *TenantUpdateEncryption) ServeHTTP(rw http.ResponseWriter, r *http.Request) {
|
||||
route, rCtx, _ := o.Context.RouteInfo(r)
|
||||
if rCtx != nil {
|
||||
r = rCtx
|
||||
}
|
||||
var Params = NewTenantUpdateEncryptionParams()
|
||||
|
||||
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)
|
||||
|
||||
}
|
||||
@@ -0,0 +1,145 @@
|
||||
// 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 (
|
||||
"io"
|
||||
"net/http"
|
||||
|
||||
"github.com/go-openapi/errors"
|
||||
"github.com/go-openapi/runtime"
|
||||
"github.com/go-openapi/runtime/middleware"
|
||||
"github.com/go-openapi/strfmt"
|
||||
|
||||
"github.com/minio/console/models"
|
||||
)
|
||||
|
||||
// NewTenantUpdateEncryptionParams creates a new TenantUpdateEncryptionParams object
|
||||
// no default values defined in spec.
|
||||
func NewTenantUpdateEncryptionParams() TenantUpdateEncryptionParams {
|
||||
|
||||
return TenantUpdateEncryptionParams{}
|
||||
}
|
||||
|
||||
// TenantUpdateEncryptionParams contains all the bound params for the tenant update encryption operation
|
||||
// typically these are obtained from a http.Request
|
||||
//
|
||||
// swagger:parameters TenantUpdateEncryption
|
||||
type TenantUpdateEncryptionParams struct {
|
||||
|
||||
// HTTP Request Object
|
||||
HTTPRequest *http.Request `json:"-"`
|
||||
|
||||
/*
|
||||
Required: true
|
||||
In: body
|
||||
*/
|
||||
Body *models.EncryptionConfiguration
|
||||
/*
|
||||
Required: true
|
||||
In: path
|
||||
*/
|
||||
Namespace string
|
||||
/*
|
||||
Required: true
|
||||
In: path
|
||||
*/
|
||||
Tenant string
|
||||
}
|
||||
|
||||
// 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 NewTenantUpdateEncryptionParams() beforehand.
|
||||
func (o *TenantUpdateEncryptionParams) BindRequest(r *http.Request, route *middleware.MatchedRoute) error {
|
||||
var res []error
|
||||
|
||||
o.HTTPRequest = r
|
||||
|
||||
if runtime.HasBody(r) {
|
||||
defer r.Body.Close()
|
||||
var body models.EncryptionConfiguration
|
||||
if err := route.Consumer.Consume(r.Body, &body); err != nil {
|
||||
if err == io.EOF {
|
||||
res = append(res, errors.Required("body", "body", ""))
|
||||
} else {
|
||||
res = append(res, errors.NewParseError("body", "body", "", err))
|
||||
}
|
||||
} else {
|
||||
// validate body object
|
||||
if err := body.Validate(route.Formats); err != nil {
|
||||
res = append(res, err)
|
||||
}
|
||||
|
||||
if len(res) == 0 {
|
||||
o.Body = &body
|
||||
}
|
||||
}
|
||||
} else {
|
||||
res = append(res, errors.Required("body", "body", ""))
|
||||
}
|
||||
rNamespace, rhkNamespace, _ := route.Params.GetOK("namespace")
|
||||
if err := o.bindNamespace(rNamespace, rhkNamespace, route.Formats); err != nil {
|
||||
res = append(res, err)
|
||||
}
|
||||
|
||||
rTenant, rhkTenant, _ := route.Params.GetOK("tenant")
|
||||
if err := o.bindTenant(rTenant, rhkTenant, route.Formats); err != nil {
|
||||
res = append(res, err)
|
||||
}
|
||||
|
||||
if len(res) > 0 {
|
||||
return errors.CompositeValidationError(res...)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// bindNamespace binds and validates parameter Namespace from path.
|
||||
func (o *TenantUpdateEncryptionParams) bindNamespace(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
|
||||
|
||||
o.Namespace = raw
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// bindTenant binds and validates parameter Tenant from path.
|
||||
func (o *TenantUpdateEncryptionParams) bindTenant(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
|
||||
|
||||
o.Tenant = raw
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
// 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"
|
||||
)
|
||||
|
||||
// TenantUpdateEncryptionCreatedCode is the HTTP code returned for type TenantUpdateEncryptionCreated
|
||||
const TenantUpdateEncryptionCreatedCode int = 201
|
||||
|
||||
/*TenantUpdateEncryptionCreated A successful response.
|
||||
|
||||
swagger:response tenantUpdateEncryptionCreated
|
||||
*/
|
||||
type TenantUpdateEncryptionCreated struct {
|
||||
}
|
||||
|
||||
// NewTenantUpdateEncryptionCreated creates TenantUpdateEncryptionCreated with default headers values
|
||||
func NewTenantUpdateEncryptionCreated() *TenantUpdateEncryptionCreated {
|
||||
|
||||
return &TenantUpdateEncryptionCreated{}
|
||||
}
|
||||
|
||||
// WriteResponse to the client
|
||||
func (o *TenantUpdateEncryptionCreated) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) {
|
||||
|
||||
rw.Header().Del(runtime.HeaderContentType) //Remove Content-Type on empty responses
|
||||
|
||||
rw.WriteHeader(201)
|
||||
}
|
||||
|
||||
/*TenantUpdateEncryptionDefault Generic error response.
|
||||
|
||||
swagger:response tenantUpdateEncryptionDefault
|
||||
*/
|
||||
type TenantUpdateEncryptionDefault struct {
|
||||
_statusCode int
|
||||
|
||||
/*
|
||||
In: Body
|
||||
*/
|
||||
Payload *models.Error `json:"body,omitempty"`
|
||||
}
|
||||
|
||||
// NewTenantUpdateEncryptionDefault creates TenantUpdateEncryptionDefault with default headers values
|
||||
func NewTenantUpdateEncryptionDefault(code int) *TenantUpdateEncryptionDefault {
|
||||
if code <= 0 {
|
||||
code = 500
|
||||
}
|
||||
|
||||
return &TenantUpdateEncryptionDefault{
|
||||
_statusCode: code,
|
||||
}
|
||||
}
|
||||
|
||||
// WithStatusCode adds the status to the tenant update encryption default response
|
||||
func (o *TenantUpdateEncryptionDefault) WithStatusCode(code int) *TenantUpdateEncryptionDefault {
|
||||
o._statusCode = code
|
||||
return o
|
||||
}
|
||||
|
||||
// SetStatusCode sets the status to the tenant update encryption default response
|
||||
func (o *TenantUpdateEncryptionDefault) SetStatusCode(code int) {
|
||||
o._statusCode = code
|
||||
}
|
||||
|
||||
// WithPayload adds the payload to the tenant update encryption default response
|
||||
func (o *TenantUpdateEncryptionDefault) WithPayload(payload *models.Error) *TenantUpdateEncryptionDefault {
|
||||
o.Payload = payload
|
||||
return o
|
||||
}
|
||||
|
||||
// SetPayload sets the payload to the tenant update encryption default response
|
||||
func (o *TenantUpdateEncryptionDefault) SetPayload(payload *models.Error) {
|
||||
o.Payload = payload
|
||||
}
|
||||
|
||||
// WriteResponse to the client
|
||||
func (o *TenantUpdateEncryptionDefault) 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
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,124 @@
|
||||
// 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"
|
||||
)
|
||||
|
||||
// TenantUpdateEncryptionURL generates an URL for the tenant update encryption operation
|
||||
type TenantUpdateEncryptionURL struct {
|
||||
Namespace string
|
||||
Tenant string
|
||||
|
||||
_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 *TenantUpdateEncryptionURL) WithBasePath(bp string) *TenantUpdateEncryptionURL {
|
||||
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 *TenantUpdateEncryptionURL) SetBasePath(bp string) {
|
||||
o._basePath = bp
|
||||
}
|
||||
|
||||
// Build a url path and query string
|
||||
func (o *TenantUpdateEncryptionURL) Build() (*url.URL, error) {
|
||||
var _result url.URL
|
||||
|
||||
var _path = "/namespaces/{namespace}/tenants/{tenant}/encryption"
|
||||
|
||||
namespace := o.Namespace
|
||||
if namespace != "" {
|
||||
_path = strings.Replace(_path, "{namespace}", namespace, -1)
|
||||
} else {
|
||||
return nil, errors.New("namespace is required on TenantUpdateEncryptionURL")
|
||||
}
|
||||
|
||||
tenant := o.Tenant
|
||||
if tenant != "" {
|
||||
_path = strings.Replace(_path, "{tenant}", tenant, -1)
|
||||
} else {
|
||||
return nil, errors.New("tenant is required on TenantUpdateEncryptionURL")
|
||||
}
|
||||
|
||||
_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 *TenantUpdateEncryptionURL) 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 *TenantUpdateEncryptionURL) String() string {
|
||||
return o.Must(o.Build()).String()
|
||||
}
|
||||
|
||||
// BuildFull builds a full url with scheme, host, path and query string
|
||||
func (o *TenantUpdateEncryptionURL) BuildFull(scheme, host string) (*url.URL, error) {
|
||||
if scheme == "" {
|
||||
return nil, errors.New("scheme is required for a full url on TenantUpdateEncryptionURL")
|
||||
}
|
||||
if host == "" {
|
||||
return nil, errors.New("host is required for a full url on TenantUpdateEncryptionURL")
|
||||
}
|
||||
|
||||
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 *TenantUpdateEncryptionURL) StringFull(scheme, host string) string {
|
||||
return o.Must(o.BuildFull(scheme, host)).String()
|
||||
}
|
||||
90
restapi/operations/admin_api/tenant_update_zones.go
Normal file
90
restapi/operations/admin_api/tenant_update_zones.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"
|
||||
)
|
||||
|
||||
// TenantUpdateZonesHandlerFunc turns a function with the right signature into a tenant update zones handler
|
||||
type TenantUpdateZonesHandlerFunc func(TenantUpdateZonesParams, *models.Principal) middleware.Responder
|
||||
|
||||
// Handle executing the request and returning a response
|
||||
func (fn TenantUpdateZonesHandlerFunc) Handle(params TenantUpdateZonesParams, principal *models.Principal) middleware.Responder {
|
||||
return fn(params, principal)
|
||||
}
|
||||
|
||||
// TenantUpdateZonesHandler interface for that can handle valid tenant update zones params
|
||||
type TenantUpdateZonesHandler interface {
|
||||
Handle(TenantUpdateZonesParams, *models.Principal) middleware.Responder
|
||||
}
|
||||
|
||||
// NewTenantUpdateZones creates a new http.Handler for the tenant update zones operation
|
||||
func NewTenantUpdateZones(ctx *middleware.Context, handler TenantUpdateZonesHandler) *TenantUpdateZones {
|
||||
return &TenantUpdateZones{Context: ctx, Handler: handler}
|
||||
}
|
||||
|
||||
/*TenantUpdateZones swagger:route PUT /namespaces/{namespace}/tenants/{tenant}/zones AdminAPI tenantUpdateZones
|
||||
|
||||
Tenant Update Zones
|
||||
|
||||
*/
|
||||
type TenantUpdateZones struct {
|
||||
Context *middleware.Context
|
||||
Handler TenantUpdateZonesHandler
|
||||
}
|
||||
|
||||
func (o *TenantUpdateZones) ServeHTTP(rw http.ResponseWriter, r *http.Request) {
|
||||
route, rCtx, _ := o.Context.RouteInfo(r)
|
||||
if rCtx != nil {
|
||||
r = rCtx
|
||||
}
|
||||
var Params = NewTenantUpdateZonesParams()
|
||||
|
||||
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)
|
||||
|
||||
}
|
||||
145
restapi/operations/admin_api/tenant_update_zones_parameters.go
Normal file
145
restapi/operations/admin_api/tenant_update_zones_parameters.go
Normal file
@@ -0,0 +1,145 @@
|
||||
// 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 (
|
||||
"io"
|
||||
"net/http"
|
||||
|
||||
"github.com/go-openapi/errors"
|
||||
"github.com/go-openapi/runtime"
|
||||
"github.com/go-openapi/runtime/middleware"
|
||||
"github.com/go-openapi/strfmt"
|
||||
|
||||
"github.com/minio/console/models"
|
||||
)
|
||||
|
||||
// NewTenantUpdateZonesParams creates a new TenantUpdateZonesParams object
|
||||
// no default values defined in spec.
|
||||
func NewTenantUpdateZonesParams() TenantUpdateZonesParams {
|
||||
|
||||
return TenantUpdateZonesParams{}
|
||||
}
|
||||
|
||||
// TenantUpdateZonesParams contains all the bound params for the tenant update zones operation
|
||||
// typically these are obtained from a http.Request
|
||||
//
|
||||
// swagger:parameters TenantUpdateZones
|
||||
type TenantUpdateZonesParams struct {
|
||||
|
||||
// HTTP Request Object
|
||||
HTTPRequest *http.Request `json:"-"`
|
||||
|
||||
/*
|
||||
Required: true
|
||||
In: body
|
||||
*/
|
||||
Body *models.ZoneUpdateRequest
|
||||
/*
|
||||
Required: true
|
||||
In: path
|
||||
*/
|
||||
Namespace string
|
||||
/*
|
||||
Required: true
|
||||
In: path
|
||||
*/
|
||||
Tenant string
|
||||
}
|
||||
|
||||
// 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 NewTenantUpdateZonesParams() beforehand.
|
||||
func (o *TenantUpdateZonesParams) BindRequest(r *http.Request, route *middleware.MatchedRoute) error {
|
||||
var res []error
|
||||
|
||||
o.HTTPRequest = r
|
||||
|
||||
if runtime.HasBody(r) {
|
||||
defer r.Body.Close()
|
||||
var body models.ZoneUpdateRequest
|
||||
if err := route.Consumer.Consume(r.Body, &body); err != nil {
|
||||
if err == io.EOF {
|
||||
res = append(res, errors.Required("body", "body", ""))
|
||||
} else {
|
||||
res = append(res, errors.NewParseError("body", "body", "", err))
|
||||
}
|
||||
} else {
|
||||
// validate body object
|
||||
if err := body.Validate(route.Formats); err != nil {
|
||||
res = append(res, err)
|
||||
}
|
||||
|
||||
if len(res) == 0 {
|
||||
o.Body = &body
|
||||
}
|
||||
}
|
||||
} else {
|
||||
res = append(res, errors.Required("body", "body", ""))
|
||||
}
|
||||
rNamespace, rhkNamespace, _ := route.Params.GetOK("namespace")
|
||||
if err := o.bindNamespace(rNamespace, rhkNamespace, route.Formats); err != nil {
|
||||
res = append(res, err)
|
||||
}
|
||||
|
||||
rTenant, rhkTenant, _ := route.Params.GetOK("tenant")
|
||||
if err := o.bindTenant(rTenant, rhkTenant, route.Formats); err != nil {
|
||||
res = append(res, err)
|
||||
}
|
||||
|
||||
if len(res) > 0 {
|
||||
return errors.CompositeValidationError(res...)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// bindNamespace binds and validates parameter Namespace from path.
|
||||
func (o *TenantUpdateZonesParams) bindNamespace(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
|
||||
|
||||
o.Namespace = raw
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// bindTenant binds and validates parameter Tenant from path.
|
||||
func (o *TenantUpdateZonesParams) bindTenant(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
|
||||
|
||||
o.Tenant = raw
|
||||
|
||||
return nil
|
||||
}
|
||||
133
restapi/operations/admin_api/tenant_update_zones_responses.go
Normal file
133
restapi/operations/admin_api/tenant_update_zones_responses.go
Normal file
@@ -0,0 +1,133 @@
|
||||
// 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"
|
||||
)
|
||||
|
||||
// TenantUpdateZonesOKCode is the HTTP code returned for type TenantUpdateZonesOK
|
||||
const TenantUpdateZonesOKCode int = 200
|
||||
|
||||
/*TenantUpdateZonesOK A successful response.
|
||||
|
||||
swagger:response tenantUpdateZonesOK
|
||||
*/
|
||||
type TenantUpdateZonesOK struct {
|
||||
|
||||
/*
|
||||
In: Body
|
||||
*/
|
||||
Payload *models.Tenant `json:"body,omitempty"`
|
||||
}
|
||||
|
||||
// NewTenantUpdateZonesOK creates TenantUpdateZonesOK with default headers values
|
||||
func NewTenantUpdateZonesOK() *TenantUpdateZonesOK {
|
||||
|
||||
return &TenantUpdateZonesOK{}
|
||||
}
|
||||
|
||||
// WithPayload adds the payload to the tenant update zones o k response
|
||||
func (o *TenantUpdateZonesOK) WithPayload(payload *models.Tenant) *TenantUpdateZonesOK {
|
||||
o.Payload = payload
|
||||
return o
|
||||
}
|
||||
|
||||
// SetPayload sets the payload to the tenant update zones o k response
|
||||
func (o *TenantUpdateZonesOK) SetPayload(payload *models.Tenant) {
|
||||
o.Payload = payload
|
||||
}
|
||||
|
||||
// WriteResponse to the client
|
||||
func (o *TenantUpdateZonesOK) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) {
|
||||
|
||||
rw.WriteHeader(200)
|
||||
if o.Payload != nil {
|
||||
payload := o.Payload
|
||||
if err := producer.Produce(rw, payload); err != nil {
|
||||
panic(err) // let the recovery middleware deal with this
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*TenantUpdateZonesDefault Generic error response.
|
||||
|
||||
swagger:response tenantUpdateZonesDefault
|
||||
*/
|
||||
type TenantUpdateZonesDefault struct {
|
||||
_statusCode int
|
||||
|
||||
/*
|
||||
In: Body
|
||||
*/
|
||||
Payload *models.Error `json:"body,omitempty"`
|
||||
}
|
||||
|
||||
// NewTenantUpdateZonesDefault creates TenantUpdateZonesDefault with default headers values
|
||||
func NewTenantUpdateZonesDefault(code int) *TenantUpdateZonesDefault {
|
||||
if code <= 0 {
|
||||
code = 500
|
||||
}
|
||||
|
||||
return &TenantUpdateZonesDefault{
|
||||
_statusCode: code,
|
||||
}
|
||||
}
|
||||
|
||||
// WithStatusCode adds the status to the tenant update zones default response
|
||||
func (o *TenantUpdateZonesDefault) WithStatusCode(code int) *TenantUpdateZonesDefault {
|
||||
o._statusCode = code
|
||||
return o
|
||||
}
|
||||
|
||||
// SetStatusCode sets the status to the tenant update zones default response
|
||||
func (o *TenantUpdateZonesDefault) SetStatusCode(code int) {
|
||||
o._statusCode = code
|
||||
}
|
||||
|
||||
// WithPayload adds the payload to the tenant update zones default response
|
||||
func (o *TenantUpdateZonesDefault) WithPayload(payload *models.Error) *TenantUpdateZonesDefault {
|
||||
o.Payload = payload
|
||||
return o
|
||||
}
|
||||
|
||||
// SetPayload sets the payload to the tenant update zones default response
|
||||
func (o *TenantUpdateZonesDefault) SetPayload(payload *models.Error) {
|
||||
o.Payload = payload
|
||||
}
|
||||
|
||||
// WriteResponse to the client
|
||||
func (o *TenantUpdateZonesDefault) 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
|
||||
}
|
||||
}
|
||||
}
|
||||
124
restapi/operations/admin_api/tenant_update_zones_urlbuilder.go
Normal file
124
restapi/operations/admin_api/tenant_update_zones_urlbuilder.go
Normal file
@@ -0,0 +1,124 @@
|
||||
// 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"
|
||||
)
|
||||
|
||||
// TenantUpdateZonesURL generates an URL for the tenant update zones operation
|
||||
type TenantUpdateZonesURL struct {
|
||||
Namespace string
|
||||
Tenant string
|
||||
|
||||
_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 *TenantUpdateZonesURL) WithBasePath(bp string) *TenantUpdateZonesURL {
|
||||
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 *TenantUpdateZonesURL) SetBasePath(bp string) {
|
||||
o._basePath = bp
|
||||
}
|
||||
|
||||
// Build a url path and query string
|
||||
func (o *TenantUpdateZonesURL) Build() (*url.URL, error) {
|
||||
var _result url.URL
|
||||
|
||||
var _path = "/namespaces/{namespace}/tenants/{tenant}/zones"
|
||||
|
||||
namespace := o.Namespace
|
||||
if namespace != "" {
|
||||
_path = strings.Replace(_path, "{namespace}", namespace, -1)
|
||||
} else {
|
||||
return nil, errors.New("namespace is required on TenantUpdateZonesURL")
|
||||
}
|
||||
|
||||
tenant := o.Tenant
|
||||
if tenant != "" {
|
||||
_path = strings.Replace(_path, "{tenant}", tenant, -1)
|
||||
} else {
|
||||
return nil, errors.New("tenant is required on TenantUpdateZonesURL")
|
||||
}
|
||||
|
||||
_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 *TenantUpdateZonesURL) 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 *TenantUpdateZonesURL) String() string {
|
||||
return o.Must(o.Build()).String()
|
||||
}
|
||||
|
||||
// BuildFull builds a full url with scheme, host, path and query string
|
||||
func (o *TenantUpdateZonesURL) BuildFull(scheme, host string) (*url.URL, error) {
|
||||
if scheme == "" {
|
||||
return nil, errors.New("scheme is required for a full url on TenantUpdateZonesURL")
|
||||
}
|
||||
if host == "" {
|
||||
return nil, errors.New("host is required for a full url on TenantUpdateZonesURL")
|
||||
}
|
||||
|
||||
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 *TenantUpdateZonesURL) StringFull(scheme, host string) string {
|
||||
return o.Must(o.BuildFull(scheme, host)).String()
|
||||
}
|
||||
@@ -114,6 +114,9 @@ func NewConsoleAPI(spec *loads.Document) *ConsoleAPI {
|
||||
AdminAPIDeleteTenantHandler: admin_api.DeleteTenantHandlerFunc(func(params admin_api.DeleteTenantParams, principal *models.Principal) middleware.Responder {
|
||||
return middleware.NotImplemented("operation admin_api.DeleteTenant has not yet been implemented")
|
||||
}),
|
||||
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")
|
||||
}),
|
||||
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")
|
||||
}),
|
||||
@@ -210,6 +213,15 @@ func NewConsoleAPI(spec *loads.Document) *ConsoleAPI {
|
||||
AdminAPITenantInfoHandler: admin_api.TenantInfoHandlerFunc(func(params admin_api.TenantInfoParams, principal *models.Principal) middleware.Responder {
|
||||
return middleware.NotImplemented("operation admin_api.TenantInfo has not yet been implemented")
|
||||
}),
|
||||
AdminAPITenantUpdateCertificateHandler: admin_api.TenantUpdateCertificateHandlerFunc(func(params admin_api.TenantUpdateCertificateParams, principal *models.Principal) middleware.Responder {
|
||||
return middleware.NotImplemented("operation admin_api.TenantUpdateCertificate has not yet been implemented")
|
||||
}),
|
||||
AdminAPITenantUpdateEncryptionHandler: admin_api.TenantUpdateEncryptionHandlerFunc(func(params admin_api.TenantUpdateEncryptionParams, principal *models.Principal) middleware.Responder {
|
||||
return middleware.NotImplemented("operation admin_api.TenantUpdateEncryption has not yet been implemented")
|
||||
}),
|
||||
AdminAPITenantUpdateZonesHandler: admin_api.TenantUpdateZonesHandlerFunc(func(params admin_api.TenantUpdateZonesParams, principal *models.Principal) middleware.Responder {
|
||||
return middleware.NotImplemented("operation admin_api.TenantUpdateZones has not yet been implemented")
|
||||
}),
|
||||
AdminAPIUpdateGroupHandler: admin_api.UpdateGroupHandlerFunc(func(params admin_api.UpdateGroupParams, principal *models.Principal) middleware.Responder {
|
||||
return middleware.NotImplemented("operation admin_api.UpdateGroup has not yet been implemented")
|
||||
}),
|
||||
@@ -305,6 +317,8 @@ type ConsoleAPI struct {
|
||||
UserAPIDeleteServiceAccountHandler user_api.DeleteServiceAccountHandler
|
||||
// AdminAPIDeleteTenantHandler sets the operation handler for the delete tenant operation
|
||||
AdminAPIDeleteTenantHandler admin_api.DeleteTenantHandler
|
||||
// AdminAPIGetMaxAllocatableMemHandler sets the operation handler for the get max allocatable mem operation
|
||||
AdminAPIGetMaxAllocatableMemHandler admin_api.GetMaxAllocatableMemHandler
|
||||
// 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
|
||||
@@ -369,6 +383,12 @@ type ConsoleAPI struct {
|
||||
AdminAPITenantAddZoneHandler admin_api.TenantAddZoneHandler
|
||||
// AdminAPITenantInfoHandler sets the operation handler for the tenant info operation
|
||||
AdminAPITenantInfoHandler admin_api.TenantInfoHandler
|
||||
// AdminAPITenantUpdateCertificateHandler sets the operation handler for the tenant update certificate operation
|
||||
AdminAPITenantUpdateCertificateHandler admin_api.TenantUpdateCertificateHandler
|
||||
// AdminAPITenantUpdateEncryptionHandler sets the operation handler for the tenant update encryption operation
|
||||
AdminAPITenantUpdateEncryptionHandler admin_api.TenantUpdateEncryptionHandler
|
||||
// AdminAPITenantUpdateZonesHandler sets the operation handler for the tenant update zones operation
|
||||
AdminAPITenantUpdateZonesHandler admin_api.TenantUpdateZonesHandler
|
||||
// AdminAPIUpdateGroupHandler sets the operation handler for the update group operation
|
||||
AdminAPIUpdateGroupHandler admin_api.UpdateGroupHandler
|
||||
// AdminAPIUpdateTenantHandler sets the operation handler for the update tenant operation
|
||||
@@ -501,6 +521,9 @@ func (o *ConsoleAPI) Validate() error {
|
||||
if o.AdminAPIDeleteTenantHandler == nil {
|
||||
unregistered = append(unregistered, "admin_api.DeleteTenantHandler")
|
||||
}
|
||||
if o.AdminAPIGetMaxAllocatableMemHandler == nil {
|
||||
unregistered = append(unregistered, "admin_api.GetMaxAllocatableMemHandler")
|
||||
}
|
||||
if o.AdminAPIGetResourceQuotaHandler == nil {
|
||||
unregistered = append(unregistered, "admin_api.GetResourceQuotaHandler")
|
||||
}
|
||||
@@ -597,6 +620,15 @@ func (o *ConsoleAPI) Validate() error {
|
||||
if o.AdminAPITenantInfoHandler == nil {
|
||||
unregistered = append(unregistered, "admin_api.TenantInfoHandler")
|
||||
}
|
||||
if o.AdminAPITenantUpdateCertificateHandler == nil {
|
||||
unregistered = append(unregistered, "admin_api.TenantUpdateCertificateHandler")
|
||||
}
|
||||
if o.AdminAPITenantUpdateEncryptionHandler == nil {
|
||||
unregistered = append(unregistered, "admin_api.TenantUpdateEncryptionHandler")
|
||||
}
|
||||
if o.AdminAPITenantUpdateZonesHandler == nil {
|
||||
unregistered = append(unregistered, "admin_api.TenantUpdateZonesHandler")
|
||||
}
|
||||
if o.AdminAPIUpdateGroupHandler == nil {
|
||||
unregistered = append(unregistered, "admin_api.UpdateGroupHandler")
|
||||
}
|
||||
@@ -780,6 +812,10 @@ func (o *ConsoleAPI) initHandlerCache() {
|
||||
if o.handlers["GET"] == nil {
|
||||
o.handlers["GET"] = make(map[string]http.Handler)
|
||||
}
|
||||
o.handlers["GET"]["/cluster/max-allocatable-memory"] = admin_api.NewGetMaxAllocatableMem(o.context, o.AdminAPIGetMaxAllocatableMemHandler)
|
||||
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)
|
||||
@@ -908,6 +944,18 @@ func (o *ConsoleAPI) initHandlerCache() {
|
||||
if o.handlers["PUT"] == nil {
|
||||
o.handlers["PUT"] = make(map[string]http.Handler)
|
||||
}
|
||||
o.handlers["PUT"]["/namespaces/{namespace}/tenants/{tenant}/certificates"] = admin_api.NewTenantUpdateCertificate(o.context, o.AdminAPITenantUpdateCertificateHandler)
|
||||
if o.handlers["PUT"] == nil {
|
||||
o.handlers["PUT"] = make(map[string]http.Handler)
|
||||
}
|
||||
o.handlers["PUT"]["/namespaces/{namespace}/tenants/{tenant}/encryption"] = admin_api.NewTenantUpdateEncryption(o.context, o.AdminAPITenantUpdateEncryptionHandler)
|
||||
if o.handlers["PUT"] == nil {
|
||||
o.handlers["PUT"] = make(map[string]http.Handler)
|
||||
}
|
||||
o.handlers["PUT"]["/namespaces/{namespace}/tenants/{tenant}/zones"] = admin_api.NewTenantUpdateZones(o.context, o.AdminAPITenantUpdateZonesHandler)
|
||||
if o.handlers["PUT"] == nil {
|
||||
o.handlers["PUT"] = make(map[string]http.Handler)
|
||||
}
|
||||
o.handlers["PUT"]["/groups/{name}"] = admin_api.NewUpdateGroup(o.context, o.AdminAPIUpdateGroupHandler)
|
||||
if o.handlers["PUT"] == nil {
|
||||
o.handlers["PUT"] = make(map[string]http.Handler)
|
||||
|
||||
@@ -25,10 +25,10 @@ import (
|
||||
types "k8s.io/apimachinery/pkg/types"
|
||||
)
|
||||
|
||||
// OperatorClient interface with all functions to be implemented
|
||||
// by mock when testing, it should include all OperatorClient respective api calls
|
||||
// OperatorClientI interface with all functions to be implemented
|
||||
// by mock when testing, it should include all OperatorClientI respective api calls
|
||||
// that are used within this project.
|
||||
type OperatorClient interface {
|
||||
type OperatorClientI interface {
|
||||
TenantDelete(ctx context.Context, namespace string, instanceName string, options metav1.DeleteOptions) error
|
||||
TenantGet(ctx context.Context, namespace string, instanceName string, options metav1.GetOptions) (*v1.Tenant, error)
|
||||
TenantPatch(ctx context.Context, namespace string, instanceName string, pt types.PatchType, data []byte, options metav1.PatchOptions) (*v1.Tenant, error)
|
||||
|
||||
@@ -18,12 +18,10 @@ package restapi
|
||||
|
||||
import (
|
||||
"context"
|
||||
"log"
|
||||
|
||||
"github.com/minio/console/cluster"
|
||||
|
||||
"github.com/go-openapi/runtime/middleware"
|
||||
"github.com/go-openapi/swag"
|
||||
"github.com/minio/console/models"
|
||||
"github.com/minio/console/restapi/operations"
|
||||
"github.com/minio/console/restapi/operations/admin_api"
|
||||
@@ -35,14 +33,14 @@ func registerResourceQuotaHandlers(api *operations.ConsoleAPI) {
|
||||
api.AdminAPIGetResourceQuotaHandler = admin_api.GetResourceQuotaHandlerFunc(func(params admin_api.GetResourceQuotaParams, session *models.Principal) middleware.Responder {
|
||||
resp, err := getResourceQuotaResponse(session, params)
|
||||
if err != nil {
|
||||
return admin_api.NewGetResourceQuotaDefault(500).WithPayload(&models.Error{Code: 500, Message: swag.String(err.Error())})
|
||||
return admin_api.NewGetResourceQuotaDefault(int(err.Code)).WithPayload(err)
|
||||
}
|
||||
return admin_api.NewGetResourceQuotaOK().WithPayload(resp)
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
func getResourceQuota(ctx context.Context, client K8sClient, namespace, resourcequota string) (*models.ResourceQuota, error) {
|
||||
func getResourceQuota(ctx context.Context, client K8sClientI, namespace, resourcequota string) (*models.ResourceQuota, error) {
|
||||
resourceQuota, err := client.getResourceQuota(ctx, namespace, resourcequota, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -68,20 +66,18 @@ func getResourceQuota(ctx context.Context, client K8sClient, namespace, resource
|
||||
return &rq, nil
|
||||
}
|
||||
|
||||
func getResourceQuotaResponse(session *models.Principal, params admin_api.GetResourceQuotaParams) (*models.ResourceQuota, error) {
|
||||
func getResourceQuotaResponse(session *models.Principal, params admin_api.GetResourceQuotaParams) (*models.ResourceQuota, *models.Error) {
|
||||
ctx := context.Background()
|
||||
client, err := cluster.K8sClient(session.SessionToken)
|
||||
if err != nil {
|
||||
log.Println("error getting k8sClient:", err)
|
||||
return nil, err
|
||||
return nil, prepareError(err)
|
||||
}
|
||||
k8sClient := &k8sClient{
|
||||
client: client,
|
||||
}
|
||||
resourceQuota, err := getResourceQuota(ctx, k8sClient, params.Namespace, params.ResourceQuotaName)
|
||||
if err != nil {
|
||||
log.Println("error getting resource quota:", err)
|
||||
return nil, err
|
||||
return nil, prepareError(err)
|
||||
|
||||
}
|
||||
return resourceQuota, nil
|
||||
|
||||
@@ -48,7 +48,7 @@ func Test_ResourceQuota(t *testing.T) {
|
||||
kClient := k8sClientMock{}
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
client K8sClient
|
||||
client K8sClientI
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
|
||||
@@ -19,18 +19,37 @@ package restapi
|
||||
import (
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net"
|
||||
"net/http"
|
||||
"time"
|
||||
)
|
||||
|
||||
var (
|
||||
certDontExists = "File certificate doesn't exists: %s"
|
||||
)
|
||||
func getCertPool() *x509.CertPool {
|
||||
rootCAs, _ := x509.SystemCertPool()
|
||||
if rootCAs == nil {
|
||||
// In some systems (like Windows) system cert pool is
|
||||
// not supported or no certificates are present on the
|
||||
// system - so we create a new cert pool.
|
||||
rootCAs = x509.NewCertPool()
|
||||
}
|
||||
caCertFileNames := getMinioServerTLSRootCAs()
|
||||
for _, caCert := range caCertFileNames {
|
||||
pemData, err := ioutil.ReadFile(caCert)
|
||||
if err != nil {
|
||||
// logging this error
|
||||
log.Println(err)
|
||||
continue
|
||||
}
|
||||
rootCAs.AppendCertsFromPEM(pemData)
|
||||
}
|
||||
return rootCAs
|
||||
}
|
||||
|
||||
func prepareSTSClientTransport() *http.Transport {
|
||||
var certPool = getCertPool()
|
||||
|
||||
func prepareSTSClientTransport(insecure bool) *http.Transport {
|
||||
// This takes github.com/minio/minio/pkg/madmin/transport.go as an example
|
||||
//
|
||||
// DefaultTransport - this default transport is similar to
|
||||
@@ -49,47 +68,25 @@ func prepareSTSClientTransport() *http.Transport {
|
||||
TLSHandshakeTimeout: 10 * time.Second,
|
||||
ExpectContinueTimeout: 1 * time.Second,
|
||||
DisableCompression: true,
|
||||
}
|
||||
// If Minio instance is running with TLS enabled and it's using a self-signed certificate
|
||||
// or a certificate issued by a custom certificate authority we prepare a new custom *http.Transport
|
||||
if getMinIOEndpointIsSecure() {
|
||||
caCertFileNames := getMinioServerTLSRootCAs()
|
||||
tlsConfig := &tls.Config{
|
||||
TLSClientConfig: &tls.Config{
|
||||
// Can't use SSLv3 because of POODLE and BEAST
|
||||
// Can't use TLSv1.0 because of POODLE and BEAST using CBC cipher
|
||||
// Can't use TLSv1.1 because of RC4 cipher usage
|
||||
MinVersion: tls.VersionTLS12,
|
||||
}
|
||||
// If CAs certificates are configured we save them to the http.Client RootCAs store
|
||||
if len(caCertFileNames) > 0 {
|
||||
certs := x509.NewCertPool()
|
||||
for _, caCert := range caCertFileNames {
|
||||
// Validate certificate exists
|
||||
if FileExists(caCert) {
|
||||
pemData, err := ioutil.ReadFile(caCert)
|
||||
if err != nil {
|
||||
// if there was an error reading pem file stop console
|
||||
panic(err)
|
||||
}
|
||||
certs.AppendCertsFromPEM(pemData)
|
||||
} else {
|
||||
// if provided cert filename doesn't exists stop console
|
||||
panic(fmt.Sprintf(certDontExists, caCert))
|
||||
}
|
||||
}
|
||||
tlsConfig.RootCAs = certs
|
||||
}
|
||||
DefaultTransport.TLSClientConfig = tlsConfig
|
||||
MinVersion: tls.VersionTLS12,
|
||||
InsecureSkipVerify: insecure,
|
||||
RootCAs: certPool,
|
||||
},
|
||||
}
|
||||
return DefaultTransport
|
||||
}
|
||||
|
||||
// PrepareSTSClient returns an http.Client with custom configurations need it by *credentials.STSAssumeRole
|
||||
// custom configurations include the use of CA certificates
|
||||
func PrepareSTSClient() *http.Client {
|
||||
transport := prepareSTSClientTransport()
|
||||
func PrepareSTSClient(insecure bool) *http.Client {
|
||||
transport := prepareSTSClientTransport(insecure)
|
||||
// Return http client with default configuration
|
||||
return &http.Client{
|
||||
c := &http.Client{
|
||||
Transport: transport,
|
||||
}
|
||||
return c
|
||||
}
|
||||
|
||||
@@ -20,11 +20,9 @@ import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"log"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/go-openapi/errors"
|
||||
"github.com/go-openapi/runtime/middleware"
|
||||
"github.com/go-openapi/swag"
|
||||
"github.com/minio/console/models"
|
||||
@@ -39,21 +37,21 @@ func registerBucketsHandlers(api *operations.ConsoleAPI) {
|
||||
api.UserAPIListBucketsHandler = user_api.ListBucketsHandlerFunc(func(params user_api.ListBucketsParams, session *models.Principal) middleware.Responder {
|
||||
listBucketsResponse, err := getListBucketsResponse(session)
|
||||
if err != nil {
|
||||
return user_api.NewListBucketsDefault(500).WithPayload(&models.Error{Code: 500, Message: swag.String(err.Error())})
|
||||
return user_api.NewListBucketsDefault(int(err.Code)).WithPayload(err)
|
||||
}
|
||||
return user_api.NewListBucketsOK().WithPayload(listBucketsResponse)
|
||||
})
|
||||
// make bucket
|
||||
api.UserAPIMakeBucketHandler = user_api.MakeBucketHandlerFunc(func(params user_api.MakeBucketParams, session *models.Principal) middleware.Responder {
|
||||
if err := getMakeBucketResponse(session, params.Body); err != nil {
|
||||
return user_api.NewMakeBucketDefault(500).WithPayload(&models.Error{Code: 500, Message: swag.String(err.Error())})
|
||||
return user_api.NewMakeBucketDefault(int(err.Code)).WithPayload(err)
|
||||
}
|
||||
return user_api.NewMakeBucketCreated()
|
||||
})
|
||||
// delete bucket
|
||||
api.UserAPIDeleteBucketHandler = user_api.DeleteBucketHandlerFunc(func(params user_api.DeleteBucketParams, session *models.Principal) middleware.Responder {
|
||||
if err := getDeleteBucketResponse(session, params); err != nil {
|
||||
return user_api.NewMakeBucketDefault(500).WithPayload(&models.Error{Code: 500, Message: swag.String(err.Error())})
|
||||
return user_api.NewMakeBucketDefault(int(err.Code)).WithPayload(err)
|
||||
|
||||
}
|
||||
return user_api.NewDeleteBucketNoContent()
|
||||
@@ -62,7 +60,7 @@ func registerBucketsHandlers(api *operations.ConsoleAPI) {
|
||||
api.UserAPIBucketInfoHandler = user_api.BucketInfoHandlerFunc(func(params user_api.BucketInfoParams, session *models.Principal) middleware.Responder {
|
||||
bucketInfoResp, err := getBucketInfoResponse(session, params)
|
||||
if err != nil {
|
||||
return user_api.NewBucketInfoDefault(500).WithPayload(&models.Error{Code: 500, Message: swag.String(err.Error())})
|
||||
return user_api.NewBucketInfoDefault(int(err.Code)).WithPayload(err)
|
||||
}
|
||||
|
||||
return user_api.NewBucketInfoOK().WithPayload(bucketInfoResp)
|
||||
@@ -71,7 +69,7 @@ func registerBucketsHandlers(api *operations.ConsoleAPI) {
|
||||
api.UserAPIBucketSetPolicyHandler = user_api.BucketSetPolicyHandlerFunc(func(params user_api.BucketSetPolicyParams, session *models.Principal) middleware.Responder {
|
||||
bucketSetPolicyResp, err := getBucketSetPolicyResponse(session, params.Name, params.Body)
|
||||
if err != nil {
|
||||
return user_api.NewBucketSetPolicyDefault(500).WithPayload(&models.Error{Code: 500, Message: swag.String(err.Error())})
|
||||
return user_api.NewBucketSetPolicyDefault(int(err.Code)).WithPayload(err)
|
||||
}
|
||||
return user_api.NewBucketSetPolicyOK().WithPayload(bucketSetPolicyResp)
|
||||
})
|
||||
@@ -92,22 +90,20 @@ func getaAcountUsageInfo(ctx context.Context, client MinioAdmin) ([]*models.Buck
|
||||
}
|
||||
|
||||
// getListBucketsResponse performs listBuckets() and serializes it to the handler's output
|
||||
func getListBucketsResponse(session *models.Principal) (*models.ListBucketsResponse, error) {
|
||||
func getListBucketsResponse(session *models.Principal) (*models.ListBucketsResponse, *models.Error) {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), time.Second*20)
|
||||
defer cancel()
|
||||
|
||||
mAdmin, err := newMAdminClient(session)
|
||||
if err != nil {
|
||||
log.Println("error creating Madmin Client:", err)
|
||||
return nil, err
|
||||
return nil, prepareError(err)
|
||||
}
|
||||
// create a minioClient interface implementation
|
||||
// defining the client to be used
|
||||
adminClient := adminClient{client: mAdmin}
|
||||
buckets, err := getaAcountUsageInfo(ctx, adminClient)
|
||||
if err != nil {
|
||||
log.Println("error accountingUsageInfo:", err)
|
||||
return nil, err
|
||||
return nil, prepareError(err)
|
||||
}
|
||||
|
||||
// serialize output
|
||||
@@ -128,26 +124,23 @@ func makeBucket(ctx context.Context, client MinioClient, bucketName string) erro
|
||||
}
|
||||
|
||||
// getMakeBucketResponse performs makeBucket() to create a bucket with its access policy
|
||||
func getMakeBucketResponse(session *models.Principal, br *models.MakeBucketRequest) error {
|
||||
func getMakeBucketResponse(session *models.Principal, br *models.MakeBucketRequest) *models.Error {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), time.Second*20)
|
||||
defer cancel()
|
||||
// bucket request needed to proceed
|
||||
if br == nil {
|
||||
log.Println("error bucket body not in request")
|
||||
return errors.New(500, "error bucket body not in request")
|
||||
return prepareError(errBucketBodyNotInRequest)
|
||||
}
|
||||
mClient, err := newMinioClient(session)
|
||||
if err != nil {
|
||||
log.Println("error creating MinIO Client:", err)
|
||||
return err
|
||||
return prepareError(err)
|
||||
}
|
||||
// create a minioClient interface implementation
|
||||
// defining the client to be used
|
||||
minioClient := minioClient{client: mClient}
|
||||
|
||||
if err := makeBucket(ctx, minioClient, *br.Name); err != nil {
|
||||
log.Println("error making bucket:", err)
|
||||
return err
|
||||
return prepareError(err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -182,14 +175,13 @@ func setBucketAccessPolicy(ctx context.Context, client MinioClient, bucketName s
|
||||
|
||||
// getBucketSetPolicyResponse calls setBucketAccessPolicy() to set a access policy to a bucket
|
||||
// and returns the serialized output.
|
||||
func getBucketSetPolicyResponse(session *models.Principal, bucketName string, req *models.SetBucketPolicyRequest) (*models.Bucket, error) {
|
||||
func getBucketSetPolicyResponse(session *models.Principal, bucketName string, req *models.SetBucketPolicyRequest) (*models.Bucket, *models.Error) {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), time.Second*20)
|
||||
defer cancel()
|
||||
|
||||
mClient, err := newMinioClient(session)
|
||||
if err != nil {
|
||||
log.Println("error creating MinIO Client:", err)
|
||||
return nil, err
|
||||
return nil, prepareError(err)
|
||||
}
|
||||
// create a minioClient interface implementation
|
||||
// defining the client to be used
|
||||
@@ -197,14 +189,12 @@ func getBucketSetPolicyResponse(session *models.Principal, bucketName string, re
|
||||
|
||||
// set bucket access policy
|
||||
if err := setBucketAccessPolicy(ctx, minioClient, bucketName, req.Access); err != nil {
|
||||
log.Println("error setting bucket access policy:", err)
|
||||
return nil, err
|
||||
return nil, prepareError(err)
|
||||
}
|
||||
// get updated bucket details and return it
|
||||
bucket, err := getBucketInfo(minioClient, bucketName)
|
||||
if err != nil {
|
||||
log.Println("error getting bucket's info:", err)
|
||||
return nil, err
|
||||
return nil, prepareError(err)
|
||||
}
|
||||
return bucket, nil
|
||||
}
|
||||
@@ -215,23 +205,23 @@ func removeBucket(client MinioClient, bucketName string) error {
|
||||
}
|
||||
|
||||
// getDeleteBucketResponse performs removeBucket() to delete a bucket
|
||||
func getDeleteBucketResponse(session *models.Principal, params user_api.DeleteBucketParams) error {
|
||||
func getDeleteBucketResponse(session *models.Principal, params user_api.DeleteBucketParams) *models.Error {
|
||||
if params.Name == "" {
|
||||
log.Println("error bucket name not in request")
|
||||
return errors.New(500, "error bucket name not in request")
|
||||
return prepareError(errBucketNameNotInRequest)
|
||||
}
|
||||
bucketName := params.Name
|
||||
|
||||
mClient, err := newMinioClient(session)
|
||||
if err != nil {
|
||||
log.Println("error creating MinIO Client:", err)
|
||||
return err
|
||||
return prepareError(err)
|
||||
}
|
||||
// create a minioClient interface implementation
|
||||
// defining the client to be used
|
||||
minioClient := minioClient{client: mClient}
|
||||
|
||||
return removeBucket(minioClient, bucketName)
|
||||
if err := removeBucket(minioClient, bucketName); err != nil {
|
||||
return prepareError(err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// getBucketInfo return bucket information including name, policy access, size and creation date
|
||||
@@ -264,11 +254,10 @@ func getBucketInfo(client MinioClient, bucketName string) (*models.Bucket, error
|
||||
}
|
||||
|
||||
// getBucketInfoResponse calls getBucketInfo() to get the bucket's info
|
||||
func getBucketInfoResponse(session *models.Principal, params user_api.BucketInfoParams) (*models.Bucket, error) {
|
||||
func getBucketInfoResponse(session *models.Principal, params user_api.BucketInfoParams) (*models.Bucket, *models.Error) {
|
||||
mClient, err := newMinioClient(session)
|
||||
if err != nil {
|
||||
log.Println("error creating MinIO Client:", err)
|
||||
return nil, err
|
||||
return nil, prepareError(err)
|
||||
}
|
||||
// create a minioClient interface implementation
|
||||
// defining the client to be used
|
||||
@@ -276,8 +265,7 @@ func getBucketInfoResponse(session *models.Principal, params user_api.BucketInfo
|
||||
|
||||
bucket, err := getBucketInfo(minioClient, params.Name)
|
||||
if err != nil {
|
||||
log.Println("error getting bucket's info:", err)
|
||||
return nil, err
|
||||
return nil, prepareError(err)
|
||||
}
|
||||
return bucket, nil
|
||||
|
||||
|
||||
@@ -18,7 +18,6 @@ package restapi
|
||||
|
||||
import (
|
||||
"context"
|
||||
"log"
|
||||
"strings"
|
||||
|
||||
"github.com/go-openapi/runtime/middleware"
|
||||
@@ -34,21 +33,21 @@ func registerBucketEventsHandlers(api *operations.ConsoleAPI) {
|
||||
api.UserAPIListBucketEventsHandler = user_api.ListBucketEventsHandlerFunc(func(params user_api.ListBucketEventsParams, session *models.Principal) middleware.Responder {
|
||||
listBucketEventsResponse, err := getListBucketEventsResponse(session, params)
|
||||
if err != nil {
|
||||
return user_api.NewListBucketEventsDefault(500).WithPayload(&models.Error{Code: 500, Message: swag.String(err.Error())})
|
||||
return user_api.NewListBucketEventsDefault(int(err.Code)).WithPayload(err)
|
||||
}
|
||||
return user_api.NewListBucketEventsOK().WithPayload(listBucketEventsResponse)
|
||||
})
|
||||
// create bucket event
|
||||
api.UserAPICreateBucketEventHandler = user_api.CreateBucketEventHandlerFunc(func(params user_api.CreateBucketEventParams, session *models.Principal) middleware.Responder {
|
||||
if err := getCreateBucketEventsResponse(session, params.BucketName, params.Body); err != nil {
|
||||
return user_api.NewCreateBucketEventDefault(500).WithPayload(&models.Error{Code: 500, Message: swag.String(err.Error())})
|
||||
return user_api.NewCreateBucketEventDefault(int(err.Code)).WithPayload(err)
|
||||
}
|
||||
return user_api.NewCreateBucketEventCreated()
|
||||
})
|
||||
// delete bucket event
|
||||
api.UserAPIDeleteBucketEventHandler = user_api.DeleteBucketEventHandlerFunc(func(params user_api.DeleteBucketEventParams, session *models.Principal) middleware.Responder {
|
||||
if err := getDeleteBucketEventsResponse(session, params.BucketName, params.Arn, params.Body.Events, params.Body.Prefix, params.Body.Suffix); err != nil {
|
||||
return user_api.NewDeleteBucketEventDefault(500).WithPayload(&models.Error{Code: 500, Message: swag.String(err.Error())})
|
||||
return user_api.NewDeleteBucketEventDefault(int(err.Code)).WithPayload(err)
|
||||
}
|
||||
return user_api.NewDeleteBucketEventNoContent()
|
||||
})
|
||||
@@ -125,11 +124,10 @@ func listBucketEvents(client MinioClient, bucketName string) ([]*models.Notifica
|
||||
}
|
||||
|
||||
// getListBucketsResponse performs listBucketEvents() and serializes it to the handler's output
|
||||
func getListBucketEventsResponse(session *models.Principal, params user_api.ListBucketEventsParams) (*models.ListBucketEventsResponse, error) {
|
||||
func getListBucketEventsResponse(session *models.Principal, params user_api.ListBucketEventsParams) (*models.ListBucketEventsResponse, *models.Error) {
|
||||
mClient, err := newMinioClient(session)
|
||||
if err != nil {
|
||||
log.Println("error creating MinIO Client:", err)
|
||||
return nil, err
|
||||
return nil, prepareError(err)
|
||||
}
|
||||
// create a minioClient interface implementation
|
||||
// defining the client to be used
|
||||
@@ -137,8 +135,7 @@ func getListBucketEventsResponse(session *models.Principal, params user_api.List
|
||||
|
||||
bucketEvents, err := listBucketEvents(minioClient, params.BucketName)
|
||||
if err != nil {
|
||||
log.Println("error listing bucket events:", err)
|
||||
return nil, err
|
||||
return nil, prepareError(err)
|
||||
}
|
||||
// serialize output
|
||||
listBucketsResponse := &models.ListBucketEventsResponse{
|
||||
@@ -178,20 +175,18 @@ func createBucketEvent(ctx context.Context, client MCClient, arn string, notific
|
||||
}
|
||||
|
||||
// getCreateBucketEventsResponse calls createBucketEvent to add a bucket event notification
|
||||
func getCreateBucketEventsResponse(session *models.Principal, bucketName string, eventReq *models.BucketEventRequest) error {
|
||||
func getCreateBucketEventsResponse(session *models.Principal, bucketName string, eventReq *models.BucketEventRequest) *models.Error {
|
||||
ctx := context.Background()
|
||||
s3Client, err := newS3BucketClient(session, bucketName)
|
||||
if err != nil {
|
||||
log.Println("error creating S3Client:", err)
|
||||
return err
|
||||
return prepareError(err)
|
||||
}
|
||||
// create a mc S3Client interface implementation
|
||||
// defining the client to be used
|
||||
mcClient := mcClient{client: s3Client}
|
||||
err = createBucketEvent(ctx, mcClient, *eventReq.Configuration.Arn, eventReq.Configuration.Events, eventReq.Configuration.Prefix, eventReq.Configuration.Suffix, eventReq.IgnoreExisting)
|
||||
if err != nil {
|
||||
log.Println("error creating bucket event:", err)
|
||||
return err
|
||||
return prepareError(err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -215,20 +210,18 @@ func joinNotificationEvents(events []models.NotificationEventType) string {
|
||||
}
|
||||
|
||||
// getDeleteBucketEventsResponse calls deleteBucketEventNotification() to delete a bucket event notification
|
||||
func getDeleteBucketEventsResponse(session *models.Principal, bucketName string, arn string, events []models.NotificationEventType, prefix, suffix *string) error {
|
||||
func getDeleteBucketEventsResponse(session *models.Principal, bucketName string, arn string, events []models.NotificationEventType, prefix, suffix *string) *models.Error {
|
||||
ctx := context.Background()
|
||||
s3Client, err := newS3BucketClient(session, bucketName)
|
||||
if err != nil {
|
||||
log.Println("error creating S3Client:", err)
|
||||
return err
|
||||
return prepareError(err)
|
||||
}
|
||||
// create a mc S3Client interface implementation
|
||||
// defining the client to be used
|
||||
mcClient := mcClient{client: s3Client}
|
||||
err = deleteBucketEventNotification(ctx, mcClient, arn, events, prefix, suffix)
|
||||
if err != nil {
|
||||
log.Println("error deleting bucket event:", err)
|
||||
return err
|
||||
return prepareError(err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -18,11 +18,9 @@ package restapi
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"log"
|
||||
|
||||
"github.com/go-openapi/runtime/middleware"
|
||||
"github.com/go-openapi/swag"
|
||||
"github.com/minio/console/models"
|
||||
"github.com/minio/console/pkg/acl"
|
||||
"github.com/minio/console/pkg/auth"
|
||||
@@ -32,17 +30,12 @@ import (
|
||||
"github.com/minio/console/restapi/operations/user_api"
|
||||
)
|
||||
|
||||
var (
|
||||
errorGeneric = errors.New("an error occurred, please try again")
|
||||
errInvalidCredentials = errors.New("invalid Login")
|
||||
)
|
||||
|
||||
func registerLoginHandlers(api *operations.ConsoleAPI) {
|
||||
// get login strategy
|
||||
api.UserAPILoginDetailHandler = user_api.LoginDetailHandlerFunc(func(params user_api.LoginDetailParams) middleware.Responder {
|
||||
loginDetails, err := getLoginDetailsResponse()
|
||||
if err != nil {
|
||||
return user_api.NewLoginDetailDefault(500).WithPayload(&models.Error{Code: 500, Message: swag.String(err.Error())})
|
||||
return user_api.NewLoginDetailDefault(int(err.Code)).WithPayload(err)
|
||||
}
|
||||
return user_api.NewLoginDetailOK().WithPayload(loginDetails)
|
||||
})
|
||||
@@ -50,21 +43,21 @@ func registerLoginHandlers(api *operations.ConsoleAPI) {
|
||||
api.UserAPILoginHandler = user_api.LoginHandlerFunc(func(params user_api.LoginParams) middleware.Responder {
|
||||
loginResponse, err := getLoginResponse(params.Body)
|
||||
if err != nil {
|
||||
return user_api.NewLoginDefault(401).WithPayload(&models.Error{Code: 401, Message: swag.String(err.Error())})
|
||||
return user_api.NewLoginDefault(int(err.Code)).WithPayload(err)
|
||||
}
|
||||
return user_api.NewLoginCreated().WithPayload(loginResponse)
|
||||
})
|
||||
api.UserAPILoginOauth2AuthHandler = user_api.LoginOauth2AuthHandlerFunc(func(params user_api.LoginOauth2AuthParams) middleware.Responder {
|
||||
loginResponse, err := getLoginOauth2AuthResponse(params.Body)
|
||||
if err != nil {
|
||||
return user_api.NewLoginOauth2AuthDefault(401).WithPayload(&models.Error{Code: 401, Message: swag.String(err.Error())})
|
||||
return user_api.NewLoginOauth2AuthDefault(int(err.Code)).WithPayload(err)
|
||||
}
|
||||
return user_api.NewLoginOauth2AuthCreated().WithPayload(loginResponse)
|
||||
})
|
||||
api.UserAPILoginOperatorHandler = user_api.LoginOperatorHandlerFunc(func(params user_api.LoginOperatorParams) middleware.Responder {
|
||||
loginResponse, err := getLoginOperatorResponse(params.Body)
|
||||
if err != nil {
|
||||
return user_api.NewLoginOperatorDefault(401).WithPayload(&models.Error{Code: 401, Message: swag.String(err.Error())})
|
||||
return user_api.NewLoginOperatorDefault(int(err.Code)).WithPayload(err)
|
||||
}
|
||||
return user_api.NewLoginOperatorCreated().WithPayload(loginResponse)
|
||||
})
|
||||
@@ -76,8 +69,7 @@ func login(credentials ConsoleCredentials, actions []string) (*string, error) {
|
||||
// try to obtain consoleCredentials,
|
||||
tokens, err := credentials.Get()
|
||||
if err != nil {
|
||||
log.Println("error authenticating user", err)
|
||||
return nil, errInvalidCredentials
|
||||
return nil, err
|
||||
}
|
||||
// if we made it here, the consoleCredentials work, generate a jwt with claims
|
||||
jwt, err := auth.NewEncryptedTokenForClient(&tokens, actions)
|
||||
@@ -103,32 +95,29 @@ func getConfiguredRegionForLogin(client MinioAdmin) (string, error) {
|
||||
}
|
||||
|
||||
// getLoginResponse performs login() and serializes it to the handler's output
|
||||
func getLoginResponse(lr *models.LoginRequest) (*models.LoginResponse, error) {
|
||||
func getLoginResponse(lr *models.LoginRequest) (*models.LoginResponse, *models.Error) {
|
||||
ctx := context.Background()
|
||||
mAdmin, err := newSuperMAdminClient()
|
||||
if err != nil {
|
||||
log.Println("error creating Madmin Client:", err)
|
||||
return nil, errorGeneric
|
||||
return nil, prepareError(err)
|
||||
}
|
||||
adminClient := adminClient{client: mAdmin}
|
||||
// obtain the configured MinIO region
|
||||
// need it for user authentication
|
||||
location, err := getConfiguredRegionForLogin(adminClient)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, prepareError(err)
|
||||
}
|
||||
creds, err := newConsoleCredentials(*lr.AccessKey, *lr.SecretKey, location)
|
||||
if err != nil {
|
||||
log.Println("error login:", err)
|
||||
return nil, errInvalidCredentials
|
||||
return nil, prepareError(err)
|
||||
}
|
||||
credentials := consoleCredentials{consoleCredentials: creds}
|
||||
// obtain the current policy assigned to this user
|
||||
// necessary for generating the list of allowed endpoints
|
||||
userInfo, err := adminClient.getUserInfo(ctx, *lr.AccessKey)
|
||||
if err != nil {
|
||||
log.Println("error login:", err)
|
||||
return nil, errInvalidCredentials
|
||||
return nil, prepareError(err)
|
||||
}
|
||||
policy, _ := adminClient.getPolicy(ctx, userInfo.PolicyName)
|
||||
// by default every user starts with an empty array of available actions
|
||||
@@ -141,7 +130,7 @@ func getLoginResponse(lr *models.LoginRequest) (*models.LoginResponse, error) {
|
||||
}
|
||||
sessionID, err := login(credentials, actions)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, prepareError(errInvalidCredentials, nil, err)
|
||||
}
|
||||
// serialize output
|
||||
loginResponse := &models.LoginResponse{
|
||||
@@ -151,7 +140,7 @@ func getLoginResponse(lr *models.LoginRequest) (*models.LoginResponse, error) {
|
||||
}
|
||||
|
||||
// getLoginDetailsResponse returns information regarding the Console authentication mechanism.
|
||||
func getLoginDetailsResponse() (*models.LoginDetails, error) {
|
||||
func getLoginDetailsResponse() (*models.LoginDetails, *models.Error) {
|
||||
ctx := context.Background()
|
||||
loginStrategy := models.LoginDetailsLoginStrategyForm
|
||||
redirectURL := ""
|
||||
@@ -162,8 +151,7 @@ func getLoginDetailsResponse() (*models.LoginDetails, error) {
|
||||
// initialize new oauth2 client
|
||||
oauth2Client, err := oauth2.NewOauth2ProviderClient(ctx, nil)
|
||||
if err != nil {
|
||||
log.Println("error getting new oauth2 provider client", err)
|
||||
return nil, errorGeneric
|
||||
return nil, prepareError(err)
|
||||
}
|
||||
// Validate user against IDP
|
||||
identityProvider := &auth.IdentityProvider{Client: oauth2Client}
|
||||
@@ -180,31 +168,29 @@ func loginOauth2Auth(ctx context.Context, provider *auth.IdentityProvider, code,
|
||||
userIdentity, err := provider.VerifyIdentity(ctx, code, state)
|
||||
if err != nil {
|
||||
log.Println("error validating user identity against idp:", err)
|
||||
return nil, errorGeneric
|
||||
return nil, errInvalidCredentials
|
||||
}
|
||||
return userIdentity, nil
|
||||
}
|
||||
|
||||
func getLoginOauth2AuthResponse(lr *models.LoginOauth2AuthRequest) (*models.LoginResponse, error) {
|
||||
func getLoginOauth2AuthResponse(lr *models.LoginOauth2AuthRequest) (*models.LoginResponse, *models.Error) {
|
||||
ctx := context.Background()
|
||||
if oauth2.IsIdpEnabled() {
|
||||
// initialize new oauth2 client
|
||||
oauth2Client, err := oauth2.NewOauth2ProviderClient(ctx, nil)
|
||||
if err != nil {
|
||||
log.Println("error getting new oauth2 client:", err)
|
||||
return nil, errorGeneric
|
||||
return nil, prepareError(err)
|
||||
}
|
||||
// initialize new identity provider
|
||||
identityProvider := &auth.IdentityProvider{Client: oauth2Client}
|
||||
// Validate user against IDP
|
||||
identity, err := loginOauth2Auth(ctx, identityProvider, *lr.Code, *lr.State)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, prepareError(errInvalidCredentials, nil, err)
|
||||
}
|
||||
mAdmin, err := newSuperMAdminClient()
|
||||
if err != nil {
|
||||
log.Println("error creating Madmin Client:", err)
|
||||
return nil, errorGeneric
|
||||
return nil, prepareError(err)
|
||||
}
|
||||
adminClient := adminClient{client: mAdmin}
|
||||
accessKey := identity.Email
|
||||
@@ -213,12 +199,11 @@ func getLoginOauth2AuthResponse(lr *models.LoginOauth2AuthRequest) (*models.Logi
|
||||
// need it for user authentication
|
||||
location, err := getConfiguredRegionForLogin(adminClient)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, prepareError(err)
|
||||
}
|
||||
// create user in MinIO
|
||||
if _, err := addUser(ctx, adminClient, &accessKey, &secretKey, []string{}); err != nil {
|
||||
log.Println("error adding user:", err)
|
||||
return nil, errorGeneric
|
||||
return nil, prepareError(err)
|
||||
}
|
||||
// rollback user if there's an error after this point
|
||||
defer func() {
|
||||
@@ -231,26 +216,23 @@ func getLoginOauth2AuthResponse(lr *models.LoginOauth2AuthRequest) (*models.Logi
|
||||
// assign the "consoleAdmin" policy to this user
|
||||
policyName := oauth2.GetIDPPolicyForUser()
|
||||
if err := setPolicy(ctx, adminClient, policyName, accessKey, models.PolicyEntityUser); err != nil {
|
||||
log.Println("error setting policy:", err)
|
||||
return nil, errorGeneric
|
||||
return nil, prepareError(err)
|
||||
}
|
||||
// obtain the current policy details, necessary for generating the list of allowed endpoints
|
||||
policy, err := adminClient.getPolicy(ctx, policyName)
|
||||
if err != nil {
|
||||
log.Println("error reading policy:", err)
|
||||
return nil, errorGeneric
|
||||
return nil, prepareError(err)
|
||||
}
|
||||
actions := acl.GetActionsStringFromPolicy(policy)
|
||||
// User was created correctly, create a new session/JWT
|
||||
creds, err := newConsoleCredentials(accessKey, secretKey, location)
|
||||
if err != nil {
|
||||
log.Println("error login:", err)
|
||||
return nil, errorGeneric
|
||||
return nil, prepareError(err)
|
||||
}
|
||||
credentials := consoleCredentials{consoleCredentials: creds}
|
||||
jwt, err := login(credentials, actions)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, prepareError(errInvalidCredentials, nil, err)
|
||||
}
|
||||
// serialize output
|
||||
loginResponse := &models.LoginResponse{
|
||||
@@ -258,21 +240,20 @@ func getLoginOauth2AuthResponse(lr *models.LoginOauth2AuthRequest) (*models.Logi
|
||||
}
|
||||
return loginResponse, nil
|
||||
}
|
||||
return nil, errorGeneric
|
||||
return nil, prepareError(errorGeneric)
|
||||
}
|
||||
|
||||
// getLoginOperatorResponse validate the provided service account token against k8s api
|
||||
func getLoginOperatorResponse(lmr *models.LoginOperatorRequest) (*models.LoginResponse, error) {
|
||||
func getLoginOperatorResponse(lmr *models.LoginOperatorRequest) (*models.LoginResponse, *models.Error) {
|
||||
creds, err := newConsoleCredentials("", *lmr.Jwt, "")
|
||||
if err != nil {
|
||||
log.Println("error login:", err)
|
||||
return nil, errInvalidCredentials
|
||||
return nil, prepareError(err)
|
||||
}
|
||||
credentials := consoleCredentials{consoleCredentials: creds}
|
||||
var actions []string
|
||||
jwt, err := login(credentials, actions)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, prepareError(errInvalidCredentials, nil, err)
|
||||
}
|
||||
// serialize output
|
||||
loginResponse := &models.LoginResponse{
|
||||
|
||||
@@ -100,7 +100,7 @@ func TestLoginOauth2Auth(t *testing.T) {
|
||||
return nil, errors.New("error")
|
||||
}
|
||||
if _, err := loginOauth2Auth(ctx, identityProvider, mockCode, mockState); funcAssert.Error(err) {
|
||||
funcAssert.Equal("an error occurred, please try again", err.Error())
|
||||
funcAssert.Equal(errInvalidCredentials.Error(), err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -19,12 +19,10 @@ package restapi
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"log"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/go-openapi/runtime/middleware"
|
||||
"github.com/go-openapi/swag"
|
||||
"github.com/minio/console/models"
|
||||
"github.com/minio/console/restapi/operations"
|
||||
"github.com/minio/console/restapi/operations/user_api"
|
||||
@@ -36,7 +34,7 @@ func registerServiceAccountsHandlers(api *operations.ConsoleAPI) {
|
||||
api.UserAPICreateServiceAccountHandler = user_api.CreateServiceAccountHandlerFunc(func(params user_api.CreateServiceAccountParams, session *models.Principal) middleware.Responder {
|
||||
creds, err := getCreateServiceAccountResponse(session, params.Body)
|
||||
if err != nil {
|
||||
return user_api.NewCreateServiceAccountDefault(500).WithPayload(&models.Error{Code: 500, Message: swag.String(err.Error())})
|
||||
return user_api.NewCreateServiceAccountDefault(int(err.Code)).WithPayload(err)
|
||||
}
|
||||
return user_api.NewCreateServiceAccountCreated().WithPayload(creds)
|
||||
})
|
||||
@@ -44,7 +42,7 @@ func registerServiceAccountsHandlers(api *operations.ConsoleAPI) {
|
||||
api.UserAPIListUserServiceAccountsHandler = user_api.ListUserServiceAccountsHandlerFunc(func(params user_api.ListUserServiceAccountsParams, session *models.Principal) middleware.Responder {
|
||||
serviceAccounts, err := getUserServiceAccountsResponse(session)
|
||||
if err != nil {
|
||||
return user_api.NewListUserServiceAccountsDefault(500).WithPayload(&models.Error{Code: 500, Message: swag.String(err.Error())})
|
||||
return user_api.NewListUserServiceAccountsDefault(int(err.Code)).WithPayload(err)
|
||||
}
|
||||
return user_api.NewListUserServiceAccountsOK().WithPayload(serviceAccounts)
|
||||
})
|
||||
@@ -52,7 +50,7 @@ func registerServiceAccountsHandlers(api *operations.ConsoleAPI) {
|
||||
// Delete a User's service account
|
||||
api.UserAPIDeleteServiceAccountHandler = user_api.DeleteServiceAccountHandlerFunc(func(params user_api.DeleteServiceAccountParams, session *models.Principal) middleware.Responder {
|
||||
if err := getDeleteServiceAccountResponse(session, params.AccessKey); err != nil {
|
||||
return user_api.NewDeleteServiceAccountDefault(500).WithPayload(&models.Error{Code: 500, Message: swag.String(err.Error())})
|
||||
return user_api.NewDeleteServiceAccountDefault(int(err.Code)).WithPayload(err)
|
||||
}
|
||||
return user_api.NewDeleteServiceAccountNoContent()
|
||||
})
|
||||
@@ -79,14 +77,13 @@ func createServiceAccount(ctx context.Context, userClient MinioAdmin, policy str
|
||||
// getCreateServiceAccountResponse creates a service account with the defined policy for the user that
|
||||
// is requestingit ,it first gets the credentials of the user and creates a client which is going to
|
||||
// make the call to create the Service Account
|
||||
func getCreateServiceAccountResponse(session *models.Principal, serviceAccount *models.ServiceAccountRequest) (*models.ServiceAccountCreds, error) {
|
||||
func getCreateServiceAccountResponse(session *models.Principal, serviceAccount *models.ServiceAccountRequest) (*models.ServiceAccountCreds, *models.Error) {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), time.Second*20)
|
||||
defer cancel()
|
||||
|
||||
userAdmin, err := newMAdminClient(session)
|
||||
if err != nil {
|
||||
log.Println("error creating user Client:", err)
|
||||
return nil, err
|
||||
return nil, prepareError(err)
|
||||
}
|
||||
// create a MinIO user Admin Client interface implementation
|
||||
// defining the client to be used
|
||||
@@ -94,8 +91,7 @@ func getCreateServiceAccountResponse(session *models.Principal, serviceAccount *
|
||||
|
||||
saCreds, err := createServiceAccount(ctx, userAdminClient, serviceAccount.Policy)
|
||||
if err != nil {
|
||||
log.Println("error creating service account:", err)
|
||||
return nil, err
|
||||
return nil, prepareError(err)
|
||||
}
|
||||
return saCreds, nil
|
||||
}
|
||||
@@ -115,14 +111,13 @@ func getUserServiceAccounts(ctx context.Context, userClient MinioAdmin) (models.
|
||||
|
||||
// getUserServiceAccountsResponse authenticates the user and calls
|
||||
// getUserServiceAccounts to list the user's service accounts
|
||||
func getUserServiceAccountsResponse(session *models.Principal) (models.ServiceAccounts, error) {
|
||||
func getUserServiceAccountsResponse(session *models.Principal) (models.ServiceAccounts, *models.Error) {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), time.Second*20)
|
||||
defer cancel()
|
||||
|
||||
userAdmin, err := newMAdminClient(session)
|
||||
if err != nil {
|
||||
log.Println("error creating user Client:", err)
|
||||
return nil, err
|
||||
return nil, prepareError(err)
|
||||
}
|
||||
// create a MinIO user Admin Client interface implementation
|
||||
// defining the client to be used
|
||||
@@ -130,11 +125,9 @@ func getUserServiceAccountsResponse(session *models.Principal) (models.ServiceAc
|
||||
|
||||
serviceAccounts, err := getUserServiceAccounts(ctx, userAdminClient)
|
||||
if err != nil {
|
||||
log.Println("error listing user's service account:", err)
|
||||
return nil, err
|
||||
return nil, prepareError(err)
|
||||
}
|
||||
return serviceAccounts, nil
|
||||
|
||||
}
|
||||
|
||||
// deleteServiceAccount calls delete service account api
|
||||
@@ -143,22 +136,20 @@ func deleteServiceAccount(ctx context.Context, userClient MinioAdmin, accessKey
|
||||
}
|
||||
|
||||
// getDeleteServiceAccountResponse authenticates the user and calls deleteServiceAccount
|
||||
func getDeleteServiceAccountResponse(session *models.Principal, accessKey string) error {
|
||||
func getDeleteServiceAccountResponse(session *models.Principal, accessKey string) *models.Error {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), time.Second*20)
|
||||
defer cancel()
|
||||
|
||||
userAdmin, err := newMAdminClient(session)
|
||||
if err != nil {
|
||||
log.Println("error creating user Client:", err)
|
||||
return err
|
||||
return prepareError(err)
|
||||
}
|
||||
// create a MinIO user Admin Client interface implementation
|
||||
// defining the client to be used
|
||||
userAdminClient := adminClient{client: userAdmin}
|
||||
|
||||
if err := deleteServiceAccount(ctx, userAdminClient, accessKey); err != nil {
|
||||
log.Println("error deleting user's service account:", err)
|
||||
return err
|
||||
return prepareError(err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -17,36 +17,29 @@
|
||||
package restapi
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/go-openapi/runtime/middleware"
|
||||
"github.com/go-openapi/swag"
|
||||
"github.com/minio/console/models"
|
||||
"github.com/minio/console/pkg/acl"
|
||||
"github.com/minio/console/restapi/operations"
|
||||
"github.com/minio/console/restapi/operations/user_api"
|
||||
)
|
||||
|
||||
var (
|
||||
errorGenericInvalidSession = errors.New("invalid session")
|
||||
)
|
||||
|
||||
func registerSessionHandlers(api *operations.ConsoleAPI) {
|
||||
// session check
|
||||
api.UserAPISessionCheckHandler = user_api.SessionCheckHandlerFunc(func(params user_api.SessionCheckParams, session *models.Principal) middleware.Responder {
|
||||
sessionResp, err := getSessionResponse(session)
|
||||
if err != nil {
|
||||
return user_api.NewSessionCheckDefault(401).WithPayload(&models.Error{Code: 401, Message: swag.String(err.Error())})
|
||||
return user_api.NewSessionCheckDefault(int(err.Code)).WithPayload(err)
|
||||
}
|
||||
return user_api.NewSessionCheckOK().WithPayload(sessionResp)
|
||||
})
|
||||
}
|
||||
|
||||
// getSessionResponse parse the jwt of the current session and returns a list of allowed actions to render in the UI
|
||||
func getSessionResponse(session *models.Principal) (*models.SessionResponse, error) {
|
||||
func getSessionResponse(session *models.Principal) (*models.SessionResponse, *models.Error) {
|
||||
// serialize output
|
||||
if session == nil {
|
||||
return nil, errorGenericInvalidSession
|
||||
return nil, prepareError(errorGenericInvalidSession)
|
||||
}
|
||||
sessionResp := &models.SessionResponse{
|
||||
Pages: acl.GetAuthorizedEndpoints(session.Actions),
|
||||
|
||||
235
swagger.yml
235
swagger.yml
@@ -1069,7 +1069,7 @@ paths:
|
||||
tags:
|
||||
- AdminAPI
|
||||
delete:
|
||||
summary: Delete Tenant
|
||||
summary: Delete tenant and underlying pvcs
|
||||
operationId: DeleteTenant
|
||||
parameters:
|
||||
- name: namespace
|
||||
@@ -1080,6 +1080,11 @@ paths:
|
||||
in: path
|
||||
required: true
|
||||
type: string
|
||||
- name: body
|
||||
in: body
|
||||
required: false
|
||||
schema:
|
||||
$ref: "#/definitions/deleteTenantRequest"
|
||||
responses:
|
||||
204:
|
||||
description: A successful response.
|
||||
@@ -1143,6 +1148,34 @@ paths:
|
||||
$ref: "#/definitions/error"
|
||||
tags:
|
||||
- AdminAPI
|
||||
put:
|
||||
summary: Tenant Update Zones
|
||||
operationId: TenantUpdateZones
|
||||
parameters:
|
||||
- name: namespace
|
||||
in: path
|
||||
required: true
|
||||
type: string
|
||||
- name: tenant
|
||||
in: path
|
||||
required: true
|
||||
type: string
|
||||
- name: body
|
||||
in: body
|
||||
required: true
|
||||
schema:
|
||||
$ref: "#/definitions/zoneUpdateRequest"
|
||||
responses:
|
||||
200:
|
||||
description: A successful response.
|
||||
schema:
|
||||
$ref: "#/definitions/tenant"
|
||||
default:
|
||||
description: Generic error response.
|
||||
schema:
|
||||
$ref: "#/definitions/error"
|
||||
tags:
|
||||
- AdminAPI
|
||||
|
||||
/namespaces/{namespace}/tenants/{tenant}/usage:
|
||||
get:
|
||||
@@ -1169,6 +1202,62 @@ paths:
|
||||
tags:
|
||||
- AdminAPI
|
||||
|
||||
/namespaces/{namespace}/tenants/{tenant}/certificates:
|
||||
put:
|
||||
summary: Tenant Update Certificates
|
||||
operationId: TenantUpdateCertificate
|
||||
parameters:
|
||||
- name: namespace
|
||||
in: path
|
||||
required: true
|
||||
type: string
|
||||
- name: tenant
|
||||
in: path
|
||||
required: true
|
||||
type: string
|
||||
- name: body
|
||||
in: body
|
||||
required: true
|
||||
schema:
|
||||
$ref: "#/definitions/tlsConfiguration"
|
||||
responses:
|
||||
201:
|
||||
description: A successful response.
|
||||
default:
|
||||
description: Generic error response.
|
||||
schema:
|
||||
$ref: "#/definitions/error"
|
||||
tags:
|
||||
- AdminAPI
|
||||
|
||||
/namespaces/{namespace}/tenants/{tenant}/encryption:
|
||||
put:
|
||||
summary: Tenant Update Encryption
|
||||
operationId: TenantUpdateEncryption
|
||||
parameters:
|
||||
- name: namespace
|
||||
in: path
|
||||
required: true
|
||||
type: string
|
||||
- name: tenant
|
||||
in: path
|
||||
required: true
|
||||
type: string
|
||||
- name: body
|
||||
in: body
|
||||
required: true
|
||||
schema:
|
||||
$ref: "#/definitions/encryptionConfiguration"
|
||||
responses:
|
||||
201:
|
||||
description: A successful response.
|
||||
default:
|
||||
description: Generic error response.
|
||||
schema:
|
||||
$ref: "#/definitions/error"
|
||||
tags:
|
||||
- AdminAPI
|
||||
|
||||
/namespaces/{namespace}/resourcequotas/{resource-quota-name}:
|
||||
get:
|
||||
summary: Get Resource Quota
|
||||
@@ -1193,6 +1282,29 @@ paths:
|
||||
$ref: "#/definitions/error"
|
||||
tags:
|
||||
- AdminAPI
|
||||
|
||||
/cluster/max-allocatable-memory:
|
||||
get:
|
||||
summary: Get maximum allocatable memory for given number of nodes
|
||||
operationId: GetMaxAllocatableMem
|
||||
parameters:
|
||||
- name: num_nodes
|
||||
in: query
|
||||
required: true
|
||||
type: integer
|
||||
format: int32
|
||||
minimum: 1
|
||||
responses:
|
||||
200:
|
||||
description: A successful response.
|
||||
schema:
|
||||
$ref: "#/definitions/maxAllocatableMemResponse"
|
||||
default:
|
||||
description: Generic error response.
|
||||
schema:
|
||||
$ref: "#/definitions/error"
|
||||
tags:
|
||||
- AdminAPI
|
||||
|
||||
definitions:
|
||||
bucketAccess:
|
||||
@@ -1243,7 +1355,7 @@ definitions:
|
||||
properties:
|
||||
code:
|
||||
type: integer
|
||||
format: int64
|
||||
format: int32
|
||||
message:
|
||||
type: string
|
||||
user:
|
||||
@@ -1716,6 +1828,8 @@ definitions:
|
||||
type: string
|
||||
creation_date:
|
||||
type: string
|
||||
deletion_date:
|
||||
type: string
|
||||
currentState:
|
||||
type: string
|
||||
zones:
|
||||
@@ -1724,11 +1838,15 @@ definitions:
|
||||
$ref: "#/definitions/zone"
|
||||
image:
|
||||
type: string
|
||||
console_image:
|
||||
type: string
|
||||
namespace:
|
||||
type: string
|
||||
total_size:
|
||||
type: integer
|
||||
format: int64
|
||||
enable_prometheus:
|
||||
type: boolean
|
||||
|
||||
tenantUsage:
|
||||
type: object
|
||||
@@ -1755,10 +1873,13 @@ definitions:
|
||||
type: integer
|
||||
creation_date:
|
||||
type: string
|
||||
deletion_date:
|
||||
type: string
|
||||
currentState:
|
||||
type: string
|
||||
namespace:
|
||||
type: string
|
||||
|
||||
listTenantsResponse:
|
||||
type: object
|
||||
properties:
|
||||
@@ -1778,8 +1899,15 @@ definitions:
|
||||
image:
|
||||
type: string
|
||||
pattern: "^((.*?)/(.*?):(.+))$"
|
||||
console_image:
|
||||
type: string
|
||||
pattern: "^((.*?)/(.*?):(.+))$"
|
||||
image_registry:
|
||||
$ref: "#/definitions/imageRegistry"
|
||||
image_pull_secret:
|
||||
type: string
|
||||
enable_prometheus:
|
||||
type: boolean
|
||||
|
||||
imageRegistry:
|
||||
type: object
|
||||
@@ -1807,6 +1935,8 @@ definitions:
|
||||
pattern: "^[a-z0-9-]{3,63}$"
|
||||
image:
|
||||
type: string
|
||||
console_image:
|
||||
type: string
|
||||
service_name:
|
||||
type: string
|
||||
zones:
|
||||
@@ -1822,9 +1952,12 @@ definitions:
|
||||
enable_console:
|
||||
type: boolean
|
||||
default: true
|
||||
enable_ssl:
|
||||
enable_tls:
|
||||
type: boolean
|
||||
default: true
|
||||
enable_prometheus:
|
||||
type: boolean
|
||||
default: false
|
||||
namespace:
|
||||
type: string
|
||||
erasureCodingParity:
|
||||
@@ -1835,6 +1968,8 @@ definitions:
|
||||
type: string
|
||||
image_registry:
|
||||
$ref: "#/definitions/imageRegistry"
|
||||
image_pull_secret:
|
||||
type: string
|
||||
idp:
|
||||
type: object
|
||||
$ref: "#/definitions/idpConfiguration"
|
||||
@@ -1845,7 +1980,7 @@ definitions:
|
||||
type: object
|
||||
$ref: "#/definitions/encryptionConfiguration"
|
||||
|
||||
tlsConfiguration:
|
||||
keyPairConfiguration:
|
||||
type: object
|
||||
required:
|
||||
- crt
|
||||
@@ -1856,6 +1991,16 @@ definitions:
|
||||
key:
|
||||
type: string
|
||||
|
||||
tlsConfiguration:
|
||||
type: object
|
||||
properties:
|
||||
minio:
|
||||
type: object
|
||||
$ref: "#/definitions/keyPairConfiguration"
|
||||
console:
|
||||
type: object
|
||||
$ref: "#/definitions/keyPairConfiguration"
|
||||
|
||||
idpConfiguration:
|
||||
type: object
|
||||
properties:
|
||||
@@ -1891,7 +2036,7 @@ definitions:
|
||||
type: string
|
||||
group_name_attribute:
|
||||
type: string
|
||||
skip_ssl_verification:
|
||||
skip_tls_verification:
|
||||
type: boolean
|
||||
server_insecure:
|
||||
type: boolean
|
||||
@@ -1903,26 +2048,10 @@ definitions:
|
||||
type: string
|
||||
server:
|
||||
type: object
|
||||
required:
|
||||
- crt
|
||||
- key
|
||||
properties:
|
||||
crt:
|
||||
type: string
|
||||
key:
|
||||
type: string
|
||||
$ref: "#/definitions/keyPairConfiguration"
|
||||
client:
|
||||
type: object
|
||||
required:
|
||||
- crt
|
||||
- key
|
||||
properties:
|
||||
crt:
|
||||
type: string
|
||||
key:
|
||||
type: string
|
||||
master_key:
|
||||
type: string
|
||||
$ref: "#/definitions/keyPairConfiguration"
|
||||
gemalto:
|
||||
type: object
|
||||
$ref: "#/definitions/gemaltoConfiguration"
|
||||
@@ -1968,6 +2097,15 @@ definitions:
|
||||
ping:
|
||||
type: integer
|
||||
format: int64
|
||||
tls:
|
||||
type: object
|
||||
properties:
|
||||
key:
|
||||
type: string
|
||||
crt:
|
||||
type: string
|
||||
ca:
|
||||
type: string
|
||||
|
||||
awsConfiguration:
|
||||
type: object
|
||||
@@ -2071,6 +2209,10 @@ definitions:
|
||||
type: integer
|
||||
storage_class_name:
|
||||
type: string
|
||||
labels:
|
||||
type: object
|
||||
additionalProperties:
|
||||
type: string
|
||||
resources:
|
||||
$ref: "#/definitions/zoneResources"
|
||||
node_selector:
|
||||
@@ -2113,14 +2255,7 @@ definitions:
|
||||
category.
|
||||
type: string
|
||||
tolerationSeconds:
|
||||
description: TolerationSeconds represents the period of
|
||||
time the toleration (which must be of effect NoExecute,
|
||||
otherwise this field is ignored) tolerates the taint.
|
||||
By default, it is not set, which means tolerate the taint
|
||||
forever (do not evict). Zero and negative values will
|
||||
be treated as 0 (evict immediately) by the system.
|
||||
format: int64
|
||||
type: integer
|
||||
$ref: "#/definitions/zoneTolerationSeconds"
|
||||
value:
|
||||
description: Value is the taint value the toleration matches
|
||||
to. If the operator is Exists, the value should be empty,
|
||||
@@ -2128,6 +2263,21 @@ definitions:
|
||||
type: string
|
||||
type: object
|
||||
type: array
|
||||
|
||||
zoneTolerationSeconds:
|
||||
description: TolerationSeconds represents the period of
|
||||
time the toleration (which must be of effect NoExecute,
|
||||
otherwise this field is ignored) tolerates the taint.
|
||||
By default, it is not set, which means tolerate the taint
|
||||
forever (do not evict). Zero and negative values will
|
||||
be treated as 0 (evict immediately) by the system.
|
||||
type: object
|
||||
required:
|
||||
- seconds
|
||||
properties:
|
||||
seconds:
|
||||
type: integer
|
||||
format: int64
|
||||
|
||||
zoneResources:
|
||||
description: If provided, use these requests and limit for cpu/memory
|
||||
@@ -2496,3 +2646,26 @@ definitions:
|
||||
used:
|
||||
type: integer
|
||||
format: int64
|
||||
|
||||
deleteTenantRequest:
|
||||
type: object
|
||||
properties:
|
||||
delete_pvcs:
|
||||
type: boolean
|
||||
|
||||
zoneUpdateRequest:
|
||||
type: object
|
||||
required:
|
||||
- zones
|
||||
properties:
|
||||
zones:
|
||||
type: array
|
||||
items:
|
||||
$ref: "#/definitions/zone"
|
||||
|
||||
maxAllocatableMemResponse:
|
||||
type: object
|
||||
properties:
|
||||
max_memory:
|
||||
type: integer
|
||||
format: int64
|
||||
|
||||
Reference in New Issue
Block a user