Skip to content

Commit a2dce5f

Browse files
authored
Show error when editing tenant Yaml (#733)
* Show error when editing tenant Yaml Also adds error line when we prepareError() Signed-off-by: Daniel Valdivia <hola@danielvaldivia.com> * make certain metadata fields editable Signed-off-by: Daniel Valdivia <hola@danielvaldivia.com>
1 parent 3a7da72 commit a2dce5f

File tree

8 files changed

+56
-21
lines changed

8 files changed

+56
-21
lines changed

portal-ui/build/asset-manifest.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
{
22
"files": {
33
"main.css": "/static/css/main.a19f3d53.chunk.css",
4-
"main.js": "/static/js/main.b74c83f1.chunk.js",
5-
"main.js.map": "/static/js/main.b74c83f1.chunk.js.map",
4+
"main.js": "/static/js/main.e1a90e12.chunk.js",
5+
"main.js.map": "/static/js/main.e1a90e12.chunk.js.map",
66
"runtime-main.js": "/static/js/runtime-main.f48e99e5.js",
77
"runtime-main.js.map": "/static/js/runtime-main.f48e99e5.js.map",
88
"static/css/2.f324abd6.chunk.css": "/static/css/2.f324abd6.chunk.css",
@@ -20,6 +20,6 @@
2020
"static/css/2.f324abd6.chunk.css",
2121
"static/js/2.26f9f812.chunk.js",
2222
"static/css/main.a19f3d53.chunk.css",
23-
"static/js/main.b74c83f1.chunk.js"
23+
"static/js/main.e1a90e12.chunk.js"
2424
]
2525
}

portal-ui/build/index.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
<!doctype html><html lang="en"><head><meta charset="utf-8"/><meta name="viewport" content="width=device-width,initial-scale=1"/><meta name="theme-color" content="#000000"/><meta name="description" content="MinIO Console"/><link href="https://fonts.googleapis.com/css2?family=Lato:wght@400;500;700;900&display=swap" rel="stylesheet"/><link rel="apple-touch-icon" sizes="180x180" href="/apple-icon-180x180.png"/><link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png"/><link rel="icon" type="image/png" sizes="96x96" href="/favicon-96x96.png"/><link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png"/><link rel="manifest" href="/manifest.json"/><link rel="mask-icon" href="/safari-pinned-tab.svg" color="#3a4e54"/><title>MinIO Console</title><link href="/static/css/2.f324abd6.chunk.css" rel="stylesheet"><link href="/static/css/main.a19f3d53.chunk.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div><script>!function(e){function r(r){for(var n,l,i=r[0],a=r[1],p=r[2],c=0,s=[];c<i.length;c++)l=i[c],Object.prototype.hasOwnProperty.call(o,l)&&o[l]&&s.push(o[l][0]),o[l]=0;for(n in a)Object.prototype.hasOwnProperty.call(a,n)&&(e[n]=a[n]);for(f&&f(r);s.length;)s.shift()();return u.push.apply(u,p||[]),t()}function t(){for(var e,r=0;r<u.length;r++){for(var t=u[r],n=!0,i=1;i<t.length;i++){var a=t[i];0!==o[a]&&(n=!1)}n&&(u.splice(r--,1),e=l(l.s=t[0]))}return e}var n={},o={1:0},u=[];function l(r){if(n[r])return n[r].exports;var t=n[r]={i:r,l:!1,exports:{}};return e[r].call(t.exports,t,t.exports,l),t.l=!0,t.exports}l.m=e,l.c=n,l.d=function(e,r,t){l.o(e,r)||Object.defineProperty(e,r,{enumerable:!0,get:t})},l.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},l.t=function(e,r){if(1&r&&(e=l(e)),8&r)return e;if(4&r&&"object"==typeof e&&e&&e.__esModule)return e;var t=Object.create(null);if(l.r(t),Object.defineProperty(t,"default",{enumerable:!0,value:e}),2&r&&"string"!=typeof e)for(var n in e)l.d(t,n,function(r){return e[r]}.bind(null,n));return t},l.n=function(e){var r=e&&e.__esModule?function(){return e.default}:function(){return e};return l.d(r,"a",r),r},l.o=function(e,r){return Object.prototype.hasOwnProperty.call(e,r)},l.p="/";var i=this["webpackJsonpportal-ui"]=this["webpackJsonpportal-ui"]||[],a=i.push.bind(i);i.push=r,i=i.slice();for(var p=0;p<i.length;p++)r(i[p]);var f=a;t()}([])</script><script src="/static/js/2.26f9f812.chunk.js"></script><script src="/static/js/main.b74c83f1.chunk.js"></script></body></html>
1+
<!doctype html><html lang="en"><head><meta charset="utf-8"/><meta name="viewport" content="width=device-width,initial-scale=1"/><meta name="theme-color" content="#000000"/><meta name="description" content="MinIO Console"/><link href="https://fonts.googleapis.com/css2?family=Lato:wght@400;500;700;900&display=swap" rel="stylesheet"/><link rel="apple-touch-icon" sizes="180x180" href="/apple-icon-180x180.png"/><link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png"/><link rel="icon" type="image/png" sizes="96x96" href="/favicon-96x96.png"/><link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png"/><link rel="manifest" href="/manifest.json"/><link rel="mask-icon" href="/safari-pinned-tab.svg" color="#3a4e54"/><title>MinIO Console</title><link href="/static/css/2.f324abd6.chunk.css" rel="stylesheet"><link href="/static/css/main.a19f3d53.chunk.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div><script>!function(e){function r(r){for(var n,l,i=r[0],a=r[1],p=r[2],c=0,s=[];c<i.length;c++)l=i[c],Object.prototype.hasOwnProperty.call(o,l)&&o[l]&&s.push(o[l][0]),o[l]=0;for(n in a)Object.prototype.hasOwnProperty.call(a,n)&&(e[n]=a[n]);for(f&&f(r);s.length;)s.shift()();return u.push.apply(u,p||[]),t()}function t(){for(var e,r=0;r<u.length;r++){for(var t=u[r],n=!0,i=1;i<t.length;i++){var a=t[i];0!==o[a]&&(n=!1)}n&&(u.splice(r--,1),e=l(l.s=t[0]))}return e}var n={},o={1:0},u=[];function l(r){if(n[r])return n[r].exports;var t=n[r]={i:r,l:!1,exports:{}};return e[r].call(t.exports,t,t.exports,l),t.l=!0,t.exports}l.m=e,l.c=n,l.d=function(e,r,t){l.o(e,r)||Object.defineProperty(e,r,{enumerable:!0,get:t})},l.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},l.t=function(e,r){if(1&r&&(e=l(e)),8&r)return e;if(4&r&&"object"==typeof e&&e&&e.__esModule)return e;var t=Object.create(null);if(l.r(t),Object.defineProperty(t,"default",{enumerable:!0,value:e}),2&r&&"string"!=typeof e)for(var n in e)l.d(t,n,function(r){return e[r]}.bind(null,n));return t},l.n=function(e){var r=e&&e.__esModule?function(){return e.default}:function(){return e};return l.d(r,"a",r),r},l.o=function(e,r){return Object.prototype.hasOwnProperty.call(e,r)},l.p="/";var i=this["webpackJsonpportal-ui"]=this["webpackJsonpportal-ui"]||[],a=i.push.bind(i);i.push=r,i=i.slice();for(var p=0;p<i.length;p++)r(i[p]);var f=a;t()}([])</script><script src="/static/js/2.26f9f812.chunk.js"></script><script src="/static/js/main.e1a90e12.chunk.js"></script></body></html>

portal-ui/build/static/js/main.b74c83f1.chunk.js.map

Lines changed: 0 additions & 1 deletion
This file was deleted.

portal-ui/build/static/js/main.b74c83f1.chunk.js renamed to portal-ui/build/static/js/main.e1a90e12.chunk.js

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

portal-ui/build/static/js/main.e1a90e12.chunk.js.map

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

portal-ui/src/screens/Console/Tenants/TenantDetails/TenantYAML.tsx

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,11 @@ const styles = (theme: Theme) =>
4040
buttonContainer: {
4141
textAlign: "right",
4242
},
43+
errorState: {
44+
color: "#b53b4b",
45+
fontSize: 14,
46+
fontWeight: "bold",
47+
},
4348
...modalBasic,
4449
...fieldBasic,
4550
});
@@ -63,28 +68,33 @@ const TenantYAML = ({
6368
closeModalAndRefresh,
6469
tenant,
6570
namespace,
71+
setModalErrorSnackMessage,
6672
}: ITenantYAMLProps) => {
6773
const [addLoading, setAddLoading] = useState<boolean>(false);
6874
const [loading, setLoading] = useState<boolean>(false);
6975
const [tenantYaml, setTenantYaml] = useState<string>("");
76+
const [errorMessage, setErrorMessage] = useState<string>("");
7077

7178
const updateTenant = (event: React.FormEvent) => {
7279
event.preventDefault();
7380
if (addLoading) {
7481
return;
7582
}
7683
setAddLoading(true);
84+
setErrorMessage("");
7785
api
7886
.invoke("PUT", `/api/v1/namespaces/${namespace}/tenants/${tenant}/yaml`, {
7987
yaml: tenantYaml,
8088
})
8189
.then((res) => {
8290
setAddLoading(false);
8391
closeModalAndRefresh(true);
92+
setErrorMessage("");
8493
})
8594
.catch((err) => {
8695
setAddLoading(false);
87-
setModalErrorSnackMessage(err);
96+
console.log(err);
97+
setErrorMessage(err);
8898
});
8999
};
90100

@@ -98,7 +108,7 @@ const TenantYAML = ({
98108
})
99109
.catch((err: any) => {
100110
setLoading(false);
101-
setErrorSnackMessage(err);
111+
setModalErrorSnackMessage(err);
102112
});
103113
}, [tenant, namespace]);
104114

@@ -115,6 +125,9 @@ const TenantYAML = ({
115125
title={`YAML`}
116126
>
117127
{loading && <LinearProgress />}
128+
{errorMessage !== "" && (
129+
<div className={classes.errorState}>{errorMessage}</div>
130+
)}
118131
{!loading && (
119132
<form
120133
noValidate

restapi/admin_tenants.go

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1888,14 +1888,6 @@ func getTenantYAML(session *models.Principal, params admin_api.GetTenantYAMLPara
18881888
}
18891889

18901890
func getUpdateTenantYAML(session *models.Principal, params admin_api.PutTenantYAMLParams) *models.Error {
1891-
1892-
// can we parse the inbound?
1893-
//var inTenant miniov2.Tenant
1894-
//err := yaml.Unmarshal([]byte(params.Body.Yaml), &inTenant)
1895-
//if err != nil {
1896-
// return prepareError(err)
1897-
//}
1898-
18991891
// https://godoc.org/k8s.io/apimachinery/pkg/runtime#Scheme
19001892
scheme := runtime.NewScheme()
19011893

@@ -1907,7 +1899,7 @@ func getUpdateTenantYAML(session *models.Principal, params admin_api.PutTenantYA
19071899

19081900
tenantObject, _, err := deserializer.Decode([]byte(params.Body.Yaml), nil, &miniov2.Tenant{})
19091901
if err != nil {
1910-
panic(err)
1902+
return &models.Error{Code: 400, Message: swag.String(err.Error())}
19111903
}
19121904
inTenant := tenantObject.(*miniov2.Tenant)
19131905
// get Kubernetes Client
@@ -1921,12 +1913,15 @@ func getUpdateTenantYAML(session *models.Principal, params admin_api.PutTenantYA
19211913
return prepareError(err)
19221914
}
19231915
upTenant := tenant.DeepCopy()
1924-
// only replace the spec field
1916+
// only update safe fields: spec, metadata.finalizers, metadata.labels and metadata.annotations
1917+
upTenant.Labels = inTenant.Labels
1918+
upTenant.Annotations = inTenant.Annotations
1919+
upTenant.Finalizers = inTenant.Finalizers
19251920
upTenant.Spec = inTenant.Spec
19261921

19271922
_, err = opClient.MinioV2().Tenants(params.Namespace).Update(params.HTTPRequest.Context(), upTenant, metav1.UpdateOptions{})
19281923
if err != nil {
1929-
return prepareError(err)
1924+
return &models.Error{Code: 400, Message: swag.String(err.Error())}
19301925
}
19311926

19321927
return nil

restapi/error.go

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ package restapi
33
import (
44
"errors"
55
"log"
6+
"runtime"
7+
"strings"
68

79
"github.com/go-openapi/swag"
810
"github.com/minio/console/models"
@@ -45,7 +47,9 @@ func prepareError(err ...error) *models.Error {
4547
errorCode := int32(500)
4648
errorMessage := errorGeneric.Error()
4749
if len(err) > 0 {
48-
log.Print("original error: ", err[0].Error())
50+
frame := getFrame(2)
51+
fileParts := strings.Split(frame.File, "/")
52+
log.Printf("%s:%d: original error: %s", fileParts[len(fileParts)-1], frame.Line, err[0].Error())
4953
if k8sErrors.IsUnauthorized(err[0]) {
5054
errorCode = 401
5155
errorMessage = errorGenericUnauthorized.Error()
@@ -157,3 +161,26 @@ func prepareError(err ...error) *models.Error {
157161
}
158162
return &models.Error{Code: errorCode, Message: swag.String(errorMessage)}
159163
}
164+
165+
func getFrame(skipFrames int) runtime.Frame {
166+
// We need the frame at index skipFrames+2, since we never want runtime.Callers and getFrame
167+
targetFrameIndex := skipFrames + 2
168+
169+
// Set size to targetFrameIndex+2 to ensure we have room for one more caller than we need
170+
programCounters := make([]uintptr, targetFrameIndex+2)
171+
n := runtime.Callers(0, programCounters)
172+
173+
frame := runtime.Frame{Function: "unknown"}
174+
if n > 0 {
175+
frames := runtime.CallersFrames(programCounters[:n])
176+
for more, frameIndex := true, 0; more && frameIndex <= targetFrameIndex; frameIndex++ {
177+
var frameCandidate runtime.Frame
178+
frameCandidate, more = frames.Next()
179+
if frameIndex == targetFrameIndex {
180+
frame = frameCandidate
181+
}
182+
}
183+
}
184+
185+
return frame
186+
}

0 commit comments

Comments
 (0)