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 ( - +
- -
- - -
-
- -
-
Welcome to
-
{consoleText}
+
+ + +
+
+
- - - {loginComponent} - +
Welcome to
+
{consoleText}
+
Multi-Cloud Object Storage
+
-
- - + + {loginComponent} + + + + + + + +
+
); }; 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