Refactor and tests for adding tenant (#2577)

This commit is contained in:
Javier Adriel
2023-01-13 13:11:40 -06:00
committed by GitHub
parent 6a88d26054
commit aa9f6f02ca
3 changed files with 393 additions and 180 deletions

View File

@@ -1542,7 +1542,7 @@ jobs:
go tool cover -func=all.out | grep total > tmp2
result=`cat tmp2 | awk 'END {print $3}'`
result=${result%\%}
threshold=62.0
threshold=63.2
echo "Result:"
echo "$result%"
if (( $(echo "$result >= $threshold" |bc -l) )); then

View File

@@ -22,18 +22,17 @@ import (
"fmt"
"github.com/dustin/go-humanize"
"github.com/minio/console/restapi"
"github.com/minio/console/operatorapi/operations/operator_api"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/resource"
"github.com/go-openapi/swag"
"github.com/minio/console/cluster"
"github.com/minio/console/models"
miniov2 "github.com/minio/operator/pkg/apis/minio.min.io/v2"
"k8s.io/apimachinery/pkg/api/resource"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
v1 "k8s.io/client-go/kubernetes/typed/core/v1"
)
@@ -56,7 +55,6 @@ func getTenantCreatedResponse(session *models.Principal, params operator_api.Cre
func createTenant(ctx context.Context, params operator_api.CreateTenantParams, clientSet K8sClientI, cv1 v1.CoreV1Interface, session *models.Principal) (response *models.CreateTenantResponse, mError *models.Error) {
tenantReq := params.Body
minioImage := getTenantMinIOImage(tenantReq.Image)
imm := true
ns := *tenantReq.Namespace
@@ -64,6 +62,11 @@ func createTenant(ctx context.Context, params operator_api.CreateTenantParams, c
tenantName := *tenantReq.Name
var users []*corev1.LocalObjectReference
// delete secrets created if an errors occurred during tenant creation,
defer func() {
deleteSecretsIfTenantCreationFails(ctx, mError, tenantName, ns, clientSet)
}()
err := createTenantCredentialsSecret(ctx, ns, tenantName, clientSet)
if err != nil {
return nil, restapi.ErrorWithContext(ctx, err)
@@ -74,11 +77,6 @@ func createTenant(ctx context.Context, params operator_api.CreateTenantParams, c
tenantConfigurationENV["MINIO_ROOT_USER"] = accessKey
tenantConfigurationENV["MINIO_ROOT_PASSWORD"] = secretKey
// delete secrets created if an errors occurred during tenant creation,
defer func() {
deleteSecretsIfTenantCreationFails(ctx, mError, tenantName, ns, clientSet)
}()
// Check the Erasure Coding Parity for validity and pass it to Tenant
if tenantReq.ErasureCodingParity > 0 {
if tenantReq.ErasureCodingParity < 2 || tenantReq.ErasureCodingParity > 8 {
@@ -115,44 +113,11 @@ func createTenant(ctx context.Context, params operator_api.CreateTenantParams, c
minInst.Spec.Users = users
case tenantReq.Idp.Oidc != nil:
tenantExternalIDPConfigured = true
// Enable IDP (OIDC) for MinIO
configurationURL := *tenantReq.Idp.Oidc.ConfigurationURL
clientID := *tenantReq.Idp.Oidc.ClientID
secretID := *tenantReq.Idp.Oidc.SecretID
claimName := *tenantReq.Idp.Oidc.ClaimName
scopes := tenantReq.Idp.Oidc.Scopes
callbackURL := tenantReq.Idp.Oidc.CallbackURL
tenantConfigurationENV["MINIO_IDENTITY_OPENID_CONFIG_URL"] = configurationURL
tenantConfigurationENV["MINIO_IDENTITY_OPENID_CLIENT_ID"] = clientID
tenantConfigurationENV["MINIO_IDENTITY_OPENID_CLIENT_SECRET"] = secretID
tenantConfigurationENV["MINIO_IDENTITY_OPENID_CLAIM_NAME"] = claimName
tenantConfigurationENV["MINIO_IDENTITY_OPENID_REDIRECT_URI"] = callbackURL
if scopes == "" {
scopes = "openid,profile,email"
}
tenantConfigurationENV["MINIO_IDENTITY_OPENID_SCOPES"] = scopes
tenantConfigurationENV = setTenantOIDCConfig(tenantReq, tenantConfigurationENV)
case len(tenantReq.Idp.Keys) > 0:
// Create the secret any built-in user passed if no external IDP was configured
for i := 0; i < len(tenantReq.Idp.Keys); i++ {
userSecretName := fmt.Sprintf("%s-user-%d", tenantName, i)
users = append(users, &corev1.LocalObjectReference{Name: userSecretName})
userSecret := corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: userSecretName,
Labels: map[string]string{
miniov2.TenantLabel: tenantName,
},
},
Immutable: &imm,
Data: map[string][]byte{
"CONSOLE_ACCESS_KEY": []byte(*tenantReq.Idp.Keys[i].AccessKey),
"CONSOLE_SECRET_KEY": []byte(*tenantReq.Idp.Keys[i].SecretKey),
},
}
_, err := clientSet.createSecret(ctx, ns, &userSecret, metav1.CreateOptions{})
if err != nil {
return nil, restapi.ErrorWithContext(ctx, err)
}
users, err = setTenantBuiltInUsers(ctx, clientSet, tenantReq, users)
if err != nil {
return nil, restapi.ErrorWithContext(ctx, err)
}
// attach the users to the tenant
minInst.Spec.Users = users
@@ -294,144 +259,18 @@ func createTenant(ctx context.Context, params operator_api.CreateTenantParams, c
// Is Log Search enabled? (present in the parameters) if so configure
if tenantReq.LogSearchConfiguration != nil {
// Default class name for Log search
diskSpaceFromAPI := int64(5) * humanize.GiByte // Default is 5Gi
logSearchImage := ""
logSearchPgImage := ""
logSearchPgInitImage := ""
var logSearchStorageClass *string // Nil means use default storage class
var logSearchSecurityContext *corev1.PodSecurityContext
var logSearchPgSecurityContext *corev1.PodSecurityContext
if tenantReq.LogSearchConfiguration.StorageSize != nil {
diskSpaceFromAPI = int64(*tenantReq.LogSearchConfiguration.StorageSize) * humanize.GiByte
minInst, err = setTenantLogSearchConfiguration(ctx, tenantReq, minInst)
if err != nil {
return nil, restapi.ErrorWithContext(ctx, err)
}
if tenantReq.LogSearchConfiguration.StorageClass != "" {
logSearchStorageClass = stringPtr(tenantReq.LogSearchConfiguration.StorageClass)
}
if tenantReq.LogSearchConfiguration.Image != "" {
logSearchImage = tenantReq.LogSearchConfiguration.Image
}
if tenantReq.LogSearchConfiguration.PostgresImage != "" {
logSearchPgImage = tenantReq.LogSearchConfiguration.PostgresImage
}
if tenantReq.LogSearchConfiguration.PostgresInitImage != "" {
logSearchPgInitImage = tenantReq.LogSearchConfiguration.PostgresInitImage
}
// if security context for logSearch is present, configure it.
if tenantReq.LogSearchConfiguration.SecurityContext != nil {
sc, err := convertModelSCToK8sSC(tenantReq.LogSearchConfiguration.SecurityContext)
if err != nil {
return nil, restapi.ErrorWithContext(ctx, err)
}
logSearchSecurityContext = sc
}
// if security context for logSearch is present, configure it.
if tenantReq.LogSearchConfiguration.PostgresSecurityContext != nil {
sc, err := convertModelSCToK8sSC(tenantReq.LogSearchConfiguration.PostgresSecurityContext)
if err != nil {
return nil, restapi.ErrorWithContext(ctx, err)
}
logSearchPgSecurityContext = sc
}
logSearchDiskSpace := resource.NewQuantity(diskSpaceFromAPI, resource.DecimalExponent)
// the audit max cap cannot be larger than disk size on the DB, else it won't trim the data
auditMaxCap := 10
if (diskSpaceFromAPI / humanize.GiByte) < int64(auditMaxCap) {
auditMaxCap = int(diskSpaceFromAPI / humanize.GiByte)
}
// default activate lgo search and prometheus
minInst.Spec.Log = &miniov2.LogConfig{
Audit: &miniov2.AuditConfig{DiskCapacityGB: swag.Int(auditMaxCap)},
Db: &miniov2.LogDbConfig{
VolumeClaimTemplate: &corev1.PersistentVolumeClaim{
ObjectMeta: metav1.ObjectMeta{
Name: tenantName + "-log",
},
Spec: corev1.PersistentVolumeClaimSpec{
AccessModes: []corev1.PersistentVolumeAccessMode{
corev1.ReadWriteOnce,
},
Resources: corev1.ResourceRequirements{
Requests: corev1.ResourceList{
corev1.ResourceStorage: *logSearchDiskSpace,
},
},
StorageClassName: logSearchStorageClass,
},
},
},
}
// set log search images if any
if logSearchImage != "" {
minInst.Spec.Log.Image = logSearchImage
}
if logSearchPgImage != "" {
minInst.Spec.Log.Db.Image = logSearchPgImage
}
if logSearchPgInitImage != "" {
minInst.Spec.Log.Db.InitImage = logSearchPgInitImage
}
if logSearchSecurityContext != nil {
minInst.Spec.Log.SecurityContext = logSearchSecurityContext
}
if logSearchPgSecurityContext != nil {
minInst.Spec.Log.Db.SecurityContext = logSearchPgSecurityContext
}
}
// Is Prometheus/Monitoring enabled? (config present in the parameters) if so configure
if tenantReq.PrometheusConfiguration != nil {
prometheusDiskSpace := 5 // Default is 5 by API
prometheusImage := "" // Default is ""
prometheusSidecardImage := "" // Default is ""
prometheusInitImage := "" // Default is ""
var prometheusStorageClass *string // Nil means default storage class
if tenantReq.PrometheusConfiguration.StorageSize != nil {
prometheusDiskSpace = int(*tenantReq.PrometheusConfiguration.StorageSize)
minInst, err = setTenantPrometheusConfig(ctx, tenantReq, minInst)
if err != nil {
return nil, restapi.ErrorWithContext(ctx, err)
}
if tenantReq.PrometheusConfiguration.StorageClass != "" {
prometheusStorageClass = stringPtr(tenantReq.PrometheusConfiguration.StorageClass)
}
if tenantReq.PrometheusConfiguration.Image != "" {
prometheusImage = tenantReq.PrometheusConfiguration.Image
}
if tenantReq.PrometheusConfiguration.SidecarImage != "" {
prometheusSidecardImage = tenantReq.PrometheusConfiguration.SidecarImage
}
if tenantReq.PrometheusConfiguration.InitImage != "" {
prometheusInitImage = tenantReq.PrometheusConfiguration.InitImage
}
minInst.Spec.Prometheus = &miniov2.PrometheusConfig{
DiskCapacityDB: swag.Int(prometheusDiskSpace),
StorageClassName: prometheusStorageClass,
}
if prometheusImage != "" {
minInst.Spec.Prometheus.Image = prometheusImage
}
if prometheusSidecardImage != "" {
minInst.Spec.Prometheus.SideCarImage = prometheusSidecardImage
}
if prometheusInitImage != "" {
minInst.Spec.Prometheus.InitImage = prometheusInitImage
}
// if security context for prometheus is present, configure it.
if tenantReq.PrometheusConfiguration != nil && tenantReq.PrometheusConfiguration.SecurityContext != nil {
sc, err := convertModelSCToK8sSC(tenantReq.PrometheusConfiguration.SecurityContext)
if err != nil {
return nil, restapi.ErrorWithContext(ctx, err)
}
minInst.Spec.Prometheus.SecurityContext = sc
}
}
// expose services
@@ -636,3 +475,186 @@ func setTenantActiveDirectoryConfig(ctx context.Context, clientSet K8sClientI, t
}
return tenantConfigurationENV, users, nil
}
func setTenantOIDCConfig(tenantReq *models.CreateTenantRequest, tenantConfigurationENV map[string]string) map[string]string {
configurationURL := *tenantReq.Idp.Oidc.ConfigurationURL
clientID := *tenantReq.Idp.Oidc.ClientID
secretID := *tenantReq.Idp.Oidc.SecretID
claimName := *tenantReq.Idp.Oidc.ClaimName
scopes := tenantReq.Idp.Oidc.Scopes
callbackURL := tenantReq.Idp.Oidc.CallbackURL
tenantConfigurationENV["MINIO_IDENTITY_OPENID_CONFIG_URL"] = configurationURL
tenantConfigurationENV["MINIO_IDENTITY_OPENID_CLIENT_ID"] = clientID
tenantConfigurationENV["MINIO_IDENTITY_OPENID_CLIENT_SECRET"] = secretID
tenantConfigurationENV["MINIO_IDENTITY_OPENID_CLAIM_NAME"] = claimName
tenantConfigurationENV["MINIO_IDENTITY_OPENID_REDIRECT_URI"] = callbackURL
if scopes == "" {
scopes = "openid,profile,email"
}
tenantConfigurationENV["MINIO_IDENTITY_OPENID_SCOPES"] = scopes
return tenantConfigurationENV
}
func setTenantBuiltInUsers(ctx context.Context, clientSet K8sClientI, tenantReq *models.CreateTenantRequest, users []*corev1.LocalObjectReference) ([]*corev1.LocalObjectReference, error) {
imm := true
for i := 0; i < len(tenantReq.Idp.Keys); i++ {
userSecretName := fmt.Sprintf("%s-user-%d", *tenantReq.Name, i)
users = append(users, &corev1.LocalObjectReference{Name: userSecretName})
userSecret := corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: userSecretName,
Labels: map[string]string{
miniov2.TenantLabel: *tenantReq.Name,
},
},
Immutable: &imm,
Data: map[string][]byte{
"CONSOLE_ACCESS_KEY": []byte(*tenantReq.Idp.Keys[i].AccessKey),
"CONSOLE_SECRET_KEY": []byte(*tenantReq.Idp.Keys[i].SecretKey),
},
}
_, err := clientSet.createSecret(ctx, *tenantReq.Namespace, &userSecret, metav1.CreateOptions{})
if err != nil {
return users, err
}
}
return users, nil
}
func setTenantLogSearchConfiguration(ctx context.Context, tenantReq *models.CreateTenantRequest, minInst miniov2.Tenant) (miniov2.Tenant, error) {
diskSpaceFromAPI := int64(5) * humanize.GiByte // Default is 5Gi
logSearchImage := ""
logSearchPgImage := ""
logSearchPgInitImage := ""
var logSearchStorageClass *string // Nil means use default storage class
var logSearchSecurityContext *corev1.PodSecurityContext
var logSearchPgSecurityContext *corev1.PodSecurityContext
if tenantReq.LogSearchConfiguration.StorageSize != nil {
diskSpaceFromAPI = int64(*tenantReq.LogSearchConfiguration.StorageSize) * humanize.GiByte
}
if tenantReq.LogSearchConfiguration.StorageClass != "" {
logSearchStorageClass = stringPtr(tenantReq.LogSearchConfiguration.StorageClass)
}
if tenantReq.LogSearchConfiguration.Image != "" {
logSearchImage = tenantReq.LogSearchConfiguration.Image
}
if tenantReq.LogSearchConfiguration.PostgresImage != "" {
logSearchPgImage = tenantReq.LogSearchConfiguration.PostgresImage
}
if tenantReq.LogSearchConfiguration.PostgresInitImage != "" {
logSearchPgInitImage = tenantReq.LogSearchConfiguration.PostgresInitImage
}
// if security context for logSearch is present, configure it.
if tenantReq.LogSearchConfiguration.SecurityContext != nil {
sc, err := convertModelSCToK8sSC(tenantReq.LogSearchConfiguration.SecurityContext)
if err != nil {
return minInst, err
}
logSearchSecurityContext = sc
}
// if security context for logSearch is present, configure it.
if tenantReq.LogSearchConfiguration.PostgresSecurityContext != nil {
sc, err := convertModelSCToK8sSC(tenantReq.LogSearchConfiguration.PostgresSecurityContext)
if err != nil {
return minInst, err
}
logSearchPgSecurityContext = sc
}
logSearchDiskSpace := resource.NewQuantity(diskSpaceFromAPI, resource.DecimalExponent)
// the audit max cap cannot be larger than disk size on the DB, else it won't trim the data
auditMaxCap := 10
if (diskSpaceFromAPI / humanize.GiByte) < int64(auditMaxCap) {
auditMaxCap = int(diskSpaceFromAPI / humanize.GiByte)
}
// default activate lgo search and prometheus
minInst.Spec.Log = &miniov2.LogConfig{
Audit: &miniov2.AuditConfig{DiskCapacityGB: swag.Int(auditMaxCap)},
Db: &miniov2.LogDbConfig{
VolumeClaimTemplate: &corev1.PersistentVolumeClaim{
ObjectMeta: metav1.ObjectMeta{
Name: *tenantReq.Name + "-log",
},
Spec: corev1.PersistentVolumeClaimSpec{
AccessModes: []corev1.PersistentVolumeAccessMode{
corev1.ReadWriteOnce,
},
Resources: corev1.ResourceRequirements{
Requests: corev1.ResourceList{
corev1.ResourceStorage: *logSearchDiskSpace,
},
},
StorageClassName: logSearchStorageClass,
},
},
},
}
// set log search images if any
if logSearchImage != "" {
minInst.Spec.Log.Image = logSearchImage
}
if logSearchPgImage != "" {
minInst.Spec.Log.Db.Image = logSearchPgImage
}
if logSearchPgInitImage != "" {
minInst.Spec.Log.Db.InitImage = logSearchPgInitImage
}
if logSearchSecurityContext != nil {
minInst.Spec.Log.SecurityContext = logSearchSecurityContext
}
if logSearchPgSecurityContext != nil {
minInst.Spec.Log.Db.SecurityContext = logSearchPgSecurityContext
}
return minInst, nil
}
func setTenantPrometheusConfig(ctx context.Context, tenantReq *models.CreateTenantRequest, minInst miniov2.Tenant) (miniov2.Tenant, error) {
prometheusDiskSpace := 5 // Default is 5 by API
prometheusImage := "" // Default is ""
prometheusSidecardImage := "" // Default is ""
prometheusInitImage := "" // Default is ""
var prometheusStorageClass *string // Nil means default storage class
if tenantReq.PrometheusConfiguration.StorageSize != nil {
prometheusDiskSpace = int(*tenantReq.PrometheusConfiguration.StorageSize)
}
if tenantReq.PrometheusConfiguration.StorageClass != "" {
prometheusStorageClass = stringPtr(tenantReq.PrometheusConfiguration.StorageClass)
}
if tenantReq.PrometheusConfiguration.Image != "" {
prometheusImage = tenantReq.PrometheusConfiguration.Image
}
if tenantReq.PrometheusConfiguration.SidecarImage != "" {
prometheusSidecardImage = tenantReq.PrometheusConfiguration.SidecarImage
}
if tenantReq.PrometheusConfiguration.InitImage != "" {
prometheusInitImage = tenantReq.PrometheusConfiguration.InitImage
}
minInst.Spec.Prometheus = &miniov2.PrometheusConfig{
DiskCapacityDB: swag.Int(prometheusDiskSpace),
StorageClassName: prometheusStorageClass,
}
if prometheusImage != "" {
minInst.Spec.Prometheus.Image = prometheusImage
}
if prometheusSidecardImage != "" {
minInst.Spec.Prometheus.SideCarImage = prometheusSidecardImage
}
if prometheusInitImage != "" {
minInst.Spec.Prometheus.InitImage = prometheusInitImage
}
// if security context for prometheus is present, configure it.
if tenantReq.PrometheusConfiguration != nil && tenantReq.PrometheusConfiguration.SecurityContext != nil {
sc, err := convertModelSCToK8sSC(tenantReq.PrometheusConfiguration.SecurityContext)
if err != nil {
return minInst, err
}
minInst.Spec.Prometheus.SecurityContext = sc
}
return minInst, nil
}

View File

@@ -17,7 +17,11 @@
package operatorapi
import (
"context"
"errors"
"fmt"
"net/http"
"strings"
"testing"
"github.com/minio/console/models"
@@ -25,17 +29,24 @@ import (
"github.com/minio/console/operatorapi/operations/operator_api"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/suite"
v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
type TenantTestSuite struct {
suite.Suite
assert *assert.Assertions
opClient opClientMock
assert *assert.Assertions
opClient opClientMock
k8sclient k8sClientMock
}
func (suite *TenantTestSuite) SetupSuite() {
suite.assert = assert.New(suite.T())
suite.opClient = opClientMock{}
suite.k8sclient = k8sClientMock{}
k8sClientDeleteSecretsCollectionMock = func(ctx context.Context, namespace string, opts metav1.DeleteOptions, listOpts metav1.ListOptions) error {
return nil
}
}
func (suite *TenantTestSuite) SetupTest() {
@@ -129,6 +140,186 @@ func (suite *TenantTestSuite) TestCreateTenantHandlerWithError() {
suite.assert.True(ok)
}
func (suite *TenantTestSuite) TestCreateTenantWithWrongECP() {
params, _ := suite.initCreateTenantRequest()
params.Body.ErasureCodingParity = 1
k8sClientCreateSecretMock = func(ctx context.Context, namespace string, secret *v1.Secret, opts metav1.CreateOptions) (*v1.Secret, error) {
return nil, nil
}
_, err := createTenant(context.Background(), params, suite.k8sclient, nil, &models.Principal{})
suite.assert.NotNil(err)
}
func (suite *TenantTestSuite) TestCreateTenantWithWrongActiveDirectoryConfig() {
params, _ := suite.initCreateTenantRequest()
params.Body.ErasureCodingParity = 2
url := "mock-url"
lookup := "mock-lookup"
params.Body.Idp = &models.IdpConfiguration{
ActiveDirectory: &models.IdpConfigurationActiveDirectory{
SkipTLSVerification: true,
ServerInsecure: true,
ServerStartTLS: true,
UserDNS: []string{"mock-user"},
URL: &url,
LookupBindDn: &lookup,
},
}
k8sClientCreateSecretMock = func(ctx context.Context, namespace string, secret *v1.Secret, opts metav1.CreateOptions) (*v1.Secret, error) {
if strings.HasPrefix(secret.Name, fmt.Sprintf("%s-user-", *params.Body.Name)) {
return nil, errors.New("mock-error")
}
return nil, nil
}
_, err := createTenant(context.Background(), params, suite.k8sclient, nil, &models.Principal{})
suite.assert.NotNil(err)
}
func (suite *TenantTestSuite) TestCreateTenantWithWrongBuiltInUsers() {
params, _ := suite.initCreateTenantRequest()
accessKey := "mock-access-key"
secretKey := "mock-secret-key"
params.Body.Idp = &models.IdpConfiguration{
Keys: []*models.IdpConfigurationKeysItems0{
{
AccessKey: &accessKey,
SecretKey: &secretKey,
},
},
}
k8sClientCreateSecretMock = func(ctx context.Context, namespace string, secret *v1.Secret, opts metav1.CreateOptions) (*v1.Secret, error) {
if strings.HasPrefix(secret.Name, fmt.Sprintf("%s-user-", *params.Body.Name)) {
return nil, errors.New("mock-error")
}
return nil, nil
}
_, err := createTenant(context.Background(), params, suite.k8sclient, nil, &models.Principal{})
suite.assert.NotNil(err)
}
func (suite *TenantTestSuite) TestCreateTenantWithOIDCAndWrongServerCertificates() {
params, _ := suite.initCreateTenantRequest()
url := "mock-url"
clientID := "mock-client-id"
clientSecret := "mock-client-secret"
claimName := "mock-claim-name"
crt := "mock-crt"
key := "mock-key"
params.Body.Idp = &models.IdpConfiguration{
Oidc: &models.IdpConfigurationOidc{
ClientID: &clientID,
SecretID: &clientSecret,
ClaimName: &claimName,
ConfigurationURL: &url,
},
}
params.Body.TLS = &models.TLSConfiguration{
MinioServerCertificates: []*models.KeyPairConfiguration{
{
Crt: &crt,
Key: &key,
},
},
}
k8sClientDeleteSecretMock = func(ctx context.Context, namespace, name string, opts metav1.DeleteOptions) error {
return nil
}
_, err := createTenant(context.Background(), params, suite.k8sclient, nil, &models.Principal{})
suite.assert.NotNil(err)
}
func (suite *TenantTestSuite) TestCreateTenantWithWrongClientCertificates() {
params, _ := suite.initCreateTenantRequest()
crt := "mock-crt"
key := "mock-key"
params.Body.TLS = &models.TLSConfiguration{
MinioClientCertificates: []*models.KeyPairConfiguration{
{
Crt: &crt,
Key: &key,
},
},
}
k8sClientDeleteSecretMock = func(ctx context.Context, namespace, name string, opts metav1.DeleteOptions) error {
return nil
}
_, err := createTenant(context.Background(), params, suite.k8sclient, nil, &models.Principal{})
suite.assert.NotNil(err)
}
func (suite *TenantTestSuite) TestCreateTenantWithWrongCAsCertificates() {
params, _ := suite.initCreateTenantRequest()
params.Body.TLS = &models.TLSConfiguration{
MinioCAsCertificates: []string{"bW9jay1jcnQ="},
}
k8sClientDeleteSecretMock = func(ctx context.Context, namespace, name string, opts metav1.DeleteOptions) error {
return nil
}
k8sClientCreateSecretMock = func(ctx context.Context, namespace string, secret *v1.Secret, opts metav1.CreateOptions) (*v1.Secret, error) {
if strings.HasPrefix(secret.Name, fmt.Sprintf("%s-ca-certificate-", *params.Body.Name)) {
return nil, errors.New("mock-error")
}
return nil, nil
}
_, err := createTenant(context.Background(), params, suite.k8sclient, nil, &models.Principal{})
suite.assert.NotNil(err)
}
func (suite *TenantTestSuite) TestCreateTenantWithWrongMtlsCertificates() {
params, _ := suite.initCreateTenantRequest()
crt := "mock-crt"
key := "mock-key"
enableTLS := true
params.Body.EnableTLS = &enableTLS
params.Body.Encryption = &models.EncryptionConfiguration{
MinioMtls: &models.KeyPairConfiguration{
Crt: &crt,
Key: &key,
},
}
k8sClientDeleteSecretMock = func(ctx context.Context, namespace, name string, opts metav1.DeleteOptions) error {
return nil
}
_, err := createTenant(context.Background(), params, suite.k8sclient, nil, &models.Principal{})
suite.assert.NotNil(err)
}
func (suite *TenantTestSuite) TestCreateTenantWithWrongKESConfig() {
params, _ := suite.initCreateTenantRequest()
crt := "mock-crt"
key := "mock-key"
enableTLS := true
params.Body.EnableTLS = &enableTLS
params.Body.Encryption = &models.EncryptionConfiguration{
ServerTLS: &models.KeyPairConfiguration{
Crt: &crt,
Key: &key,
},
Image: "mock-image",
Replicas: "1",
}
k8sClientDeleteSecretMock = func(ctx context.Context, namespace, name string, opts metav1.DeleteOptions) error {
return nil
}
_, err := createTenant(context.Background(), params, suite.k8sclient, nil, &models.Principal{})
suite.assert.NotNil(err)
}
func (suite *TenantTestSuite) TestCreateTenantWithWrongPool() {
params, _ := suite.initCreateTenantRequest()
params.Body.Annotations = map[string]string{"mock": "mock"}
params.Body.Pools = []*models.Pool{{}}
k8sClientCreateSecretMock = func(ctx context.Context, namespace string, secret *v1.Secret, opts metav1.CreateOptions) (*v1.Secret, error) {
return nil, nil
}
k8sClientDeleteSecretMock = func(ctx context.Context, namespace, name string, opts metav1.DeleteOptions) error {
return nil
}
_, err := createTenant(context.Background(), params, suite.k8sclient, nil, &models.Principal{})
suite.assert.NotNil(err)
}
func (suite *TenantTestSuite) initCreateTenantRequest() (params operator_api.CreateTenantParams, api operations.OperatorAPI) {
registerTenantHandlers(&api)
params.HTTPRequest = &http.Request{}