diff --git a/docs/sources/developers/http_api/folder.md b/docs/sources/developers/http_api/folder.md index 73a9c54ba39..7a65f7fa56d 100644 --- a/docs/sources/developers/http_api/folder.md +++ b/docs/sources/developers/http_api/folder.md @@ -205,7 +205,7 @@ Status Codes: - **400** – Errors (invalid json, missing or invalid fields, etc) - **401** – Unauthorized - **403** – Access Denied -- **409** - Folder already exists +- **412** - Folder already exists ## Update folder diff --git a/pkg/api/apierrors/folder.go b/pkg/api/apierrors/folder.go index b29d5000fad..19cf5323e56 100644 --- a/pkg/api/apierrors/folder.go +++ b/pkg/api/apierrors/folder.go @@ -44,9 +44,13 @@ func ToFolderErrorResponse(err error) response.Response { return response.JSON(http.StatusPreconditionFailed, util.DynMap{"status": "version-mismatch", "message": dashboards.ErrFolderVersionMismatch.Error()}) } - // folder errors are wrapped in an error util, so this is the only way of comparing errors - if err.Error() == folder.ErrMaximumDepthReached.Error() { - return response.JSON(http.StatusBadRequest, util.DynMap{"messageId": "folder.maximum-depth-reached", "message": "Maximum nested folder depth reached"}) + if errors.Is(err, folder.ErrMaximumDepthReached) { + return response.JSON(http.StatusBadRequest, util.DynMap{"messageId": "folder.maximum-depth-reached", "message": folder.ErrMaximumDepthReached.Error()}) + } + + var statusErr *k8sErrors.StatusError + if errors.As(err, &statusErr) { + return response.Error(int(statusErr.ErrStatus.Code), statusErr.ErrStatus.Message, err) } return response.ErrOrFallback(http.StatusInternalServerError, "Folder API error", err) diff --git a/pkg/api/apierrors/folder_test.go b/pkg/api/apierrors/folder_test.go index e3d70bded31..09cd5aba16b 100644 --- a/pkg/api/apierrors/folder_test.go +++ b/pkg/api/apierrors/folder_test.go @@ -10,6 +10,8 @@ import ( "github.com/grafana/grafana/pkg/services/folder" "github.com/grafana/grafana/pkg/util" "github.com/stretchr/testify/require" + k8sErrors "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) func TestToFolderErrorResponse(t *testing.T) { @@ -66,13 +68,28 @@ func TestToFolderErrorResponse(t *testing.T) { { name: "folder max depth reached", input: folder.ErrMaximumDepthReached, - want: response.JSON(http.StatusBadRequest, util.DynMap{"messageId": "folder.maximum-depth-reached", "message": "Maximum nested folder depth reached"}), + want: response.JSON(http.StatusBadRequest, util.DynMap{"messageId": "folder.maximum-depth-reached", "message": folder.ErrMaximumDepthReached.Error()}), }, { name: "fallback error", input: errors.New("some error"), want: response.ErrOrFallback(http.StatusInternalServerError, "Folder API error", errors.New("some error")), }, + { + name: "kubernetes status error", + input: &k8sErrors.StatusError{ + ErrStatus: metav1.Status{ + Code: 412, + Message: "the folder has been changed by someone else", + }, + }, + want: response.Error(412, "the folder has been changed by someone else", &k8sErrors.StatusError{ + ErrStatus: metav1.Status{ + Code: 412, + Message: "the folder has been changed by someone else", + }, + }), + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) {