K8s: Schema v2: Return 406 in /api (#101842)

pull/101668/head
Stephanie Hingtgen 4 months ago committed by GitHub
parent 1444e9d572
commit bd0c645ff0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 11
      pkg/api/dashboard.go
  2. 41
      pkg/api/dashboard_test.go
  3. 5
      pkg/api/swagger_responses.go
  4. 4
      pkg/tests/apis/dashboard/dashboards_test.go
  5. 9
      public/api-merged.json
  6. 13
      public/openapi3.json

@ -85,6 +85,7 @@ func dashboardGuardianResponse(err error) response.Response {
// 401: unauthorisedError
// 403: forbiddenError
// 404: notFoundError
// 406: notAcceptableError
// 500: internalServerError
//
//nolint:gocyclo
@ -99,14 +100,10 @@ func (hs *HTTPServer) GetDashboard(c *contextmodel.ReqContext) response.Response
return rsp
}
// V2 values should be read from the k8s API
// v2 is not supported in /api
if strings.HasPrefix(dash.APIVersion, "v2") {
root := hs.Cfg.AppSubURL
if !strings.HasSuffix(root, "/") {
root += "/"
}
url := fmt.Sprintf("%sapis/dashboard.grafana.app/%s/namespaces/%s/dashboards/%s", root, dash.APIVersion, hs.namespacer(c.OrgID), dash.UID)
return response.Redirect(url)
url := fmt.Sprintf("/apis/dashboard.grafana.app/%s/namespaces/%s/dashboards/%s", dash.APIVersion, hs.namespacer(c.SignedInUser.GetOrgID()), dash.UID)
return response.Error(http.StatusNotAcceptable, "dashboard api version not supported, use "+url+" instead", nil)
}
var (

@ -6,6 +6,7 @@ import (
"fmt"
"net/http"
"os"
"strconv"
"testing"
"time"
@ -694,6 +695,46 @@ func TestDashboardAPIEndpoint(t *testing.T) {
assert.Equal(t, false, dash.Meta.Provisioned)
}, mockSQLStore)
})
t.Run("v2 dashboards should not be returned in api", func(t *testing.T) {
mockSQLStore := dbtest.NewFakeDB()
dashboardService := dashboards.NewFakeDashboardService(t)
dataValue, err := simplejson.NewJson([]byte(`{"id": 1, "apiVersion": "v2"}`))
require.NoError(t, err)
qResult := &dashboards.Dashboard{
ID: 1,
UID: "dash",
OrgID: 1,
APIVersion: "v2",
Data: dataValue,
}
dashboardService.On("GetDashboard", mock.Anything, mock.AnythingOfType("*dashboards.GetDashboardQuery")).Return(qResult, nil)
guardian.MockDashboardGuardian(&guardian.FakeDashboardGuardian{CanViewValue: true})
loggedInUserScenarioWithRole(t, "When calling GET on", "GET", "/api/dashboards/uid/dash", "/api/dashboards/uid/:uid", org.RoleEditor, func(sc *scenarioContext) {
hs := &HTTPServer{
Cfg: setting.NewCfg(),
LibraryPanelService: &mockLibraryPanelService{},
LibraryElementService: &libraryelementsfake.LibraryElementService{},
SQLStore: mockSQLStore,
AccessControl: accesscontrolmock.New(),
DashboardService: dashboardService,
Features: featuremgmt.WithFeatures(),
starService: startest.NewStarServiceFake(),
tracer: tracing.InitializeTracerForTest(),
dashboardProvisioningService: mockDashboardProvisioningService{},
folderService: foldertest.NewFakeService(),
log: log.New("test"),
namespacer: func(orgID int64) string { return strconv.FormatInt(orgID, 10) },
}
hs.callGetDashboard(sc)
assert.Equal(t, http.StatusNotAcceptable, sc.resp.Code)
result := sc.ToJSON()
assert.Equal(t, "dashboard api version not supported, use /apis/dashboard.grafana.app/v2/namespaces/1/dashboards/dash instead", result.Get("message").MustString())
}, mockSQLStore)
})
}
func TestDashboardVersionsAPIEndpoint(t *testing.T) {

@ -52,6 +52,11 @@ type NotFoundError GenericError
// swagger:response badRequestError
type BadRequestError GenericError
// NotAcceptableError is returned when the server cannot produce a response matching the accepted formats.
//
// swagger:response notAcceptableError
type NotAcceptableError GenericError
// ConflictError
//
// swagger:response conflictError

@ -334,10 +334,10 @@ func TestIntegrationLegacySupport(t *testing.T) {
require.Equal(t, 200, rsp.Response.StatusCode)
require.Equal(t, "v1alpha1", rsp.Result.Meta.APIVersion)
// V2 should send a redirect
// V2 should send a not acceptable
rsp = apis.DoRequest(helper, apis.RequestParams{
User: helper.Org1.Admin,
Path: "/api/dashboards/uid/test-v2",
}, &dtos.DashboardFullWithMeta{})
require.Equal(t, 302, rsp.Response.StatusCode) // redirect
require.Equal(t, 406, rsp.Response.StatusCode) // not acceptable
}

@ -3356,6 +3356,9 @@
"404": {
"$ref": "#/responses/notFoundError"
},
"406": {
"$ref": "#/responses/notAcceptableError"
},
"500": {
"$ref": "#/responses/internalServerError"
}
@ -24440,6 +24443,12 @@
"type": "object"
}
},
"notAcceptableError": {
"description": "NotAcceptableError is returned when the server cannot produce a response matching the accepted formats.",
"schema": {
"$ref": "#/definitions/ErrorResponseBody"
}
},
"notFoundError": {
"description": "NotFoundError is returned when the requested resource was not found.",
"schema": {

@ -1641,6 +1641,16 @@
},
"description": "(empty)"
},
"notAcceptableError": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ErrorResponseBody"
}
}
},
"description": "NotAcceptableError is returned when the server cannot produce a response matching the accepted formats."
},
"notFoundError": {
"content": {
"application/json": {
@ -16997,6 +17007,9 @@
"404": {
"$ref": "#/components/responses/notFoundError"
},
"406": {
"$ref": "#/components/responses/notAcceptableError"
},
"500": {
"$ref": "#/components/responses/internalServerError"
}

Loading…
Cancel
Save