Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9f005b7537 | ||
|
|
1ad6e977f2 | ||
|
|
e9a64c5479 | ||
|
|
a2e7259ccb | ||
|
|
d28e66a353 |
@@ -15,7 +15,7 @@ spec:
|
|||||||
serviceAccountName: console-sa
|
serviceAccountName: console-sa
|
||||||
containers:
|
containers:
|
||||||
- name: console
|
- name: console
|
||||||
image: minio/console:v0.3.11
|
image: minio/console:v0.3.13
|
||||||
imagePullPolicy: "IfNotPresent"
|
imagePullPolicy: "IfNotPresent"
|
||||||
args:
|
args:
|
||||||
- server
|
- server
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ spec:
|
|||||||
serviceAccountName: console-sa
|
serviceAccountName: console-sa
|
||||||
containers:
|
containers:
|
||||||
- name: console
|
- name: console
|
||||||
image: minio/console:v0.3.11
|
image: minio/console:v0.3.13
|
||||||
imagePullPolicy: "IfNotPresent"
|
imagePullPolicy: "IfNotPresent"
|
||||||
env:
|
env:
|
||||||
- name: CONSOLE_OPERATOR_MODE
|
- name: CONSOLE_OPERATOR_MODE
|
||||||
|
|||||||
@@ -42,6 +42,9 @@ type CreateTenantRequest struct {
|
|||||||
// annotations
|
// annotations
|
||||||
Annotations map[string]string `json:"annotations,omitempty"`
|
Annotations map[string]string `json:"annotations,omitempty"`
|
||||||
|
|
||||||
|
// console image
|
||||||
|
ConsoleImage string `json:"console_image,omitempty"`
|
||||||
|
|
||||||
// enable console
|
// enable console
|
||||||
EnableConsole *bool `json:"enable_console,omitempty"`
|
EnableConsole *bool `json:"enable_console,omitempty"`
|
||||||
|
|
||||||
@@ -60,6 +63,9 @@ type CreateTenantRequest struct {
|
|||||||
// image
|
// image
|
||||||
Image string `json:"image,omitempty"`
|
Image string `json:"image,omitempty"`
|
||||||
|
|
||||||
|
// image pull secret
|
||||||
|
ImagePullSecret string `json:"image_pull_secret,omitempty"`
|
||||||
|
|
||||||
// image registry
|
// image registry
|
||||||
ImageRegistry *ImageRegistry `json:"image_registry,omitempty"`
|
ImageRegistry *ImageRegistry `json:"image_registry,omitempty"`
|
||||||
|
|
||||||
|
|||||||
@@ -34,10 +34,17 @@ import (
|
|||||||
// swagger:model updateTenantRequest
|
// swagger:model updateTenantRequest
|
||||||
type UpdateTenantRequest struct {
|
type UpdateTenantRequest struct {
|
||||||
|
|
||||||
|
// console image
|
||||||
|
// Pattern: ^((.*?)/(.*?):(.+))$
|
||||||
|
ConsoleImage string `json:"console_image,omitempty"`
|
||||||
|
|
||||||
// image
|
// image
|
||||||
// Pattern: ^((.*?)/(.*?):(.+))$
|
// Pattern: ^((.*?)/(.*?):(.+))$
|
||||||
Image string `json:"image,omitempty"`
|
Image string `json:"image,omitempty"`
|
||||||
|
|
||||||
|
// image pull secret
|
||||||
|
ImagePullSecret string `json:"image_pull_secret,omitempty"`
|
||||||
|
|
||||||
// image registry
|
// image registry
|
||||||
ImageRegistry *ImageRegistry `json:"image_registry,omitempty"`
|
ImageRegistry *ImageRegistry `json:"image_registry,omitempty"`
|
||||||
}
|
}
|
||||||
@@ -46,6 +53,10 @@ type UpdateTenantRequest struct {
|
|||||||
func (m *UpdateTenantRequest) Validate(formats strfmt.Registry) error {
|
func (m *UpdateTenantRequest) Validate(formats strfmt.Registry) error {
|
||||||
var res []error
|
var res []error
|
||||||
|
|
||||||
|
if err := m.validateConsoleImage(formats); err != nil {
|
||||||
|
res = append(res, err)
|
||||||
|
}
|
||||||
|
|
||||||
if err := m.validateImage(formats); err != nil {
|
if err := m.validateImage(formats); err != nil {
|
||||||
res = append(res, err)
|
res = append(res, err)
|
||||||
}
|
}
|
||||||
@@ -60,6 +71,19 @@ func (m *UpdateTenantRequest) Validate(formats strfmt.Registry) error {
|
|||||||
return nil
|
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 {
|
func (m *UpdateTenantRequest) validateImage(formats strfmt.Registry) error {
|
||||||
|
|
||||||
if swag.IsZero(m.Image) { // not required
|
if swag.IsZero(m.Image) { // not required
|
||||||
|
|||||||
@@ -54,10 +54,6 @@ import (
|
|||||||
v1 "k8s.io/client-go/kubernetes/typed/core/v1"
|
v1 "k8s.io/client-go/kubernetes/typed/core/v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
|
||||||
minioRegCred = "minio-regcred-secret"
|
|
||||||
)
|
|
||||||
|
|
||||||
type imageRegistry struct {
|
type imageRegistry struct {
|
||||||
Auths map[string]imageRegistryCredentials `json:"auths"`
|
Auths map[string]imageRegistryCredentials `json:"auths"`
|
||||||
}
|
}
|
||||||
@@ -345,10 +341,10 @@ func getTenantCreatedResponse(session *models.Principal, params admin_api.Create
|
|||||||
|
|
||||||
if minioImage == "" {
|
if minioImage == "" {
|
||||||
minImg, err := cluster.GetMinioImage()
|
minImg, err := cluster.GetMinioImage()
|
||||||
if err != nil {
|
// we can live without figuring out the latest version of MinIO, Operator will use a hardcoded value
|
||||||
return nil, err
|
if err == nil {
|
||||||
|
minioImage = *minImg
|
||||||
}
|
}
|
||||||
minioImage = *minImg
|
|
||||||
}
|
}
|
||||||
// get Kubernetes Client
|
// get Kubernetes Client
|
||||||
clientset, err := cluster.K8sClient(session.SessionToken)
|
clientset, err := cluster.K8sClient(session.SessionToken)
|
||||||
@@ -587,9 +583,9 @@ func getTenantCreatedResponse(session *models.Principal, params admin_api.Create
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
const consoleVersion = "minio/console:v0.3.11"
|
const consoleVersion = "minio/console:v0.3.13"
|
||||||
minInst.Spec.Console = &operator.ConsoleConfiguration{
|
minInst.Spec.Console = &operator.ConsoleConfiguration{
|
||||||
Replicas: 2,
|
Replicas: 1,
|
||||||
Image: consoleVersion,
|
Image: consoleVersion,
|
||||||
ConsoleSecret: &corev1.LocalObjectReference{Name: consoleSecretName},
|
ConsoleSecret: &corev1.LocalObjectReference{Name: consoleSecretName},
|
||||||
Resources: corev1.ResourceRequirements{
|
Resources: corev1.ResourceRequirements{
|
||||||
@@ -660,13 +656,25 @@ func getTenantCreatedResponse(session *models.Principal, params admin_api.Create
|
|||||||
minInst.Spec.Mountpath = tenantReq.MounthPath
|
minInst.Spec.Mountpath = tenantReq.MounthPath
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := setImageRegistry(ctx, tenantReq.ImageRegistry, clientset.CoreV1(), ns); err != nil {
|
// We accept either `image_pull_secret` or the individual details of the `image_registry` but not both
|
||||||
|
var imagePullSecret string
|
||||||
|
|
||||||
|
if tenantReq.ImagePullSecret != "" {
|
||||||
|
imagePullSecret = tenantReq.ImagePullSecret
|
||||||
|
} else if imagePullSecret, err = setImageRegistry(ctx, *tenantReq.Name, tenantReq.ImageRegistry, clientset.CoreV1(), ns); err != nil {
|
||||||
log.Println("error setting image registry secret:", err)
|
log.Println("error setting image registry secret:", err)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
// pass the image pull secret to the Tenant
|
||||||
|
if imagePullSecret != "" {
|
||||||
|
minInst.Spec.ImagePullSecret = corev1.LocalObjectReference{
|
||||||
|
Name: imagePullSecret,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
minInst.Spec.ImagePullSecret = corev1.LocalObjectReference{
|
// set console image if provided
|
||||||
Name: minioRegCred,
|
if tenantReq.ConsoleImage != "" {
|
||||||
|
minInst.Spec.Console.Image = tenantReq.ConsoleImage
|
||||||
}
|
}
|
||||||
|
|
||||||
opClient, err := cluster.OperatorClient(session.SessionToken)
|
opClient, err := cluster.OperatorClient(session.SessionToken)
|
||||||
@@ -700,9 +708,11 @@ func getTenantCreatedResponse(session *models.Principal, params admin_api.Create
|
|||||||
return response, nil
|
return response, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func setImageRegistry(ctx context.Context, req *models.ImageRegistry, clientset v1.CoreV1Interface, namespace string) error {
|
// setImageRegistry creates a secret to store the private registry credentials, if one exist it updates the existing one
|
||||||
|
// returns the name of the secret created/updated
|
||||||
|
func setImageRegistry(ctx context.Context, tenantName string, req *models.ImageRegistry, clientset v1.CoreV1Interface, namespace string) (string, error) {
|
||||||
if req == nil || req.Registry == nil || req.Username == nil || req.Password == nil {
|
if req == nil || req.Registry == nil || req.Username == nil || req.Password == nil {
|
||||||
return nil
|
return "", nil
|
||||||
}
|
}
|
||||||
|
|
||||||
credentials := make(map[string]imageRegistryCredentials)
|
credentials := make(map[string]imageRegistryCredentials)
|
||||||
@@ -720,12 +730,14 @@ func setImageRegistry(ctx context.Context, req *models.ImageRegistry, clientset
|
|||||||
}
|
}
|
||||||
imRegistryJSON, err := json.Marshal(imRegistry)
|
imRegistryJSON, err := json.Marshal(imRegistry)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pullSecretName := fmt.Sprintf("%s-regcred", tenantName)
|
||||||
|
|
||||||
instanceSecret := corev1.Secret{
|
instanceSecret := corev1.Secret{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Name: minioRegCred,
|
Name: pullSecretName,
|
||||||
},
|
},
|
||||||
Data: map[string][]byte{
|
Data: map[string][]byte{
|
||||||
corev1.DockerConfigJsonKey: []byte(string(imRegistryJSON)),
|
corev1.DockerConfigJsonKey: []byte(string(imRegistryJSON)),
|
||||||
@@ -734,22 +746,22 @@ func setImageRegistry(ctx context.Context, req *models.ImageRegistry, clientset
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Get or Create secret if it doesn't exist
|
// Get or Create secret if it doesn't exist
|
||||||
_, err = clientset.Secrets(namespace).Get(ctx, minioRegCred, metav1.GetOptions{})
|
_, err = clientset.Secrets(namespace).Get(ctx, pullSecretName, metav1.GetOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if k8sErrors.IsNotFound(err) {
|
if k8sErrors.IsNotFound(err) {
|
||||||
_, err = clientset.Secrets(namespace).Create(ctx, &instanceSecret, metav1.CreateOptions{})
|
_, err = clientset.Secrets(namespace).Create(ctx, &instanceSecret, metav1.CreateOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return "", err
|
||||||
}
|
}
|
||||||
return nil
|
return "", nil
|
||||||
}
|
}
|
||||||
return err
|
return "", err
|
||||||
}
|
}
|
||||||
_, err = clientset.Secrets(namespace).Update(ctx, &instanceSecret, metav1.UpdateOptions{})
|
_, err = clientset.Secrets(namespace).Update(ctx, &instanceSecret, metav1.UpdateOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return "", err
|
||||||
}
|
}
|
||||||
return nil
|
return pullSecretName, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// updateTenantAction does an update on the minioTenant by patching the desired changes
|
// updateTenantAction does an update on the minioTenant by patching the desired changes
|
||||||
@@ -757,25 +769,35 @@ func updateTenantAction(ctx context.Context, operatorClient OperatorClient, clie
|
|||||||
imageToUpdate := params.Body.Image
|
imageToUpdate := params.Body.Image
|
||||||
imageRegistryReq := params.Body.ImageRegistry
|
imageRegistryReq := params.Body.ImageRegistry
|
||||||
|
|
||||||
if err := setImageRegistry(ctx, imageRegistryReq, clientset, namespace); err != nil {
|
|
||||||
log.Println("error setting image registry secret:", err)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
minInst, err := operatorClient.TenantGet(ctx, namespace, params.Tenant, metav1.GetOptions{})
|
minInst, err := operatorClient.TenantGet(ctx, namespace, params.Tenant, metav1.GetOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
// we can take either the `image_pull_secret` of the `image_registry` but not both
|
||||||
|
if params.Body.ImagePullSecret != "" {
|
||||||
|
minInst.Spec.ImagePullSecret.Name = params.Body.ImagePullSecret
|
||||||
|
} else {
|
||||||
|
// update the image pull secret content
|
||||||
|
if _, err := setImageRegistry(ctx, params.Tenant, imageRegistryReq, clientset, namespace); err != nil {
|
||||||
|
log.Println("error setting image registry secret:", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// update the console image
|
||||||
|
if strings.TrimSpace(params.Body.ConsoleImage) != "" && minInst.Spec.Console != nil {
|
||||||
|
minInst.Spec.Console.Image = params.Body.ConsoleImage
|
||||||
|
}
|
||||||
|
|
||||||
// if image to update is empty we'll use the latest image by default
|
// if image to update is empty we'll use the latest image by default
|
||||||
if strings.TrimSpace(imageToUpdate) != "" {
|
if strings.TrimSpace(imageToUpdate) != "" {
|
||||||
minInst.Spec.Image = imageToUpdate
|
minInst.Spec.Image = imageToUpdate
|
||||||
} else {
|
} else {
|
||||||
im, err := cluster.GetLatestMinioImage(httpCl)
|
im, err := cluster.GetLatestMinioImage(httpCl)
|
||||||
if err != nil {
|
// if we can't get the MinIO image, we won' auto-update it unless it's explicit by name
|
||||||
return err
|
if err == nil {
|
||||||
|
minInst.Spec.Image = *im
|
||||||
}
|
}
|
||||||
minInst.Spec.Image = *im
|
|
||||||
}
|
}
|
||||||
|
|
||||||
payloadBytes, err := json.Marshal(minInst)
|
payloadBytes, err := json.Marshal(minInst)
|
||||||
|
|||||||
@@ -647,6 +647,7 @@ func Test_UpdateTenantAction(t *testing.T) {
|
|||||||
return &http.Response{}, nil
|
return &http.Response{}, nil
|
||||||
},
|
},
|
||||||
params: admin_api.UpdateTenantParams{
|
params: admin_api.UpdateTenantParams{
|
||||||
|
Tenant: "minio-tenant",
|
||||||
Body: &models.UpdateTenantRequest{
|
Body: &models.UpdateTenantRequest{
|
||||||
Image: "minio/minio:RELEASE.2020-06-03T22-13-49Z",
|
Image: "minio/minio:RELEASE.2020-06-03T22-13-49Z",
|
||||||
},
|
},
|
||||||
@@ -675,6 +676,7 @@ func Test_UpdateTenantAction(t *testing.T) {
|
|||||||
}, nil
|
}, nil
|
||||||
},
|
},
|
||||||
params: admin_api.UpdateTenantParams{
|
params: admin_api.UpdateTenantParams{
|
||||||
|
Tenant: "minio-tenant",
|
||||||
Body: &models.UpdateTenantRequest{
|
Body: &models.UpdateTenantRequest{
|
||||||
Image: "",
|
Image: "",
|
||||||
},
|
},
|
||||||
@@ -683,7 +685,7 @@ func Test_UpdateTenantAction(t *testing.T) {
|
|||||||
wantErr: false,
|
wantErr: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Empty image input Error retrieving latest image",
|
name: "Empty image input Error retrieving latest image, nothing happens",
|
||||||
args: args{
|
args: args{
|
||||||
ctx: context.Background(),
|
ctx: context.Background(),
|
||||||
operatorClient: opClient,
|
operatorClient: opClient,
|
||||||
@@ -700,12 +702,63 @@ func Test_UpdateTenantAction(t *testing.T) {
|
|||||||
return nil, errors.New("error")
|
return nil, errors.New("error")
|
||||||
},
|
},
|
||||||
params: admin_api.UpdateTenantParams{
|
params: admin_api.UpdateTenantParams{
|
||||||
|
Tenant: "minio-tenant",
|
||||||
Body: &models.UpdateTenantRequest{
|
Body: &models.UpdateTenantRequest{
|
||||||
Image: "",
|
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.13",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
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 {
|
for _, tt := range tests {
|
||||||
|
|||||||
@@ -2024,6 +2024,9 @@ func init() {
|
|||||||
"type": "string"
|
"type": "string"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"console_image": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
"enable_console": {
|
"enable_console": {
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"default": true
|
"default": true
|
||||||
@@ -2046,6 +2049,9 @@ func init() {
|
|||||||
"image": {
|
"image": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
|
"image_pull_secret": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
"image_registry": {
|
"image_registry": {
|
||||||
"$ref": "#/definitions/imageRegistry"
|
"$ref": "#/definitions/imageRegistry"
|
||||||
},
|
},
|
||||||
@@ -3059,10 +3065,17 @@ func init() {
|
|||||||
"updateTenantRequest": {
|
"updateTenantRequest": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
|
"console_image": {
|
||||||
|
"type": "string",
|
||||||
|
"pattern": "^((.*?)/(.*?):(.+))$"
|
||||||
|
},
|
||||||
"image": {
|
"image": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"pattern": "^((.*?)/(.*?):(.+))$"
|
"pattern": "^((.*?)/(.*?):(.+))$"
|
||||||
},
|
},
|
||||||
|
"image_pull_secret": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
"image_registry": {
|
"image_registry": {
|
||||||
"$ref": "#/definitions/imageRegistry"
|
"$ref": "#/definitions/imageRegistry"
|
||||||
}
|
}
|
||||||
@@ -5938,6 +5951,9 @@ func init() {
|
|||||||
"type": "string"
|
"type": "string"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"console_image": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
"enable_console": {
|
"enable_console": {
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"default": true
|
"default": true
|
||||||
@@ -5960,6 +5976,9 @@ func init() {
|
|||||||
"image": {
|
"image": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
|
"image_pull_secret": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
"image_registry": {
|
"image_registry": {
|
||||||
"$ref": "#/definitions/imageRegistry"
|
"$ref": "#/definitions/imageRegistry"
|
||||||
},
|
},
|
||||||
@@ -6907,10 +6926,17 @@ func init() {
|
|||||||
"updateTenantRequest": {
|
"updateTenantRequest": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
|
"console_image": {
|
||||||
|
"type": "string",
|
||||||
|
"pattern": "^((.*?)/(.*?):(.+))$"
|
||||||
|
},
|
||||||
"image": {
|
"image": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"pattern": "^((.*?)/(.*?):(.+))$"
|
"pattern": "^((.*?)/(.*?):(.+))$"
|
||||||
},
|
},
|
||||||
|
"image_pull_secret": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
"image_registry": {
|
"image_registry": {
|
||||||
"$ref": "#/definitions/imageRegistry"
|
"$ref": "#/definitions/imageRegistry"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,16 +19,30 @@ package restapi
|
|||||||
import (
|
import (
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"crypto/x509"
|
"crypto/x509"
|
||||||
"fmt"
|
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
"log"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
func getCertPool() *x509.CertPool {
|
||||||
certDontExists = "File certificate doesn't exists: %s"
|
caCertFileNames := getMinioServerTLSRootCAs()
|
||||||
)
|
// If CAs certificates are configured we save them to the http.Client RootCAs store
|
||||||
|
certs := x509.NewCertPool()
|
||||||
|
for _, caCert := range caCertFileNames {
|
||||||
|
pemData, err := ioutil.ReadFile(caCert)
|
||||||
|
if err != nil {
|
||||||
|
// logging this error
|
||||||
|
log.Println(err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
certs.AppendCertsFromPEM(pemData)
|
||||||
|
}
|
||||||
|
return certs
|
||||||
|
}
|
||||||
|
|
||||||
|
var certPool = getCertPool()
|
||||||
|
|
||||||
func prepareSTSClientTransport(insecure bool) *http.Transport {
|
func prepareSTSClientTransport(insecure bool) *http.Transport {
|
||||||
// This takes github.com/minio/minio/pkg/madmin/transport.go as an example
|
// This takes github.com/minio/minio/pkg/madmin/transport.go as an example
|
||||||
@@ -36,18 +50,6 @@ func prepareSTSClientTransport(insecure bool) *http.Transport {
|
|||||||
// DefaultTransport - this default transport is similar to
|
// DefaultTransport - this default transport is similar to
|
||||||
// http.DefaultTransport but with additional param DisableCompression
|
// http.DefaultTransport but with additional param DisableCompression
|
||||||
// is set to true to avoid decompressing content with 'gzip' encoding.
|
// is set to true to avoid decompressing content with 'gzip' encoding.
|
||||||
|
|
||||||
// Keep TLS config.
|
|
||||||
tlsConfig := &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 insecure {
|
|
||||||
tlsConfig.InsecureSkipVerify = true
|
|
||||||
}
|
|
||||||
|
|
||||||
DefaultTransport := &http.Transport{
|
DefaultTransport := &http.Transport{
|
||||||
Proxy: http.ProxyFromEnvironment,
|
Proxy: http.ProxyFromEnvironment,
|
||||||
DialContext: (&net.Dialer{
|
DialContext: (&net.Dialer{
|
||||||
@@ -61,38 +63,14 @@ func prepareSTSClientTransport(insecure bool) *http.Transport {
|
|||||||
TLSHandshakeTimeout: 10 * time.Second,
|
TLSHandshakeTimeout: 10 * time.Second,
|
||||||
ExpectContinueTimeout: 1 * time.Second,
|
ExpectContinueTimeout: 1 * time.Second,
|
||||||
DisableCompression: true,
|
DisableCompression: true,
|
||||||
TLSClientConfig: tlsConfig,
|
TLSClientConfig: &tls.Config{
|
||||||
}
|
|
||||||
// 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{
|
|
||||||
// Can't use SSLv3 because of POODLE and BEAST
|
// 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.0 because of POODLE and BEAST using CBC cipher
|
||||||
// Can't use TLSv1.1 because of RC4 cipher usage
|
// Can't use TLSv1.1 because of RC4 cipher usage
|
||||||
MinVersion: tls.VersionTLS12,
|
MinVersion: tls.VersionTLS12,
|
||||||
}
|
InsecureSkipVerify: insecure,
|
||||||
// If CAs certificates are configured we save them to the http.Client RootCAs store
|
RootCAs: certPool,
|
||||||
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
|
|
||||||
}
|
}
|
||||||
return DefaultTransport
|
return DefaultTransport
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1778,8 +1778,13 @@ definitions:
|
|||||||
image:
|
image:
|
||||||
type: string
|
type: string
|
||||||
pattern: "^((.*?)/(.*?):(.+))$"
|
pattern: "^((.*?)/(.*?):(.+))$"
|
||||||
|
console_image:
|
||||||
|
type: string
|
||||||
|
pattern: "^((.*?)/(.*?):(.+))$"
|
||||||
image_registry:
|
image_registry:
|
||||||
$ref: "#/definitions/imageRegistry"
|
$ref: "#/definitions/imageRegistry"
|
||||||
|
image_pull_secret:
|
||||||
|
type: string
|
||||||
|
|
||||||
imageRegistry:
|
imageRegistry:
|
||||||
type: object
|
type: object
|
||||||
@@ -1807,6 +1812,8 @@ definitions:
|
|||||||
pattern: "^[a-z0-9-]{3,63}$"
|
pattern: "^[a-z0-9-]{3,63}$"
|
||||||
image:
|
image:
|
||||||
type: string
|
type: string
|
||||||
|
console_image:
|
||||||
|
type: string
|
||||||
service_name:
|
service_name:
|
||||||
type: string
|
type: string
|
||||||
zones:
|
zones:
|
||||||
@@ -1835,6 +1842,8 @@ definitions:
|
|||||||
type: string
|
type: string
|
||||||
image_registry:
|
image_registry:
|
||||||
$ref: "#/definitions/imageRegistry"
|
$ref: "#/definitions/imageRegistry"
|
||||||
|
image_pull_secret:
|
||||||
|
type: string
|
||||||
idp:
|
idp:
|
||||||
type: object
|
type: object
|
||||||
$ref: "#/definitions/idpConfiguration"
|
$ref: "#/definitions/idpConfiguration"
|
||||||
|
|||||||
Reference in New Issue
Block a user