Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PublicDashboards: Add annotations support #56413

Merged
merged 49 commits into from
Oct 19, 2022
Merged
Show file tree
Hide file tree
Changes from 18 commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
a526987
Adds backend pubdash support for annotations
owensmallwood Oct 4, 2022
8889988
Adds frontend support for pubdash annotations
owensmallwood Oct 4, 2022
baf4e58
dont get rules when its a public dashboard
owensmallwood Oct 4, 2022
ded15f6
Merge branch 'main' into owensmallwood/pubdash-add-annotations-support
owensmallwood Oct 4, 2022
1db5187
Only send out request for grafana annotations. Don't support query an…
owensmallwood Oct 5, 2022
e420e4e
Adds permissions for getting annotations. Anonymous user needs to be …
owensmallwood Oct 5, 2022
5091e31
regenerates mocks for pubdash service
owensmallwood Oct 5, 2022
fcb47a1
Adds validation for getting pubdash annotations
owensmallwood Oct 5, 2022
9ee81c1
Fixes failing tests. Needed to provide annotations service.
owensmallwood Oct 5, 2022
e23cf1d
Adds tests for pubdash annotations api
owensmallwood Oct 5, 2022
5f75198
formatting
owensmallwood Oct 5, 2022
a2eb4ba
Generates mock for annotations service
owensmallwood Oct 5, 2022
1747f98
Adds pubdash service tests for getting annotations
owensmallwood Oct 5, 2022
302535f
change annotations repo on http_server back to private
owensmallwood Oct 6, 2022
0651445
JsonEditorSettings: Fix invisible json editor
kaydelaney Oct 6, 2022
0b773a0
Merge branch 'main' into owensmallwood/pubdash-add-annotations-support
owensmallwood Oct 6, 2022
9639d9a
Merge remote-tracking branch 'origin/fix-json-editor-settings' into o…
owensmallwood Oct 6, 2022
8bb014f
Gets pubdash annotations from the backend in one request. WIP
owensmallwood Oct 6, 2022
0afb9f4
Gathers all pubdash annotations on the backend. Uses default annotati…
owensmallwood Oct 7, 2022
234287e
Merge branch 'main' into owensmallwood/pubdash-add-annotations-support
owensmallwood Oct 7, 2022
6b8a9c8
Updates pubdash annotations tests
owensmallwood Oct 7, 2022
c28a48e
Excludes annotation queries when looping over dashboard annotations. …
owensmallwood Oct 7, 2022
a3ff68b
Updates test to make sure disabled dashboard annotations are excluded.
owensmallwood Oct 7, 2022
c200233
removes stuff from bad merge
owensmallwood Oct 7, 2022
430f6df
removes more from bad merge
owensmallwood Oct 7, 2022
0e5b6f9
Uses generated type for dashboard annotations. Adds cue schema for an…
owensmallwood Oct 11, 2022
64b3406
regenerates pubdash service mock
owensmallwood Oct 11, 2022
d79798d
renames test helper function
owensmallwood Oct 11, 2022
50a1e46
removes unused struct
owensmallwood Oct 11, 2022
4000e10
adds comment
owensmallwood Oct 12, 2022
23974b1
Adds tests to pubdash frontend ds
owensmallwood Oct 12, 2022
9cfdcbc
adds support for tag annotation queries
owensmallwood Oct 12, 2022
c25e6d0
makes sure duplicate events are not returned. Events from tag queries…
owensmallwood Oct 12, 2022
cec0371
fixes failing frontend and backend tests for pubdash
owensmallwood Oct 13, 2022
ee705c8
Merge branch 'main' into owensmallwood/pubdash-add-annotations-support
owensmallwood Oct 13, 2022
feaa835
Makes a new schema for Annotation Target. Accidentally used the Panel…
owensmallwood Oct 14, 2022
71feb57
some small refactors and cleanup
owensmallwood Oct 14, 2022
346191e
Merge branch 'main' into owensmallwood/pubdash-add-annotations-support
owensmallwood Oct 14, 2022
e41cfc3
renames repo
owensmallwood Oct 14, 2022
53c1cea
adds helpful comment
owensmallwood Oct 14, 2022
c59e3da
refactors scopes to use constants
owensmallwood Oct 14, 2022
ec55cd3
had to move internal package test helper to its own file in models pa…
owensmallwood Oct 14, 2022
8dccc5d
formats imports. Removes helper function because linter says its a se…
owensmallwood Oct 14, 2022
acaf30f
Merge branch 'main' into owensmallwood/pubdash-add-annotations-support
owensmallwood Oct 14, 2022
45550c1
If it's a tags annotation, don't scope query by dashboard id since ta…
owensmallwood Oct 17, 2022
4e0437d
linter fix - ineffectual assignment to error
owensmallwood Oct 17, 2022
27e5d6c
resolves PR comments. Moves some test helper functions into the tests…
owensmallwood Oct 18, 2022
3f02f95
Merged master. Resolved conflicts.
owensmallwood Oct 18, 2022
884ca8f
Merge branch 'main' into owensmallwood/pubdash-add-annotations-support
owensmallwood Oct 18, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions pkg/services/annotations/annotations.go
Expand Up @@ -13,6 +13,7 @@ var (
ErrBaseTagLimitExceeded = errutil.NewBase(errutil.StatusBadRequest, "annotations.tag-limit-exceeded", errutil.WithPublicMessage("Tags length exceeds the maximum allowed."))
)

//go:generate mockery --name Repository --structname FakeAnnotationsRepo --inpackage --filename annotations_repository_mock.go
jalevin marked this conversation as resolved.
Show resolved Hide resolved
type Repository interface {
Save(ctx context.Context, item *Item) error
Update(ctx context.Context, item *Item) error
Expand Down
111 changes: 111 additions & 0 deletions pkg/services/annotations/annotations_repository_mock.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 16 additions & 0 deletions pkg/services/publicdashboards/api/api.go
Expand Up @@ -62,6 +62,7 @@ func (api *Api) RegisterAPIEndpoints() {
// public endpoints
api.RouteRegister.Get("/api/public/dashboards/:accessToken", routing.Wrap(api.GetPublicDashboard))
api.RouteRegister.Post("/api/public/dashboards/:accessToken/panels/:panelId/query", routing.Wrap(api.QueryPublicDashboard))
api.RouteRegister.Get("/api/public/dashboards/:accessToken/annotations", routing.Wrap(api.GetAnnotations))

// Create/Update Public Dashboard
uidScope := dashboards.ScopeDashboardsProvider.GetResourceScopeUID(accesscontrol.Parameter(":uid"))
Expand Down Expand Up @@ -174,6 +175,21 @@ func (api *Api) QueryPublicDashboard(c *models.ReqContext) response.Response {
return toJsonStreamingResponse(api.Features, resp)
}

func (api *Api) GetAnnotations(c *models.ReqContext) response.Response {
reqDTO := AnnotationsQueryDTO{
From: c.QueryInt64("from"),
To: c.QueryInt64("to"),
}

annotations, err := api.PublicDashboardService.GetAnnotations(c.Req.Context(), reqDTO, web.Params(c.Req)[":accessToken"])

if err != nil {
return api.handleError(http.StatusInternalServerError, "error getting public dashboard annotations", err)
}

return response.JSON(http.StatusOK, annotations)
}

// util to help us unpack dashboard and publicdashboard errors or use default http code and message
// we should look to do some future refactoring of these errors as publicdashboard err is the same as a dashboarderr, just defined in a
// different package.
Expand Down
77 changes: 76 additions & 1 deletion pkg/services/publicdashboards/api/api_test.go
Expand Up @@ -10,6 +10,7 @@ import (
"testing"

"github.com/google/uuid"
"github.com/grafana/grafana/pkg/services/annotations"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"
Expand All @@ -22,6 +23,7 @@ import (
"github.com/grafana/grafana/pkg/infra/localcache"
"github.com/grafana/grafana/pkg/infra/log"
"github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/services/annotations/annotationstest"
"github.com/grafana/grafana/pkg/services/dashboards"
dashboardStore "github.com/grafana/grafana/pkg/services/dashboards/database"
"github.com/grafana/grafana/pkg/services/datasources"
Expand All @@ -46,6 +48,77 @@ var userViewer = &user.SignedInUser{UserID: 3, OrgID: 1, OrgRole: org.RoleViewer
var userViewerRBAC = &user.SignedInUser{UserID: 4, OrgID: 1, OrgRole: org.RoleViewer, Login: "testViewerUserRBAC", Permissions: map[int64]map[string][]string{1: {dashboards.ActionDashboardsRead: {dashboards.ScopeDashboardsAll}}}}
var anonymousUser *user.SignedInUser

func TestAPIGetAnnotations(t *testing.T) {
testCases := []struct {
Name string
ExpectedHttpResponse int
Annotations []*annotations.ItemDTO
ServiceError error
From string
To string
}{
{
Name: "will return success when there is no error and to and from are provided",
ExpectedHttpResponse: http.StatusOK,
Annotations: []*annotations.ItemDTO{{Id: 1}},
ServiceError: nil,
From: "123",
To: "123",
},
{
Name: "will return 400 when from not provided",
ExpectedHttpResponse: http.StatusBadRequest,
Annotations: nil,
ServiceError: nil,
From: "",
To: "123",
},
{
Name: "will return 400 when to not provided",
ExpectedHttpResponse: http.StatusBadRequest,
Annotations: nil,
ServiceError: nil,
From: "123",
To: "",
},
{
Name: "will return 500 when service returns an error",
ExpectedHttpResponse: http.StatusInternalServerError,
Annotations: nil,
ServiceError: errors.New("an error happened"),
From: "123",
To: "123",
},
}
for _, test := range testCases {
t.Run(test.Name, func(t *testing.T) {
cfg := setting.NewCfg()
cfg.RBACEnabled = false
service := publicdashboards.NewFakePublicDashboardService(t)
if test.ServiceError != nil {
service.On("GetAnnotations", mock.Anything, mock.Anything, mock.AnythingOfType("string")).
jalevin marked this conversation as resolved.
Show resolved Hide resolved
Return(nil, test.ServiceError).Maybe()
} else {
service.On("GetAnnotations", mock.Anything, mock.Anything, mock.AnythingOfType("string")).
Return(test.Annotations, nil).Maybe()
}
testServer := setupTestServer(t, cfg, featuremgmt.WithFeatures(featuremgmt.FlagPublicDashboards), service, nil, anonymousUser)

path := fmt.Sprintf("/api/public/dashboards/abc123/annotations?from=%s&to=%s", test.From, test.To)
response := callAPI(testServer, http.MethodGet, path, nil, t)

assert.Equal(t, test.ExpectedHttpResponse, response.Code)

if test.ExpectedHttpResponse == http.StatusOK {
var items []*annotations.ItemDTO
err := json.Unmarshal(response.Body.Bytes(), &items)
assert.NoError(t, err)
assert.Equal(t, items, test.Annotations)
}
jalevin marked this conversation as resolved.
Show resolved Hide resolved
})
}
}

func TestAPIGetPublicDashboard(t *testing.T) {
t.Run("It should 404 if featureflag is not enabled", func(t *testing.T) {
cfg := setting.NewCfg()
Expand Down Expand Up @@ -540,11 +613,13 @@ func TestIntegrationUnauthenticatedUserCanGetPubdashPanelQueryData(t *testing.T)
},
}

annotationsService := annotationstest.NewFakeAnnotationsRepo()

// create public dashboard
store := publicdashboardsStore.ProvideStore(db)
cfg := setting.NewCfg()
cfg.RBACEnabled = false
service := publicdashboardsService.ProvideService(cfg, store, qds)
service := publicdashboardsService.ProvideService(cfg, store, qds, annotationsService)
pubdash, err := service.SavePublicDashboardConfig(context.Background(), &user.SignedInUser{}, savePubDashboardCmd)
require.NoError(t, err)

Expand Down
4 changes: 3 additions & 1 deletion pkg/services/publicdashboards/api/middleware_test.go
Expand Up @@ -9,6 +9,7 @@ import (

"github.com/grafana/grafana-plugin-sdk-go/backend"
"github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/services/annotations/annotationstest"
"github.com/grafana/grafana/pkg/services/contexthandler/ctxkey"
fakeDatasources "github.com/grafana/grafana/pkg/services/datasources/fakes"
"github.com/grafana/grafana/pkg/services/publicdashboards"
Expand Down Expand Up @@ -80,8 +81,9 @@ func mockAccessTokenExistsResponse(returnArguments ...interface{}) *publicdashbo
},
&fakeOAuthTokenService{},
)
annotationsService := annotationstest.NewFakeAnnotationsRepo()

return publicdashboardsService.ProvideService(setting.NewCfg(), fakeStore, qds)
return publicdashboardsService.ProvideService(setting.NewCfg(), fakeStore, qds, annotationsService)
}

func runMiddleware(request *http.Request, pubdashService *publicdashboardsService.PublicDashboardServiceImpl) *httptest.ResponseRecorder {
Expand Down
5 changes: 5 additions & 0 deletions pkg/services/publicdashboards/models/models.go
Expand Up @@ -127,6 +127,11 @@ type PublicDashboardQueryDTO struct {
MaxDataPoints int64
}

type AnnotationsQueryDTO struct {
From int64
To int64
}

//
// COMMANDS
//
Expand Down
28 changes: 26 additions & 2 deletions pkg/services/publicdashboards/public_dashboard_service_mock.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion pkg/services/publicdashboards/publicdashboard.go
Expand Up @@ -6,6 +6,7 @@ import (
"github.com/grafana/grafana-plugin-sdk-go/backend"
"github.com/grafana/grafana/pkg/api/dtos"
"github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/services/annotations"
. "github.com/grafana/grafana/pkg/services/publicdashboards/models"
"github.com/grafana/grafana/pkg/services/user"
)
Expand All @@ -16,8 +17,9 @@ import (
type Service interface {
AccessTokenExists(ctx context.Context, accessToken string) (bool, error)
BuildAnonymousUser(ctx context.Context, dashboard *models.Dashboard) (*user.SignedInUser, error)
GetPublicDashboard(ctx context.Context, accessToken string) (*PublicDashboard, *models.Dashboard, error)
GetAnnotations(ctx context.Context, reqDTO AnnotationsQueryDTO, accessToken string) ([]*annotations.ItemDTO, error)
GetDashboard(ctx context.Context, dashboardUid string) (*models.Dashboard, error)
GetPublicDashboard(ctx context.Context, accessToken string) (*PublicDashboard, *models.Dashboard, error)
GetMetricRequest(ctx context.Context, dashboard *models.Dashboard, publicDashboard *PublicDashboard, panelId int64, reqDTO PublicDashboardQueryDTO) (dtos.MetricRequest, error)
GetPublicDashboardConfig(ctx context.Context, orgId int64, dashboardUid string) (*PublicDashboard, error)
GetQueryDataResponse(ctx context.Context, skipCache bool, reqDTO PublicDashboardQueryDTO, panelId int64, accessToken string) (*backend.QueryDataResponse, error)
Expand Down