diff --git a/cluster/config.go b/cluster/config.go
index 7c4e09dbf..6deb72b01 100644
--- a/cluster/config.go
+++ b/cluster/config.go
@@ -17,20 +17,15 @@
package cluster
import (
- "errors"
- "fmt"
"io/ioutil"
"net"
"net/http"
- "regexp"
"strings"
"time"
- "github.com/minio/pkg/env"
-)
+ "github.com/minio/console/pkg/utils"
-var (
- errCantDetermineMinIOImage = errors.New("can't determine MinIO Image")
+ "github.com/minio/pkg/env"
)
func GetK8sAPIServer() string {
@@ -66,31 +61,8 @@ func GetNsFromFile() string {
// Namespace will run only once at console startup
var Namespace = GetNsFromFile()
-// getLatestMinIOImage returns the latest docker image for MinIO if found on the internet
-func getLatestMinIOImage(client HTTPClientI) (*string, error) {
- resp, err := client.Get("https://dl.min.io/server/minio/release/linux-amd64/")
- if err != nil {
- return nil, err
- }
- defer resp.Body.Close()
-
- body, err := ioutil.ReadAll(resp.Body)
- if err != nil {
- return nil, err
- }
- var re = regexp.MustCompile(`(?m)\.\/minio\.(RELEASE.*?Z)"`)
- // look for a single match
- matches := re.FindAllStringSubmatch(string(body), 1)
- for i := range matches {
- release := matches[i][1]
- dockerImage := fmt.Sprintf("minio/minio:%s", release)
- return &dockerImage, nil
- }
- return nil, errCantDetermineMinIOImage
-}
-
-var latestMinIOImage, errLatestMinIOImage = getLatestMinIOImage(
- &HTTPClient{
+var latestMinIOImage, errLatestMinIOImage = utils.GetLatestMinIOImage(
+ &utils.HTTPClient{
Client: &http.Client{
Timeout: 15 * time.Second,
},
@@ -112,8 +84,8 @@ func GetMinioImage() (*string, error) {
}
// GetLatestMinioImage returns the latest image URL on minio repository
-func GetLatestMinioImage(client HTTPClientI) (*string, error) {
- latestMinIOImage, err := getLatestMinIOImage(client)
+func GetLatestMinioImage(client utils.HTTPClientI) (*string, error) {
+ latestMinIOImage, err := utils.GetLatestMinIOImage(client)
if err != nil {
return nil, err
}
diff --git a/models/check_operator_version_response.go b/models/check_operator_version_response.go
new file mode 100644
index 000000000..e23e03cf8
--- /dev/null
+++ b/models/check_operator_version_response.go
@@ -0,0 +1,70 @@
+// Code generated by go-swagger; DO NOT EDIT.
+
+// This file is part of MinIO Console Server
+// Copyright (c) 2021 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 .
+//
+
+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 (
+ "context"
+
+ "github.com/go-openapi/strfmt"
+ "github.com/go-openapi/swag"
+)
+
+// CheckOperatorVersionResponse check operator version response
+//
+// swagger:model checkOperatorVersionResponse
+type CheckOperatorVersionResponse struct {
+
+ // current version
+ CurrentVersion string `json:"current_version,omitempty"`
+
+ // latest version
+ LatestVersion string `json:"latest_version,omitempty"`
+}
+
+// Validate validates this check operator version response
+func (m *CheckOperatorVersionResponse) Validate(formats strfmt.Registry) error {
+ return nil
+}
+
+// ContextValidate validates this check operator version response based on context it is used
+func (m *CheckOperatorVersionResponse) ContextValidate(ctx context.Context, formats strfmt.Registry) error {
+ return nil
+}
+
+// MarshalBinary interface implementation
+func (m *CheckOperatorVersionResponse) MarshalBinary() ([]byte, error) {
+ if m == nil {
+ return nil, nil
+ }
+ return swag.WriteJSON(m)
+}
+
+// UnmarshalBinary interface implementation
+func (m *CheckOperatorVersionResponse) UnmarshalBinary(b []byte) error {
+ var res CheckOperatorVersionResponse
+ if err := swag.ReadJSON(b, &res); err != nil {
+ return err
+ }
+ *m = res
+ return nil
+}
diff --git a/models/check_version_response.go b/models/check_version_response.go
new file mode 100644
index 000000000..82f73c088
--- /dev/null
+++ b/models/check_version_response.go
@@ -0,0 +1,70 @@
+// Code generated by go-swagger; DO NOT EDIT.
+
+// This file is part of MinIO Console Server
+// Copyright (c) 2021 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 .
+//
+
+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 (
+ "context"
+
+ "github.com/go-openapi/strfmt"
+ "github.com/go-openapi/swag"
+)
+
+// CheckVersionResponse check version response
+//
+// swagger:model checkVersionResponse
+type CheckVersionResponse struct {
+
+ // current version
+ CurrentVersion string `json:"current_version,omitempty"`
+
+ // latest version
+ LatestVersion string `json:"latest_version,omitempty"`
+}
+
+// Validate validates this check version response
+func (m *CheckVersionResponse) Validate(formats strfmt.Registry) error {
+ return nil
+}
+
+// ContextValidate validates this check version response based on context it is used
+func (m *CheckVersionResponse) ContextValidate(ctx context.Context, formats strfmt.Registry) error {
+ return nil
+}
+
+// MarshalBinary interface implementation
+func (m *CheckVersionResponse) MarshalBinary() ([]byte, error) {
+ if m == nil {
+ return nil, nil
+ }
+ return swag.WriteJSON(m)
+}
+
+// UnmarshalBinary interface implementation
+func (m *CheckVersionResponse) UnmarshalBinary(b []byte) error {
+ var res CheckVersionResponse
+ if err := swag.ReadJSON(b, &res); err != nil {
+ return err
+ }
+ *m = res
+ return nil
+}
diff --git a/operatorapi/configure_operator.go b/operatorapi/configure_operator.go
index dfa6a4b39..b78d904c6 100644
--- a/operatorapi/configure_operator.go
+++ b/operatorapi/configure_operator.go
@@ -75,6 +75,7 @@ func configureAPI(api *operations.OperatorAPI) http.Handler {
// Register login handlers
registerLoginHandlers(api)
registerSessionHandlers(api)
+ registerVersionHandlers(api)
// Operator Console
// Register tenant handlers
diff --git a/operatorapi/embedded_spec.go b/operatorapi/embedded_spec.go
index fdb45671b..01848b88c 100644
--- a/operatorapi/embedded_spec.go
+++ b/operatorapi/embedded_spec.go
@@ -52,6 +52,30 @@ func init() {
},
"basePath": "/api/v1",
"paths": {
+ "/check-version": {
+ "get": {
+ "security": [],
+ "tags": [
+ "UserAPI"
+ ],
+ "summary": "Checks the current Operator version against the latest",
+ "operationId": "CheckMinIOVersion”",
+ "responses": {
+ "200": {
+ "description": "A successful response.",
+ "schema": {
+ "$ref": "#/definitions/checkOperatorVersionResponse"
+ }
+ },
+ "default": {
+ "description": "Generic error response.",
+ "schema": {
+ "$ref": "#/definitions/error"
+ }
+ }
+ }
+ }
+ },
"/cluster/allocatable-resources": {
"get": {
"tags": [
@@ -1863,6 +1887,17 @@ func init() {
}
}
},
+ "checkOperatorVersionResponse": {
+ "type": "object",
+ "properties": {
+ "current_version": {
+ "type": "string"
+ },
+ "latest_version": {
+ "type": "string"
+ }
+ }
+ },
"configureTenantRequest": {
"type": "object",
"properties": {
@@ -3921,6 +3956,30 @@ func init() {
},
"basePath": "/api/v1",
"paths": {
+ "/check-version": {
+ "get": {
+ "security": [],
+ "tags": [
+ "UserAPI"
+ ],
+ "summary": "Checks the current Operator version against the latest",
+ "operationId": "CheckMinIOVersion”",
+ "responses": {
+ "200": {
+ "description": "A successful response.",
+ "schema": {
+ "$ref": "#/definitions/checkOperatorVersionResponse"
+ }
+ },
+ "default": {
+ "description": "Generic error response.",
+ "schema": {
+ "$ref": "#/definitions/error"
+ }
+ }
+ }
+ }
+ },
"/cluster/allocatable-resources": {
"get": {
"tags": [
@@ -6583,6 +6642,17 @@ func init() {
}
}
},
+ "checkOperatorVersionResponse": {
+ "type": "object",
+ "properties": {
+ "current_version": {
+ "type": "string"
+ },
+ "latest_version": {
+ "type": "string"
+ }
+ }
+ },
"configureTenantRequest": {
"type": "object",
"properties": {
diff --git a/operatorapi/operations/operator_api.go b/operatorapi/operations/operator_api.go
index a7928f747..1e7b1174c 100644
--- a/operatorapi/operations/operator_api.go
+++ b/operatorapi/operations/operator_api.go
@@ -63,6 +63,9 @@ func NewOperatorAPI(spec *loads.Document) *OperatorAPI {
JSONProducer: runtime.JSONProducer(),
+ UserAPICheckMinIOVersionHandler: user_api.CheckMinIOVersionHandlerFunc(func(params user_api.CheckMinIOVersionParams) middleware.Responder {
+ return middleware.NotImplemented("operation user_api.CheckMinIOVersion has not yet been implemented")
+ }),
OperatorAPICreateNamespaceHandler: operator_api.CreateNamespaceHandlerFunc(func(params operator_api.CreateNamespaceParams, principal *models.Principal) middleware.Responder {
return middleware.NotImplemented("operation operator_api.CreateNamespace has not yet been implemented")
}),
@@ -253,6 +256,8 @@ type OperatorAPI struct {
// APIAuthorizer provides access control (ACL/RBAC/ABAC) by providing access to the request and authenticated principal
APIAuthorizer runtime.Authorizer
+ // UserAPICheckMinIOVersionHandler sets the operation handler for the check min i o version operation
+ UserAPICheckMinIOVersionHandler user_api.CheckMinIOVersionHandler
// OperatorAPICreateNamespaceHandler sets the operation handler for the create namespace operation
OperatorAPICreateNamespaceHandler operator_api.CreateNamespaceHandler
// OperatorAPICreateTenantHandler sets the operation handler for the create tenant operation
@@ -428,6 +433,9 @@ func (o *OperatorAPI) Validate() error {
unregistered = append(unregistered, "KeyAuth")
}
+ if o.UserAPICheckMinIOVersionHandler == nil {
+ unregistered = append(unregistered, "user_api.CheckMinIOVersionHandler")
+ }
if o.OperatorAPICreateNamespaceHandler == nil {
unregistered = append(unregistered, "operator_api.CreateNamespaceHandler")
}
@@ -667,6 +675,10 @@ func (o *OperatorAPI) initHandlerCache() {
o.handlers = make(map[string]map[string]http.Handler)
}
+ if o.handlers["GET"] == nil {
+ o.handlers["GET"] = make(map[string]http.Handler)
+ }
+ o.handlers["GET"]["/check-version"] = user_api.NewCheckMinIOVersion(o.context, o.UserAPICheckMinIOVersionHandler)
if o.handlers["POST"] == nil {
o.handlers["POST"] = make(map[string]http.Handler)
}
diff --git a/operatorapi/operations/user_api/check_min_i_o_version.go b/operatorapi/operations/user_api/check_min_i_o_version.go
new file mode 100644
index 000000000..b72b27a0b
--- /dev/null
+++ b/operatorapi/operations/user_api/check_min_i_o_version.go
@@ -0,0 +1,73 @@
+// Code generated by go-swagger; DO NOT EDIT.
+
+// This file is part of MinIO Console Server
+// Copyright (c) 2021 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 .
+//
+
+package user_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"
+)
+
+// CheckMinIOVersionHandlerFunc turns a function with the right signature into a check min i o version handler
+type CheckMinIOVersionHandlerFunc func(CheckMinIOVersionParams) middleware.Responder
+
+// Handle executing the request and returning a response
+func (fn CheckMinIOVersionHandlerFunc) Handle(params CheckMinIOVersionParams) middleware.Responder {
+ return fn(params)
+}
+
+// CheckMinIOVersionHandler interface for that can handle valid check min i o version params
+type CheckMinIOVersionHandler interface {
+ Handle(CheckMinIOVersionParams) middleware.Responder
+}
+
+// NewCheckMinIOVersion creates a new http.Handler for the check min i o version operation
+func NewCheckMinIOVersion(ctx *middleware.Context, handler CheckMinIOVersionHandler) *CheckMinIOVersion {
+ return &CheckMinIOVersion{Context: ctx, Handler: handler}
+}
+
+/* CheckMinIOVersion swagger:route GET /check-version UserAPI checkMinIOVersion
+
+Checks the current Operator version against the latest
+
+*/
+type CheckMinIOVersion struct {
+ Context *middleware.Context
+ Handler CheckMinIOVersionHandler
+}
+
+func (o *CheckMinIOVersion) ServeHTTP(rw http.ResponseWriter, r *http.Request) {
+ route, rCtx, _ := o.Context.RouteInfo(r)
+ if rCtx != nil {
+ *r = *rCtx
+ }
+ var Params = NewCheckMinIOVersionParams()
+ 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) // actually handle the request
+ o.Context.Respond(rw, r, route.Produces, route, res)
+
+}
diff --git a/operatorapi/operations/user_api/check_min_i_o_version_parameters.go b/operatorapi/operations/user_api/check_min_i_o_version_parameters.go
new file mode 100644
index 000000000..c98825992
--- /dev/null
+++ b/operatorapi/operations/user_api/check_min_i_o_version_parameters.go
@@ -0,0 +1,63 @@
+// Code generated by go-swagger; DO NOT EDIT.
+
+// This file is part of MinIO Console Server
+// Copyright (c) 2021 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 .
+//
+
+package user_api
+
+// This file was generated by the swagger tool.
+// Editing this file might prove futile when you re-run the swagger generate command
+
+import (
+ "net/http"
+
+ "github.com/go-openapi/errors"
+ "github.com/go-openapi/runtime/middleware"
+)
+
+// NewCheckMinIOVersionParams creates a new CheckMinIOVersionParams object
+//
+// There are no default values defined in the spec.
+func NewCheckMinIOVersionParams() CheckMinIOVersionParams {
+
+ return CheckMinIOVersionParams{}
+}
+
+// CheckMinIOVersionParams contains all the bound params for the check min i o version operation
+// typically these are obtained from a http.Request
+//
+// swagger:parameters CheckMinIOVersion”
+type CheckMinIOVersionParams struct {
+
+ // HTTP Request Object
+ HTTPRequest *http.Request `json:"-"`
+}
+
+// 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 NewCheckMinIOVersionParams() beforehand.
+func (o *CheckMinIOVersionParams) BindRequest(r *http.Request, route *middleware.MatchedRoute) error {
+ var res []error
+
+ o.HTTPRequest = r
+
+ if len(res) > 0 {
+ return errors.CompositeValidationError(res...)
+ }
+ return nil
+}
diff --git a/operatorapi/operations/user_api/check_min_i_o_version_responses.go b/operatorapi/operations/user_api/check_min_i_o_version_responses.go
new file mode 100644
index 000000000..41b102f82
--- /dev/null
+++ b/operatorapi/operations/user_api/check_min_i_o_version_responses.go
@@ -0,0 +1,133 @@
+// Code generated by go-swagger; DO NOT EDIT.
+
+// This file is part of MinIO Console Server
+// Copyright (c) 2021 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 .
+//
+
+package user_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"
+)
+
+// CheckMinIOVersionOKCode is the HTTP code returned for type CheckMinIOVersionOK
+const CheckMinIOVersionOKCode int = 200
+
+/*CheckMinIOVersionOK A successful response.
+
+swagger:response checkMinIOVersionOK
+*/
+type CheckMinIOVersionOK struct {
+
+ /*
+ In: Body
+ */
+ Payload *models.CheckOperatorVersionResponse `json:"body,omitempty"`
+}
+
+// NewCheckMinIOVersionOK creates CheckMinIOVersionOK with default headers values
+func NewCheckMinIOVersionOK() *CheckMinIOVersionOK {
+
+ return &CheckMinIOVersionOK{}
+}
+
+// WithPayload adds the payload to the check min i o version o k response
+func (o *CheckMinIOVersionOK) WithPayload(payload *models.CheckOperatorVersionResponse) *CheckMinIOVersionOK {
+ o.Payload = payload
+ return o
+}
+
+// SetPayload sets the payload to the check min i o version o k response
+func (o *CheckMinIOVersionOK) SetPayload(payload *models.CheckOperatorVersionResponse) {
+ o.Payload = payload
+}
+
+// WriteResponse to the client
+func (o *CheckMinIOVersionOK) 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
+ }
+ }
+}
+
+/*CheckMinIOVersionDefault Generic error response.
+
+swagger:response checkMinIOVersionDefault
+*/
+type CheckMinIOVersionDefault struct {
+ _statusCode int
+
+ /*
+ In: Body
+ */
+ Payload *models.Error `json:"body,omitempty"`
+}
+
+// NewCheckMinIOVersionDefault creates CheckMinIOVersionDefault with default headers values
+func NewCheckMinIOVersionDefault(code int) *CheckMinIOVersionDefault {
+ if code <= 0 {
+ code = 500
+ }
+
+ return &CheckMinIOVersionDefault{
+ _statusCode: code,
+ }
+}
+
+// WithStatusCode adds the status to the check min i o version default response
+func (o *CheckMinIOVersionDefault) WithStatusCode(code int) *CheckMinIOVersionDefault {
+ o._statusCode = code
+ return o
+}
+
+// SetStatusCode sets the status to the check min i o version default response
+func (o *CheckMinIOVersionDefault) SetStatusCode(code int) {
+ o._statusCode = code
+}
+
+// WithPayload adds the payload to the check min i o version default response
+func (o *CheckMinIOVersionDefault) WithPayload(payload *models.Error) *CheckMinIOVersionDefault {
+ o.Payload = payload
+ return o
+}
+
+// SetPayload sets the payload to the check min i o version default response
+func (o *CheckMinIOVersionDefault) SetPayload(payload *models.Error) {
+ o.Payload = payload
+}
+
+// WriteResponse to the client
+func (o *CheckMinIOVersionDefault) 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
+ }
+ }
+}
diff --git a/operatorapi/operations/user_api/check_min_i_o_version_urlbuilder.go b/operatorapi/operations/user_api/check_min_i_o_version_urlbuilder.go
new file mode 100644
index 000000000..1f5e2d5ef
--- /dev/null
+++ b/operatorapi/operations/user_api/check_min_i_o_version_urlbuilder.go
@@ -0,0 +1,104 @@
+// Code generated by go-swagger; DO NOT EDIT.
+
+// This file is part of MinIO Console Server
+// Copyright (c) 2021 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 .
+//
+
+package user_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"
+)
+
+// CheckMinIOVersionURL generates an URL for the check min i o version operation
+type CheckMinIOVersionURL struct {
+ _basePath string
+}
+
+// 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 *CheckMinIOVersionURL) WithBasePath(bp string) *CheckMinIOVersionURL {
+ 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 *CheckMinIOVersionURL) SetBasePath(bp string) {
+ o._basePath = bp
+}
+
+// Build a url path and query string
+func (o *CheckMinIOVersionURL) Build() (*url.URL, error) {
+ var _result url.URL
+
+ var _path = "/check-version"
+
+ _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 *CheckMinIOVersionURL) 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 *CheckMinIOVersionURL) String() string {
+ return o.Must(o.Build()).String()
+}
+
+// BuildFull builds a full url with scheme, host, path and query string
+func (o *CheckMinIOVersionURL) BuildFull(scheme, host string) (*url.URL, error) {
+ if scheme == "" {
+ return nil, errors.New("scheme is required for a full url on CheckMinIOVersionURL")
+ }
+ if host == "" {
+ return nil, errors.New("host is required for a full url on CheckMinIOVersionURL")
+ }
+
+ 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 *CheckMinIOVersionURL) StringFull(scheme, host string) string {
+ return o.Must(o.BuildFull(scheme, host)).String()
+}
diff --git a/operatorapi/operator_tenants.go b/operatorapi/operator_tenants.go
index 38f970c22..a406569de 100644
--- a/operatorapi/operator_tenants.go
+++ b/operatorapi/operator_tenants.go
@@ -33,6 +33,8 @@ import (
"strings"
"time"
+ utils2 "github.com/minio/console/pkg/utils"
+
"github.com/dustin/go-humanize"
"github.com/minio/console/restapi"
@@ -1039,7 +1041,7 @@ func setImageRegistry(ctx context.Context, req *models.ImageRegistry, clientset
}
// updateTenantAction does an update on the minioTenant by patching the desired changes
-func updateTenantAction(ctx context.Context, operatorClient OperatorClientI, clientset v1.CoreV1Interface, httpCl cluster.HTTPClientI, namespace string, params operator_api.UpdateTenantParams) error {
+func updateTenantAction(ctx context.Context, operatorClient OperatorClientI, clientset v1.CoreV1Interface, httpCl utils2.HTTPClientI, namespace string, params operator_api.UpdateTenantParams) error {
imageToUpdate := params.Body.Image
imageRegistryReq := params.Body.ImageRegistry
@@ -1145,7 +1147,7 @@ func getUpdateTenantResponse(session *models.Principal, params operator_api.Upda
opClient := &operatorClient{
client: opClientClientSet,
}
- httpC := &cluster.HTTPClient{
+ httpC := &utils2.HTTPClient{
Client: &http.Client{
Timeout: 4 * time.Second,
},
diff --git a/operatorapi/operator_tenants_test.go b/operatorapi/operator_tenants_test.go
index f69e3b652..eaf340dd4 100644
--- a/operatorapi/operator_tenants_test.go
+++ b/operatorapi/operator_tenants_test.go
@@ -28,10 +28,11 @@ import (
"testing"
"time"
+ "github.com/minio/console/pkg/utils"
+
"github.com/minio/console/operatorapi/operations/operator_api"
"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"
corev1 "k8s.io/api/core/v1"
@@ -895,7 +896,7 @@ func Test_UpdateTenantAction(t *testing.T) {
type args struct {
ctx context.Context
operatorClient OperatorClientI
- httpCl cluster.HTTPClientI
+ httpCl utils.HTTPClientI
nameSpace string
tenantName string
mockTenantPatch func(ctx context.Context, namespace string, tenantName string, pt types.PatchType, data []byte, options metav1.PatchOptions) (*miniov2.Tenant, error)
diff --git a/operatorapi/operator_version.go b/operatorapi/operator_version.go
new file mode 100644
index 000000000..0e9c027be
--- /dev/null
+++ b/operatorapi/operator_version.go
@@ -0,0 +1,53 @@
+// This file is part of MinIO Console Server
+// Copyright (c) 2022 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 .
+
+package operatorapi
+
+import (
+ "github.com/go-openapi/runtime/middleware"
+ "github.com/minio/console/models"
+ "github.com/minio/console/operatorapi/operations"
+ "github.com/minio/console/operatorapi/operations/user_api"
+
+ "net/http"
+ "time"
+
+ "github.com/minio/console/pkg/utils"
+)
+
+func registerVersionHandlers(api *operations.OperatorAPI) {
+ api.UserAPICheckMinIOVersionHandler = user_api.CheckMinIOVersionHandlerFunc(func(params user_api.CheckMinIOVersionParams) middleware.Responder {
+ versionResponse, err := getVersionResponse()
+ if err != nil {
+ return user_api.NewCheckMinIOVersionDefault(int(err.Code)).WithPayload(err)
+ }
+ return user_api.NewCheckMinIOVersionOK().WithPayload(versionResponse)
+ })
+}
+
+// getSessionResponse parse the token of the current session and returns a list of allowed actions to render in the UI
+func getVersionResponse() (*models.CheckOperatorVersionResponse, *models.Error) {
+ ver, err := utils.GetLatestMinIOImage(&utils.HTTPClient{
+ Client: &http.Client{
+ Timeout: 15 * time.Second,
+ }})
+ if err != nil {
+ return nil, prepareError(err)
+ }
+ return &models.CheckOperatorVersionResponse{
+ LatestVersion: *ver,
+ }, nil
+}
diff --git a/pkg/subnet/subnet.go b/pkg/subnet/subnet.go
index dbc65ea89..d9fe00f03 100644
--- a/pkg/subnet/subnet.go
+++ b/pkg/subnet/subnet.go
@@ -24,17 +24,17 @@ import (
"fmt"
"log"
+ "github.com/minio/console/pkg/utils"
+
"github.com/minio/pkg/licverifier"
"github.com/minio/console/models"
"github.com/minio/madmin-go"
mc "github.com/minio/mc/cmd"
"github.com/tidwall/gjson"
-
- "github.com/minio/console/cluster"
)
-func LoginWithMFA(client cluster.HTTPClientI, username, mfaToken, otp string) (*LoginResp, error) {
+func LoginWithMFA(client utils.HTTPClientI, username, mfaToken, otp string) (*LoginResp, error) {
mfaLoginReq := MfaReq{Username: username, OTP: otp, Token: mfaToken}
resp, err := subnetPostReq(client, subnetMFAURL(), mfaLoginReq, nil)
if err != nil {
@@ -47,7 +47,7 @@ func LoginWithMFA(client cluster.HTTPClientI, username, mfaToken, otp string) (*
return nil, errors.New("access token not found in response")
}
-func Login(client cluster.HTTPClientI, username, password string) (*LoginResp, error) {
+func Login(client utils.HTTPClientI, username, password string) (*LoginResp, error) {
loginReq := map[string]string{
"username": username,
"password": password,
@@ -71,7 +71,7 @@ func Login(client cluster.HTTPClientI, username, password string) (*LoginResp, e
return nil, errors.New("access token not found in response")
}
-func GetOrganizations(client cluster.HTTPClientI, token string) ([]*models.SubnetOrganization, error) {
+func GetOrganizations(client utils.HTTPClientI, token string) ([]*models.SubnetOrganization, error) {
headers := subnetAuthHeaders(token)
respStr, err := subnetGetReq(client, subnetOrgsURL(), headers)
if err != nil {
@@ -90,7 +90,7 @@ type LicenseTokenConfig struct {
Proxy string
}
-func Register(client cluster.HTTPClientI, admInfo madmin.InfoMessage, apiKey, token, accountID string) (*LicenseTokenConfig, error) {
+func Register(client utils.HTTPClientI, admInfo madmin.InfoMessage, apiKey, token, accountID string) (*LicenseTokenConfig, error) {
var headers map[string]string
regInfo := GetClusterRegInfo(admInfo)
regURL := subnetRegisterURL()
@@ -128,7 +128,7 @@ func Register(client cluster.HTTPClientI, admInfo madmin.InfoMessage, apiKey, to
const publicKey = "/downloads/license-pubkey.pem"
// downloadSubnetPublicKey will download the current subnet public key.
-func downloadSubnetPublicKey(client cluster.HTTPClientI) (string, error) {
+func downloadSubnetPublicKey(client utils.HTTPClientI) (string, error) {
// Get the public key directly from Subnet
url := fmt.Sprintf("%s%s", subnetBaseURL(), publicKey)
resp, err := client.Get(url)
@@ -145,7 +145,7 @@ func downloadSubnetPublicKey(client cluster.HTTPClientI) (string, error) {
}
// ParseLicense parses the license with the bundle public key and return it's information
-func ParseLicense(client cluster.HTTPClientI, license string) (*licverifier.LicenseInfo, error) {
+func ParseLicense(client utils.HTTPClientI, license string) (*licverifier.LicenseInfo, error) {
var publicKeys []string
subnetPubKey, err := downloadSubnetPublicKey(client)
diff --git a/pkg/subnet/utils.go b/pkg/subnet/utils.go
index 7b509b78a..811ce9e50 100644
--- a/pkg/subnet/utils.go
+++ b/pkg/subnet/utils.go
@@ -25,7 +25,8 @@ import (
"io/ioutil"
"net/http"
- "github.com/minio/console/cluster"
+ "github.com/minio/console/pkg/utils"
+
"github.com/minio/madmin-go"
mc "github.com/minio/mc/cmd"
"github.com/minio/pkg/env"
@@ -68,11 +69,11 @@ func subnetAuthHeaders(authToken string) map[string]string {
return map[string]string{"Authorization": "Bearer " + authToken}
}
-func httpDo(client cluster.HTTPClientI, req *http.Request) (*http.Response, error) {
+func httpDo(client utils.HTTPClientI, req *http.Request) (*http.Response, error) {
return client.Do(req)
}
-func subnetReqDo(client cluster.HTTPClientI, r *http.Request, headers map[string]string) (string, error) {
+func subnetReqDo(client utils.HTTPClientI, r *http.Request, headers map[string]string) (string, error) {
for k, v := range headers {
r.Header.Add(k, v)
}
@@ -100,7 +101,7 @@ func subnetReqDo(client cluster.HTTPClientI, r *http.Request, headers map[string
return respStr, fmt.Errorf("Request failed with code %d and error: %s", resp.StatusCode, respStr)
}
-func subnetGetReq(client cluster.HTTPClientI, reqURL string, headers map[string]string) (string, error) {
+func subnetGetReq(client utils.HTTPClientI, reqURL string, headers map[string]string) (string, error) {
r, e := http.NewRequest(http.MethodGet, reqURL, nil)
if e != nil {
return "", e
@@ -108,7 +109,7 @@ func subnetGetReq(client cluster.HTTPClientI, reqURL string, headers map[string]
return subnetReqDo(client, r, headers)
}
-func subnetPostReq(client cluster.HTTPClientI, reqURL string, payload interface{}, headers map[string]string) (string, error) {
+func subnetPostReq(client utils.HTTPClientI, reqURL string, payload interface{}, headers map[string]string) (string, error) {
body, e := json.Marshal(payload)
if e != nil {
return "", e
diff --git a/cluster/http_client.go b/pkg/utils/http_client.go
similarity index 97%
rename from cluster/http_client.go
rename to pkg/utils/http_client.go
index 4d610379d..4dff79349 100644
--- a/cluster/http_client.go
+++ b/pkg/utils/http_client.go
@@ -1,5 +1,5 @@
// This file is part of MinIO Console Server
-// Copyright (c) 2021 MinIO, Inc.
+// Copyright (c) 2022 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
@@ -14,7 +14,7 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see .
-package cluster
+package utils
import (
"io"
diff --git a/pkg/utils/version.go b/pkg/utils/version.go
new file mode 100644
index 000000000..10498da75
--- /dev/null
+++ b/pkg/utils/version.go
@@ -0,0 +1,51 @@
+// This file is part of MinIO Console Server
+// Copyright (c) 2022 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 .
+
+package utils
+
+import (
+ "errors"
+ "fmt"
+ "io/ioutil"
+ "regexp"
+)
+
+var (
+ ErrCantDetermineMinIOImage = errors.New("can't determine MinIO Image")
+)
+
+// getLatestMinIOImage returns the latest docker image for MinIO if found on the internet
+func GetLatestMinIOImage(client HTTPClientI) (*string, error) {
+ resp, err := client.Get("https://dl.min.io/server/minio/release/linux-amd64/")
+ if err != nil {
+ return nil, err
+ }
+ defer resp.Body.Close()
+
+ body, err := ioutil.ReadAll(resp.Body)
+ if err != nil {
+ return nil, err
+ }
+ var re = regexp.MustCompile(`minio\.(RELEASE.*?Z)"`)
+ // look for a single match
+ matches := re.FindAllStringSubmatch(string(body), 1)
+ for i := range matches {
+ release := matches[i][1]
+ dockerImage := fmt.Sprintf("minio/minio:%s", release)
+ return &dockerImage, nil
+ }
+ return nil, ErrCantDetermineMinIOImage
+}
diff --git a/portal-ui/public/images/background-wave-orig.svg b/portal-ui/public/images/background-wave-orig.svg
new file mode 100644
index 000000000..24c8f695f
--- /dev/null
+++ b/portal-ui/public/images/background-wave-orig.svg
@@ -0,0 +1,1385 @@
+
diff --git a/portal-ui/public/images/background.svg b/portal-ui/public/images/background.svg
new file mode 100644
index 000000000..3c75f0f3a
--- /dev/null
+++ b/portal-ui/public/images/background.svg
@@ -0,0 +1,9 @@
+
diff --git a/portal-ui/src/icons/GithubIcon.tsx b/portal-ui/src/icons/GithubIcon.tsx
new file mode 100644
index 000000000..3818c5164
--- /dev/null
+++ b/portal-ui/src/icons/GithubIcon.tsx
@@ -0,0 +1,36 @@
+// This file is part of MinIO Console Server
+// Copyright (c) 2022 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 .
+
+import * as React from "react";
+import { SVGProps } from "react";
+
+const GithubIcon = (props: SVGProps) => (
+
+);
+
+export default GithubIcon;
diff --git a/portal-ui/src/icons/LockFilledIcon.tsx b/portal-ui/src/icons/LockFilledIcon.tsx
new file mode 100644
index 000000000..d3952a19c
--- /dev/null
+++ b/portal-ui/src/icons/LockFilledIcon.tsx
@@ -0,0 +1,37 @@
+// This file is part of MinIO Console Server
+// Copyright (c) 2021 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 .
+
+import * as React from "react";
+import { SVGProps } from "react";
+
+const LockFilledIcon = (props: SVGProps) => (
+
+);
+
+export default LockFilledIcon;
diff --git a/portal-ui/src/icons/UsersFilledIcon.tsx b/portal-ui/src/icons/UsersFilledIcon.tsx
new file mode 100644
index 000000000..c1e6122e6
--- /dev/null
+++ b/portal-ui/src/icons/UsersFilledIcon.tsx
@@ -0,0 +1,58 @@
+// This file is part of MinIO Console Server
+// Copyright (c) 2021 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 .
+
+import * as React from "react";
+import { SVGProps } from "react";
+
+const UserFilledIcon = (props: SVGProps) => (
+
+);
+
+export default UserFilledIcon;
diff --git a/portal-ui/src/screens/LoginPage/LoginPage.tsx b/portal-ui/src/screens/LoginPage/LoginPage.tsx
index 22dcaf21b..ee40ba43f 100644
--- a/portal-ui/src/screens/LoginPage/LoginPage.tsx
+++ b/portal-ui/src/screens/LoginPage/LoginPage.tsx
@@ -20,7 +20,6 @@ import {
CircularProgress,
InputAdornment,
LinearProgress,
- Paper,
TextFieldProps,
} from "@mui/material";
import { Theme } from "@mui/material/styles";
@@ -39,56 +38,97 @@ import history from "../../history";
import RefreshIcon from "../../icons/RefreshIcon";
import MainError from "../Console/Common/MainError/MainError";
import { encodeFileName } from "../../common/utils";
-import { LockIcon, LoginMinIOLogo, UsersIcon } from "../../icons";
+import {
+ ArrowRightIcon,
+ DocumentationIcon,
+ DownloadIcon,
+ LockIcon,
+ LoginMinIOLogo,
+ MinIOTierIconXs,
+} from "../../icons";
import { spacingUtils } from "../Console/Common/FormComponents/common/styleLibrary";
import CssBaseline from "@mui/material/CssBaseline";
+import LockFilledIcon from "../../icons/LockFilledIcon";
+import UserFilledIcon from "../../icons/UsersFilledIcon";
+import { SupportMenuIcon } from "../../icons/SidebarMenus";
+import GithubIcon from "../../icons/GithubIcon";
+import clsx from "clsx";
const styles = (theme: Theme) =>
createStyles({
+ root: {
+ backgroundImage: `url('/images/background-wave-orig.svg'), url('/images/background.svg')`,
+ backgroundPosition: "center 250px, center center",
+ backgroundRepeat: "no-repeat",
+ backgroundSize: "2547px 980px,cover",
+ backgroundBlendMode: "color-dodge",
+ position: "absolute",
+ top: 0,
+ left: 0,
+ width: "100%",
+ height: "100%",
+ },
form: {
width: "100%", // Fix IE 11 issue.
},
submit: {
- margin: "30px 0px 16px",
+ margin: "30px 0px 8px",
height: 40,
+ width: "100%",
boxShadow: "none",
padding: "16px 30px",
},
- loginPage: {
- height: "100%",
- display: "flex",
- flexFlow: "column",
- alignItems: "stretch",
- position: "relative",
- padding: 84,
-
- "@media (max-width: 900px)": {
- padding: 0,
+ learnMore: {
+ textAlign: "center",
+ fontSize: 10,
+ "& a": {
+ color: "#2781B0",
+ },
+ "& .min-icon": {
+ marginLeft: 12,
+ marginTop: 2,
+ width: 10,
},
},
- shadowBox: {
- boxShadow:
- "rgba(0, 0, 0, 0) 0px 0px 0px 0px, rgba(0, 0, 0, 0) 0px 0px 0px 0px, rgba(0, 0, 0, 0.125) 0px 15px 50px 0px",
+ separator: {
+ marginLeft: 8,
+ marginRight: 8,
+ },
+ linkHolder: {
+ marginTop: 20,
+ },
+ miniLinks: {
+ margin: "auto",
+ fontSize: 10,
+ textAlign: "center",
+ color: "#B2DEF5",
+ "& a": {
+ color: "#B2DEF5",
+ textDecoration: "none",
+ },
+ "& .min-icon": {
+ height: 10,
+ color: "#B2DEF5",
+ },
+ },
+ miniLogo: {
+ marginTop: 8,
+ "& .min-icon": {
+ height: 12,
+ paddingTop: 2,
+ },
+ },
+ loginPage: {
height: "100%",
+ maxWidth: 360,
+ margin: "auto",
},
loginContainer: {
- flex: 1,
- height: "100%",
-
"& .right-items": {
- padding: 50,
- flex: 1,
- height: "100%",
- display: "flex",
- flexFlow: "column",
- alignItems: "center",
- justifyContent: "center",
- maxWidth: "33%",
-
- "@media (max-width: 900px)": {
- maxWidth: "100%",
- margin: "auto",
- },
+ backgroundColor: "white",
+ borderRadius: 3,
+ boxShadow: "6px 6px 50",
+ padding: 20,
},
"& .consoleTextBanner": {
fontWeight: 300,
@@ -101,8 +141,6 @@ const styles = (theme: Theme) =>
display: "flex",
justifyContent: "flex-start",
margin: "auto",
- flexFlow: "column",
- background: "linear-gradient(120deg,#081c42,#073052)",
"& .logoLine": {
display: "flex",
@@ -112,21 +150,8 @@ const styles = (theme: Theme) =>
},
"& .left-items": {
margin: "auto",
- textAlign: "left",
- paddingRight: 240,
- paddingBottom: 200,
- "@media (max-width: 1400px)": {
- paddingBottom: 120,
- paddingRight: 50,
- },
- "@media (max-width: 900px)": {
- paddingBottom: 0,
- paddingRight: 0,
- },
- "@media (max-width: 600px)": {
- paddingBottom: 0,
- paddingRight: 0,
- },
+ paddingTop: 100,
+ paddingBottom: 60,
},
"& .left-logo": {
"& .min-icon": {
@@ -136,27 +161,16 @@ const styles = (theme: Theme) =>
marginBottom: 10,
},
"& .text-line1": {
- font: " 100 70px 'Lato'",
-
- "@media (max-width: 600px)": {
- fontSize: 35,
- },
- "@media (max-width: 800px)": {
- fontSize: 45,
- },
+ font: " 100 44px 'Lato'",
},
"& .text-line2": {
- fontSize: 100,
+ fontSize: 80,
fontWeight: 100,
textTransform: "uppercase",
- "@media (max-width: 600px)": {
- fontSize: 35,
- marginLeft: 0,
- },
- "@media (max-width: 800px)": {
- fontSize: 55,
- marginLeft: 0,
- },
+ },
+ "& .text-line3": {
+ fontSize: 14,
+ fontWeight: "bold",
},
"& .logo-console": {
display: "flex",
@@ -227,11 +241,13 @@ const inputStyles = makeStyles((theme: Theme) =>
"& .MuiOutlinedInput-root": {
paddingLeft: 0,
"& svg": {
- height: 16,
+ marginLeft: 4,
+ height: 14,
color: theme.palette.primary.main,
},
"& input": {
- padding: 5,
+ padding: 10,
+ fontSize: 14,
paddingLeft: 0,
"&::placeholder": {
fontSize: 12,
@@ -240,15 +256,8 @@ const inputStyles = makeStyles((theme: Theme) =>
padding: 10,
},
},
- "& fieldset": {
- border: "none", // default
- borderBottom: "1px solid #EAEAEA",
- borderRadius: 0,
- },
- "&.Mui-focused fieldset": {
- borderBottom: "1px solid #000000",
- borderRadius: 0,
- },
+ "& fieldset": {},
+
"& fieldset:hover": {
borderBottom: "2px solid #000000",
borderRadius: 0,
@@ -311,6 +320,9 @@ const Login = ({
const [loadingFetchConfiguration, setLoadingFetchConfiguration] =
useState(true);
+ const [latestMinIOVersion, setLatestMinIOVersion] = useState("");
+ const [loadingVersion, setLoadingVersion] = useState(true);
+
const loginStrategyEndpoints: LoginStrategyRoutes = {
form: "/api/v1/login",
"service-account": "/api/v1/login/operator",
@@ -370,6 +382,45 @@ const Login = ({
}
}, [loadingFetchConfiguration, setErrorSnackMessage]);
+ useEffect(() => {
+ if (loadingVersion) {
+ api
+ .invoke("GET", "/api/v1/check-version")
+ .then(
+ ({
+ current_version,
+ latest_version,
+ }: {
+ current_version: string;
+ latest_version: string;
+ }) => {
+ setLatestMinIOVersion(latest_version);
+ setLoadingVersion(false);
+ }
+ )
+ .catch((err: ErrorResponseHandler) => {
+ // try the operator version
+ api
+ .invoke("GET", "/api/v1/check-operator-version")
+ .then(
+ ({
+ current_version,
+ latest_version,
+ }: {
+ current_version: string;
+ latest_version: string;
+ }) => {
+ setLatestMinIOVersion(latest_version);
+ setLoadingVersion(false);
+ }
+ )
+ .catch((err: ErrorResponseHandler) => {
+ setLoadingVersion(false);
+ });
+ });
+ }
+ }, [loadingVersion, setLoadingVersion, setLatestMinIOVersion]);
+
let loginComponent = null;
switch (loginStrategy.loginStrategy) {
@@ -398,7 +449,7 @@ const Login = ({
position="start"
className={classes.iconColor}
>
-
+
),
}}
@@ -425,7 +476,7 @@ const Login = ({
position="start"
className={classes.iconColor}
>
-
+
),
}}
@@ -556,28 +607,83 @@ const Login = ({
: "Console";
return (
-
+
);
};
diff --git a/restapi/admin_subnet.go b/restapi/admin_subnet.go
index a1561def3..87517717d 100644
--- a/restapi/admin_subnet.go
+++ b/restapi/admin_subnet.go
@@ -24,8 +24,9 @@ import (
"net/http"
"net/url"
+ "github.com/minio/console/pkg/utils"
+
"github.com/go-openapi/runtime/middleware"
- "github.com/minio/console/cluster"
"github.com/minio/console/models"
"github.com/minio/console/pkg/subnet"
"github.com/minio/console/restapi/operations"
@@ -99,7 +100,7 @@ func SubnetRegisterWithAPIKey(ctx context.Context, minioClient MinioAdmin, apiKe
return true, nil
}
-func SubnetLogin(client cluster.HTTPClientI, username, password string) (string, string, error) {
+func SubnetLogin(client utils.HTTPClientI, username, password string) (string, string, error) {
tokens, err := subnet.Login(client, username, password)
if err != nil {
return "", "", err
@@ -159,7 +160,7 @@ type SubnetRegistration struct {
Organizations []models.SubnetOrganization
}
-func SubnetLoginWithMFA(client cluster.HTTPClientI, username, mfaToken, otp string) (*models.SubnetLoginResponse, error) {
+func SubnetLoginWithMFA(client utils.HTTPClientI, username, mfaToken, otp string) (*models.SubnetLoginResponse, error) {
tokens, err := subnet.LoginWithMFA(client, username, mfaToken, otp)
if err != nil {
return nil, err
@@ -178,7 +179,7 @@ func SubnetLoginWithMFA(client cluster.HTTPClientI, username, mfaToken, otp stri
}
// GetSubnetHTTPClient will return a client with proxy if configured, otherwise will return the default console http client
-func GetSubnetHTTPClient(ctx context.Context, minioClient MinioAdmin) (*cluster.HTTPClient, error) {
+func GetSubnetHTTPClient(ctx context.Context, minioClient MinioAdmin) (*utils.HTTPClient, error) {
var subnetHTTPClient *http.Client
var proxy string
envProxy := getSubnetProxy()
@@ -204,7 +205,7 @@ func GetSubnetHTTPClient(ctx context.Context, minioClient MinioAdmin) (*cluster.
} else {
subnetHTTPClient = GetConsoleHTTPClient()
}
- clientI := &cluster.HTTPClient{
+ clientI := &utils.HTTPClient{
Client: subnetHTTPClient,
}
return clientI, nil
@@ -254,7 +255,7 @@ func GetSubnetKeyFromMinIOConfig(ctx context.Context, minioClient MinioAdmin) (*
return &res, nil
}
-func GetSubnetRegister(ctx context.Context, minioClient MinioAdmin, httpClient cluster.HTTPClientI, params admin_api.SubnetRegisterParams) error {
+func GetSubnetRegister(ctx context.Context, minioClient MinioAdmin, httpClient utils.HTTPClientI, params admin_api.SubnetRegisterParams) error {
serverInfo, err := minioClient.serverInfo(ctx)
if err != nil {
return err
@@ -308,7 +309,7 @@ func GetSubnetInfoResponse(session *models.Principal) (*models.License, *models.
if subnetTokens.APIKey == "" {
return nil, prepareError(errLicenseNotFound)
}
- client := &cluster.HTTPClient{
+ client := &utils.HTTPClient{
Client: GetConsoleHTTPClient(),
}
licenseInfo, err := subnet.ParseLicense(client, subnetTokens.License)
diff --git a/restapi/configure_console.go b/restapi/configure_console.go
index f07e8f39e..44d918b45 100644
--- a/restapi/configure_console.go
+++ b/restapi/configure_console.go
@@ -108,6 +108,8 @@ func configureAPI(api *operations.ConsoleAPI) http.Handler {
registerProfilingHandler(api)
// Register session handlers
registerSessionHandlers(api)
+ // Register version handlers
+ registerVersionHandlers(api)
// Register admin info handlers
registerAdminInfoHandlers(api)
// Register admin arns handlers
diff --git a/restapi/embedded_spec.go b/restapi/embedded_spec.go
index 6d1137a02..2ff327be1 100644
--- a/restapi/embedded_spec.go
+++ b/restapi/embedded_spec.go
@@ -2235,6 +2235,30 @@ func init() {
}
}
},
+ "/check-version": {
+ "get": {
+ "security": [],
+ "tags": [
+ "UserAPI"
+ ],
+ "summary": "Checks the current MinIO version against the latest",
+ "operationId": "CheckMinIOVersion",
+ "responses": {
+ "200": {
+ "description": "A successful response.",
+ "schema": {
+ "$ref": "#/definitions/checkVersionResponse"
+ }
+ },
+ "default": {
+ "description": "Generic error response.",
+ "schema": {
+ "$ref": "#/definitions/error"
+ }
+ }
+ }
+ }
+ },
"/configs": {
"get": {
"tags": [
@@ -4550,6 +4574,17 @@ func init() {
}
}
},
+ "checkVersionResponse": {
+ "type": "object",
+ "properties": {
+ "current_version": {
+ "type": "string"
+ },
+ "latest_version": {
+ "type": "string"
+ }
+ }
+ },
"configDescription": {
"type": "object",
"properties": {
@@ -8696,6 +8731,30 @@ func init() {
}
}
},
+ "/check-version": {
+ "get": {
+ "security": [],
+ "tags": [
+ "UserAPI"
+ ],
+ "summary": "Checks the current MinIO version against the latest",
+ "operationId": "CheckMinIOVersion",
+ "responses": {
+ "200": {
+ "description": "A successful response.",
+ "schema": {
+ "$ref": "#/definitions/checkVersionResponse"
+ }
+ },
+ "default": {
+ "description": "Generic error response.",
+ "schema": {
+ "$ref": "#/definitions/error"
+ }
+ }
+ }
+ }
+ },
"/configs": {
"get": {
"tags": [
@@ -11137,6 +11196,17 @@ func init() {
}
}
},
+ "checkVersionResponse": {
+ "type": "object",
+ "properties": {
+ "current_version": {
+ "type": "string"
+ },
+ "latest_version": {
+ "type": "string"
+ }
+ }
+ },
"configDescription": {
"type": "object",
"properties": {
diff --git a/restapi/operations/console_api.go b/restapi/operations/console_api.go
index eaecbb587..56ebde018 100644
--- a/restapi/operations/console_api.go
+++ b/restapi/operations/console_api.go
@@ -110,6 +110,9 @@ func NewConsoleAPI(spec *loads.Document) *ConsoleAPI {
AdminAPIChangeUserPasswordHandler: admin_api.ChangeUserPasswordHandlerFunc(func(params admin_api.ChangeUserPasswordParams, principal *models.Principal) middleware.Responder {
return middleware.NotImplemented("operation admin_api.ChangeUserPassword has not yet been implemented")
}),
+ UserAPICheckMinIOVersionHandler: user_api.CheckMinIOVersionHandlerFunc(func(params user_api.CheckMinIOVersionParams) middleware.Responder {
+ return middleware.NotImplemented("operation user_api.CheckMinIOVersion has not yet been implemented")
+ }),
AdminAPIConfigInfoHandler: admin_api.ConfigInfoHandlerFunc(func(params admin_api.ConfigInfoParams, principal *models.Principal) middleware.Responder {
return middleware.NotImplemented("operation admin_api.ConfigInfo has not yet been implemented")
}),
@@ -489,6 +492,8 @@ type ConsoleAPI struct {
AdminAPIBulkUpdateUsersGroupsHandler admin_api.BulkUpdateUsersGroupsHandler
// AdminAPIChangeUserPasswordHandler sets the operation handler for the change user password operation
AdminAPIChangeUserPasswordHandler admin_api.ChangeUserPasswordHandler
+ // UserAPICheckMinIOVersionHandler sets the operation handler for the check min i o version operation
+ UserAPICheckMinIOVersionHandler user_api.CheckMinIOVersionHandler
// AdminAPIConfigInfoHandler sets the operation handler for the config info operation
AdminAPIConfigInfoHandler admin_api.ConfigInfoHandler
// AdminAPICreateAUserServiceAccountHandler sets the operation handler for the create a user service account operation
@@ -817,6 +822,9 @@ func (o *ConsoleAPI) Validate() error {
if o.AdminAPIChangeUserPasswordHandler == nil {
unregistered = append(unregistered, "admin_api.ChangeUserPasswordHandler")
}
+ if o.UserAPICheckMinIOVersionHandler == nil {
+ unregistered = append(unregistered, "user_api.CheckMinIOVersionHandler")
+ }
if o.AdminAPIConfigInfoHandler == nil {
unregistered = append(unregistered, "admin_api.ConfigInfoHandler")
}
@@ -1276,6 +1284,10 @@ func (o *ConsoleAPI) initHandlerCache() {
if o.handlers["GET"] == nil {
o.handlers["GET"] = make(map[string]http.Handler)
}
+ o.handlers["GET"]["/check-version"] = user_api.NewCheckMinIOVersion(o.context, o.UserAPICheckMinIOVersionHandler)
+ if o.handlers["GET"] == nil {
+ o.handlers["GET"] = make(map[string]http.Handler)
+ }
o.handlers["GET"]["/configs/{name}"] = admin_api.NewConfigInfo(o.context, o.AdminAPIConfigInfoHandler)
if o.handlers["POST"] == nil {
o.handlers["POST"] = make(map[string]http.Handler)
diff --git a/restapi/operations/user_api/check_min_i_o_version.go b/restapi/operations/user_api/check_min_i_o_version.go
new file mode 100644
index 000000000..0c42eae07
--- /dev/null
+++ b/restapi/operations/user_api/check_min_i_o_version.go
@@ -0,0 +1,73 @@
+// Code generated by go-swagger; DO NOT EDIT.
+
+// This file is part of MinIO Console Server
+// Copyright (c) 2021 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 .
+//
+
+package user_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"
+)
+
+// CheckMinIOVersionHandlerFunc turns a function with the right signature into a check min i o version handler
+type CheckMinIOVersionHandlerFunc func(CheckMinIOVersionParams) middleware.Responder
+
+// Handle executing the request and returning a response
+func (fn CheckMinIOVersionHandlerFunc) Handle(params CheckMinIOVersionParams) middleware.Responder {
+ return fn(params)
+}
+
+// CheckMinIOVersionHandler interface for that can handle valid check min i o version params
+type CheckMinIOVersionHandler interface {
+ Handle(CheckMinIOVersionParams) middleware.Responder
+}
+
+// NewCheckMinIOVersion creates a new http.Handler for the check min i o version operation
+func NewCheckMinIOVersion(ctx *middleware.Context, handler CheckMinIOVersionHandler) *CheckMinIOVersion {
+ return &CheckMinIOVersion{Context: ctx, Handler: handler}
+}
+
+/* CheckMinIOVersion swagger:route GET /check-version UserAPI checkMinIOVersion
+
+Checks the current MinIO version against the latest
+
+*/
+type CheckMinIOVersion struct {
+ Context *middleware.Context
+ Handler CheckMinIOVersionHandler
+}
+
+func (o *CheckMinIOVersion) ServeHTTP(rw http.ResponseWriter, r *http.Request) {
+ route, rCtx, _ := o.Context.RouteInfo(r)
+ if rCtx != nil {
+ *r = *rCtx
+ }
+ var Params = NewCheckMinIOVersionParams()
+ 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) // actually handle the request
+ o.Context.Respond(rw, r, route.Produces, route, res)
+
+}
diff --git a/restapi/operations/user_api/check_min_i_o_version_parameters.go b/restapi/operations/user_api/check_min_i_o_version_parameters.go
new file mode 100644
index 000000000..dc2f9704d
--- /dev/null
+++ b/restapi/operations/user_api/check_min_i_o_version_parameters.go
@@ -0,0 +1,63 @@
+// Code generated by go-swagger; DO NOT EDIT.
+
+// This file is part of MinIO Console Server
+// Copyright (c) 2021 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 .
+//
+
+package user_api
+
+// This file was generated by the swagger tool.
+// Editing this file might prove futile when you re-run the swagger generate command
+
+import (
+ "net/http"
+
+ "github.com/go-openapi/errors"
+ "github.com/go-openapi/runtime/middleware"
+)
+
+// NewCheckMinIOVersionParams creates a new CheckMinIOVersionParams object
+//
+// There are no default values defined in the spec.
+func NewCheckMinIOVersionParams() CheckMinIOVersionParams {
+
+ return CheckMinIOVersionParams{}
+}
+
+// CheckMinIOVersionParams contains all the bound params for the check min i o version operation
+// typically these are obtained from a http.Request
+//
+// swagger:parameters CheckMinIOVersion
+type CheckMinIOVersionParams struct {
+
+ // HTTP Request Object
+ HTTPRequest *http.Request `json:"-"`
+}
+
+// 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 NewCheckMinIOVersionParams() beforehand.
+func (o *CheckMinIOVersionParams) BindRequest(r *http.Request, route *middleware.MatchedRoute) error {
+ var res []error
+
+ o.HTTPRequest = r
+
+ if len(res) > 0 {
+ return errors.CompositeValidationError(res...)
+ }
+ return nil
+}
diff --git a/restapi/operations/user_api/check_min_i_o_version_responses.go b/restapi/operations/user_api/check_min_i_o_version_responses.go
new file mode 100644
index 000000000..1f318bd5f
--- /dev/null
+++ b/restapi/operations/user_api/check_min_i_o_version_responses.go
@@ -0,0 +1,133 @@
+// Code generated by go-swagger; DO NOT EDIT.
+
+// This file is part of MinIO Console Server
+// Copyright (c) 2021 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 .
+//
+
+package user_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"
+)
+
+// CheckMinIOVersionOKCode is the HTTP code returned for type CheckMinIOVersionOK
+const CheckMinIOVersionOKCode int = 200
+
+/*CheckMinIOVersionOK A successful response.
+
+swagger:response checkMinIOVersionOK
+*/
+type CheckMinIOVersionOK struct {
+
+ /*
+ In: Body
+ */
+ Payload *models.CheckVersionResponse `json:"body,omitempty"`
+}
+
+// NewCheckMinIOVersionOK creates CheckMinIOVersionOK with default headers values
+func NewCheckMinIOVersionOK() *CheckMinIOVersionOK {
+
+ return &CheckMinIOVersionOK{}
+}
+
+// WithPayload adds the payload to the check min i o version o k response
+func (o *CheckMinIOVersionOK) WithPayload(payload *models.CheckVersionResponse) *CheckMinIOVersionOK {
+ o.Payload = payload
+ return o
+}
+
+// SetPayload sets the payload to the check min i o version o k response
+func (o *CheckMinIOVersionOK) SetPayload(payload *models.CheckVersionResponse) {
+ o.Payload = payload
+}
+
+// WriteResponse to the client
+func (o *CheckMinIOVersionOK) 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
+ }
+ }
+}
+
+/*CheckMinIOVersionDefault Generic error response.
+
+swagger:response checkMinIOVersionDefault
+*/
+type CheckMinIOVersionDefault struct {
+ _statusCode int
+
+ /*
+ In: Body
+ */
+ Payload *models.Error `json:"body,omitempty"`
+}
+
+// NewCheckMinIOVersionDefault creates CheckMinIOVersionDefault with default headers values
+func NewCheckMinIOVersionDefault(code int) *CheckMinIOVersionDefault {
+ if code <= 0 {
+ code = 500
+ }
+
+ return &CheckMinIOVersionDefault{
+ _statusCode: code,
+ }
+}
+
+// WithStatusCode adds the status to the check min i o version default response
+func (o *CheckMinIOVersionDefault) WithStatusCode(code int) *CheckMinIOVersionDefault {
+ o._statusCode = code
+ return o
+}
+
+// SetStatusCode sets the status to the check min i o version default response
+func (o *CheckMinIOVersionDefault) SetStatusCode(code int) {
+ o._statusCode = code
+}
+
+// WithPayload adds the payload to the check min i o version default response
+func (o *CheckMinIOVersionDefault) WithPayload(payload *models.Error) *CheckMinIOVersionDefault {
+ o.Payload = payload
+ return o
+}
+
+// SetPayload sets the payload to the check min i o version default response
+func (o *CheckMinIOVersionDefault) SetPayload(payload *models.Error) {
+ o.Payload = payload
+}
+
+// WriteResponse to the client
+func (o *CheckMinIOVersionDefault) 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
+ }
+ }
+}
diff --git a/restapi/operations/user_api/check_min_i_o_version_urlbuilder.go b/restapi/operations/user_api/check_min_i_o_version_urlbuilder.go
new file mode 100644
index 000000000..1f5e2d5ef
--- /dev/null
+++ b/restapi/operations/user_api/check_min_i_o_version_urlbuilder.go
@@ -0,0 +1,104 @@
+// Code generated by go-swagger; DO NOT EDIT.
+
+// This file is part of MinIO Console Server
+// Copyright (c) 2021 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 .
+//
+
+package user_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"
+)
+
+// CheckMinIOVersionURL generates an URL for the check min i o version operation
+type CheckMinIOVersionURL struct {
+ _basePath string
+}
+
+// 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 *CheckMinIOVersionURL) WithBasePath(bp string) *CheckMinIOVersionURL {
+ 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 *CheckMinIOVersionURL) SetBasePath(bp string) {
+ o._basePath = bp
+}
+
+// Build a url path and query string
+func (o *CheckMinIOVersionURL) Build() (*url.URL, error) {
+ var _result url.URL
+
+ var _path = "/check-version"
+
+ _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 *CheckMinIOVersionURL) 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 *CheckMinIOVersionURL) String() string {
+ return o.Must(o.Build()).String()
+}
+
+// BuildFull builds a full url with scheme, host, path and query string
+func (o *CheckMinIOVersionURL) BuildFull(scheme, host string) (*url.URL, error) {
+ if scheme == "" {
+ return nil, errors.New("scheme is required for a full url on CheckMinIOVersionURL")
+ }
+ if host == "" {
+ return nil, errors.New("host is required for a full url on CheckMinIOVersionURL")
+ }
+
+ 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 *CheckMinIOVersionURL) StringFull(scheme, host string) string {
+ return o.Must(o.BuildFull(scheme, host)).String()
+}
diff --git a/restapi/user_version.go b/restapi/user_version.go
new file mode 100644
index 000000000..5513ddb41
--- /dev/null
+++ b/restapi/user_version.go
@@ -0,0 +1,52 @@
+// This file is part of MinIO Console Server
+// Copyright (c) 2022 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 .
+
+package restapi
+
+import (
+ "net/http"
+ "time"
+
+ "github.com/go-openapi/runtime/middleware"
+ "github.com/minio/console/models"
+ "github.com/minio/console/pkg/utils"
+ "github.com/minio/console/restapi/operations"
+ "github.com/minio/console/restapi/operations/user_api"
+)
+
+func registerVersionHandlers(api *operations.ConsoleAPI) {
+ api.UserAPICheckMinIOVersionHandler = user_api.CheckMinIOVersionHandlerFunc(func(params user_api.CheckMinIOVersionParams) middleware.Responder {
+ versionResponse, err := getVersionResponse()
+ if err != nil {
+ return user_api.NewCheckMinIOVersionDefault(int(err.Code)).WithPayload(err)
+ }
+ return user_api.NewCheckMinIOVersionOK().WithPayload(versionResponse)
+ })
+}
+
+// getSessionResponse parse the token of the current session and returns a list of allowed actions to render in the UI
+func getVersionResponse() (*models.CheckVersionResponse, *models.Error) {
+ ver, err := utils.GetLatestMinIOImage(&utils.HTTPClient{
+ Client: &http.Client{
+ Timeout: 15 * time.Second,
+ }})
+ if err != nil {
+ return nil, prepareError(err)
+ }
+ return &models.CheckVersionResponse{
+ LatestVersion: *ver,
+ }, nil
+}
diff --git a/swagger-console.yml b/swagger-console.yml
index 8daf31bc4..4e68b8d16 100644
--- a/swagger-console.yml
+++ b/swagger-console.yml
@@ -109,6 +109,23 @@ paths:
tags:
- UserAPI
+ /check-version:
+ get:
+ summary: Checks the current MinIO version against the latest
+ operationId: CheckMinIOVersion
+ responses:
+ 200:
+ description: A successful response.
+ schema:
+ $ref: "#/definitions/checkVersionResponse"
+ default:
+ description: Generic error response.
+ schema:
+ $ref: "#/definitions/error"
+ security: [ ]
+ tags:
+ - UserAPI
+
/account/change-password:
post:
summary: Change password of currently logged in user.
@@ -4446,3 +4463,10 @@ definitions:
type: string
shortName:
type: string
+ checkVersionResponse:
+ type: object
+ properties:
+ current_version:
+ type: string
+ latest_version:
+ type: string
diff --git a/swagger-operator.yml b/swagger-operator.yml
index a83ba4445..104ed3855 100644
--- a/swagger-operator.yml
+++ b/swagger-operator.yml
@@ -110,6 +110,23 @@ paths:
tags:
- UserAPI
+ /check-version:
+ get:
+ summary: Checks the current Operator version against the latest
+ operationId: CheckMinIOVersion”
+ responses:
+ 200:
+ description: A successful response.
+ schema:
+ $ref: "#/definitions/checkOperatorVersionResponse"
+ default:
+ description: Generic error response.
+ schema:
+ $ref: "#/definitions/error"
+ security: [ ]
+ tags:
+ - UserAPI
+
/subscription/info:
get:
summary: Subscription info
@@ -2838,26 +2855,11 @@ definitions:
max_allocatable_mem:
type: integer
format: int64
- label:
- type: object
- properties:
- key:
- type: string
- value:
- type: string
- annotation:
+ checkOperatorVersionResponse:
type: object
properties:
- key:
+ current_version:
type: string
- value:
- type: string
-
- nodeSelector:
- type: object
- properties:
- key:
- type: string
- value:
+ latest_version:
type: string